diff --git a/components/Icon.js b/components/Icon.js index a773b9cc..88731cf2 100644 --- a/components/Icon.js +++ b/components/Icon.js @@ -10,8 +10,8 @@ const documentLoadedStyleSheets = new Set(); // https://html.spec.whatwg.org/multipage/embedded-content.html#htmlimageelement -/** @implements {Omit} */ -export default class Icon extends CustomElement +/** -implements {Omit} */ +export default CustomElement .extend() .mixin(ThemableMixin) .define({ @@ -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'); diff --git a/components/ListOption.js b/components/ListOption.js index 2415e01c..5566eb8f 100644 --- a/components/ListOption.js +++ b/components/ListOption.js @@ -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, @@ -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'); diff --git a/components/Listbox.js b/components/Listbox.js index e5747070..340775da 100644 --- a/components/Listbox.js +++ b/components/Listbox.js @@ -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) diff --git a/components/MenuItem.js b/components/MenuItem.js index 3583e1fc..65e28a4c 100644 --- a/components/MenuItem.js +++ b/components/MenuItem.js @@ -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({ @@ -261,5 +261,4 @@ export default class MenuItem extends ListOption color: inherit; } ` - .autoRegister('mdw-menu-item') - .tsClassFix() {} + .autoRegister('mdw-menu-item'); diff --git a/components/NavItem.js b/components/NavItem.js index f5cd0006..6f646814 100644 --- a/components/NavItem.js +++ b/components/NavItem.js @@ -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) @@ -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>['addRipple']} */ + addRipple(...args) { + if (!this.active) return null; + return super.addRipple(...args); + } + }) + .autoRegister('mdw-nav-item'); diff --git a/core/CustomElement.js b/core/CustomElement.js index f2f0f4f5..971959b4 100644 --- a/core/CustomElement.js +++ b/core/CustomElement.js @@ -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 {}; } /** diff --git a/core/ICustomElement.d.ts b/core/ICustomElement.d.ts index e805ba1f..9f4a248f 100644 --- a/core/ICustomElement.d.ts +++ b/core/ICustomElement.d.ts @@ -101,9 +101,10 @@ export declare const ICustomElement: { schema: Record; - extend(this: T): T; - - tsClassFix(this:T): T & (new (...args:any[]) => InstanceType) + extend( + this: T1, + customExtender?: (Base:T1) => T2 + ): T2; html( this: T,