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-radio): converts radio components to glimmer components. #1309

Open
wants to merge 4 commits into
base: feature/glimmer-paper-checkbox
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 37 additions & 20 deletions addon/components/paper-radio-base.hbs
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
{{! template-lint-disable no-curly-component-invocation }}
<div class="md-container">
<div class="md-off"></div>
<div class="md-on"></div>
<PaperRipple
@center={{true}}
@fitRipple={{true}}/>
</div>
{{#if (has-block)}}
<div class="md-label">
<span>
{{yield}}
</span>
<md-radio-button
class='md-default-theme
{{if this.checked " md-checked"}}
{{if @warn " md-warn"}}
{{if @accent " md-accent"}}
{{if @primary " md-primary"}}
{{if this.focused " md-focused"}}
{{@class}}'
aria-checked={{this.ariaChecked}}
aria-label={{@ariaLabel}}
aria-labelledby={{this.labelId}}
disabled={{this.disabled}}
role='radio'
tabindex={{if this.disabled '-1' '0'}}
{{did-insert this.didInsertNode}}
{{will-destroy this.willDestroyNode}}
{{on 'click' this.onClick}}
...attributes
>
<div class='md-container'>
<div class='md-off'></div>
<div class='md-on'></div>
<PaperRipple @center={{true}} @fitRipple={{true}} />
</div>
{{else}}
<div class="md-label">
<span>
{{@label}}
</span>
</div>
{{/if}}
{{#if (has-block)}}
<div class='md-label'>
<span>
{{yield}}
</span>
</div>
{{else}}
<div class='md-label'>
<span>
{{@label}}
</span>
</div>
{{/if}}
</md-radio-button>
169 changes: 117 additions & 52 deletions addon/components/paper-radio-base.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,137 @@
/* eslint-disable ember/no-classic-components, ember/no-mixins, ember/require-tagless-components */
/**
* @module ember-paper
*/
import Component from '@ember/component';

import { computed } from '@ember/object';
import Focusable from './-focusable';
import { action } from '@ember/object';
import { guidFor } from '@ember/object/internals';
import { assert } from '@ember/debug';
import FocusableMixin from 'ember-paper/mixins/focusable-mixin';
import { invokeAction } from 'ember-paper/utils/invoke-action';

/**
* @class PaperRadio
* @extends Ember.Component
* @uses FocusableMixin
* @extends Component
*/
export default Component.extend(FocusableMixin, {
tagName: 'md-radio-button',
classNames: ['md-default-theme'],
classNameBindings: [
'checked:md-checked',
'warn:md-warn',
'accent:md-accent',
'primary:md-primary',
],

attributeBindings: [
'role',
'ariaChecked:aria-checked',
'ariaLabel:aria-label',
],

tabindex: null,
toggle: false,
role: 'radio',

/* FocusableMixin Overrides */
focusOnlyOnKey: true,
export default class PaperRadioBase extends Focusable {
/**
* Reference to the component's DOM element
* @type {HTMLElement}
*/
element;
/**
* provides a globally unique component id for tracking bindings between aria
* tags and labels.
* @type {string}
*/
labelId;
/**
* The parent this component is bound to.
* @type {PaperRadioGroup|PaperForm|PaperItem|PaperTabs}
*/
parent;
/**
* Marks whether the component should register itself to the supplied parent
* @type {Boolean}
*/
shouldRegister;
/**
* Marks whether the component should skip being proxied.
* @type {Boolean}
*/
skipProxy;

/* Focusable Overrides */
focusOnlyOnKey = true;
toggle = false;

// Lifecycle hooks
init() {
constructor(owner, args) {
super(owner, args);

this.labelId = `${guidFor(this)}-label`;
this.shouldRegister = this.args.shouldRegister || false;
this.skipProxy = this.args.skipProxy || false;
this.toggle = this.args.toggle || false;

if (this.shouldRegister) {
assert(
'A parent component should be supplied to <PaperRadio> when shouldRegister=true',
this.args.parentComponent
);
this.parent = this.args.parentComponent;
}

assert(
'{{paper-radio}} requires an `onChange` action or null for no action.',
this.onChange !== undefined
'<PaperRadio> requires an `onChange` action or null for no action.',
this.args.onChange !== undefined
);
this._super(...arguments);
},
}

/**
* Performs any required DOM setup.
* @param element
*/
@action didInsertNode(element) {
this.element = element;
this.registerListeners(element);

if (this.shouldRegister) {
this.parent.registerChild(this);
}
}

checked: computed('groupValue', 'value', function () {
return this.groupValue === this.value;
}),
@action didUpdateNode() {
// noop
}

ariaChecked: computed('checked', function () {
/**
* Performs any required DOM teardown.
* @param element
*/
@action willDestroyNode(element) {
this.unregisterListeners(element);
}

willDestroy() {
super.willDestroy(...arguments);

if (this.shouldRegister) {
this.parent.unregisterChild(this);
}
}

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

get checked() {
return this.args.groupValue === this.value;
}

get ariaChecked() {
return this.checked ? 'true' : 'false';
}),
}

labelId: computed('elementId', function () {
return `${this.elementId}-label`;
}),
get bubbles() {
return this.args.bubbles === undefined || this.args.bubbles;
}

click() {
@action onClick(e) {
if (!this.disabled) {
if (this.toggle) {
invokeAction(this, 'onChange', this.checked ? null : this.value);
} else {
invokeAction(this, 'onChange', this.value);
if (this.args.onChange) {
if (this.toggle) {
this.args.onChange(this.checked ? null : this.value);
} else {
this.args.onChange(this.value);
}
}

// Prevent bubbling, if specified. If undefined, the event will bubble.
if (!this.bubbles && e) {
e.stopPropagation();
}
}
// Prevent bubbling, if specified. If undefined, the event will bubble.
return this.bubbles;
},
});
}

processProxy() {
this.onClick();
}
}
14 changes: 7 additions & 7 deletions addon/components/paper-radio-group-label.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{! template-lint-disable no-curly-component-invocation }}
{{#if (has-block)}}
{{yield}}
{{else}}
{{@text}}
{{/if}}

<md-label id={{this.labelId}} {{did-insert this.didInsertNode}} ...attributes>
{{#if (has-block)}}
{{yield}}
{{else}}
{{@text}}
{{/if}}
</md-label>
34 changes: 24 additions & 10 deletions addon/components/paper-radio-group-label.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
/* eslint-disable ember/no-classic-components, ember/no-component-lifecycle-hooks, ember/require-tagless-components */
import Component from '@ember/component';
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { guidFor } from '@ember/object/internals';

export default Component.extend({
tagName: 'md-label',
export default class PaperRadioGroupLabel extends Component {
/**
* provides a globally unique component id for tracking bindings between aria
* tags and labels.
* @type {string}
*/
labelId;

didInsertElement() {
this._super(...arguments);
constructor(owner, args) {
super(owner, args);

if (this.setAriaLabelledby) {
this.setAriaLabelledby(this.elementId);
this.labelId = this.args.labelId || `${guidFor(this)}-label`;
}

/**
* Performs any required DOM setup.
* @param element
*/
@action didInsertNode() {
if (this.args.setAriaLabelledby) {
this.args.setAriaLabelledby(this.labelId);
}
},
});
}
}
44 changes: 31 additions & 13 deletions addon/components/paper-radio-group.hbs
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
{{! template-lint-disable no-action }}
{{yield (hash
label=(component this.labelComponent
setAriaLabelledby=(action (mut this.ariaLabelledby))
)
radio=(component this.radioComponent
toggle=this.toggle
disabled=this.disabled
groupValue=@groupValue
onChange=(action "onChange")
parentComponent=this
shouldRegister=true)
)}}
<md-radio-group
class="{{if this.focused " md-focused"}} {{@class}}"
aria-label={{@ariaLabel}}
aria-labelledby={{if this.hasLabel this.labelId}}
disabled={{this.disabled}}
role="radiogroup"
tabindex="0"
{{did-insert this.didInsertNode}}
{{will-destroy this.willDestroyNode}}
{{on 'keydown' this.onKeyDown}} {{! template-lint-disable no-down-event-binding }}
...attributes
>
{{yield
(hash
label=(component
this.labelComponent
labelId=this.labelId
setAriaLabelledby=this.didInsertLabel
)
radio=(component
this.radioComponent
toggle=this.toggle
disabled=this.disabled
groupValue=@groupValue
onChange=this.onChange
parentComponent=this
shouldRegister=true
)
)
}}
</md-radio-group>
Loading
Loading