Skip to content

Commit

Permalink
feat(core): support declarative custom class extentions
Browse files Browse the repository at this point in the history
  • Loading branch information
clshortfuse committed Jul 19, 2023
1 parent f75fc34 commit 8aab39e
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 77 deletions.
38 changes: 19 additions & 19 deletions components/Icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const documentLoadedStyleSheets = new Set();

// https://html.spec.whatwg.org/multipage/embedded-content.html#htmlimageelement

/** @implements {Omit<HTMLImageElement,DeprecatedHTMLImageElementProperties>} */
export default class Icon extends CustomElement
/** -implements {Omit<HTMLImageElement,DeprecatedHTMLImageElementProperties>} */
export default CustomElement
.extend()
.mixin(ThemableMixin)
.define({
Expand Down Expand Up @@ -204,21 +204,21 @@ export default class Icon extends CustomElement
documentLoadedStyleSheets.add(href);
},
},
}) {
/**
* @param {number} [width]
* @param {number} [height]
*/
constructor(width, height) {
super();

if (width != null) {
this.width = width;
}
if (height != null) {
this.height = height;
})
.extend((BaseClass) => class extends BaseClass {
/**
* @param {number} [width]
* @param {number} [height]
*/
constructor(width, height) {
super();

if (width != null) {
this.width = width;
}
if (height != null) {
this.height = height;
}
}
}
}

Icon.autoRegister('mdw-icon');
})
.autoRegister('mdw-icon');
60 changes: 30 additions & 30 deletions components/ListOption.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ListItem from './ListItem.js';

// https://html.spec.whatwg.org/multipage/form-elements.html#htmloptionelement

export default class ListOption extends ListItem
export default ListItem
.extend()
.setStatic({
formAssociated: true,
Expand Down Expand Up @@ -146,35 +146,35 @@ export default class ListOption extends ListItem
background-color: rgb(var(--mdw-bg));
color: rgb(var(--mdw-ink));
}
` {
static { this.autoRegister('mdw-list-option'); }

/**
* @param {string} [text]
* @param {string} [value]
* @param {boolean} [defaultSelected]
* @param {boolean} [selected]
*/
constructor(text, value, defaultSelected, selected) {
super();
if (text !== undefined) {
this.text = text;
}
if (value !== undefined) {
this._value = value;
}
if (defaultSelected !== undefined) {
this.defaultSelected = defaultSelected;
`
.extend((BaseClass) => class extends BaseClass {
/**
* @param {string} [text]
* @param {string} [value]
* @param {boolean} [defaultSelected]
* @param {boolean} [selected]
*/
constructor(text, value, defaultSelected, selected) {
super();
if (text !== undefined) {
this.text = text;
}
if (value !== undefined) {
this._value = value;
}
if (defaultSelected !== undefined) {
this.defaultSelected = defaultSelected;
}
if (selected !== undefined) {
this._selected = selected;
}
}
if (selected !== undefined) {
this._selected = selected;
}
}

connectedCallback() {
super.connectedCallback();
if (!this.hasAttribute('tabindex')) {
this.tabIndex = 0;
connectedCallback() {
super.connectedCallback();
if (!this.hasAttribute('tabindex')) {
this.tabIndex = 0;
}
}
}
}
})
.autoRegister('mdw-list-option');
3 changes: 1 addition & 2 deletions components/Listbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import StateMixin from '../mixins/StateMixin.js';
import List from './List.js';
import ListOption from './ListOption.js';

/** @implements {HTMLSelectElement} */
// @ts-expect-error Can't implement index signatures (use `item()`)
/** -implements {HTMLSelectElement} */
export default List
.extend()
.mixin(StateMixin)
Expand Down
5 changes: 2 additions & 3 deletions components/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import FormAssociatedMixin from '../mixins/FormAssociatedMixin.js';
import './Icon.js';
import ListOption from './ListOption.js';

export default class MenuItem extends ListOption
export default ListOption
.extend()
.mixin(FormAssociatedMixin)
.set({
Expand Down Expand Up @@ -261,5 +261,4 @@ export default class MenuItem extends ListOption
color: inherit;
}
`
.autoRegister('mdw-menu-item')
.tsClassFix() {}
.autoRegister('mdw-menu-item');
17 changes: 9 additions & 8 deletions components/NavItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ThemableMixin from '../mixins/ThemableMixin.js';

/** @typedef {'charset'|'coords'|'name'|'shape'} DeprecatedHTMLAnchorElementProperties */

export default class NavItem extends CustomElement
export default CustomElement
.extend()
.mixin(ThemableMixin)
.mixin(StateMixin)
Expand Down Expand Up @@ -269,10 +269,11 @@ export default class NavItem extends CustomElement
},
},
})
.autoRegister('mdw-nav-item')
.tsClassFix() {
addRipple(...args) {
if (!this.active) return null;
return super.addRipple(...args);
}
}
.extend((Base) => class NavItem extends Base {
/** @type {InstanceType<ReturnType<RippleMixin>>['addRipple']} */
addRipple(...args) {
if (!this.active) return null;
return super.addRipple(...args);
}
})
.autoRegister('mdw-nav-item');
14 changes: 2 additions & 12 deletions core/CustomElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,21 +216,11 @@ export default class CustomElement extends ICustomElement {
/**
* Extends base class into a new class.
* Use to avoid mutating base class.
* TODO: Add constructor arguments typing
* @type {typeof ICustomElement.extend}
*/
static extend() {
static extend(customExtender) {
// @ts-expect-error Can't cast T
return class extends this {};
}

/**
* Fix for Typescript not parsing constructor params
* @type {typeof ICustomElement.tsClassFix}
*/
static tsClassFix() {
// @ts-expect-error Can't cast T
return this;
return customExtender ? customExtender(this) : class extends this {};
}

/**
Expand Down
7 changes: 4 additions & 3 deletions core/ICustomElement.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ export declare const ICustomElement: {

schema: Record<string, unknown>;

extend<T extends typeof ICustomElement>(this: T): T;

tsClassFix<T extends typeof ICustomElement>(this:T): T & (new (...args:any[]) => InstanceType<T>)
extend<T1 extends typeof ICustomElement, T2 extends T1>(
this: T1,
customExtender?: (Base:T1) => T2
): T2;

html<T extends typeof ICustomElement>(
this: T,
Expand Down

0 comments on commit 8aab39e

Please sign in to comment.