@pzerelles/headlessui-svelte 2.1.1-next.1 → 2.1.2-next.3

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.
Files changed (178) hide show
  1. package/dist/button/Button.svelte +6 -10
  2. package/dist/button/Button.svelte.d.ts +34 -26
  3. package/dist/checkbox/Checkbox.svelte +40 -22
  4. package/dist/checkbox/Checkbox.svelte.d.ts +44 -28
  5. package/dist/close-button/CloseButton.svelte +5 -4
  6. package/dist/close-button/CloseButton.svelte.d.ts +36 -13
  7. package/dist/combobox/Combobox.svelte +2 -2
  8. package/dist/combobox/Combobox.svelte.d.ts +9 -9
  9. package/dist/data-interactive/DataInteractive.svelte +41 -0
  10. package/dist/data-interactive/DataInteractive.svelte.d.ts +39 -0
  11. package/dist/data-interactive/index.d.ts +1 -0
  12. package/dist/data-interactive/index.js +1 -0
  13. package/dist/description/Description.svelte +10 -53
  14. package/dist/description/Description.svelte.d.ts +15 -32
  15. package/dist/description/context.svelte.d.ts +17 -0
  16. package/dist/description/context.svelte.js +51 -0
  17. package/dist/dialog/Dialog.svelte +51 -0
  18. package/dist/dialog/Dialog.svelte.d.ts +60 -0
  19. package/dist/dialog/DialogBackdrop.svelte +39 -0
  20. package/dist/dialog/DialogBackdrop.svelte.d.ts +38 -0
  21. package/dist/dialog/DialogPanel.svelte +46 -0
  22. package/dist/dialog/DialogPanel.svelte.d.ts +40 -0
  23. package/dist/dialog/DialogTitle.svelte +29 -0
  24. package/dist/dialog/DialogTitle.svelte.d.ts +34 -0
  25. package/dist/dialog/InternalDialog.svelte +233 -0
  26. package/dist/dialog/InternalDialog.svelte.d.ts +42 -0
  27. package/dist/dialog/context.svelte.d.ts +15 -0
  28. package/dist/dialog/context.svelte.js +16 -0
  29. package/dist/dialog/index.d.ts +4 -0
  30. package/dist/dialog/index.js +4 -0
  31. package/dist/field/Field.svelte +8 -10
  32. package/dist/field/Field.svelte.d.ts +21 -17
  33. package/dist/fieldset/Fieldset.svelte +11 -9
  34. package/dist/fieldset/Fieldset.svelte.d.ts +21 -17
  35. package/dist/focus-trap/FocusTrap.svelte +332 -0
  36. package/dist/focus-trap/FocusTrap.svelte.d.ts +58 -0
  37. package/dist/hooks/use-controllable.svelte.d.ts +1 -1
  38. package/dist/hooks/use-controllable.svelte.js +3 -3
  39. package/dist/hooks/use-escape.svelte.d.ts +5 -0
  40. package/dist/hooks/use-escape.svelte.js +26 -0
  41. package/dist/hooks/use-event-listener.svelte.d.ts +6 -0
  42. package/dist/hooks/use-event-listener.svelte.js +12 -0
  43. package/dist/hooks/use-inert-others.svelte.d.ts +2 -2
  44. package/dist/hooks/use-inert-others.svelte.js +3 -3
  45. package/dist/hooks/use-is-mounted.svelte.d.ts +3 -0
  46. package/dist/hooks/use-is-mounted.svelte.js +14 -0
  47. package/dist/hooks/use-is-touch-device.svelte.d.ts +3 -0
  48. package/dist/hooks/use-is-touch-device.svelte.js +20 -0
  49. package/dist/hooks/use-root-containers.svelte.d.ts +9 -0
  50. package/dist/hooks/use-root-containers.svelte.js +50 -0
  51. package/dist/hooks/use-tab-direction.svelte.d.ts +7 -0
  52. package/dist/hooks/use-tab-direction.svelte.js +25 -0
  53. package/dist/hooks/use-transition.svelte.js +14 -13
  54. package/dist/hooks/use-tree-walker.svelte.d.ts +8 -0
  55. package/dist/hooks/use-tree-walker.svelte.js +19 -0
  56. package/dist/hooks/use-watch.svelte.d.ts +4 -0
  57. package/dist/hooks/use-watch.svelte.js +16 -0
  58. package/dist/hooks/use-window-event.svelte.d.ts +6 -0
  59. package/dist/hooks/use-window-event.svelte.js +12 -0
  60. package/dist/index.d.ts +10 -0
  61. package/dist/index.js +10 -0
  62. package/dist/input/Input.svelte +59 -0
  63. package/dist/input/Input.svelte.d.ts +52 -0
  64. package/dist/input/index.d.ts +1 -0
  65. package/dist/input/index.js +1 -0
  66. package/dist/internal/FocusSentinel.svelte.d.ts +4 -1
  67. package/dist/internal/ForcePortalRoot.svelte +6 -0
  68. package/dist/internal/ForcePortalRoot.svelte.d.ts +22 -0
  69. package/dist/internal/FormFields.svelte.d.ts +4 -1
  70. package/dist/internal/FormResolver.svelte.d.ts +4 -1
  71. package/dist/internal/Hidden.svelte +5 -9
  72. package/dist/internal/Hidden.svelte.d.ts +17 -10
  73. package/dist/internal/HoistFormFields.svelte.d.ts +4 -1
  74. package/dist/internal/MainTreeProvider.svelte +45 -0
  75. package/dist/internal/MainTreeProvider.svelte.d.ts +31 -0
  76. package/dist/internal/Portal.svelte.d.ts +4 -1
  77. package/dist/internal/close-provider.d.ts +7 -0
  78. package/dist/internal/close-provider.js +7 -0
  79. package/dist/internal/floating.svelte.d.ts +13 -8
  80. package/dist/internal/floating.svelte.js +197 -186
  81. package/dist/internal/id.d.ts +1 -1
  82. package/dist/internal/open-closed.d.ts +1 -1
  83. package/dist/internal/open-closed.js +1 -1
  84. package/dist/label/Label.svelte +12 -61
  85. package/dist/label/Label.svelte.d.ts +19 -32
  86. package/dist/label/context.svelte.d.ts +17 -0
  87. package/dist/label/context.svelte.js +56 -0
  88. package/dist/legend/Legend.svelte +4 -3
  89. package/dist/legend/Legend.svelte.d.ts +33 -15
  90. package/dist/listbox/Listbox.svelte +6 -9
  91. package/dist/listbox/Listbox.svelte.d.ts +29 -10
  92. package/dist/listbox/ListboxButton.svelte +6 -8
  93. package/dist/listbox/ListboxButton.svelte.d.ts +18 -7
  94. package/dist/listbox/ListboxOption.svelte +4 -6
  95. package/dist/listbox/ListboxOption.svelte.d.ts +22 -11
  96. package/dist/listbox/ListboxOptions.svelte +21 -19
  97. package/dist/listbox/ListboxOptions.svelte.d.ts +23 -7
  98. package/dist/listbox/ListboxSelectedOption.svelte +17 -7
  99. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +23 -13
  100. package/dist/menu/Menu.svelte +235 -0
  101. package/dist/menu/Menu.svelte.d.ts +42 -0
  102. package/dist/menu/MenuButton.svelte +127 -0
  103. package/dist/menu/MenuButton.svelte.d.ts +52 -0
  104. package/dist/menu/MenuHeading.svelte +19 -0
  105. package/dist/menu/MenuHeading.svelte.d.ts +39 -0
  106. package/dist/menu/MenuItem.svelte +114 -0
  107. package/dist/menu/MenuItem.svelte.d.ts +49 -0
  108. package/dist/menu/MenuItems.svelte +244 -0
  109. package/dist/menu/MenuItems.svelte.d.ts +55 -0
  110. package/dist/menu/MenuSection.svelte +14 -0
  111. package/dist/menu/MenuSection.svelte.d.ts +35 -0
  112. package/dist/menu/MenuSeparator.svelte +9 -0
  113. package/dist/menu/MenuSeparator.svelte.d.ts +35 -0
  114. package/dist/menu/context.svelte.d.ts +47 -0
  115. package/dist/menu/context.svelte.js +21 -0
  116. package/dist/menu/index.d.ts +7 -0
  117. package/dist/menu/index.js +7 -0
  118. package/dist/portal/InternalPortal.svelte +22 -33
  119. package/dist/portal/InternalPortal.svelte.d.ts +16 -7
  120. package/dist/portal/Portal.svelte +4 -8
  121. package/dist/portal/Portal.svelte.d.ts +6 -6
  122. package/dist/portal/PortalGroup.svelte +5 -6
  123. package/dist/portal/PortalGroup.svelte.d.ts +16 -7
  124. package/dist/switch/Switch.svelte +11 -17
  125. package/dist/switch/Switch.svelte.d.ts +23 -6
  126. package/dist/switch/SwitchGroup.svelte +7 -8
  127. package/dist/switch/SwitchGroup.svelte.d.ts +14 -7
  128. package/dist/tabs/Tab.svelte +9 -14
  129. package/dist/tabs/Tab.svelte.d.ts +18 -6
  130. package/dist/tabs/TabGroup.svelte +20 -23
  131. package/dist/tabs/TabGroup.svelte.d.ts +19 -6
  132. package/dist/tabs/TabList.svelte +5 -7
  133. package/dist/tabs/TabList.svelte.d.ts +13 -6
  134. package/dist/tabs/TabPanel.svelte +30 -32
  135. package/dist/tabs/TabPanel.svelte.d.ts +19 -6
  136. package/dist/tabs/TabPanels.svelte +5 -6
  137. package/dist/tabs/TabPanels.svelte.d.ts +13 -6
  138. package/dist/textarea/Textarea.svelte +67 -0
  139. package/dist/textarea/Textarea.svelte.d.ts +47 -0
  140. package/dist/textarea/index.d.ts +1 -0
  141. package/dist/textarea/index.js +1 -0
  142. package/dist/transition/InternalTransitionChild.svelte +178 -0
  143. package/dist/transition/InternalTransitionChild.svelte.d.ts +55 -0
  144. package/dist/transition/Transition.svelte +89 -0
  145. package/dist/transition/Transition.svelte.d.ts +42 -0
  146. package/dist/transition/TransitionChild.svelte +16 -0
  147. package/dist/transition/TransitionChild.svelte.d.ts +44 -0
  148. package/dist/transition/context.svelte.d.ts +64 -0
  149. package/dist/transition/context.svelte.js +120 -0
  150. package/dist/transition/index.d.ts +2 -0
  151. package/dist/transition/index.js +2 -0
  152. package/dist/utils/ElementOrComponent.svelte +26 -0
  153. package/dist/utils/ElementOrComponent.svelte.d.ts +56 -0
  154. package/dist/utils/Generic.svelte +44 -0
  155. package/dist/utils/Generic.svelte.d.ts +35 -0
  156. package/dist/utils/StableCollection.svelte +1 -1
  157. package/dist/utils/StableCollection.svelte.d.ts +4 -1
  158. package/dist/utils/active-element-history.d.ts +1 -0
  159. package/dist/utils/active-element-history.js +35 -0
  160. package/dist/utils/alternative-types.d.ts +21 -0
  161. package/dist/utils/alternative-types.js +1 -0
  162. package/dist/utils/class-names.d.ts +1 -0
  163. package/dist/utils/class-names.js +10 -0
  164. package/dist/utils/focus-management.d.ts +2 -1
  165. package/dist/utils/focus-management.js +13 -13
  166. package/dist/utils/on-document-ready.d.ts +1 -0
  167. package/dist/utils/on-document-ready.js +12 -0
  168. package/dist/utils/render.d.ts +3 -0
  169. package/dist/utils/render.js +63 -0
  170. package/dist/utils/state.d.ts +7 -1
  171. package/dist/utils/state.js +10 -6
  172. package/dist/utils/types.d.ts +14 -17
  173. package/dist/utils/types.js +0 -5
  174. package/package.json +26 -25
  175. package/dist/tabs/Button.svelte +0 -65
  176. package/dist/tabs/Button.svelte.d.ts +0 -39
  177. package/dist/utils/close.d.ts +0 -2
  178. package/dist/utils/close.js +0 -3
