@pzerelles/headlessui-svelte 2.0.0-next.1 → 2.1.2-next.2

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 (275) hide show
  1. package/dist/button/Button.svelte +61 -0
  2. package/dist/button/Button.svelte.d.ts +47 -0
  3. package/dist/button/index.d.ts +1 -0
  4. package/dist/button/index.js +1 -0
  5. package/dist/checkbox/Checkbox.svelte +93 -61
  6. package/dist/checkbox/Checkbox.svelte.d.ts +45 -29
  7. package/dist/close-button/CloseButton.svelte +11 -0
  8. package/dist/close-button/CloseButton.svelte.d.ts +48 -0
  9. package/dist/close-button/index.d.ts +1 -0
  10. package/dist/close-button/index.js +1 -0
  11. package/dist/combobox/Combobox.svelte +6 -0
  12. package/dist/combobox/Combobox.svelte.d.ts +50 -0
  13. package/dist/data-interactive/DataInteractive.svelte +41 -0
  14. package/dist/data-interactive/DataInteractive.svelte.d.ts +39 -0
  15. package/dist/data-interactive/index.d.ts +1 -0
  16. package/dist/data-interactive/index.js +1 -0
  17. package/dist/description/Description.svelte +16 -41
  18. package/dist/description/Description.svelte.d.ts +15 -23
  19. package/dist/description/context.svelte.d.ts +17 -0
  20. package/dist/description/context.svelte.js +51 -0
  21. package/dist/dialog/Dialog.svelte +51 -0
  22. package/dist/dialog/Dialog.svelte.d.ts +60 -0
  23. package/dist/dialog/DialogBackdrop.svelte +39 -0
  24. package/dist/dialog/DialogBackdrop.svelte.d.ts +38 -0
  25. package/dist/dialog/DialogPanel.svelte +46 -0
  26. package/dist/dialog/DialogPanel.svelte.d.ts +40 -0
  27. package/dist/dialog/DialogTitle.svelte +29 -0
  28. package/dist/dialog/DialogTitle.svelte.d.ts +34 -0
  29. package/dist/dialog/InternalDialog.svelte +233 -0
  30. package/dist/dialog/InternalDialog.svelte.d.ts +42 -0
  31. package/dist/dialog/context.svelte.d.ts +15 -0
  32. package/dist/dialog/context.svelte.js +16 -0
  33. package/dist/dialog/index.d.ts +4 -0
  34. package/dist/dialog/index.js +4 -0
  35. package/dist/field/Field.svelte +14 -16
  36. package/dist/field/Field.svelte.d.ts +21 -17
  37. package/dist/fieldset/Fieldset.svelte +19 -17
  38. package/dist/fieldset/Fieldset.svelte.d.ts +21 -17
  39. package/dist/focus-trap/FocusTrap.svelte +332 -0
  40. package/dist/focus-trap/FocusTrap.svelte.d.ts +58 -0
  41. package/dist/hooks/document-overflow/adjust-scrollbar-padding.d.ts +2 -0
  42. package/dist/hooks/document-overflow/adjust-scrollbar-padding.js +18 -0
  43. package/dist/hooks/document-overflow/handle-ios-locking.d.ts +6 -0
  44. package/dist/hooks/document-overflow/handle-ios-locking.js +134 -0
  45. package/dist/hooks/document-overflow/overflow-store.d.ts +19 -0
  46. package/dist/hooks/document-overflow/overflow-store.js +76 -0
  47. package/dist/hooks/document-overflow/prevent-scroll.d.ts +2 -0
  48. package/dist/hooks/document-overflow/prevent-scroll.js +7 -0
  49. package/dist/hooks/document-overflow/use-document-overflow.svelte.d.ts +7 -0
  50. package/dist/hooks/document-overflow/use-document-overflow.svelte.js +27 -0
  51. package/dist/hooks/use-active-press.svelte.d.ts +14 -0
  52. package/dist/{actions/activePress.svelte.js → hooks/use-active-press.svelte.js} +33 -39
  53. package/dist/hooks/use-by-comparator.d.ts +2 -0
  54. package/dist/hooks/use-by-comparator.js +15 -0
  55. package/dist/hooks/use-controllable.svelte.d.ts +6 -0
  56. package/dist/hooks/use-controllable.svelte.js +34 -0
  57. package/dist/hooks/use-did-element-move.svelte.d.ts +6 -0
  58. package/dist/hooks/use-did-element-move.svelte.js +27 -0
  59. package/dist/hooks/use-disabled.d.ts +3 -0
  60. package/dist/hooks/use-disabled.js +9 -0
  61. package/dist/hooks/use-element-size.svelte.d.ts +7 -0
  62. package/dist/hooks/use-element-size.svelte.js +36 -0
  63. package/dist/hooks/use-escape.svelte.d.ts +5 -0
  64. package/dist/hooks/use-escape.svelte.js +26 -0
  65. package/dist/hooks/use-event-listener.svelte.d.ts +6 -0
  66. package/dist/hooks/use-event-listener.svelte.js +12 -0
  67. package/dist/hooks/use-flags.svelte.d.ts +8 -0
  68. package/dist/hooks/use-flags.svelte.js +18 -0
  69. package/dist/hooks/use-focus-ring.svelte.d.ts +10 -0
  70. package/dist/hooks/use-focus-ring.svelte.js +24 -0
  71. package/dist/hooks/use-hover.svelte.d.ts +26 -0
  72. package/dist/hooks/use-hover.svelte.js +124 -0
  73. package/dist/hooks/use-id.d.ts +1 -0
  74. package/dist/hooks/use-id.js +1 -0
  75. package/dist/hooks/use-inert-others.svelte.d.ts +32 -0
  76. package/dist/hooks/use-inert-others.svelte.js +114 -0
  77. package/dist/hooks/use-is-mounted.svelte.d.ts +3 -0
  78. package/dist/hooks/use-is-mounted.svelte.js +14 -0
  79. package/dist/hooks/use-is-top-layer.svelte.d.ts +29 -0
  80. package/dist/hooks/use-is-top-layer.svelte.js +82 -0
  81. package/dist/hooks/use-is-touch-device.svelte.d.ts +3 -0
  82. package/dist/hooks/use-is-touch-device.svelte.js +20 -0
  83. package/dist/hooks/use-on-disappear.svelte.d.ts +12 -0
  84. package/dist/hooks/use-on-disappear.svelte.js +38 -0
  85. package/dist/hooks/use-outside-click.svelte.d.ts +10 -0
  86. package/dist/hooks/use-outside-click.svelte.js +150 -0
  87. package/dist/hooks/use-reducer.d.ts +4 -0
  88. package/dist/hooks/use-reducer.js +11 -0
  89. package/dist/hooks/use-resolve-button-type.svelte.d.ts +10 -0
  90. package/dist/hooks/use-resolve-button-type.svelte.js +19 -0
  91. package/dist/hooks/use-root-containers.svelte.d.ts +9 -0
  92. package/dist/hooks/use-root-containers.svelte.js +50 -0
  93. package/dist/hooks/use-scroll-lock.svelte.d.ts +5 -0
  94. package/dist/hooks/use-scroll-lock.svelte.js +24 -0
  95. package/dist/hooks/use-sync-refs.d.ts +7 -0
  96. package/dist/hooks/use-sync-refs.js +22 -0
  97. package/dist/hooks/use-tab-direction.svelte.d.ts +7 -0
  98. package/dist/hooks/use-tab-direction.svelte.js +25 -0
  99. package/dist/hooks/use-text-value.svelte.d.ts +3 -0
  100. package/dist/hooks/use-text-value.svelte.js +20 -0
  101. package/dist/hooks/use-tracked-pointer.d.ts +4 -0
  102. package/dist/hooks/use-tracked-pointer.js +26 -0
  103. package/dist/hooks/use-transition.svelte.d.ts +20 -0
  104. package/dist/hooks/use-transition.svelte.js +253 -0
  105. package/dist/hooks/use-tree-walker.svelte.d.ts +8 -0
  106. package/dist/hooks/use-tree-walker.svelte.js +19 -0
  107. package/dist/hooks/use-watch.svelte.d.ts +4 -0
  108. package/dist/hooks/use-watch.svelte.js +16 -0
  109. package/dist/hooks/use-window-event.svelte.d.ts +6 -0
  110. package/dist/hooks/use-window-event.svelte.js +12 -0
  111. package/dist/index.d.ts +13 -0
  112. package/dist/index.js +13 -0
  113. package/dist/input/Input.svelte +59 -0
  114. package/dist/input/Input.svelte.d.ts +52 -0
  115. package/dist/input/index.d.ts +1 -0
  116. package/dist/input/index.js +1 -0
  117. package/dist/internal/FocusSentinel.svelte +45 -0
  118. package/dist/internal/FocusSentinel.svelte.d.ts +20 -0
  119. package/dist/internal/ForcePortalRoot.svelte +6 -0
  120. package/dist/internal/ForcePortalRoot.svelte.d.ts +22 -0
  121. package/dist/internal/FormFields.svelte +2 -4
  122. package/dist/internal/FormFields.svelte.d.ts +9 -7
  123. package/dist/internal/FormResolver.svelte +11 -16
  124. package/dist/internal/FormResolver.svelte.d.ts +6 -4
  125. package/dist/internal/Hidden.svelte +5 -9
  126. package/dist/internal/Hidden.svelte.d.ts +35 -19
  127. package/dist/internal/HoistFormFields.svelte.d.ts +5 -2
  128. package/dist/internal/MainTreeProvider.svelte +45 -0
  129. package/dist/internal/MainTreeProvider.svelte.d.ts +31 -0
  130. package/dist/internal/Portal.svelte.d.ts +5 -2
  131. package/dist/internal/close-provider.d.ts +7 -0
  132. package/dist/internal/close-provider.js +7 -0
  133. package/dist/internal/floating.svelte.d.ts +62 -0
  134. package/dist/internal/floating.svelte.js +488 -0
  135. package/dist/internal/frozen.svelte.d.ts +6 -0
  136. package/dist/internal/frozen.svelte.js +18 -0
  137. package/dist/internal/id.d.ts +8 -0
  138. package/dist/internal/id.js +11 -0
  139. package/dist/internal/open-closed.d.ts +14 -0
  140. package/dist/internal/open-closed.js +17 -0
  141. package/dist/internal/portal-force-root.svelte.d.ts +6 -0
  142. package/dist/internal/portal-force-root.svelte.js +11 -0
  143. package/dist/label/Label.svelte +17 -45
  144. package/dist/label/Label.svelte.d.ts +19 -23
  145. package/dist/label/context.svelte.d.ts +17 -0
  146. package/dist/label/context.svelte.js +56 -0
  147. package/dist/legend/Legend.svelte +4 -3
  148. package/dist/legend/Legend.svelte.d.ts +33 -16
  149. package/dist/listbox/Listbox.svelte +448 -0
  150. package/dist/listbox/Listbox.svelte.d.ts +126 -0
  151. package/dist/listbox/ListboxButton.svelte +139 -0
  152. package/dist/listbox/ListboxButton.svelte.d.ts +52 -0
  153. package/dist/listbox/ListboxOption.svelte +136 -0
  154. package/dist/listbox/ListboxOption.svelte.d.ts +50 -0
  155. package/dist/listbox/ListboxOptions.svelte +269 -0
  156. package/dist/listbox/ListboxOptions.svelte.d.ts +55 -0
  157. package/dist/listbox/ListboxSelectedOption.svelte +35 -0
  158. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +40 -0
  159. package/dist/listbox/index.d.ts +5 -0
  160. package/dist/listbox/index.js +5 -0
  161. package/dist/menu/Menu.svelte +235 -0
  162. package/dist/menu/Menu.svelte.d.ts +42 -0
  163. package/dist/menu/MenuButton.svelte +127 -0
  164. package/dist/menu/MenuButton.svelte.d.ts +52 -0
  165. package/dist/menu/MenuHeading.svelte +19 -0
  166. package/dist/menu/MenuHeading.svelte.d.ts +39 -0
  167. package/dist/menu/MenuItem.svelte +114 -0
  168. package/dist/menu/MenuItem.svelte.d.ts +49 -0
  169. package/dist/menu/MenuItems.svelte +244 -0
  170. package/dist/menu/MenuItems.svelte.d.ts +55 -0
  171. package/dist/menu/MenuSection.svelte +14 -0
  172. package/dist/menu/MenuSection.svelte.d.ts +35 -0
  173. package/dist/menu/MenuSeparator.svelte +9 -0
  174. package/dist/menu/MenuSeparator.svelte.d.ts +35 -0
  175. package/dist/menu/context.svelte.d.ts +47 -0
  176. package/dist/menu/context.svelte.js +21 -0
  177. package/dist/menu/index.d.ts +7 -0
  178. package/dist/menu/index.js +7 -0
  179. package/dist/portal/InternalPortal.svelte +97 -0
  180. package/dist/portal/InternalPortal.svelte.d.ts +43 -0
  181. package/dist/portal/Portal.svelte +7 -0
  182. package/dist/portal/Portal.svelte.d.ts +23 -0
  183. package/dist/portal/PortalGroup.svelte +14 -0
  184. package/dist/portal/PortalGroup.svelte.d.ts +40 -0
  185. package/dist/switch/Switch.svelte +143 -0
  186. package/dist/switch/Switch.svelte.d.ts +61 -0
  187. package/dist/switch/SwitchGroup.svelte +37 -0
  188. package/dist/switch/SwitchGroup.svelte.d.ts +34 -0
  189. package/dist/switch/index.d.ts +2 -0
  190. package/dist/switch/index.js +2 -0
  191. package/dist/tabs/Tab.svelte +156 -0
  192. package/dist/tabs/Tab.svelte.d.ts +48 -0
  193. package/dist/tabs/TabGroup.svelte +241 -0
  194. package/dist/tabs/TabGroup.svelte.d.ts +67 -0
  195. package/dist/tabs/TabList.svelte +16 -0
  196. package/dist/tabs/TabList.svelte.d.ts +35 -0
  197. package/dist/tabs/TabPanel.svelte +61 -0
  198. package/dist/tabs/TabPanel.svelte.d.ts +47 -0
  199. package/dist/tabs/TabPanels.svelte +12 -0
  200. package/dist/tabs/TabPanels.svelte.d.ts +34 -0
  201. package/dist/tabs/index.d.ts +5 -0
  202. package/dist/tabs/index.js +5 -0
  203. package/dist/test-utils/accessability-assertions.d.ts +271 -0
  204. package/dist/test-utils/accessability-assertions.js +1572 -0
  205. package/dist/test-utils/fake-pointer.d.ts +24 -0
  206. package/dist/test-utils/fake-pointer.js +48 -0
  207. package/dist/test-utils/interactions.d.ts +61 -0
  208. package/dist/test-utils/interactions.js +453 -0
  209. package/dist/test-utils/suppress-console-logs.d.ts +7 -0
  210. package/dist/test-utils/suppress-console-logs.js +17 -0
  211. package/dist/transition/InternalTransitionChild.svelte +178 -0
  212. package/dist/transition/InternalTransitionChild.svelte.d.ts +55 -0
  213. package/dist/transition/Transition.svelte +89 -0
  214. package/dist/transition/Transition.svelte.d.ts +42 -0
  215. package/dist/transition/TransitionChild.svelte +16 -0
  216. package/dist/transition/TransitionChild.svelte.d.ts +44 -0
  217. package/dist/transition/context.svelte.d.ts +64 -0
  218. package/dist/transition/context.svelte.js +120 -0
  219. package/dist/transition/index.d.ts +2 -0
  220. package/dist/transition/index.js +2 -0
  221. package/dist/utils/ElementOrComponent.svelte +26 -0
  222. package/dist/utils/ElementOrComponent.svelte.d.ts +56 -0
  223. package/dist/utils/Generic.svelte +44 -0
  224. package/dist/utils/Generic.svelte.d.ts +35 -0
  225. package/dist/utils/StableCollection.svelte +43 -0
  226. package/dist/utils/StableCollection.svelte.d.ts +22 -0
  227. package/dist/utils/active-element-history.d.ts +1 -0
  228. package/dist/utils/active-element-history.js +35 -0
  229. package/dist/utils/alternative-types.d.ts +21 -0
  230. package/dist/utils/alternative-types.js +1 -0
  231. package/dist/utils/calculate-active-index.d.ts +25 -0
  232. package/dist/utils/calculate-active-index.js +74 -0
  233. package/dist/utils/class-names.d.ts +1 -0
  234. package/dist/utils/class-names.js +10 -0
  235. package/dist/utils/default-map.d.ts +5 -0
  236. package/dist/utils/default-map.js +15 -0
  237. package/dist/utils/disposables.d.ts +14 -12
  238. package/dist/utils/disposables.js +13 -10
  239. package/dist/utils/dom.d.ts +0 -2
  240. package/dist/utils/dom.js +2 -4
  241. package/dist/utils/env.d.ts +17 -0
  242. package/dist/utils/env.js +39 -0
  243. package/dist/utils/focus-management.d.ts +45 -0
  244. package/dist/utils/focus-management.js +242 -0
  245. package/dist/utils/focusVisible.svelte.d.ts +3 -3
  246. package/dist/utils/focusVisible.svelte.js +52 -41
  247. package/dist/utils/get-text-value.d.ts +1 -0
  248. package/dist/utils/get-text-value.js +71 -0
  249. package/dist/utils/id.d.ts +1 -1
  250. package/dist/utils/match.d.ts +1 -0
  251. package/dist/utils/match.js +13 -0
  252. package/dist/utils/on-document-ready.d.ts +1 -0
  253. package/dist/utils/on-document-ready.js +12 -0
  254. package/dist/utils/once.d.ts +1 -0
  255. package/dist/utils/once.js +9 -0
  256. package/dist/utils/owner.d.ts +1 -0
  257. package/dist/utils/owner.js +8 -0
  258. package/dist/utils/platform.d.ts +2 -0
  259. package/dist/utils/platform.js +17 -0
  260. package/dist/utils/ref.svelte.d.ts +4 -0
  261. package/dist/utils/ref.svelte.js +4 -0
  262. package/dist/utils/render.d.ts +34 -0
  263. package/dist/utils/render.js +119 -0
  264. package/dist/utils/state.d.ts +7 -1
  265. package/dist/utils/state.js +10 -6
  266. package/dist/utils/store.d.ts +11 -0
  267. package/dist/utils/store.js +20 -0
  268. package/dist/utils/types.d.ts +24 -0
  269. package/dist/utils/types.js +1 -0
  270. package/package.json +33 -25
  271. package/dist/actions/activePress.svelte.d.ts +0 -8
  272. package/dist/actions/focusRing.svelte.d.ts +0 -9
  273. package/dist/actions/focusRing.svelte.js +0 -34
  274. package/dist/utils/disabled.d.ts +0 -3
  275. package/dist/utils/disabled.js +0 -2
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ export declare function useTextValue(options: {
2
+ element: HTMLElement | null;
3
+ }): () => string;
@@ -0,0 +1,20 @@
1
+ import { getTextValue } from "../utils/get-text-value.js";
2
+ export function useTextValue(options) {
3
+ const { element } = $derived(options);
4
+ let cacheKey = $state("");
5
+ let cacheValue = $state("");
6
+ return () => {
7
+ if (!element)
8
+ return "";
9
+ // Check for a cached version
10
+ let currentKey = element.innerText;
11
+ if (cacheKey === currentKey) {
12
+ return cacheValue;
13
+ }
14
+ // Calculate the value
15
+ let value = getTextValue(element).trim().toLowerCase();
16
+ cacheKey = currentKey;
17
+ cacheValue = value;
18
+ return value;
19
+ };
20
+ }
@@ -0,0 +1,4 @@
1
+ export declare function useTrackedPointer(): {
2
+ wasMoved(evt: PointerEvent): boolean;
3
+ update(evt: PointerEvent): void;
4
+ };
@@ -0,0 +1,26 @@
1
+ import { BROWSER } from "esm-env";
2
+ function eventToPosition(evt) {
3
+ return [evt.screenX, evt.screenY];
4
+ }
5
+ export function useTrackedPointer() {
6
+ let lastPos = [-1, -1];
7
+ return {
8
+ wasMoved(evt) {
9
+ // FIXME: Remove this once we use browser testing in all the relevant places.
10
+ // NOTE: This is replaced with a compile-time define during the build process
11
+ // This hack exists to work around a few failing tests caused by our inability to "move" the virtual pointer in JSDOM pointer events.
12
+ if (!BROWSER && process.env.TEST_BYPASS_TRACKED_POINTER) {
13
+ return true;
14
+ }
15
+ let newPos = eventToPosition(evt);
16
+ if (lastPos[0] === newPos[0] && lastPos[1] === newPos[1]) {
17
+ return false;
18
+ }
19
+ lastPos = newPos;
20
+ return true;
21
+ },
22
+ update(evt) {
23
+ lastPos = eventToPosition(evt);
24
+ },
25
+ };
26
+ }
@@ -0,0 +1,20 @@
1
+ type TransitionData = {
2
+ closed?: boolean;
3
+ enter?: boolean;
4
+ leave?: boolean;
5
+ transition?: boolean;
6
+ };
7
+ export declare function transitionDataAttributes(data: TransitionData): Record<string, string>;
8
+ export declare function useTransition(options: {
9
+ enabled: boolean;
10
+ element: HTMLElement | null | undefined;
11
+ show: boolean;
12
+ events?: {
13
+ start?(show: boolean): void;
14
+ end?(show: boolean): void;
15
+ };
16
+ }): {
17
+ readonly visible: boolean;
18
+ readonly data: TransitionData;
19
+ };
20
+ export {};
@@ -0,0 +1,253 @@
1
+ import { disposables, useDisposables } from "../utils/disposables.js";
2
+ import { once } from "../utils/once.js";
3
+ import { untrack } from "svelte";
4
+ /**
5
+ * ```
6
+ * ┌──────┐ │ ┌──────────────┐
7
+ * │Closed│ │ │Closed │
8
+ * └──────┘ │ └──────────────┘
9
+ * ┌──────┐┌──────┐┌──────┐│┌──────┐┌──────┐┌──────┐
10
+ * │Frame ││Frame ││Frame │││Frame ││Frame ││Frame │
11
+ * └──────┘└──────┘└──────┘│└──────┘└──────┘└──────┘
12
+ * ┌──────────────────────┐│┌──────────────────────┐
13
+ * │Enter │││Leave │
14
+ * └──────────────────────┘│└──────────────────────┘
15
+ * ┌──────────────────────┐│┌──────────────────────┐
16
+ * │Transition │││Transition │
17
+ * ├──────────────────────┘│└──────────────────────┘
18
+ * │
19
+ * └─ Applied when `Enter` or `Leave` is applied.
20
+ * ```
21
+ */
22
+ var TransitionState;
23
+ (function (TransitionState) {
24
+ TransitionState[TransitionState["None"] = 0] = "None";
25
+ TransitionState[TransitionState["Closed"] = 1] = "Closed";
26
+ TransitionState[TransitionState["Enter"] = 2] = "Enter";
27
+ TransitionState[TransitionState["Leave"] = 4] = "Leave";
28
+ })(TransitionState || (TransitionState = {}));
29
+ export function transitionDataAttributes(data) {
30
+ const attributes = {};
31
+ for (const key in data) {
32
+ if (data[key] === true) {
33
+ attributes[`data-${key}`] = "";
34
+ }
35
+ }
36
+ return attributes;
37
+ }
38
+ export function useTransition(options) {
39
+ const { enabled, element, show, events } = $derived(options);
40
+ let visible = $state(show);
41
+ let flags = $state(enabled && visible ? TransitionState.Enter | TransitionState.Closed : TransitionState.None);
42
+ let inFlight = $state(false);
43
+ let cancelled = $state(false);
44
+ const d = useDisposables();
45
+ function retry(enabled, show, node, d) {
46
+ if (!enabled)
47
+ return;
48
+ if (show) {
49
+ visible = true;
50
+ }
51
+ if (!node) {
52
+ // Retry if the DOM node isn't available yet
53
+ if (show) {
54
+ flags |= TransitionState.Enter | TransitionState.Closed;
55
+ return d.nextFrame(() => retry(enabled, show, node, d));
56
+ }
57
+ return;
58
+ }
59
+ events?.start?.(show);
60
+ return transition(node, {
61
+ inFlight,
62
+ prepare() {
63
+ if (cancelled) {
64
+ // Cancelled a cancellation, we're back to the original state.
65
+ cancelled = false;
66
+ }
67
+ else {
68
+ // If we were already in-flight, then we want to cancel the current
69
+ // transition.
70
+ cancelled = inFlight;
71
+ }
72
+ inFlight = true;
73
+ if (cancelled)
74
+ return;
75
+ if (show) {
76
+ flags = TransitionState.Enter | TransitionState.Closed;
77
+ }
78
+ else {
79
+ flags = TransitionState.Leave | (flags & TransitionState.Closed);
80
+ }
81
+ },
82
+ run() {
83
+ if (cancelled) {
84
+ // If we cancelled a transition, then the `show` state is going to
85
+ // be inverted already, but that doesn't mean we have to go to that
86
+ // new state.
87
+ //
88
+ // What we actually want is to revert to the "idle" state (the
89
+ // stable state where an `Enter` transitions to, and a `Leave`
90
+ // transitions from.)
91
+ //
92
+ // Because of this, it might look like we are swapping the flags in
93
+ // the following branches, but that's not the case.
94
+ if (!show) {
95
+ flags = TransitionState.Leave | TransitionState.Closed;
96
+ }
97
+ else {
98
+ flags = TransitionState.Enter | TransitionState.Closed;
99
+ }
100
+ }
101
+ else {
102
+ if (show) {
103
+ flags = flags & ~TransitionState.Closed;
104
+ }
105
+ else {
106
+ flags |= TransitionState.Closed;
107
+ }
108
+ }
109
+ },
110
+ done() {
111
+ if (cancelled) {
112
+ if (typeof node.getAnimations === "function" && node.getAnimations().length > 0) {
113
+ return;
114
+ }
115
+ }
116
+ inFlight = false;
117
+ flags = 0;
118
+ if (!show) {
119
+ visible = false;
120
+ }
121
+ events?.end?.(show);
122
+ },
123
+ });
124
+ }
125
+ $effect(() => {
126
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
127
+ ;
128
+ [enabled, show, element, d];
129
+ return untrack(() => retry(enabled, show, element, d));
130
+ });
131
+ const data = $derived({
132
+ closed: enabled ? !!(flags & TransitionState.Closed) : undefined,
133
+ enter: enabled ? !!(flags & TransitionState.Enter) : undefined,
134
+ leave: enabled ? !!(flags & TransitionState.Leave) : undefined,
135
+ transition: enabled ? !!(flags & (TransitionState.Enter | TransitionState.Leave)) : undefined,
136
+ });
137
+ return {
138
+ get visible() {
139
+ return enabled ? visible : show;
140
+ },
141
+ get data() {
142
+ return data;
143
+ },
144
+ };
145
+ }
146
+ function transition(node, { prepare, run, done, inFlight, }) {
147
+ const d = disposables();
148
+ // Prepare the transitions by ensuring that all the "before" classes are
149
+ // applied and flushed to the DOM.
150
+ prepareTransition(node, {
151
+ prepare,
152
+ inFlight,
153
+ });
154
+ // This is a workaround for a bug in all major browsers.
155
+ //
156
+ // 1. When an element is just mounted
157
+ // 2. And you apply a transition to it (e.g.: via a class)
158
+ // 3. And you're using `getComputedStyle` and read any returned value
159
+ // 4. Then the `transition` immediately jumps to the end state
160
+ //
161
+ // This means that no transition happens at all. To fix this, we delay the
162
+ // actual transition by one frame.
163
+ d.nextFrame(() => {
164
+ // Wait for the transition, once the transition is complete we can cleanup.
165
+ // This is registered first to prevent race conditions, otherwise it could
166
+ // happen that the transition is already done before we start waiting for
167
+ // the actual event.
168
+ d.add(waitForTransition(node, done));
169
+ // Initiate the transition by applying the new classes.
170
+ run();
171
+ });
172
+ return d.dispose;
173
+ }
174
+ function waitForTransition(node, _done) {
175
+ const done = once(_done);
176
+ const d = disposables();
177
+ if (!node)
178
+ return d.dispose;
179
+ // Safari returns a comma separated list of values, so let's sort them and take the highest value.
180
+ const { transitionDuration, transitionDelay } = getComputedStyle(node);
181
+ const [durationMs, delayMs] = [transitionDuration, transitionDelay].map((value) => {
182
+ const [resolvedValue = 0] = value
183
+ .split(",")
184
+ // Remove falsy we can't work with
185
+ .filter(Boolean)
186
+ // Values are returned as `0.3s` or `75ms`
187
+ .map((v) => (v.includes("ms") ? parseFloat(v) : parseFloat(v) * 1000))
188
+ .sort((a, z) => z - a);
189
+ return resolvedValue;
190
+ });
191
+ const totalDuration = durationMs + delayMs;
192
+ if (totalDuration !== 0) {
193
+ if (process.env.NODE_ENV === "test") {
194
+ const dispose = d.setTimeout(() => {
195
+ done();
196
+ dispose();
197
+ }, totalDuration);
198
+ }
199
+ else {
200
+ const disposeGroup = d.group((d) => {
201
+ // Mark the transition as done when the timeout is reached. This is a fallback in case the
202
+ // transitionrun event is not fired.
203
+ const cancelTimeout = d.setTimeout(() => {
204
+ done();
205
+ d.dispose();
206
+ }, totalDuration);
207
+ // The moment the transitionrun event fires, we should cleanup the timeout fallback, because
208
+ // then we know that we can use the native transition events because something is
209
+ // transitioning.
210
+ d.addEventListener(node, "transitionrun", (event) => {
211
+ if (event.target !== event.currentTarget)
212
+ return;
213
+ cancelTimeout();
214
+ d.addEventListener(node, "transitioncancel", (event) => {
215
+ if (event.target !== event.currentTarget)
216
+ return;
217
+ done();
218
+ disposeGroup();
219
+ });
220
+ });
221
+ });
222
+ d.addEventListener(node, "transitionend", (event) => {
223
+ if (event.target !== event.currentTarget)
224
+ return;
225
+ done();
226
+ d.dispose();
227
+ });
228
+ }
229
+ }
230
+ else {
231
+ // No transition is happening, so we should cleanup already. Otherwise we have to wait until we
232
+ // get disposed.
233
+ done();
234
+ }
235
+ return d.dispose;
236
+ }
237
+ function prepareTransition(node, { inFlight, prepare }) {
238
+ // If we are already transitioning, then we don't need to force cancel the
239
+ // current transition (by triggering a reflow).
240
+ if (inFlight) {
241
+ prepare();
242
+ return;
243
+ }
244
+ const previous = node.style.transition;
245
+ // Force cancel current transition
246
+ node.style.transition = "none";
247
+ prepare();
248
+ // Trigger a reflow, flushing the CSS changes
249
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
250
+ node.offsetHeight;
251
+ // Reset the transition to what it was before
252
+ node.style.transition = previous;
253
+ }
@@ -0,0 +1,8 @@
1
+ type AcceptNode = (node: HTMLElement) => typeof NodeFilter.FILTER_ACCEPT | typeof NodeFilter.FILTER_SKIP | typeof NodeFilter.FILTER_REJECT;
2
+ export declare function useTreeWalker(options: {
3
+ enabled: boolean;
4
+ container: HTMLElement | null;
5
+ accept: AcceptNode;
6
+ walk(node: HTMLElement): void;
7
+ }): void;
8
+ export {};
@@ -0,0 +1,19 @@
1
+ import { getOwnerDocument } from "../utils/owner.js";
2
+ export function useTreeWalker(options) {
3
+ const { enabled, container, accept, walk } = $derived(options);
4
+ $effect(() => {
5
+ if (!container)
6
+ return;
7
+ if (!enabled)
8
+ return;
9
+ const ownerDocument = getOwnerDocument(container);
10
+ if (!ownerDocument)
11
+ return;
12
+ const acceptNode = Object.assign((node) => accept(node), { acceptNode: accept });
13
+ const walker = ownerDocument.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, acceptNode,
14
+ // @ts-expect-error This `false` is a simple small fix for older browsers
15
+ false);
16
+ while (walker.nextNode())
17
+ walk(walker.currentNode);
18
+ });
19
+ }
@@ -0,0 +1,4 @@
1
+ export declare function useWatch<T extends any[]>(options: {
2
+ action: (newValues: [...T], oldValues: [...T]) => void | (() => void);
3
+ dependencies: [...T];
4
+ }): void;
@@ -0,0 +1,16 @@
1
+ import { untrack } from "svelte";
2
+ export function useWatch(options) {
3
+ const { action, dependencies } = $derived(options);
4
+ let track = [];
5
+ $effect(() => {
6
+ let oldValues = untrack(() => [...track]);
7
+ for (let [idx, value] of dependencies.entries()) {
8
+ if (untrack(() => track[idx]) !== value) {
9
+ // At least 1 item changed
10
+ let returnValue = action(dependencies, oldValues);
11
+ track = dependencies;
12
+ return returnValue;
13
+ }
14
+ }
15
+ });
16
+ }
@@ -0,0 +1,6 @@
1
+ export declare function useWindowEvent<TType extends keyof WindowEventMap>(params: {
2
+ enabled: boolean;
3
+ type: TType;
4
+ listener: (ev: WindowEventMap[TType]) => any;
5
+ options?: boolean | AddEventListenerOptions;
6
+ }): void;
@@ -0,0 +1,12 @@
1
+ export function useWindowEvent(params) {
2
+ let { enabled, type, listener, options } = $derived(params);
3
+ $effect(() => {
4
+ if (!enabled)
5
+ return;
6
+ function handler(event) {
7
+ listener(event);
8
+ }
9
+ window.addEventListener(type, handler, options);
10
+ return () => window.removeEventListener(type, handler, options);
11
+ });
12
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,19 @@
1
+ export * from "./button/index.js";
1
2
  export * from "./checkbox/index.js";
3
+ export * from "./close-button/index.js";
4
+ export * from "./data-interactive/index.js";
2
5
  export * from "./description/index.js";
6
+ export * from "./dialog/index.js";
3
7
  export * from "./field/index.js";
4
8
  export * from "./fieldset/index.js";
9
+ export * from "./input/index.js";
5
10
  export * from "./label/index.js";
6
11
  export * from "./legend/index.js";
12
+ export * from "./listbox/index.js";
13
+ export * from "./menu/index.js";
14
+ export * from "./switch/index.js";
15
+ export * from "./tabs/index.js";
16
+ export * from "./transition/index.js";
17
+ export * from "./hooks/use-id.js";
18
+ export * from "./utils/types.js";
19
+ export { mergeProps } from "./utils/render.js";
package/dist/index.js CHANGED
@@ -1,6 +1,19 @@
1
+ export * from "./button/index.js";
1
2
  export * from "./checkbox/index.js";
3
+ export * from "./close-button/index.js";
4
+ export * from "./data-interactive/index.js";
2
5
  export * from "./description/index.js";
6
+ export * from "./dialog/index.js";
3
7
  export * from "./field/index.js";
4
8
  export * from "./fieldset/index.js";
9
+ export * from "./input/index.js";
5
10
  export * from "./label/index.js";
6
11
  export * from "./legend/index.js";
12
+ export * from "./listbox/index.js";
13
+ export * from "./menu/index.js";
14
+ export * from "./switch/index.js";
15
+ export * from "./tabs/index.js";
16
+ export * from "./transition/index.js";
17
+ export * from "./hooks/use-id.js";
18
+ export * from "./utils/types.js";
19
+ export { mergeProps } from "./utils/render.js";
@@ -0,0 +1,59 @@
1
+ <script lang="ts" module>const DEFAULT_INPUT_TAG = "input";
2
+ </script>
3
+
4
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string">import { htmlid } from "../utils/id.js";
5
+ import { useDisabled } from "../hooks/use-disabled.js";
6
+ import { useProvidedId } from "../internal/id.js";
7
+ import { useLabelledBy } from "../label/context.svelte.js";
8
+ import { useDescribedBy } from "../description/context.svelte.js";
9
+ import { useHover } from "../hooks/use-hover.svelte.js";
10
+ import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
11
+ import { mergeProps } from "../utils/render.js";
12
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
13
+ const internalId = htmlid();
14
+ const providedId = useProvidedId();
15
+ const providedDisabled = useDisabled();
16
+ let {
17
+ ref = $bindable(),
18
+ value = $bindable(),
19
+ id = providedId?.value || `headlessui-input-${internalId}`,
20
+ disabled: theirDisabled = false,
21
+ autofocus = false,
22
+ invalid = false,
23
+ ...theirProps
24
+ } = $props();
25
+ const disabled = $derived(providedDisabled?.value ?? theirDisabled);
26
+ const labelledBy = useLabelledBy();
27
+ const describedBy = useDescribedBy();
28
+ const { isHovered: hover, hoverProps } = $derived(
29
+ useHover({
30
+ get disabled() {
31
+ return disabled;
32
+ }
33
+ })
34
+ );
35
+ const { isFocusVisible: focus, focusProps } = $derived(
36
+ useFocusRing({
37
+ get autofocus() {
38
+ return autofocus;
39
+ }
40
+ })
41
+ );
42
+ const ourProps = $derived(
43
+ mergeProps(
44
+ {
45
+ id,
46
+ "aria-labelledby": labelledBy?.value,
47
+ "aria-describedby": describedBy?.value,
48
+ "aria-invalid": invalid ? "" : void 0,
49
+ disabled: disabled || void 0,
50
+ autofocus
51
+ },
52
+ focusProps,
53
+ hoverProps
54
+ )
55
+ );
56
+ const slot = $derived({ disabled, invalid, hover, focus, autofocus });
57
+ </script>
58
+
59
+ <ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_INPUT_TAG} name="Input" bind:ref bind:value />
@@ -0,0 +1,52 @@
1
+ import type { ElementType, Props } from "../utils/types.js";
2
+ declare const DEFAULT_INPUT_TAG: "input";
3
+ type InputRenderPropArg = {
4
+ disabled: boolean;
5
+ hover: boolean;
6
+ focus: boolean;
7
+ autofocus: boolean;
8
+ invalid: boolean;
9
+ };
10
+ type InputPropsWeControl = "aria-labelledby" | "aria-describedby";
11
+ export type InputProps<TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string> = Props<TTag, InputRenderPropArg, InputPropsWeControl, {
12
+ id?: string;
13
+ value?: TValue;
14
+ disabled?: boolean;
15
+ invalid?: boolean;
16
+ autofocus?: boolean;
17
+ }>;
18
+ declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string> {
19
+ props(): {
20
+ as?: TTag | undefined;
21
+ value?: TValue | undefined;
22
+ } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("as" | "children" | "refName" | "class") | "invalid" | "disabled" | "autofocus" | "value" | "id" | InputPropsWeControl> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
23
+ children?: import("../utils/types.js").Children<InputRenderPropArg> | undefined;
24
+ ref?: HTMLElement;
25
+ } & (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) ? {
26
+ class?: import("../utils/types.js").PropsOf<TTag>["class"] | ((bag: InputRenderPropArg) => string) | undefined;
27
+ } : {}) & {
28
+ id?: string;
29
+ value?: TValue | undefined;
30
+ disabled?: boolean;
31
+ invalid?: boolean;
32
+ autofocus?: boolean;
33
+ };
34
+ events(): {} & {
35
+ [evt: string]: CustomEvent<any>;
36
+ };
37
+ slots(): {};
38
+ bindings(): "ref" | "value";
39
+ exports(): {};
40
+ }
41
+ interface $$IsomorphicComponent {
42
+ new <TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag, TValue>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag, TValue>['props']>, ReturnType<__sveltets_Render<TTag, TValue>['events']>, ReturnType<__sveltets_Render<TTag, TValue>['slots']>> & {
43
+ $$bindings?: ReturnType<__sveltets_Render<TTag, TValue>['bindings']>;
44
+ } & ReturnType<__sveltets_Render<TTag, TValue>['exports']>;
45
+ <TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string>(internal: unknown, props: ReturnType<__sveltets_Render<TTag, TValue>['props']> & {
46
+ $$events?: ReturnType<__sveltets_Render<TTag, TValue>['events']>;
47
+ }): ReturnType<__sveltets_Render<TTag, TValue>['exports']>;
48
+ z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
49
+ }
50
+ declare const Input: $$IsomorphicComponent;
51
+ type Input<TTag extends ElementType = typeof DEFAULT_INPUT_TAG, TValue = string> = InstanceType<typeof Input<TTag, TValue>>;
52
+ export default Input;
@@ -0,0 +1 @@
1
+ export { default as Input, type InputProps } from "./Input.svelte";
@@ -0,0 +1 @@
1
+ export { default as Input } from "./Input.svelte";
@@ -0,0 +1,45 @@
1
+ <script lang="ts">import { onMount } from "svelte";
2
+ import Hidden, { HiddenFeatures } from "./Hidden.svelte";
3
+ let { onfocus } = $props();
4
+ let enabled = $state(true);
5
+ let mounted = $state(false);
6
+ onMount(() => {
7
+ mounted = true;
8
+ });
9
+ </script>
10
+
11
+ {#if enabled}
12
+ <Hidden
13
+ as="button"
14
+ type="button"
15
+ features={HiddenFeatures.Focusable}
16
+ onfocus={(event: FocusEvent) => {
17
+ event.preventDefault()
18
+ let frame: ReturnType<typeof requestAnimationFrame>
19
+
20
+ let tries = 50
21
+ function forwardFocus() {
22
+ // Prevent infinite loops
23
+ if (tries-- <= 0) {
24
+ if (frame) cancelAnimationFrame(frame)
25
+ return
26
+ }
27
+
28
+ // Try to move focus to the correct element. This depends on the implementation
29
+ // of `onFocus` of course since it would be different for each place we use it in.
30
+ if (onfocus?.()) {
31
+ cancelAnimationFrame(frame)
32
+ if (!mounted) return
33
+
34
+ enabled = false
35
+ return
36
+ }
37
+
38
+ // Retry
39
+ frame = requestAnimationFrame(forwardFocus)
40
+ }
41
+
42
+ frame = requestAnimationFrame(forwardFocus)
43
+ }}
44
+ />
45
+ {/if}
@@ -0,0 +1,20 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: Props & {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const FocusSentinel: $$__sveltets_2_IsomorphicComponent<{
15
+ onfocus: () => boolean;
16
+ }, {
17
+ [evt: string]: CustomEvent<any>;
18
+ }, {}, {}, "">;
19
+ type FocusSentinel = InstanceType<typeof FocusSentinel>;
20
+ export default FocusSentinel;