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

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