@@ -0,0 +1,332 @@
1
+ <script lang="ts" module>import { getOwnerDocument } from "../utils/owner.js";
2
+ import { history } from "../utils/active-element-history.js";
3
+ import { useWatch } from "../hooks/use-watch.svelte.js";
4
+ import { microTask } from "../utils/microTask.js";
5
+ import { Focus, focusElement, focusIn, FocusResult } from "../utils/focus-management.js";
6
+ import { useIsTopLayer } from "../hooks/use-is-top-layer.svelte.js";
7
+ import { useIsMounted } from "../hooks/use-is-mounted.svelte.js";
8
+ import { useEventListener } from "../hooks/use-event-listener.svelte.js";
9
+ import { useTabDirection, Direction as TabDirection } from "../hooks/use-tab-direction.svelte.js";
10
+ import { match } from "../utils/match.js";
11
+ import { useDisposables } from "../utils/disposables.js";
12
+ import Hidden, { HiddenFeatures } from "../internal/Hidden.svelte";
13
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
14
+ function resolveContainers(containers) {
15
+ if (!containers) return /* @__PURE__ */ new Set();
16
+ if (typeof containers === "function") return new Set(containers());
17
+ let all = /* @__PURE__ */ new Set();
18
+ for (let container of containers) {
19
+ if (container instanceof HTMLElement) {
20
+ all.add(container);
21
+ }
22
+ }
23
+ return all;
24
+ }
25
+ let DEFAULT_FOCUS_TRAP_TAG = "div";
26
+ export var FocusTrapFeatures = /* @__PURE__ */ ((FocusTrapFeatures2) => {
27
+ FocusTrapFeatures2[FocusTrapFeatures2["None"] = 0] = "None";
28
+ FocusTrapFeatures2[FocusTrapFeatures2["InitialFocus"] = 1] = "InitialFocus";
29
+ FocusTrapFeatures2[FocusTrapFeatures2["TabLock"] = 2] = "TabLock";
30
+ FocusTrapFeatures2[FocusTrapFeatures2["FocusLock"] = 4] = "FocusLock";
31
+ FocusTrapFeatures2[FocusTrapFeatures2["RestoreFocus"] = 8] = "RestoreFocus";
32
+ FocusTrapFeatures2[FocusTrapFeatures2["AutoFocus"] = 16] = "AutoFocus";
33
+ return FocusTrapFeatures2;
34
+ })(FocusTrapFeatures || {});
35
+ function useRestoreElement(options) {
36
+ const { enabled } = $derived(options ?? { enabled: true });
37
+ let localHistory = $state(history.slice());
38
+ useWatch({
39
+ action: ([newEnabled], [oldEnabled]) => {
40
+ if (oldEnabled === true && newEnabled === false) {
41
+ microTask(() => {
42
+ localHistory.splice(0);
43
+ });
44
+ }
45
+ if (oldEnabled === false && newEnabled === true) {
46
+ localHistory = history.slice();
47
+ }
48
+ },
49
+ get dependencies() {
50
+ return [enabled, history, localHistory];
51
+ }
52
+ });
53
+ return {
54
+ get lastElement() {
55
+ return localHistory.find((x) => x != null && x.isConnected) ?? null;
56
+ }
57
+ };
58
+ }
59
+ function useRestoreFocus(options) {
60
+ const { features, ownerDocument } = $derived(options);
61
+ const enabled = $derived(Boolean(features & 8 /* RestoreFocus */));
62
+ const restoreElement = useRestoreElement({
63
+ get enabled() {
64
+ return enabled;
65
+ }
66
+ });
67
+ useWatch({
68
+ action: () => {
69
+ if (enabled) return;
70
+ if (ownerDocument?.activeElement === ownerDocument?.body) {
71
+ focusElement(restoreElement.lastElement);
72
+ }
73
+ },
74
+ get dependencies() {
75
+ return [enabled];
76
+ }
77
+ });
78
+ $effect(() => {
79
+ if (!enabled) return;
80
+ return () => focusElement(restoreElement.lastElement);
81
+ });
82
+ }
83
+ function useInitialFocus(options) {
84
+ const { features, ownerDocument, container, initialFocus, initialFocusFallback } = $derived(options);
85
+ let previousActiveElement = $state(null);
86
+ let enabled = useIsTopLayer({
87
+ get enabled() {
88
+ return Boolean(features & 1 /* InitialFocus */);
89
+ },
90
+ scope: "focus-trap#initial-focus"
91
+ });
92
+ let mounted = useIsMounted();
93
+ useWatch({
94
+ action: () => {
95
+ if (features === 0 /* None */) {
96
+ return;
97
+ }
98
+ if (!enabled) {
99
+ if (initialFocusFallback) {
100
+ focusElement(initialFocusFallback);
101
+ }
102
+ return;
103
+ }
104
+ let containerElement = container;
105
+ if (!containerElement) return;
106
+ microTask(() => {
107
+ if (!mounted.current) {
108
+ return;
109
+ }
110
+ let activeElement = ownerDocument?.activeElement;
111
+ if (initialFocus) {
112
+ if (initialFocus === activeElement) {
113
+ previousActiveElement = activeElement;
114
+ return;
115
+ }
116
+ } else if (containerElement.contains(activeElement)) {
117
+ previousActiveElement = activeElement;
118
+ return;
119
+ }
120
+ if (initialFocus) {
121
+ focusElement(initialFocus);
122
+ } else {
123
+ if (features & 16 /* AutoFocus */) {
124
+ if (focusIn(containerElement, Focus.First | Focus.AutoFocus) !== FocusResult.Error) {
125
+ return;
126
+ }
127
+ } else if (focusIn(containerElement, Focus.First) !== FocusResult.Error) {
128
+ return;
129
+ }
130
+ if (initialFocusFallback) {
131
+ focusElement(initialFocusFallback);
132
+ if (ownerDocument?.activeElement === initialFocusFallback) {
133
+ return;
134
+ }
135
+ }
136
+ console.warn("There are no focusable elements inside the <FocusTrap />");
137
+ }
138
+ previousActiveElement = ownerDocument?.activeElement;
139
+ });
140
+ },
141
+ get dependencies() {
142
+ return [initialFocusFallback, enabled, features];
143
+ }
144
+ });
145
+ return {
146
+ get value() {
147
+ return previousActiveElement;
148
+ },
149
+ set value(element) {
150
+ previousActiveElement = element;
151
+ }
152
+ };
153
+ }
154
+ function useFocusLock(options) {
155
+ let { features, ownerDocument, container, containers, previousActiveElement } = $derived(options);
156
+ const mounted = useIsMounted();
157
+ const enabled = $derived(Boolean(features & 4 /* FocusLock */));
158
+ useEventListener({
159
+ get element() {
160
+ return ownerDocument?.defaultView;
161
+ },
162
+ type: "focus",
163
+ listener: (event) => {
164
+ if (!enabled) return;
165
+ if (!mounted.current) return;
166
+ let allContainers = resolveContainers(containers);
167
+ if (container instanceof HTMLElement) allContainers.add(container);
168
+ let previous = previousActiveElement;
169
+ if (!previous) return;
170
+ let toElement = event.target;
171
+ if (toElement && toElement instanceof HTMLElement) {
172
+ if (!contains(allContainers, toElement)) {
173
+ event.preventDefault();
174
+ event.stopPropagation();
175
+ focusElement(previous);
176
+ } else {
177
+ options.previousActiveElement = toElement;
178
+ focusElement(toElement);
179
+ }
180
+ } else {
181
+ focusElement(previousActiveElement);
182
+ }
183
+ },
184
+ options: true
185
+ });
186
+ }
187
+ function contains(containers, element) {
188
+ for (let container of containers) {
189
+ if (container.contains(element)) return true;
190
+ }
191
+ return false;
192
+ }
193
+ </script>
194
+
195
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG">let container = $state(null);
196
+ let {
197
+ ref = $bindable(),
198
+ initialFocus,
199
+ initialFocusFallback,
200
+ containers,
201
+ features = FocusTrapFeatures.InitialFocus | FocusTrapFeatures.TabLock | FocusTrapFeatures.FocusLock | FocusTrapFeatures.RestoreFocus,
202
+ ...theirProps
203
+ } = $props();
204
+ const ownerDocument = $derived(getOwnerDocument(ref));
205
+ useRestoreFocus({
206
+ get features() {
207
+ return features;
208
+ },
209
+ get ownerDocument() {
210
+ return ownerDocument;
211
+ }
212
+ });
213
+ let previousActiveElement = useInitialFocus({
214
+ get features() {
215
+ return features;
216
+ },
217
+ get ownerDocument() {
218
+ return ownerDocument;
219
+ },
220
+ get container() {
221
+ return container;
222
+ },
223
+ get initialFocus() {
224
+ return initialFocus;
225
+ },
226
+ get initialFocusFallback() {
227
+ return initialFocusFallback;
228
+ }
229
+ });
230
+ useFocusLock({
231
+ get features() {
232
+ return features;
233
+ },
234
+ get ownerDocument() {
235
+ return ownerDocument;
236
+ },
237
+ get container() {
238
+ return container;
239
+ },
240
+ get containers() {
241
+ return containers;
242
+ },
243
+ get previousActiveElement() {
244
+ return previousActiveElement.value;
245
+ },
246
+ set previousActiveElement(element) {
247
+ previousActiveElement.value = element;
248
+ }
249
+ });
250
+ const direction = useTabDirection();
251
+ const handleFocus = (e) => {
252
+ let el = container;
253
+ if (!el) return;
254
+ let wrapper = process.env.NODE_ENV === "test" ? microTask : (cb) => cb();
255
+ wrapper(() => {
256
+ match(direction.current, {
257
+ [TabDirection.Forwards]: () => {
258
+ focusIn(el, Focus.First, {
259
+ skipElements: [e.relatedTarget, initialFocusFallback]
260
+ });
261
+ },
262
+ [TabDirection.Backwards]: () => {
263
+ focusIn(el, Focus.Last, {
264
+ skipElements: [e.relatedTarget, initialFocusFallback]
265
+ });
266
+ }
267
+ });
268
+ });
269
+ };
270
+ let tabLockEnabled = useIsTopLayer({
271
+ get enabled() {
272
+ return Boolean(features & FocusTrapFeatures.TabLock);
273
+ },
274
+ scope: "focus-trap#tab-lock"
275
+ });
276
+ const d = useDisposables();
277
+ let recentlyUsedTabKey = $state(false);
278
+ const ourProps = $derived({
279
+ onkeydown(e) {
280
+ if (e.key == "Tab") {
281
+ recentlyUsedTabKey = true;
282
+ d.requestAnimationFrame(() => {
283
+ recentlyUsedTabKey = false;
284
+ });
285
+ }
286
+ },
287
+ onblur(e) {
288
+ if (!(features & FocusTrapFeatures.FocusLock)) return;
289
+ let allContainers = resolveContainers(containers);
290
+ if (container instanceof HTMLElement) allContainers.add(container);
291
+ let relatedTarget = e.relatedTarget;
292
+ if (!(relatedTarget instanceof HTMLElement)) return;
293
+ if (relatedTarget.dataset.headlessuiFocusGuard === "true") {
294
+ return;
295
+ }
296
+ if (!contains(allContainers, relatedTarget)) {
297
+ if (recentlyUsedTabKey) {
298
+ focusIn(
299
+ container,
300
+ match(direction.current, {
301
+ [TabDirection.Forwards]: () => Focus.Next,
302
+ [TabDirection.Backwards]: () => Focus.Previous
303
+ }) | Focus.WrapAround,
304
+ { relativeTo: e.target }
305
+ );
306
+ } else if (e.target instanceof HTMLElement) {
307
+ focusElement(e.target);
308
+ }
309
+ }
310
+ }
311
+ });
312
+ </script>
313
+
314
+ {#if tabLockEnabled}
315
+ <Hidden
316
+ as="button"
317
+ type="button"
318
+ data-headlessui-focus-guard
319
+ onfocus={handleFocus}
320
+ features={HiddenFeatures.Focusable}
321
+ />
322
+ {/if}
323
+ <ElementOrComponent {ourProps} {theirProps} defaultTag={DEFAULT_FOCUS_TRAP_TAG} name="FocusTrap" bind:ref />
324
+ {#if tabLockEnabled}
325
+ <Hidden
326
+ as="button"
327
+ type="button"
328
+ data-headlessui-focus-guard
329
+ onfocus={handleFocus}
330
+ features={HiddenFeatures.Focusable}
331
+ />
332
+ {/if}
@@ -0,0 +1,58 @@
1
+ import type { ElementType, Props } from "../utils/types.js";
2
+ type Containers = (() => Iterable<HTMLElement>) | Iterable<HTMLElement>;
3
+ declare let DEFAULT_FOCUS_TRAP_TAG: "div";
4
+ export declare enum FocusTrapFeatures {
5
+ /** No features enabled for the focus trap. */
6
+ None = 0,
7
+ /** Ensure that we move focus initially into the container. */
8
+ InitialFocus = 1,
9
+ /** Ensure that pressing `Tab` and `Shift+Tab` is trapped within the container. */
10
+ TabLock = 2,
11
+ /** Ensure that programmatically moving focus outside of the container is disallowed. */
12
+ FocusLock = 4,
13
+ /** Ensure that we restore the focus when unmounting the focus trap. */
14
+ RestoreFocus = 8,
15
+ /** Initial focus should look for the `data-autofocus` */
16
+ AutoFocus = 16
17
+ }
18
+ type FocusTrapRenderPropArg = {};
19
+ type FocusTrapPropsWeControl = never;
20
+ export type FocusTrapProps<TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG> = Props<TTag, FocusTrapRenderPropArg, FocusTrapPropsWeControl, {
21
+ initialFocus?: HTMLElement;
22
+ initialFocusFallback?: HTMLElement;
23
+ features?: FocusTrapFeatures;
24
+ containers?: Containers;
25
+ }>;
26
+ declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG> {
27
+ props(): {
28
+ as?: TTag | undefined;
29
+ } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("as" | "children" | "refName" | "class") | "features" | "containers" | "initialFocus" | "initialFocusFallback"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
30
+ children?: import("../utils/types.js").Children<FocusTrapRenderPropArg> | undefined;
31
+ ref?: HTMLElement;
32
+ } & (true extends (import("../utils/types.js").PropsOf<TTag> extends infer T_1 ? T_1 extends import("../utils/types.js").PropsOf<TTag> ? T_1 extends never ? never : "class" extends infer T_2 ? T_2 extends "class" ? T_2 extends keyof T_1 ? true : never : never : never : never : never) ? {
33
+ class?: import("../utils/types.js").PropsOf<TTag>["class"] | ((bag: FocusTrapRenderPropArg) => string) | undefined;
34
+ } : {}) & {
35
+ initialFocus?: HTMLElement;
36
+ initialFocusFallback?: HTMLElement;
37
+ features?: FocusTrapFeatures;
38
+ containers?: Containers;
39
+ };
40
+ events(): {} & {
41
+ [evt: string]: CustomEvent<any>;
42
+ };
43
+ slots(): {};
44
+ bindings(): "ref";
45
+ exports(): {};
46
+ }
47
+ interface $$IsomorphicComponent {
48
+ new <TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
49
+ $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
50
+ } & ReturnType<__sveltets_Render<TTag>['exports']>;
51
+ <TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {
52
+ $$events?: ReturnType<__sveltets_Render<TTag>['events']>;
53
+ }): ReturnType<__sveltets_Render<TTag>['exports']>;
54
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
55
+ }
56
+ declare const FocusTrap: $$IsomorphicComponent;
57
+ type FocusTrap<TTag extends ElementType = typeof DEFAULT_FOCUS_TRAP_TAG> = InstanceType<typeof FocusTrap<TTag>>;
58
+ export default FocusTrap;
@@ -2,5 +2,5 @@ export declare function useControllable<T>(input: {
2
2
  controlledValue: T | undefined;
3
3
  }, onchange?: (value: T) => void, defaultValue?: T): {
4
4
  readonly value: NonNullable<T>;
5
- onchange: (value: T) => void | undefined;
5
+ onchange: (value: T) => void;
6
6
  };
