@pzerelles/headlessui-svelte 2.1.2-next.4 → 2.1.2-next.41

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 (252) hide show
  1. package/dist/button/Button.svelte +15 -18
  2. package/dist/button/Button.svelte.d.ts +8 -36
  3. package/dist/button/index.d.ts +1 -1
  4. package/dist/button/index.js +1 -1
  5. package/dist/checkbox/Checkbox.svelte +30 -26
  6. package/dist/checkbox/Checkbox.svelte.d.ts +17 -38
  7. package/dist/checkbox/index.d.ts +1 -1
  8. package/dist/checkbox/index.js +1 -1
  9. package/dist/close-button/CloseButton.svelte +4 -7
  10. package/dist/close-button/CloseButton.svelte.d.ts +3 -46
  11. package/dist/close-button/index.d.ts +1 -0
  12. package/dist/close-button/index.js +1 -0
  13. package/dist/data-interactive/DataInteractive.svelte +6 -22
  14. package/dist/data-interactive/DataInteractive.svelte.d.ts +9 -34
  15. package/dist/data-interactive/index.d.ts +1 -1
  16. package/dist/data-interactive/index.js +1 -1
  17. package/dist/description/Description.svelte +28 -23
  18. package/dist/description/Description.svelte.d.ts +9 -30
  19. package/dist/description/context.svelte.js +14 -16
  20. package/dist/description/index.d.ts +1 -1
  21. package/dist/dialog/Dialog.svelte +315 -31
  22. package/dist/dialog/Dialog.svelte.d.ts +7 -45
  23. package/dist/dialog/DialogBackdrop.svelte +11 -14
  24. package/dist/dialog/DialogBackdrop.svelte.d.ts +8 -33
  25. package/dist/dialog/DialogPanel.svelte +23 -19
  26. package/dist/dialog/DialogPanel.svelte.d.ts +8 -34
  27. package/dist/dialog/DialogTitle.svelte +17 -8
  28. package/dist/dialog/DialogTitle.svelte.d.ts +9 -30
  29. package/dist/dialog/context.svelte.js +2 -2
  30. package/dist/dialog/index.d.ts +4 -4
  31. package/dist/dialog/index.js +4 -4
  32. package/dist/field/Field.svelte +27 -26
  33. package/dist/field/Field.svelte.d.ts +7 -34
  34. package/dist/field/index.d.ts +1 -1
  35. package/dist/fieldset/Fieldset.svelte +14 -20
  36. package/dist/fieldset/Fieldset.svelte.d.ts +8 -35
  37. package/dist/fieldset/index.d.ts +1 -1
  38. package/dist/focus-trap/FocusTrap.svelte +30 -54
  39. package/dist/focus-trap/FocusTrap.svelte.d.ts +10 -52
  40. package/dist/focus-trap/FocusTrapFeatures.d.ts +14 -0
  41. package/dist/focus-trap/FocusTrapFeatures.js +15 -0
  42. package/dist/hooks/use-controllable.svelte.js +2 -1
  43. package/dist/hooks/use-did-element-move.svelte.js +5 -10
  44. package/dist/hooks/use-disabled.d.ts +6 -1
  45. package/dist/hooks/use-disabled.js +10 -5
  46. package/dist/hooks/use-event-listener.svelte.d.ts +1 -1
  47. package/dist/hooks/use-event-listener.svelte.js +3 -1
  48. package/dist/hooks/use-inert-others.svelte.js +10 -10
  49. package/dist/hooks/use-resolve-button-type.svelte.js +0 -1
  50. package/dist/hooks/use-root-containers.svelte.d.ts +2 -2
  51. package/dist/hooks/use-root-containers.svelte.js +5 -5
  52. package/dist/hooks/use-tab-direction.svelte.js +1 -1
  53. package/dist/index.d.ts +5 -2
  54. package/dist/index.js +5 -2
  55. package/dist/input/Input.svelte +28 -21
  56. package/dist/input/Input.svelte.d.ts +16 -33
  57. package/dist/input/index.d.ts +1 -1
  58. package/dist/input/index.js +1 -1
  59. package/dist/internal/FloatingProvider.svelte +17 -0
  60. package/dist/internal/FloatingProvider.svelte.d.ts +8 -0
  61. package/dist/internal/FocusSentinel.svelte +33 -32
  62. package/dist/internal/FocusSentinel.svelte.d.ts +4 -18
  63. package/dist/internal/ForcePortalRoot.svelte.d.ts +4 -18
  64. package/dist/internal/FormFields.svelte +18 -13
  65. package/dist/internal/FormFields.svelte.d.ts +4 -18
  66. package/dist/internal/FormFieldsProvider.svelte +17 -0
  67. package/dist/internal/FormFieldsProvider.svelte.d.ts +7 -0
  68. package/dist/internal/FormResolver.svelte +6 -2
  69. package/dist/internal/FormResolver.svelte.d.ts +4 -18
  70. package/dist/internal/Hidden.svelte +10 -10
  71. package/dist/internal/Hidden.svelte.d.ts +6 -33
  72. package/dist/internal/MainTreeProvider.svelte +1 -1
  73. package/dist/internal/MainTreeProvider.svelte.d.ts +4 -18
  74. package/dist/internal/Portal.svelte.d.ts +4 -18
  75. package/dist/internal/floating-provider.svelte.d.ts +3 -0
  76. package/dist/internal/floating-provider.svelte.js +206 -0
  77. package/dist/internal/floating.svelte.d.ts +46 -22
  78. package/dist/internal/floating.svelte.js +90 -272
  79. package/dist/internal/form-fields.svelte.d.ts +10 -0
  80. package/dist/internal/form-fields.svelte.js +23 -0
  81. package/dist/label/Label.svelte +17 -13
  82. package/dist/label/Label.svelte.d.ts +8 -33
  83. package/dist/label/context.svelte.js +1 -1
  84. package/dist/label/index.d.ts +1 -1
  85. package/dist/legend/Legend.svelte +21 -15
  86. package/dist/legend/Legend.svelte.d.ts +9 -34
  87. package/dist/listbox/Listbox.svelte +79 -163
  88. package/dist/listbox/Listbox.svelte.d.ts +16 -101
  89. package/dist/listbox/ListboxButton.svelte +24 -29
  90. package/dist/listbox/ListboxButton.svelte.d.ts +8 -38
  91. package/dist/listbox/ListboxOption.svelte +33 -27
  92. package/dist/listbox/ListboxOption.svelte.d.ts +16 -32
  93. package/dist/listbox/ListboxOptions.svelte +126 -73
  94. package/dist/listbox/ListboxOptions.svelte.d.ts +8 -43
  95. package/dist/listbox/ListboxSelectedOption.svelte +24 -26
  96. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +14 -39
  97. package/dist/listbox/context.svelte.d.ts +76 -0
  98. package/dist/listbox/context.svelte.js +36 -0
  99. package/dist/listbox/index.d.ts +5 -5
  100. package/dist/listbox/index.js +4 -4
  101. package/dist/menu/Menu.svelte +22 -266
  102. package/dist/menu/Menu.svelte.d.ts +7 -37
  103. package/dist/menu/MenuButton.svelte +22 -24
  104. package/dist/menu/MenuButton.svelte.d.ts +8 -39
  105. package/dist/menu/MenuHeading.svelte +12 -16
  106. package/dist/menu/MenuHeading.svelte.d.ts +7 -36
  107. package/dist/menu/MenuItem.svelte +18 -23
  108. package/dist/menu/MenuItem.svelte.d.ts +9 -39
  109. package/dist/menu/MenuItems.svelte +33 -34
  110. package/dist/menu/MenuItems.svelte.d.ts +8 -43
  111. package/dist/menu/MenuSection.svelte +9 -12
  112. package/dist/menu/MenuSection.svelte.d.ts +7 -33
  113. package/dist/menu/MenuSeparator.svelte +9 -12
  114. package/dist/menu/MenuSeparator.svelte.d.ts +7 -33
  115. package/dist/menu/context.svelte.d.ts +2 -1
  116. package/dist/menu/context.svelte.js +212 -2
  117. package/dist/menu/index.d.ts +7 -7
  118. package/dist/menu/index.js +3 -3
  119. package/dist/popover/Popover.svelte +225 -0
  120. package/dist/popover/Popover.svelte.d.ts +15 -0
  121. package/dist/popover/PopoverBackdrop.svelte +83 -0
  122. package/dist/popover/PopoverBackdrop.svelte.d.ts +17 -0
  123. package/dist/popover/PopoverButton.svelte +324 -0
  124. package/dist/popover/PopoverButton.svelte.d.ts +21 -0
  125. package/dist/popover/PopoverGroup.svelte +66 -0
  126. package/dist/popover/PopoverGroup.svelte.d.ts +9 -0
  127. package/dist/popover/PopoverPanel.svelte +359 -0
  128. package/dist/popover/PopoverPanel.svelte.d.ts +22 -0
  129. package/dist/popover/context.svelte.d.ts +51 -0
  130. package/dist/popover/context.svelte.js +108 -0
  131. package/dist/popover/index.d.ts +5 -0
  132. package/dist/popover/index.js +5 -0
  133. package/dist/portal/InternalPortal.svelte +17 -17
  134. package/dist/portal/InternalPortal.svelte.d.ts +6 -33
  135. package/dist/portal/Portal.svelte +7 -6
  136. package/dist/portal/Portal.svelte.d.ts +3 -22
  137. package/dist/portal/PortalGroup.svelte +6 -14
  138. package/dist/portal/PortalGroup.svelte.d.ts +5 -34
  139. package/dist/radio-group/Radio.svelte +135 -0
  140. package/dist/radio-group/Radio.svelte.d.ts +35 -0
  141. package/dist/radio-group/RadioGroup.svelte +223 -0
  142. package/dist/radio-group/RadioGroup.svelte.d.ts +34 -0
  143. package/dist/radio-group/RadioOption.svelte +138 -0
  144. package/dist/radio-group/RadioOption.svelte.d.ts +37 -0
  145. package/dist/radio-group/contest.svelte.d.ts +30 -0
  146. package/dist/radio-group/contest.svelte.js +40 -0
  147. package/dist/radio-group/index.d.ts +3 -0
  148. package/dist/radio-group/index.js +3 -0
  149. package/dist/select/Select.svelte +112 -0
  150. package/dist/select/Select.svelte.d.ts +21 -0
  151. package/dist/select/index.d.ts +1 -0
  152. package/dist/select/index.js +1 -0
  153. package/dist/switch/Switch.svelte +27 -28
  154. package/dist/switch/Switch.svelte.d.ts +9 -42
  155. package/dist/switch/SwitchGroup.svelte +5 -5
  156. package/dist/switch/SwitchGroup.svelte.d.ts +8 -30
  157. package/dist/switch/index.d.ts +1 -1
  158. package/dist/switch/index.js +1 -1
  159. package/dist/tabs/Tab.svelte +26 -29
  160. package/dist/tabs/Tab.svelte.d.ts +8 -36
  161. package/dist/tabs/TabGroup.svelte +42 -264
  162. package/dist/tabs/TabGroup.svelte.d.ts +7 -57
  163. package/dist/tabs/TabList.svelte +13 -16
  164. package/dist/tabs/TabList.svelte.d.ts +8 -31
  165. package/dist/tabs/TabPanel.svelte +19 -19
  166. package/dist/tabs/TabPanel.svelte.d.ts +8 -38
  167. package/dist/tabs/TabPanels.svelte +11 -9
  168. package/dist/tabs/TabPanels.svelte.d.ts +8 -30
  169. package/dist/tabs/context.svelte.d.ts +31 -0
  170. package/dist/tabs/context.svelte.js +134 -0
  171. package/dist/tabs/index.d.ts +5 -5
  172. package/dist/tabs/index.js +4 -4
  173. package/dist/textarea/Textarea.svelte +23 -19
  174. package/dist/textarea/Textarea.svelte.d.ts +18 -30
  175. package/dist/textarea/index.d.ts +1 -1
  176. package/dist/textarea/index.js +1 -1
  177. package/dist/transition/InternalTransitionChild.svelte +19 -12
  178. package/dist/transition/InternalTransitionChild.svelte.d.ts +4 -35
  179. package/dist/transition/Transition.svelte +16 -17
  180. package/dist/transition/Transition.svelte.d.ts +8 -38
  181. package/dist/transition/TransitionChild.svelte +13 -12
  182. package/dist/transition/TransitionChild.svelte.d.ts +11 -38
  183. package/dist/transition/context.svelte.js +9 -9
  184. package/dist/transition/index.d.ts +2 -2
  185. package/dist/transition/index.js +2 -2
  186. package/dist/utils/DisabledProvider.svelte +10 -0
  187. package/dist/utils/DisabledProvider.svelte.d.ts +8 -0
  188. package/dist/utils/ElementOrComponent.svelte +57 -14
  189. package/dist/utils/ElementOrComponent.svelte.d.ts +19 -29
  190. package/dist/utils/StableCollection.svelte.d.ts +4 -18
  191. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +32 -0
  192. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte.d.ts +8 -0
  193. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +94 -0
  194. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte.d.ts +26 -0
  195. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.d.ts +6 -0
  196. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +158 -0
  197. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.d.ts +11 -0
  198. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +53 -0
  199. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.d.ts +9 -0
  200. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.js +28 -0
  201. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.d.ts +23 -0
  202. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.js +72 -0
  203. package/dist/utils/floating-ui/svelte/index.d.ts +5 -0
  204. package/dist/utils/floating-ui/svelte/index.js +5 -0
  205. package/dist/utils/floating-ui/svelte/inner.svelte.d.ts +83 -0
  206. package/dist/utils/floating-ui/svelte/inner.svelte.js +178 -0
  207. package/dist/utils/floating-ui/svelte/types.d.ts +114 -0
  208. package/dist/utils/floating-ui/svelte/utils/createPubSub.d.ts +5 -0
  209. package/dist/utils/floating-ui/svelte/utils/createPubSub.js +14 -0
  210. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.d.ts +2 -0
  211. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.js +13 -0
  212. package/dist/utils/floating-ui/svelte/utils/log.d.ts +2 -0
  213. package/dist/utils/floating-ui/svelte/utils/log.js +19 -0
  214. package/dist/utils/floating-ui/svelte/utils.d.ts +19 -0
  215. package/dist/utils/floating-ui/svelte/utils.js +136 -0
  216. package/dist/utils/floating-ui/svelte-dom/arrow.d.ts +22 -0
  217. package/dist/utils/floating-ui/svelte-dom/arrow.js +29 -0
  218. package/dist/utils/floating-ui/svelte-dom/index.d.ts +2 -0
  219. package/dist/utils/floating-ui/svelte-dom/index.js +2 -0
  220. package/dist/utils/floating-ui/svelte-dom/types.d.ts +80 -0
  221. package/dist/utils/floating-ui/svelte-dom/types.js +3 -0
  222. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.d.ts +6 -0
  223. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +182 -0
  224. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.d.ts +1 -0
  225. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.js +50 -0
  226. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.d.ts +1 -0
  227. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.js +7 -0
  228. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.d.ts +1 -0
  229. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.js +5 -0
  230. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.d.ts +4 -0
  231. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.js +7 -0
  232. package/dist/utils/id.d.ts +1 -1
  233. package/dist/utils/id.js +1 -1
  234. package/dist/utils/index.d.ts +3 -0
  235. package/dist/utils/index.js +3 -0
  236. package/dist/utils/state.js +4 -4
  237. package/dist/utils/style.d.ts +2 -0
  238. package/dist/utils/style.js +6 -0
  239. package/dist/utils/types.d.ts +12 -18
  240. package/package.json +33 -32
  241. package/dist/combobox/Combobox.svelte +0 -53
  242. package/dist/combobox/Combobox.svelte.d.ts +0 -50
  243. package/dist/dialog/InternalDialog.svelte +0 -294
  244. package/dist/dialog/InternalDialog.svelte.d.ts +0 -42
  245. package/dist/internal/HoistFormFields.svelte +0 -14
  246. package/dist/internal/HoistFormFields.svelte.d.ts +0 -21
  247. package/dist/internal/id.d.ts +0 -8
  248. package/dist/internal/id.js +0 -11
  249. package/dist/utils/Generic.svelte +0 -56
  250. package/dist/utils/Generic.svelte.d.ts +0 -35
  251. package/dist/utils/alternative-types.d.ts +0 -21
  252. /package/dist/utils/{alternative-types.js → floating-ui/svelte/types.js} +0 -0
