@lion/ui 0.15.1 → 0.15.2
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/dialog/test/lion-dialog.integration.test.js +170 -0
- package/components/input-amount-dropdown/src/localizeNamespaceLoader.js +53 -0
- package/components/input-amount-dropdown/translations/bg.js +5 -0
- package/components/input-amount-dropdown/translations/cs.js +5 -0
- package/components/input-amount-dropdown/translations/de.js +5 -0
- package/components/input-amount-dropdown/translations/es.js +5 -0
- package/components/input-amount-dropdown/translations/fr.js +5 -0
- package/components/input-amount-dropdown/translations/hu.js +5 -0
- package/components/input-amount-dropdown/translations/id.js +5 -0
- package/components/input-amount-dropdown/translations/it.js +5 -0
- package/components/input-amount-dropdown/translations/nl.js +5 -0
- package/components/input-amount-dropdown/translations/pl.js +5 -0
- package/components/input-amount-dropdown/translations/ro.js +5 -0
- package/components/input-amount-dropdown/translations/ru.js +5 -0
- package/components/input-amount-dropdown/translations/sk.js +5 -0
- package/components/input-amount-dropdown/translations/uk.js +5 -0
- package/components/input-amount-dropdown/translations/zh.js +5 -0
- package/components/overlays/src/OverlayController.js +34 -7
- package/components/overlays/test/OverlayMixin.test.js +2 -2
- package/components/overlays/test-suites/OverlayMixin.suite.js +57 -0
- package/custom-elements.json +10 -0
- package/dist-types/components/dialog/test/lion-dialog.integration.test.d.ts +3 -0
- package/dist-types/components/dialog/test/lion-dialog.integration.test.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/src/localizeNamespaceLoader.d.ts +1 -1
- package/dist-types/components/input-amount-dropdown/src/localizeNamespaceLoader.d.ts.map +1 -1
- package/dist-types/components/input-amount-dropdown/translations/bg.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/bg.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/cs.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/cs.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/de.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/de.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/es.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/es.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/fr.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/fr.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/hu.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/hu.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/id.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/id.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/it.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/it.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/nl.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/nl.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/pl.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/pl.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/ro.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/ro.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/ru.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/ru.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/sk.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/sk.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/uk.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/uk.d.ts.map +1 -0
- package/dist-types/components/input-amount-dropdown/translations/zh.d.ts +7 -0
- package/dist-types/components/input-amount-dropdown/translations/zh.d.ts.map +1 -0
- package/dist-types/components/overlays/src/OverlayController.d.ts +13 -4
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
- 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/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/dialog/use-cases.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/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/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/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- 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/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 +1 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/* eslint-disable lit-a11y/no-autofocus */
|
|
2
|
+
import { expect, fixture as _fixture, html, waitUntil } from '@open-wc/testing';
|
|
3
|
+
import { sendKeys } from '@web/test-runner-commands';
|
|
4
|
+
|
|
5
|
+
import '@lion/ui/define/lion-button.js';
|
|
6
|
+
import '@lion/ui/define/lion-combobox.js';
|
|
7
|
+
import '@lion/ui/define/lion-select-rich.js';
|
|
8
|
+
import '@lion/ui/define/lion-option.js';
|
|
9
|
+
import '@lion/ui/define/lion-dialog.js';
|
|
10
|
+
import '@lion/ui/define/lion-tooltip.js';
|
|
11
|
+
|
|
12
|
+
import { mimicUserTyping } from '@lion/ui/combobox-test-helpers.js';
|
|
13
|
+
import sinon from 'sinon';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {import('../src/LionDialog.js').LionDialog} LionDialog
|
|
17
|
+
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
18
|
+
*/
|
|
19
|
+
const fixture = /** @type {(arg: TemplateResult) => Promise<LionDialog>} */ (_fixture);
|
|
20
|
+
|
|
21
|
+
const dropDownEntries = ['Apple', 'Banana'];
|
|
22
|
+
|
|
23
|
+
describe('lion-dialog', () => {
|
|
24
|
+
describe('lion-combobox integration', () => {
|
|
25
|
+
it('should close lion-combobox dropdown on Escape and should not close the parent lion-dialog', async () => {
|
|
26
|
+
const el = await fixture(html`
|
|
27
|
+
<lion-dialog has-close-button>
|
|
28
|
+
<lion-button slot="invoker">Open Dialog</lion-button>
|
|
29
|
+
<div slot="header">Combobox example</div>
|
|
30
|
+
<div slot="content">
|
|
31
|
+
<lion-combobox name="combo" label="Select a fruit">
|
|
32
|
+
${dropDownEntries.map(
|
|
33
|
+
(/** @type { string } */ entry) =>
|
|
34
|
+
html` <lion-option .choiceValue="${entry}">${entry}</lion-option>`,
|
|
35
|
+
)}
|
|
36
|
+
</lion-combobox>
|
|
37
|
+
</div>
|
|
38
|
+
</lion-dialog>
|
|
39
|
+
`);
|
|
40
|
+
const dialogInvoker = /** @type {HTMLElement} */ (el.querySelector('[slot="invoker"]'));
|
|
41
|
+
dialogInvoker.click();
|
|
42
|
+
const combobox = /** @type {HTMLElement} */ el.querySelector('lion-combobox');
|
|
43
|
+
const isComboboxRendered = () => !!combobox?.shadowRoot?.childNodes.length;
|
|
44
|
+
await waitUntil(isComboboxRendered);
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
await mimicUserTyping(combobox, 'a');
|
|
47
|
+
const firstOption = /** @type { HTMLElement | undefined } */ (
|
|
48
|
+
el.querySelectorAll('lion-option')?.[0]
|
|
49
|
+
);
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
const isComboboxFirstOptionInDropdownVisible = () => firstOption?.checkVisibility();
|
|
52
|
+
await waitUntil(isComboboxFirstOptionInDropdownVisible);
|
|
53
|
+
const comboboxDialog = combobox?.shadowRoot?.querySelector('dialog');
|
|
54
|
+
// Note, do not remove `console.log` down below. There is a bug in test engine.
|
|
55
|
+
// Referring dialog.close from the test environement fixes the bug
|
|
56
|
+
console.log(sinon.spy(comboboxDialog?.close));
|
|
57
|
+
const comboboxInput = combobox?.querySelector('input');
|
|
58
|
+
comboboxInput?.focus();
|
|
59
|
+
const dropdownDialog = combobox?.shadowRoot?.querySelector('dialog');
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
const dropdownDialogCloseSpy = sinon.spy(dropdownDialog, 'close');
|
|
62
|
+
await sendKeys({
|
|
63
|
+
press: 'Escape',
|
|
64
|
+
});
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
const isDialogVisible = () => el?.shadowRoot?.querySelector('dialog')?.checkVisibility();
|
|
67
|
+
await waitUntil(() => dropdownDialogCloseSpy.called);
|
|
68
|
+
expect(isDialogVisible()).to.equal(true);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('lion-select-rich integration', () => {
|
|
73
|
+
it('should close lion-select-rich dropdown on Escape and should not close the parent lion-dialog', async () => {
|
|
74
|
+
const el = await fixture(html`
|
|
75
|
+
<lion-dialog has-close-button>
|
|
76
|
+
<lion-button slot="invoker">Open Dialog</lion-button>
|
|
77
|
+
<div slot="header">Select rich example</div>
|
|
78
|
+
<div slot="content">
|
|
79
|
+
<lion-select-rich label="Select a fruit">
|
|
80
|
+
${dropDownEntries.map(
|
|
81
|
+
(/** @type { string } */ entry) =>
|
|
82
|
+
html` <lion-option .choiceValue="${entry}">${entry}</lion-option>`,
|
|
83
|
+
)}
|
|
84
|
+
</lion-select-rich>
|
|
85
|
+
</div>
|
|
86
|
+
</lion-dialog>
|
|
87
|
+
`);
|
|
88
|
+
const dialogInvoker = /** @type {HTMLElement} */ (el.querySelector('[slot="invoker"]'));
|
|
89
|
+
dialogInvoker.click();
|
|
90
|
+
const selectRichInvoker = /** @type {HTMLElement} */ (
|
|
91
|
+
el.querySelector('lion-select-invoker')
|
|
92
|
+
);
|
|
93
|
+
const isSelectRichInvokerRendered = () => !!selectRichInvoker?.shadowRoot?.childNodes.length;
|
|
94
|
+
await waitUntil(isSelectRichInvokerRendered);
|
|
95
|
+
const selectRich = el?.querySelector('lion-select-rich');
|
|
96
|
+
const selectRichDialog = selectRich?.shadowRoot?.querySelector('dialog');
|
|
97
|
+
// Note, do not remove `console.log` down below. There is a bug in test engine.
|
|
98
|
+
// Referring dialog.close from the test environement fixes the bug
|
|
99
|
+
console.log(selectRichDialog?.close);
|
|
100
|
+
|
|
101
|
+
selectRichInvoker?.click();
|
|
102
|
+
const dropdownDialog = el
|
|
103
|
+
?.querySelector('lion-select-rich')
|
|
104
|
+
?.shadowRoot?.querySelector('dialog');
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
const dropdownDialogCloseSpy = sinon.spy(dropdownDialog, 'close');
|
|
107
|
+
const isDropdownVisible = () =>
|
|
108
|
+
el
|
|
109
|
+
?.querySelector('lion-select-rich')
|
|
110
|
+
?.shadowRoot?.querySelector('dialog')
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
?.checkVisibility();
|
|
113
|
+
await waitUntil(isDropdownVisible);
|
|
114
|
+
const lionOptions = /** @type {HTMLElement} */ (el.querySelector('lion-options'));
|
|
115
|
+
lionOptions?.focus();
|
|
116
|
+
await sendKeys({
|
|
117
|
+
press: 'Escape',
|
|
118
|
+
});
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
const isDialogVisible = () => el?.shadowRoot?.querySelector('dialog')?.checkVisibility();
|
|
121
|
+
await waitUntil(() => dropdownDialogCloseSpy.called);
|
|
122
|
+
expect(isDialogVisible()).to.equal(true);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('lion-tooltip integration', () => {
|
|
127
|
+
it('should close lion-tooltip on first Escape and should close the parent lion-dialog on the second Escape', async () => {
|
|
128
|
+
const el = await fixture(html`
|
|
129
|
+
<lion-dialog has-close-button>
|
|
130
|
+
<lion-button slot="invoker" class="dialog-invoker">Open Dialog</lion-button>
|
|
131
|
+
<div slot="header">Tooltip example</div>
|
|
132
|
+
<div slot="content">
|
|
133
|
+
<lion-tooltip has-arrow>
|
|
134
|
+
<button slot="invoker" class="demo-tooltip-invoker">Focus on me</button>
|
|
135
|
+
<div slot="content">This is a tooltip</div>
|
|
136
|
+
</lion-tooltip>
|
|
137
|
+
</div>
|
|
138
|
+
</lion-dialog>
|
|
139
|
+
`);
|
|
140
|
+
|
|
141
|
+
await el.updateComplete;
|
|
142
|
+
const dialogInvoker = /** @type {HTMLElement} */ (el.querySelector('.dialog-invoker'));
|
|
143
|
+
dialogInvoker.click();
|
|
144
|
+
const tooltip = /** @type {HTMLElement} */ el.querySelector('lion-tooltip');
|
|
145
|
+
const isTooltipRendered = () => !!tooltip?.shadowRoot?.childNodes.length;
|
|
146
|
+
await waitUntil(isTooltipRendered);
|
|
147
|
+
const tooltipButton = /** @type {HTMLElement} */ (el.querySelector('.demo-tooltip-invoker'));
|
|
148
|
+
tooltipButton?.focus();
|
|
149
|
+
const getTooltipContent = () =>
|
|
150
|
+
el
|
|
151
|
+
.querySelector('lion-tooltip')
|
|
152
|
+
?.shadowRoot?.querySelector('#overlay-content-node-wrapper');
|
|
153
|
+
// @ts-ignore
|
|
154
|
+
const isTooltipContentVisible = () => getTooltipContent()?.checkVisibility();
|
|
155
|
+
await waitUntil(isTooltipContentVisible);
|
|
156
|
+
await sendKeys({
|
|
157
|
+
press: 'Escape',
|
|
158
|
+
});
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
const isDialogVisible = () => el?.shadowRoot?.querySelector('dialog')?.checkVisibility();
|
|
161
|
+
expect(isTooltipContentVisible()).to.equal(false);
|
|
162
|
+
expect(isDialogVisible()).to.equal(true);
|
|
163
|
+
await sendKeys({
|
|
164
|
+
press: 'Escape',
|
|
165
|
+
});
|
|
166
|
+
expect(isTooltipContentVisible()).to.equal(false);
|
|
167
|
+
expect(isDialogVisible()).to.equal(false);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
});
|
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
2
|
export const localizeNamespaceLoader = /** @param {string} locale */ locale => {
|
|
3
3
|
switch (locale) {
|
|
4
|
+
case 'bg-BG':
|
|
5
|
+
case 'bg':
|
|
6
|
+
return import('@lion/ui/input-amount-dropdown-translations/bg.js');
|
|
7
|
+
case 'cs-CZ':
|
|
8
|
+
case 'cs':
|
|
9
|
+
return import('@lion/ui/input-amount-dropdown-translations/cs.js');
|
|
10
|
+
case 'de-DE':
|
|
11
|
+
case 'de':
|
|
12
|
+
return import('@lion/ui/input-amount-dropdown-translations/de.js');
|
|
13
|
+
case 'en-AU':
|
|
14
|
+
case 'en-GB':
|
|
15
|
+
case 'en-US':
|
|
16
|
+
case 'en-PH':
|
|
17
|
+
case 'en':
|
|
18
|
+
return import('@lion/ui/input-amount-dropdown-translations/en.js');
|
|
19
|
+
case 'es-ES':
|
|
20
|
+
case 'es':
|
|
21
|
+
return import('@lion/ui/input-amount-dropdown-translations/es.js');
|
|
22
|
+
case 'fr-FR':
|
|
23
|
+
case 'fr-BE':
|
|
24
|
+
case 'fr':
|
|
25
|
+
return import('@lion/ui/input-amount-dropdown-translations/fr.js');
|
|
26
|
+
case 'hu-HU':
|
|
27
|
+
case 'hu':
|
|
28
|
+
return import('@lion/ui/input-amount-dropdown-translations/hu.js');
|
|
29
|
+
case 'id-ID':
|
|
30
|
+
case 'id':
|
|
31
|
+
return import('@lion/ui/input-amount-dropdown-translations/id.js');
|
|
32
|
+
case 'it-IT':
|
|
33
|
+
case 'it':
|
|
34
|
+
return import('@lion/ui/input-amount-dropdown-translations/it.js');
|
|
35
|
+
case 'nl-BE':
|
|
36
|
+
case 'nl-NL':
|
|
37
|
+
case 'nl':
|
|
38
|
+
return import('@lion/ui/input-amount-dropdown-translations/nl.js');
|
|
39
|
+
case 'pl-PL':
|
|
40
|
+
case 'pl':
|
|
41
|
+
return import('@lion/ui/input-amount-dropdown-translations/pl.js');
|
|
42
|
+
case 'ro-RO':
|
|
43
|
+
case 'ro':
|
|
44
|
+
return import('@lion/ui/input-amount-dropdown-translations/ro.js');
|
|
45
|
+
case 'ru-RU':
|
|
46
|
+
case 'ru':
|
|
47
|
+
return import('@lion/ui/input-amount-dropdown-translations/ru.js');
|
|
48
|
+
case 'sk-SK':
|
|
49
|
+
case 'sk':
|
|
50
|
+
return import('@lion/ui/input-amount-dropdown-translations/sk.js');
|
|
51
|
+
case 'uk-UA':
|
|
52
|
+
case 'uk':
|
|
53
|
+
return import('@lion/ui/input-amount-dropdown-translations/uk.js');
|
|
54
|
+
case 'zh-CN':
|
|
55
|
+
case 'zh':
|
|
56
|
+
return import('@lion/ui/input-amount-dropdown-translations/zh.js');
|
|
4
57
|
default:
|
|
5
58
|
return import('@lion/ui/input-amount-dropdown-translations/en.js');
|
|
6
59
|
}
|
|
@@ -197,15 +197,24 @@ export class OverlayController extends EventTarget {
|
|
|
197
197
|
this._contentId = `overlay-content--${Math.random().toString(36).slice(2, 10)}`;
|
|
198
198
|
/** @private */
|
|
199
199
|
this.__originalAttrs = new Map();
|
|
200
|
+
/** @private */
|
|
201
|
+
this.__escKeyHandler = this.__escKeyHandler.bind(this);
|
|
200
202
|
this.updateConfig(config);
|
|
201
203
|
/** @private */
|
|
202
204
|
this.__hasActiveTrapsKeyboardFocus = false;
|
|
203
205
|
/** @private */
|
|
204
206
|
this.__hasActiveBackdrop = true;
|
|
205
207
|
/** @private */
|
|
206
|
-
this.__escKeyHandler = this.__escKeyHandler.bind(this);
|
|
207
|
-
/** @private */
|
|
208
208
|
this.__cancelHandler = this.__cancelHandler.bind(this);
|
|
209
|
+
/**
|
|
210
|
+
* The property is used to skip `__escKeyHandler` handler for overlays that have been closed
|
|
211
|
+
* by `__escKeyHandlerCalled` previously.
|
|
212
|
+
* `__escKeyHandlerCalled` is set to `false` right before overlay show up
|
|
213
|
+
* `__escKeyHandlerCalled` is set to `true` when `__escKeyHandler` is called at least one time
|
|
214
|
+
* after each 'show' phase
|
|
215
|
+
* @private
|
|
216
|
+
*/
|
|
217
|
+
this.__escKeyHandlerCalled = false;
|
|
209
218
|
}
|
|
210
219
|
|
|
211
220
|
/**
|
|
@@ -1211,13 +1220,21 @@ export class OverlayController extends EventTarget {
|
|
|
1211
1220
|
* @returns {void}
|
|
1212
1221
|
*/
|
|
1213
1222
|
__escKeyHandler(event) {
|
|
1214
|
-
if (
|
|
1223
|
+
if (
|
|
1224
|
+
event.key !== 'Escape' ||
|
|
1225
|
+
childDialogsClosedInEventLoopWeakmap.has(event) ||
|
|
1226
|
+
(!this.isShown && this.__escKeyHandlerCalled)
|
|
1227
|
+
) {
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1215
1230
|
|
|
1216
1231
|
const hasPressedInside =
|
|
1217
1232
|
event.composedPath().includes(this.contentNode) ||
|
|
1233
|
+
(this.invokerNode && event.composedPath().includes(this.invokerNode)) ||
|
|
1218
1234
|
deepContains(this.contentNode, /** @type {HTMLElement|ShadowRoot} */ (event.target));
|
|
1219
1235
|
|
|
1220
1236
|
if (hasPressedInside) {
|
|
1237
|
+
this.__escKeyHandlerCalled = true;
|
|
1221
1238
|
this.hide();
|
|
1222
1239
|
// We could do event.stopPropagation() here, but we don't want to hide info for
|
|
1223
1240
|
// the outside world about user interactions. Instead, we store the event in a WeakMap
|
|
@@ -1245,12 +1262,21 @@ export class OverlayController extends EventTarget {
|
|
|
1245
1262
|
* @protected
|
|
1246
1263
|
*/
|
|
1247
1264
|
_handleHidesOnEsc({ phase }) {
|
|
1248
|
-
if (phase === '
|
|
1265
|
+
if (phase === 'init') {
|
|
1266
|
+
// we remove previously added (if any) event listener to guarantee
|
|
1267
|
+
// there is only one Escape handler added here.
|
|
1268
|
+
// Note `init` phase triggered on every `updateConfig` call and that
|
|
1269
|
+
// could happen multiple times during the component life cycle
|
|
1270
|
+
this.contentNode.removeEventListener('keyup', this.__escKeyHandler);
|
|
1249
1271
|
this.contentNode.addEventListener('keyup', this.__escKeyHandler);
|
|
1250
1272
|
if (this.invokerNode) {
|
|
1251
1273
|
this.invokerNode.addEventListener('keyup', this.__escKeyHandler);
|
|
1252
1274
|
}
|
|
1253
|
-
}
|
|
1275
|
+
}
|
|
1276
|
+
if (phase === 'show') {
|
|
1277
|
+
this.__escKeyHandlerCalled = false;
|
|
1278
|
+
}
|
|
1279
|
+
if (phase === 'teardown') {
|
|
1254
1280
|
this.contentNode.removeEventListener('keyup', this.__escKeyHandler);
|
|
1255
1281
|
if (this.invokerNode) {
|
|
1256
1282
|
this.invokerNode.removeEventListener('keyup', this.__escKeyHandler);
|
|
@@ -1263,9 +1289,10 @@ export class OverlayController extends EventTarget {
|
|
|
1263
1289
|
* @protected
|
|
1264
1290
|
*/
|
|
1265
1291
|
_handleHidesOnOutsideEsc({ phase }) {
|
|
1266
|
-
if (phase === '
|
|
1292
|
+
if (phase === 'init') {
|
|
1293
|
+
document.removeEventListener('keyup', this.#outsideEscKeyHandler);
|
|
1267
1294
|
document.addEventListener('keyup', this.#outsideEscKeyHandler);
|
|
1268
|
-
} else if (phase === '
|
|
1295
|
+
} else if (phase === 'teardown') {
|
|
1269
1296
|
document.removeEventListener('keyup', this.#outsideEscKeyHandler);
|
|
1270
1297
|
}
|
|
1271
1298
|
}
|
|
@@ -7,9 +7,9 @@ const tagString = defineCE(
|
|
|
7
7
|
class extends OverlayMixin(LitElement) {
|
|
8
8
|
render() {
|
|
9
9
|
return html`
|
|
10
|
-
<
|
|
10
|
+
<slot name="invoker"></slot>
|
|
11
11
|
<div id="overlay-content-node-wrapper">
|
|
12
|
-
<
|
|
12
|
+
<slot name="content"></slot>
|
|
13
13
|
</div>
|
|
14
14
|
`;
|
|
15
15
|
}
|
|
@@ -111,6 +111,63 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
111
111
|
expect(el.opened).to.be.false;
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* In case OverlayMixin has a handler for Escape which sets `opened` to `false`,
|
|
116
|
+
* make sure it does not conflict with the Escape handler in OverlayController.
|
|
117
|
+
* */
|
|
118
|
+
it('syncs opened between overlayController and OverlayMixin on Escape', async () => {
|
|
119
|
+
const config = { hidesOnEsc: true };
|
|
120
|
+
const el = /** @type {OverlayEl} */ (
|
|
121
|
+
await fixture(html`
|
|
122
|
+
<${tag} id="main-dialog" .config="${config}">
|
|
123
|
+
<div slot="content" id="mainContent">
|
|
124
|
+
open nested overlay:
|
|
125
|
+
<${tag} id="sub-dialog" .config="${config}">
|
|
126
|
+
<div slot="content" id="nestedContent">
|
|
127
|
+
<input id="nestedContentInput">
|
|
128
|
+
</div>
|
|
129
|
+
<button slot="invoker" id="nestedInvoker">nested invoker button</button>
|
|
130
|
+
</${tag}>
|
|
131
|
+
</div>
|
|
132
|
+
<button slot="invoker" id="mainInvoker">invoker button</button>
|
|
133
|
+
</${tag}>
|
|
134
|
+
`)
|
|
135
|
+
);
|
|
136
|
+
await el.updateComplete;
|
|
137
|
+
const subDialog = /** @type {OverlayEl} */ (el.querySelector('#sub-dialog'));
|
|
138
|
+
const nestedContentInput = /** @type {OverlayEl} */ (el.querySelector('#nestedContentInput'));
|
|
139
|
+
|
|
140
|
+
// Note, OverlayController has Escape key listener added to "#nestedContent".
|
|
141
|
+
// And the sub-dialog adds the Escape key listener to "#nestedContentInput" which is a child evelement of "#nestedContent"
|
|
142
|
+
// In this case when "#nestedContentInput" is focused and Escape is pressed, the listener of "#nestedContentInput"
|
|
143
|
+
// is always called before the listener set for "#nestedContent" inside OverlayController.
|
|
144
|
+
// This way we check the scenario when OverlayController's `hide()` is called first from
|
|
145
|
+
// The OverlayMixin and it does not prevent OverlayController `hidesOnEsc` handler from being called
|
|
146
|
+
nestedContentInput?.addEventListener('keyup', (/** @type {* & KeyboardEvent} */ event) => {
|
|
147
|
+
if (event.key === 'Escape') {
|
|
148
|
+
subDialog.opened = false;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
el.opened = true;
|
|
153
|
+
await el.updateComplete;
|
|
154
|
+
await el._overlayCtrl._showComplete;
|
|
155
|
+
expect(el.opened).to.be.true;
|
|
156
|
+
expect(el._overlayCtrl.isShown).to.be.true;
|
|
157
|
+
|
|
158
|
+
subDialog.opened = true;
|
|
159
|
+
await subDialog.updateComplete;
|
|
160
|
+
await subDialog._overlayCtrl._showComplete;
|
|
161
|
+
expect(subDialog.opened).to.be.true;
|
|
162
|
+
expect(subDialog._overlayCtrl.isShown).to.be.true;
|
|
163
|
+
|
|
164
|
+
await mimicEscapePress(nestedContentInput);
|
|
165
|
+
expect(subDialog.opened).to.be.false;
|
|
166
|
+
expect(subDialog._overlayCtrl.isShown).to.be.false;
|
|
167
|
+
expect(el.opened).to.be.true;
|
|
168
|
+
expect(el._overlayCtrl.isShown).to.be.true;
|
|
169
|
+
});
|
|
170
|
+
|
|
114
171
|
// TODO: put this tests in OverlayController.test.js instead?
|
|
115
172
|
it('does not change the body size when opened', async () => {
|
|
116
173
|
const parentNode = document.createElement('div');
|
package/custom-elements.json
CHANGED
|
@@ -123690,6 +123690,16 @@
|
|
|
123690
123690
|
},
|
|
123691
123691
|
"privacy": "private"
|
|
123692
123692
|
},
|
|
123693
|
+
{
|
|
123694
|
+
"kind": "field",
|
|
123695
|
+
"name": "__escKeyHandlerCalled",
|
|
123696
|
+
"type": {
|
|
123697
|
+
"text": "boolean"
|
|
123698
|
+
},
|
|
123699
|
+
"description": "The property is used to skip `__escKeyHandler` handler for overlays that have been closed\nby `__escKeyHandlerCalled` previously.\n`__escKeyHandlerCalled` is set to `false` right before overlay show up\n`__escKeyHandlerCalled` is set to `true` when `__escKeyHandler` is called at least one time\nafter each 'show' phase",
|
|
123700
|
+
"privacy": "private",
|
|
123701
|
+
"default": "false"
|
|
123702
|
+
},
|
|
123693
123703
|
{
|
|
123694
123704
|
"kind": "field",
|
|
123695
123705
|
"name": "__eventListeners",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lion-dialog.integration.test.d.ts","sourceRoot":"","sources":["../../../../components/dialog/test/lion-dialog.integration.test.js"],"names":[],"mappings":"yBAea,OAAO,sBAAsB,EAAE,UAAU;6BACzC,OAAO,KAAK,EAAE,cAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export function localizeNamespaceLoader(locale: string): Promise<typeof import("../translations/
|
|
1
|
+
export function localizeNamespaceLoader(locale: string): Promise<typeof import("../translations/bg.js")>;
|
|
2
2
|
//# sourceMappingURL=localizeNamespaceLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localizeNamespaceLoader.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/src/localizeNamespaceLoader.js"],"names":[],"mappings":"AACO,gDAA4C,MAAM,
|
|
1
|
+
{"version":3,"file":"localizeNamespaceLoader.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/src/localizeNamespaceLoader.js"],"names":[],"mappings":"AACO,gDAA4C,MAAM,mDA0DxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bg.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/bg.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cs.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/cs.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/de.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/es.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fr.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/fr.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hu.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/hu.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/id.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"it.d.ts","sourceRoot":"","sources":["../../../../components/input-amount-dropdown/translations/it.js"],"names":[],"mappings":""}
|