@@ -22,12 +22,12 @@ export function useControllable(input, onchange, defaultValue) {
22
22
  return value;
23
23
  },
24
24
  onchange: (value) => {
25
- if (isControlled) {
26
- return onchange?.(value);
25
+ if (isControlled && onchange) {
26
+ onchange?.(value);
27
27
  }
28
28
  else {
29
29
  internalValue = value;
30
- return onchange?.(value);
30
+ input.controlledValue = value;
31
31
  }
32
32
  },
33
33
  };
@@ -0,0 +1,5 @@
1
+ export declare function useEscape(options: {
2
+ enabled: boolean;
3
+ view: typeof document.defaultView | null;
4
+ cb: (event: KeyboardEvent) => void;
5
+ }): void;
@@ -0,0 +1,26 @@
1
+ import { useEventListener } from "./use-event-listener.svelte.js";
2
+ import { useIsTopLayer } from "./use-is-top-layer.svelte.js";
3
+ export function useEscape(options) {
4
+ const { enabled, view = typeof document !== "undefined" ? document.defaultView : null, cb } = $derived(options);
5
+ let isTopLayer = useIsTopLayer({
6
+ get enabled() {
7
+ return enabled;
8
+ },
9
+ scope: "escape",
10
+ });
11
+ useEventListener({
12
+ get element() {
13
+ return view;
14
+ },
15
+ type: "keydown",
16
+ listener: (event) => {
17
+ if (!isTopLayer.value)
18
+ return;
19
+ if (event.defaultPrevented)
20
+ return;
21
+ if (event.key !== "Escape")
22
+ return;
23
+ cb(event);
24
+ },
25
+ });
26
+ }
@@ -0,0 +1,6 @@
1
+ export declare function useEventListener<TType extends keyof WindowEventMap>(params: {
2
+ element: HTMLElement | Document | Window | EventTarget | null | undefined;
3
+ type: TType;
4
+ listener: (event: WindowEventMap[TType]) => any;
5
+ options?: boolean | AddEventListenerOptions;
6
+ }): void;
@@ -0,0 +1,12 @@
1
+ export function useEventListener(params) {
2
+ let { element = window, type, listener, options } = $derived(params);
3
+ $effect(() => {
4
+ if (!element)
5
+ return;
6
+ function handler(event) {
7
+ listener(event);
8
+ }
9
+ element.addEventListener(type, handler, options);
10
+ return () => element.removeEventListener(type, handler, options);
11
+ });
12
+ }
@@ -26,7 +26,7 @@
26
26
  export declare function useInertOthers(options: {
27
27
  enabled: boolean;
28
28
  elements?: {
29
- allowed?: () => (HTMLElement | null)[];
30
- disallowed?: () => (HTMLElement | null)[];
29
+ allowed?: (HTMLElement | null)[];
30
+ disallowed?: (HTMLElement | null)[];
31
31
  };
32
32
  }): void;
