Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(addon/components/paper-button): converts to a glimmer component. #1298

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
174 changes: 174 additions & 0 deletions addon/components/-focusable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* @module ember-paper
*/
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

/**
* @class Focusable
* @extends @glimmer/component
*
* When extending from Focusable it is expected that md-focused be implemented
* on the top level tag along with setting tabindex and disabled. This component
* listens to a large number of events, therefore render listener register
* functions have been created to ease usage. Clearly, this is non-optimal and
* only the listeners that are required should be added using the `on` modifier.
*
* Use the following as a base:
* ```hbs
* <myTag class='{{if this.focused " md-focused"}}' disabled={{this.disabled}} tabindex={{if this.disabled "-1" "0"}} {{did-insert this.registerListeners}} {{will-destroy this.unregisterListeners}} ...attributes>
* </myTag>
* ```
*/
export default class Focusable extends Component {
@tracked pressed = false;
@tracked active = false;
@tracked focused = false;
@tracked hover = false;

// classNameBindings: ['focused:md-focused'],
// attributeBindings: ['tabindex', 'disabledAttr:disabled'],

get disabled() {
return this.args.disabled || false;
}

toggle = false;

// Only render the "focused" state if the element gains focus due to
// keyboard navigation.
get focusOnlyOnKey() {
return this.args.focusOnlyOnKey || false;
}

@action registerListeners(element) {
element.addEventListener('focusin', this.handleFocusIn);
element.addEventListener('focusout', this.handleFocusOut);
element.addEventListener('mousedown', this.handleMouseDown);
element.addEventListener('mouseenter', this.handleMouseEnter);
element.addEventListener('mouseleave', this.handleMouseLeave);
element.addEventListener('mousemove', this.handleMouseMove);
element.addEventListener('mouseup', this.handleMouseUp);
element.addEventListener('pointermove', this.handlePointerMove);
// Set all touch events as passive listeners to remove scroll jank on
// mobile devices.
// refer: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
element.addEventListener('touchcancel', this.handleTouchCancel, {
passive: true,
});
element.addEventListener('touchend', this.handleTouchEnd, {
passive: true,
});
element.addEventListener('touchmove', this.handleTouchMove, {
passive: true,
});
element.addEventListener('touchstart', this.handleTouchStart, {
passive: true,
});
}

@action unregisterListeners(element) {
element.removeEventListener('focusin', this.handleFocusIn);
element.removeEventListener('focusout', this.handleFocusOut);
element.removeEventListener('mousedown', this.handleMouseDown);
element.removeEventListener('mouseenter', this.handleMouseEnter);
element.removeEventListener('mouseleave', this.handleMouseLeave);
element.removeEventListener('mousemove', this.handleMouseMove);
element.removeEventListener('mouseup', this.handleMouseUp);
element.removeEventListener('pointermove', this.handlePointerMove);
element.removeEventListener('touchcancel', this.handleTouchCancel);
element.removeEventListener('touchend', this.handleTouchEnd);
element.removeEventListener('touchmove', this.handleTouchMove);
element.removeEventListener('touchstart', this.handleTouchStart);
}

/*
* Listen to `focusIn` and `focusOut` events instead of `focus` and `blur`.
* This way we don't need to explicitly bubble the events.
* They bubble by default.
*/
@action handleFocusIn(e) {
if ((!this.disabled && !this.focusOnlyOnKey) || !this.pressed) {
this.focused = true;
if (this.args.onFocusIn) {
this.args.onFocusIn(e);
}
}
}

@action handleFocusOut(e) {
this.focused = false;
if (this.args.onFocusOut) {
this.args.onFocusOut(e);
}
}

@action handleMouseDown(e) {
this.down(e);
if (this.args.onMouseDown) {
this.args.onMouseDown(e);
}
}

@action handleMouseEnter(e) {
this.hover = true;
if (this.args.onMouseEnter) {
this.args.onMouseEnter(e);
}
}

@action handleMouseLeave(e) {
this.hover = false;
this.up(e);
if (this.args.onMouseLeave) {
this.args.onMouseLeave(e);
}
}

@action handleMouseMove(e) {
return this.move(e);
}

@action handleMouseUp(e) {
return this.up(e);
}

@action handlePointerMove(e) {
return this.move(e);
}

@action handleTouchCancel(e) {
return this.up(e);
}

@action handleTouchEnd(e) {
return this.up(e);
}

@action handleTouchMove(e) {
return this.move(e);
}

@action handleTouchStart(e) {
return this.down(e);
}

@action up() {
this.pressed = false;
if (!this.toggle) {
this.active = false;
}
}

@action down() {
this.pressed = true;
if (this.toggle) {
this.active = !this.active;
} else {
this.active = true;
}
}

move() {}
}
48 changes: 38 additions & 10 deletions addon/components/paper-button.hbs
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
{{! template-lint-disable no-curly-component-invocation }}
{{#if (has-block)}}
{{yield}}
{{else}}
{{@label}}
{{/if}}
{{#let (element this.tag) as |Tag|}}
<Tag
class='md-default-theme md-button
{{if @raised " md-raised"}}
{{if @iconButton " md-icon-button"}}
{{if this.fab " md-fab"}}
{{if @mini " md-mini"}}
{{if @warn " md-warn"}}
{{if @accent " md-accent"}}
{{if @primary " md-primary"}}
{{if @secondary " md-secondary"}}
{{if this.focused " md-focused"}} {{@class}}'
disabled={{this.disabled}}
download={{@download}}
href={{@href}}
id={{@id}}
rel={{@rel}}
tabindex={{if this.disabled "-1" "0"}}
target={{@target}}
title={{@title}}
type={{this.type}}
{{did-insert this.didInsertNode}}
{{will-destroy this.willDestroyNode}}
{{on 'click' this.handleClick}}
...attributes
>
{{#if (has-block)}}
{{yield}}
{{else}}
{{@label}}
{{/if}}

<PaperRipple
@fitRipple={{@iconButton}}
@center={{@iconButton}}
@dimBackground={{not @iconButton}}/>
<PaperRipple
@fitRipple={{@iconButton}}
@center={{@iconButton}}
@dimBackground={{not @iconButton}}
/>
</Tag>
{{/let}}
Loading
Loading