diff --git a/.changeset/four-roses-fetch.md b/.changeset/four-roses-fetch.md new file mode 100644 index 000000000..ce356daf4 --- /dev/null +++ b/.changeset/four-roses-fetch.md @@ -0,0 +1,21 @@ +--- +'@lion/calendar': patch +'@lion/checkbox-group': patch +'@lion/core': patch +'@lion/fieldset': patch +'@lion/form-core': patch +'@lion/input-date': patch +'@lion/input-datepicker': patch +'@lion/input-email': patch +'@lion/input-iban': patch +'@lion/listbox': patch +'@lion/localize': patch +'@lion/overlays': patch +'@lion/pagination': patch +'@lion/progress-indicator': patch +'@lion/radio-group': patch +'@lion/select-rich': patch +'@lion/switch': patch +--- + +Fix type issues where base constructors would not have the same return type. This allows us to remove a LOT of @ts-expect-errors/@ts-ignores across lion. diff --git a/.changeset/lemon-countries-clap.md b/.changeset/lemon-countries-clap.md new file mode 100644 index 000000000..66a5dd482 --- /dev/null +++ b/.changeset/lemon-countries-clap.md @@ -0,0 +1,23 @@ +--- +'@lion/calendar': patch +'@lion/checkbox-group': patch +'@lion/combobox': patch +'@lion/core': patch +'@lion/fieldset': patch +'@lion/form-core': patch +'@lion/form-integrations': patch +'@lion/input-date': patch +'@lion/input-datepicker': patch +'@lion/input-email': patch +'@lion/input-iban': patch +'@lion/listbox': patch +'@lion/localize': patch +'@lion/overlays': patch +'@lion/pagination': patch +'@lion/progress-indicator': patch +'@lion/radio-group': patch +'@lion/select-rich': patch +'@lion/switch': patch +--- + +Fix missing types and update to latest scoped elements to fix constructor type. diff --git a/.eslintignore b/.eslintignore index de2cd1c13..cdffae36b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ node_modules coverage/ bundlesize/ .history/ +*.d.ts diff --git a/packages/calendar/src/LionCalendar.js b/packages/calendar/src/LionCalendar.js index 37dce69d1..ac089783c 100644 --- a/packages/calendar/src/LionCalendar.js +++ b/packages/calendar/src/LionCalendar.js @@ -25,7 +25,6 @@ import { isSameDate } from './utils/isSameDate.js'; /** * @customElement lion-calendar */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionCalendar extends LocalizeMixin(LitElement) { static get localizeNamespaces() { return [ diff --git a/packages/checkbox-group/src/LionCheckboxGroup.js b/packages/checkbox-group/src/LionCheckboxGroup.js index 6e09239c8..6ad4b89f2 100644 --- a/packages/checkbox-group/src/LionCheckboxGroup.js +++ b/packages/checkbox-group/src/LionCheckboxGroup.js @@ -4,7 +4,6 @@ import { ChoiceGroupMixin, FormGroupMixin } from '@lion/form-core'; /** * A wrapper around multiple checkboxes */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionCheckboxGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) { constructor() { super(); diff --git a/packages/combobox/docs/google-combobox/google-combobox.js b/packages/combobox/docs/google-combobox/google-combobox.js index f4aa653a7..c318e676b 100644 --- a/packages/combobox/docs/google-combobox/google-combobox.js +++ b/packages/combobox/docs/google-combobox/google-combobox.js @@ -445,7 +445,7 @@ export class GoogleCombobox extends LionCombobox { } _showOverlayCondition(options) { - return this.focused || super.showOverlayCondition(options); + return this.focused || super._showOverlayCondition(options); } __resetFocus() { diff --git a/packages/combobox/src/LionCombobox.js b/packages/combobox/src/LionCombobox.js index 7d66ec08b..730f04e70 100644 --- a/packages/combobox/src/LionCombobox.js +++ b/packages/combobox/src/LionCombobox.js @@ -372,7 +372,7 @@ export class LionCombobox extends OverlayMixin(LionListbox) { * * @example * _showOverlayCondition(options) { - * return this.focused || super.showOverlayCondition(options); + * return this.focused || super._showOverlayCondition(options); * } * * @example @@ -382,7 +382,7 @@ export class LionCombobox extends OverlayMixin(LionListbox) { * * @example * _showOverlayCondition(options) { - * return options.currentValue.length > 4 && super.showOverlayCondition(options); + * return options.currentValue.length > 4 && super._showOverlayCondition(options); * } * * @param {{ currentValue: string, lastKey:string }} options diff --git a/packages/combobox/test/lion-combobox.test.js b/packages/combobox/test/lion-combobox.test.js index a28951bf3..ffcc06161 100644 --- a/packages/combobox/test/lion-combobox.test.js +++ b/packages/combobox/test/lion-combobox.test.js @@ -8,7 +8,6 @@ import { Required } from '@lion/form-core'; import { LionCombobox } from '../src/LionCombobox.js'; /** - * @typedef {import('../src/LionCombobox.js').LionCombobox} LionCombobox * @typedef {import('../types/SelectionDisplay').SelectionDisplay} SelectionDisplay */ @@ -384,8 +383,9 @@ describe('lion-combobox', () => { describe('Subclassers', () => { it('allows to control overlay visibility via "_showOverlayCondition"', async () => { class ShowOverlayConditionCombobox extends LionCombobox { + /** @param {{ currentValue: string, lastKey:string }} options */ _showOverlayCondition(options) { - return this.focused || super.showOverlayCondition(options); + return this.focused || super._showOverlayCondition(options); } } const tagName = defineCE(ShowOverlayConditionCombobox); @@ -575,6 +575,7 @@ describe('lion-combobox', () => { Item 1 `)); + // @ts-ignore sinon type error const spy = sinon.spy(el._selectionDisplayNode, 'onComboboxElementUpdated'); el.requestUpdate('modelValue'); await el.updateComplete; @@ -823,6 +824,11 @@ describe('lion-combobox', () => { `)); expect(el._inputNode.value).to.equal(''); + /** + * @param {'none' | 'list' | 'inline' | 'both'} autocomplete + * @param {number|number[]} index + * @param {string} valueOnClose + */ async function performChecks(autocomplete, index, valueOnClose) { await el.updateComplete; el.opened = true; @@ -945,7 +951,7 @@ describe('lion-combobox', () => { `)); // This ensures autocomplete would be off originally el.autocomplete = 'list'; - await mimicUserTypingAdvanced(el, 'vi'); // so we have options ['Victoria Plum'] + await mimicUserTypingAdvanced(el, ['v', 'i']); // so we have options ['Victoria Plum'] await el.updateComplete; expect(el.checkedIndex).to.equal(3); }); @@ -1057,6 +1063,10 @@ describe('lion-combobox', () => { return true; } + /** + * @param {?} modelValue + * @param {?} oldModelValue + */ // eslint-disable-next-line no-unused-vars _syncToTextboxMultiple(modelValue, oldModelValue) { // In a real scenario (depending on how selection display works), diff --git a/packages/core/package.json b/packages/core/package.json index 6f2e58232..cdb6d2769 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -32,7 +32,7 @@ "sideEffects": false, "dependencies": { "@open-wc/dedupe-mixin": "^1.2.18", - "@open-wc/scoped-elements": "^1.3.2", + "@open-wc/scoped-elements": "^1.3.3", "lit-element": "~2.4.0", "lit-html": "^1.3.0" }, diff --git a/packages/core/types/DelegateMixinTypes.d.ts b/packages/core/types/DelegateMixinTypes.d.ts index 01422a6ca..bf6fcaaa2 100644 --- a/packages/core/types/DelegateMixinTypes.d.ts +++ b/packages/core/types/DelegateMixinTypes.d.ts @@ -10,6 +10,7 @@ export type Delegations = { }; export declare class DelegateHost { + constructor(...args: any[]); delegations: Delegations; protected _connectDelegateMixin(): void; diff --git a/packages/core/types/DisabledMixinTypes.d.ts b/packages/core/types/DisabledMixinTypes.d.ts index 663b8b9ab..b1f21e5d0 100644 --- a/packages/core/types/DisabledMixinTypes.d.ts +++ b/packages/core/types/DisabledMixinTypes.d.ts @@ -2,6 +2,7 @@ import { Constructor } from '@open-wc/dedupe-mixin'; import { LitElement } from '../index.js'; export declare class DisabledHost { + constructor(...args: any[]); disabled: boolean; /** @@ -20,6 +21,6 @@ export declare class DisabledHost { export declare function DisabledMixinImplementation>( superclass: T, -): T & Constructor; +): T & Constructor & typeof DisabledHost; export type DisabledMixin = typeof DisabledMixinImplementation; diff --git a/packages/core/types/DisabledWithTabIndexMixinTypes.d.ts b/packages/core/types/DisabledWithTabIndexMixinTypes.d.ts index b5eee2c33..dd6f3a51e 100644 --- a/packages/core/types/DisabledWithTabIndexMixinTypes.d.ts +++ b/packages/core/types/DisabledWithTabIndexMixinTypes.d.ts @@ -2,6 +2,7 @@ import { Constructor } from '@open-wc/dedupe-mixin'; import { DisabledHost } from './DisabledMixinTypes'; import { LitElement } from '../index.js'; export declare class DisabledWithTabIndexHost { + constructor(...args: any[]); tabIndex: number; /** * Makes request to make the element disabled and set the tabindex diff --git a/packages/core/types/SlotMixinTypes.d.ts b/packages/core/types/SlotMixinTypes.d.ts index 8644536b9..5595e5501 100644 --- a/packages/core/types/SlotMixinTypes.d.ts +++ b/packages/core/types/SlotMixinTypes.d.ts @@ -7,6 +7,7 @@ export type SlotsMap = { }; export declare class SlotHost { + constructor(...args: any[]); /** * Obtains all the slots to create */ @@ -50,6 +51,6 @@ export declare class SlotHost { */ export declare function SlotMixinImplementation>( superclass: T, -): T & Constructor; +): T & Constructor & typeof SlotHost; export type SlotMixin = typeof SlotMixinImplementation; diff --git a/packages/core/types/UpdateStylesMixinTypes.d.ts b/packages/core/types/UpdateStylesMixinTypes.d.ts index fed904166..cc1c41b80 100644 --- a/packages/core/types/UpdateStylesMixinTypes.d.ts +++ b/packages/core/types/UpdateStylesMixinTypes.d.ts @@ -21,6 +21,7 @@ export declare class UpdateStylesHost { * * @param {StylesMap} updateStyles */ + constructor(...args: any[]); public updateStyles(updateStyles: StylesMap): void; } diff --git a/packages/fieldset/src/LionFieldset.js b/packages/fieldset/src/LionFieldset.js index c5cbb234d..6a582e15a 100644 --- a/packages/fieldset/src/LionFieldset.js +++ b/packages/fieldset/src/LionFieldset.js @@ -19,13 +19,15 @@ import { FormGroupMixin } from '@lion/form-core'; * * @customElement lion-fieldset */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionFieldset extends FormGroupMixin(LitElement) { constructor() { super(); /** @override FormRegistrarMixin */ this._isFormOrFieldset = true; - /** @override FormControlMixin */ + /** + * @type {'child' | 'choice-group' | 'fieldset'} + * @override FormControlMixin + */ this._repropagationRole = 'fieldset'; } } diff --git a/packages/form-core/src/FormControlMixin.js b/packages/form-core/src/FormControlMixin.js index 0f7820599..830202373 100644 --- a/packages/form-core/src/FormControlMixin.js +++ b/packages/form-core/src/FormControlMixin.js @@ -9,7 +9,6 @@ import { Unparseable } from './validate/Unparseable.js'; * @typedef {import('@lion/core').CSSResult} CSSResult * @typedef {import('@lion/core').nothing} nothing * @typedef {import('@lion/core/types/SlotMixinTypes').SlotsMap} SlotsMap - * @typedef {import('../types/FormControlMixinTypes.js').FormControlHost} FormControlHost * @typedef {import('../types/FormControlMixinTypes.js').FormControlMixin} FormControlMixin * @typedef {import('../types/FormControlMixinTypes.js').ModelValueEventDetails} ModelValueEventDetails */ @@ -522,15 +521,13 @@ const FormControlMixinImplementation = superclass => /** * @param {?} modelValue * @return {boolean} - * - * FIXME: Move to FormatMixin? Since there we have access to modelValue prop */ - // @ts-expect-error + // @ts-ignore FIXME: Move to FormatMixin? Since there we have access to modelValue prop _isEmpty(modelValue = this.modelValue) { let value = modelValue; - // @ts-expect-error + // @ts-ignore if (this.modelValue instanceof Unparseable) { - // @ts-expect-error + // @ts-ignore value = this.modelValue.viewValue; } diff --git a/packages/form-core/src/FormatMixin.js b/packages/form-core/src/FormatMixin.js index 8ec33e3c4..c14c75192 100644 --- a/packages/form-core/src/FormatMixin.js +++ b/packages/form-core/src/FormatMixin.js @@ -304,15 +304,16 @@ const FormatMixinImplementation = superclass => */ _onModelValueChanged(...args) { this._calculateValues({ source: 'model' }); - // @ts-expect-error only passing this so a subclasser can use it, but we do not use it ourselves this._dispatchModelValueChangedEvent(...args); } /** + * @param {{ modelValue: unknown; }[]} args * This is wrapped in a distinct method, so that parents can control when the changed event * is fired. For objects, a deep comparison might be needed. */ - _dispatchModelValueChangedEvent() { + // eslint-disable-next-line no-unused-vars + _dispatchModelValueChangedEvent(...args) { /** @event model-value-changed */ this.dispatchEvent( new CustomEvent('model-value-changed', { diff --git a/packages/form-core/src/LionField.js b/packages/form-core/src/LionField.js index e6b36105d..5b83594be 100644 --- a/packages/form-core/src/LionField.js +++ b/packages/form-core/src/LionField.js @@ -22,7 +22,7 @@ import { InteractionStateMixin } from './InteractionStateMixin.js'; // applies F * * @customElement lion-field */ -// @ts-expect-error base constructors same return type +// @ts-expect-error lit properties false positive export class LionField extends FormControlMixin( InteractionStateMixin(FocusMixin(FormatMixin(ValidateMixin(SlotMixin(LitElement))))), ) { diff --git a/packages/form-core/src/choice-group/ChoiceInputMixin.js b/packages/form-core/src/choice-group/ChoiceInputMixin.js index dac659e9c..ea7313cbc 100644 --- a/packages/form-core/src/choice-group/ChoiceInputMixin.js +++ b/packages/form-core/src/choice-group/ChoiceInputMixin.js @@ -244,12 +244,15 @@ const ChoiceInputMixinImplementation = superclass => * hasChanged is designed for async (updated) callback, also check for sync * (requestUpdateInternal) callback * @param {{ modelValue:unknown }} newV - * @param {{ modelValue:unknown }} [oldV] + * @param {{ modelValue:unknown }} [old] */ - // @ts-expect-error - _onModelValueChanged({ modelValue }, { modelValue: old }) { - // @ts-expect-error - if (this.constructor._classProperties.get('modelValue').hasChanged(modelValue, old)) { + _onModelValueChanged({ modelValue }, old) { + let _old; + if (old && old.modelValue) { + _old = old.modelValue; + } + // @ts-expect-error lit private property + if (this.constructor._classProperties.get('modelValue').hasChanged(modelValue, _old)) { super._onModelValueChanged({ modelValue }); } } diff --git a/packages/form-core/src/registration/FormRegistrarMixin.js b/packages/form-core/src/registration/FormRegistrarMixin.js index 53ecc78d6..5bef28b20 100644 --- a/packages/form-core/src/registration/FormRegistrarMixin.js +++ b/packages/form-core/src/registration/FormRegistrarMixin.js @@ -93,7 +93,7 @@ const FormRegistrarMixinImplementation = superclass => console.info('Error Node:', child); // eslint-disable-line no-console throw new TypeError('You need to define a name'); } - // @ts-expect-error + // @ts-expect-error this._isFormOrFieldset true means we can assume `this.name` exists if (name === this.name) { console.info('Error Node:', child); // eslint-disable-line no-console throw new TypeError(`You can not have the same name "${name}" as your parent`); diff --git a/packages/form-core/src/utils/SyncUpdatableMixin.js b/packages/form-core/src/utils/SyncUpdatableMixin.js index 55b7daae4..eb8b7d12b 100644 --- a/packages/form-core/src/utils/SyncUpdatableMixin.js +++ b/packages/form-core/src/utils/SyncUpdatableMixin.js @@ -53,7 +53,7 @@ const SyncUpdatableMixinImplementation = superclass => * @param {*} oldValue */ static __syncUpdatableHasChanged(name, newValue, oldValue) { - // @ts-expect-error FIXME: Typescript bug, superclass static method not availabe from static context + // @ts-expect-error accessing private lit property const properties = this._classProperties; if (properties.get(name) && properties.get(name).hasChanged) { return properties.get(name).hasChanged(newValue, oldValue); diff --git a/packages/form-core/test-suites/FormRegistrationMixins.suite.js b/packages/form-core/test-suites/FormRegistrationMixins.suite.js index 8cabf1966..b719b1e51 100644 --- a/packages/form-core/test-suites/FormRegistrationMixins.suite.js +++ b/packages/form-core/test-suites/FormRegistrationMixins.suite.js @@ -10,7 +10,7 @@ import { FormRegistrarPortalMixin } from '../src/registration/FormRegistrarPorta /** * @typedef {Object} customConfig - * @property {typeof HTMLElement | typeof import('@lion/core').UpdatingElement | typeof LitElement} [baseElement] + * @property {typeof LitElement} [baseElement] * @property {string} [customConfig.suffix] * @property {string} [customConfig.parentTagString] * @property {string} [customConfig.childTagString] @@ -22,19 +22,16 @@ import { FormRegistrarPortalMixin } from '../src/registration/FormRegistrarPorta */ export const runRegistrationSuite = customConfig => { const cfg = { - // @ts-expect-error https://github.com/microsoft/TypeScript/issues/38535 - baseElement: HTMLElement, + // @ts-expect-error https://github.com/microsoft/TypeScript/issues/38535 fixed in later typescript version + baseElement: LitElement, ...customConfig, }; describe(`FormRegistrationMixins ${cfg.suffix}`, () => { - // @ts-expect-error base constructors same return type & type cannot be assigned like this class RegistrarClass extends FormRegistrarMixin(cfg.baseElement) {} cfg.parentTagString = defineCE(RegistrarClass); - // @ts-expect-error base constructors same return type & type cannot be assigned like this class RegisteringClass extends FormRegisteringMixin(cfg.baseElement) {} cfg.childTagString = defineCE(RegisteringClass); - // @ts-expect-error base constructors same return type & type cannot be assigned like this class PortalClass extends FormRegistrarPortalMixin(cfg.baseElement) {} cfg.portalTagString = defineCE(PortalClass); @@ -91,7 +88,6 @@ export const runRegistrationSuite = customConfig => { }); it('works for components that have a delayed render', async () => { - // @ts-expect-error base constructors same return type class PerformUpdate extends FormRegistrarMixin(LitElement) { async performUpdate() { await new Promise(resolve => setTimeout(() => resolve(), 10)); diff --git a/packages/form-core/test-suites/FormatMixin.suite.js b/packages/form-core/test-suites/FormatMixin.suite.js index 6180c2d7a..638beb88a 100644 --- a/packages/form-core/test-suites/FormatMixin.suite.js +++ b/packages/form-core/test-suites/FormatMixin.suite.js @@ -9,7 +9,6 @@ import { Unparseable, Validator } from '../index.js'; * @typedef {ArrayConstructor | ObjectConstructor | NumberConstructor | BooleanConstructor | StringConstructor | DateConstructor | 'iban' | 'email'} modelValueType */ -// @ts-expect-error base constructor same return type class FormatClass extends FormatMixin(LitElement) { get _inputNode() { return /** @type {HTMLInputElement} */ (super._inputNode); // casts type @@ -279,7 +278,6 @@ export function runFormatMixinSuite(customConfig) { }); it('works if there is no underlying _inputNode', async () => { - // @ts-expect-error base constructor same return type const tagNoInputString = defineCE(class extends FormatMixin(LitElement) {}); const tagNoInput = unsafeStatic(tagNoInputString); expect(async () => { diff --git a/packages/form-core/test-suites/InteractionStateMixin.suite.js b/packages/form-core/test-suites/InteractionStateMixin.suite.js index caef8ee4e..e9a23e390 100644 --- a/packages/form-core/test-suites/InteractionStateMixin.suite.js +++ b/packages/form-core/test-suites/InteractionStateMixin.suite.js @@ -24,7 +24,6 @@ export function runInteractionStateMixinSuite(customConfig) { }; describe(`InteractionStateMixin`, async () => { - // @ts-expect-error base constructors same return type class IState extends InteractionStateMixin(ValidateMixin(LitElement)) { connectedCallback() { super.connectedCallback(); @@ -244,7 +243,6 @@ export function runInteractionStateMixinSuite(customConfig) { describe('SubClassers', () => { it('can override the `_leaveEvent`', async () => { - // @ts-expect-error base constructor same return type class IStateCustomBlur extends InteractionStateMixin(LitElement) { constructor() { super(); diff --git a/packages/form-core/test-suites/ValidateMixin.suite.js b/packages/form-core/test-suites/ValidateMixin.suite.js index 06acf1902..b78e3346b 100644 --- a/packages/form-core/test-suites/ValidateMixin.suite.js +++ b/packages/form-core/test-suites/ValidateMixin.suite.js @@ -28,7 +28,6 @@ export function runValidateMixinSuite(customConfig) { const lightDom = cfg.lightDom || ''; - // @ts-expect-error base constructor same return type class ValidateElement extends ValidateMixin(LitElement) { connectedCallback() { super.connectedCallback(); @@ -562,7 +561,6 @@ export function runValidateMixinSuite(customConfig) { }; const withSuccessTagString = defineCE( - // @ts-expect-error class extends ValidateMixin(LitElement) { static get validationTypes() { return [...super.validationTypes, 'success']; @@ -677,7 +675,6 @@ export function runValidateMixinSuite(customConfig) { }); it('calls "._isEmpty" when provided (useful for different modelValues)', async () => { - // @ts-expect-error base constructor same return type class _isEmptyValidate extends ValidateMixin(LitElement) { _isEmpty() { // @ts-expect-error @@ -729,7 +726,6 @@ export function runValidateMixinSuite(customConfig) { describe('Default (preconfigured) Validators', () => { const preconfTagString = defineCE( - // @ts-expect-error base constructor same return type class extends ValidateMixin(LitElement) { constructor() { super(); @@ -752,7 +748,6 @@ export function runValidateMixinSuite(customConfig) { it('can be altered by App Developers', async () => { const altPreconfTagString = defineCE( - // @ts-expect-error base constructor same return type class extends ValidateMixin(LitElement) { constructor() { super(); @@ -918,7 +913,6 @@ export function runValidateMixinSuite(customConfig) { describe('Extensibility: Custom Validator types', () => { const customTypeTagString = defineCE( - // @ts-expect-error base constructor same return type class extends ValidateMixin(LitElement) { static get validationTypes() { return [...super.validationTypes, 'x', 'y']; @@ -1026,7 +1020,6 @@ export function runValidateMixinSuite(customConfig) { describe('Subclassers', () => { describe('Adding new Validator types', () => { it('can add helpers for validation types', async () => { - // @ts-expect-error base constructor same return type class ValidateHasX extends ValidateMixin(LitElement) { static get validationTypes() { return [...super.validationTypes, 'x']; @@ -1074,7 +1067,6 @@ export function runValidateMixinSuite(customConfig) { .concat(array2.filter(x => !array1.includes(x))); } const elTagString = defineCE( - // @ts-expect-error base constructor same return type class extends ValidateMixin(LitElement) { static get validationTypes() { return [...super.validationTypes, 'x']; @@ -1123,7 +1115,7 @@ export function runValidateMixinSuite(customConfig) { // TODO: add this test on FormControl layer it('reconsiders feedback visibility when interaction states changed', async () => { const elTagString = defineCE( - // @ts-expect-error base constructor same return type + // @ts-expect-error lit properties false positive, they get merged with parent properties by lit automatically class extends ValidateMixin(LitElement) { static get properties() { return { @@ -1168,7 +1160,7 @@ export function runValidateMixinSuite(customConfig) { it('filters feedback visibility according interaction states', async () => { const elTagString = defineCE( - // @ts-expect-error base constructor same return type + // @ts-expect-error lit properties false positive, they get merged with parent properties by lit automatically class extends ValidateMixin(LitElement) { static get validationTypes() { return ['error', 'info']; diff --git a/packages/form-core/test-suites/ValidateMixinFeedbackPart.suite.js b/packages/form-core/test-suites/ValidateMixinFeedbackPart.suite.js index e4fc39e0b..4fe45b8b1 100644 --- a/packages/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +++ b/packages/form-core/test-suites/ValidateMixinFeedbackPart.suite.js @@ -12,7 +12,6 @@ export function runValidateMixinFeedbackPart() { localizeTearDown(); }); - // @ts-expect-error base constructor same return type class ValidateElement extends ValidateMixin(LitElement) { connectedCallback() { super.connectedCallback(); @@ -80,7 +79,6 @@ export function runValidateMixinFeedbackPart() { }); it('reflects .showsFeedbackFor as attribute joined with "," to be used as a style hook', async () => { - // @ts-expect-error base constructors same return type class ValidateElementCustomTypes extends ValidateMixin(LitElement) { static get validationTypes() { return [...super.validationTypes, 'x']; @@ -307,7 +305,6 @@ export function runValidateMixinFeedbackPart() { }); it('shows success message after fixing an error', async () => { - // @ts-expect-error base constructor same return type class ValidateElementCustomTypes extends ValidateMixin(LitElement) { static get validationTypes() { return ['error', 'success']; @@ -362,7 +359,6 @@ export function runValidateMixinFeedbackPart() { describe('Meta data', () => { it('".getMessage()" gets a reference to formControl, params, modelValue and type', async () => { - // @ts-expect-error base constructor same return type class ValidateElementCustomTypes extends ValidateMixin(LitElement) { static get validationTypes() { return ['error', 'x']; diff --git a/packages/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js b/packages/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js index 2640f68ea..fac70a9b2 100644 --- a/packages/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js +++ b/packages/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js @@ -8,7 +8,6 @@ import { ChoiceInputMixin } from '../../src/choice-group/ChoiceInputMixin.js'; class ChoiceInput extends ChoiceInputMixin(LionInput) {} customElements.define('choice-group-input', ChoiceInput); -// @ts-expect-error class ChoiceGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) {} customElements.define('choice-group', ChoiceGroup); diff --git a/packages/form-core/test-suites/form-group/FormGroupMixin-input.suite.js b/packages/form-core/test-suites/form-group/FormGroupMixin-input.suite.js index 3d28b237a..eac385c87 100644 --- a/packages/form-core/test-suites/form-group/FormGroupMixin-input.suite.js +++ b/packages/form-core/test-suites/form-group/FormGroupMixin-input.suite.js @@ -20,12 +20,14 @@ export function runFormGroupMixinInputSuite(cfg = {}) { const childTagString = cfg.childTagString || defineCE(FormChild); - // @ts-expect-error const FormGroup = class extends FormGroupMixin(LitElement) { constructor() { super(); /** @override from FormRegistrarMixin */ this._isFormOrFieldset = true; + /** + * @type {'fieldset' | 'child' | 'choice-group'} + */ this._repropagationRole = 'fieldset'; // configures FormControlMixin } }; diff --git a/packages/form-core/test-suites/form-group/FormGroupMixin.suite.js b/packages/form-core/test-suites/form-group/FormGroupMixin.suite.js index d2a681723..5bb5ff6a8 100644 --- a/packages/form-core/test-suites/form-group/FormGroupMixin.suite.js +++ b/packages/form-core/test-suites/form-group/FormGroupMixin.suite.js @@ -29,7 +29,6 @@ export function runFormGroupMixinSuite(cfg = {}) { const childTagString = cfg.childTagString || defineCE(FormChild); - // @ts-expect-error base constructors same return type class FormGroup extends FormGroupMixin(LitElement) { constructor() { super(); @@ -131,8 +130,9 @@ export function runFormGroupMixinSuite(cfg = {}) { try { // we test the api directly as errors thrown from a web component are in a // different context and we can not catch them here => register fake elements - // @ts-expect-error - el.addFormElement(/** @type {FormControlHost} */ ({})); + el.addFormElement( + /** @type {HTMLElement & import('../../types/FormControlMixinTypes').FormControlHost} */ ({}), + ); } catch (err) { error = err; } @@ -151,8 +151,11 @@ export function runFormGroupMixinSuite(cfg = {}) { try { // we test the api directly as errors thrown from a web component are in a // different context and we can not catch them here => register fake elements - // @ts-expect-error - el.addFormElement(/** @type {FormControlHost} */ ({ name: 'foo' })); + el.addFormElement( + /** @type {HTMLElement & import('../../types/FormControlMixinTypes').FormControlHost} */ ({ + name: 'foo', + }), + ); } catch (err) { error = err; } @@ -171,10 +174,16 @@ export function runFormGroupMixinSuite(cfg = {}) { try { // we test the api directly as errors thrown from a web component are in a // different context and we can not catch them here => register fake elements - // @ts-expect-error - el.addFormElement(/** @type {FormControlHost} */ ({ name: 'fooBar' })); - // @ts-expect-error - el.addFormElement(/** @type {FormControlHost} */ ({ name: 'fooBar' })); + el.addFormElement( + /** @type {HTMLElement & import('../../types/FormControlMixinTypes').FormControlHost} */ ({ + name: 'fooBar', + }), + ); + el.addFormElement( + /** @type {HTMLElement & import('../../types/FormControlMixinTypes').FormControlHost} */ ({ + name: 'fooBar', + }), + ); } catch (err) { error = err; } @@ -628,7 +637,7 @@ export function runFormGroupMixinSuite(cfg = {}) { return 'Input1IsTen'; } - // @ts-expect-error + /** @param {?} value */ execute(value) { const hasError = value.input1 !== 10; return hasError; @@ -643,10 +652,8 @@ export function runFormGroupMixinSuite(cfg = {}) { <${childTag} name="input2" .validators=${[new IsNumber()]}> `)); - const inputs = el.querySelectorAll(childTagString); - // @ts-expect-error + const inputs = /** @type {FormChild[]} */ (Array.from(el.querySelectorAll(childTagString))); inputs[1].modelValue = 2; // make it dirty - // @ts-expect-error inputs[1].focus(); outSideButton.focus(); @@ -662,8 +669,8 @@ export function runFormGroupMixinSuite(cfg = {}) { const fieldset = /** @type {FormGroup} */ (await fixture( html`<${tag}>${inputSlots}`, )); - // @ts-expect-error - fieldset.formElements['hobbies[]'][0].serializer = v => `${v.value}-serialized`; + fieldset.formElements['hobbies[]'][0].serializer = /** @param {?} v */ v => + `${v.value}-serialized`; fieldset.formElements['hobbies[]'][0].modelValue = { checked: false, value: 'Bar' }; fieldset.formElements['hobbies[]'][1].modelValue = { checked: false, value: 'rugby' }; fieldset.formElements['gender[]'][0].modelValue = { checked: false, value: 'male' }; diff --git a/packages/form-core/test/FocusMixin.test.js b/packages/form-core/test/FocusMixin.test.js index a2e7cdf34..754a8ef01 100644 --- a/packages/form-core/test/FocusMixin.test.js +++ b/packages/form-core/test/FocusMixin.test.js @@ -3,7 +3,6 @@ import { defineCE, expect, fixture, html, oneEvent, unsafeStatic } from '@open-w import { FocusMixin } from '../src/FocusMixin.js'; describe('FocusMixin', () => { - // @ts-expect-error base constructors same return type class Focusable extends FocusMixin(LitElement) { render() { return html``; diff --git a/packages/form-core/test/FormControlMixin.test.js b/packages/form-core/test/FormControlMixin.test.js index 36c7a3dbd..6e7686b90 100644 --- a/packages/form-core/test/FormControlMixin.test.js +++ b/packages/form-core/test/FormControlMixin.test.js @@ -7,7 +7,6 @@ import { FormRegistrarMixin } from '../src/registration/FormRegistrarMixin.js'; describe('FormControlMixin', () => { const inputSlot = ''; - // @ts-expect-error base constructor same return type class FormControlMixinClass extends FormControlMixin(LitElement) {} const tagString = defineCE(FormControlMixinClass); @@ -213,7 +212,6 @@ describe('FormControlMixin', () => { }); describe('Model-value-changed event propagation', () => { - // @ts-expect-error base constructor same return type const FormControlWithRegistrarMixinClass = class extends FormControlMixin( FormRegistrarMixin(LitElement), ) {}; diff --git a/packages/form-core/test/FormRegistrationMixins.test.js b/packages/form-core/test/FormRegistrationMixins.test.js index 6d926eeea..06a7828d1 100644 --- a/packages/form-core/test/FormRegistrationMixins.test.js +++ b/packages/form-core/test/FormRegistrationMixins.test.js @@ -1,10 +1,10 @@ -import { LitElement, UpdatingElement } from '@lion/core'; +import { LitElement } from '@lion/core'; import { html } from '@open-wc/testing'; import { runRegistrationSuite } from '../test-suites/FormRegistrationMixins.suite.js'; runRegistrationSuite({ - suffix: 'with UpdatingElement', - baseElement: UpdatingElement, + suffix: 'with LitElement', + baseElement: LitElement, }); runRegistrationSuite({ diff --git a/packages/form-core/test/utils/SyncUpdatableMixin.test.js b/packages/form-core/test/utils/SyncUpdatableMixin.test.js index 680039de7..28f7c7488 100644 --- a/packages/form-core/test/utils/SyncUpdatableMixin.test.js +++ b/packages/form-core/test/utils/SyncUpdatableMixin.test.js @@ -8,7 +8,6 @@ describe('SyncUpdatableMixin', () => { it('initializes all properties', async () => { let hasCalledFirstUpdated = false; let hasCalledUpdateSync = false; - // @ts-expect-error base constructors same return type class UpdatableImplementation extends SyncUpdatableMixin(LitElement) { static get properties() { return { @@ -65,7 +64,6 @@ describe('SyncUpdatableMixin', () => { it('guarantees Member Order Independence', async () => { let hasCalledRunPropertyEffect = false; - // @ts-expect-error base constructors same return type class UpdatableImplementation extends SyncUpdatableMixin(LitElement) { static get properties() { return { @@ -136,7 +134,6 @@ describe('SyncUpdatableMixin', () => { let propChangedCount = 0; let propUpdateSyncCount = 0; - // @ts-expect-error the private override is on purpose class UpdatableImplementation extends SyncUpdatableMixin(LitElement) { static get properties() { return { @@ -189,7 +186,6 @@ describe('SyncUpdatableMixin', () => { describe('After firstUpdated', () => { it('calls "updateSync" immediately when the observed property is changed (newValue !== oldValue)', async () => { - // @ts-expect-error class UpdatableImplementation extends SyncUpdatableMixin(LitElement) { static get properties() { return { @@ -245,7 +241,6 @@ describe('SyncUpdatableMixin', () => { describe('Features', () => { // See: https://lit-element.polymer-project.org/guide/lifecycle#haschanged it('supports "hasChanged" from UpdatingElement', async () => { - // @ts-expect-error base constructors same return type class UpdatableImplementation extends SyncUpdatableMixin(LitElement) { static get properties() { return { diff --git a/packages/form-core/test/validate/Validator.test.js b/packages/form-core/test/validate/Validator.test.js index bd9cbbd62..8e0e0e5b9 100644 --- a/packages/form-core/test/validate/Validator.test.js +++ b/packages/form-core/test/validate/Validator.test.js @@ -134,7 +134,7 @@ describe('Validator', () => { it('has access to FormControl', async () => { const lightDom = ''; - // @ts-expect-error base constructors same return type + // @ts-expect-error false positive for incompatible static get properties. Lit-element merges super properties already for you. class ValidateElement extends ValidateMixin(LitElement) { static get properties() { return { modelValue: String }; diff --git a/packages/form-core/types/FocusMixinTypes.d.ts b/packages/form-core/types/FocusMixinTypes.d.ts index 806c9db3e..ce4270c6c 100644 --- a/packages/form-core/types/FocusMixinTypes.d.ts +++ b/packages/form-core/types/FocusMixinTypes.d.ts @@ -3,6 +3,7 @@ import { LitElement } from '@lion/core'; import { FormControlHost } from './FormControlMixinTypes'; export declare class FocusHost { + constructor(...args: any[]); focused: boolean; connectedCallback(): void; diff --git a/packages/form-core/types/FormControlMixinTypes.d.ts b/packages/form-core/types/FormControlMixinTypes.d.ts index c0b01c739..35de99bf7 100644 --- a/packages/form-core/types/FormControlMixinTypes.d.ts +++ b/packages/form-core/types/FormControlMixinTypes.d.ts @@ -36,6 +36,7 @@ declare interface HTMLElementWithValue extends HTMLElement { } export declare class FormControlHost { + constructor(...args: any[]); static get styles(): CSSResultArray; static get properties(): { name: { diff --git a/packages/form-core/types/FormatMixinTypes.d.ts b/packages/form-core/types/FormatMixinTypes.d.ts index f40272159..88dba6df4 100644 --- a/packages/form-core/types/FormatMixinTypes.d.ts +++ b/packages/form-core/types/FormatMixinTypes.d.ts @@ -5,6 +5,7 @@ import { ValidateHost } from './validate/ValidateMixinTypes'; import { FormControlHost } from './FormControlMixinTypes'; export declare class FormatHost { + constructor(...args: any[]); formattedValue: string; serializedValue: string; formatOn: string; diff --git a/packages/form-core/types/InteractionStateMixinTypes.d.ts b/packages/form-core/types/InteractionStateMixinTypes.d.ts index a9e929beb..1d4f2a90e 100644 --- a/packages/form-core/types/InteractionStateMixinTypes.d.ts +++ b/packages/form-core/types/InteractionStateMixinTypes.d.ts @@ -3,6 +3,7 @@ import { LitElement } from '@lion/core'; import { FormControlHost } from './FormControlMixinTypes'; export declare class InteractionStateHost { + constructor(...args: any[]); prefilled: boolean; filled: boolean; touched: boolean; @@ -26,7 +27,7 @@ export declare function InteractionStateImplementation & - InteractionStateHost & + typeof InteractionStateHost & Constructor & typeof FormControlHost; diff --git a/packages/form-core/types/NativeTextFieldMixinTypes.d.ts b/packages/form-core/types/NativeTextFieldMixinTypes.d.ts index 6ccb883d4..7411f77d9 100644 --- a/packages/form-core/types/NativeTextFieldMixinTypes.d.ts +++ b/packages/form-core/types/NativeTextFieldMixinTypes.d.ts @@ -6,6 +6,7 @@ export declare class NativeTextField extends LionField { } export declare class NativeTextFieldHost { + constructor(...args: any[]); get selectionStart(): number; set selectionStart(value: number); get selectionEnd(): number; diff --git a/packages/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts b/packages/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts index 0a5ba16b2..1eb530966 100644 --- a/packages/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts +++ b/packages/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts @@ -5,6 +5,7 @@ import { FormRegistrarHost } from '../registration/FormRegistrarMixinTypes'; import { InteractionStateHost } from '../InteractionStateMixinTypes'; export declare class ChoiceGroupHost { + constructor(...args: any[]); multipleChoice: boolean; connectedCallback(): void; diff --git a/packages/form-core/types/choice-group/ChoiceInputMixinTypes.d.ts b/packages/form-core/types/choice-group/ChoiceInputMixinTypes.d.ts index 00326c14d..fc0ed434e 100644 --- a/packages/form-core/types/choice-group/ChoiceInputMixinTypes.d.ts +++ b/packages/form-core/types/choice-group/ChoiceInputMixinTypes.d.ts @@ -15,6 +15,7 @@ export interface ChoiceInputSerializedValue { } export declare class ChoiceInputHost { + constructor(...args: any[]); modelValue: ChoiceInputModelValue; serializedValue: ChoiceInputSerializedValue; diff --git a/packages/form-core/types/form-group/FormGroupMixinTypes.d.ts b/packages/form-core/types/form-group/FormGroupMixinTypes.d.ts index 7afaa1c4d..539fddbfd 100644 --- a/packages/form-core/types/form-group/FormGroupMixinTypes.d.ts +++ b/packages/form-core/types/form-group/FormGroupMixinTypes.d.ts @@ -7,6 +7,7 @@ import { FormRegistrarHost } from '../registration/FormRegistrarMixinTypes'; import { ValidateHost } from '../validate/ValidateMixinTypes'; export declare class FormGroupHost { + constructor(...args: any[]); protected static _addDescriptionElementIdsToField(): void; _inputNode: HTMLElement; submitGroup(): void; @@ -29,7 +30,7 @@ export declare function FormGroupImplementation & - FormGroupHost & + typeof FormGroupHost & Constructor & typeof FormRegistrarHost & Constructor & diff --git a/packages/form-core/types/registration/FormRegisteringMixinTypes.d.ts b/packages/form-core/types/registration/FormRegisteringMixinTypes.d.ts index 5503d135d..3f418755b 100644 --- a/packages/form-core/types/registration/FormRegisteringMixinTypes.d.ts +++ b/packages/form-core/types/registration/FormRegisteringMixinTypes.d.ts @@ -3,6 +3,7 @@ import { FormRegistrarHost } from './FormRegistrarMixinTypes'; import { LitElement } from '@lion/core'; export declare class FormRegisteringHost { + constructor(...args: any[]); connectedCallback(): void; disconnectedCallback(): void; __parentFormGroup?: FormRegistrarHost; diff --git a/packages/form-core/types/registration/FormRegistrarMixinTypes.d.ts b/packages/form-core/types/registration/FormRegistrarMixinTypes.d.ts index d38ac0aad..f6a8a230d 100644 --- a/packages/form-core/types/registration/FormRegistrarMixinTypes.d.ts +++ b/packages/form-core/types/registration/FormRegistrarMixinTypes.d.ts @@ -9,6 +9,7 @@ export declare class ElementWithParentFormGroup { } export declare class FormRegistrarHost { + constructor(...args: any[]); _isFormOrFieldset: boolean; formElements: FormControlsCollection & { [x: string]: any }; addFormElement( diff --git a/packages/form-core/types/registration/FormRegistrarPortalMixinTypes.d.ts b/packages/form-core/types/registration/FormRegistrarPortalMixinTypes.d.ts index a53d49986..e376d4ee2 100644 --- a/packages/form-core/types/registration/FormRegistrarPortalMixinTypes.d.ts +++ b/packages/form-core/types/registration/FormRegistrarPortalMixinTypes.d.ts @@ -2,6 +2,7 @@ import { Constructor } from '@open-wc/dedupe-mixin'; import { LitElement } from '@lion/core'; export declare class FormRegistrarPortalHost { + constructor(...args: any[]); registrationTarget: HTMLElement; __redispatchEventForFormRegistrarPortalMixin(ev: CustomEvent): void; } diff --git a/packages/form-core/types/utils/SyncUpdatableMixinTypes.d.ts b/packages/form-core/types/utils/SyncUpdatableMixinTypes.d.ts index 911fda41b..d47766660 100644 --- a/packages/form-core/types/utils/SyncUpdatableMixinTypes.d.ts +++ b/packages/form-core/types/utils/SyncUpdatableMixinTypes.d.ts @@ -10,6 +10,7 @@ export declare interface SyncUpdatableNamespace { } export declare class SyncUpdatableHost { + constructor(...args: any[]); static __syncUpdatableHasChanged(name: string, newValue: any, oldValue: any): boolean; updateSync(name: string, oldValue: any): void; __syncUpdatableInitialize(): void; diff --git a/packages/form-core/types/validate/ValidateMixinTypes.d.ts b/packages/form-core/types/validate/ValidateMixinTypes.d.ts index bb2885018..5849a12bd 100644 --- a/packages/form-core/types/validate/ValidateMixinTypes.d.ts +++ b/packages/form-core/types/validate/ValidateMixinTypes.d.ts @@ -19,6 +19,7 @@ type FeedbackMessage = { }; export declare class ValidateHost { + constructor(...args: any[]); validators: Validator[]; hasFeedbackFor: string[]; shouldShowFeedbackFor: string[]; diff --git a/packages/form-integrations/test/form-integrations.test.js b/packages/form-integrations/test/form-integrations.test.js index ae14f72f4..6d28f3bd6 100644 --- a/packages/form-integrations/test/form-integrations.test.js +++ b/packages/form-integrations/test/form-integrations.test.js @@ -1,10 +1,14 @@ import { expect, fixture, html } from '@open-wc/testing'; import './helpers/umbrella-form.js'; +/** + * @typedef {import('./helpers/umbrella-form.js').UmbrellaForm} UmbrellaForm + */ + // Test umbrella form. describe('Form Integrations', () => { it('".serializedValue" returns all non disabled fields based on form structure', async () => { - const el = await fixture(html``); + const el = /** @type {UmbrellaForm} */ (await fixture(html``)); await el.updateComplete; const formEl = el._lionFormNode; expect(formEl.serializedValue).to.eql({ @@ -29,7 +33,7 @@ describe('Form Integrations', () => { }); it('".formattedValue" returns all non disabled fields based on form structure', async () => { - const el = await fixture(html``); + const el = /** @type {UmbrellaForm} */ (await fixture(html``)); await el.updateComplete; const formEl = el._lionFormNode; expect(formEl.formattedValue).to.eql({ diff --git a/packages/form-integrations/test/form-reset.test.js b/packages/form-integrations/test/form-reset.test.js index 2462c5bdd..d2a0c54a0 100644 --- a/packages/form-integrations/test/form-reset.test.js +++ b/packages/form-integrations/test/form-reset.test.js @@ -18,6 +18,7 @@ import '@lion/textarea/lion-textarea'; import { elementUpdated, expect, fixture, html } from '@open-wc/testing'; describe(`Submitting/Resetting Form`, async () => { + /** @type {import('@lion/form').LionForm} */ let el; beforeEach(async () => { el = await fixture(html` @@ -121,7 +122,7 @@ describe(`Submitting/Resetting Form`, async () => { }); it('Submitting a form should make submitted true for all fields', async () => { - el.querySelector('#submit_button').click(); + /** @type {import('@lion/button').LionButton} */ (el.querySelector('#submit_button')).click(); await elementUpdated(el); await el.updateComplete; el.formElements.forEach(field => { @@ -130,8 +131,8 @@ describe(`Submitting/Resetting Form`, async () => { }); it('Resetting a form should reset metadata of all fields', async () => { - el.querySelector('#submit_button').click(); - el.querySelector('#reset_button').click(); + /** @type {import('@lion/button').LionButton} */ (el.querySelector('#submit_button')).click(); + /** @type {import('@lion/button').LionButton} */ (el.querySelector('#reset_button')).click(); await elementUpdated(el); await el.updateComplete; expect(el.submitted).to.be.false; diff --git a/packages/form-integrations/test/helpers/umbrella-form.js b/packages/form-integrations/test/helpers/umbrella-form.js index da9e44136..363c90447 100644 --- a/packages/form-integrations/test/helpers/umbrella-form.js +++ b/packages/form-integrations/test/helpers/umbrella-form.js @@ -22,7 +22,9 @@ import '@lion/button/lion-button.js'; export class UmbrellaForm extends LitElement { get _lionFormNode() { - return this.shadowRoot.querySelector('lion-form'); + return /** @type {import('@lion/form').LionForm} */ (this.shadowRoot?.querySelector( + 'lion-form', + )); } render() { @@ -113,8 +115,10 @@ export class UmbrellaForm extends LitElement { - ev.currentTarget.parentElement.parentElement.parentElement.resetGroup()} + @click=${() => { + const lionForm = this._lionFormNode; + lionForm.resetGroup(); + }} >Reset diff --git a/packages/form-integrations/test/model-value-consistency.test.js b/packages/form-integrations/test/model-value-consistency.test.js index f2eace889..7679ae1ed 100644 --- a/packages/form-integrations/test/model-value-consistency.test.js +++ b/packages/form-integrations/test/model-value-consistency.test.js @@ -29,14 +29,29 @@ import '@lion/fieldset/lion-fieldset.js'; import '@lion/form/lion-form.js'; import '@lion/form-core/lion-field.js'; +/** + * @typedef {import('@lion/core').LitElement} LitElement + * @typedef {import('@lion/form-core').LionField} LionField + * @typedef {import('@lion/form-core/types/FormControlMixinTypes').FormControlHost & HTMLElement & {__parentFormGroup?: HTMLElement, checked?: boolean, disabled: boolean, hasFeedbackFor: string[], makeRequestToBeDisabled: Function }} FormControl + * @typedef {import('@lion/input').LionInput} LionInput + * @typedef {import('@lion/select').LionSelect} LionSelect + * @typedef {import('@lion/listbox').LionOption} LionOption + */ + const featureName = 'model value'; -const getFirstPaintTitle = count => `should dispatch ${count} time(s) on first paint`; -const getInteractionTitle = count => `should dispatch ${count} time(s) on interaction`; +const getFirstPaintTitle = /** @param {number} count */ count => + `should dispatch ${count} time(s) on first paint`; +const getInteractionTitle = /** @param {number} count */ count => + `should dispatch ${count} time(s) on interaction`; const firstStampCount = 1; const interactionCount = 1; +/** + * @param {string} tagname + * @param {number} count + */ const fieldDispatchesCountOnFirstPaint = (tagname, count) => { const tag = unsafeStatic(tagname); const spy = sinon.spy(); @@ -46,11 +61,15 @@ const fieldDispatchesCountOnFirstPaint = (tagname, count) => { }); }; +/** + * @param {string} tagname + * @param {number} count + */ const fieldDispatchesCountOnInteraction = (tagname, count) => { const tag = unsafeStatic(tagname); const spy = sinon.spy(); it(getInteractionTitle(count), async () => { - const el = await fixture(html`<${tag}>`); + const el = /** @type {LionField} */ (await fixture(html`<${tag}>`)); el.addEventListener('model-value-changed', spy); // TODO: discuss if this is the "correct" way to interact with component el.modelValue = 'foo'; @@ -59,6 +78,10 @@ const fieldDispatchesCountOnInteraction = (tagname, count) => { }); }; +/** + * @param {string} tagname + * @param {number} count + */ const choiceDispatchesCountOnFirstPaint = (tagname, count) => { const tag = unsafeStatic(tagname); const spy = sinon.spy(); @@ -68,17 +91,28 @@ const choiceDispatchesCountOnFirstPaint = (tagname, count) => { }); }; +/** + * @param {string} tagname + * @param {number} count + */ const choiceDispatchesCountOnInteraction = (tagname, count) => { const tag = unsafeStatic(tagname); const spy = sinon.spy(); it(getInteractionTitle(count), async () => { - const el = await fixture(html`<${tag} .choiceValue="${'option'}">`); + const el = /** @type {HTMLElement & {checked: boolean}} */ (await fixture( + html`<${tag} .choiceValue="${'option'}">`, + )); el.addEventListener('model-value-changed', spy); el.checked = true; expect(spy.callCount).to.equal(count); }); }; +/** + * @param {string} groupTagname + * @param {string} itemTagname + * @param {number} count + */ const choiceGroupDispatchesCountOnFirstPaint = (groupTagname, itemTagname, count) => { const groupTag = unsafeStatic(groupTagname); const itemTag = unsafeStatic(itemTagname); @@ -96,6 +130,11 @@ const choiceGroupDispatchesCountOnFirstPaint = (groupTagname, itemTagname, count }); }; +/** + * @param {string} groupTagname + * @param {string} itemTagname + * @param {number} count + */ const choiceGroupDispatchesCountOnInteraction = (groupTagname, itemTagname, count) => { const groupTag = unsafeStatic(groupTagname); const itemTag = unsafeStatic(itemTagname); @@ -110,13 +149,17 @@ const choiceGroupDispatchesCountOnInteraction = (groupTagname, itemTagname, coun `); el.addEventListener('model-value-changed', spy); - const option2 = el.querySelector(`${itemTagname}:nth-child(2)`); + const option2 = /** @type {HTMLElement & {checked: boolean}} */ (el.querySelector( + `${itemTagname}:nth-child(2)`, + )); option2.checked = true; expect(spy.callCount).to.equal(count); spy.resetHistory(); - const option3 = el.querySelector(`${itemTagname}:nth-child(3)`); + const option3 = /** @type {HTMLElement & {checked: boolean}} */ (el.querySelector( + `${itemTagname}:nth-child(3)`, + )); option3.checked = true; expect(spy.callCount).to.equal(count); }); @@ -178,7 +221,7 @@ describe('lion-select', () => { it(getInteractionTitle(interactionCount), async () => { const spy = sinon.spy(); - const el = await fixture(html` + const el = /** @type {LionSelect} */ (await fixture(html` - `); + `)); el.addEventListener('model-value-changed', spy); - const option2 = el.querySelector('option:nth-child(2)'); + const option2 = /** @type {HTMLOptionElement} */ (el.querySelector('option:nth-child(2)')); // mimic user input option2.selected = true; @@ -198,7 +241,7 @@ describe('lion-select', () => { spy.resetHistory(); - const option3 = el.querySelector('option:nth-child(3)'); + const option3 = /** @type {HTMLOptionElement} */ (el.querySelector('option:nth-child(3)')); // mimic user input option3.selected = true; @@ -238,13 +281,13 @@ describe('lion-select', () => { `); el.addEventListener('model-value-changed', spy); - const option2 = el.querySelector('lion-option:nth-child(2)'); + const option2 = /** @type {LionOption} */ (el.querySelector('lion-option:nth-child(2)')); option2.checked = true; expect(spy.callCount).to.equal(interactionCount); spy.resetHistory(); - const option3 = el.querySelector('lion-option:nth-child(3)'); + const option3 = /** @type {LionOption} */ (el.querySelector('lion-option:nth-child(3)')); option3.checked = true; expect(spy.callCount).to.equal(interactionCount); }); @@ -274,7 +317,7 @@ describe('lion-fieldset', () => { `); el.addEventListener('model-value-changed', spy); - const input = el.querySelector('lion-input'); + const input = /** @type {LionInput} */ (el.querySelector('lion-input')); input.modelValue = 'foo'; expect(spy.callCount).to.equal(interactionCount); }); @@ -337,8 +380,9 @@ describe('detail.isTriggeredByUser', () => { * - false: when child formElement condition for RegularField is not met */ - const featureDetectChoiceField = el => 'checked' in el && 'choiceValue' in el; - const featureDetectOptionChoiceField = el => 'active' in el; + const featureDetectChoiceField = /** @param {HTMLElement} el */ el => + 'checked' in el && 'choiceValue' in el; + const featureDetectOptionChoiceField = /** @param {HTMLElement} el */ el => 'active' in el; /** * @param {FormControl} el @@ -355,9 +399,8 @@ describe('detail.isTriggeredByUser', () => { } /** - * @param {FormControl} el + * @param {FormControl & {value: string}} el * @param {string} newViewValue - * @returns {'RegularField'|'ChoiceField'|'OptionChoiceField'|'ChoiceGroupField'|'FormOrFieldset'} */ function mimicUserInput(el, newViewValue) { const type = detectType(el); @@ -391,27 +434,39 @@ describe('detail.isTriggeredByUser', () => { } else if (controlName === 'field') { childrenEl = await fixture(html``); } - const el = await fixture(html`<${tag}>${childrenEl}`); + + const el = /** @type {LitElement & FormControl & {value: string} & {registrationComplete: Promise} & {formElements: Array.}} */ (await fixture( + html`<${tag}>${childrenEl}`, + )); await el.registrationComplete; el.addEventListener('model-value-changed', spy); + /** + * @param {FormControl & {value: string}} formControl + */ function expectCorrectEventMetaRegularField(formControl) { - mimicUserInput(formControl, 'userValue', 'RegularField'); + mimicUserInput(formControl, 'userValue'); expect(spy.firstCall.args[0].detail.isTriggeredByUser).to.be.true; // eslint-disable-next-line no-param-reassign formControl.modelValue = 'programmaticValue'; expect(spy.secondCall.args[0].detail.isTriggeredByUser).to.be.false; } + /** + * @param {FormControl & {value: string}} formControl + */ function resetChoiceFieldToForceRepropagation(formControl) { // eslint-disable-next-line no-param-reassign formControl.checked = false; spy.resetHistory(); } + /** + * @param {FormControl & {value: string}} formControl + */ function expectCorrectEventMetaChoiceField(formControl) { resetChoiceFieldToForceRepropagation(formControl); - mimicUserInput(formControl, 'userValue', 'ChoiceField'); + mimicUserInput(formControl, 'userValue'); expect(spy.firstCall.args[0].detail.isTriggeredByUser).to.be.true; resetChoiceFieldToForceRepropagation(formControl); diff --git a/packages/form-integrations/test/model-value-event.test.js b/packages/form-integrations/test/model-value-event.test.js index 0004423f2..f579c9677 100644 --- a/packages/form-integrations/test/model-value-event.test.js +++ b/packages/form-integrations/test/model-value-event.test.js @@ -4,20 +4,28 @@ import { expect, html, fixture } from '@open-wc/testing'; // eslint-disable-next-line import/no-extraneous-dependencies import sinon from 'sinon'; +/** + * @typedef {import('@lion/input').LionInput} LionInput + * @typedef {import('@lion/fieldset').LionFieldset} LionFieldset + * @typedef {import('@lion/core').TemplateResult} TemplateResult + */ +const inputFixture = /** @type {(arg: TemplateResult) => Promise} */ (fixture); +const fieldsetFixture = /** @type {(arg: TemplateResult) => Promise} */ (fixture); + describe('model value event', () => { describe('form path', () => { it('should be property', async () => { const spy = sinon.spy(); - const input = await fixture(html``); + const input = await inputFixture(html``); input.addEventListener('model-value-changed', spy); input.modelValue = 'woof'; const e = spy.firstCall.args[0]; - expect(e.detail).to.have.a.property('formPath'); + expect(e.detail).to.have.property('formPath'); }); it('should contain dispatching field', async () => { const spy = sinon.spy(); - const input = await fixture(html``); + const input = await inputFixture(html``); input.addEventListener('model-value-changed', spy); input.modelValue = 'foo'; const e = spy.firstCall.args[0]; @@ -26,14 +34,14 @@ describe('model value event', () => { it('should contain field and group', async () => { const spy = sinon.spy(); - const fieldset = await fixture(html` + const fieldset = await fieldsetFixture(html` `); await fieldset.registrationComplete; fieldset.addEventListener('model-value-changed', spy); - const input = fieldset.querySelector('lion-input'); + const input = /** @type {LionInput} */ (fieldset.querySelector('lion-input')); input.modelValue = 'foo'; const e = spy.firstCall.args[0]; expect(e.detail.formPath).to.eql([input, fieldset]); @@ -41,15 +49,15 @@ describe('model value event', () => { it('should contain deep elements', async () => { const spy = sinon.spy(); - const grandparent = await fixture(html` + const grandparent = await fieldsetFixture(html` `); - const parent = grandparent.querySelector('[name=parent]'); - const input = grandparent.querySelector('[name=input]'); + const parent = /** @type {LionFieldset} */ (grandparent.querySelector('[name=parent]')); + const input = /** @type {LionInput} */ (grandparent.querySelector('[name=input]')); await grandparent.registrationComplete; await parent.registrationComplete; @@ -61,7 +69,7 @@ describe('model value event', () => { it('should ignore elements that are not fields or fieldsets', async () => { const spy = sinon.spy(); - const grandparent = await fixture(html` + const grandparent = await fieldsetFixture(html`
@@ -74,8 +82,8 @@ describe('model value event', () => {
`); - const parent = grandparent.querySelector('[name=parent]'); - const input = grandparent.querySelector('[name=input]'); + const parent = /** @type {LionFieldset} */ (grandparent.querySelector('[name=parent]')); + const input = /** @type {LionInput} */ (grandparent.querySelector('[name=input]')); await grandparent.registrationComplete; await parent.registrationComplete; @@ -87,10 +95,11 @@ describe('model value event', () => { }); describe('signature', () => { + /** @type {?} */ let e; beforeEach(async () => { const spy = sinon.spy(); - const el = await fixture(html``); + const el = await inputFixture(html``); el.addEventListener('model-value-changed', spy); el.modelValue = 'foo'; // eslint-disable-next-line prefer-destructuring @@ -112,18 +121,19 @@ describe('model value event', () => { describe('propagation', () => { it('should dispatch different event at each level', async () => { - const grandparent = await fixture(html` + const grandparent = await fieldsetFixture(html` `); - const parent = grandparent.querySelector('[name="parent"]'); - const input = grandparent.querySelector('[name="input"]'); + const parent = /** @type {LionFieldset} */ (grandparent.querySelector('[name="parent"]')); + const input = /** @type {LionInput} */ (grandparent.querySelector('[name="input"]')); await grandparent.registrationComplete; await parent.registrationComplete; + /** @type {sinon.SinonSpy[]} */ const spies = []; [grandparent, parent, input].forEach(element => { const spy = sinon.spy(); diff --git a/packages/input-date/src/LionInputDate.js b/packages/input-date/src/LionInputDate.js index 6579055f0..6d27b5fe4 100644 --- a/packages/input-date/src/LionInputDate.js +++ b/packages/input-date/src/LionInputDate.js @@ -18,7 +18,7 @@ function isValidDate(date) { * * @customElement lion-input-date */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 +// @ts-expect-error false positive for incompatible static get properties. Lit-element merges super properties already for you. export class LionInputDate extends LocalizeMixin(LionInput) { static get properties() { return { diff --git a/packages/input-datepicker/src/LionCalendarOverlayFrame.js b/packages/input-datepicker/src/LionCalendarOverlayFrame.js index 5b1c5d919..a6147bef4 100644 --- a/packages/input-datepicker/src/LionCalendarOverlayFrame.js +++ b/packages/input-datepicker/src/LionCalendarOverlayFrame.js @@ -1,7 +1,6 @@ import { css, html, LitElement } from '@lion/core'; import { LocalizeMixin } from '@lion/localize'; -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionCalendarOverlayFrame extends LocalizeMixin(LitElement) { static get styles() { return [ diff --git a/packages/input-datepicker/src/LionInputDatepicker.js b/packages/input-datepicker/src/LionInputDatepicker.js index 3601ae3d5..5d05c6560 100644 --- a/packages/input-datepicker/src/LionInputDatepicker.js +++ b/packages/input-datepicker/src/LionInputDatepicker.js @@ -12,7 +12,7 @@ import { LionCalendarOverlayFrame } from './LionCalendarOverlayFrame.js'; /** * @customElement lion-input-datepicker */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 +// @ts-expect-error false positive for incompatible static get properties. Lit-element merges super properties already for you. export class LionInputDatepicker extends ScopedElementsMixin( ArrowMixin(OverlayMixin(LionInputDate)), ) { @@ -199,9 +199,8 @@ export class LionInputDatepicker extends ScopedElementsMixin( __toggleInvokerDisabled() { if (this._invokerNode) { - // @ts-expect-error even though disabled may not exist on the invoker node - // set it anyway, it doesn't harm, and is needed in case of invoker elements that do have disabled prop - this._invokerNode.disabled = this.disabled || this.readOnly; + const invokerNode = /** @type {HTMLElement & {disabled: boolean}} */ (this._invokerNode); + invokerNode.disabled = this.disabled || this.readOnly; } } diff --git a/packages/input-email/src/LionInputEmail.js b/packages/input-email/src/LionInputEmail.js index f8479393d..9ae5bfd23 100644 --- a/packages/input-email/src/LionInputEmail.js +++ b/packages/input-email/src/LionInputEmail.js @@ -7,7 +7,6 @@ import { LocalizeMixin } from '@lion/localize'; * * @customElement lion-input-email */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionInputEmail extends LocalizeMixin(LionInput) { constructor() { super(); diff --git a/packages/input-iban/src/LionInputIban.js b/packages/input-iban/src/LionInputIban.js index d9ff6d991..9e88adf98 100644 --- a/packages/input-iban/src/LionInputIban.js +++ b/packages/input-iban/src/LionInputIban.js @@ -8,7 +8,6 @@ import { IsIBAN } from './validators.js'; * `LionInputIban` is a class for an IBAN custom form element (``). * @customElement lion-input-iban */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionInputIban extends LocalizeMixin(LionInput) { constructor() { super(); diff --git a/packages/listbox/src/LionListbox.js b/packages/listbox/src/LionListbox.js index 4c74b9bae..33804085d 100644 --- a/packages/listbox/src/LionListbox.js +++ b/packages/listbox/src/LionListbox.js @@ -8,7 +8,6 @@ import { ListboxMixin } from './ListboxMixin.js'; * LionListbox: implements the wai-aria listbox design pattern and integrates it as a Lion * FormControl */ -// @ts-expect-error export class LionListbox extends ListboxMixin( FocusMixin(InteractionStateMixin(ValidateMixin(LitElement))), ) {} diff --git a/packages/listbox/src/LionOption.js b/packages/listbox/src/LionOption.js index 8e70dd071..4ee22ffdb 100644 --- a/packages/listbox/src/LionOption.js +++ b/packages/listbox/src/LionOption.js @@ -13,7 +13,6 @@ import { css, DisabledMixin, html, LitElement } from '@lion/core'; * Element gets state supplied externally, reflects this to attributes, * enabling SubClassers to style based on those states */ -// @ts-expect-error export class LionOption extends DisabledMixin(ChoiceInputMixin(FormRegisteringMixin(LitElement))) { static get properties() { return { diff --git a/packages/listbox/types/LionOption.d.ts b/packages/listbox/types/LionOption.d.ts index 428930cd3..b36816f2e 100644 --- a/packages/listbox/types/LionOption.d.ts +++ b/packages/listbox/types/LionOption.d.ts @@ -1,5 +1,6 @@ import { ChoiceGroupHost } from '@lion/form-core/types/choice-group/ChoiceGroupMixinTypes'; export declare class LionOptionHost { + constructor(...args: any[]); private __parentFormGroup: ChoiceGroupHost; } diff --git a/packages/listbox/types/ListboxMixinTypes.d.ts b/packages/listbox/types/ListboxMixinTypes.d.ts index a498ea0bd..ba570226f 100644 --- a/packages/listbox/types/ListboxMixinTypes.d.ts +++ b/packages/listbox/types/ListboxMixinTypes.d.ts @@ -9,6 +9,7 @@ import { LionOptions } from '../src/LionOptions.js'; import { LionOption } from '../src/LionOption.js'; export declare class ListboxHost { + constructor(...args: any[]); /** * When true, will synchronize activedescendant and selected element on * arrow key navigation. diff --git a/packages/localize/test/LocalizeMixin.test.js b/packages/localize/test/LocalizeMixin.test.js index a3d9dacd4..f948e9509 100644 --- a/packages/localize/test/LocalizeMixin.test.js +++ b/packages/localize/test/LocalizeMixin.test.js @@ -71,7 +71,6 @@ describe('LocalizeMixin', () => { 'child-element': loc => fakeImport(`./child-element/${loc}.js`), }; - // @ts-expect-error class ParentElement extends LocalizeMixin(LitElement) { static get localizeNamespaces() { return [parentElementNs, defaultNs, ...super.localizeNamespaces]; @@ -79,7 +78,6 @@ describe('LocalizeMixin', () => { } const tagString = defineCE( - // @ts-expect-error class ChildElement extends LocalizeMixin(ParentElement) { static get localizeNamespaces() { return [childElementNs, defaultNs, ...super.localizeNamespaces]; diff --git a/packages/localize/types/LocalizeMixinTypes.d.ts b/packages/localize/types/LocalizeMixinTypes.d.ts index dde294a95..329a1416c 100644 --- a/packages/localize/types/LocalizeMixinTypes.d.ts +++ b/packages/localize/types/LocalizeMixinTypes.d.ts @@ -56,7 +56,7 @@ interface msgOptions { } declare class LocalizeMixinHost { - // FIXME: return value type check doesn't seem to be `working! + constructor(...args: any[]); static get localizeNamespaces(): StringToFunctionMap[]; static get waitForLocalizeNamespaces(): boolean; diff --git a/packages/overlays/src/OverlayController.js b/packages/overlays/src/OverlayController.js index f09371879..4381f0b9f 100644 --- a/packages/overlays/src/OverlayController.js +++ b/packages/overlays/src/OverlayController.js @@ -507,7 +507,7 @@ export class OverlayController extends EventTargetShim { if (this.placementMode === 'local') { // Lazily load Popper if not done yet if (!OverlayController.popperModule) { - // @ts-expect-error + // @ts-expect-error FIXME: for some reason createPopper is missing here OverlayController.popperModule = preloadPopper(); } } @@ -838,8 +838,8 @@ export class OverlayController extends EventTargetShim { hideConfig.backdropNode.classList.remove( `${this.placementMode}-overlays__backdrop--animation-in`, ); - /** @type {(ev:AnimationEvent) => void} */ - let afterFadeOut; + /** @type {() => void} */ + let afterFadeOut = () => {}; hideConfig.backdropNode.classList.add( `${this.placementMode}-overlays__backdrop--animation-out`, ); @@ -857,7 +857,7 @@ export class OverlayController extends EventTargetShim { resolve(undefined); }; }); - // @ts-expect-error + hideConfig.backdropNode.addEventListener('animationend', afterFadeOut); } } diff --git a/packages/overlays/src/utils/deep-contains.js b/packages/overlays/src/utils/deep-contains.js index 0df64dc14..b87e5a35e 100644 --- a/packages/overlays/src/utils/deep-contains.js +++ b/packages/overlays/src/utils/deep-contains.js @@ -1,7 +1,7 @@ /** * Whether first element contains the second element, also goes through shadow roots * @param {HTMLElement|ShadowRoot} el - * @param {HTMLElement} targetEl + * @param {HTMLElement|ShadowRoot} targetEl * @returns {boolean} */ export function deepContains(el, targetEl) { diff --git a/packages/overlays/src/utils/is-equal-config.js b/packages/overlays/src/utils/is-equal-config.js index 7e0051ecf..dba2eeede 100644 --- a/packages/overlays/src/utils/is-equal-config.js +++ b/packages/overlays/src/utils/is-equal-config.js @@ -6,8 +6,8 @@ * Compares two OverlayConfigs to equivalence. Intended to prevent unnecessary resets. * Note that it doesn't cover as many use cases as common implementations, such as Lodash isEqual. * - * @param {OverlayConfig} a - * @param {OverlayConfig} b + * @param {Partial} a + * @param {Partial} b * @returns {boolean} Whether the configs are equivalent */ export function isEqualConfig(a, b) { diff --git a/packages/overlays/test/utils-tests/contain-focus.test.js b/packages/overlays/test/utils-tests/contain-focus.test.js index a45843acd..b7fcb3552 100644 --- a/packages/overlays/test/utils-tests/contain-focus.test.js +++ b/packages/overlays/test/utils-tests/contain-focus.test.js @@ -1,5 +1,4 @@ import { expect, fixture, html } from '@open-wc/testing'; -// @ts-expect-error import { renderLitAsNode } from '@lion/helpers'; import { getDeepActiveElement } from '../../src/utils/get-deep-active-element.js'; import { getFocusableElements } from '../../src/utils/get-focusable-elements.js'; @@ -72,9 +71,11 @@ function createShadowDomNode() { `); - const rootElementShadow = shadowDomNode.querySelector('#rootElementShadow'); - rootElementShadow.attachShadow({ mode: 'open' }); - rootElementShadow.shadowRoot.appendChild(interactionElementsNode); + const rootElementShadow = shadowDomNode?.querySelector('#rootElementShadow'); + rootElementShadow?.attachShadow({ mode: 'open' }); + if (interactionElementsNode) { + rootElementShadow?.shadowRoot?.appendChild(interactionElementsNode); + } return shadowDomNode; } diff --git a/packages/overlays/test/utils-tests/deep-contains.test.js b/packages/overlays/test/utils-tests/deep-contains.test.js index fa743a885..e5cc9425e 100644 --- a/packages/overlays/test/utils-tests/deep-contains.test.js +++ b/packages/overlays/test/utils-tests/deep-contains.test.js @@ -30,7 +30,12 @@ describe('deepContains()', () => { expect(deepContains(shadowRoot, shadowElementChild)).to.be.true; // Siblings - expect(deepContains(element.firstElementChild, element.lastElementChild)).to.be.false; + expect( + deepContains( + /** @type {HTMLElement} */ (element.firstElementChild), + /** @type {HTMLElement} */ (element.lastElementChild), + ), + ).to.be.false; // Unrelated expect(deepContains(lightChildEl, shadowElementChild)).to.be.false; }); @@ -95,16 +100,19 @@ describe('deepContains()', () => { `)); - expect(deepContains(element, element.firstElementChild)).to.be.true; - expect(deepContains(element, element.firstElementChild.shadowRoot)).to.be.true; - expect(deepContains(element, element.firstElementChild.shadowRoot.children[1])).to.be.true; - expect(deepContains(element, element.firstElementChild.shadowRoot.children[1].shadowRoot)).to.be - .true; - expect( - deepContains( - element, - element.firstElementChild.shadowRoot.children[1].shadowRoot.lastElementChild, - ), - ).to.be.true; + const elementFirstChild = /** @type {HTMLElement} */ (element.firstElementChild); + const elementFirstChildShadow = /** @type {ShadowRoot} */ (elementFirstChild.shadowRoot); + const elementFirstChildShadowChildren = /** @type {HTMLElement[]} */ (Array.from( + elementFirstChildShadow.children, + )); + const elementFirstChildShadowChildShadow = /** @type {ShadowRoot} */ (elementFirstChildShadowChildren[1] + .shadowRoot); + const elementFirstChildShadowChildShadowLastChild = /** @type {HTMLElement} */ (elementFirstChildShadowChildShadow.lastElementChild); + + expect(deepContains(element, elementFirstChild)).to.be.true; + expect(deepContains(element, elementFirstChildShadow)).to.be.true; + expect(deepContains(element, elementFirstChildShadowChildren[1])).to.be.true; + expect(deepContains(element, elementFirstChildShadowChildShadow)).to.be.true; + expect(deepContains(element, elementFirstChildShadowChildShadowLastChild)).to.be.true; }); }); diff --git a/packages/overlays/test/utils-tests/is-equal-config.test.js b/packages/overlays/test/utils-tests/is-equal-config.test.js index d6e1b78f1..d13a77431 100644 --- a/packages/overlays/test/utils-tests/is-equal-config.test.js +++ b/packages/overlays/test/utils-tests/is-equal-config.test.js @@ -3,14 +3,15 @@ import { isEqualConfig } from '../../src/utils/is-equal-config.js'; function TestConfig() { return { - placementMode: 'local', + placementMode: /** @type {'local'|'global'} */ ('local'), hidesOnOutsideClick: true, popperConfig: { - modifiers: { - offset: { + modifiers: [ + { + name: 'offset', enabled: false, }, - }, + ], }, }; } @@ -31,13 +32,13 @@ describe('isEqualConfig()', () => { it('compares prop count', () => { const config = TestConfig(); - expect(isEqualConfig(config, { ...config, extra: 'value' })).eql(false); - expect(isEqualConfig({ ...config, extra: 'value' }, config)).eql(false); + expect(isEqualConfig(config, { ...config, isBlocking: true })).eql(false); + expect(isEqualConfig({ ...config, isBlocking: true }, config)).eql(false); }); it('regards missing props different from ones with undefined value', () => { const config = TestConfig(); - expect(isEqualConfig(config, { ...config, extra: undefined })).eql(false); + expect(isEqualConfig(config, { ...config, referenceNode: undefined })).eql(false); }); it('compares nested props', () => { @@ -46,12 +47,7 @@ describe('isEqualConfig()', () => { ...config, popperConfig: { ...config.popperConfig, - modifiers: { - ...config.popperConfig.modifiers, - offset: { - ...config.popperConfig.modifiers.offset, - }, - }, + modifiers: [...config.popperConfig.modifiers], }, }; expect(isEqualConfig(config, sameConfig)).eql(true); @@ -59,12 +55,13 @@ describe('isEqualConfig()', () => { ...config, popperConfig: { ...config.popperConfig, - modifiers: { + modifiers: [ ...config.popperConfig.modifiers, - offset: { - enabled: !config.popperConfig.modifiers.offset.enabled, + { + name: 'offset', + enabled: !config.popperConfig.modifiers.find(mod => mod.name === 'offset')?.enabled, }, - }, + ], }, }; expect(isEqualConfig(config, differentConfig)).eql(false); diff --git a/packages/overlays/types/ArrowMixinTypes.d.ts b/packages/overlays/types/ArrowMixinTypes.d.ts index 672d886bc..20a3d8101 100644 --- a/packages/overlays/types/ArrowMixinTypes.d.ts +++ b/packages/overlays/types/ArrowMixinTypes.d.ts @@ -5,6 +5,7 @@ import { Options as PopperOptions, State } from '@popperjs/core/lib/popper'; import { OverlayConfig } from '../types/OverlayConfig'; export declare class ArrowHost { + constructor(...args: any[]); static get properties(): { hasArrow: { type: BooleanConstructor; diff --git a/packages/overlays/types/OverlayMixinTypes.d.ts b/packages/overlays/types/OverlayMixinTypes.d.ts index ed7c344fe..875cd468d 100644 --- a/packages/overlays/types/OverlayMixinTypes.d.ts +++ b/packages/overlays/types/OverlayMixinTypes.d.ts @@ -17,6 +17,7 @@ export interface DefineOverlayConfig { } export declare class OverlayHost { + constructor(...args: any[]); public opened: Boolean; public get config(): OverlayConfig; @@ -66,6 +67,6 @@ export declare class OverlayHost { export declare function OverlayImplementation>( superclass: T, -): T & Constructor & OverlayHost; +): T & Constructor & typeof OverlayHost; export type OverlayMixin = typeof OverlayImplementation; diff --git a/packages/pagination/src/LionPagination.js b/packages/pagination/src/LionPagination.js index 835644c2f..12061ddb6 100644 --- a/packages/pagination/src/LionPagination.js +++ b/packages/pagination/src/LionPagination.js @@ -10,7 +10,6 @@ import { LocalizeMixin } from '@lion/localize'; * * @customElement lion-pagination */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionPagination extends LocalizeMixin(LitElement) { static get styles() { return [ diff --git a/packages/progress-indicator/src/LionProgressIndicator.js b/packages/progress-indicator/src/LionProgressIndicator.js index 701bf1ef9..0d5702c43 100644 --- a/packages/progress-indicator/src/LionProgressIndicator.js +++ b/packages/progress-indicator/src/LionProgressIndicator.js @@ -3,7 +3,6 @@ import { nothing, LitElement } from '@lion/core'; import { localize, LocalizeMixin } from '@lion/localize'; -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionProgressIndicator extends LocalizeMixin(LitElement) { static get localizeNamespaces() { return [ diff --git a/packages/radio-group/src/LionRadioGroup.js b/packages/radio-group/src/LionRadioGroup.js index 6b77f83a3..029710aa0 100644 --- a/packages/radio-group/src/LionRadioGroup.js +++ b/packages/radio-group/src/LionRadioGroup.js @@ -4,7 +4,6 @@ import { ChoiceGroupMixin, FormGroupMixin } from '@lion/form-core'; /** * A wrapper around multiple radios. */ -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionRadioGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) { connectedCallback() { super.connectedCallback(); diff --git a/packages/select-rich/src/LionSelectRich.js b/packages/select-rich/src/LionSelectRich.js index b5bd8a403..d07babdae 100644 --- a/packages/select-rich/src/LionSelectRich.js +++ b/packages/select-rich/src/LionSelectRich.js @@ -23,7 +23,7 @@ function detectInteractionMode() { /** * LionSelectRich: wraps the element */ -// @ts-expect-error +// @ts-expect-error false positive for incompatible static get properties. Lit-element merges super properties already for you. export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(LionListbox))) { static get scopedElements() { return { @@ -88,7 +88,6 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L * @configure ListboxMixin * @protected */ - // @ts-ignore get _scrollTargetNode() { // TODO: should this be defined here or in extension layer? // @ts-expect-error we allow the _overlayContentNode to define its own _scrollTargetNode diff --git a/packages/select-rich/test/lion-select-rich.test.js b/packages/select-rich/test/lion-select-rich.test.js index fdd76fc4f..35f58cb67 100644 --- a/packages/select-rich/test/lion-select-rich.test.js +++ b/packages/select-rich/test/lion-select-rich.test.js @@ -1,5 +1,4 @@ import { LitElement } from '@lion/core'; -// @ts-expect-error import { renderLitAsNode } from '@lion/helpers'; import { OverlayController } from '@lion/overlays'; import { LionOption } from '@lion/listbox'; @@ -10,7 +9,7 @@ import { html, nextFrame, unsafeStatic, - fixture, + fixture as _fixture, } from '@open-wc/testing'; import { LionSelectInvoker, LionSelectRich } from '../index.js'; @@ -19,6 +18,12 @@ import '@lion/listbox/lion-option.js'; import '@lion/listbox/lion-options.js'; import '../lion-select-rich.js'; +/** + * @typedef {import('@lion/core').TemplateResult} TemplateResult + */ + +const fixture = /** @type {(arg: TemplateResult) => Promise} */ (_fixture); + /** * @param {LionSelectRich} lionSelectEl */ @@ -26,10 +31,16 @@ function getProtectedMembers(lionSelectEl) { // @ts-ignore protected members allowed in test const { _invokerNode: invoker, + // @ts-ignore _feedbackNode: feedback, + // @ts-ignore _labelNode: label, + // @ts-ignore _helpTextNode: helpText, + // @ts-ignore _listboxNode: listbox, + // @ts-ignore + _overlayCtrl: overlay, } = lionSelectEl; return { invoker, @@ -37,53 +48,53 @@ function getProtectedMembers(lionSelectEl) { label, helpText, listbox, + overlay, }; } describe('lion-select-rich', () => { it('clicking the label should focus the invoker', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); expect(document.activeElement === document.body).to.be.true; - el._labelNode.click(); + const { label } = getProtectedMembers(el); + label.click(); // @ts-ignore allow protected access in tests expect(document.activeElement === el._invokerNode).to.be.true; }); it('checks the first enabled option', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` - `)); + `); expect(el.activeIndex).to.equal(0); expect(el.checkedIndex).to.equal(0); }); it('still has a checked value while disabled', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Red Hotpink Blue - `)); + `); expect(el.modelValue).to.equal('Red'); }); it('supports having no default selection initially', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Red Hotpink Teal - `)); + `); const { invoker } = getProtectedMembers(el); expect(invoker.selectedElement).to.be.undefined; expect(el.modelValue).to.equal(''); @@ -91,9 +102,7 @@ describe('lion-select-rich', () => { describe('Invoker', () => { it('generates an lion-select-invoker if no invoker is provided', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // @ts-ignore allow protected access in tests expect(el._invokerNode).to.exist; @@ -102,24 +111,24 @@ describe('lion-select-rich', () => { }); it('sets the first option as the selectedElement if no option is checked', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); const options = el.formElements; // @ts-ignore allow protected access in tests expect(el._invokerNode.selectedElement).dom.to.equal(options[0]); }); it('syncs the selected element to the invoker', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); const options = el.querySelectorAll('lion-option'); // @ts-ignore allow protected access in tests expect(el._invokerNode.selectedElement).dom.to.equal(options[1]); @@ -131,12 +140,12 @@ describe('lion-select-rich', () => { }); it('delegates readonly to the invoker', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); expect(el.hasAttribute('readonly')).to.be.true; // @ts-ignore allow protected access in tests @@ -144,11 +153,11 @@ describe('lion-select-rich', () => { }); it('delegates singleOption to the invoker', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 - `)); + `); expect(el.singleOption).to.be.true; // @ts-ignore allow protected access in tests @@ -169,16 +178,16 @@ describe('lion-select-rich', () => { ); const tagString = unsafeStatic(tag); - const firstOption = renderLitAsNode( + const firstOption = /** @type {LionOption} */ (renderLitAsNode( html`<${tagString} checked .choiceValue=${10}>`, - ); + )); - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` ${firstOption} <${tagString} .choiceValue=${20}> - `)); + `); // @ts-ignore allow protected access in tests expect(el._invokerNode.shadowRoot.firstElementChild.textContent).to.equal('10'); @@ -191,16 +200,17 @@ describe('lion-select-rich', () => { }); it('inherits the content width including arrow width', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 with long label - `)); + `); el.opened = true; const options = el.formElements; await el.updateComplete; - expect(el._invokerNode.clientWidth).to.equal(options[1].clientWidth); + const { invoker } = getProtectedMembers(el); + expect(invoker.clientWidth).to.equal(options[1].clientWidth); const newOption = /** @type {LionOption} */ (document.createElement('lion-option')); newOption.choiceValue = 30; @@ -208,26 +218,22 @@ describe('lion-select-rich', () => { el._inputNode.appendChild(newOption); await el.updateComplete; - expect(el._invokerNode.clientWidth).to.equal(options[2].clientWidth); + expect(invoker.clientWidth).to.equal(options[2].clientWidth); el._inputNode.removeChild(newOption); await el.updateComplete; - expect(el._invokerNode.clientWidth).to.equal(options[1].clientWidth); + expect(invoker.clientWidth).to.equal(options[1].clientWidth); }); }); describe('overlay', () => { it('should be closed by default', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); expect(el.opened).to.be.false; }); it('shows/hides the listbox via opened attribute', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); el.opened = true; await el.updateComplete; // @ts-ignore allow protected access in tests @@ -241,10 +247,8 @@ describe('lion-select-rich', () => { }); it('syncs opened state with overlay shown', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); - const outerEl = /** @type {HTMLButtonElement} */ (await fixture( + const el = await fixture(html` `); + const outerEl = /** @type {HTMLButtonElement} */ (await _fixture( '', )); @@ -257,9 +261,7 @@ describe('lion-select-rich', () => { }); it('will focus the listbox on open and invoker on close', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // @ts-ignore allow protected access in tests await el._overlayCtrl.show(); await el.updateComplete; @@ -278,12 +280,12 @@ describe('lion-select-rich', () => { }); it('opens the listbox with checked option as active', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); // @ts-ignore allow protected access in tests await el._overlayCtrl.show(); await el.updateComplete; @@ -294,25 +296,25 @@ describe('lion-select-rich', () => { }); it('stays closed on click if it is disabled or readonly or has a single option', async () => { - const elReadOnly = /** @type {LionSelectRich} */ (await fixture(html` + const elReadOnly = await fixture(html` Item 1 Item 2 - `)); + `); - const elDisabled = /** @type {LionSelectRich} */ (await fixture(html` + const elDisabled = await fixture(html` Item 1 Item 2 - `)); + `); - const elSingleoption = /** @type {LionSelectRich} */ (await fixture(html` + const elSingleoption = await fixture(html` Item 1 - `)); + `); // @ts-ignore allow protected access in tests elReadOnly._invokerNode.click(); @@ -331,13 +333,13 @@ describe('lion-select-rich', () => { }); it('sets inheritsReferenceWidth to min by default', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Red Hotpink Teal - `)); + `); // @ts-ignore allow protected access in tests expect(el._overlayCtrl.inheritsReferenceWidth).to.equal('min'); @@ -349,26 +351,28 @@ describe('lion-select-rich', () => { }); it('should override the inheritsWidth prop when no default selected feature is used', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Red Hotpink Teal - `)); + `); + + const { overlay } = getProtectedMembers(el); // The default is min, so we override that behavior here // @ts-ignore allow protected access in tests - el._overlayCtrl.updateConfig({ inheritsReferenceWidth: 'full' }); + overlay.updateConfig({ inheritsReferenceWidth: 'full' }); el._initialInheritsReferenceWidth = 'full'; // @ts-ignore allow protected access in tests - expect(el._overlayCtrl.inheritsReferenceWidth).to.equal('full'); + expect(overlay.inheritsReferenceWidth).to.equal('full'); el.opened = true; await el.updateComplete; // Opens while hasNoDefaultSelected = true, so we expect an override // @ts-ignore allow protected access in tests - expect(el._overlayCtrl.inheritsReferenceWidth).to.equal('min'); + expect(overlay.inheritsReferenceWidth).to.equal('min'); // Emulate selecting hotpink, it closing, and opening it again el.modelValue = 'hotpink'; @@ -378,7 +382,7 @@ describe('lion-select-rich', () => { el.opened = true; await el.updateComplete; await el.updateComplete; // safari takes a little longer - await el._overlayCtrl._showComplete; + await overlay._showComplete; // noDefaultSelected will now flip the override back to what was the initial reference width // @ts-ignore allow protected access in tests @@ -386,12 +390,12 @@ describe('lion-select-rich', () => { }); it('should have singleOption only if there is exactly one option', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); expect(el.singleOption).to.be.false; // @ts-ignore allow protected access in tests expect(el._invokerNode.singleOption).to.be.false; @@ -418,18 +422,16 @@ describe('lion-select-rich', () => { describe('interaction-mode', () => { it('allows to specify an interaction-mode which determines other behaviors', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` - `)); + `); expect(el.interactionMode).to.equal('mac'); }); }); describe('Keyboard navigation', () => { it('opens the listbox with [Enter] key via click handler', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // @ts-ignore allow protected access in tests el._invokerNode.click(); await aTimeout(0); @@ -437,9 +439,7 @@ describe('lion-select-rich', () => { }); it('opens the listbox with [ ](Space) key via click handler', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // @ts-ignore allow protected access in tests el._invokerNode.click(); await aTimeout(0); @@ -447,18 +447,14 @@ describe('lion-select-rich', () => { }); it('closes the listbox with [Escape] key once opened', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // @ts-ignore allow protected access in tests el._listboxNode.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); expect(el.opened).to.be.false; }); it('closes the listbox with [Tab] key once opened', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // tab can only be caught via keydown // @ts-ignore allow protected access in tests el._listboxNode.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' })); @@ -468,9 +464,7 @@ describe('lion-select-rich', () => { describe('Mouse navigation', () => { it('opens the listbox via click on invoker', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); expect(el.opened).to.be.false; // @ts-ignore allow protected access in tests el._invokerNode.click(); @@ -479,11 +473,11 @@ describe('lion-select-rich', () => { }); it('closes the listbox when an option gets clicked', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 - `)); + `); expect(el.opened).to.be.true; el.formElements[0].click(); expect(el.opened).to.be.false; @@ -492,9 +486,7 @@ describe('lion-select-rich', () => { describe('Keyboard navigation Windows', () => { it('closes the listbox with [Enter] key once opened', async () => { - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); // @ts-ignore allow protected access in tests el._listboxNode.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' })); expect(el.opened).to.be.false; @@ -503,12 +495,12 @@ describe('lion-select-rich', () => { describe('Keyboard navigation Mac', () => { it('checks active item and closes the listbox with [Enter] key via click handler once opened', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); // changes active but not checked el.activeIndex = 1; @@ -520,18 +512,18 @@ describe('lion-select-rich', () => { }); it('opens the listbox with [ArrowUp] key', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` - `)); + `); el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowUp' })); await el.updateComplete; expect(el.opened).to.be.true; }); it('opens the listbox with [ArrowDown] key', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` - `)); + `); el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown' })); await el.updateComplete; expect(el.opened).to.be.true; @@ -540,12 +532,12 @@ describe('lion-select-rich', () => { describe('Accessibility', () => { it('has the right references to its inner elements', async () => { - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` Item 1 Item 2 - `)); + `); const { invoker, feedback, label, helpText } = getProtectedMembers(el); expect(invoker.getAttribute('aria-labelledby')).to.contain(label.id); @@ -557,9 +549,7 @@ describe('lion-select-rich', () => { it('notifies when the listbox is expanded or not', async () => { // smoke test for overlay functionality - const el = /** @type {LionSelectRich} */ (await fixture( - html` `, - )); + const el = await fixture(html` `); const { invoker } = getProtectedMembers(el); expect(invoker.getAttribute('aria-expanded')).to.equal('false'); @@ -619,9 +609,9 @@ describe('lion-select-rich', () => { }, ); const mySelectContainerTag = unsafeStatic(mySelectContainerTagString); - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` <${mySelectContainerTag}> - `)); + `); const selectRich = /** @type {LionSelectRich} */ ( /** @type {ShadowRoot} */ (el.shadowRoot).querySelector('lion-select-rich') @@ -667,7 +657,7 @@ describe('lion-select-rich', () => { const mySelectTag = unsafeStatic(mySelectTagString); - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` <${mySelectTag} label="Favorite color" name="color"> ${Array(2).map( @@ -677,7 +667,7 @@ describe('lion-select-rich', () => { )} - `)); + `); await el.updateComplete; // @ts-ignore allow protected member access in tests expect(el._overlayCtrl.placementMode).to.equal('global'); @@ -708,7 +698,7 @@ describe('lion-select-rich', () => { ); const selectTag = unsafeStatic(selectTagName); - const el = /** @type {LionSelectRich} */ (await fixture(html` + const el = await fixture(html` <${selectTag} id="color" name="color" label="Favorite color" has-no-default-selected> Red @@ -716,7 +706,7 @@ describe('lion-select-rich', () => { Teal - `)); + `); const { invoker } = getProtectedMembers(el); expect( diff --git a/packages/switch/src/LionSwitch.js b/packages/switch/src/LionSwitch.js index ccbbb305a..ce44ce644 100644 --- a/packages/switch/src/LionSwitch.js +++ b/packages/switch/src/LionSwitch.js @@ -2,7 +2,6 @@ import { css, html, ScopedElementsMixin } from '@lion/core'; import { ChoiceInputMixin, LionField } from '@lion/form-core'; import { LionSwitchButton } from './LionSwitchButton.js'; -// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionSwitch extends ScopedElementsMixin(ChoiceInputMixin(LionField)) { static get styles() { return [ diff --git a/tsconfig.json b/tsconfig.json index 4819d0f7a..e97b85874 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,10 +22,6 @@ "**/dist/**/*", "packages/**/test-helpers", "packages/**/docs/**/*", - "packages/combobox/test/**/*.js", // TODO: Needs to get typed! - "packages/form-integrations/test/**/*.js", // TODO: Needs to get typed! - "packages/overlays/test/utils-tests/**/*.js", // TODO: Needs to get typed! - "packages/select-rich/test/**/*.js", // TODO: Needs to get typed! "packages/singleton-manager/demo/", "packages/singleton-manager/test/", // ignore test/demos for singleton manager until overlays are typed as it's used in there diff --git a/yarn.lock b/yarn.lock index d10a1578a..d2c11a724 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1834,10 +1834,10 @@ "@open-wc/rollup-plugin-html" "^1.2.5" polyfills-loader "^1.7.5" -"@open-wc/scoped-elements@^1.2.4", "@open-wc/scoped-elements@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@open-wc/scoped-elements/-/scoped-elements-1.3.2.tgz#6ae54c49731bbe8c3e0b5383c989f983dcdfacf5" - integrity sha512-DoP3XA8r03tGx+IrlJwP/voLuDFkyS56kvwhmXIhpESo7M5jMt5e0zScNrawj7EMe4b5gDaJjorx2Jza8FLaLw== +"@open-wc/scoped-elements@^1.2.4", "@open-wc/scoped-elements@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@open-wc/scoped-elements/-/scoped-elements-1.3.3.tgz#fe008aef4d74fb00c553c900602960638fc1c7b0" + integrity sha512-vFIQVYYjFw67odUE4JzZOpctnF7S/2DX+S+clrL3bQPql7HvEnV0wMFwOWUavQTuCJi0rfU8GTcNMiUybio+Yg== dependencies: "@open-wc/dedupe-mixin" "^1.3.0" lit-html "^1.0.0"