@lion/ui 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/accordion/src/LionAccordion.js +3 -2
- package/components/button/src/LionButton.js +6 -10
- package/components/button/src/LionButtonReset.js +2 -0
- package/components/button/src/LionButtonSubmit.js +2 -0
- package/components/button/test-suites/LionButton.suite.js +0 -14
- package/components/checkbox-group/src/LionCheckbox.js +3 -0
- package/components/checkbox-group/src/LionCheckboxGroup.js +2 -0
- package/components/checkbox-group/src/LionCheckboxIndeterminate.js +3 -0
- package/components/collapsible/src/LionCollapsible.js +4 -1
- package/components/combobox/src/LionCombobox.js +31 -8
- package/components/combobox/test/lion-combobox.test.js +206 -57
- package/components/dialog/src/LionDialog.js +3 -0
- package/components/drawer/src/LionDrawer.js +9 -0
- package/components/fieldset/src/LionFieldset.js +1 -1
- package/components/form/src/LionForm.js +0 -1
- package/components/form-core/src/FocusMixin.js +1 -0
- package/components/form-core/src/FormControlMixin.js +33 -18
- package/components/form-core/src/FormatMixin.js +1 -1
- package/components/form-core/src/validate/LionValidationFeedback.js +8 -10
- package/components/form-core/src/validate/ValidateMixin.js +40 -4
- package/components/form-core/test/FormControlMixin.test.js +68 -0
- package/components/form-core/test/validate/lion-validation-feedback.test.js +0 -22
- package/components/form-core/test-suites/ValidateMixin.suite.js +19 -3
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +119 -0
- package/components/form-core/types/validate/validate.ts +1 -0
- package/components/icon/src/LionIcon.js +2 -0
- package/components/input-file/src/LionInputFile.js +9 -0
- package/components/input-tel/src/LionInputTel.js +3 -0
- package/components/input-tel-dropdown/src/LionInputTelDropdown.js +2 -0
- package/components/listbox/src/LionListbox.js +2 -0
- package/components/overlays/src/OverlayController.js +32 -5
- package/components/overlays/src/OverlayMixin.js +5 -0
- package/components/overlays/src/configurations/withDropdownConfig.js +0 -1
- package/components/overlays/src/configurations/withTooltipConfig.js +0 -1
- package/components/overlays/test/OverlayController.test.js +16 -4
- package/components/overlays/test-suites/OverlayMixin.suite.js +71 -0
- package/components/progress-indicator/src/LionProgressIndicator.js +4 -0
- package/components/radio-group/src/LionRadioGroup.js +3 -1
- package/components/select/src/LionSelect.js +4 -0
- package/components/select-rich/src/LionSelectInvoker.js +2 -0
- package/components/select-rich/src/LionSelectRich.js +2 -0
- package/components/steps/src/LionStep.js +0 -1
- package/components/steps/src/LionSteps.js +0 -1
- package/components/switch/src/LionSwitch.js +3 -0
- package/components/switch/src/LionSwitchButton.js +5 -0
- package/components/tabs/src/LionTabs.js +8 -0
- package/custom-elements.json +1271 -406
- package/dist-types/components/accordion/src/LionAccordion.d.ts +3 -2
- package/dist-types/components/accordion/src/LionAccordion.d.ts.map +1 -1
- package/dist-types/components/button/src/LionButton.d.ts +2 -1
- package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
- package/dist-types/components/button/src/LionButtonReset.d.ts +2 -0
- package/dist-types/components/button/src/LionButtonReset.d.ts.map +1 -1
- package/dist-types/components/button/src/LionButtonSubmit.d.ts +2 -0
- package/dist-types/components/button/src/LionButtonSubmit.d.ts.map +1 -1
- package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
- package/dist-types/components/checkbox-group/src/LionCheckbox.d.ts +3 -0
- package/dist-types/components/checkbox-group/src/LionCheckbox.d.ts.map +1 -1
- package/dist-types/components/checkbox-group/src/LionCheckboxGroup.d.ts +2 -0
- package/dist-types/components/checkbox-group/src/LionCheckboxGroup.d.ts.map +1 -1
- package/dist-types/components/checkbox-group/src/LionCheckboxIndeterminate.d.ts +3 -0
- package/dist-types/components/checkbox-group/src/LionCheckboxIndeterminate.d.ts.map +1 -1
- package/dist-types/components/collapsible/src/LionCollapsible.d.ts +3 -1
- package/dist-types/components/collapsible/src/LionCollapsible.d.ts.map +1 -1
- package/dist-types/components/combobox/src/LionCombobox.d.ts +5 -0
- package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
- package/dist-types/components/core/src/ScopedElementsMixin.d.ts.map +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +3 -0
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/drawer/src/LionDrawer.d.ts +9 -0
- package/dist-types/components/drawer/src/LionDrawer.d.ts.map +1 -1
- package/dist-types/components/fieldset/src/LionFieldset.d.ts +1 -1
- package/dist-types/components/form/src/LionForm.d.ts.map +1 -1
- package/dist-types/components/form-core/src/FocusMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/FormControlMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/validate/LionValidationFeedback.d.ts +4 -3
- package/dist-types/components/form-core/src/validate/LionValidationFeedback.d.ts.map +1 -1
- package/dist-types/components/form-core/src/validate/ValidateMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/types/validate/validate.d.ts +1 -0
- package/dist-types/components/form-core/types/validate/validate.d.ts.map +1 -1
- package/dist-types/components/icon/src/LionIcon.d.ts +2 -0
- package/dist-types/components/icon/src/LionIcon.d.ts.map +1 -1
- package/dist-types/components/input-file/src/LionInputFile.d.ts +9 -0
- package/dist-types/components/input-file/src/LionInputFile.d.ts.map +1 -1
- package/dist-types/components/input-tel/src/LionInputTel.d.ts +3 -0
- package/dist-types/components/input-tel/src/LionInputTel.d.ts.map +1 -1
- package/dist-types/components/input-tel-dropdown/src/LionInputTelDropdown.d.ts +2 -0
- package/dist-types/components/input-tel-dropdown/src/LionInputTelDropdown.d.ts.map +1 -1
- package/dist-types/components/listbox/src/LionListbox.d.ts +2 -0
- package/dist-types/components/listbox/src/LionListbox.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts +4 -0
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/configurations/withDropdownConfig.d.ts.map +1 -1
- package/dist-types/components/overlays/src/configurations/withTooltipConfig.d.ts.map +1 -1
- package/dist-types/components/overlays/test/OverlayController.test.d.ts.map +1 -1
- package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
- package/dist-types/components/progress-indicator/src/LionProgressIndicator.d.ts +3 -0
- package/dist-types/components/progress-indicator/src/LionProgressIndicator.d.ts.map +1 -1
- package/dist-types/components/radio-group/src/LionRadioGroup.d.ts +3 -1
- package/dist-types/components/radio-group/src/LionRadioGroup.d.ts.map +1 -1
- package/dist-types/components/select/src/LionSelect.d.ts +3 -0
- package/dist-types/components/select/src/LionSelect.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts +2 -0
- package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +3 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/steps/src/LionStep.d.ts +0 -1
- package/dist-types/components/steps/src/LionStep.d.ts.map +1 -1
- package/dist-types/components/steps/src/LionSteps.d.ts +0 -1
- package/dist-types/components/steps/src/LionSteps.d.ts.map +1 -1
- package/dist-types/components/switch/src/LionSwitch.d.ts +3 -0
- package/dist-types/components/switch/src/LionSwitch.d.ts.map +1 -1
- package/dist-types/components/switch/src/LionSwitchButton.d.ts +5 -0
- package/dist-types/components/switch/src/LionSwitchButton.d.ts.map +1 -1
- package/dist-types/components/tabs/src/LionTabs.d.ts +8 -0
- package/dist-types/components/tabs/src/LionTabs.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/accordion/api-table.md +8 -0
- package/docs/components/button/api-table.md +0 -3
- package/docs/components/checkbox-group/api-table.md +6 -6
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/api-table.md +7 -0
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/api-table.md +9 -2
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +90 -1
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/drawer/api-table.md +8 -0
- package/docs/components/fieldset/api-table.md +2 -2
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/form/use-cases.md +2 -2
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/api-table.md +2 -2
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/api-table.md +2 -2
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-date/api-table.md +2 -2
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/api-table.md +2 -2
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/api-table.md +2 -2
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-file/api-table.md +9 -2
- package/docs/components/input-file/overview.md +1 -1
- package/docs/components/input-iban/api-table.md +2 -2
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/api-table.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/api-table.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-tel/api-table.md +2 -2
- package/docs/components/input-tel/overview.md +1 -1
- package/docs/components/input-tel/use-cases.md +6 -6
- package/docs/components/input-tel-dropdown/api-table.md +2 -2
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/listbox/api-table.md +2 -2
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/radio-group/api-table.md +4 -4
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/api-table.md +2 -2
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/api-table.md +2 -3
- package/docs/components/select-rich/use-cases.md +1 -1
- package/docs/components/switch/api-table.md +2 -2
- package/docs/components/tabs/api-table.md +7 -0
- package/docs/components/tabs/examples.md +1 -1
- package/docs/components/textarea/api-table.md +2 -2
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/api-table.md +2 -2
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/styling.md +3 -20
- package/docs/fundamentals/systems/form/validate.md +19 -3
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/create-a-form.md +4 -4
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/package.json +3 -3
|
@@ -24,6 +24,16 @@ import { FormRegisteringMixin } from './registration/FormRegisteringMixin.js';
|
|
|
24
24
|
* This Mixin is a shared fundament for all form components, it's applied on:
|
|
25
25
|
* - LionField (which is extended to LionInput, LionTextarea, LionSelect etc. etc.)
|
|
26
26
|
* - LionFieldset (which is extended to LionRadioGroup, LionCheckboxGroup, LionForm)
|
|
27
|
+
*
|
|
28
|
+
* @slot label - The label for the form control
|
|
29
|
+
* @slot help-text - The help text for the form control
|
|
30
|
+
* @slot input - The input element for the form control, e.g. <input>, <textarea>, <select>
|
|
31
|
+
* @slot feedback - The validation feedback for the form control
|
|
32
|
+
* @slot prefix - The prefix for the form control, e.g. currency symbol
|
|
33
|
+
* @slot suffix - The suffix for the form control, e.g. currency symbol
|
|
34
|
+
* @slot before - The before element for the form control, e.g. a label
|
|
35
|
+
* @slot after - The after element for the form control, e.g. a label
|
|
36
|
+
*
|
|
27
37
|
* @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
|
|
28
38
|
* @type {FormControlMixin}
|
|
29
39
|
*/
|
|
@@ -52,7 +62,7 @@ const FormControlMixinImplementation = superclass =>
|
|
|
52
62
|
* @type {string}
|
|
53
63
|
*/
|
|
54
64
|
get label() {
|
|
55
|
-
return this.__label
|
|
65
|
+
return this.__label ?? (this._labelNode?.textContent || '');
|
|
56
66
|
}
|
|
57
67
|
|
|
58
68
|
/**
|
|
@@ -71,7 +81,7 @@ const FormControlMixinImplementation = superclass =>
|
|
|
71
81
|
* @type {string}
|
|
72
82
|
*/
|
|
73
83
|
get helpText() {
|
|
74
|
-
return this.__helpText
|
|
84
|
+
return this.__helpText ?? (this._helpTextNode?.textContent || '');
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
/**
|
|
@@ -158,6 +168,21 @@ const FormControlMixinImplementation = superclass =>
|
|
|
158
168
|
*/
|
|
159
169
|
static enabledWarnings = super.enabledWarnings?.filter(w => w !== 'change-in-update') || [];
|
|
160
170
|
|
|
171
|
+
// N.B. add these label/helpText props for types + ce manifest output
|
|
172
|
+
// (explicity setting them to undefined does not have desired result)
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* The label text for the input node.
|
|
176
|
+
* When no value is defined, textContent of [slot=label] will be used
|
|
177
|
+
* @property {string} label
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The helpt text for the input node.
|
|
182
|
+
* When no value is defined, textContent of [slot=help-text] will be used
|
|
183
|
+
* @property {string} helpText
|
|
184
|
+
*/
|
|
185
|
+
|
|
161
186
|
constructor() {
|
|
162
187
|
super();
|
|
163
188
|
|
|
@@ -171,26 +196,12 @@ const FormControlMixinImplementation = superclass =>
|
|
|
171
196
|
*/
|
|
172
197
|
this.readOnly = false;
|
|
173
198
|
|
|
174
|
-
/**
|
|
175
|
-
* The label text for the input node.
|
|
176
|
-
* When no value is defined, textContent of [slot=label] will be used
|
|
177
|
-
* @type {string}
|
|
178
|
-
*/
|
|
179
|
-
this.label = '';
|
|
180
|
-
|
|
181
199
|
/**
|
|
182
200
|
* The label will only be visible for srceen readers when true
|
|
183
201
|
* @type {boolean}
|
|
184
202
|
*/
|
|
185
203
|
this.labelSrOnly = false;
|
|
186
204
|
|
|
187
|
-
/**
|
|
188
|
-
* The helpt text for the input node.
|
|
189
|
-
* When no value is defined, textContent of [slot=help-text] will be used
|
|
190
|
-
* @type {string}
|
|
191
|
-
*/
|
|
192
|
-
this.helpText = '';
|
|
193
|
-
|
|
194
205
|
/**
|
|
195
206
|
* The model value is the result of the parser function(when available).
|
|
196
207
|
* It should be considered as the internal value used for validation and reasoning/logic.
|
|
@@ -293,11 +304,15 @@ const FormControlMixinImplementation = superclass =>
|
|
|
293
304
|
);
|
|
294
305
|
}
|
|
295
306
|
|
|
296
|
-
if (changedProperties.has('label') && this.__label && this._labelNode) {
|
|
307
|
+
if (changedProperties.has('label') && this.__label !== undefined && this._labelNode) {
|
|
297
308
|
this._labelNode.textContent = this.label;
|
|
298
309
|
}
|
|
299
310
|
|
|
300
|
-
if (
|
|
311
|
+
if (
|
|
312
|
+
changedProperties.has('helpText') &&
|
|
313
|
+
this.__helpText !== undefined &&
|
|
314
|
+
this._helpTextNode
|
|
315
|
+
) {
|
|
301
316
|
this._helpTextNode.textContent = this.helpText;
|
|
302
317
|
}
|
|
303
318
|
|
|
@@ -25,7 +25,7 @@ import { Unparseable } from './validate/Unparseable.js';
|
|
|
25
25
|
// formattedValue condition needs to be evaluated right before syncing back to the view
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Designed to be applied on top of a LionField.
|
|
29
29
|
* To understand all concepts within the Mixin, please consult the flow diagram in the
|
|
30
30
|
* documentation.
|
|
31
31
|
*
|
|
@@ -48,6 +48,14 @@ export class LionValidationFeedback extends LocalizeMixin(LitElement) {
|
|
|
48
48
|
];
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
constructor() {
|
|
52
|
+
super();
|
|
53
|
+
/**
|
|
54
|
+
* @type {FeedbackMessage[] | undefined}
|
|
55
|
+
*/
|
|
56
|
+
this.feedbackData = undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
/**
|
|
52
60
|
* @overridable
|
|
53
61
|
* @param {Object} opts
|
|
@@ -69,16 +77,6 @@ export class LionValidationFeedback extends LocalizeMixin(LitElement) {
|
|
|
69
77
|
if (this.feedbackData && this.feedbackData[0]) {
|
|
70
78
|
this.setAttribute('type', this.feedbackData[0].type);
|
|
71
79
|
this.currentType = this.feedbackData[0].type;
|
|
72
|
-
window.clearTimeout(this.removeMessage);
|
|
73
|
-
// TODO: this logic should be in ValidateMixin, so that [show-feedback-for] is in sync,
|
|
74
|
-
// plus duration should be configurable
|
|
75
|
-
if (this.currentType === 'success') {
|
|
76
|
-
this.removeMessage = window.setTimeout(() => {
|
|
77
|
-
this.removeAttribute('type');
|
|
78
|
-
/** @type {FeedbackMessage[]} */
|
|
79
|
-
this.feedbackData = [];
|
|
80
|
-
}, 3000);
|
|
81
|
-
}
|
|
82
80
|
} else if (this.currentType !== 'success') {
|
|
83
81
|
this.removeAttribute('type');
|
|
84
82
|
}
|
|
@@ -420,6 +420,22 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
420
420
|
await this.__executeValidators();
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
/**
|
|
424
|
+
* @param {Validator} validator
|
|
425
|
+
* @returns {boolean}
|
|
426
|
+
*/
|
|
427
|
+
#isInstanceOfRequiredValidator(validator) {
|
|
428
|
+
// walk prototype and check if validatorName is 'Required'
|
|
429
|
+
let validatorLvlInPrototype = validator;
|
|
430
|
+
while (validatorLvlInPrototype) {
|
|
431
|
+
const ctor = /** @type {typeof Validator} */ (validatorLvlInPrototype.constructor);
|
|
432
|
+
if (ctor.validatorName === 'Required') return true;
|
|
433
|
+
|
|
434
|
+
validatorLvlInPrototype = Object.getPrototypeOf(validatorLvlInPrototype);
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
|
|
423
439
|
/**
|
|
424
440
|
* @desc step a1-3 + b (as explained in `validate()`)
|
|
425
441
|
*/
|
|
@@ -482,7 +498,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
482
498
|
for (const v of this._allValidators) {
|
|
483
499
|
if (/** @type {MetaValidator} */ (v)?.executeOnResults) {
|
|
484
500
|
metaValidators.push(/** @type {MetaValidator} */ (v));
|
|
485
|
-
} else if (
|
|
501
|
+
} else if (this.#isInstanceOfRequiredValidator(v)) {
|
|
486
502
|
// Required validator was already handled
|
|
487
503
|
} else if (/** @type {typeof Validator} */ (v.constructor).async) {
|
|
488
504
|
asyncValidators.push(v);
|
|
@@ -574,7 +590,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
574
590
|
return [];
|
|
575
591
|
}
|
|
576
592
|
|
|
577
|
-
// If empty, do not show the
|
|
593
|
+
// If empty, do not show the ResultValidation message (e.g. Correct!)
|
|
578
594
|
if (this._isEmpty(this.modelValue)) {
|
|
579
595
|
this.__prevShownValidationResult = [];
|
|
580
596
|
return [];
|
|
@@ -603,7 +619,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
603
619
|
* - on sync validation
|
|
604
620
|
* - on async validation (can depend on server response)
|
|
605
621
|
*
|
|
606
|
-
* This method
|
|
622
|
+
* This method finishes a pass by adding the properties to the instance:
|
|
607
623
|
* - validationStates
|
|
608
624
|
* - hasFeedbackFor
|
|
609
625
|
*
|
|
@@ -747,6 +763,7 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
747
763
|
* @property {string} type will be 'error' for messages from default Validators. Could be
|
|
748
764
|
* 'warning', 'info' etc. for Validators with custom types. Needed as a directive for
|
|
749
765
|
* feedbackNode how to render a message of a certain type
|
|
766
|
+
* @property {number} visibilityDuration duration in ms for how long the message should be shown
|
|
750
767
|
* @property {Validator} [validator] when the message is directly coupled to a Validator
|
|
751
768
|
* (in most cases), this property is filled. When a message is not coupled to a Validator
|
|
752
769
|
* (in case of success feedback which is based on a diff or current and previous validation
|
|
@@ -772,7 +789,12 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
772
789
|
fieldName,
|
|
773
790
|
outcome,
|
|
774
791
|
});
|
|
775
|
-
return {
|
|
792
|
+
return {
|
|
793
|
+
message,
|
|
794
|
+
type: validator.type,
|
|
795
|
+
validator,
|
|
796
|
+
visibilityDuration: validator.config?.visibilityDuration || 3000,
|
|
797
|
+
};
|
|
776
798
|
}),
|
|
777
799
|
);
|
|
778
800
|
}
|
|
@@ -793,6 +815,8 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
793
815
|
* @protected
|
|
794
816
|
*/
|
|
795
817
|
_updateFeedbackComponent() {
|
|
818
|
+
window.clearTimeout(this.removeMessage);
|
|
819
|
+
|
|
796
820
|
const { _feedbackNode } = this;
|
|
797
821
|
if (!_feedbackNode) {
|
|
798
822
|
return;
|
|
@@ -824,6 +848,18 @@ export const ValidateMixinImplementation = superclass =>
|
|
|
824
848
|
|
|
825
849
|
const messageMap = await this.__getFeedbackMessages(this.__prioritizedResult);
|
|
826
850
|
_feedbackNode.feedbackData = messageMap || [];
|
|
851
|
+
|
|
852
|
+
if (
|
|
853
|
+
messageMap?.[0] &&
|
|
854
|
+
messageMap[0].type === 'success' &&
|
|
855
|
+
messageMap[0].visibilityDuration !== Infinity
|
|
856
|
+
) {
|
|
857
|
+
this.removeMessage = window.setTimeout(() => {
|
|
858
|
+
_feedbackNode.removeAttribute('type');
|
|
859
|
+
/** @type {FeedbackMessage[]} */
|
|
860
|
+
_feedbackNode.feedbackData = [];
|
|
861
|
+
}, messageMap[0].visibilityDuration);
|
|
862
|
+
}
|
|
827
863
|
});
|
|
828
864
|
} else {
|
|
829
865
|
this.__feedbackQueue.add(async () => {
|
|
@@ -86,6 +86,40 @@ describe('FormControlMixin', () => {
|
|
|
86
86
|
expect(el.label).to.equal('');
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
+
it('supports empty string as label', async () => {
|
|
90
|
+
const el = /** @type {FormControlMixinClass} */ (
|
|
91
|
+
await fixture(html`
|
|
92
|
+
<${tag} label="With Value">${inputSlot}</${tag}>
|
|
93
|
+
`)
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(el.label).to.equal('With Value');
|
|
97
|
+
// @ts-expect-error
|
|
98
|
+
expect(el._labelNode.innerHTML).to.equal('With Value');
|
|
99
|
+
|
|
100
|
+
el.label = '';
|
|
101
|
+
await el.updateComplete;
|
|
102
|
+
|
|
103
|
+
expect(el.label).to.equal('');
|
|
104
|
+
// @ts-expect-error
|
|
105
|
+
expect(el._labelNode.innerHTML).to.equal('');
|
|
106
|
+
|
|
107
|
+
// Reset
|
|
108
|
+
el.label = 'With Value';
|
|
109
|
+
await el.updateComplete;
|
|
110
|
+
|
|
111
|
+
expect(el.label).to.equal('With Value');
|
|
112
|
+
// @ts-expect-error
|
|
113
|
+
expect(el._labelNode.innerHTML).to.equal('With Value');
|
|
114
|
+
|
|
115
|
+
el.setAttribute('label', '');
|
|
116
|
+
await el.updateComplete;
|
|
117
|
+
|
|
118
|
+
expect(el.label).to.equal('');
|
|
119
|
+
// @ts-expect-error
|
|
120
|
+
expect(el._labelNode.innerHTML).to.equal('');
|
|
121
|
+
});
|
|
122
|
+
|
|
89
123
|
/**
|
|
90
124
|
* N.B. For platform controls, the same would be achieved with <input aria-label="My label">
|
|
91
125
|
* However, since FormControl is usually not the activeElement (_inputNode is), this
|
|
@@ -176,6 +210,40 @@ describe('FormControlMixin', () => {
|
|
|
176
210
|
);
|
|
177
211
|
expect(el.helpText).to.equal('');
|
|
178
212
|
});
|
|
213
|
+
|
|
214
|
+
it('supports empty string as help-text', async () => {
|
|
215
|
+
const el = /** @type {FormControlMixinClass} */ (
|
|
216
|
+
await fixture(html`
|
|
217
|
+
<${tag} help-text="With Value">${inputSlot}</${tag}>
|
|
218
|
+
`)
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
expect(el.helpText).to.equal('With Value');
|
|
222
|
+
// @ts-expect-error
|
|
223
|
+
expect(el._helpTextNode.innerHTML).to.equal('With Value');
|
|
224
|
+
|
|
225
|
+
el.helpText = '';
|
|
226
|
+
await el.updateComplete;
|
|
227
|
+
|
|
228
|
+
expect(el.helpText).to.equal('');
|
|
229
|
+
// @ts-expect-error
|
|
230
|
+
expect(el._helpTextNode.innerHTML).to.equal('');
|
|
231
|
+
|
|
232
|
+
// Reset
|
|
233
|
+
el.helpText = 'With Value';
|
|
234
|
+
await el.updateComplete;
|
|
235
|
+
|
|
236
|
+
expect(el.helpText).to.equal('With Value');
|
|
237
|
+
// @ts-expect-error
|
|
238
|
+
expect(el._helpTextNode.innerHTML).to.equal('With Value');
|
|
239
|
+
|
|
240
|
+
el.setAttribute('help-text', '');
|
|
241
|
+
await el.updateComplete;
|
|
242
|
+
|
|
243
|
+
expect(el.helpText).to.equal('');
|
|
244
|
+
// @ts-expect-error
|
|
245
|
+
expect(el._helpTextNode.innerHTML).to.equal('');
|
|
246
|
+
});
|
|
179
247
|
});
|
|
180
248
|
|
|
181
249
|
describe('Accessibility', () => {
|
|
@@ -33,28 +33,6 @@ describe('lion-validation-feedback', () => {
|
|
|
33
33
|
expect(el.getAttribute('type')).to.equal('warning');
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it('success message clears after 3s', async () => {
|
|
37
|
-
const el = /** @type {LionValidationFeedback} */ (
|
|
38
|
-
await fixture(html`<lion-validation-feedback></lion-validation-feedback>`)
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const clock = sinon.useFakeTimers();
|
|
42
|
-
|
|
43
|
-
el.feedbackData = [{ message: 'hello', type: 'success', validator: new AlwaysValid() }];
|
|
44
|
-
await el.updateComplete;
|
|
45
|
-
expect(el.getAttribute('type')).to.equal('success');
|
|
46
|
-
|
|
47
|
-
clock.tick(2900);
|
|
48
|
-
|
|
49
|
-
expect(el.getAttribute('type')).to.equal('success');
|
|
50
|
-
|
|
51
|
-
clock.tick(200);
|
|
52
|
-
|
|
53
|
-
expect(el).to.not.have.attribute('type');
|
|
54
|
-
|
|
55
|
-
clock.restore();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
36
|
it('does not clear error messages', async () => {
|
|
59
37
|
const el = /** @type {LionValidationFeedback} */ (
|
|
60
38
|
await fixture(html`<lion-validation-feedback></lion-validation-feedback>`)
|
|
@@ -130,6 +130,7 @@ export function runValidateMixinSuite(customConfig) {
|
|
|
130
130
|
expect(el.hasFeedbackFor).to.deep.equal(['error']);
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
// TODO: keep this use case for backwards compatibility or just required extending Required?
|
|
133
134
|
it('determines whether the "Required" validator was already handled by judging the validatorName', async () => {
|
|
134
135
|
class BundledValidator extends EventTarget {
|
|
135
136
|
static ['_$isValidator$'] = true;
|
|
@@ -163,9 +164,7 @@ export function runValidateMixinSuite(customConfig) {
|
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
class BundledRequired extends BundledValidator {
|
|
166
|
-
static
|
|
167
|
-
return 'Required';
|
|
168
|
-
}
|
|
167
|
+
static validatorName = 'Required';
|
|
169
168
|
}
|
|
170
169
|
|
|
171
170
|
const el = /** @type {ValidateElement} */ (
|
|
@@ -180,6 +179,23 @@ export function runValidateMixinSuite(customConfig) {
|
|
|
180
179
|
expect(el.hasFeedbackFor).to.deep.equal([]);
|
|
181
180
|
});
|
|
182
181
|
|
|
182
|
+
it('determines whether the "Required" validator was already handled by judging the validatorName', async () => {
|
|
183
|
+
class MyRequired extends Required {
|
|
184
|
+
static validatorName = 'SomethingOtherThanRequired';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const el = /** @type {ValidateElement} */ (
|
|
188
|
+
await fixture(html`
|
|
189
|
+
<${tag}
|
|
190
|
+
.validators=${[new MyRequired()]}
|
|
191
|
+
.modelValue=${'myValue'}
|
|
192
|
+
>${lightDom}</${tag}>
|
|
193
|
+
`)
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
expect(el.hasFeedbackFor).to.deep.equal([]);
|
|
197
|
+
});
|
|
198
|
+
|
|
183
199
|
it('determines whether the passed Validators are ResultValidators judging by the presence of "executeOnResults"', async () => {
|
|
184
200
|
class ValidateElementWithSuccessType extends ValidateElement {
|
|
185
201
|
static get validationTypes() {
|
|
@@ -349,6 +349,125 @@ export function runValidateMixinFeedbackPart() {
|
|
|
349
349
|
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Nachricht für MinLength');
|
|
350
350
|
});
|
|
351
351
|
|
|
352
|
+
it('shows success message and clears after 3s', async () => {
|
|
353
|
+
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
354
|
+
static get validationTypes() {
|
|
355
|
+
return ['error', 'success'];
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const clock = sinon.useFakeTimers();
|
|
359
|
+
const elTagString = defineCE(ValidateElementCustomTypes);
|
|
360
|
+
const elTag = unsafeStatic(elTagString);
|
|
361
|
+
const el = /** @type {ValidateElementCustomTypes} */ (
|
|
362
|
+
await fixture(html`
|
|
363
|
+
<${elTag}
|
|
364
|
+
.submitted=${true}
|
|
365
|
+
.validators=${[
|
|
366
|
+
new MinLength(3),
|
|
367
|
+
new DefaultSuccess(null, { getMessage: () => 'This is a success message' }),
|
|
368
|
+
]}
|
|
369
|
+
>${lightDom}</${elTag}>
|
|
370
|
+
`)
|
|
371
|
+
);
|
|
372
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
373
|
+
|
|
374
|
+
el.modelValue = 'a';
|
|
375
|
+
await el.updateComplete;
|
|
376
|
+
await el.feedbackComplete;
|
|
377
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Message for MinLength');
|
|
378
|
+
|
|
379
|
+
el.modelValue = 'abcd';
|
|
380
|
+
await el.updateComplete;
|
|
381
|
+
await el.feedbackComplete;
|
|
382
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
383
|
+
clock.tick(2900);
|
|
384
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
385
|
+
clock.tick(200);
|
|
386
|
+
expect(_feedbackNode.feedbackData).to.be.empty;
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('shows success message and clears after configured time', async () => {
|
|
390
|
+
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
391
|
+
static get validationTypes() {
|
|
392
|
+
return ['error', 'success'];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
const clock = sinon.useFakeTimers();
|
|
396
|
+
const elTagString = defineCE(ValidateElementCustomTypes);
|
|
397
|
+
const elTag = unsafeStatic(elTagString);
|
|
398
|
+
const el = /** @type {ValidateElementCustomTypes} */ (
|
|
399
|
+
await fixture(html`
|
|
400
|
+
<${elTag}
|
|
401
|
+
.submitted=${true}
|
|
402
|
+
.validators=${[
|
|
403
|
+
new MinLength(3),
|
|
404
|
+
new DefaultSuccess(null, {
|
|
405
|
+
getMessage: () => 'This is a success message',
|
|
406
|
+
visibilityDuration: 6000,
|
|
407
|
+
}),
|
|
408
|
+
]}
|
|
409
|
+
>${lightDom}</${elTag}>
|
|
410
|
+
`)
|
|
411
|
+
);
|
|
412
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
413
|
+
|
|
414
|
+
el.modelValue = 'a';
|
|
415
|
+
await el.updateComplete;
|
|
416
|
+
await el.feedbackComplete;
|
|
417
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Message for MinLength');
|
|
418
|
+
|
|
419
|
+
el.modelValue = 'abcd';
|
|
420
|
+
await el.updateComplete;
|
|
421
|
+
await el.feedbackComplete;
|
|
422
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
423
|
+
clock.tick(5900);
|
|
424
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
425
|
+
clock.tick(200);
|
|
426
|
+
expect(_feedbackNode.feedbackData).to.be.empty;
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('shows success message and stays persistent', async () => {
|
|
430
|
+
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
431
|
+
static get validationTypes() {
|
|
432
|
+
return ['error', 'success'];
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const clock = sinon.useFakeTimers();
|
|
436
|
+
const elTagString = defineCE(ValidateElementCustomTypes);
|
|
437
|
+
const elTag = unsafeStatic(elTagString);
|
|
438
|
+
const el = /** @type {ValidateElementCustomTypes} */ (
|
|
439
|
+
await fixture(html`
|
|
440
|
+
<${elTag}
|
|
441
|
+
.submitted=${true}
|
|
442
|
+
.validators=${[
|
|
443
|
+
new MinLength(3),
|
|
444
|
+
new DefaultSuccess(null, {
|
|
445
|
+
getMessage: () => 'This is a success message',
|
|
446
|
+
visibilityDuration: Infinity,
|
|
447
|
+
}),
|
|
448
|
+
]}
|
|
449
|
+
>${lightDom}</${elTag}>
|
|
450
|
+
`)
|
|
451
|
+
);
|
|
452
|
+
const { _feedbackNode } = getFormControlMembers(el);
|
|
453
|
+
|
|
454
|
+
el.modelValue = 'a';
|
|
455
|
+
await el.updateComplete;
|
|
456
|
+
await el.feedbackComplete;
|
|
457
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Message for MinLength');
|
|
458
|
+
|
|
459
|
+
el.modelValue = 'abcd';
|
|
460
|
+
await el.updateComplete;
|
|
461
|
+
await el.feedbackComplete;
|
|
462
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
463
|
+
clock.tick(2900);
|
|
464
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
465
|
+
clock.tick(200);
|
|
466
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
467
|
+
clock.tick(20000);
|
|
468
|
+
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
|
469
|
+
});
|
|
470
|
+
|
|
352
471
|
it('shows success message after fixing an error', async () => {
|
|
353
472
|
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
|
354
473
|
static get validationTypes() {
|
|
@@ -31,6 +31,15 @@ function formatBytes(bytes, decimals = 2) {
|
|
|
31
31
|
return `${parseFloat((bytes / k ** i).toFixed(dm))}${sizes[i]}`;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* LionInputFile: A file input component
|
|
36
|
+
* This component allows users to select files, displays selected files, and handles file uploads.
|
|
37
|
+
*
|
|
38
|
+
* @slot file-select-button - [private] The button to open the file dialog
|
|
39
|
+
* @slot selected-file-list - [private] The list of selected files
|
|
40
|
+
*
|
|
41
|
+
* @customElement lion-input-file
|
|
42
|
+
*/
|
|
34
43
|
export class LionInputFile extends ScopedElementsMixin(LocalizeMixin(LionField)) {
|
|
35
44
|
static get scopedElements() {
|
|
36
45
|
return {
|
|
@@ -18,6 +18,9 @@ import { localizeNamespaceLoader } from './localizeNamespaceLoader.js';
|
|
|
18
18
|
* @typedef {FormatOptions & {regionCode: RegionCode; formatStrategy: PhoneNumberFormat; formatCountryCodeStyle: string;}} FormatOptionsTel
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @customElement lion-input-tel
|
|
23
|
+
*/
|
|
21
24
|
export class LionInputTel extends LocalizeMixin(LionInput) {
|
|
22
25
|
/**
|
|
23
26
|
* @configure LitElement
|
|
@@ -40,6 +40,8 @@ import { regionCodeToLocale } from './regionCodeToLocale.js';
|
|
|
40
40
|
* possible. Also, it doesn't need to be a `FormControl`, because it's purely a helper element
|
|
41
41
|
* to provide better UX: the modelValue (the text field) contains all needed info, since it's in
|
|
42
42
|
* `e164` format that contains all info (both region code and national phone number).
|
|
43
|
+
*
|
|
44
|
+
* @customElement lion-input-tel-dropdown
|
|
43
45
|
*/
|
|
44
46
|
export class LionInputTelDropdown extends LionInputTel {
|
|
45
47
|
refs = {
|
|
@@ -7,6 +7,8 @@ import { ListboxMixin } from './ListboxMixin.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* LionListbox: implements the wai-aria listbox design pattern and integrates it as a Lion
|
|
9
9
|
* FormControl
|
|
10
|
+
*
|
|
11
|
+
* @customElement lion-listbox
|
|
10
12
|
*/
|
|
11
13
|
export class LionListbox extends ListboxMixin(
|
|
12
14
|
FocusMixin(InteractionStateMixin(ValidateMixin(LitElement))),
|
|
@@ -528,8 +528,6 @@ export class OverlayController extends EventTarget {
|
|
|
528
528
|
this.__contentHasBeenInitialized = true;
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
-
this.__wrappingDialogNode?.addEventListener('cancel', this.__cancelHandler);
|
|
532
|
-
|
|
533
531
|
// Reset all positioning styles (local, c.q. Popper) and classes (global)
|
|
534
532
|
this.contentWrapperNode.removeAttribute('style');
|
|
535
533
|
this.contentWrapperNode.removeAttribute('class');
|
|
@@ -618,8 +616,9 @@ export class OverlayController extends EventTarget {
|
|
|
618
616
|
contentWrapperNodeL2: this.contentWrapperNode,
|
|
619
617
|
contentNodeL3: this.contentNode,
|
|
620
618
|
});
|
|
621
|
-
// @ts-
|
|
619
|
+
// @ts-expect-error
|
|
622
620
|
wrappingDialogElement.open = true;
|
|
621
|
+
|
|
623
622
|
if (this.isTooltip) {
|
|
624
623
|
// needed to prevent tooltip getting focus in Safari and Firefox
|
|
625
624
|
wrappingDialogElement.setAttribute('tabindex', '-1');
|
|
@@ -633,6 +632,35 @@ export class OverlayController extends EventTarget {
|
|
|
633
632
|
// computed height of 0...
|
|
634
633
|
this.contentNode.style.position = 'static';
|
|
635
634
|
}
|
|
635
|
+
|
|
636
|
+
// Here we prevent any interference of the native <dialog> element with the keyboard behavior
|
|
637
|
+
// as defined by the OverlayController. This is needed until we can configure `closedby="none"`
|
|
638
|
+
// on the native dialog for all browsers: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby
|
|
639
|
+
const hasClosedBySupport = HTMLDialogElement && 'closedBy' in HTMLDialogElement.prototype;
|
|
640
|
+
if (hasClosedBySupport) {
|
|
641
|
+
// @ts-expect-error
|
|
642
|
+
wrappingDialogElement.closedBy = 'none';
|
|
643
|
+
} else {
|
|
644
|
+
wrappingDialogElement.addEventListener(
|
|
645
|
+
'keydown',
|
|
646
|
+
(/** @type {* & KeyboardEvent} */ event) => {
|
|
647
|
+
if (event.key === 'Escape') {
|
|
648
|
+
event.preventDefault();
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
);
|
|
652
|
+
wrappingDialogElement.addEventListener('keyup', (/** @type {* & KeyboardEvent} */ event) => {
|
|
653
|
+
if (event.key === 'Escape') {
|
|
654
|
+
event.preventDefault();
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
wrappingDialogElement.addEventListener('cancel', event => {
|
|
658
|
+
event.stopPropagation();
|
|
659
|
+
});
|
|
660
|
+
wrappingDialogElement.addEventListener('close', event => {
|
|
661
|
+
event.stopPropagation();
|
|
662
|
+
});
|
|
663
|
+
}
|
|
636
664
|
}
|
|
637
665
|
|
|
638
666
|
/**
|
|
@@ -1188,6 +1216,7 @@ export class OverlayController extends EventTarget {
|
|
|
1188
1216
|
const hasPressedInside =
|
|
1189
1217
|
event.composedPath().includes(this.contentNode) ||
|
|
1190
1218
|
deepContains(this.contentNode, /** @type {HTMLElement|ShadowRoot} */ (event.target));
|
|
1219
|
+
|
|
1191
1220
|
if (hasPressedInside) {
|
|
1192
1221
|
this.hide();
|
|
1193
1222
|
// We could do event.stopPropagation() here, but we don't want to hide info for
|
|
@@ -1384,8 +1413,6 @@ export class OverlayController extends EventTarget {
|
|
|
1384
1413
|
teardown() {
|
|
1385
1414
|
this.__handleOverlayStyles({ phase: 'teardown' });
|
|
1386
1415
|
this._handleFeatures({ phase: 'teardown' });
|
|
1387
|
-
this.__wrappingDialogNode?.removeEventListener('cancel', this.__cancelHandler);
|
|
1388
|
-
|
|
1389
1416
|
if (this.#isRegisteredOnManager()) {
|
|
1390
1417
|
this.manager.remove(this);
|
|
1391
1418
|
}
|
|
@@ -9,6 +9,10 @@ import { isEqualConfig } from './utils/is-equal-config.js';
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
+
* @slot backdrop - The backdrop element for the overlay
|
|
13
|
+
* @slot content - The content element for the overlay
|
|
14
|
+
* @slot invoker - The invoker element for the overlay
|
|
15
|
+
*
|
|
12
16
|
* @type {OverlayMixin}
|
|
13
17
|
* @param {import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>} superclass
|
|
14
18
|
*/
|
|
@@ -179,6 +183,7 @@ export const OverlayMixinImplementation = superclass =>
|
|
|
179
183
|
super.connectedCallback();
|
|
180
184
|
|
|
181
185
|
this.updateComplete.then(() => {
|
|
186
|
+
if (!this.isConnected) return;
|
|
182
187
|
if (this.#hasSetup) return;
|
|
183
188
|
this._setupOverlayCtrl();
|
|
184
189
|
this.#hasSetup = true;
|