@vielzeug/refine 1.5.3 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion.cjs +1 -1
- package/dist/accordion.cjs.map +1 -1
- package/dist/accordion.js +30 -28
- package/dist/accordion.js.map +1 -1
- package/dist/button-group.cjs.map +1 -1
- package/dist/button-group.js.map +1 -1
- package/dist/button.cjs +1 -1
- package/dist/button.cjs.map +1 -1
- package/dist/button.js +1 -0
- package/dist/button.js.map +1 -1
- package/dist/checkbox-group.cjs +3 -3
- package/dist/checkbox-group.cjs.map +1 -1
- package/dist/checkbox-group.js +51 -58
- package/dist/checkbox-group.js.map +1 -1
- package/dist/combobox.cjs +29 -28
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +201 -195
- package/dist/combobox.js.map +1 -1
- package/dist/content/card/card.css.cjs +1 -1
- package/dist/content/card/card.css.cjs.map +1 -1
- package/dist/content/card/card.css.js +1 -1
- package/dist/content/card/card.css.js.map +1 -1
- package/dist/content/chat-message/chat-message.css.cjs +1 -1
- package/dist/content/chat-message/chat-message.css.cjs.map +1 -1
- package/dist/content/chat-message/chat-message.css.js +1 -1
- package/dist/content/chat-message/chat-message.css.js.map +1 -1
- package/dist/content/icon/icon.d.ts.map +1 -1
- package/dist/content/index.d.ts +4 -0
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/list/_list-item-reveal.cjs +2 -0
- package/dist/content/list/_list-item-reveal.cjs.map +1 -0
- package/dist/content/list/_list-item-reveal.d.ts +25 -0
- package/dist/content/list/_list-item-reveal.d.ts.map +1 -0
- package/dist/content/list/_list-item-reveal.js +33 -0
- package/dist/content/list/_list-item-reveal.js.map +1 -0
- package/dist/content/list/list-item.css.cjs +2 -0
- package/dist/content/list/list-item.css.cjs.map +1 -0
- package/dist/content/list/list-item.css.js +6 -0
- package/dist/content/list/list-item.css.js.map +1 -0
- package/dist/content/list/list-item.d.ts +111 -0
- package/dist/content/list/list-item.d.ts.map +1 -0
- package/dist/content/list/list.css.cjs +2 -0
- package/dist/content/list/list.css.cjs.map +1 -0
- package/dist/content/list/list.css.js +6 -0
- package/dist/content/list/list.css.js.map +1 -0
- package/dist/content/list/list.d.ts +93 -0
- package/dist/content/list/list.d.ts.map +1 -0
- package/dist/custom-elements.json +5224 -4621
- package/dist/date-picker.cjs +2 -1
- package/dist/date-picker.cjs.map +1 -1
- package/dist/date-picker.js +2 -0
- package/dist/date-picker.js.map +1 -1
- package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
- package/dist/disclosure/tab-panel/tab-panel.d.ts.map +1 -1
- package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
- package/dist/drawer.cjs +1 -1
- package/dist/drawer.cjs.map +1 -1
- package/dist/drawer.js +47 -48
- package/dist/drawer.js.map +1 -1
- package/dist/file-input.cjs +111 -45
- package/dist/file-input.cjs.map +1 -1
- package/dist/file-input.js +216 -156
- package/dist/file-input.js.map +1 -1
- package/dist/headless/aria-reflection.cjs +2 -0
- package/dist/headless/aria-reflection.cjs.map +1 -0
- package/dist/headless/aria-reflection.d.ts +27 -0
- package/dist/headless/aria-reflection.d.ts.map +1 -0
- package/dist/headless/aria-reflection.js +18 -0
- package/dist/headless/aria-reflection.js.map +1 -0
- package/dist/headless/checkable.cjs +1 -1
- package/dist/headless/checkable.cjs.map +1 -1
- package/dist/headless/checkable.d.ts +2 -10
- package/dist/headless/checkable.d.ts.map +1 -1
- package/dist/headless/checkable.js +29 -29
- package/dist/headless/checkable.js.map +1 -1
- package/dist/headless/choice-field.cjs +1 -1
- package/dist/headless/choice-field.cjs.map +1 -1
- package/dist/headless/choice-field.d.ts +2 -7
- package/dist/headless/choice-field.d.ts.map +1 -1
- package/dist/headless/choice-field.js +37 -37
- package/dist/headless/choice-field.js.map +1 -1
- package/dist/headless/field-base.cjs +1 -1
- package/dist/headless/field-base.cjs.map +1 -1
- package/dist/headless/field-base.d.ts +17 -0
- package/dist/headless/field-base.d.ts.map +1 -1
- package/dist/headless/field-base.js +21 -6
- package/dist/headless/field-base.js.map +1 -1
- package/dist/headless/focus.cjs +1 -1
- package/dist/headless/focus.cjs.map +1 -1
- package/dist/headless/focus.d.ts +7 -0
- package/dist/headless/focus.d.ts.map +1 -1
- package/dist/headless/focus.js +6 -6
- package/dist/headless/focus.js.map +1 -1
- package/dist/headless/index.d.ts +4 -2
- package/dist/headless/index.d.ts.map +1 -1
- package/dist/headless/nav.cjs +1 -1
- package/dist/headless/nav.cjs.map +1 -1
- package/dist/headless/nav.d.ts +12 -0
- package/dist/headless/nav.d.ts.map +1 -1
- package/dist/headless/nav.js +68 -50
- package/dist/headless/nav.js.map +1 -1
- package/dist/headless/overlay.cjs +1 -1
- package/dist/headless/overlay.cjs.map +1 -1
- package/dist/headless/overlay.d.ts +2 -0
- package/dist/headless/overlay.d.ts.map +1 -1
- package/dist/headless/overlay.js +8 -5
- package/dist/headless/overlay.js.map +1 -1
- package/dist/headless/ref-callback.cjs +2 -0
- package/dist/headless/ref-callback.cjs.map +1 -0
- package/dist/headless/ref-callback.d.ts +26 -0
- package/dist/headless/ref-callback.d.ts.map +1 -0
- package/dist/headless/ref-callback.js +13 -0
- package/dist/headless/ref-callback.js.map +1 -0
- package/dist/headless/swipe.cjs +1 -1
- package/dist/headless/swipe.cjs.map +1 -1
- package/dist/headless/swipe.d.ts +2 -0
- package/dist/headless/swipe.d.ts.map +1 -1
- package/dist/headless/swipe.js +26 -21
- package/dist/headless/swipe.js.map +1 -1
- package/dist/headless.cjs +1 -1
- package/dist/headless.js +28 -26
- package/dist/icon.cjs +1 -1
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js +36 -38
- package/dist/icon.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +63 -61
- package/dist/input.cjs +29 -26
- package/dist/input.cjs.map +1 -1
- package/dist/input.js +91 -79
- package/dist/input.js.map +1 -1
- package/dist/inputs/button/button.css.cjs +1 -1
- package/dist/inputs/button/button.css.cjs.map +1 -1
- package/dist/inputs/button/button.css.js +1 -1
- package/dist/inputs/button/button.css.js.map +1 -1
- package/dist/inputs/button/button.d.ts +8 -0
- package/dist/inputs/button/button.d.ts.map +1 -1
- package/dist/inputs/checkbox/checkbox.css.cjs +1 -1
- package/dist/inputs/checkbox/checkbox.css.cjs.map +1 -1
- package/dist/inputs/checkbox/checkbox.css.js +1 -1
- package/dist/inputs/checkbox/checkbox.css.js.map +1 -1
- package/dist/inputs/combobox/combobox.d.ts +1 -0
- package/dist/inputs/combobox/combobox.d.ts.map +1 -1
- package/dist/inputs/date-picker/date-picker.css.cjs +1 -1
- package/dist/inputs/date-picker/date-picker.css.cjs.map +1 -1
- package/dist/inputs/date-picker/date-picker.css.js +1 -1
- package/dist/inputs/date-picker/date-picker.css.js.map +1 -1
- package/dist/inputs/date-picker/date-picker.d.ts +6 -0
- package/dist/inputs/date-picker/date-picker.d.ts.map +1 -1
- package/dist/inputs/file-input/file-input-upload.cjs +2 -0
- package/dist/inputs/file-input/file-input-upload.cjs.map +1 -0
- package/dist/inputs/file-input/file-input-upload.d.ts +76 -0
- package/dist/inputs/file-input/file-input-upload.d.ts.map +1 -0
- package/dist/inputs/file-input/file-input-upload.js +145 -0
- package/dist/inputs/file-input/file-input-upload.js.map +1 -0
- package/dist/inputs/file-input/file-input.css.cjs +1 -1
- package/dist/inputs/file-input/file-input.css.cjs.map +1 -1
- package/dist/inputs/file-input/file-input.css.js +1 -1
- package/dist/inputs/file-input/file-input.css.js.map +1 -1
- package/dist/inputs/file-input/file-input.d.ts +54 -1
- package/dist/inputs/file-input/file-input.d.ts.map +1 -1
- package/dist/inputs/input/input.css.cjs +1 -1
- package/dist/inputs/input/input.css.cjs.map +1 -1
- package/dist/inputs/input/input.css.js +1 -1
- package/dist/inputs/input/input.css.js.map +1 -1
- package/dist/inputs/input/input.d.ts +13 -0
- package/dist/inputs/input/input.d.ts.map +1 -1
- package/dist/inputs/message-composer/message-composer.css.cjs +1 -1
- package/dist/inputs/message-composer/message-composer.css.cjs.map +1 -1
- package/dist/inputs/message-composer/message-composer.css.js +1 -1
- package/dist/inputs/message-composer/message-composer.css.js.map +1 -1
- package/dist/inputs/message-composer/message-composer.d.ts +7 -0
- package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
- package/dist/inputs/number-input/number-input.css.cjs +1 -1
- package/dist/inputs/number-input/number-input.css.cjs.map +1 -1
- package/dist/inputs/number-input/number-input.css.js +1 -1
- package/dist/inputs/number-input/number-input.css.js.map +1 -1
- package/dist/inputs/number-input/number-input.d.ts +15 -0
- package/dist/inputs/number-input/number-input.d.ts.map +1 -1
- package/dist/inputs/otp-input/otp-input.css.cjs +1 -1
- package/dist/inputs/otp-input/otp-input.css.cjs.map +1 -1
- package/dist/inputs/otp-input/otp-input.css.js +1 -1
- package/dist/inputs/otp-input/otp-input.css.js.map +1 -1
- package/dist/inputs/radio/radio.d.ts.map +1 -1
- package/dist/inputs/select/select.d.ts +1 -0
- package/dist/inputs/select/select.d.ts.map +1 -1
- package/dist/inputs/shared/index.d.ts +1 -1
- package/dist/inputs/shared/index.d.ts.map +1 -1
- package/dist/inputs/shared/templates.cjs +26 -3
- package/dist/inputs/shared/templates.cjs.map +1 -1
- package/dist/inputs/shared/templates.d.ts +20 -0
- package/dist/inputs/shared/templates.d.ts.map +1 -1
- package/dist/inputs/shared/templates.js +29 -5
- package/dist/inputs/shared/templates.js.map +1 -1
- package/dist/inputs/switch/switch.css.cjs +1 -1
- package/dist/inputs/switch/switch.css.cjs.map +1 -1
- package/dist/inputs/switch/switch.css.js +1 -1
- package/dist/inputs/switch/switch.css.js.map +1 -1
- package/dist/inputs/switch/switch.d.ts.map +1 -1
- package/dist/inputs/textarea/textarea.css.cjs +1 -1
- package/dist/inputs/textarea/textarea.css.cjs.map +1 -1
- package/dist/inputs/textarea/textarea.css.js +1 -1
- package/dist/inputs/textarea/textarea.css.js.map +1 -1
- package/dist/inputs/textarea/textarea.d.ts +14 -0
- package/dist/inputs/textarea/textarea.d.ts.map +1 -1
- package/dist/inputs/time-picker/time-picker.css.cjs +1 -1
- package/dist/inputs/time-picker/time-picker.css.cjs.map +1 -1
- package/dist/inputs/time-picker/time-picker.css.js +1 -1
- package/dist/inputs/time-picker/time-picker.css.js.map +1 -1
- package/dist/inputs/time-picker/time-picker.d.ts +6 -0
- package/dist/inputs/time-picker/time-picker.d.ts.map +1 -1
- package/dist/list-item.cjs +22 -0
- package/dist/list-item.cjs.map +1 -0
- package/dist/list-item.js +91 -0
- package/dist/list-item.js.map +1 -0
- package/dist/list.cjs +2 -0
- package/dist/list.cjs.map +1 -0
- package/dist/list.js +64 -0
- package/dist/list.js.map +1 -0
- package/dist/menu.cjs +4 -4
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +60 -59
- package/dist/menu.js.map +1 -1
- package/dist/message-composer.cjs +14 -20
- package/dist/message-composer.cjs.map +1 -1
- package/dist/message-composer.js +63 -64
- package/dist/message-composer.js.map +1 -1
- package/dist/number-input.cjs +5 -3
- package/dist/number-input.cjs.map +1 -1
- package/dist/number-input.js +8 -4
- package/dist/number-input.js.map +1 -1
- package/dist/otp-input.cjs +9 -9
- package/dist/otp-input.cjs.map +1 -1
- package/dist/otp-input.js +70 -62
- package/dist/otp-input.js.map +1 -1
- package/dist/overlay/menu/menu-item.css.cjs +1 -1
- package/dist/overlay/menu/menu-item.css.cjs.map +1 -1
- package/dist/overlay/menu/menu-item.css.js +1 -1
- package/dist/overlay/menu/menu-item.css.js.map +1 -1
- package/dist/overlay/menu/menu-separator.css.cjs +1 -1
- package/dist/overlay/menu/menu-separator.css.cjs.map +1 -1
- package/dist/overlay/menu/menu-separator.css.js +1 -1
- package/dist/overlay/menu/menu-separator.css.js.map +1 -1
- package/dist/overlay/menu/menu.css.cjs +1 -1
- package/dist/overlay/menu/menu.css.cjs.map +1 -1
- package/dist/overlay/menu/menu.css.js +1 -1
- package/dist/overlay/menu/menu.css.js.map +1 -1
- package/dist/overlay/shared/use-dialog.cjs +1 -1
- package/dist/overlay/shared/use-dialog.cjs.map +1 -1
- package/dist/overlay/shared/use-dialog.d.ts.map +1 -1
- package/dist/overlay/shared/use-dialog.js +7 -6
- package/dist/overlay/shared/use-dialog.js.map +1 -1
- package/dist/radio-group.cjs +3 -3
- package/dist/radio-group.cjs.map +1 -1
- package/dist/radio-group.js +64 -70
- package/dist/radio-group.js.map +1 -1
- package/dist/radio.cjs +4 -4
- package/dist/radio.cjs.map +1 -1
- package/dist/radio.js +58 -58
- package/dist/radio.js.map +1 -1
- package/dist/rating.cjs.map +1 -1
- package/dist/rating.js.map +1 -1
- package/dist/refine.cjs +426 -233
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +431 -238
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +452 -259
- package/dist/refine.js.map +1 -1
- package/dist/select.cjs +21 -21
- package/dist/select.cjs.map +1 -1
- package/dist/select.js +135 -127
- package/dist/select.js.map +1 -1
- package/dist/shared/size-presets.cjs +1 -1
- package/dist/shared/size-presets.cjs.map +1 -1
- package/dist/shared/size-presets.d.ts +74 -0
- package/dist/shared/size-presets.d.ts.map +1 -1
- package/dist/shared/size-presets.js +48 -1
- package/dist/shared/size-presets.js.map +1 -1
- package/dist/shared/types.d.ts +5 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/styles/index.cjs +1 -1
- package/dist/styles/index.cjs.map +1 -1
- package/dist/styles/index.d.ts +1 -0
- package/dist/styles/index.d.ts.map +1 -1
- package/dist/styles/index.js +5 -4
- package/dist/styles/index.js.map +1 -1
- package/dist/styles/mixins/field-variants.css.cjs +85 -0
- package/dist/styles/mixins/field-variants.css.cjs.map +1 -0
- package/dist/styles/mixins/field-variants.css.d.ts +66 -0
- package/dist/styles/mixins/field-variants.css.d.ts.map +1 -0
- package/dist/styles/mixins/field-variants.css.js +90 -0
- package/dist/styles/mixins/field-variants.css.js.map +1 -0
- package/dist/switch.cjs +3 -3
- package/dist/switch.cjs.map +1 -1
- package/dist/switch.js +38 -36
- package/dist/switch.js.map +1 -1
- package/dist/tab-item.cjs +8 -8
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js +38 -28
- package/dist/tab-item.js.map +1 -1
- package/dist/tab-panel.cjs +7 -7
- package/dist/tab-panel.cjs.map +1 -1
- package/dist/tab-panel.js +34 -26
- package/dist/tab-panel.js.map +1 -1
- package/dist/tabs.cjs +4 -4
- package/dist/tabs.cjs.map +1 -1
- package/dist/tabs.js +64 -60
- package/dist/tabs.js.map +1 -1
- package/dist/textarea.cjs +15 -18
- package/dist/textarea.cjs.map +1 -1
- package/dist/textarea.js +83 -74
- package/dist/textarea.js.map +1 -1
- package/dist/time-picker.cjs +34 -31
- package/dist/time-picker.cjs.map +1 -1
- package/dist/time-picker.js +121 -109
- package/dist/time-picker.js.map +1 -1
- package/package.json +21 -9
- package/dist/headless/dialog-focus.cjs +0 -2
- package/dist/headless/dialog-focus.cjs.map +0 -1
- package/dist/headless/dialog-focus.d.ts +0 -40
- package/dist/headless/dialog-focus.d.ts.map +0 -1
- package/dist/headless/dialog-focus.js +0 -22
- package/dist/headless/dialog-focus.js.map +0 -1
- package/dist/headless/focus-trap.cjs +0 -2
- package/dist/headless/focus-trap.cjs.map +0 -1
- package/dist/headless/focus-trap.d.ts +0 -45
- package/dist/headless/focus-trap.d.ts.map +0 -1
- package/dist/headless/focus-trap.js +0 -51
- package/dist/headless/focus-trap.js.map +0 -1
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export type DialogFocusControlOptions = {
|
|
2
|
-
/** Returns the container element (dialog or shadow root) for focus trapping. */
|
|
3
|
-
getContainer: () => HTMLElement | ShadowRoot | null;
|
|
4
|
-
/** Returns the CSS selector for the element to focus on open (e.g. `'[autofocus]'`). */
|
|
5
|
-
getInitialFocusSelector: () => string | undefined;
|
|
6
|
-
/** Returns whether focus should be restored to the trigger on close. */
|
|
7
|
-
getReturnFocus: () => boolean | undefined;
|
|
8
|
-
/** Host element used to resolve `getInitialFocusSelector`. */
|
|
9
|
-
host: HTMLElement;
|
|
10
|
-
/** When provided, the trap only intercepts Tab when this returns `true`. */
|
|
11
|
-
trapEnabled?: () => boolean;
|
|
12
|
-
};
|
|
13
|
-
export type DialogFocusControl = {
|
|
14
|
-
/** Capture return focus, activate the trap, and apply initial focus. */
|
|
15
|
-
activate(): void;
|
|
16
|
-
/** Deactivate the trap and restore focus. */
|
|
17
|
-
deactivate(): void;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Combines {@link createFocusTrap} and {@link createFocusManager} into a single
|
|
21
|
-
* `activate / deactivate` API suited for modal dialogs and drawers.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```ts
|
|
25
|
-
* const focusCtrl = createDialogFocusControl({
|
|
26
|
-
* getContainer: () => dialog,
|
|
27
|
-
* getInitialFocusSelector: () => props['initial-focus'].value,
|
|
28
|
-
* getReturnFocus: () => props['return-focus'].value !== false,
|
|
29
|
-
* host: el,
|
|
30
|
-
* });
|
|
31
|
-
*
|
|
32
|
-
* // On open:
|
|
33
|
-
* focusCtrl.activate();
|
|
34
|
-
*
|
|
35
|
-
* // On close:
|
|
36
|
-
* focusCtrl.deactivate();
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
export declare const createDialogFocusControl: (options: DialogFocusControlOptions) => DialogFocusControl;
|
|
40
|
-
//# sourceMappingURL=dialog-focus.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-focus.d.ts","sourceRoot":"","sources":["../../src/headless/dialog-focus.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,yBAAyB,GAAG;IACtC,gFAAgF;IAChF,YAAY,EAAE,MAAM,WAAW,GAAG,UAAU,GAAG,IAAI,CAAC;IACpD,wFAAwF;IACxF,uBAAuB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAClD,wEAAwE;IACxE,cAAc,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;IAC1C,8DAA8D;IAC9D,IAAI,EAAE,WAAW,CAAC;IAClB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,wEAAwE;IACxE,QAAQ,IAAI,IAAI,CAAC;IACjB,6CAA6C;IAC7C,UAAU,IAAI,IAAI,CAAC;CACpB,CAAC;AAIF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,yBAAyB,KAAG,kBAsB7E,CAAC"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createFocusManager as e } from "./focus.js";
|
|
2
|
-
import { createFocusTrap as t } from "./focus-trap.js";
|
|
3
|
-
//#region src/headless/dialog-focus.ts
|
|
4
|
-
var n = (n) => {
|
|
5
|
-
let r = t(n.getContainer, { enabled: n.trapEnabled }), i = e({
|
|
6
|
-
getInitialFocusSelector: n.getInitialFocusSelector,
|
|
7
|
-
getReturnFocus: n.getReturnFocus,
|
|
8
|
-
host: n.host
|
|
9
|
-
});
|
|
10
|
-
return {
|
|
11
|
-
activate() {
|
|
12
|
-
i.captureReturnFocus(), r.activate(), i.applyInitialFocus();
|
|
13
|
-
},
|
|
14
|
-
deactivate() {
|
|
15
|
-
i.cancelInitialFocus(), r.deactivate(), i.restoreFocus();
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
//#endregion
|
|
20
|
-
export { n as createDialogFocusControl };
|
|
21
|
-
|
|
22
|
-
//# sourceMappingURL=dialog-focus.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-focus.js","names":[],"sources":["../../src/headless/dialog-focus.ts"],"sourcesContent":["import { createFocusManager } from './focus';\nimport { createFocusTrap } from './focus-trap';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DialogFocusControlOptions = {\n /** Returns the container element (dialog or shadow root) for focus trapping. */\n getContainer: () => HTMLElement | ShadowRoot | null;\n /** Returns the CSS selector for the element to focus on open (e.g. `'[autofocus]'`). */\n getInitialFocusSelector: () => string | undefined;\n /** Returns whether focus should be restored to the trigger on close. */\n getReturnFocus: () => boolean | undefined;\n /** Host element used to resolve `getInitialFocusSelector`. */\n host: HTMLElement;\n /** When provided, the trap only intercepts Tab when this returns `true`. */\n trapEnabled?: () => boolean;\n};\n\nexport type DialogFocusControl = {\n /** Capture return focus, activate the trap, and apply initial focus. */\n activate(): void;\n /** Deactivate the trap and restore focus. */\n deactivate(): void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Combines {@link createFocusTrap} and {@link createFocusManager} into a single\n * `activate / deactivate` API suited for modal dialogs and drawers.\n *\n * @example\n * ```ts\n * const focusCtrl = createDialogFocusControl({\n * getContainer: () => dialog,\n * getInitialFocusSelector: () => props['initial-focus'].value,\n * getReturnFocus: () => props['return-focus'].value !== false,\n * host: el,\n * });\n *\n * // On open:\n * focusCtrl.activate();\n *\n * // On close:\n * focusCtrl.deactivate();\n * ```\n */\nexport const createDialogFocusControl = (options: DialogFocusControlOptions): DialogFocusControl => {\n const trap = createFocusTrap(options.getContainer, { enabled: options.trapEnabled });\n\n const manager = createFocusManager({\n getInitialFocusSelector: options.getInitialFocusSelector,\n getReturnFocus: options.getReturnFocus,\n host: options.host,\n });\n\n return {\n activate() {\n manager.captureReturnFocus();\n trap.activate();\n manager.applyInitialFocus();\n },\n\n deactivate() {\n manager.cancelInitialFocus();\n trap.deactivate();\n manager.restoreFocus();\n },\n };\n};\n"],"mappings":";;;AA+CA,IAAa,KAA4B,MAA2D;CAClG,IAAM,IAAO,EAAgB,EAAQ,cAAc,EAAE,SAAS,EAAQ,YAAY,CAAC,GAE7E,IAAU,EAAmB;EACjC,yBAAyB,EAAQ;EACjC,gBAAgB,EAAQ;EACxB,MAAM,EAAQ;CAChB,CAAC;CAED,OAAO;EACL,WAAW;GAGT,AAFA,EAAQ,mBAAmB,GAC3B,EAAK,SAAS,GACd,EAAQ,kBAAkB;EAC5B;EAEA,aAAa;GAGX,AAFA,EAAQ,mBAAmB,GAC3B,EAAK,WAAW,GAChB,EAAQ,aAAa;EACvB;CACF;AACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var e=[`a[href]`,`area[href]`,`button:not([disabled])`,`details > summary:not([disabled])`,`iframe`,`input:not([disabled])`,`select:not([disabled])`,`textarea:not([disabled])`,`[contenteditable]:not([contenteditable="false"])`,`[tabindex]:not([tabindex="-1"])`,`[role="button"]:not([disabled]):not([aria-disabled="true"])`,`[role="link"]:not([aria-disabled="true"])`,`[role="menuitem"]:not([aria-disabled="true"])`,`[role="menuitemcheckbox"]:not([aria-disabled="true"])`,`[role="menuitemradio"]:not([aria-disabled="true"])`,`[role="option"]:not([aria-disabled="true"])`,`[role="tab"]:not([aria-disabled="true"])`].join(`,`),t=(t,n={})=>{let r=!1,i=()=>{let n=t();return n?Array.from(n.querySelectorAll(e)).filter(e=>!e.closest(`[aria-hidden="true"]`)&&!e.closest(`[hidden]`)&&!e.closest(`[inert]`)):[]},a=e=>{if(!r||n.enabled?.()===!1||e.key!==`Tab`)return;let t=i();if(t.length===0){e.preventDefault();return}let a=t[0],o=t[t.length-1],s=e.target??document.activeElement;e.shiftKey?(s===a||!t.includes(s))&&(e.preventDefault(),o.focus()):(s===o||!t.includes(s))&&(e.preventDefault(),a.focus())},o=()=>{r||(r=!0,document.addEventListener(`keydown`,a,!0))},s=()=>{r&&(r=!1,document.removeEventListener(`keydown`,a,!0))};return n.signal&&!n.signal.aborted&&n.signal.addEventListener(`abort`,s,{once:!0}),{activate:o,get active(){return r},deactivate:s,dispose:s,[Symbol.dispose]:s}};exports.createFocusTrap=t;
|
|
2
|
-
//# sourceMappingURL=focus-trap.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus-trap.cjs","names":[],"sources":["../../src/headless/focus-trap.ts"],"sourcesContent":["// ── Focus Trap ────────────────────────────────────────────────────────────────\n// Implements the WAI-ARIA modal dialog focus-containment pattern.\n//\n// When active, Tab/Shift-Tab wrap within the container's focusable descendants\n// instead of leaving it. The focusable list is re-queried on every Tab keydown\n// so DOM changes (e.g. lazy-rendered content) are always reflected without a\n// MutationObserver.\n//\n// Usage (inside a ore component):\n// ```ts\n// const trap = createFocusTrap(() => dialogEl);\n// onOpen: () => trap.activate(),\n// onClose: () => trap.deactivate(),\n// ```\n\n// ── Constants ─────────────────────────────────────────────────────────────────\n\n/**\n * CSS selector matching all focusable elements, including:\n * - Native HTML interactive elements\n * - Elements with explicit `tabindex` (covers custom elements that correctly manage focus)\n * - Custom elements using ARIA interactive roles that are inherently focusable\n * but may not carry a native `tabindex` attribute\n *\n * Note: `[tabindex]:not([tabindex=\"-1\"])` already covers any element that\n * explicitly opts into the tab order. The ARIA role selectors below additionally\n * capture elements that rely on the implicit focusability of their role\n * without a redundant `tabindex=\"0\"` attribute.\n */\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'details > summary:not([disabled])',\n 'iframe',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[contenteditable]:not([contenteditable=\"false\"])',\n '[tabindex]:not([tabindex=\"-1\"])',\n // ARIA interactive roles that should participate in focus order.\n // These cover custom components that set role but not explicit tabindex.\n '[role=\"button\"]:not([disabled]):not([aria-disabled=\"true\"])',\n '[role=\"link\"]:not([aria-disabled=\"true\"])',\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])',\n '[role=\"menuitemcheckbox\"]:not([aria-disabled=\"true\"])',\n '[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])',\n '[role=\"option\"]:not([aria-disabled=\"true\"])',\n '[role=\"tab\"]:not([aria-disabled=\"true\"])',\n // Note: [role=\"gridcell\"] and [role=\"row\"] are intentionally omitted — they\n // participate in focus order only when an explicit tabindex is set, which is\n // already caught by the [tabindex]:not([tabindex=\"-1\"]) selector above.\n].join(',');\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FocusTrapOptions = {\n /**\n * When provided, the trap only processes events when this returns `true`.\n * Useful to pause trapping while an inner dialog is open.\n */\n enabled?: () => boolean;\n /**\n * Optional `AbortSignal`. When aborted, `deactivate()` is called automatically.\n * Prevents global `keydown` listener leaks if the component is destroyed while\n * the trap is still active.\n */\n signal?: AbortSignal;\n};\n\nexport type FocusTrap = {\n [Symbol.dispose](): void;\n /** Start trapping Tab/Shift-Tab. Safe to call when already active. */\n activate(): void;\n /** Whether the trap is currently active. */\n readonly active: boolean;\n /** Stop trapping. Safe to call when already inactive. */\n deactivate(): void;\n /** Alias for `deactivate()`. Conforms to the monorepo disposal convention. */\n dispose(): void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Creates a WAI-ARIA modal focus trap for a container element.\n *\n * When active, Tab wraps from the last focusable child to the first, and\n * Shift-Tab wraps in reverse. The focusable list is re-queried live on each\n * Tab keydown — no MutationObserver required.\n *\n * The container itself is queried lazily via `getContainer()` so it may be\n * `null` at construction time (the typical case when the container is inside\n * an initially-hidden overlay).\n *\n * @example\n * ```ts\n * const trap = createFocusTrap(() => dialogEl);\n *\n * onOpen: () => trap.activate(),\n * onClose: () => trap.deactivate(),\n * ```\n */\nexport const createFocusTrap = (\n getContainer: () => HTMLElement | ShadowRoot | null,\n options: FocusTrapOptions = {},\n): FocusTrap => {\n let _active = false;\n\n const getFocusable = (): HTMLElement[] => {\n const container = getContainer();\n\n if (!container) return [];\n\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n // Exclude elements hidden from the accessibility tree or removed from tab order.\n // aria-hidden=\"true\" and [hidden] have long been standard; [inert] is the\n // modern successor that browsers honour natively from 2022+.\n (el) => !el.closest('[aria-hidden=\"true\"]') && !el.closest('[hidden]') && !el.closest('[inert]'),\n );\n };\n\n const handleKeydown = (event: KeyboardEvent): void => {\n if (!_active) return;\n\n if (options.enabled?.() === false) return;\n\n if (event.key !== 'Tab') return;\n\n const focusable = getFocusable();\n\n if (focusable.length === 0) {\n // Prevent focus from escaping the empty container.\n event.preventDefault();\n\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n // Prefer event.target over document.activeElement: the capture-phase handler\n // fires before focus has moved in some environments (e.g. jsdom).\n const current = (event.target as HTMLElement) ?? document.activeElement;\n\n if (event.shiftKey) {\n // Shift+Tab from first (or outside) → wrap to last.\n if (current === first || !focusable.includes(current as HTMLElement)) {\n event.preventDefault();\n last.focus();\n }\n } else {\n // Tab from last (or outside) → wrap to first.\n if (current === last || !focusable.includes(current as HTMLElement)) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n\n const activate = (): void => {\n if (_active) return;\n\n _active = true;\n document.addEventListener('keydown', handleKeydown, true);\n };\n\n const deactivate = (): void => {\n if (!_active) return;\n\n _active = false;\n document.removeEventListener('keydown', handleKeydown, true);\n };\n\n if (options.signal && !options.signal.aborted) {\n options.signal.addEventListener('abort', deactivate, { once: true });\n }\n\n return {\n activate,\n get active() {\n return _active;\n },\n deactivate,\n dispose: deactivate,\n [Symbol.dispose]: deactivate,\n };\n};\n"],"mappings":"AA6BA,IAAM,EAAqB,CACzB,UACA,aACA,yBACA,oCACA,SACA,wBACA,yBACA,2BACA,mDACA,kCAGA,8DACA,4CACA,gDACA,wDACA,qDACA,8CACA,0CAIF,CAAC,CAAC,KAAK,GAAG,EAmDG,GACX,EACA,EAA4B,CAAC,IACf,CACd,IAAI,EAAU,GAER,MAAoC,CACxC,IAAM,EAAY,EAAa,EAI/B,OAFK,EAEE,MAAM,KAAK,EAAU,iBAA8B,CAAkB,CAAC,CAAC,CAAC,OAI5E,GAAO,CAAC,EAAG,QAAQ,sBAAsB,GAAK,CAAC,EAAG,QAAQ,UAAU,GAAK,CAAC,EAAG,QAAQ,SAAS,CACjG,EAPuB,CAAC,CAQ1B,EAEM,EAAiB,GAA+B,CAKpD,GAJI,CAAC,GAED,EAAQ,UAAU,IAAM,IAExB,EAAM,MAAQ,MAAO,OAEzB,IAAM,EAAY,EAAa,EAE/B,GAAI,EAAU,SAAW,EAAG,CAE1B,EAAM,eAAe,EAErB,MACF,CAEA,IAAM,EAAQ,EAAU,GAClB,EAAO,EAAU,EAAU,OAAS,GAGpC,EAAW,EAAM,QAA0B,SAAS,cAEtD,EAAM,UAEJ,IAAY,GAAS,CAAC,EAAU,SAAS,CAAsB,KACjE,EAAM,eAAe,EACrB,EAAK,MAAM,IAIT,IAAY,GAAQ,CAAC,EAAU,SAAS,CAAsB,KAChE,EAAM,eAAe,EACrB,EAAM,MAAM,EAGlB,EAEM,MAAuB,CACvB,IAEJ,EAAU,GACV,SAAS,iBAAiB,UAAW,EAAe,EAAI,EAC1D,EAEM,MAAyB,CACxB,IAEL,EAAU,GACV,SAAS,oBAAoB,UAAW,EAAe,EAAI,EAC7D,EAMA,OAJI,EAAQ,QAAU,CAAC,EAAQ,OAAO,SACpC,EAAQ,OAAO,iBAAiB,QAAS,EAAY,CAAE,KAAM,EAAK,CAAC,EAG9D,CACL,WACA,IAAI,QAAS,CACX,OAAO,CACT,EACA,aACA,QAAS,GACR,OAAO,SAAU,CACpB,CACF"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export type FocusTrapOptions = {
|
|
2
|
-
/**
|
|
3
|
-
* When provided, the trap only processes events when this returns `true`.
|
|
4
|
-
* Useful to pause trapping while an inner dialog is open.
|
|
5
|
-
*/
|
|
6
|
-
enabled?: () => boolean;
|
|
7
|
-
/**
|
|
8
|
-
* Optional `AbortSignal`. When aborted, `deactivate()` is called automatically.
|
|
9
|
-
* Prevents global `keydown` listener leaks if the component is destroyed while
|
|
10
|
-
* the trap is still active.
|
|
11
|
-
*/
|
|
12
|
-
signal?: AbortSignal;
|
|
13
|
-
};
|
|
14
|
-
export type FocusTrap = {
|
|
15
|
-
[Symbol.dispose](): void;
|
|
16
|
-
/** Start trapping Tab/Shift-Tab. Safe to call when already active. */
|
|
17
|
-
activate(): void;
|
|
18
|
-
/** Whether the trap is currently active. */
|
|
19
|
-
readonly active: boolean;
|
|
20
|
-
/** Stop trapping. Safe to call when already inactive. */
|
|
21
|
-
deactivate(): void;
|
|
22
|
-
/** Alias for `deactivate()`. Conforms to the monorepo disposal convention. */
|
|
23
|
-
dispose(): void;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Creates a WAI-ARIA modal focus trap for a container element.
|
|
27
|
-
*
|
|
28
|
-
* When active, Tab wraps from the last focusable child to the first, and
|
|
29
|
-
* Shift-Tab wraps in reverse. The focusable list is re-queried live on each
|
|
30
|
-
* Tab keydown — no MutationObserver required.
|
|
31
|
-
*
|
|
32
|
-
* The container itself is queried lazily via `getContainer()` so it may be
|
|
33
|
-
* `null` at construction time (the typical case when the container is inside
|
|
34
|
-
* an initially-hidden overlay).
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```ts
|
|
38
|
-
* const trap = createFocusTrap(() => dialogEl);
|
|
39
|
-
*
|
|
40
|
-
* onOpen: () => trap.activate(),
|
|
41
|
-
* onClose: () => trap.deactivate(),
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export declare const createFocusTrap: (getContainer: () => HTMLElement | ShadowRoot | null, options?: FocusTrapOptions) => FocusTrap;
|
|
45
|
-
//# sourceMappingURL=focus-trap.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus-trap.d.ts","sourceRoot":"","sources":["../../src/headless/focus-trap.ts"],"names":[],"mappings":"AAwDA,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,sEAAsE;IACtE,QAAQ,IAAI,IAAI,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,UAAU,IAAI,IAAI,CAAC;IACnB,8EAA8E;IAC9E,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,eAAe,GAC1B,cAAc,MAAM,WAAW,GAAG,UAAU,GAAG,IAAI,EACnD,UAAS,gBAAqB,KAC7B,SAgFF,CAAC"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
//#region src/headless/focus-trap.ts
|
|
2
|
-
var e = [
|
|
3
|
-
"a[href]",
|
|
4
|
-
"area[href]",
|
|
5
|
-
"button:not([disabled])",
|
|
6
|
-
"details > summary:not([disabled])",
|
|
7
|
-
"iframe",
|
|
8
|
-
"input:not([disabled])",
|
|
9
|
-
"select:not([disabled])",
|
|
10
|
-
"textarea:not([disabled])",
|
|
11
|
-
"[contenteditable]:not([contenteditable=\"false\"])",
|
|
12
|
-
"[tabindex]:not([tabindex=\"-1\"])",
|
|
13
|
-
"[role=\"button\"]:not([disabled]):not([aria-disabled=\"true\"])",
|
|
14
|
-
"[role=\"link\"]:not([aria-disabled=\"true\"])",
|
|
15
|
-
"[role=\"menuitem\"]:not([aria-disabled=\"true\"])",
|
|
16
|
-
"[role=\"menuitemcheckbox\"]:not([aria-disabled=\"true\"])",
|
|
17
|
-
"[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])",
|
|
18
|
-
"[role=\"option\"]:not([aria-disabled=\"true\"])",
|
|
19
|
-
"[role=\"tab\"]:not([aria-disabled=\"true\"])"
|
|
20
|
-
].join(","), t = (t, n = {}) => {
|
|
21
|
-
let r = !1, i = () => {
|
|
22
|
-
let n = t();
|
|
23
|
-
return n ? Array.from(n.querySelectorAll(e)).filter((e) => !e.closest("[aria-hidden=\"true\"]") && !e.closest("[hidden]") && !e.closest("[inert]")) : [];
|
|
24
|
-
}, a = (e) => {
|
|
25
|
-
if (!r || n.enabled?.() === !1 || e.key !== "Tab") return;
|
|
26
|
-
let t = i();
|
|
27
|
-
if (t.length === 0) {
|
|
28
|
-
e.preventDefault();
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
let a = t[0], o = t[t.length - 1], s = e.target ?? document.activeElement;
|
|
32
|
-
e.shiftKey ? (s === a || !t.includes(s)) && (e.preventDefault(), o.focus()) : (s === o || !t.includes(s)) && (e.preventDefault(), a.focus());
|
|
33
|
-
}, o = () => {
|
|
34
|
-
r || (r = !0, document.addEventListener("keydown", a, !0));
|
|
35
|
-
}, s = () => {
|
|
36
|
-
r && (r = !1, document.removeEventListener("keydown", a, !0));
|
|
37
|
-
};
|
|
38
|
-
return n.signal && !n.signal.aborted && n.signal.addEventListener("abort", s, { once: !0 }), {
|
|
39
|
-
activate: o,
|
|
40
|
-
get active() {
|
|
41
|
-
return r;
|
|
42
|
-
},
|
|
43
|
-
deactivate: s,
|
|
44
|
-
dispose: s,
|
|
45
|
-
[Symbol.dispose]: s
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
//#endregion
|
|
49
|
-
export { t as createFocusTrap };
|
|
50
|
-
|
|
51
|
-
//# sourceMappingURL=focus-trap.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus-trap.js","names":[],"sources":["../../src/headless/focus-trap.ts"],"sourcesContent":["// ── Focus Trap ────────────────────────────────────────────────────────────────\n// Implements the WAI-ARIA modal dialog focus-containment pattern.\n//\n// When active, Tab/Shift-Tab wrap within the container's focusable descendants\n// instead of leaving it. The focusable list is re-queried on every Tab keydown\n// so DOM changes (e.g. lazy-rendered content) are always reflected without a\n// MutationObserver.\n//\n// Usage (inside a ore component):\n// ```ts\n// const trap = createFocusTrap(() => dialogEl);\n// onOpen: () => trap.activate(),\n// onClose: () => trap.deactivate(),\n// ```\n\n// ── Constants ─────────────────────────────────────────────────────────────────\n\n/**\n * CSS selector matching all focusable elements, including:\n * - Native HTML interactive elements\n * - Elements with explicit `tabindex` (covers custom elements that correctly manage focus)\n * - Custom elements using ARIA interactive roles that are inherently focusable\n * but may not carry a native `tabindex` attribute\n *\n * Note: `[tabindex]:not([tabindex=\"-1\"])` already covers any element that\n * explicitly opts into the tab order. The ARIA role selectors below additionally\n * capture elements that rely on the implicit focusability of their role\n * without a redundant `tabindex=\"0\"` attribute.\n */\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'details > summary:not([disabled])',\n 'iframe',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[contenteditable]:not([contenteditable=\"false\"])',\n '[tabindex]:not([tabindex=\"-1\"])',\n // ARIA interactive roles that should participate in focus order.\n // These cover custom components that set role but not explicit tabindex.\n '[role=\"button\"]:not([disabled]):not([aria-disabled=\"true\"])',\n '[role=\"link\"]:not([aria-disabled=\"true\"])',\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])',\n '[role=\"menuitemcheckbox\"]:not([aria-disabled=\"true\"])',\n '[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])',\n '[role=\"option\"]:not([aria-disabled=\"true\"])',\n '[role=\"tab\"]:not([aria-disabled=\"true\"])',\n // Note: [role=\"gridcell\"] and [role=\"row\"] are intentionally omitted — they\n // participate in focus order only when an explicit tabindex is set, which is\n // already caught by the [tabindex]:not([tabindex=\"-1\"]) selector above.\n].join(',');\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FocusTrapOptions = {\n /**\n * When provided, the trap only processes events when this returns `true`.\n * Useful to pause trapping while an inner dialog is open.\n */\n enabled?: () => boolean;\n /**\n * Optional `AbortSignal`. When aborted, `deactivate()` is called automatically.\n * Prevents global `keydown` listener leaks if the component is destroyed while\n * the trap is still active.\n */\n signal?: AbortSignal;\n};\n\nexport type FocusTrap = {\n [Symbol.dispose](): void;\n /** Start trapping Tab/Shift-Tab. Safe to call when already active. */\n activate(): void;\n /** Whether the trap is currently active. */\n readonly active: boolean;\n /** Stop trapping. Safe to call when already inactive. */\n deactivate(): void;\n /** Alias for `deactivate()`. Conforms to the monorepo disposal convention. */\n dispose(): void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Creates a WAI-ARIA modal focus trap for a container element.\n *\n * When active, Tab wraps from the last focusable child to the first, and\n * Shift-Tab wraps in reverse. The focusable list is re-queried live on each\n * Tab keydown — no MutationObserver required.\n *\n * The container itself is queried lazily via `getContainer()` so it may be\n * `null` at construction time (the typical case when the container is inside\n * an initially-hidden overlay).\n *\n * @example\n * ```ts\n * const trap = createFocusTrap(() => dialogEl);\n *\n * onOpen: () => trap.activate(),\n * onClose: () => trap.deactivate(),\n * ```\n */\nexport const createFocusTrap = (\n getContainer: () => HTMLElement | ShadowRoot | null,\n options: FocusTrapOptions = {},\n): FocusTrap => {\n let _active = false;\n\n const getFocusable = (): HTMLElement[] => {\n const container = getContainer();\n\n if (!container) return [];\n\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n // Exclude elements hidden from the accessibility tree or removed from tab order.\n // aria-hidden=\"true\" and [hidden] have long been standard; [inert] is the\n // modern successor that browsers honour natively from 2022+.\n (el) => !el.closest('[aria-hidden=\"true\"]') && !el.closest('[hidden]') && !el.closest('[inert]'),\n );\n };\n\n const handleKeydown = (event: KeyboardEvent): void => {\n if (!_active) return;\n\n if (options.enabled?.() === false) return;\n\n if (event.key !== 'Tab') return;\n\n const focusable = getFocusable();\n\n if (focusable.length === 0) {\n // Prevent focus from escaping the empty container.\n event.preventDefault();\n\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n // Prefer event.target over document.activeElement: the capture-phase handler\n // fires before focus has moved in some environments (e.g. jsdom).\n const current = (event.target as HTMLElement) ?? document.activeElement;\n\n if (event.shiftKey) {\n // Shift+Tab from first (or outside) → wrap to last.\n if (current === first || !focusable.includes(current as HTMLElement)) {\n event.preventDefault();\n last.focus();\n }\n } else {\n // Tab from last (or outside) → wrap to first.\n if (current === last || !focusable.includes(current as HTMLElement)) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n\n const activate = (): void => {\n if (_active) return;\n\n _active = true;\n document.addEventListener('keydown', handleKeydown, true);\n };\n\n const deactivate = (): void => {\n if (!_active) return;\n\n _active = false;\n document.removeEventListener('keydown', handleKeydown, true);\n };\n\n if (options.signal && !options.signal.aborted) {\n options.signal.addEventListener('abort', deactivate, { once: true });\n }\n\n return {\n activate,\n get active() {\n return _active;\n },\n deactivate,\n dispose: deactivate,\n [Symbol.dispose]: deactivate,\n };\n};\n"],"mappings":";AA6BA,IAAM,IAAqB;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;AAIF,CAAC,CAAC,KAAK,GAAG,GAmDG,KACX,GACA,IAA4B,CAAC,MACf;CACd,IAAI,IAAU,IAER,UAAoC;EACxC,IAAM,IAAY,EAAa;EAI/B,OAFK,IAEE,MAAM,KAAK,EAAU,iBAA8B,CAAkB,CAAC,CAAC,CAAC,QAI5E,MAAO,CAAC,EAAG,QAAQ,wBAAsB,KAAK,CAAC,EAAG,QAAQ,UAAU,KAAK,CAAC,EAAG,QAAQ,SAAS,CACjG,IAPuB,CAAC;CAQ1B,GAEM,KAAiB,MAA+B;EAKpD,IAJI,CAAC,KAED,EAAQ,UAAU,MAAM,MAExB,EAAM,QAAQ,OAAO;EAEzB,IAAM,IAAY,EAAa;EAE/B,IAAI,EAAU,WAAW,GAAG;GAE1B,EAAM,eAAe;GAErB;EACF;EAEA,IAAM,IAAQ,EAAU,IAClB,IAAO,EAAU,EAAU,SAAS,IAGpC,IAAW,EAAM,UAA0B,SAAS;EAE1D,AAAI,EAAM,YAEJ,MAAY,KAAS,CAAC,EAAU,SAAS,CAAsB,OACjE,EAAM,eAAe,GACrB,EAAK,MAAM,MAIT,MAAY,KAAQ,CAAC,EAAU,SAAS,CAAsB,OAChE,EAAM,eAAe,GACrB,EAAM,MAAM;CAGlB,GAEM,UAAuB;EACvB,MAEJ,IAAU,IACV,SAAS,iBAAiB,WAAW,GAAe,EAAI;CAC1D,GAEM,UAAyB;EACxB,MAEL,IAAU,IACV,SAAS,oBAAoB,WAAW,GAAe,EAAI;CAC7D;CAMA,OAJI,EAAQ,UAAU,CAAC,EAAQ,OAAO,WACpC,EAAQ,OAAO,iBAAiB,SAAS,GAAY,EAAE,MAAM,GAAK,CAAC,GAG9D;EACL;EACA,IAAI,SAAS;GACX,OAAO;EACT;EACA;EACA,SAAS;GACR,OAAO,UAAU;CACpB;AACF"}
|