@@ -81,13 +81,13 @@ export function useInertOthers(options) {
81
81
  return;
82
82
  let d = disposables();
83
83
  // Mark all disallowed elements as inert
84
- for (let element of disallowed?.() ?? []) {
84
+ for (let element of disallowed ?? []) {
85
85
  if (!element)
86
86
  continue;
87
87
  d.add(markInert(element));
88
88
  }
89
89
  // Mark all siblings of allowed elements (and parents) as inert
90
- let allowedElements = allowed?.() ?? [];
90
+ let allowedElements = allowed ?? [];
91
91
  for (let element of allowedElements) {
92
92
  if (!element)
93
93
  continue;
@@ -100,7 +100,7 @@ export function useInertOthers(options) {
100
100
  for (let node of parent.children) {
101
101
  // If the node contains any of the elements we should not mark it as inert
102
102
  // because it would make the elements unreachable.
103
- if (allowedElements.some((el) => node.contains(el)))
103
+ if (node.tagName.toLowerCase() === "svelte:fragment" || allowedElements.some((el) => node.contains(el)))
104
104
  continue;
105
105
  // Mark the node as inert
106
106
  d.add(markInert(node));
@@ -0,0 +1,3 @@
1
+ export declare function useIsMounted(): {
2
+ readonly current: boolean;
3
+ };
@@ -0,0 +1,14 @@
1
+ export function useIsMounted() {
2
+ let mounted = $state(false);
3
+ $effect(() => {
4
+ mounted = true;
5
+ return () => {
6
+ mounted = false;
7
+ };
8
+ });
9
+ return {
10
+ get current() {
11
+ return mounted;
12
+ },
13
+ };
14
+ }
@@ -0,0 +1,3 @@
1
+ export declare function useIsTouchDevice(): {
2
+ readonly value: boolean;
3
+ };
@@ -0,0 +1,20 @@
1
+ export function useIsTouchDevice() {
2
+ const mq = typeof window !== "undefined" && typeof window.matchMedia === "function"
3
+ ? window.matchMedia("(pointer: coarse)")
4
+ : null;
5
+ let isTouchDevice = $state(mq?.matches ?? false);
6
+ $effect(() => {
7
+ if (!mq)
8
+ return;
9
+ function handle(event) {
10
+ isTouchDevice = event.matches;
11
+ }
12
+ mq.addEventListener("change", handle);
13
+ return () => mq.removeEventListener("change", handle);
14
+ });
15
+ return {
16
+ get value() {
17
+ return isTouchDevice;
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,9 @@
1
+ export { default as MainTreeProvider, useMainTreeNode } from "../internal/MainTreeProvider.svelte";
2
+ export declare function useRootContainers(options?: {
3
+ defaultContainers?: (HTMLElement | null)[];
4
+ portals?: HTMLElement[];
5
+ mainTreeNode?: HTMLElement | null;
6
+ }): {
7
+ readonly resolvedContainers: HTMLElement[];
8
+ contains: (element: HTMLElement) => boolean;
9
+ };
@@ -0,0 +1,50 @@
1
+ import { getOwnerDocument } from "../utils/owner.js";
2
+ export { default as MainTreeProvider, useMainTreeNode } from "../internal/MainTreeProvider.svelte";
3
+ export function useRootContainers(options = {}) {
4
+ const { defaultContainers = [], portals,
5
+ // Reference to a node in the "main" tree, not in the portalled Dialog tree.
6
+ mainTreeNode, } = $derived(options);
7
+ const ownerDocument = $derived(getOwnerDocument(mainTreeNode));
8
+ const resolvedContainers = $derived.by(() => {
9
+ let containers = [];
10
+ // Resolve default containers
11
+ for (let container of defaultContainers) {
12
+ if (container === null)
13
+ continue;
14
+ containers.push(container);
15
+ }
16
+ // Resolve portal containers
17
+ if (portals) {
18
+ for (let portal of portals) {
19
+ containers.push(portal);
20
+ }
21
+ }
22
+ // Resolve third party (root) containers
23
+ for (let container of ownerDocument?.querySelectorAll("html > *, body > *") ?? []) {
24
+ if (container === document.body)
25
+ continue; // Skip `<body>`
26
+ if (container === document.head)
27
+ continue; // Skip `<head>`
28
+ if (!(container instanceof HTMLElement))
29
+ continue; // Skip non-HTMLElements
30
+ if (container.id === "headlessui-portal-root")
31
+ continue; // Skip the Headless UI portal root
32
+ if (mainTreeNode) {
33
+ if (container.contains(mainTreeNode))
34
+ continue; // Skip if it is the main app
35
+ if (container.contains(mainTreeNode?.getRootNode()?.host))
36
+ continue; // Skip if it is the main app (and the component is inside a shadow root)
37
+ }
38
+ if (containers.some((defaultContainer) => container.contains(defaultContainer)))
39
+ continue; // Skip if the current container is part of a container we've already seen (e.g.: default container / portal)
40
+ containers.push(container);
41
+ }
42
+ return containers;
43
+ });
44
+ return {
45
+ get resolvedContainers() {
46
+ return resolvedContainers;
47
+ },
48
+ contains: (element) => resolvedContainers.some((container) => container.contains(element)),
49
+ };
50
+ }
@@ -0,0 +1,7 @@
1
+ export declare enum Direction {
2
+ Forwards = 0,
3
+ Backwards = 1
4
+ }
5
+ export declare function useTabDirection(): {
6
+ readonly current: Direction;
7
+ };
@@ -0,0 +1,25 @@
1
+ import { useWindowEvent } from "./use-window-event.svelte.js";
2
+ export var Direction;
3
+ (function (Direction) {
4
+ Direction[Direction["Forwards"] = 0] = "Forwards";
5
+ Direction[Direction["Backwards"] = 1] = "Backwards";
6
+ })(Direction || (Direction = {}));
7
+ export function useTabDirection() {
8
+ let direction = $state(Direction.Forwards);
9
+ let enabled = true;
10
+ useWindowEvent({
11
+ enabled,
12
+ type: "keydown",
13
+ listener: (event) => {
14
+ if (event.key === "Tab") {
15
+ direction = event.shiftKey ? Direction.Backwards : Direction.Forwards;
16
+ }
17
+ },
18
+ options: true,
19
+ });
20
+ return {
21
+ get current() {
22
+ return direction;
23
+ },
24
+ };
25
+ }