@shoper/phoenix_design_system 1.18.23-3 → 1.18.23-5
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/build/cjs/packages/phoenix/src/components/dropdown/dropdown.js +2 -2
- package/build/cjs/packages/phoenix/src/components/form/search/search.js +7 -9
- package/build/cjs/packages/phoenix/src/components/form/search/search.js.map +1 -1
- package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js +3 -13
- package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js.map +1 -1
- package/build/cjs/packages/phoenix/src/components/modal/modal.js +5 -5
- package/build/cjs/packages/phoenix/src/components/sheet/sheet.js +4 -4
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.js +32 -176
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.js.map +1 -1
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/cyclic_focus_trap_strategy.js +53 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/cyclic_focus_trap_strategy.js.map +1 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/focus_trap_strategy.js +36 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/focus_trap_strategy.js.map +1 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/sentinel_focus_trap_strategy.js +89 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/sentinel_focus_trap_strategy.js.map +1 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/toggler_focus_trap_strategy.js +77 -0
- package/build/cjs/packages/phoenix/src/controllers/focus_trap_controller/strategies/toggler_focus_trap_strategy.js.map +1 -0
- package/build/esm/packages/phoenix/src/components/dropdown/dropdown.js +2 -2
- package/build/esm/packages/phoenix/src/components/form/search/search.js +7 -9
- package/build/esm/packages/phoenix/src/components/form/search/search.js.map +1 -1
- package/build/esm/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js +3 -13
- package/build/esm/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js.map +1 -1
- package/build/esm/packages/phoenix/src/components/modal/modal.js +5 -5
- package/build/esm/packages/phoenix/src/components/sheet/sheet.js +4 -4
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.d.ts +19 -17
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.js +33 -177
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.js.map +1 -1
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller_types.d.ts +12 -11
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller_types.js +1 -1
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller_types.js.map +1 -1
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/cyclic_focus_trap_strategy.d.ts +17 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/cyclic_focus_trap_strategy.js +49 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/cyclic_focus_trap_strategy.js.map +1 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/focus_trap_strategy.d.ts +11 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/focus_trap_strategy.js +32 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/focus_trap_strategy.js.map +1 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/index.d.ts +6 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/index.js +5 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/index.js.map +1 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/sentinel_focus_trap_strategy.d.ts +31 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/sentinel_focus_trap_strategy.js +85 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/sentinel_focus_trap_strategy.js.map +1 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/toggler_focus_trap_strategy.d.ts +21 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/toggler_focus_trap_strategy.js +73 -0
- package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/strategies/toggler_focus_trap_strategy.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib_es6 = require('../../../../../../external/tslib/tslib.es6.js');
|
|
6
|
+
var focus_trap_strategy = require('./focus_trap_strategy.js');
|
|
7
|
+
|
|
8
|
+
var _TogglerFocusTrapStrategy_getToggler;
|
|
9
|
+
/**
|
|
10
|
+
* Toggler mode focus trap.
|
|
11
|
+
*
|
|
12
|
+
* Focus cycles: toggler → content[0] → … → content[last] → toggler (and reverse).
|
|
13
|
+
* Uses `keydown` + `preventDefault` so the browser never moves focus on its own.
|
|
14
|
+
*
|
|
15
|
+
* Suitable for dropdowns where the toggler button should stay in the Tab cycle
|
|
16
|
+
* alongside the dropdown content.
|
|
17
|
+
*/
|
|
18
|
+
class TogglerFocusTrapStrategy extends focus_trap_strategy.FocusTrapStrategy {
|
|
19
|
+
constructor({ getContainer, getToggler }) {
|
|
20
|
+
super(getContainer);
|
|
21
|
+
_TogglerFocusTrapStrategy_getToggler.set(this, void 0);
|
|
22
|
+
this._handleKeyDown = (ev) => {
|
|
23
|
+
var _a;
|
|
24
|
+
if (!this.active || ev.code !== 'Tab')
|
|
25
|
+
return;
|
|
26
|
+
const container = this.getContainer();
|
|
27
|
+
const toggler = (_a = tslib_es6.__classPrivateFieldGet(this, _TogglerFocusTrapStrategy_getToggler, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
28
|
+
if (!container || !toggler)
|
|
29
|
+
return;
|
|
30
|
+
const $target = ev.target;
|
|
31
|
+
const focusableElements = this.getFocusableElements(container);
|
|
32
|
+
if (ev.shiftKey) {
|
|
33
|
+
// Shift+Tab on toggler → last content element
|
|
34
|
+
if (toggler.contains($target)) {
|
|
35
|
+
const last = focusableElements[focusableElements.length - 1];
|
|
36
|
+
if (!last)
|
|
37
|
+
return;
|
|
38
|
+
ev.preventDefault();
|
|
39
|
+
last.focus();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Shift+Tab on first content element → toggler
|
|
43
|
+
if ($target === focusableElements[0]) {
|
|
44
|
+
ev.preventDefault();
|
|
45
|
+
toggler.focus();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Tab on toggler → first content element
|
|
50
|
+
if (toggler.contains($target)) {
|
|
51
|
+
const first = focusableElements[0];
|
|
52
|
+
if (!first)
|
|
53
|
+
return;
|
|
54
|
+
ev.preventDefault();
|
|
55
|
+
first.focus();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Tab on last content element → toggler
|
|
59
|
+
if ($target === focusableElements[focusableElements.length - 1]) {
|
|
60
|
+
ev.preventDefault();
|
|
61
|
+
toggler.focus();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
tslib_es6.__classPrivateFieldSet(this, _TogglerFocusTrapStrategy_getToggler, getToggler, "f");
|
|
66
|
+
}
|
|
67
|
+
attach() {
|
|
68
|
+
document.addEventListener('keydown', this._handleKeyDown);
|
|
69
|
+
}
|
|
70
|
+
detach() {
|
|
71
|
+
document.removeEventListener('keydown', this._handleKeyDown);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
_TogglerFocusTrapStrategy_getToggler = new WeakMap();
|
|
75
|
+
|
|
76
|
+
exports.TogglerFocusTrapStrategy = TogglerFocusTrapStrategy;
|
|
77
|
+
//# sourceMappingURL=toggler_focus_trap_strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA,wBAAwB,+CAAmD;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
|
|
@@ -31,8 +31,8 @@ let HDropdown = HDropdown_1 = class HDropdown extends PhoenixLightLitElement {
|
|
|
31
31
|
this.preventFocusTrap = false;
|
|
32
32
|
this.noAutoFocus = false;
|
|
33
33
|
this._backdropController = new BackdropController();
|
|
34
|
-
this._focusTrapController = new FocusTrapController({
|
|
35
|
-
|
|
34
|
+
this._focusTrapController = new FocusTrapController(this, {
|
|
35
|
+
mode: 'toggler',
|
|
36
36
|
getContainer: () => { var _a; return (_a = this.$dropdownContent) !== null && _a !== void 0 ? _a : undefined; },
|
|
37
37
|
getToggler: () => this.$dropdownToggler
|
|
38
38
|
});
|
|
@@ -30,11 +30,9 @@ let HSearch = class HSearch extends PhoenixLightLitElement {
|
|
|
30
30
|
this._id = v4();
|
|
31
31
|
this._openSearchButtonAriaLabelId = `${this._id}-open-search-button-aria-label`;
|
|
32
32
|
this._searchContentContainerId = v4();
|
|
33
|
-
this._mobileFocusTrapController = new FocusTrapController({
|
|
34
|
-
|
|
35
|
-
getContainer: () => this
|
|
36
|
-
noAutofocus: true,
|
|
37
|
-
cyclicKeydown: true
|
|
33
|
+
this._mobileFocusTrapController = new FocusTrapController(this, {
|
|
34
|
+
mode: 'cyclic',
|
|
35
|
+
getContainer: () => this
|
|
38
36
|
});
|
|
39
37
|
this._searchResultsRef = createRef();
|
|
40
38
|
this._searchHistoryRef = createRef();
|
|
@@ -398,7 +396,7 @@ let HSearch = class HSearch extends PhoenixLightLitElement {
|
|
|
398
396
|
$searchInput === null || $searchInput === void 0 ? void 0 : $searchInput.focus();
|
|
399
397
|
};
|
|
400
398
|
this._handleOpenSearchWithKeyboard = (ev) => {
|
|
401
|
-
if (ev.code !== 'Enter')
|
|
399
|
+
if (ev.code !== 'Enter' || ev.repeat)
|
|
402
400
|
return;
|
|
403
401
|
ev.preventDefault();
|
|
404
402
|
this._handleOpenSearch();
|
|
@@ -632,13 +630,13 @@ let HSearch = class HSearch extends PhoenixLightLitElement {
|
|
|
632
630
|
if (!this._togglerElement)
|
|
633
631
|
return;
|
|
634
632
|
this._togglerElement.addEventListener('click', this._handleOpenSearch);
|
|
635
|
-
this._togglerElement.addEventListener('
|
|
633
|
+
this._togglerElement.addEventListener('keydown', this._handleOpenSearchWithKeyboard);
|
|
636
634
|
}
|
|
637
635
|
_teardownToggler() {
|
|
638
636
|
if (!this._togglerElement)
|
|
639
637
|
return;
|
|
640
638
|
this._togglerElement.removeEventListener('click', this._handleOpenSearch);
|
|
641
|
-
this._togglerElement.removeEventListener('
|
|
639
|
+
this._togglerElement.removeEventListener('keydown', this._handleOpenSearchWithKeyboard);
|
|
642
640
|
}
|
|
643
641
|
render() {
|
|
644
642
|
super.render();
|
|
@@ -648,7 +646,7 @@ let HSearch = class HSearch extends PhoenixLightLitElement {
|
|
|
648
646
|
tabindex="0"
|
|
649
647
|
aria-haspopup="dialog"
|
|
650
648
|
@click=${this._handleOpenSearch}
|
|
651
|
-
@
|
|
649
|
+
@keydown=${this._handleOpenSearchWithKeyboard}
|
|
652
650
|
>
|
|
653
651
|
${n(this._translations.openSearchButtonAriaLabel, () => html `
|
|
654
652
|
<span id="${this._openSearchButtonAriaLabelId}" class="sr-only">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,uCAAuC,+CAAmD;AAC1F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,wDAA4D;AAC3E;AACA;AACA;AACA,0BAA0B,wDAA4D;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;
|
|
1
|
+
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,uCAAuC,+CAAmD;AAC1F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,wDAA4D;AAC3E;AACA;AACA;AACA,0BAA0B,wDAA4D;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
|
package/build/esm/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js
CHANGED
|
@@ -68,25 +68,15 @@ let HSearchInput = class HSearchInput extends PhoenixLightLitElement {
|
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
|
-
this.input.addEventListener('
|
|
72
|
-
if (ev.key
|
|
71
|
+
this.input.addEventListener('keydown', (ev) => {
|
|
72
|
+
if (ev.key !== 'Enter' || ev.repeat)
|
|
73
73
|
return;
|
|
74
|
-
if (ev.key !== 'Enter') {
|
|
75
|
-
this.emitCustomEvent(SEARCH_CUSTOM_EVENT_NAMES.keyup, {
|
|
76
|
-
detail: {
|
|
77
|
-
searchPhrase: ev.target.value
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
74
|
if (this._isSearchPhraseCleared) {
|
|
83
75
|
this._isSearchPhraseCleared = false;
|
|
84
76
|
return;
|
|
85
77
|
}
|
|
86
78
|
this.emitCustomEvent(SEARCH_CUSTOM_EVENT_NAMES.submit, {
|
|
87
|
-
detail: {
|
|
88
|
-
searchPhrase: ev.target.value
|
|
89
|
-
}
|
|
79
|
+
detail: { searchPhrase: ev.target.value }
|
|
90
80
|
});
|
|
91
81
|
});
|
|
92
82
|
this.input.addEventListener('keyup', debounce_1((ev) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,uCAAuC,qDAAyD;AAChG;AACA;AACA;AACA;AACA,uBAAuB,qDAAyD;AAChF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;
|
|
1
|
+
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,uCAAuC,qDAAyD;AAChG;AACA;AACA;AACA;AACA,uBAAuB,qDAAyD;AAChF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
|
|
@@ -43,8 +43,8 @@ let HModal = HModal_1 = class HModal extends PhoenixLightLitElement {
|
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
this._backdropController = new BackdropController();
|
|
46
|
-
this._focusTrapController = new FocusTrapController({
|
|
47
|
-
|
|
46
|
+
this._focusTrapController = new FocusTrapController(this, {
|
|
47
|
+
mode: 'sentinel',
|
|
48
48
|
getContainer: () => this._contentRef.value,
|
|
49
49
|
noAutofocus: this.noAutofocus
|
|
50
50
|
});
|
|
@@ -134,14 +134,14 @@ let HModal = HModal_1 = class HModal extends PhoenixLightLitElement {
|
|
|
134
134
|
}
|
|
135
135
|
firstUpdated(props) {
|
|
136
136
|
super.firstUpdated(props);
|
|
137
|
-
this._focusTrapController.setSentinels(this._focusSentinelStart.value, this._focusSentinelEnd.value);
|
|
137
|
+
this._focusTrapController.strategy.setSentinels(this._focusSentinelStart.value, this._focusSentinelEnd.value);
|
|
138
138
|
}
|
|
139
139
|
updated(changedProps) {
|
|
140
140
|
if (changedProps.has(MODAL_OPENED_PROP)) {
|
|
141
141
|
this._propsChangeStrategies[MODAL_OPENED_PROP][String(this[MODAL_OPENED_PROP])]();
|
|
142
142
|
}
|
|
143
143
|
if (changedProps.has('noAutofocus')) {
|
|
144
|
-
this._focusTrapController.noAutofocus = this.noAutofocus;
|
|
144
|
+
this._focusTrapController.strategy.noAutofocus = this.noAutofocus;
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
async open() {
|
|
@@ -159,7 +159,7 @@ let HModal = HModal_1 = class HModal extends PhoenixLightLitElement {
|
|
|
159
159
|
setTimeout(() => {
|
|
160
160
|
var _a;
|
|
161
161
|
(_a = this._contentRef.value) === null || _a === void 0 ? void 0 : _a.classList.remove(`modal_show-${this.transition}-start`, `modal_show-${this.transition}-end`);
|
|
162
|
-
this._focusTrapController.focusFirst();
|
|
162
|
+
this._focusTrapController.strategy.focusFirst();
|
|
163
163
|
resolve();
|
|
164
164
|
}, transitionDuration);
|
|
165
165
|
});
|
|
@@ -42,8 +42,8 @@ let HSheet = HSheet_1 = class HSheet extends PhoenixLightLitElement {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
this._backdropController = new BackdropController();
|
|
45
|
-
this._focusTrapController = new FocusTrapController({
|
|
46
|
-
|
|
45
|
+
this._focusTrapController = new FocusTrapController(this, {
|
|
46
|
+
mode: 'sentinel',
|
|
47
47
|
getContainer: () => this._contentRef.value
|
|
48
48
|
});
|
|
49
49
|
this._handleCloseFromCloseComponent = async (ev) => {
|
|
@@ -132,7 +132,7 @@ let HSheet = HSheet_1 = class HSheet extends PhoenixLightLitElement {
|
|
|
132
132
|
}
|
|
133
133
|
firstUpdated(props) {
|
|
134
134
|
super.firstUpdated(props);
|
|
135
|
-
this._focusTrapController.setSentinels(this._focusSentinelStart.value, this._focusSentinelEnd.value);
|
|
135
|
+
this._focusTrapController.strategy.setSentinels(this._focusSentinelStart.value, this._focusSentinelEnd.value);
|
|
136
136
|
}
|
|
137
137
|
updated(changedProps) {
|
|
138
138
|
if (changedProps.has(SHEET_OPENED_PROP)) {
|
|
@@ -154,7 +154,7 @@ let HSheet = HSheet_1 = class HSheet extends PhoenixLightLitElement {
|
|
|
154
154
|
setTimeout(() => {
|
|
155
155
|
var _a;
|
|
156
156
|
(_a = this._contentRef.value) === null || _a === void 0 ? void 0 : _a.classList.remove(`sheet_show-${this.transition}-start`, `sheet_show-${this.transition}-end`);
|
|
157
|
-
this._focusTrapController.focusFirst();
|
|
157
|
+
this._focusTrapController.strategy.focusFirst();
|
|
158
158
|
resolve();
|
|
159
159
|
}, transitionDuration);
|
|
160
160
|
});
|
package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.d.ts
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import { ReactiveController } from 'lit';
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { SentinelFocusTrapStrategy } from './strategies/sentinel_focus_trap_strategy';
|
|
3
|
+
import { CyclicFocusTrapStrategy } from './strategies/cyclic_focus_trap_strategy';
|
|
4
|
+
import { TogglerFocusTrapStrategy } from './strategies/toggler_focus_trap_strategy';
|
|
5
|
+
import type { TFocusTrapProps, TSentinelFocusTrapProps, TCyclicFocusTrapProps } from './focus_trap_controller_types';
|
|
6
|
+
declare type StrategyFor<T extends TFocusTrapProps> = T extends TSentinelFocusTrapProps ? SentinelFocusTrapStrategy : T extends TCyclicFocusTrapProps ? CyclicFocusTrapStrategy : TogglerFocusTrapStrategy;
|
|
7
|
+
/**
|
|
8
|
+
* A thin Lit ReactiveController that owns the lifecycle of a FocusTrapStrategy.
|
|
9
|
+
*
|
|
10
|
+
* Pass a discriminated-union `props` object with `mode: 'sentinel' | 'cyclic' | 'toggler'`
|
|
11
|
+
* and the required options for that mode. The controller creates the correct strategy
|
|
12
|
+
* internally and exposes it as a typed `.strategy` property for mode-specific API access
|
|
13
|
+
* (e.g. `controller.strategy.setSentinels(...)` when mode is 'sentinel').
|
|
14
|
+
*/
|
|
15
|
+
export declare class FocusTrapController<TProps extends TFocusTrapProps = TFocusTrapProps> implements ReactiveController {
|
|
4
16
|
#private;
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
constructor(host: ReactiveControllerHost, props: TProps);
|
|
18
|
+
/** The underlying strategy instance, typed to match the mode passed at construction. */
|
|
19
|
+
get strategy(): StrategyFor<TProps>;
|
|
7
20
|
hostConnected(): void;
|
|
8
21
|
hostDisconnected(): void;
|
|
9
|
-
/** Sentinel mode only: call once in firstUpdated with the two bookend elements. */
|
|
10
|
-
setSentinels(start: HTMLElement, end: HTMLElement): void;
|
|
11
22
|
activate(): void;
|
|
12
23
|
deactivate(): void;
|
|
13
|
-
/**
|
|
14
|
-
* Sentinel mode: move focus to the first real interactive element after the
|
|
15
|
-
* open transition completes (skips sentinelStart at index 0).
|
|
16
|
-
*/
|
|
17
|
-
focusFirst(): void;
|
|
18
|
-
private _getFocusableElements;
|
|
19
24
|
getFocusableElements(container: HTMLElement): HTMLElement[];
|
|
20
|
-
private _isElementTrulyFocusable;
|
|
21
|
-
private _handleSentinelModeKeyUp;
|
|
22
|
-
private _handleCyclicKeyDown;
|
|
23
|
-
private _handleTogglerModeKeyDown;
|
|
24
25
|
}
|
|
26
|
+
export {};
|
package/build/esm/packages/phoenix/src/controllers/focus_trap_controller/focus_trap_controller.js
CHANGED
|
@@ -1,196 +1,52 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __classPrivateFieldSet, __classPrivateFieldGet } from '../../../../../external/tslib/tslib.es6.js';
|
|
2
2
|
import 'lit';
|
|
3
|
-
import {
|
|
3
|
+
import { SentinelFocusTrapStrategy } from './strategies/sentinel_focus_trap_strategy.js';
|
|
4
|
+
import { CyclicFocusTrapStrategy } from './strategies/cyclic_focus_trap_strategy.js';
|
|
5
|
+
import { TogglerFocusTrapStrategy } from './strategies/toggler_focus_trap_strategy.js';
|
|
4
6
|
|
|
5
|
-
var
|
|
7
|
+
var _FocusTrapController_strategy;
|
|
8
|
+
function createStrategy(props) {
|
|
9
|
+
switch (props.mode) {
|
|
10
|
+
case 'sentinel': return new SentinelFocusTrapStrategy({ getContainer: props.getContainer, noAutofocus: props.noAutofocus });
|
|
11
|
+
case 'cyclic': return new CyclicFocusTrapStrategy(props.getContainer);
|
|
12
|
+
case 'toggler': return new TogglerFocusTrapStrategy({ getContainer: props.getContainer, getToggler: props.getToggler });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A thin Lit ReactiveController that owns the lifecycle of a FocusTrapStrategy.
|
|
17
|
+
*
|
|
18
|
+
* Pass a discriminated-union `props` object with `mode: 'sentinel' | 'cyclic' | 'toggler'`
|
|
19
|
+
* and the required options for that mode. The controller creates the correct strategy
|
|
20
|
+
* internally and exposes it as a typed `.strategy` property for mode-specific API access
|
|
21
|
+
* (e.g. `controller.strategy.setSentinels(...)` when mode is 'sentinel').
|
|
22
|
+
*/
|
|
6
23
|
class FocusTrapController {
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
_FocusTrapController_cyclicKeydown.set(this, void 0);
|
|
11
|
-
_FocusTrapController_active.set(this, false);
|
|
12
|
-
_FocusTrapController_sentinelStart.set(this, void 0);
|
|
13
|
-
_FocusTrapController_sentinelEnd.set(this, void 0);
|
|
14
|
-
// ─── Sentinel mode ───────────────────────────────────────────────────────
|
|
15
|
-
this._handleSentinelModeKeyUp = (ev) => {
|
|
16
|
-
var _a;
|
|
17
|
-
if (!__classPrivateFieldGet(this, _FocusTrapController_active, "f") || ev.code !== 'Tab')
|
|
18
|
-
return;
|
|
19
|
-
const container = __classPrivateFieldGet(this, _FocusTrapController_getContainer, "f").call(this);
|
|
20
|
-
if (!container)
|
|
21
|
-
return;
|
|
22
|
-
if (ev.shiftKey) {
|
|
23
|
-
if (document.activeElement === __classPrivateFieldGet(this, _FocusTrapController_sentinelStart, "f")) {
|
|
24
|
-
const focusableElements = this._getFocusableElements(container);
|
|
25
|
-
(_a = focusableElements[focusableElements.length - 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
26
|
-
ev.preventDefault();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
else if (document.activeElement === __classPrivateFieldGet(this, _FocusTrapController_sentinelEnd, "f")) {
|
|
30
|
-
UiDomUtils.setFocusToFirstFocusableElementInContainer(container);
|
|
31
|
-
ev.preventDefault();
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
// ─── Cyclic keydown mode ─────────────────────────────────────────────────
|
|
35
|
-
//
|
|
36
|
-
// No sentinel elements. Tab past the last focusable element wraps to the
|
|
37
|
-
// first; Shift+Tab past the first wraps to the last. Uses keydown +
|
|
38
|
-
// preventDefault so the browser never moves focus outside the container.
|
|
39
|
-
this._handleCyclicKeyDown = (ev) => {
|
|
40
|
-
if (!__classPrivateFieldGet(this, _FocusTrapController_active, "f") || ev.code !== 'Tab')
|
|
41
|
-
return;
|
|
42
|
-
const container = __classPrivateFieldGet(this, _FocusTrapController_getContainer, "f").call(this);
|
|
43
|
-
if (!container)
|
|
44
|
-
return;
|
|
45
|
-
const focusableElements = this._getFocusableElements(container);
|
|
46
|
-
if (focusableElements.length === 0)
|
|
47
|
-
return;
|
|
48
|
-
const $target = ev.target;
|
|
49
|
-
if (ev.shiftKey) {
|
|
50
|
-
if ($target === focusableElements[0]) {
|
|
51
|
-
ev.preventDefault();
|
|
52
|
-
focusableElements[focusableElements.length - 1].focus();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
if ($target === focusableElements[focusableElements.length - 1]) {
|
|
57
|
-
ev.preventDefault();
|
|
58
|
-
focusableElements[0].focus();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
// ─── Toggler mode ────────────────────────────────────────────────────────
|
|
63
|
-
//
|
|
64
|
-
// Cycle: toggler → content[0] → … → content[last] → toggler (and reverse).
|
|
65
|
-
// Uses keydown + preventDefault so the browser never moves focus on its own.
|
|
66
|
-
this._handleTogglerModeKeyDown = (ev) => {
|
|
67
|
-
var _a;
|
|
68
|
-
if (!__classPrivateFieldGet(this, _FocusTrapController_active, "f") || ev.code !== 'Tab')
|
|
69
|
-
return;
|
|
70
|
-
const container = __classPrivateFieldGet(this, _FocusTrapController_getContainer, "f").call(this);
|
|
71
|
-
const toggler = (_a = __classPrivateFieldGet(this, _FocusTrapController_getToggler, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
72
|
-
if (!container || !toggler)
|
|
73
|
-
return;
|
|
74
|
-
const $target = ev.target;
|
|
75
|
-
const focusableElements = this._getFocusableElements(container);
|
|
76
|
-
if (ev.shiftKey) {
|
|
77
|
-
// Shift+Tab on toggler → last content element
|
|
78
|
-
if (toggler.contains($target)) {
|
|
79
|
-
const last = focusableElements[focusableElements.length - 1];
|
|
80
|
-
if (!last)
|
|
81
|
-
return;
|
|
82
|
-
ev.preventDefault();
|
|
83
|
-
last.focus();
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Shift+Tab on first content element → toggler
|
|
87
|
-
if ($target === focusableElements[0]) {
|
|
88
|
-
ev.preventDefault();
|
|
89
|
-
toggler.focus();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
// Tab on toggler → first content element
|
|
94
|
-
if (toggler.contains($target)) {
|
|
95
|
-
const first = focusableElements[0];
|
|
96
|
-
if (!first)
|
|
97
|
-
return;
|
|
98
|
-
ev.preventDefault();
|
|
99
|
-
first.focus();
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
// Tab on last content element → toggler
|
|
103
|
-
if ($target === focusableElements[focusableElements.length - 1]) {
|
|
104
|
-
ev.preventDefault();
|
|
105
|
-
toggler.focus();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
__classPrivateFieldSet(this, _FocusTrapController_getContainer, getContainer, "f");
|
|
110
|
-
__classPrivateFieldSet(this, _FocusTrapController_getToggler, getToggler, "f");
|
|
111
|
-
__classPrivateFieldSet(this, _FocusTrapController_cyclicKeydown, cyclicKeydown, "f");
|
|
112
|
-
this.noAutofocus = noAutofocus;
|
|
24
|
+
constructor(host, props) {
|
|
25
|
+
_FocusTrapController_strategy.set(this, void 0);
|
|
26
|
+
__classPrivateFieldSet(this, _FocusTrapController_strategy, createStrategy(props), "f");
|
|
113
27
|
host.addController(this);
|
|
114
28
|
}
|
|
29
|
+
/** The underlying strategy instance, typed to match the mode passed at construction. */
|
|
30
|
+
get strategy() {
|
|
31
|
+
return __classPrivateFieldGet(this, _FocusTrapController_strategy, "f");
|
|
32
|
+
}
|
|
115
33
|
hostConnected() {
|
|
116
|
-
|
|
117
|
-
document.addEventListener('keydown', this._handleCyclicKeyDown);
|
|
118
|
-
}
|
|
119
|
-
else if (__classPrivateFieldGet(this, _FocusTrapController_getToggler, "f")) {
|
|
120
|
-
document.addEventListener('keydown', this._handleTogglerModeKeyDown);
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
document.addEventListener('keyup', this._handleSentinelModeKeyUp);
|
|
124
|
-
}
|
|
34
|
+
__classPrivateFieldGet(this, _FocusTrapController_strategy, "f").attach();
|
|
125
35
|
}
|
|
126
36
|
hostDisconnected() {
|
|
127
|
-
|
|
128
|
-
document.removeEventListener('keydown', this._handleCyclicKeyDown);
|
|
129
|
-
}
|
|
130
|
-
else if (__classPrivateFieldGet(this, _FocusTrapController_getToggler, "f")) {
|
|
131
|
-
document.removeEventListener('keydown', this._handleTogglerModeKeyDown);
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
document.removeEventListener('keyup', this._handleSentinelModeKeyUp);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/** Sentinel mode only: call once in firstUpdated with the two bookend elements. */
|
|
138
|
-
setSentinels(start, end) {
|
|
139
|
-
__classPrivateFieldSet(this, _FocusTrapController_sentinelStart, start, "f");
|
|
140
|
-
__classPrivateFieldSet(this, _FocusTrapController_sentinelEnd, end, "f");
|
|
37
|
+
__classPrivateFieldGet(this, _FocusTrapController_strategy, "f").detach();
|
|
141
38
|
}
|
|
142
39
|
activate() {
|
|
143
|
-
|
|
144
|
-
// Sentinel mode: move focus to sentinelStart to prime the trap.
|
|
145
|
-
if (!__classPrivateFieldGet(this, _FocusTrapController_getToggler, "f") && !this.noAutofocus) {
|
|
146
|
-
const scrollY = window.scrollY;
|
|
147
|
-
setTimeout(() => {
|
|
148
|
-
var _a;
|
|
149
|
-
(_a = __classPrivateFieldGet(this, _FocusTrapController_sentinelStart, "f")) === null || _a === void 0 ? void 0 : _a.focus();
|
|
150
|
-
window.scrollTo(0, scrollY);
|
|
151
|
-
}, 0);
|
|
152
|
-
}
|
|
40
|
+
__classPrivateFieldGet(this, _FocusTrapController_strategy, "f").activate();
|
|
153
41
|
}
|
|
154
42
|
deactivate() {
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Sentinel mode: move focus to the first real interactive element after the
|
|
159
|
-
* open transition completes (skips sentinelStart at index 0).
|
|
160
|
-
*/
|
|
161
|
-
focusFirst() {
|
|
162
|
-
if (this.noAutofocus)
|
|
163
|
-
return;
|
|
164
|
-
requestAnimationFrame(() => {
|
|
165
|
-
const container = __classPrivateFieldGet(this, _FocusTrapController_getContainer, "f").call(this);
|
|
166
|
-
if (!container)
|
|
167
|
-
return;
|
|
168
|
-
const focusableElements = this._getFocusableElements(container);
|
|
169
|
-
if (focusableElements.length > 0) {
|
|
170
|
-
focusableElements.length > 1 ? focusableElements[1].focus() : focusableElements[0].focus();
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
_getFocusableElements(container) {
|
|
175
|
-
return UiDomUtils.getFocusableElements(container).filter(($el) => this._isElementTrulyFocusable($el));
|
|
43
|
+
__classPrivateFieldGet(this, _FocusTrapController_strategy, "f").deactivate();
|
|
176
44
|
}
|
|
177
45
|
getFocusableElements(container) {
|
|
178
|
-
return this.
|
|
179
|
-
}
|
|
180
|
-
_isElementTrulyFocusable($el) {
|
|
181
|
-
const style = window.getComputedStyle($el);
|
|
182
|
-
if (style.display === 'none' || style.visibility === 'hidden') {
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
if ($el.nodeName === 'H-PORTAL')
|
|
186
|
-
return true;
|
|
187
|
-
const $parent = $el.parentElement;
|
|
188
|
-
if (!$parent)
|
|
189
|
-
return true;
|
|
190
|
-
return this._isElementTrulyFocusable($parent);
|
|
46
|
+
return __classPrivateFieldGet(this, _FocusTrapController_strategy, "f").getFocusableElements(container);
|
|
191
47
|
}
|
|
192
48
|
}
|
|
193
|
-
|
|
49
|
+
_FocusTrapController_strategy = new WeakMap();
|
|
194
50
|
|
|
195
51
|
export { FocusTrapController };
|
|
196
52
|
//# sourceMappingURL=focus_trap_controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,+DAA+D,4CAAgD;AAC/G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;
|
|
1
|
+
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,+DAA+D,4CAAgD;AAC/G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
host: ReactiveControllerHost & HTMLElement;
|
|
1
|
+
export declare type TSentinelFocusTrapProps = {
|
|
2
|
+
mode: 'sentinel';
|
|
4
3
|
getContainer: () => HTMLElement | undefined;
|
|
5
4
|
noAutofocus?: boolean;
|
|
6
|
-
/** When provided, enables toggler mode: focus cycles between the toggler and the container's focusable elements. */
|
|
7
|
-
getToggler?: () => HTMLElement | null | undefined;
|
|
8
|
-
/**
|
|
9
|
-
* When true, enables cyclic keydown mode: Tab past the last focusable element wraps to the
|
|
10
|
-
* first, and Shift+Tab past the first wraps to the last. No sentinel DOM elements required.
|
|
11
|
-
* Use this when the host element is not portaled and `inert` is not applied to background content.
|
|
12
|
-
*/
|
|
13
|
-
cyclicKeydown?: boolean;
|
|
14
5
|
};
|
|
6
|
+
export declare type TCyclicFocusTrapProps = {
|
|
7
|
+
mode: 'cyclic';
|
|
8
|
+
getContainer: () => HTMLElement | undefined;
|
|
9
|
+
};
|
|
10
|
+
export declare type TTogglerFocusTrapProps = {
|
|
11
|
+
mode: 'toggler';
|
|
12
|
+
getContainer: () => HTMLElement | undefined;
|
|
13
|
+
getToggler: () => HTMLElement | null | undefined;
|
|
14
|
+
};
|
|
15
|
+
export declare type TFocusTrapProps = TSentinelFocusTrapProps | TCyclicFocusTrapProps | TTogglerFocusTrapProps;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=focus_trap_controller_types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus_trap_controller_types.js","sourceRoot":"","sources":["../../../../../../../src/controllers/focus_trap_controller/focus_trap_controller_types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"focus_trap_controller_types.js","sourceRoot":"","sources":["../../../../../../../src/controllers/focus_trap_controller/focus_trap_controller_types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FocusTrapStrategy } from './focus_trap_strategy';
|
|
2
|
+
/**
|
|
3
|
+
* Cyclic keydown focus trap.
|
|
4
|
+
*
|
|
5
|
+
* No sentinel DOM elements. Tab past the last focusable element wraps to the first;
|
|
6
|
+
* Shift+Tab past the first wraps to the last. Uses `keydown` + `preventDefault` so the
|
|
7
|
+
* browser never moves focus outside the container.
|
|
8
|
+
*
|
|
9
|
+
* Suitable when the host is not portaled and `inert` is not applied to background content
|
|
10
|
+
* (e.g. a full-screen search overlay on mobile).
|
|
11
|
+
*/
|
|
12
|
+
export declare class CyclicFocusTrapStrategy extends FocusTrapStrategy {
|
|
13
|
+
constructor(getContainer: () => HTMLElement | undefined);
|
|
14
|
+
attach(): void;
|
|
15
|
+
detach(): void;
|
|
16
|
+
private _handleKeyDown;
|
|
17
|
+
}
|