@lion/ui 0.17.0-menu-system.0 → 0.17.0
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/collapsible.js +0 -1
- package/components/button/src/LionButton.js +0 -4
- package/components/button/test-suites/LionButton.suite.js +0 -1
- package/components/calendar/src/LionCalendar.js +0 -2
- package/components/combobox/test/lion-combobox.test.js +0 -1
- package/components/form-core/src/form-group/FormGroupMixin.js +0 -7
- package/components/form-core/src/registration/FormRegistrarMixin.js +0 -11
- package/components/form-core/test/FormControlMixin.test.js +0 -1
- package/components/form-core/test/validate/Validator.test.js +0 -2
- package/components/form-core/test-suites/ValidateMixin.suite.js +0 -2
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +0 -1
- package/components/input-datepicker/src/localizeNamespaceLoader.js +0 -1
- package/components/input-datepicker/test/lion-input-datepicker.test.js +6 -5
- package/components/localize/test/date/formatDate.test.js +0 -1
- package/components/overlays/src/OverlayController.js +76 -160
- package/components/overlays/src/OverlayMixin.js +11 -57
- package/components/overlays/src/OverlaysManager.js +2 -2
- package/components/overlays/src/utils/adopt-styles.js +1 -2
- package/components/overlays/src/utils/get-focusable-elements.js +0 -4
- package/components/overlays/src/utils/is-equal-config.js +1 -4
- package/components/overlays/test/OverlayController.test.js +2 -2
- package/components/overlays/types/OverlayConfig.ts +5 -10
- package/components/select-rich/test/lion-select-rich.test.js +0 -3
- package/custom-elements.json +19168 -31113
- package/dist-types/components/button/src/LionButton.d.ts +0 -1
- package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
- package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
- package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +1 -2
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/registration/FormRegistrarMixin.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/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayController.d.ts +6 -6
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/get-focusable-elements.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayConfig.d.ts +2 -5
- package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +2 -7
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/exports/overlays.d.ts +0 -2
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/api-table.md +8 -21
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/api-table.md +6 -31
- package/docs/components/dialog/overview.md +1 -1
- 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/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/api-table.md +4 -21
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-file/overview.md +1 -1
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- 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/overview.md +1 -1
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/api-table.md +5 -21
- package/docs/components/select-rich/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/components/tooltip/api-table.md +11 -36
- 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/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/validate.md +2 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/api-table.md +34 -34
- 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/how-to/index.md +1 -1
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/exports/collapsible.js +0 -1
- package/exports/overlays.js +0 -2
- package/overlays.js +0 -2
- package/package.json +1 -1
- package/components/collapsible/src/DisclosureMixin.js +0 -313
- package/components/collapsible/types/DisclosureMixinTypes.ts +0 -48
- package/components/menu/CHANGELOG.md +0 -37
- package/components/menu/README.md +0 -335
- package/components/menu/index.js +0 -2
- package/components/menu/lion-menu-overlay.js +0 -3
- package/components/menu/lion-menu.js +0 -3
- package/components/menu/lion-spinbutton.js +0 -3
- package/components/menu/lion-toolbar.js +0 -3
- package/components/menu/lion-tree.js +0 -3
- package/components/menu/package.json +0 -46
- package/components/menu/requirements.temp.md +0 -12
- package/components/menu/src/InteractiveListMixin.js +0 -796
- package/components/menu/src/LionMenu.js +0 -250
- package/components/menu/src/LionMenuHybrid.js +0 -46
- package/components/menu/src/LionMenuOverlay.js +0 -155
- package/components/menu/src/LionSpinbutton.js +0 -213
- package/components/menu/src/LionToolbar.js +0 -94
- package/components/menu/src/LionTree.js +0 -52
- package/components/menu/src/MultiLevelListMixin.js +0 -275
- package/components/menu/src/utils/isInView.js +0 -26
- package/components/menu/src/utils/listItemInteractions.js +0 -104
- package/components/menu/src/utils/uuid.js +0 -3
- package/components/menu/test/lion-menu.test.js +0 -3
- package/components/menu/test-suites/InteractiveListMixin.suite.js +0 -142
- package/components/menu/types/InteractiveListMixinTypes.d.ts +0 -82
- package/components/navigation-bar/README.md +0 -1
- package/components/navigation-bar/src/LionNavigationBar.js +0 -449
- package/components/navigation-bar/src/types.js +0 -41
- package/components/overlays/NEXT.md +0 -49
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +0 -3
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +0 -1
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +0 -24
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +0 -1
- package/dist-types/components/menu/index.d.ts +0 -3
- package/dist-types/components/menu/index.d.ts.map +0 -1
- package/dist-types/components/menu/lion-menu-overlay.d.ts +0 -2
- package/dist-types/components/menu/lion-menu-overlay.d.ts.map +0 -1
- package/dist-types/components/menu/lion-menu.d.ts +0 -2
- package/dist-types/components/menu/lion-menu.d.ts.map +0 -1
- package/dist-types/components/menu/lion-spinbutton.d.ts +0 -2
- package/dist-types/components/menu/lion-spinbutton.d.ts.map +0 -1
- package/dist-types/components/menu/lion-toolbar.d.ts +0 -2
- package/dist-types/components/menu/lion-toolbar.d.ts.map +0 -1
- package/dist-types/components/menu/lion-tree.d.ts +0 -2
- package/dist-types/components/menu/lion-tree.d.ts.map +0 -1
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts +0 -611
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +0 -1
- package/dist-types/components/menu/src/LionMenu.d.ts +0 -563
- package/dist-types/components/menu/src/LionMenu.d.ts.map +0 -1
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts +0 -19
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +0 -1
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts +0 -1006
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +0 -1
- package/dist-types/components/menu/src/LionSpinbutton.d.ts +0 -58
- package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +0 -1
- package/dist-types/components/menu/src/LionToolbar.d.ts +0 -8
- package/dist-types/components/menu/src/LionToolbar.d.ts.map +0 -1
- package/dist-types/components/menu/src/LionTree.d.ts +0 -445
- package/dist-types/components/menu/src/LionTree.d.ts.map +0 -1
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +0 -493
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +0 -1
- package/dist-types/components/menu/src/utils/isInView.d.ts +0 -9
- package/dist-types/components/menu/src/utils/isInView.d.ts.map +0 -1
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +0 -42
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +0 -1
- package/dist-types/components/menu/src/utils/uuid.d.ts +0 -2
- package/dist-types/components/menu/src/utils/uuid.d.ts.map +0 -1
- package/dist-types/components/menu/test/lion-menu.test.d.ts +0 -2
- package/dist-types/components/menu/test/lion-menu.test.d.ts.map +0 -1
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +0 -13
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +0 -1
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +0 -226
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +0 -1
- package/dist-types/components/navigation-bar/src/types.d.ts +0 -85
- package/dist-types/components/navigation-bar/src/types.d.ts.map +0 -1
- package/dist-types/exports/define/lion-item.d.ts +0 -2
- package/dist-types/exports/define/lion-item.d.ts.map +0 -1
- package/dist-types/exports/define/lion-menu-overlay.d.ts +0 -2
- package/dist-types/exports/define/lion-menu-overlay.d.ts.map +0 -1
- package/dist-types/exports/define/lion-menu.d.ts +0 -2
- package/dist-types/exports/define/lion-menu.d.ts.map +0 -1
- package/dist-types/exports/define/lion-navigation-bar.d.ts +0 -2
- package/dist-types/exports/define/lion-navigation-bar.d.ts.map +0 -1
- package/dist-types/exports/define/lion-toolbar.d.ts +0 -2
- package/dist-types/exports/define/lion-toolbar.d.ts.map +0 -1
- package/dist-types/exports/define/lion-tree.d.ts +0 -2
- package/dist-types/exports/define/lion-tree.d.ts.map +0 -1
- package/dist-types/exports/menu.d.ts +0 -7
- package/dist-types/exports/menu.d.ts.map +0 -1
- package/dist-types/exports/navigation-bar.d.ts +0 -2
- package/dist-types/exports/navigation-bar.d.ts.map +0 -1
- package/docs/components/menu/api-table.md +0 -450
- package/docs/components/menu/applyMenuDemoStyles.js +0 -173
- package/docs/components/menu/extensions.md +0 -216
- package/docs/components/menu/index.md +0 -13
- package/docs/components/menu/overview.md +0 -422
- package/exports/define/lion-item.js +0 -3
- package/exports/define/lion-menu-overlay.js +0 -3
- package/exports/define/lion-menu.js +0 -3
- package/exports/define/lion-navigation-bar.js +0 -3
- package/exports/define/lion-toolbar.js +0 -3
- package/exports/define/lion-tree.js +0 -3
- package/exports/menu.js +0 -6
- package/exports/navigation-bar.js +0 -1
- package/menu.js +0 -6
- package/navigation-bar.js +0 -1
package/collapsible.js
CHANGED
|
@@ -220,8 +220,4 @@ export class LionButton extends DisabledWithTabIndexMixin(LitElement) {
|
|
|
220
220
|
this.click();
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
|
-
|
|
224
|
-
// we want to be able to identify LionButtons w/o instanceof (for perf (loose dep) and dual version support),
|
|
225
|
-
// so we use a static property for that that doesn't get renamed by minifiers
|
|
226
|
-
static ['_$isLionButton$'] = true;
|
|
227
223
|
}
|
|
@@ -279,7 +279,6 @@ export function LionButtonSuite({ klass = LionButton } = {}) {
|
|
|
279
279
|
|
|
280
280
|
sameProperties.forEach(property => {
|
|
281
281
|
it(`has same value of the property "${property}" as in native button event`, () => {
|
|
282
|
-
// @ts-ignore - dynamic property access
|
|
283
282
|
expect(lionButtonEvent[property]).to.equal(nativeButtonEvent[property]);
|
|
284
283
|
});
|
|
285
284
|
});
|
|
@@ -928,7 +928,6 @@ export class LionCalendar extends LocalizeMixin(LitElement) {
|
|
|
928
928
|
if (type !== 'Date') {
|
|
929
929
|
tmpDate.setDate(1);
|
|
930
930
|
}
|
|
931
|
-
// @ts-ignore - dynamic method access
|
|
932
931
|
tmpDate[`set${type}`](tmpDate[`get${type}`]() + modify);
|
|
933
932
|
// if we've reset the day count,
|
|
934
933
|
// restore day count as best we can
|
|
@@ -936,7 +935,6 @@ export class LionCalendar extends LocalizeMixin(LitElement) {
|
|
|
936
935
|
const maxDays = new Date(tmpDate.getFullYear(), tmpDate.getMonth() + 1, 0).getDate();
|
|
937
936
|
tmpDate.setDate(Math.min(this.centralDate.getDate(), maxDays));
|
|
938
937
|
}
|
|
939
|
-
// @ts-ignore - dynamic property access
|
|
940
938
|
this[dateType] = tmpDate;
|
|
941
939
|
}
|
|
942
940
|
|
|
@@ -3227,7 +3227,6 @@ describe('lion-combobox', () => {
|
|
|
3227
3227
|
const [el, options] = await fruitFixture({ autocomplete: 'both', matchMode: 'all' });
|
|
3228
3228
|
await mimicUserTyping(/** @type {LionCombobox} */ (el), 'choke');
|
|
3229
3229
|
await el.updateComplete;
|
|
3230
|
-
// @ts-ignore - array index access
|
|
3231
3230
|
const labelledElement = options[0].querySelector('span[aria-label="Artichoke"]');
|
|
3232
3231
|
expect(labelledElement).to.not.be.null;
|
|
3233
3232
|
expect(labelledElement.innerText).to.equal('Artichoke');
|
|
@@ -352,14 +352,11 @@ const FormGroupMixinImplementation = superclass =>
|
|
|
352
352
|
this.formElements._keys().forEach(name => {
|
|
353
353
|
const elem = this.formElements[name];
|
|
354
354
|
if (elem instanceof FormControlsCollection) {
|
|
355
|
-
// @ts-ignore - dynamic property access
|
|
356
355
|
result[name] = elem.filter(el => _filterFn(el, property)).map(el => el[property]);
|
|
357
356
|
} else if (_filterFn(elem, property)) {
|
|
358
357
|
if (typeof elem._getFromAllFormElements === 'function') {
|
|
359
|
-
// @ts-ignore - dynamic property access
|
|
360
358
|
result[name] = elem._getFromAllFormElements(property);
|
|
361
359
|
} else {
|
|
362
|
-
// @ts-ignore - dynamic property access
|
|
363
360
|
result[name] = elem[property];
|
|
364
361
|
}
|
|
365
362
|
}
|
|
@@ -389,7 +386,6 @@ const FormGroupMixinImplementation = superclass =>
|
|
|
389
386
|
if (Array.isArray(this.formElements[name])) {
|
|
390
387
|
this.formElements[name].forEach(
|
|
391
388
|
(/** @type {FormControl} */ el, /** @type {number} */ index) => {
|
|
392
|
-
// @ts-ignore - dynamic property access
|
|
393
389
|
el[property] = values[name][index]; // eslint-disable-line no-param-reassign
|
|
394
390
|
},
|
|
395
391
|
);
|
|
@@ -397,7 +393,6 @@ const FormGroupMixinImplementation = superclass =>
|
|
|
397
393
|
if (this.formElements[name]) {
|
|
398
394
|
this.formElements[name][property] = values[name];
|
|
399
395
|
} else {
|
|
400
|
-
// @ts-ignore - dynamic property access
|
|
401
396
|
this.__pendingValues[property][name] = values[name];
|
|
402
397
|
}
|
|
403
398
|
});
|
|
@@ -411,7 +406,6 @@ const FormGroupMixinImplementation = superclass =>
|
|
|
411
406
|
_anyFormElementHas(property) {
|
|
412
407
|
return Object.keys(this.formElements).some(name => {
|
|
413
408
|
if (Array.isArray(this.formElements[name])) {
|
|
414
|
-
// @ts-ignore - dynamic property access
|
|
415
409
|
return this.formElements[name].some((/** @type {FormControl} */ el) => !!el[property]);
|
|
416
410
|
}
|
|
417
411
|
return !!this.formElements[name][property];
|
|
@@ -442,7 +436,6 @@ const FormGroupMixinImplementation = superclass =>
|
|
|
442
436
|
_everyFormElementHas(property) {
|
|
443
437
|
return Object.keys(this.formElements).every(name => {
|
|
444
438
|
if (Array.isArray(this.formElements[name])) {
|
|
445
|
-
// @ts-ignore - dynamic property access
|
|
446
439
|
return this.formElements[name].every((/** @type {FormControl} */ el) => !!el[property]);
|
|
447
440
|
}
|
|
448
441
|
return !!this.formElements[name][property];
|
|
@@ -162,21 +162,15 @@ const FormRegistrarMixinImplementation = superclass =>
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
if (name.substr(-2) === '[]') {
|
|
165
|
-
// @ts-ignore - dynamic named access to form elements
|
|
166
165
|
if (!Array.isArray(this.formElements[name])) {
|
|
167
|
-
// @ts-ignore
|
|
168
166
|
this.formElements[name] = new FormControlsCollection();
|
|
169
167
|
}
|
|
170
168
|
if (indexToInsertAt > 0) {
|
|
171
|
-
// @ts-ignore
|
|
172
169
|
this.formElements[name].splice(indexToInsertAt, 0, child);
|
|
173
170
|
} else {
|
|
174
|
-
// @ts-ignore
|
|
175
171
|
this.formElements[name].push(child);
|
|
176
172
|
}
|
|
177
|
-
// @ts-ignore
|
|
178
173
|
} else if (!this.formElements[name]) {
|
|
179
|
-
// @ts-ignore
|
|
180
174
|
this.formElements[name] = child;
|
|
181
175
|
} else {
|
|
182
176
|
console.info('Error Node:', child); // eslint-disable-line no-console
|
|
@@ -200,17 +194,12 @@ const FormRegistrarMixinImplementation = superclass =>
|
|
|
200
194
|
// 2. Handle name based object keys
|
|
201
195
|
if (this._isFormOrFieldset) {
|
|
202
196
|
const { name } = child; // FIXME: <-- ElementWithParentFormGroup should become LionFieldWithParentFormGroup so that "name" exists
|
|
203
|
-
// @ts-ignore - dynamic named access to form elements
|
|
204
197
|
if (name.substr(-2) === '[]' && this.formElements[name]) {
|
|
205
|
-
// @ts-ignore
|
|
206
198
|
const idx = this.formElements[name].indexOf(child);
|
|
207
199
|
if (idx > -1) {
|
|
208
|
-
// @ts-ignore
|
|
209
200
|
this.formElements[name].splice(idx, 1);
|
|
210
201
|
}
|
|
211
|
-
// @ts-ignore
|
|
212
202
|
} else if (this.formElements[name]) {
|
|
213
|
-
// @ts-ignore
|
|
214
203
|
delete this.formElements[name];
|
|
215
204
|
}
|
|
216
205
|
}
|
|
@@ -153,7 +153,6 @@ describe('FormControlMixin', () => {
|
|
|
153
153
|
el.shadowRoot?.querySelector('.form-field__label'),
|
|
154
154
|
);
|
|
155
155
|
Object.entries(expectedValues).forEach(([key, val]) => {
|
|
156
|
-
// @ts-ignore - dynamic style property access
|
|
157
156
|
expect(labelStyle[key]).to.equal(val);
|
|
158
157
|
});
|
|
159
158
|
});
|
|
@@ -191,9 +191,7 @@ describe('Validator', () => {
|
|
|
191
191
|
it('adds static ["_$isValidator$"] property as a marker to identify the Validator class across different lion versions (as instanceof cannot be used)', async () => {
|
|
192
192
|
const myValidator = new Validator();
|
|
193
193
|
|
|
194
|
-
// @ts-ignore - static property access
|
|
195
194
|
expect(myValidator.constructor['_$isValidator$']).to.exist;
|
|
196
|
-
// @ts-ignore - static property access
|
|
197
195
|
expect(myValidator.constructor['_$isValidator$']).to.be.true;
|
|
198
196
|
});
|
|
199
197
|
|
|
@@ -1554,13 +1554,11 @@ export function runValidateMixinSuite(customConfig) {
|
|
|
1554
1554
|
// eslint-disable-next-line no-restricted-syntax
|
|
1555
1555
|
for (const state of ['dirty', 'touched', 'prefilled', 'submitted']) {
|
|
1556
1556
|
counter += 1;
|
|
1557
|
-
// @ts-ignore - test property access
|
|
1558
1557
|
el[state] = false;
|
|
1559
1558
|
// eslint-disable-next-line no-await-in-loop
|
|
1560
1559
|
await el.updateComplete;
|
|
1561
1560
|
expect(spy.callCount).to.equal(counter);
|
|
1562
1561
|
counter += 1;
|
|
1563
|
-
// @ts-ignore - test property access
|
|
1564
1562
|
el[state] = true;
|
|
1565
1563
|
// eslint-disable-next-line no-await-in-loop
|
|
1566
1564
|
await el.updateComplete;
|
|
@@ -6,7 +6,6 @@ async function combineLocalizeImports(importPromises) {
|
|
|
6
6
|
const combinedResult = localizeObjects[0];
|
|
7
7
|
for (const localizeObject of localizeObjects.slice(1)) {
|
|
8
8
|
Object.entries(localizeObject.default).forEach(([key, val]) => {
|
|
9
|
-
// @ts-ignore - dynamic property access
|
|
10
9
|
combinedResult.default[key] = val;
|
|
11
10
|
});
|
|
12
11
|
}
|
|
@@ -597,11 +597,12 @@ describe('<lion-input-datepicker>', () => {
|
|
|
597
597
|
<lion-input-datepicker label="End date" name="endDate"></lion-input-datepicker>
|
|
598
598
|
`);
|
|
599
599
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
600
|
+
// @ts-expect-error
|
|
601
|
+
const elements = el.parentElement.children;
|
|
602
|
+
// @ts-expect-error
|
|
603
|
+
const startLabel = elements.startDate.querySelector('button').ariaLabel;
|
|
604
|
+
// @ts-expect-error
|
|
605
|
+
const endLabel = elements.endDate.querySelector('button').ariaLabel;
|
|
605
606
|
|
|
606
607
|
expect(startLabel).to.not.equal(endLabel);
|
|
607
608
|
});
|
|
@@ -210,7 +210,6 @@ describe('formatDate', () => {
|
|
|
210
210
|
locale,
|
|
211
211
|
};
|
|
212
212
|
const parsedDate = /** @type {Date} */ (parseDate('12.10.2019'));
|
|
213
|
-
// @ts-ignore - dynamic locale key access
|
|
214
213
|
expect(formatDate(parsedDate, options)).to.equal(LOCALE_FORMATTED_DATE_MAP[locale]);
|
|
215
214
|
});
|
|
216
215
|
});
|
|
@@ -106,21 +106,6 @@ async function preloadPopper() {
|
|
|
106
106
|
|
|
107
107
|
const childDialogsClosedInEventLoopWeakmap = new WeakMap();
|
|
108
108
|
|
|
109
|
-
/**
|
|
110
|
-
* @param {HTMLElement | null} el
|
|
111
|
-
* @param {string} selector
|
|
112
|
-
* @returns {HTMLElement | null}
|
|
113
|
-
*/
|
|
114
|
-
function deepClosest(el, selector) {
|
|
115
|
-
// @ts-ignore - comparing HTMLElement to document/window for safety
|
|
116
|
-
return (
|
|
117
|
-
// @ts-ignore - type comparison check
|
|
118
|
-
(el && el !== document && el !== window && el.closest(selector)) ||
|
|
119
|
-
// @ts-ignore - host property on ShadowRoot
|
|
120
|
-
deepClosest(el.getRootNode().host, selector)
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
109
|
/**
|
|
125
110
|
* OverlayController is the fundament for every single type of overlay. With the right
|
|
126
111
|
* configuration, it can be used to build (modal) dialogs, tooltips, dropdowns, popovers,
|
|
@@ -211,19 +196,10 @@ export class OverlayController extends EventTarget {
|
|
|
211
196
|
placement: 'center',
|
|
212
197
|
},
|
|
213
198
|
zIndex: 9999,
|
|
214
|
-
isOpenable: true,
|
|
215
|
-
focusContentOnOpen: false,
|
|
216
|
-
// This means that content will have visually-hidden / sr-only styles. This is handy for:
|
|
217
|
-
// - hidden menus that should be "indexable" by screen readers (like the Links list in VO: https://support.apple.com/en-gb/guide/voiceover/mchlp2719/mac)
|
|
218
|
-
// - "more" menus that put content in a dropdown that do not fit in the current row
|
|
219
|
-
// - menus that should generally open on tab.
|
|
220
|
-
// @ts-ignore - hideVisually is an extension property
|
|
221
|
-
hideVisually: false,
|
|
222
199
|
};
|
|
223
200
|
|
|
224
201
|
/** @protected */
|
|
225
202
|
this._contentId = `overlay-content--${Math.random().toString(36).slice(2, 10)}`;
|
|
226
|
-
|
|
227
203
|
/** @private */
|
|
228
204
|
this.__originalAttrs = new Map();
|
|
229
205
|
/** @private */
|
|
@@ -244,8 +220,6 @@ export class OverlayController extends EventTarget {
|
|
|
244
220
|
this.__escKeyHandlerCalled = false;
|
|
245
221
|
}
|
|
246
222
|
|
|
247
|
-
#hasSetup = false;
|
|
248
|
-
|
|
249
223
|
/**
|
|
250
224
|
* The invokerNode
|
|
251
225
|
* @type {HTMLElement | undefined}
|
|
@@ -264,7 +238,7 @@ export class OverlayController extends EventTarget {
|
|
|
264
238
|
|
|
265
239
|
/**
|
|
266
240
|
* Determines the connection point in DOM (body vs next to invoker).
|
|
267
|
-
* @type {'global' | 'local' |
|
|
241
|
+
* @type {'global' | 'local' | undefined}
|
|
268
242
|
*/
|
|
269
243
|
get placementMode() {
|
|
270
244
|
return this.config?.placementMode;
|
|
@@ -519,6 +493,8 @@ export class OverlayController extends EventTarget {
|
|
|
519
493
|
this.__validateConfiguration(this.config);
|
|
520
494
|
/** @protected */
|
|
521
495
|
this._init();
|
|
496
|
+
/** @private */
|
|
497
|
+
this.__elementToFocusAfterHide = undefined;
|
|
522
498
|
|
|
523
499
|
if (!this.#isRegisteredOnManager()) {
|
|
524
500
|
this.manager.add(this);
|
|
@@ -540,7 +516,7 @@ export class OverlayController extends EventTarget {
|
|
|
540
516
|
'[OverlayController] You need to provide a .placementMode ("global"|"local")',
|
|
541
517
|
);
|
|
542
518
|
}
|
|
543
|
-
if (!['global', 'local'
|
|
519
|
+
if (!['global', 'local'].includes(newConfig.placementMode)) {
|
|
544
520
|
throw new Error(
|
|
545
521
|
`[OverlayController] "${newConfig.placementMode}" is not a valid .placementMode, use ("global"|"local")`,
|
|
546
522
|
);
|
|
@@ -559,8 +535,6 @@ export class OverlayController extends EventTarget {
|
|
|
559
535
|
* @protected
|
|
560
536
|
*/
|
|
561
537
|
_init() {
|
|
562
|
-
if (!this.config.isOpenable) return;
|
|
563
|
-
|
|
564
538
|
if (!this.__contentHasBeenInitialized) {
|
|
565
539
|
this.__initContentDomStructure();
|
|
566
540
|
this.__contentHasBeenInitialized = true;
|
|
@@ -578,27 +552,8 @@ export class OverlayController extends EventTarget {
|
|
|
578
552
|
}
|
|
579
553
|
this.__handleOverlayStyles({ phase: 'init' });
|
|
580
554
|
this._handleFeatures({ phase: 'init' });
|
|
581
|
-
|
|
582
|
-
/** @private */
|
|
583
|
-
this.__elementToFocusAfterHide = undefined;
|
|
584
|
-
|
|
585
|
-
this.contentNode.dataset.content = '';
|
|
586
|
-
|
|
587
|
-
// Use event delegation to listen for clicks on close buttons...
|
|
588
|
-
this.contentNode.addEventListener('click', this.#hideOnCloseButtonClick);
|
|
589
|
-
|
|
590
|
-
this.#hasSetup = true;
|
|
591
555
|
}
|
|
592
556
|
|
|
593
|
-
#hideOnCloseButtonClick = (/** @type {{ target: any; }} */ ev) => {
|
|
594
|
-
const isOurCloseButton =
|
|
595
|
-
ev.target.hasAttribute('data-close') &&
|
|
596
|
-
deepClosest(ev.target, '[data-content]') === this.contentNode;
|
|
597
|
-
if (!isOurCloseButton) return;
|
|
598
|
-
|
|
599
|
-
this.hide();
|
|
600
|
-
};
|
|
601
|
-
|
|
602
557
|
/**
|
|
603
558
|
* @param {{ phase: OverlayPhase }} config
|
|
604
559
|
* @private
|
|
@@ -639,97 +594,84 @@ export class OverlayController extends EventTarget {
|
|
|
639
594
|
* @private
|
|
640
595
|
*/
|
|
641
596
|
__initContentDomStructure() {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
// @ts-ignore - 'custom' is a valid extension of placementMode
|
|
660
|
-
if (this.config.placementMode === 'custom') {
|
|
661
|
-
// The user should have full freedom to control the content node, so its wrapper nodes should remain neutral.
|
|
662
|
-
wrappingDialogElement.style.cssText += `position: static;`;
|
|
663
|
-
}
|
|
664
|
-
this.__wrappingDialogNode = wrappingDialogElement;
|
|
597
|
+
const wrappingDialogElement = document.createElement('dialog');
|
|
598
|
+
// We use a dialog for its visual capabilities: it renders to the top layer.
|
|
599
|
+
// A11y will depend on the type of overlay and is arranged on contentNode level.
|
|
600
|
+
// Also see: https://www.scottohara.me/blog/2019/03/05/open-dialog.html
|
|
601
|
+
//
|
|
602
|
+
// The role="dialog" is set on the contentNode (or another role), so role="none"
|
|
603
|
+
// is valid here, although AXE complains about this setup.
|
|
604
|
+
// For now we need to add `ignoredRules: ['aria-allowed-role']` in your AXE tests.
|
|
605
|
+
// see: https://lion.js.org/fundamentals/systems/overlays/rationale/#considerations
|
|
606
|
+
wrappingDialogElement.setAttribute('role', 'none');
|
|
607
|
+
wrappingDialogElement.setAttribute('data-overlay-outer-wrapper', '');
|
|
608
|
+
// N.B. position: fixed is needed to escape out of 'overflow: hidden'
|
|
609
|
+
// We give a high z-index for non-modal dialogs, so that we at least win from all siblings of our
|
|
610
|
+
// parent stacking context
|
|
611
|
+
// padding reset so we don't get a weird dialog visual square showing up
|
|
612
|
+
wrappingDialogElement.style.cssText = `display:none; z-index: ${this.config.zIndex}; padding: 0;`;
|
|
613
|
+
this.__wrappingDialogNode = wrappingDialogElement;
|
|
665
614
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
rearrangeNodes({
|
|
678
|
-
wrappingDialogNodeL1: wrappingDialogElement,
|
|
679
|
-
contentWrapperNodeL2: this.contentWrapperNode,
|
|
680
|
-
contentNodeL3: this.contentNode,
|
|
681
|
-
});
|
|
682
|
-
wrappingDialogElement.open = true;
|
|
615
|
+
/**
|
|
616
|
+
* Based on the configuration of the developer, multiple scenarios are accounted for
|
|
617
|
+
* A. We already have a contentWrapperNode ()
|
|
618
|
+
*/
|
|
619
|
+
if (!this.config?.contentWrapperNode) {
|
|
620
|
+
this.__contentWrapperNode = document.createElement('div');
|
|
621
|
+
}
|
|
622
|
+
this.contentWrapperNode.setAttribute('data-id', 'content-wrapper');
|
|
623
|
+
// 'hack' that makes sure popperjs (that is applied one level lower) works correctly in deeply nested shadow roots
|
|
624
|
+
this.contentWrapperNode.style.transform = 'translateZ(0px)';
|
|
683
625
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
// Having a _contWrapperNode and a contentNode with 'position:absolute' results in
|
|
691
|
-
// computed height of 0...
|
|
692
|
-
this.contentNode.style.position = 'static';
|
|
693
|
-
}
|
|
626
|
+
rearrangeNodes({
|
|
627
|
+
wrappingDialogNodeL1: wrappingDialogElement,
|
|
628
|
+
contentWrapperNodeL2: this.contentWrapperNode,
|
|
629
|
+
contentNodeL3: this.contentNode,
|
|
630
|
+
});
|
|
631
|
+
wrappingDialogElement.open = true;
|
|
694
632
|
|
|
695
|
-
|
|
696
|
-
//
|
|
697
|
-
|
|
698
|
-
const hasClosedBySupport = HTMLDialogElement && 'closedBy' in HTMLDialogElement.prototype;
|
|
699
|
-
if (hasClosedBySupport) {
|
|
700
|
-
// @ts-ignore - closedBy is a newer property not in all TypeScript versions
|
|
701
|
-
wrappingDialogElement.closedBy = 'none';
|
|
702
|
-
} else {
|
|
703
|
-
wrappingDialogElement.addEventListener(
|
|
704
|
-
'keydown',
|
|
705
|
-
(/** @type {* & KeyboardEvent} */ event) => {
|
|
706
|
-
if (event.key === 'Escape') {
|
|
707
|
-
event.preventDefault();
|
|
708
|
-
}
|
|
709
|
-
},
|
|
710
|
-
);
|
|
711
|
-
wrappingDialogElement.addEventListener(
|
|
712
|
-
'keyup',
|
|
713
|
-
(/** @type {* & KeyboardEvent} */ event) => {
|
|
714
|
-
if (event.key === 'Escape') {
|
|
715
|
-
event.preventDefault();
|
|
716
|
-
}
|
|
717
|
-
},
|
|
718
|
-
);
|
|
719
|
-
wrappingDialogElement.addEventListener('cancel', event => {
|
|
720
|
-
event.stopPropagation();
|
|
721
|
-
});
|
|
722
|
-
wrappingDialogElement.addEventListener('close', event => {
|
|
723
|
-
event.stopPropagation();
|
|
724
|
-
});
|
|
725
|
-
}
|
|
726
|
-
} else {
|
|
727
|
-
// quick hack to make none-overlay flows work...
|
|
728
|
-
this.__contentWrapperNode = this.contentNode;
|
|
729
|
-
this.__wrappingDialogNode = this.contentNode;
|
|
633
|
+
if (this.isTooltip) {
|
|
634
|
+
// needed to prevent tooltip getting focus in Safari and Firefox
|
|
635
|
+
wrappingDialogElement.setAttribute('tabindex', '-1');
|
|
730
636
|
}
|
|
731
637
|
|
|
732
638
|
this.__wrappingDialogNode.style.display = 'none';
|
|
639
|
+
this.contentWrapperNode.style.zIndex = '1';
|
|
640
|
+
|
|
641
|
+
if (getComputedStyle(this.contentNode).position === 'absolute') {
|
|
642
|
+
// Having a _contWrapperNode and a contentNode with 'position:absolute' results in
|
|
643
|
+
// computed height of 0...
|
|
644
|
+
this.contentNode.style.position = 'static';
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// Here we prevent any interference of the native <dialog> element with the keyboard behavior
|
|
648
|
+
// as defined by the OverlayController. This is needed until we can configure `closedby="none"`
|
|
649
|
+
// on the native dialog for all browsers: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby
|
|
650
|
+
const hasClosedBySupport = HTMLDialogElement && 'closedBy' in HTMLDialogElement.prototype;
|
|
651
|
+
if (hasClosedBySupport) {
|
|
652
|
+
// @ts-expect-error
|
|
653
|
+
wrappingDialogElement.closedBy = 'none';
|
|
654
|
+
} else {
|
|
655
|
+
wrappingDialogElement.addEventListener(
|
|
656
|
+
'keydown',
|
|
657
|
+
(/** @type {* & KeyboardEvent} */ event) => {
|
|
658
|
+
if (event.key === 'Escape') {
|
|
659
|
+
event.preventDefault();
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
);
|
|
663
|
+
wrappingDialogElement.addEventListener('keyup', (/** @type {* & KeyboardEvent} */ event) => {
|
|
664
|
+
if (event.key === 'Escape') {
|
|
665
|
+
event.preventDefault();
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
wrappingDialogElement.addEventListener('cancel', event => {
|
|
669
|
+
event.stopPropagation();
|
|
670
|
+
});
|
|
671
|
+
wrappingDialogElement.addEventListener('close', event => {
|
|
672
|
+
event.stopPropagation();
|
|
673
|
+
});
|
|
674
|
+
}
|
|
733
675
|
}
|
|
734
676
|
|
|
735
677
|
/**
|
|
@@ -800,7 +742,6 @@ export class OverlayController extends EventTarget {
|
|
|
800
742
|
* @private
|
|
801
743
|
*/
|
|
802
744
|
__storeOriginalAttrs(node, attrs) {
|
|
803
|
-
/** @type {Record<string, string | null>} */
|
|
804
745
|
const attrMap = {};
|
|
805
746
|
attrs.forEach(attrName => {
|
|
806
747
|
attrMap[attrName] = node.getAttribute(attrName);
|
|
@@ -870,11 +811,6 @@ export class OverlayController extends EventTarget {
|
|
|
870
811
|
contentNode: this.contentNode,
|
|
871
812
|
});
|
|
872
813
|
}
|
|
873
|
-
|
|
874
|
-
if (this.config.focusContentOnOpen) {
|
|
875
|
-
this.contentNode.focus();
|
|
876
|
-
}
|
|
877
|
-
|
|
878
814
|
/** @type {function} */
|
|
879
815
|
(this._showResolve)();
|
|
880
816
|
}
|
|
@@ -907,7 +843,6 @@ export class OverlayController extends EventTarget {
|
|
|
907
843
|
await this.__createPopperInstance();
|
|
908
844
|
this._popper.forceUpdate();
|
|
909
845
|
}
|
|
910
|
-
// N.B. leave it up to the user if placementMode === 'custom'
|
|
911
846
|
}
|
|
912
847
|
|
|
913
848
|
/**
|
|
@@ -927,9 +862,6 @@ export class OverlayController extends EventTarget {
|
|
|
927
862
|
* @event hide right after the overlay is hidden
|
|
928
863
|
*/
|
|
929
864
|
async hide() {
|
|
930
|
-
// Function like a no-op for dynamic edge cases...
|
|
931
|
-
if (!this.config.isOpenable) return;
|
|
932
|
-
|
|
933
865
|
this._hideComplete = new Promise(resolve => {
|
|
934
866
|
this._hideResolve = resolve;
|
|
935
867
|
});
|
|
@@ -1081,15 +1013,6 @@ export class OverlayController extends EventTarget {
|
|
|
1081
1013
|
if (this.visibilityTriggerFunction) {
|
|
1082
1014
|
this._handleVisibilityTriggers({ phase });
|
|
1083
1015
|
}
|
|
1084
|
-
|
|
1085
|
-
if (phase === 'init' && this.config.focusContentOnOpen) {
|
|
1086
|
-
this.contentNode?.setAttribute('tabindex', '-1');
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
if (phase === 'teardown' && this.config.focusContentOnOpen) {
|
|
1090
|
-
// TODO: capture initial attr, use Resettable mechanism of VisibilityToggleCtrl in whole Controller
|
|
1091
|
-
this.contentNode?.removeAttribute('tabindex');
|
|
1092
|
-
}
|
|
1093
1016
|
}
|
|
1094
1017
|
|
|
1095
1018
|
/**
|
|
@@ -1263,9 +1186,7 @@ export class OverlayController extends EventTarget {
|
|
|
1263
1186
|
if (phase === 'show') {
|
|
1264
1187
|
this.#handleShiftKeyPress();
|
|
1265
1188
|
this.#handleFocusInsideDialog();
|
|
1266
|
-
// @ts-ignore - HTMLDialogElement methods
|
|
1267
1189
|
this.__wrappingDialogNode?.close();
|
|
1268
|
-
// @ts-ignore - HTMLDialogElement methods
|
|
1269
1190
|
this.__wrappingDialogNode?.showModal();
|
|
1270
1191
|
/**
|
|
1271
1192
|
* At this moment `#handleFocusInsideDialog` should handle the focus.
|
|
@@ -1516,7 +1437,6 @@ export class OverlayController extends EventTarget {
|
|
|
1516
1437
|
}
|
|
1517
1438
|
|
|
1518
1439
|
teardown() {
|
|
1519
|
-
if (!this.#hasSetup) return;
|
|
1520
1440
|
this.__handleOverlayStyles({ phase: 'teardown' });
|
|
1521
1441
|
if (this.isShown) {
|
|
1522
1442
|
this._keepBodySize({ phase: 'teardown' });
|
|
@@ -1525,10 +1445,6 @@ export class OverlayController extends EventTarget {
|
|
|
1525
1445
|
if (this.#isRegisteredOnManager()) {
|
|
1526
1446
|
this.manager.remove(this);
|
|
1527
1447
|
}
|
|
1528
|
-
|
|
1529
|
-
this.contentNode?.removeEventListener('click', this.#hideOnCloseButtonClick);
|
|
1530
|
-
|
|
1531
|
-
this.#hasSetup = false;
|
|
1532
1448
|
}
|
|
1533
1449
|
|
|
1534
1450
|
/** @private */
|