@@ -1,8 +1,8 @@
1
1
  import { getContext, setContext } from "svelte";
2
2
  export function useDescriptionContext() {
3
- let context = getContext("DescriptionContext");
4
- if (context === null) {
5
- let err = new Error("You used a <Description /> component, but it is not inside a relevant parent.");
3
+ const context = getContext("DescriptionContext");
4
+ if (!context) {
5
+ const err = new Error("You used a <Description /> component, but it is not inside a relevant parent.");
6
6
  if (Error.captureStackTrace)
7
7
  Error.captureStackTrace(err, useDescriptionContext);
8
8
  throw err;
@@ -18,10 +18,19 @@ export function useDescribedBy() {
18
18
  };
19
19
  }
20
20
  export const useDescriptions = (options = {}) => {
21
- const { slot, name, props, inherit } = $derived(options);
22
- let descriptionIds = $state([]);
21
+ const { slot, name, props } = $derived(options);
22
+ const descriptionIds = $state([]);
23
+ const register = (value) => {
24
+ descriptionIds.push(value);
25
+ return () => {
26
+ const idx = descriptionIds.indexOf(value);
27
+ if (idx !== -1)
28
+ descriptionIds.splice(idx, 1);
29
+ };
30
+ };
23
31
  const value = $derived(descriptionIds.length > 0 ? descriptionIds.join(" ") : undefined);
24
32
  const context = {
33
+ register,
25
34
  get slot() {
26
35
  return slot;
27
36
  },
@@ -34,17 +43,6 @@ export const useDescriptions = (options = {}) => {
34
43
  get value() {
35
44
  return value;
36
45
  },
37
- register(value) {
38
- descriptionIds.push(value);
39
- return () => {
40
- const clone = descriptionIds.slice();
41
- const idx = clone.indexOf(value);
42
- if (idx !== -1)
43
- clone.splice(idx, 1);
44
- descriptionIds = clone;
45
- return descriptionIds;
46
- };
47
- },
48
46
  };
49
47
  setContext("DescriptionContext", context);
50
48
  return context;
@@ -1 +1 @@
1
- export { default as Description, type DescriptionProps } from "./Description.svelte";
1
+ export { default as Description, type DescriptionProps, type DescriptionOwnProps } from "./Description.svelte";
@@ -1,13 +1,9 @@
1
1
  <script lang="ts" module>
2
- import { MainTreeProvider } from "../hooks/use-root-containers.svelte.js"
3
- import { useOpenClosed } from "../internal/open-closed.js"
2
+ import type { Props } from "../utils/types.js"
4
3
  import { RenderFeatures, type PropsForFeatures } from "../utils/render.js"
5
- import type { ElementType, Props } from "../utils/types.js"
6
- import { getContext, type Component, type Snippet } from "svelte"
7
- import InternalDialog from "./InternalDialog.svelte"
8
- import Transition from "../transition/Transition.svelte"
9
4
 
10
5
  export const DEFAULT_DIALOG_TAG = "div" as const
6
+
11
7
  export type DialogRenderPropArg = {
12
8
  open: boolean
13
9
  }
@@ -15,31 +11,51 @@
15
11
 
16
12
  export const DialogRenderFeatures = RenderFeatures.RenderStrategy | RenderFeatures.Static
17
13
 
18
- export type DialogProps<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> = Props<
19
- TTag,
20
- DialogRenderPropArg,
21
- DialogPropsWeControl,
22
- PropsForFeatures<typeof DialogRenderFeatures> & {
23
- id?: string
24
- open?: boolean
25
- onclose(value: boolean): void
26
- initialFocus?: HTMLElement
27
- role?: "dialog" | "alertdialog"
28
- autofocus?: boolean
29
- transition?: boolean
30
- __demoMode?: boolean
31
- }
32
- >
14
+ export type DialogOwnProps = PropsForFeatures<typeof DialogRenderFeatures> & {
15
+ element?: HTMLElement
16
+ id?: string
17
+ open?: boolean
18
+ onclose(value: boolean): void
19
+ initialFocus?: HTMLElement
20
+ role?: "dialog" | "alertdialog"
21
+ autofocus?: boolean
22
+ transition?: boolean
23
+ __demoMode?: boolean
24
+ }
33
25
 
34
- export type DialogChildren = Snippet<[DialogRenderPropArg]>
26
+ export type DialogProps = Props<typeof DEFAULT_DIALOG_TAG, DialogRenderPropArg, DialogOwnProps>
35
27
  </script>
36
28
 
37
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_DIALOG_TAG">
38
- let { ref = $bindable(), transition = false, open, ...rest }: { as?: TTag } & DialogProps<TTag> = $props()
29
+ <script lang="ts">
30
+ import { useId } from "../hooks/use-id.js"
31
+ import { useMainTreeNode, useRootContainers } from "../hooks/use-root-containers.svelte.js"
32
+ import { clearOpenClosedContext, State, useOpenClosed } from "../internal/open-closed.js"
33
+ import { useNestedPortals } from "../portal/InternalPortal.svelte"
34
+ import { getOwnerDocument } from "../utils/owner.js"
35
+ import { useInertOthers } from "../hooks/use-inert-others.svelte.js"
36
+ import { useOutsideClick } from "../hooks/use-outside-click.svelte.js"
37
+ import { useEscape } from "../hooks/use-escape.svelte.js"
38
+ import { useScrollLock } from "../hooks/use-scroll-lock.svelte.js"
39
+ import { useOnDisappear } from "../hooks/use-on-disappear.svelte.js"
40
+ import { setContext } from "svelte"
41
+ import { useIsTouchDevice } from "../hooks/use-is-touch-device.svelte.js"
42
+ import FocusTrap, { FocusTrapFeatures } from "../focus-trap/FocusTrap.svelte"
43
+ import Portal from "../portal/Portal.svelte"
44
+ import PortalGroup from "../portal/PortalGroup.svelte"
45
+ import ForcePortalRoot from "../internal/ForcePortalRoot.svelte"
46
+ import { createCloseContext } from "../internal/close-provider.js"
47
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte"
48
+ import { DialogStates, type DialogContext, type StateDefinition } from "./context.svelte.js"
49
+ import { useDescriptions } from "../description/context.svelte.js"
50
+ import MainTreeProvider from "../internal/MainTreeProvider.svelte"
51
+ import Transition from "../transition/Transition.svelte"
52
+ import { BROWSER } from "esm-env"
53
+
54
+ let { element = $bindable(), transition = false, open: theirOpen, ...rest }: DialogProps = $props()
39
55
 
40
56
  // Validations
41
57
  const usesOpenClosedState = useOpenClosed()
42
- const hasOpen = $derived(open !== undefined || usesOpenClosedState)
58
+ const hasOpen = $derived(theirOpen !== undefined || usesOpenClosedState)
43
59
  const hasOnClose = $derived(rest.hasOwnProperty("onclose"))
44
60
 
45
61
  $effect(() => {
@@ -68,19 +84,287 @@
68
84
  }
69
85
  })
70
86
 
71
- const DialogComponent = InternalDialog as Component<DialogProps<TTag>, any>
87
+ const internalId = useId()
88
+ let {
89
+ id = `headlessui-dialog-${internalId}`,
90
+ onclose,
91
+ initialFocus,
92
+ role: theirRole = "dialog",
93
+ autofocus = true,
94
+ __demoMode = false,
95
+ unmount = false,
96
+ ...theirProps
97
+ } = $derived(rest)
98
+
99
+ let didWarnOnRole = $state(false)
100
+
101
+ const role = $derived.by(() => {
102
+ if (theirRole === "dialog" || theirRole === "alertdialog") {
103
+ return theirRole
104
+ }
105
+
106
+ if (!didWarnOnRole) {
107
+ didWarnOnRole = true
108
+ console.warn(
109
+ `Invalid role [${theirRole}] passed to <Dialog />. Only \`dialog\` and and \`alertdialog\` are supported. Using \`dialog\` instead.`
110
+ )
111
+ }
112
+
113
+ return "dialog"
114
+ })
115
+
116
+ // Update the `open` prop based on the open closed state
117
+ const open = $derived(
118
+ theirOpen === undefined && usesOpenClosedState !== null
119
+ ? (usesOpenClosedState.value & State.Open) === State.Open
120
+ : theirOpen
121
+ )
122
+
123
+ const ownerDocument = $derived(getOwnerDocument(element))
124
+
125
+ const dialogState = $derived(open ? DialogStates.Open : DialogStates.Closed)
126
+
127
+ let _state = $state({
128
+ titleId: null,
129
+ panelRef: null,
130
+ } as StateDefinition)
131
+
132
+ const close = $derived(() => onclose(false))
133
+
134
+ const setTitleId = (id: string | null) => (_state.titleId = id)
135
+
136
+ const ready = BROWSER
137
+ const enabled = $derived(ready ? dialogState === DialogStates.Open : false)
138
+ const nestedPortals = useNestedPortals()
139
+ const { portals } = $derived(nestedPortals)
140
+
141
+ // We use this because reading these values during initial render(s)
142
+ // can result in `null` rather then the actual elements
143
+ // This doesn't happen when using certain components like a
144
+ // `<Dialog.Title>` because they cause the parent to re-render
145
+ const defaultContainer: { readonly current: HTMLElement | undefined } = {
146
+ get current() {
147
+ return _state.panelRef ?? element
148
+ },
149
+ }
150
+
151
+ const mainTreeNode = useMainTreeNode()
152
+ let { resolvedContainers: resolvedRootContainers } = $derived(
153
+ useRootContainers({
154
+ get mainTreeNode() {
155
+ return mainTreeNode.node
156
+ },
157
+ get portals() {
158
+ return portals
159
+ },
160
+ get defaultContainers() {
161
+ return defaultContainer.current ? [defaultContainer.current] : []
162
+ },
163
+ })
164
+ )
165
+
166
+ // When the `Dialog` is wrapped in a `Transition` (or another Headless UI component that exposes
167
+ // the OpenClosed state) then we get some information via context about its state. When the
168
+ // `Transition` is about to close, then the `State.Closing` state will be exposed. This allows us
169
+ // to enable/disable certain functionality in the `Dialog` upfront instead of waiting until the
170
+ // `Transition` is done transitioning.
171
+ const isClosing = $derived(
172
+ usesOpenClosedState !== null ? (usesOpenClosedState.value & State.Closing) === State.Closing : false
173
+ )
174
+
175
+ // Ensure other elements can't be interacted with
176
+ const inertOthersEnabled = $derived(__demoMode ? false : isClosing ? false : enabled)
177
+ useInertOthers({
178
+ get enabled() {
179
+ return inertOthersEnabled
180
+ },
181
+ elements: {
182
+ get allowed() {
183
+ return [
184
+ // Allow the headlessui-portal of the Dialog to be interactive. This
185
+ // contains the current dialog and the necessary focus guard elements.
186
+ element?.closest<HTMLElement>("[data-headlessui-portal]") ?? null,
187
+ ]
188
+ },
189
+ get disallowed() {
190
+ return [
191
+ // Disallow the "main" tree root node
192
+ mainTreeNode.node?.closest<HTMLElement>("body > *:not(#headlessui-portal-root)") ?? null,
193
+ ]
194
+ },
195
+ },
196
+ })
197
+
198
+ // Close Dialog on outside click
199
+ useOutsideClick({
200
+ get enabled() {
201
+ return enabled
202
+ },
203
+ get containers() {
204
+ return resolvedRootContainers
205
+ },
206
+ cb(event) {
207
+ event.preventDefault()
208
+ close()
209
+ },
210
+ })
211
+
212
+ // Handle `Escape` to close
213
+ useEscape({
214
+ get enabled() {
215
+ return enabled
216
+ },
217
+ get view() {
218
+ return ownerDocument?.defaultView ?? null
219
+ },
220
+ cb(event) {
221
+ event.preventDefault()
222
+ event.stopPropagation()
223
+
224
+ // Ensure that we blur the current activeElement to prevent maintaining
225
+ // focus and potentially scrolling the page to the end (because the Dialog
226
+ // is rendered in a Portal at the end of the document.body and the browser
227
+ // tries to keep the focused element in view)
228
+ //
229
+ // Typically only happens in Safari.
230
+ if (
231
+ document.activeElement &&
232
+ "blur" in document.activeElement &&
233
+ typeof document.activeElement.blur === "function"
234
+ ) {
235
+ document.activeElement.blur()
236
+ }
237
+
238
+ close()
239
+ },
240
+ })
241
+
242
+ // Scroll lock
243
+ const scrollLockEnabled = $derived(__demoMode ? false : isClosing ? false : enabled)
244
+ useScrollLock({
245
+ get enabled() {
246
+ return scrollLockEnabled
247
+ },
248
+ get ownerDocument() {
249
+ return ownerDocument
250
+ },
251
+ resolveAllowedContainers() {
252
+ return resolvedRootContainers
253
+ },
254
+ })
255
+
256
+ // Ensure we close the dialog as soon as the dialog itself becomes hidden
257
+ useOnDisappear({
258
+ get enabled() {
259
+ return enabled
260
+ },
261
+ get ref() {
262
+ return element
263
+ },
264
+ get ondisappear() {
265
+ return close
266
+ },
267
+ })
268
+
269
+ const describedby = useDescriptions()
270
+
271
+ setContext<DialogContext>("DialogContext", {
272
+ get titleId() {
273
+ return _state.titleId
274
+ },
275
+ get panelRef() {
276
+ return _state.panelRef
277
+ },
278
+ get dialogState() {
279
+ return dialogState
280
+ },
281
+ get close() {
282
+ return close
283
+ },
284
+ get unmount() {
285
+ return unmount
286
+ },
287
+ setTitleId,
288
+ })
289
+
290
+ const slot = $derived({ open: dialogState === DialogStates.Open } satisfies DialogRenderPropArg)
291
+
292
+ const ourProps = $derived({
293
+ id,
294
+ role,
295
+ tabIndex: -1,
296
+ "aria-modal": __demoMode ? undefined : dialogState === DialogStates.Open ? true : undefined,
297
+ "aria-labelledby": _state.titleId,
298
+ "aria-describedby": describedby.value,
299
+ unmount,
300
+ })
301
+
302
+ const shouldMoveFocusInside = !useIsTouchDevice().value
303
+ const focusTrapFeatures = $derived.by(() => {
304
+ let focusTrapFeatures = FocusTrapFeatures.None
305
+
306
+ if (enabled && !__demoMode) {
307
+ focusTrapFeatures |= FocusTrapFeatures.RestoreFocus
308
+ focusTrapFeatures |= FocusTrapFeatures.TabLock
309
+
310
+ if (autofocus) {
311
+ focusTrapFeatures |= FocusTrapFeatures.AutoFocus
312
+ }
313
+
314
+ if (shouldMoveFocusInside) {
315
+ focusTrapFeatures |= FocusTrapFeatures.InitialFocus
316
+ }
317
+ }
318
+
319
+ return focusTrapFeatures
320
+ })
321
+
322
+ clearOpenClosedContext()
323
+ createCloseContext({
324
+ get close() {
325
+ return close
326
+ },
327
+ })
72
328
  </script>
73
329
 
74
- {#if (open !== undefined || transition) && !rest.static}
330
+ {#snippet internal(transitionProps?: Record<string, any>)}
331
+ <ForcePortalRoot force={true}>
332
+ <Portal>
333
+ <PortalGroup target={element ?? null}>
334
+ <ForcePortalRoot force={false}>
335
+ <FocusTrap
336
+ {initialFocus}
337
+ initialFocusFallback={element}
338
+ containers={resolvedRootContainers}
339
+ features={focusTrapFeatures}
340
+ >
341
+ <ElementOrComponent
342
+ {ourProps}
343
+ theirProps={{ ...theirProps, ...transitionProps }}
344
+ slots={slot}
345
+ defaultTag={DEFAULT_DIALOG_TAG}
346
+ features={DialogRenderFeatures}
347
+ visible={dialogState === DialogStates.Open}
348
+ name="Dialog"
349
+ bind:element
350
+ />
351
+ </FocusTrap>
352
+ </ForcePortalRoot>
353
+ </PortalGroup>
354
+ </Portal>
355
+ </ForcePortalRoot>
356
+ {/snippet}
357
+
358
+ {#if (open !== undefined || transition) && !theirProps.static}
75
359
  <MainTreeProvider>
76
- <Transition show={open} {transition} unmount={rest.unmount} {ref}>
77
- {#snippet children(slot, props)}
78
- <DialogComponent bind:ref {...props} {...rest} />
360
+ <Transition asChild show={open} {transition} unmount={rest.unmount} {element}>
361
+ {#snippet children({ props })}
362
+ {@render internal(props)}
79
363
  {/snippet}
80
364
  </Transition>
81
365
  </MainTreeProvider>
82
366
  {:else}
83
367
  <MainTreeProvider>
84
- <DialogComponent bind:ref {open} {...rest} />
368
+ {@render internal()}
85
369
  </MainTreeProvider>
86
370
  {/if}
@@ -1,13 +1,12 @@
1
+ import type { Props } from "../utils/types.js";
1
2
  import { type PropsForFeatures } from "../utils/render.js";
2
- import type { ElementType, Props } from "../utils/types.js";
3
- import { type Snippet } from "svelte";
4
3
  export declare const DEFAULT_DIALOG_TAG: "div";
5
4
  export type DialogRenderPropArg = {
6
5
  open: boolean;
7
6
  };
8
- type DialogPropsWeControl = "aria-describedby" | "aria-labelledby" | "aria-modal";
9
7
  export declare const DialogRenderFeatures: number;
10
- export type DialogProps<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> = Props<TTag, DialogRenderPropArg, DialogPropsWeControl, PropsForFeatures<typeof DialogRenderFeatures> & {
8
+ export type DialogOwnProps = PropsForFeatures<typeof DialogRenderFeatures> & {
9
+ element?: HTMLElement;
11
10
  id?: string;
12
11
  open?: boolean;
13
12
  onclose(value: boolean): void;
@@ -16,45 +15,8 @@ export type DialogProps<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> =
16
15
  autofocus?: boolean;
17
16
  transition?: boolean;
18
17
  __demoMode?: boolean;
19
- }>;
20
- export type DialogChildren = Snippet<[DialogRenderPropArg]>;
21
- declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> {
22
- props(): {
23
- as?: TTag | undefined;
24
- } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("as" | "children" | "refName" | "class") | "autofocus" | "unmount" | "static" | "id" | "role" | "onclose" | "initialFocus" | DialogPropsWeControl | "open" | "transition" | "__demoMode"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
25
- children?: import("../utils/types.js").Children<DialogRenderPropArg> | undefined;
26
- ref?: HTMLElement;
27
- } & (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) ? {
28
- class?: import("../utils/types.js").PropsOf<TTag>["class"] | ((bag: DialogRenderPropArg) => string) | undefined;
29
- } : {}) & {
30
- static?: boolean | undefined;
31
- unmount?: boolean | undefined;
32
- } & {
33
- id?: string;
34
- open?: boolean;
35
- onclose(value: boolean): void;
36
- initialFocus?: HTMLElement;
37
- role?: "dialog" | "alertdialog";
38
- autofocus?: boolean;
39
- transition?: boolean;
40
- __demoMode?: boolean;
41
- };
42
- events(): {} & {
43
- [evt: string]: CustomEvent<any>;
44
- };
45
- slots(): {};
46
- bindings(): "ref";
47
- exports(): {};
48
- }
49
- interface $$IsomorphicComponent {
50
- new <TTag extends ElementType = typeof DEFAULT_DIALOG_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']>> & {
51
- $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
52
- } & ReturnType<__sveltets_Render<TTag>['exports']>;
53
- <TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {
54
- $$events?: ReturnType<__sveltets_Render<TTag>['events']>;
55
- }): ReturnType<__sveltets_Render<TTag>['exports']>;
56
- z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
57
- }
58
- declare const Dialog: $$IsomorphicComponent;
59
- type Dialog<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> = InstanceType<typeof Dialog<TTag>>;
18
+ };
19
+ export type DialogProps = Props<typeof DEFAULT_DIALOG_TAG, DialogRenderPropArg, DialogOwnProps>;
20
+ declare const Dialog: import("svelte").Component<DialogProps, {}, "element">;
21
+ type Dialog = ReturnType<typeof Dialog>;
60
22
  export default Dialog;
@@ -1,26 +1,23 @@
1
1
  <script lang="ts" module>
2
- import type { ElementType, Props } from "../utils/types.js"
2
+ import type { Props } from "../utils/types.js"
3
3
 
4
4
  let DEFAULT_BACKDROP_TAG = "div" as const
5
- type BackdropRenderPropArg = {
5
+ export type BackdropRenderPropArg = {
6
6
  open: boolean
7
7
  }
8
8
 
9
- export type DialogBackdropProps<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> = Props<
10
- TTag,
11
- BackdropRenderPropArg,
12
- never,
13
- { transition?: boolean }
14
- >
9
+ export type DialogBackdropOwnProps = { transition?: boolean; element?: HTMLElement }
10
+
11
+ export type DialogBackdropProps = Props<typeof DEFAULT_BACKDROP_TAG, BackdropRenderPropArg, DialogBackdropOwnProps>
15
12
  </script>
16
13
 
17
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG">
14
+ <script lang="ts">
18
15
  import { DialogStates, useDialogContext } from "./context.svelte.js"
19
16
  import ElementOrComponent from "../utils/ElementOrComponent.svelte"
20
17
  import { mergeProps } from "../utils/render.js"
21
18
  import TransitionChild from "../transition/TransitionChild.svelte"
22
19
 
23
- let { ref = $bindable(), transition = false, ...theirProps }: { as?: TTag } & DialogBackdropProps<TTag> = $props()
20
+ let { element = $bindable(), transition = false, ...theirProps }: DialogBackdropProps = $props()
24
21
  const _state = useDialogContext("Dialog.Panel")
25
22
  const { dialogState, unmount } = $derived(_state)
26
23
 
@@ -32,15 +29,15 @@
32
29
  </script>
33
30
 
34
31
  {#if transition}
35
- <TransitionChild {unmount} {ref}>
36
- {#snippet children(slot, props)}
32
+ <TransitionChild asChild {unmount} {element}>
33
+ {#snippet children({ props, ...slot })}
37
34
  <ElementOrComponent
38
35
  ourProps={{ ...ourProps, ...props }}
39
36
  {theirProps}
40
37
  slots={slot}
41
38
  defaultTag={DEFAULT_BACKDROP_TAG}
42
39
  name="DialogBackdrop"
43
- bind:ref
40
+ bind:element
44
41
  />
45
42
  {/snippet}
46
43
  </TransitionChild>
@@ -51,6 +48,6 @@
51
48
  slots={slot}
52
49
  defaultTag={DEFAULT_BACKDROP_TAG}
53
50
  name="DialogBackdrop"
54
- bind:ref
51
+ bind:element
55
52
  />
56
53
  {/if}
@@ -1,38 +1,13 @@
1
- import type { ElementType, Props } from "../utils/types.js";
1
+ import type { Props } from "../utils/types.js";
2
2
  declare let DEFAULT_BACKDROP_TAG: "div";
3
- type BackdropRenderPropArg = {
3
+ export type BackdropRenderPropArg = {
4
4
  open: boolean;
5
5
  };
6
- export type DialogBackdropProps<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> = Props<TTag, BackdropRenderPropArg, never, {
6
+ export type DialogBackdropOwnProps = {
7
7
  transition?: boolean;
8
- }>;
9
- declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> {
10
- props(): {
11
- as?: TTag | undefined;
12
- } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("as" | "children" | "refName" | "class") | "transition"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
13
- children?: import("../utils/types.js").Children<BackdropRenderPropArg> | undefined;
14
- ref?: HTMLElement;
15
- } & (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) ? {
16
- class?: import("../utils/types.js").PropsOf<TTag>["class"] | ((bag: BackdropRenderPropArg) => string) | undefined;
17
- } : {}) & {
18
- transition?: boolean;
19
- };
20
- events(): {} & {
21
- [evt: string]: CustomEvent<any>;
22
- };
23
- slots(): {};
24
- bindings(): "ref";
25
- exports(): {};
26
- }
27
- interface $$IsomorphicComponent {
28
- new <TTag extends ElementType = typeof DEFAULT_BACKDROP_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']>> & {
29
- $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
30
- } & ReturnType<__sveltets_Render<TTag>['exports']>;
31
- <TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {
32
- $$events?: ReturnType<__sveltets_Render<TTag>['events']>;
33
- }): ReturnType<__sveltets_Render<TTag>['exports']>;
34
- z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
35
- }
36
- declare const DialogBackdrop: $$IsomorphicComponent;
37
- type DialogBackdrop<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> = InstanceType<typeof DialogBackdrop<TTag>>;
8
+ element?: HTMLElement;
9
+ };
10
+ export type DialogBackdropProps = Props<typeof DEFAULT_BACKDROP_TAG, BackdropRenderPropArg, DialogBackdropOwnProps>;
11
+ declare const DialogBackdrop: import("svelte").Component<DialogBackdropProps, {}, "element">;
12
+ type DialogBackdrop = ReturnType<typeof DialogBackdrop>;
38
13
  export default DialogBackdrop;