@lion/ui 0.8.2 → 0.8.4
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/core/src/ScopedElementsMixin.js +3 -3
- package/components/overlays/src/OverlayController.js +40 -13
- package/components/overlays/test/OverlayController.test.js +233 -30
- package/components/overlays/test-helpers/mimicClick.js +2 -2
- package/custom-elements.json +32 -5
- package/dist-types/components/core/src/ScopedElementsMixin.d.ts +4 -4
- package/dist-types/components/form-integrations/test/helpers/helpers.d.ts +3 -3
- package/dist-types/components/form-integrations/test/helpers/helpers.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
- package/dist-types/components/input-file/src/LionInputFile.d.ts +1 -1
- package/dist-types/components/input-file/src/LionSelectedFileList.d.ts +1 -1
- package/dist-types/components/overlays/src/OverlayController.d.ts +9 -5
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/test/OverlayController.test.d.ts +1 -1
- package/dist-types/components/overlays/test/OverlayController.test.d.ts.map +1 -1
- package/dist-types/components/overlays/test-helpers/mimicClick.d.ts +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +1 -1
- package/dist-types/components/switch/src/LionSwitch.d.ts +1 -1
- package/dist-types/exports/types/form-core.d.ts +1 -0
- package/dist-types/exports/types/form-core.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/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- 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 +61 -1
- package/docs/components/select-rich/use-cases.md +1 -1
- package/docs/components/tabs/examples.md +1 -1
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
- 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 +1 -0
- 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/ajax/overview.md +22 -1
- 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/exports/types/form-core.ts +1 -0
- package/package.json +1 -1
|
@@ -21,9 +21,9 @@ export function supportsScopedRegistry() {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* This file is combination of '@open-wc/scoped-elements@v3/lit-element.js' and '@open-wc/scoped-elements@v3/html-element.js'.
|
|
25
|
-
*
|
|
26
|
-
* This can be a great help for ssr scenarios, allowing elements to be consumed without needing knowledge about
|
|
24
|
+
* This file is a combination of '@open-wc/scoped-elements@v3/lit-element.js' and '@open-wc/scoped-elements@v3/html-element.js'.
|
|
25
|
+
* To make the polyfill an opt-in, some code from '@open-wc/scoped-elements@v2' is added as well.
|
|
26
|
+
* This can be a great help for ssr scenarios, allowing elements to be consumed without needing knowledge about internal
|
|
27
27
|
* consumption.
|
|
28
28
|
* (N.B. at this point in time, this is limited to the scenario where there's one version of lion on the page).
|
|
29
29
|
*
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { overlays } from './singleton.js';
|
|
2
2
|
import { containFocus } from './utils/contain-focus.js';
|
|
3
|
+
import { deepContains } from './utils/deep-contains.js';
|
|
3
4
|
import { overlayShadowDomStyle } from './overlayShadowDomStyle.js';
|
|
4
5
|
import { _adoptStyleUtils } from './utils/adopt-styles.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* @typedef {
|
|
8
|
+
* @typedef {'setup'|'init'|'teardown'|'before-show'|'show'|'hide'|'add'|'remove'} OverlayPhase
|
|
8
9
|
* @typedef {import('@lion/ui/types/overlays.js').ViewportConfig} ViewportConfig
|
|
9
|
-
* @typedef {import('@
|
|
10
|
+
* @typedef {import('@lion/ui/types/overlays.js').OverlayConfig} OverlayConfig
|
|
10
11
|
* @typedef {import('@popperjs/core').Options} PopperOptions
|
|
11
12
|
* @typedef {import('@popperjs/core').Placement} Placement
|
|
13
|
+
* @typedef {import('@popperjs/core').createPopper} Popper
|
|
12
14
|
* @typedef {{ createPopper: Popper }} PopperModule
|
|
13
|
-
* @typedef {'setup'|'init'|'teardown'|'before-show'|'show'|'hide'|'add'|'remove'} OverlayPhase
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -103,6 +104,8 @@ async function preloadPopper() {
|
|
|
103
104
|
return /** @type {* & Promise<PopperModule>} */ (import('@popperjs/core/dist/esm/popper.js'));
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
const childDialogsClosedInEventLoopWeakmap = new WeakMap();
|
|
108
|
+
|
|
106
109
|
/**
|
|
107
110
|
* OverlayController is the fundament for every single type of overlay. With the right
|
|
108
111
|
* configuration, it can be used to build (modal) dialogs, tooltips, dropdowns, popovers,
|
|
@@ -498,9 +501,6 @@ export class OverlayController extends EventTarget {
|
|
|
498
501
|
'[OverlayController] .isTooltip only takes effect when .handlesAccessibility is enabled',
|
|
499
502
|
);
|
|
500
503
|
}
|
|
501
|
-
// if (newConfig.popperConfig.modifiers.arrow && !newConfig.contentWrapperNode) {
|
|
502
|
-
// throw new Error('You need to provide a .contentWrapperNode when Popper arrow is enabled');
|
|
503
|
-
// }
|
|
504
504
|
}
|
|
505
505
|
|
|
506
506
|
/**
|
|
@@ -1146,11 +1146,40 @@ export class OverlayController extends EventTarget {
|
|
|
1146
1146
|
ev.preventDefault();
|
|
1147
1147
|
}
|
|
1148
1148
|
|
|
1149
|
-
/**
|
|
1150
|
-
|
|
1151
|
-
|
|
1149
|
+
/**
|
|
1150
|
+
* @param {KeyboardEvent} event
|
|
1151
|
+
* @returns {void}
|
|
1152
|
+
*/
|
|
1153
|
+
__escKeyHandler(event) {
|
|
1154
|
+
if (event.key !== 'Escape' || childDialogsClosedInEventLoopWeakmap.has(event)) return;
|
|
1155
|
+
|
|
1156
|
+
const hasPressedInside =
|
|
1157
|
+
event.composedPath().includes(this.contentNode) ||
|
|
1158
|
+
deepContains(this.contentNode, /** @type {HTMLElement|ShadowRoot} */ (event.target));
|
|
1159
|
+
if (hasPressedInside) {
|
|
1160
|
+
this.hide();
|
|
1161
|
+
// We could do event.stopPropagation() here, but we don't want to hide info for
|
|
1162
|
+
// the outside world about user interactions. Instead, we store the event in a WeakMap
|
|
1163
|
+
// that will be garbage collected after the event loop.
|
|
1164
|
+
childDialogsClosedInEventLoopWeakmap.set(event, this);
|
|
1165
|
+
}
|
|
1152
1166
|
}
|
|
1153
1167
|
|
|
1168
|
+
/**
|
|
1169
|
+
* @param {KeyboardEvent} event
|
|
1170
|
+
* @returns {void}
|
|
1171
|
+
*/
|
|
1172
|
+
#outsideEscKeyHandler = event => {
|
|
1173
|
+
if (event.key !== 'Escape') return;
|
|
1174
|
+
|
|
1175
|
+
const hasPressedInside =
|
|
1176
|
+
event.composedPath().includes(this.contentNode) ||
|
|
1177
|
+
deepContains(this.contentNode, /** @type {HTMLElement|ShadowRoot} */ (event.target));
|
|
1178
|
+
if (!hasPressedInside) {
|
|
1179
|
+
this.hide();
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1154
1183
|
/**
|
|
1155
1184
|
* @param {{ phase: OverlayPhase }} config
|
|
1156
1185
|
* @protected
|
|
@@ -1175,11 +1204,9 @@ export class OverlayController extends EventTarget {
|
|
|
1175
1204
|
*/
|
|
1176
1205
|
_handleHidesOnOutsideEsc({ phase }) {
|
|
1177
1206
|
if (phase === 'show') {
|
|
1178
|
-
|
|
1179
|
-
ev.key === 'Escape' && this.hide();
|
|
1180
|
-
document.addEventListener('keyup', this.__escKeyHandler);
|
|
1207
|
+
document.addEventListener('keyup', this.#outsideEscKeyHandler);
|
|
1181
1208
|
} else if (phase === 'hide') {
|
|
1182
|
-
document.removeEventListener('keyup', this
|
|
1209
|
+
document.removeEventListener('keyup', this.#outsideEscKeyHandler);
|
|
1183
1210
|
}
|
|
1184
1211
|
}
|
|
1185
1212
|
|
|
@@ -1,28 +1,41 @@
|
|
|
1
1
|
/* eslint-disable no-new */
|
|
2
|
+
import { OverlayController, overlays } from '@lion/ui/overlays.js';
|
|
3
|
+
import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
|
|
4
|
+
import sinon from 'sinon';
|
|
2
5
|
import {
|
|
3
|
-
|
|
6
|
+
unsafeStatic,
|
|
7
|
+
fixtureSync,
|
|
4
8
|
defineCE,
|
|
5
|
-
|
|
9
|
+
aTimeout,
|
|
6
10
|
fixture,
|
|
11
|
+
expect,
|
|
7
12
|
html,
|
|
8
|
-
unsafeStatic,
|
|
9
|
-
fixtureSync,
|
|
10
13
|
} from '@open-wc/testing';
|
|
11
|
-
|
|
12
|
-
import { OverlayController, overlays } from '@lion/ui/overlays.js';
|
|
13
|
-
import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
|
|
14
|
-
import { keyCodes } from '../src/utils/key-codes.js';
|
|
15
|
-
import { simulateTab } from '../src/utils/simulate-tab.js';
|
|
16
|
-
import { _adoptStyleUtils } from '../src/utils/adopt-styles.js';
|
|
14
|
+
|
|
17
15
|
import { createShadowHost } from '../test-helpers/createShadowHost.js';
|
|
16
|
+
import { _adoptStyleUtils } from '../src/utils/adopt-styles.js';
|
|
17
|
+
import { simulateTab } from '../src/utils/simulate-tab.js';
|
|
18
|
+
import { keyCodes } from '../src/utils/key-codes.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
|
-
* @typedef {import('../types/OverlayConfig.js').OverlayConfig} OverlayConfig
|
|
21
21
|
* @typedef {import('../types/OverlayConfig.js').ViewportPlacement} ViewportPlacement
|
|
22
|
+
* @typedef {import('../types/OverlayConfig.js').OverlayConfig} OverlayConfig
|
|
22
23
|
*/
|
|
23
24
|
|
|
24
25
|
const wrappingDialogNodeStyle = 'display: none; z-index: 9999; padding: 0px;';
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* A small wrapper function that closely mimics an escape press from a user
|
|
29
|
+
* (prevents common mistakes like no bubbling or keydown)
|
|
30
|
+
* @param {Element|Document} element
|
|
31
|
+
*/
|
|
32
|
+
async function mimicEscapePress(element) {
|
|
33
|
+
element.dispatchEvent(
|
|
34
|
+
new KeyboardEvent('keyup', { key: 'Escape', bubbles: true, composed: true }),
|
|
35
|
+
);
|
|
36
|
+
await aTimeout(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
/**
|
|
27
40
|
* Make sure that all browsers serialize html in a similar way
|
|
28
41
|
* (Firefox tends to output empty style attrs)
|
|
@@ -74,6 +87,50 @@ const withLocalTestConfig = () =>
|
|
|
74
87
|
),
|
|
75
88
|
});
|
|
76
89
|
|
|
90
|
+
/**
|
|
91
|
+
* @param {HTMLDivElement} parentContent
|
|
92
|
+
* @returns {Promise<{parentOverlay: OverlayController; childOverlay: OverlayController}>}
|
|
93
|
+
*/
|
|
94
|
+
async function createNestedEscControllers(parentContent) {
|
|
95
|
+
const childContent = /** @type {HTMLDivElement} */ (parentContent.querySelector('div[id]'));
|
|
96
|
+
// Assert valid fixure
|
|
97
|
+
const isValid =
|
|
98
|
+
(parentContent.id === 'parent-overlay--hidesOnEsc' ||
|
|
99
|
+
parentContent.id === 'parent-overlay--hidesOnOutsideEsc') &&
|
|
100
|
+
(childContent.id === 'child-overlay--hidesOnEsc' ||
|
|
101
|
+
childContent.id === 'child-overlay--hidesOnOutsideEsc');
|
|
102
|
+
if (!isValid) {
|
|
103
|
+
throw new Error('Provide a valid fixture');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (parentContent.hasAttribute('data-convert-to-shadow-root')) {
|
|
107
|
+
const shadowRootParent = parentContent.attachShadow({ mode: 'open' });
|
|
108
|
+
shadowRootParent.appendChild(childContent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const parentHasOutsideOnEsc = parentContent.id === 'parent-overlay--hidesOnOutsideEsc';
|
|
112
|
+
const childHasOutsideOnEsc = childContent.id === 'child-overlay--hidesOnOutsideEsc';
|
|
113
|
+
|
|
114
|
+
const parentConfig = parentHasOutsideOnEsc ? { hidesOnOutsideEsc: true } : { hidesOnEsc: true };
|
|
115
|
+
const childConfig = childHasOutsideOnEsc ? { hidesOnOutsideEsc: true } : { hidesOnEsc: true };
|
|
116
|
+
|
|
117
|
+
const parentOverlay = new OverlayController({
|
|
118
|
+
...withGlobalTestConfig(),
|
|
119
|
+
contentNode: parentContent,
|
|
120
|
+
...parentConfig,
|
|
121
|
+
});
|
|
122
|
+
const childOverlay = new OverlayController({
|
|
123
|
+
...withGlobalTestConfig(),
|
|
124
|
+
contentNode: childContent,
|
|
125
|
+
...childConfig,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
await parentOverlay.show();
|
|
129
|
+
await childOverlay.show();
|
|
130
|
+
|
|
131
|
+
return { parentOverlay, childOverlay };
|
|
132
|
+
}
|
|
133
|
+
|
|
77
134
|
afterEach(() => {
|
|
78
135
|
overlays.teardown();
|
|
79
136
|
});
|
|
@@ -574,74 +631,221 @@ describe('OverlayController', () => {
|
|
|
574
631
|
});
|
|
575
632
|
|
|
576
633
|
describe('hidesOnEsc', () => {
|
|
577
|
-
it('hides
|
|
634
|
+
it('hides on [Escape] press', async () => {
|
|
578
635
|
const ctrl = new OverlayController({
|
|
579
636
|
...withGlobalTestConfig(),
|
|
580
637
|
hidesOnEsc: true,
|
|
581
638
|
});
|
|
582
639
|
await ctrl.show();
|
|
583
|
-
ctrl.contentNode
|
|
584
|
-
await aTimeout(0);
|
|
640
|
+
await mimicEscapePress(ctrl.contentNode);
|
|
585
641
|
expect(ctrl.isShown).to.be.false;
|
|
586
642
|
});
|
|
587
643
|
|
|
588
|
-
it(
|
|
644
|
+
it('stays shown on [Escape] press with `.hidesOnEsc` set to false', async () => {
|
|
589
645
|
const ctrl = new OverlayController({
|
|
590
646
|
...withGlobalTestConfig(),
|
|
591
647
|
hidesOnEsc: false,
|
|
592
648
|
});
|
|
593
649
|
await ctrl.show();
|
|
594
|
-
ctrl.contentNode
|
|
595
|
-
await aTimeout(0);
|
|
650
|
+
await mimicEscapePress(ctrl.contentNode);
|
|
596
651
|
expect(ctrl.isShown).to.be.true;
|
|
597
652
|
});
|
|
598
653
|
|
|
599
|
-
it('stays shown
|
|
654
|
+
it('stays shown on [Escape] press on outside element', async () => {
|
|
600
655
|
const ctrl = new OverlayController({
|
|
601
656
|
...withGlobalTestConfig(),
|
|
602
657
|
hidesOnEsc: true,
|
|
603
658
|
});
|
|
604
659
|
await ctrl.show();
|
|
605
|
-
|
|
660
|
+
await mimicEscapePress(document);
|
|
606
661
|
expect(ctrl.isShown).to.be.true;
|
|
607
662
|
});
|
|
608
663
|
|
|
609
|
-
it('
|
|
664
|
+
it('stays shown on [Escape] press with modal <dialog> and `.hidesOnEsc` is false', async () => {
|
|
610
665
|
const ctrl = new OverlayController({
|
|
611
666
|
...withGlobalTestConfig(),
|
|
612
667
|
trapsKeyboardFocus: true,
|
|
613
668
|
hidesOnEsc: false,
|
|
614
669
|
});
|
|
615
670
|
await ctrl.show();
|
|
616
|
-
ctrl.contentNode
|
|
617
|
-
await aTimeout(0);
|
|
671
|
+
await mimicEscapePress(ctrl.contentNode);
|
|
618
672
|
expect(ctrl.isShown).to.be.true;
|
|
619
673
|
});
|
|
674
|
+
|
|
675
|
+
it('parent stays shown on [Escape] press in a nested overlay', async () => {
|
|
676
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
677
|
+
await fixture(
|
|
678
|
+
html` <!-- -->
|
|
679
|
+
<div id="parent-overlay--hidesOnEsc">
|
|
680
|
+
<div id="child-overlay--hidesOnEsc">we press [Escape] here</div>
|
|
681
|
+
</div>`,
|
|
682
|
+
)
|
|
683
|
+
);
|
|
684
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
685
|
+
await mimicEscapePress(childOverlay.contentNode);
|
|
686
|
+
|
|
687
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
688
|
+
expect(childOverlay.isShown).to.be.false;
|
|
689
|
+
});
|
|
620
690
|
});
|
|
621
691
|
|
|
622
692
|
describe('hidesOnOutsideEsc', () => {
|
|
623
|
-
it('hides
|
|
693
|
+
it('hides on [Escape] press on outside element', async () => {
|
|
624
694
|
const ctrl = new OverlayController({
|
|
625
695
|
...withGlobalTestConfig(),
|
|
626
696
|
hidesOnOutsideEsc: true,
|
|
627
697
|
});
|
|
628
698
|
await ctrl.show();
|
|
629
|
-
|
|
630
|
-
await aTimeout(0);
|
|
699
|
+
await mimicEscapePress(document);
|
|
631
700
|
expect(ctrl.isShown).to.be.false;
|
|
632
701
|
});
|
|
633
702
|
|
|
634
|
-
it('stays shown
|
|
703
|
+
it('stays shown on [Escape] press on inside element', async () => {
|
|
635
704
|
const ctrl = new OverlayController({
|
|
636
705
|
...withGlobalTestConfig(),
|
|
637
706
|
hidesOnOutsideEsc: true,
|
|
638
707
|
});
|
|
639
708
|
await ctrl.show();
|
|
640
|
-
ctrl.contentNode
|
|
709
|
+
await mimicEscapePress(ctrl.contentNode);
|
|
641
710
|
expect(ctrl.isShown).to.be.true;
|
|
642
711
|
});
|
|
712
|
+
|
|
713
|
+
it('stays shown on [Escape] press in a nested overlay', async () => {
|
|
714
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
715
|
+
await fixture(
|
|
716
|
+
html` <!-- -->
|
|
717
|
+
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
718
|
+
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
719
|
+
</div>`,
|
|
720
|
+
)
|
|
721
|
+
);
|
|
722
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
723
|
+
mimicEscapePress(childOverlay.contentNode);
|
|
724
|
+
|
|
725
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
726
|
+
expect(childOverlay.isShown).to.be.true;
|
|
727
|
+
});
|
|
643
728
|
});
|
|
644
729
|
|
|
730
|
+
describe('Nested hidesOnEsc / hidesOnOutsideEsc', () => {
|
|
731
|
+
describe('Parent has hidesOnEsc and child has hidesOnOutsideEsc', () => {
|
|
732
|
+
it('on [Escape] press in child overlay: parent hides, child stays shown', async () => {
|
|
733
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
734
|
+
await fixture(
|
|
735
|
+
html` <!-- -->
|
|
736
|
+
<div id="parent-overlay--hidesOnEsc">
|
|
737
|
+
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
738
|
+
</div>`,
|
|
739
|
+
)
|
|
740
|
+
);
|
|
741
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
742
|
+
await mimicEscapePress(childOverlay.contentNode);
|
|
743
|
+
|
|
744
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
745
|
+
expect(childOverlay.isShown).to.be.true;
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
it('on [Escape] press outside overlays: parent stays shown, child hides', async () => {
|
|
749
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
750
|
+
await fixture(
|
|
751
|
+
html` <!-- we press [Escape] here -->
|
|
752
|
+
<div id="parent-overlay--hidesOnEsc">
|
|
753
|
+
<div id="child-overlay--hidesOnOutsideEsc"></div>
|
|
754
|
+
</div>`,
|
|
755
|
+
)
|
|
756
|
+
);
|
|
757
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
758
|
+
await mimicEscapePress(document);
|
|
759
|
+
|
|
760
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
761
|
+
expect(childOverlay.isShown).to.be.false;
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
it('on [Escape] press in parent overlay: parent is hidden, child is hidden', async () => {
|
|
765
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
766
|
+
await fixture(
|
|
767
|
+
html` <!-- -->
|
|
768
|
+
<div id="parent-overlay--hidesOnEsc">
|
|
769
|
+
we press [Escape] here
|
|
770
|
+
<div id="child-overlay--hidesOnOutsideEsc"></div>
|
|
771
|
+
</div>`,
|
|
772
|
+
)
|
|
773
|
+
);
|
|
774
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
775
|
+
await mimicEscapePress(parentContent);
|
|
776
|
+
|
|
777
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
778
|
+
expect(childOverlay.isShown).to.be.false;
|
|
779
|
+
});
|
|
780
|
+
});
|
|
781
|
+
describe('Parent has hidesOnOutsideEsc and child has hidesOnEsc', () => {
|
|
782
|
+
it('on [Escape] press in child overlay: parent stays shown, child hides', async () => {
|
|
783
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
784
|
+
await fixture(
|
|
785
|
+
html` <!-- -->
|
|
786
|
+
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
787
|
+
<div id="child-overlay--hidesOnEsc">we press [Escape] here</div>
|
|
788
|
+
</div>`,
|
|
789
|
+
)
|
|
790
|
+
);
|
|
791
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
792
|
+
await mimicEscapePress(childOverlay.contentNode);
|
|
793
|
+
|
|
794
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
795
|
+
expect(childOverlay.isShown).to.be.false;
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
it('on [Escape] press outside overlays: parent hides, child stays shown', async () => {
|
|
799
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
800
|
+
await fixture(
|
|
801
|
+
html` <!-- we press [Escape] here -->
|
|
802
|
+
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
803
|
+
<div id="child-overlay--hidesOnEsc"></div>
|
|
804
|
+
</div>`,
|
|
805
|
+
)
|
|
806
|
+
);
|
|
807
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
808
|
+
await mimicEscapePress(document);
|
|
809
|
+
|
|
810
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
811
|
+
expect(childOverlay.isShown).to.be.true;
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
it('on [Escape] press in parent overlay: parent hides, child stays shown', async () => {
|
|
815
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
816
|
+
await fixture(
|
|
817
|
+
html` <!-- we press [Escape] here -->
|
|
818
|
+
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
819
|
+
<div id="child-overlay--hidesOnEsc"></div>
|
|
820
|
+
</div>`,
|
|
821
|
+
)
|
|
822
|
+
);
|
|
823
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
824
|
+
await mimicEscapePress(document);
|
|
825
|
+
|
|
826
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
827
|
+
expect(childOverlay.isShown).to.be.true;
|
|
828
|
+
});
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
describe('With shadow dom', () => {
|
|
832
|
+
it('on [Escape] press in child overlay in shadow root: parent hides, child stays shown', async () => {
|
|
833
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
834
|
+
await fixture(
|
|
835
|
+
html` <!-- -->
|
|
836
|
+
<div id="parent-overlay--hidesOnEsc" data-convert-to-shadow-root>
|
|
837
|
+
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
838
|
+
</div>`,
|
|
839
|
+
)
|
|
840
|
+
);
|
|
841
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
842
|
+
await mimicEscapePress(childOverlay.contentNode);
|
|
843
|
+
|
|
844
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
845
|
+
expect(childOverlay.isShown).to.be.true;
|
|
846
|
+
});
|
|
847
|
+
});
|
|
848
|
+
});
|
|
645
849
|
describe('hidesOnOutsideClick', () => {
|
|
646
850
|
it('hides on outside click', async () => {
|
|
647
851
|
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
@@ -684,9 +888,8 @@ describe('OverlayController', () => {
|
|
|
684
888
|
expect(ctrl.isShown).to.be.true;
|
|
685
889
|
|
|
686
890
|
// Don't hide on inside mousedown & outside mouseup
|
|
687
|
-
ctrl.contentNode.
|
|
688
|
-
|
|
689
|
-
document.body.dispatchEvent(new MouseEvent('mouseup'));
|
|
891
|
+
await mimicClick(ctrl.contentNode, { releaseElement: document.body, isAsync: true });
|
|
892
|
+
|
|
690
893
|
await aTimeout(0);
|
|
691
894
|
expect(ctrl.isShown).to.be.true;
|
|
692
895
|
|
|
@@ -8,9 +8,9 @@ async function sleep(t = 0) {
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @param {HTMLElement} el
|
|
11
|
-
* @param {{isAsync?:boolean, releaseElement?: HTMLElement}} config
|
|
11
|
+
* @param {{isAsync?:boolean, releaseElement?: HTMLElement}} config releaseElement can be different when the mouse is dragged before release
|
|
12
12
|
*/
|
|
13
|
-
export async function mimicClick(el, { isAsync, releaseElement } = {
|
|
13
|
+
export async function mimicClick(el, { isAsync = false, releaseElement } = {}) {
|
|
14
14
|
const releaseEl = releaseElement || el;
|
|
15
15
|
el.dispatchEvent(new MouseEvent('mousedown'));
|
|
16
16
|
if (isAsync) {
|
package/custom-elements.json
CHANGED
|
@@ -114306,10 +114306,11 @@
|
|
|
114306
114306
|
}
|
|
114307
114307
|
},
|
|
114308
114308
|
{
|
|
114309
|
-
"name": "{ isAsync, releaseElement }",
|
|
114310
|
-
"default": "{
|
|
114309
|
+
"name": "{ isAsync = false, releaseElement }",
|
|
114310
|
+
"default": "{}"
|
|
114311
114311
|
},
|
|
114312
114312
|
{
|
|
114313
|
+
"description": "releaseElement can be different when the mouse is dragged before release",
|
|
114313
114314
|
"name": "config",
|
|
114314
114315
|
"type": {
|
|
114315
114316
|
"text": "{isAsync?:boolean, releaseElement?: HTMLElement}"
|
|
@@ -114997,10 +114998,36 @@
|
|
|
114997
114998
|
"name": "__escKeyHandler",
|
|
114998
114999
|
"parameters": [
|
|
114999
115000
|
{
|
|
115000
|
-
"name": "
|
|
115001
|
+
"name": "event",
|
|
115002
|
+
"type": {
|
|
115003
|
+
"text": "KeyboardEvent"
|
|
115004
|
+
}
|
|
115001
115005
|
}
|
|
115002
115006
|
],
|
|
115003
|
-
"
|
|
115007
|
+
"return": {
|
|
115008
|
+
"type": {
|
|
115009
|
+
"text": "void"
|
|
115010
|
+
}
|
|
115011
|
+
},
|
|
115012
|
+
"privacy": "protected"
|
|
115013
|
+
},
|
|
115014
|
+
{
|
|
115015
|
+
"kind": "field",
|
|
115016
|
+
"name": "#outsideEscKeyHandler",
|
|
115017
|
+
"privacy": "private",
|
|
115018
|
+
"parameters": [
|
|
115019
|
+
{
|
|
115020
|
+
"name": "event",
|
|
115021
|
+
"type": {
|
|
115022
|
+
"text": "KeyboardEvent"
|
|
115023
|
+
}
|
|
115024
|
+
}
|
|
115025
|
+
],
|
|
115026
|
+
"return": {
|
|
115027
|
+
"type": {
|
|
115028
|
+
"text": "void"
|
|
115029
|
+
}
|
|
115030
|
+
}
|
|
115004
115031
|
},
|
|
115005
115032
|
{
|
|
115006
115033
|
"kind": "method",
|
|
@@ -142184,7 +142211,7 @@
|
|
|
142184
142211
|
},
|
|
142185
142212
|
{
|
|
142186
142213
|
"kind": "mixin",
|
|
142187
|
-
"description": "This file is combination of '@open-wc/scoped-elements@v3/lit-element.js' and '@open-wc/scoped-elements@v3/html-element.js'.\
|
|
142214
|
+
"description": "This file is a combination of '@open-wc/scoped-elements@v3/lit-element.js' and '@open-wc/scoped-elements@v3/html-element.js'.\nTo make the polyfill an opt-in, some code from '@open-wc/scoped-elements@v2' is added as well.\nThis can be a great help for ssr scenarios, allowing elements to be consumed without needing knowledge about internal\nconsumption.\n(N.B. at this point in time, this is limited to the scenario where there's one version of lion on the page).\n\n## Considerations\nIn its current state, the [scoped-custom-element-registry](https://github.com/webcomponents/polyfills/tree/master/packages/scoped-custom-element-registry) draft spec has uncertainties:\n- the spec is not yet final; it's not clear how long it will be dependent on a polyfill\n- the polyfill conflicts with new browser functionality (form-associated custom elements in Safari, ShadowRoot.createElement in Chrome Canary, etc.).\n- the spsc is not compatible with SSR and it remains unclear if it will be in the future\n\nAlso see: https://github.com/webcomponents/polyfills/issues?q=scoped-custom-element-registry\n\nIn previous considerations (last year), we betted on the spec to evolve quickly and the polyfill to be stable.\nTill this day, little progress has been made. In the meantime.",
|
|
142188
142215
|
"name": "ScopedElementsMixin",
|
|
142189
142216
|
"members": [
|
|
142190
142217
|
{
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export function supportsScopedRegistry(): boolean;
|
|
12
12
|
/**
|
|
13
|
-
* This file is combination of '@open-wc/scoped-elements@v3/lit-element.js' and '@open-wc/scoped-elements@v3/html-element.js'.
|
|
14
|
-
*
|
|
15
|
-
* This can be a great help for ssr scenarios, allowing elements to be consumed without needing knowledge about
|
|
13
|
+
* This file is a combination of '@open-wc/scoped-elements@v3/lit-element.js' and '@open-wc/scoped-elements@v3/html-element.js'.
|
|
14
|
+
* To make the polyfill an opt-in, some code from '@open-wc/scoped-elements@v2' is added as well.
|
|
15
|
+
* This can be a great help for ssr scenarios, allowing elements to be consumed without needing knowledge about internal
|
|
16
16
|
* consumption.
|
|
17
17
|
* (N.B. at this point in time, this is limited to the scenario where there's one version of lion on the page).
|
|
18
18
|
*
|
|
@@ -40,7 +40,7 @@ export function supportsScopedRegistry(): boolean;
|
|
|
40
40
|
* @param {T} superclass
|
|
41
41
|
* @return {T & ScopedElementsHostConstructor & ScopedElementsHostV2Constructor}
|
|
42
42
|
*/
|
|
43
|
-
export function ScopedElementsMixin<T extends import("@open-wc/dedupe-mixin").Constructor<import("lit").LitElement>>(superclass: T): T & import("@open-wc/dedupe-mixin").Constructor<import("
|
|
43
|
+
export function ScopedElementsMixin<T extends import("@open-wc/dedupe-mixin").Constructor<import("lit").LitElement>>(superclass: T): T & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/lit-element.js").ScopedElementsHost> & import("./types.js").ScopedElementsHostV2Constructor;
|
|
44
44
|
export type ScopedElementsMap = import('../../form-core/types/validate/ValidateMixinTypes.js').ScopedElementsMap;
|
|
45
45
|
export type ScopedElementsHostConstructor = import('@open-wc/dedupe-mixin').Constructor<ScopedElementsHost>;
|
|
46
46
|
export type ScopedElementsHost = import('@open-wc/scoped-elements/lit-element.js').ScopedElementsHost;
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @param {LionForm} formGroupEl
|
|
7
7
|
*/
|
|
8
|
-
export function getAllFormElements(formGroupEl: LionForm): any
|
|
8
|
+
export function getAllFormElements(formGroupEl: LionForm): any;
|
|
9
9
|
/**
|
|
10
10
|
* @param {LionForm} formGroupEl
|
|
11
11
|
*/
|
|
12
|
-
export function getAllTagNames(formGroupEl: LionForm): any
|
|
12
|
+
export function getAllTagNames(formGroupEl: LionForm): any;
|
|
13
13
|
/**
|
|
14
14
|
* @param {LionForm} formGroupEl
|
|
15
15
|
*/
|
|
16
|
-
export function getAllFieldsAndFormGroups(formGroupEl: LionForm): any
|
|
16
|
+
export function getAllFieldsAndFormGroups(formGroupEl: LionForm): any;
|
|
17
17
|
export type LionForm = import('../../../form/src/LionForm.js').LionForm;
|
|
18
18
|
export type LionField = import('../../../form-core/src/LionField.js').LionField;
|
|
19
19
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../components/form-integrations/test/helpers/helpers.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,gDAFW,QAAQ,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../components/form-integrations/test/helpers/helpers.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,gDAFW,QAAQ,OAWlB;AAED;;GAEG;AACH,4CAFW,QAAQ,OAWlB;AAED;;GAEG;AACH,uDAFW,QAAQ,OAKlB;uBAtCY,OAAO,+BAA+B,EAAE,QAAQ;wBAChD,OAAO,qCAAqC,EAAE,SAAS"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const LionInputDatepicker_base: typeof LionInputDate & import("@open-wc/dedupe-mixin").Constructor<import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost> & Pick<typeof import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost, "prototype" | "localizeNamespaces" | "waitForLocalizeNamespaces"> & Pick<typeof import("lit").LitElement, typeof Symbol.metadata | "prototype" | "_$litElement$" | "enabledWarnings" | "enableWarning" | "disableWarning" | "addInitializer" | "_initializers" | "elementProperties" | "properties" | "elementStyles" | "styles" | "observedAttributes" | "createProperty" | "getPropertyOptions" | "shadowRootOptions"> & import("@open-wc/dedupe-mixin").Constructor<import("../../overlays/types/OverlayMixinTypes.js").OverlayHost> & Pick<typeof import("../../overlays/types/OverlayMixinTypes.js").OverlayHost, "prototype"> & import("@open-wc/dedupe-mixin").Constructor<import("../../overlays/types/ArrowMixinTypes.js").ArrowHost> & Pick<typeof import("../../overlays/types/ArrowMixinTypes.js").ArrowHost, "prototype" | "properties" | "styles"> & import("@open-wc/dedupe-mixin").Constructor<import("
|
|
1
|
+
declare const LionInputDatepicker_base: typeof LionInputDate & import("@open-wc/dedupe-mixin").Constructor<import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost> & Pick<typeof import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost, "prototype" | "localizeNamespaces" | "waitForLocalizeNamespaces"> & Pick<typeof import("lit").LitElement, typeof Symbol.metadata | "prototype" | "_$litElement$" | "enabledWarnings" | "enableWarning" | "disableWarning" | "addInitializer" | "_initializers" | "elementProperties" | "properties" | "elementStyles" | "styles" | "observedAttributes" | "createProperty" | "getPropertyOptions" | "shadowRootOptions"> & import("@open-wc/dedupe-mixin").Constructor<import("../../overlays/types/OverlayMixinTypes.js").OverlayHost> & Pick<typeof import("../../overlays/types/OverlayMixinTypes.js").OverlayHost, "prototype"> & import("@open-wc/dedupe-mixin").Constructor<import("../../overlays/types/ArrowMixinTypes.js").ArrowHost> & Pick<typeof import("../../overlays/types/ArrowMixinTypes.js").ArrowHost, "prototype" | "properties" | "styles"> & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/lit-element.js").ScopedElementsHost> & import("../../core/src/types.js").ScopedElementsHostV2Constructor;
|
|
2
2
|
/**
|
|
3
3
|
* @typedef {import('../../form-core/src/validate/Validator.js').Validator} Validator
|
|
4
4
|
* @typedef {import('lit').RenderOptions} RenderOptions
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const LionInputFile_base: typeof LionField & import("@open-wc/dedupe-mixin").Constructor<import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost> & Pick<typeof import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost, "prototype" | "localizeNamespaces" | "waitForLocalizeNamespaces"> & Pick<typeof import("lit").LitElement, typeof Symbol.metadata | "prototype" | "_$litElement$" | "enabledWarnings" | "enableWarning" | "disableWarning" | "addInitializer" | "_initializers" | "elementProperties" | "properties" | "elementStyles" | "styles" | "observedAttributes" | "createProperty" | "getPropertyOptions" | "shadowRootOptions"> & import("@open-wc/dedupe-mixin").Constructor<import("
|
|
1
|
+
declare const LionInputFile_base: typeof LionField & import("@open-wc/dedupe-mixin").Constructor<import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost> & Pick<typeof import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost, "prototype" | "localizeNamespaces" | "waitForLocalizeNamespaces"> & Pick<typeof import("lit").LitElement, typeof Symbol.metadata | "prototype" | "_$litElement$" | "enabledWarnings" | "enableWarning" | "disableWarning" | "addInitializer" | "_initializers" | "elementProperties" | "properties" | "elementStyles" | "styles" | "observedAttributes" | "createProperty" | "getPropertyOptions" | "shadowRootOptions"> & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/lit-element.js").ScopedElementsHost> & import("../../core/src/types.js").ScopedElementsHostV2Constructor;
|
|
2
2
|
export class LionInputFile extends LionInputFile_base {
|
|
3
3
|
static get scopedElements(): {
|
|
4
4
|
'lion-selected-file-list': typeof LionSelectedFileList;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const LionSelectedFileList_base: typeof LitElement & import("@open-wc/dedupe-mixin").Constructor<import("
|
|
1
|
+
declare const LionSelectedFileList_base: typeof LitElement & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/lit-element.js").ScopedElementsHost> & import("../../core/src/types.js").ScopedElementsHostV2Constructor & import("@open-wc/dedupe-mixin").Constructor<import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost> & Pick<typeof import("../../localize/types/LocalizeMixinTypes.js").LocalizeMixinHost, "prototype" | "localizeNamespaces" | "waitForLocalizeNamespaces"> & Pick<typeof LitElement, typeof Symbol.metadata | "prototype" | "_$litElement$" | "enabledWarnings" | "enableWarning" | "disableWarning" | "addInitializer" | "_initializers" | "elementProperties" | "properties" | "elementStyles" | "styles" | "observedAttributes" | "createProperty" | "getPropertyOptions" | "shadowRootOptions">;
|
|
2
2
|
/**
|
|
3
3
|
* @typedef {import('lit').TemplateResult} TemplateResult
|
|
4
4
|
* @typedef {import('../types/input-file.js').InputFile} InputFile
|