-
-
Notifications
You must be signed in to change notification settings - Fork 333
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(addon/components/paper-tab): converts to a glimmer component.
- Loading branch information
1 parent
af9e992
commit cc007ed
Showing
2 changed files
with
192 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,25 @@ | ||
{{! template-lint-disable no-curly-component-invocation }} | ||
{{#if (has-block)}} | ||
{{yield}} | ||
{{else}} | ||
{{@name}} | ||
{{/if}} | ||
<PaperRipple/> | ||
{{#let (element this.tag) as |Tag|}} | ||
<Tag | ||
class='md-tab | ||
{{~if this.focused " md-focused"}} | ||
{{~if this.isSelected " md-active"}} | ||
{{@class}}' | ||
aria-selected={{this.isSelected}} | ||
disabled={{this.disabled}} | ||
href={{this.maybeHref}} | ||
style={{this.style}} | ||
tabindex={{if this.disabled '-1' '0'}} | ||
{{did-insert this.didInsertNode}} | ||
{{did-update this.didUpdateNode @value}} | ||
{{will-destroy this.willDestroyNode}} | ||
{{on 'click' this.handleClick}} | ||
...attributes | ||
> | ||
{{#if (has-block)}} | ||
{{yield}} | ||
{{else}} | ||
{{@name}} | ||
{{/if}} | ||
<PaperRipple /> | ||
</Tag> | ||
{{/let}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,194 @@ | ||
/* eslint-disable ember/classic-decorator-hooks, ember/classic-decorator-no-classic-methods, ember/no-classic-components, ember/no-computed-properties-in-native-classes, ember/no-mixins */ | ||
import { | ||
classNames, | ||
attributeBindings, | ||
classNameBindings, | ||
tagName, | ||
} from '@ember-decorators/component'; | ||
|
||
import { computed } from '@ember/object'; | ||
import Component from '@ember/component'; | ||
/** | ||
* @module ember-paper | ||
*/ | ||
import Focusable from './-focusable'; | ||
import { tracked } from '@glimmer/tracking'; | ||
import { action } from '@ember/object'; | ||
import { htmlSafe } from '@ember/template'; | ||
import { ChildMixin } from 'ember-composability-tools'; | ||
import FocusableMixin from 'ember-paper/mixins/focusable-mixin'; | ||
import { invokeAction } from 'ember-paper/utils/invoke-action'; | ||
|
||
@tagName('md-tab-item') | ||
@classNames('md-tab') | ||
@classNameBindings('isSelected:md-active') | ||
@attributeBindings('isSelected:aria-selected', 'style', 'maybeHref:href') | ||
export default class PaperTab extends Component.extend( | ||
ChildMixin, | ||
FocusableMixin | ||
) { | ||
// <a> tags have browser styles or are usually styled by the user | ||
// this makes sure that tab item still looks good with an anchor tag | ||
@computed('href') | ||
import { assert } from '@ember/debug'; | ||
|
||
/** | ||
* @class PaperTab | ||
* @extends Focusable | ||
*/ | ||
export default class PaperTab extends Focusable { | ||
/** | ||
* Reference to the component's DOM element. | ||
* | ||
* @type {HTMLElement} | ||
*/ | ||
element; | ||
/** | ||
* The parent this component is bound to. | ||
* | ||
* @type {PaperTabs} | ||
*/ | ||
parent; | ||
/** | ||
* Marks whether the component should register itself to the supplied parent. | ||
* | ||
* @type {Boolean} | ||
*/ | ||
shouldRegister; | ||
/** | ||
* The top level tag to render. One of {'a', 'md-tab'}. | ||
* | ||
* @type {string} | ||
* @private | ||
* @default 'md-tab-item' | ||
*/ | ||
tag; | ||
/** | ||
* provides a proxy value if one is not supplied by the user. | ||
* | ||
* @type {number|*} | ||
* @private | ||
*/ | ||
@tracked _value; | ||
/** | ||
* the number of pixels that the upper left corner of the current element is | ||
* offset to the left within the {@link HTMLElement.offsetParent} node. | ||
* | ||
* @type{number} | ||
*/ | ||
@tracked left; | ||
/** | ||
* the layout width of the element as an integer. | ||
* | ||
* @type{number} | ||
*/ | ||
@tracked width; | ||
|
||
/** | ||
* @constructor | ||
* @param owner | ||
* @param args | ||
*/ | ||
constructor(owner, args) { | ||
super(owner, args); | ||
|
||
this.tag = 'md-tab-item'; | ||
if (this.args.href) { | ||
this.tag = 'a'; | ||
} | ||
|
||
this.shouldRegister = this.args.shouldRegister || true; | ||
if (this.shouldRegister) { | ||
assert( | ||
'A parent component should be supplied to <PaperTab>', | ||
this.args.parentComponent | ||
); | ||
this.parent = this.args.parentComponent; | ||
} | ||
} | ||
|
||
/** | ||
* Performs any required DOM setup. | ||
* | ||
* @param {HTMLElement} element - the node that has been added to the DOM. | ||
*/ | ||
@action didInsertNode(element) { | ||
this.element = element; | ||
this.left = element.offsetLeft; | ||
this.width = element.offsetWidth; | ||
|
||
this.registerListeners(element); | ||
|
||
if (this.shouldRegister) { | ||
this.parent.registerChild(this); | ||
} | ||
} | ||
|
||
/** | ||
* didUpdateNode is called when tracked component attributes change. | ||
*/ | ||
@action didUpdateNode() { | ||
if (this.args.value) { | ||
this.value = this.args.value; | ||
} | ||
} | ||
|
||
/** | ||
* Performs any required DOM teardown. | ||
* | ||
* @param {HTMLElement} element - the node to be removed from the DOM. | ||
*/ | ||
@action willDestroyNode(element) { | ||
this.unregisterListeners(element); | ||
} | ||
|
||
/** | ||
* lifecycle hook to perform non-DOM related teardown. | ||
*/ | ||
willDestroy() { | ||
super.willDestroy(); | ||
|
||
if (this.shouldRegister) { | ||
this.parent.unregisterChild(this); | ||
} | ||
} | ||
|
||
/** | ||
* <a> tags have browser styles or are usually styled by the user | ||
* this makes sure that tab item still looks good with an anchor tag. | ||
* | ||
* @returns {string|undefined} | ||
*/ | ||
get style() { | ||
if (this.href) { | ||
if (this.args.href) { | ||
return htmlSafe('text-decoration: none; border: none;'); | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
|
||
@computed('href', 'disabled') | ||
/** | ||
* maybeHref returns the user supplied href link url. | ||
* | ||
* @returns {string|undefined} | ||
*/ | ||
get maybeHref() { | ||
if (this.href && !this.disabled) { | ||
return this.href; | ||
if (this.args.href && !this.disabled) { | ||
return this.args.href; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
|
||
@computed('selected', 'value') | ||
/** | ||
* computes whether this is the currently selected tab. | ||
* | ||
* @returns {boolean} | ||
*/ | ||
get isSelected() { | ||
return this.selected === this.value; | ||
} | ||
|
||
init() { | ||
super.init(...arguments); | ||
if (this.href) { | ||
this.set('tagName', 'a'); | ||
} | ||
return this.args.selected === this.value; | ||
} | ||
|
||
// this method is called by the parent | ||
updateDimensions() { | ||
// this is the true current width | ||
// it is used to calculate the ink bar position & pagination offset | ||
this.setProperties({ | ||
left: this.element.offsetLeft, | ||
width: this.element.offsetWidth, | ||
}); | ||
this.left = this.element.offsetLeft; | ||
this.width = this.element.offsetWidth; | ||
} | ||
|
||
click() { | ||
get value() { | ||
// enable support for user supplied value | ||
return this.args.value || this._value; | ||
} | ||
set value(value) { | ||
this._value = value; | ||
} | ||
|
||
@action handleClick(e) { | ||
if (!this.disabled) { | ||
invokeAction(this, 'onClick', ...arguments); | ||
invokeAction(this, 'onSelect', this); | ||
if (this.args.onClick) { | ||
this.args.onClick(e); | ||
} | ||
|
||
if (this.args.onSelect) { | ||
this.args.onSelect(this); | ||
} | ||
} | ||
} | ||
} |