@pzerelles/headlessui-svelte 2.1.2-next.31 → 2.1.2-next.33

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