@pzerelles/headlessui-svelte 2.1.2-next.29 → 2.1.2-next.30

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 (67) hide show
  1. package/dist/button/Button.svelte +54 -84
  2. package/dist/checkbox/Checkbox.svelte +120 -173
  3. package/dist/checkbox/Checkbox.svelte.d.ts +1 -1
  4. package/dist/close-button/CloseButton.svelte +6 -12
  5. package/dist/combobox/Combobox.svelte +3 -50
  6. package/dist/data-interactive/DataInteractive.svelte +29 -55
  7. package/dist/description/Description.svelte +21 -31
  8. package/dist/dialog/Dialog.svelte +228 -320
  9. package/dist/dialog/DialogBackdrop.svelte +12 -29
  10. package/dist/dialog/DialogPanel.svelte +25 -48
  11. package/dist/dialog/DialogTitle.svelte +23 -38
  12. package/dist/field/Field.svelte +25 -47
  13. package/dist/fieldset/Fieldset.svelte +29 -50
  14. package/dist/focus-trap/FocusTrap.svelte +283 -419
  15. package/dist/input/Input.svelte +53 -84
  16. package/dist/internal/FloatingProvider.svelte +9 -14
  17. package/dist/internal/FocusSentinel.svelte +8 -16
  18. package/dist/internal/ForcePortalRoot.svelte +3 -7
  19. package/dist/internal/FormFields.svelte +34 -47
  20. package/dist/internal/FormFieldsProvider.svelte +5 -9
  21. package/dist/internal/FormResolver.svelte +15 -20
  22. package/dist/internal/Hidden.svelte +29 -50
  23. package/dist/internal/MainTreeProvider.svelte +36 -89
  24. package/dist/internal/Portal.svelte +14 -18
  25. package/dist/label/Label.svelte +58 -93
  26. package/dist/legend/Legend.svelte +3 -12
  27. package/dist/listbox/Listbox.svelte +387 -525
  28. package/dist/listbox/Listbox.svelte.d.ts +1 -1
  29. package/dist/listbox/ListboxButton.svelte +127 -173
  30. package/dist/listbox/ListboxOption.svelte +129 -170
  31. package/dist/listbox/ListboxOptions.svelte +304 -400
  32. package/dist/listbox/ListboxSelectedOption.svelte +15 -38
  33. package/dist/menu/Menu.svelte +51 -78
  34. package/dist/menu/MenuButton.svelte +117 -157
  35. package/dist/menu/MenuHeading.svelte +14 -32
  36. package/dist/menu/MenuItem.svelte +107 -142
  37. package/dist/menu/MenuItems.svelte +229 -301
  38. package/dist/menu/MenuSection.svelte +9 -24
  39. package/dist/menu/MenuSeparator.svelte +4 -17
  40. package/dist/popover/Popover.svelte +150 -216
  41. package/dist/popover/PopoverBackdrop.svelte +41 -67
  42. package/dist/popover/PopoverButton.svelte +212 -292
  43. package/dist/popover/PopoverGroup.svelte +35 -62
  44. package/dist/popover/PopoverPanel.svelte +229 -311
  45. package/dist/portal/InternalPortal.svelte +85 -141
  46. package/dist/portal/Portal.svelte +2 -5
  47. package/dist/portal/PortalGroup.svelte +9 -30
  48. package/dist/select/Select.svelte +68 -98
  49. package/dist/switch/Switch.svelte +132 -179
  50. package/dist/switch/SwitchGroup.svelte +31 -44
  51. package/dist/tabs/Tab.svelte +142 -194
  52. package/dist/tabs/TabGroup.svelte +56 -86
  53. package/dist/tabs/TabGroup.svelte.d.ts +1 -1
  54. package/dist/tabs/TabList.svelte +11 -31
  55. package/dist/tabs/TabPanel.svelte +42 -67
  56. package/dist/tabs/TabPanels.svelte +7 -18
  57. package/dist/textarea/Textarea.svelte +53 -84
  58. package/dist/transition/InternalTransitionChild.svelte +170 -259
  59. package/dist/transition/Transition.svelte +66 -96
  60. package/dist/transition/TransitionChild.svelte +11 -31
  61. package/dist/utils/DisabledProvider.svelte +3 -7
  62. package/dist/utils/ElementOrComponent.svelte +23 -43
  63. package/dist/utils/Generic.svelte +16 -27
  64. package/dist/utils/StableCollection.svelte +36 -54
  65. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +12 -27
  66. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +44 -88
  67. package/package.json +4 -4
@@ -1,308 +1,228 @@
1
- <script lang="ts" module>
2
- import type { ElementType, Props, PropsOf } from "../utils/types.js"
3
-
4
- const DEFAULT_BUTTON_TAG = "button" as const
5
- export type PopoverButtonSlot = {
6
- open: boolean
7
- active: boolean
8
- hover: boolean
9
- focus: boolean
10
- disabled: boolean
11
- autofocus: boolean
12
- }
13
- export type PopoverButtonPropsWeControl = "aria-controls" | "aria-expanded"
14
-
15
- export type PopoverButtonComponentProps = {
16
- disabled?: boolean
17
- autofocus?: boolean
18
- }
19
-
20
- export type PopoverButtonProps<TTag extends ElementType = typeof DEFAULT_BUTTON_TAG> = Props<
21
- TTag,
22
- PopoverButtonSlot,
23
- PopoverButtonPropsWeControl,
24
- PopoverButtonComponentProps
25
- >
1
+ <script lang="ts" module>const DEFAULT_BUTTON_TAG = "button";
26
2
  </script>
27
3
 
28
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BUTTON_TAG">
29
- import { useId } from "../hooks/use-id.js"
30
- import {
31
- PopoverStates,
32
- usePopoverAPIContext,
33
- usePopoverContext,
34
- usePopoverGroupContext,
35
- usePopoverPanelContext,
36
- } from "./context.svelte.js"
37
- import { useFloatingReference } from "../internal/floating.svelte.js"
38
- import { untrack } from "svelte"
39
- import { getOwnerDocument } from "../utils/owner.js"
40
- import { useFocusRing } from "../hooks/use-focus-ring.svelte.js"
41
- import { useHover } from "../hooks/use-hover.svelte.js"
42
- import { useActivePress } from "../hooks/use-active-press.svelte.js"
43
- import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js"
44
- import { mergeProps } from "../utils/render.js"
45
- import { useTabDirection, Direction as TabDirection } from "../hooks/use-tab-direction.svelte.js"
46
- import { match } from "../utils/match.js"
47
- import { Focus, focusIn, FocusResult, getFocusableElements } from "../utils/focus-management.js"
48
- import { microTask } from "../utils/microTask.js"
49
- import Hidden, { HiddenFeatures } from "../internal/Hidden.svelte"
50
- import ElementOrComponent from "../utils/ElementOrComponent.svelte"
51
- import type { FocusEventHandler } from "svelte/elements"
52
-
53
- const internalId = useId()
54
- let {
55
- ref = $bindable(),
56
- id = `headlessui-popover-button-${internalId}` as PropsOf<TTag>["id"],
57
- disabled = false,
58
- autofocus = false as PropsOf<TTag>["autofocus"],
59
- ...theirProps
60
- }: { as?: TTag } & PopoverButtonProps<TTag> = $props()
61
- const context = usePopoverContext("PopoverButton")
62
- const api = usePopoverAPIContext("PopoverButton")
63
- const { isPortalled } = $derived(api)
64
-
65
- const sentinelId = `headlessui-focus-sentinel-${useId()}`
66
-
67
- const groupContext = usePopoverGroupContext()
68
- const closeOthers = $derived(groupContext?.closeOthers)
69
-
70
- const panelContext = usePopoverPanelContext()
71
-
72
- // A button inside a panel will just have "close" functionality, no "open" functionality. However,
73
- // if a `PopoverButton` is rendered inside a `Popover` which in turn is rendered inside a
74
- // `PopoverPanel` (aka nested popovers), then we need to make sure that the button is able to
75
- // open the nested popover.
76
- //
77
- // The `Popover` itself will also render a `PopoverPanelContext` but with a value of `null`. That
78
- // way we don't need to keep track of _which_ `PopoverPanel` (if at all) we are in, we can just
79
- // check if we are in a `PopoverPanel` or not since this will always point to the nearest one and
80
- // won't pierce through `Popover` components themselves.
81
- const isWithinPanel = panelContext !== undefined
82
-
83
- $effect(() => {
84
- // [isWithinPanel, id, dispatch]
85
- if (isWithinPanel) return
86
- id
87
- return untrack(() => {
88
- context.setButtonId(id)
89
- return () => {
90
- context.setButtonId(undefined)
91
- }
92
- })
93
- })
94
-
95
- // This is a little bit different compared to the `id` we already have. The goal is to have a very
96
- // unique identifier for this specific component. This can be achieved with the `id` from above.
97
- //
98
- // However, the difference is for React 17 and lower where the `useId` hook doesn't exist yet.
99
- // There we will generate a unique ID based on a simple counter, but for SSR this will result in
100
- // `undefined` first, later it is patched to be a unique ID. The problem is that this patching
101
- // happens after the component is rendered and therefore there is a moment in time where multiple
102
- // buttons have the exact same ID and the `state.buttons` would result in something like:
103
- //
104
- // ```js
105
- // ['headlessui-popover-button-undefined', 'headlessui-popover-button-1']
106
- // ```
107
- //
108
- // With this approach we guarantee that there is a unique value for each button.
109
- const uniqueIdentifier = Symbol()
110
-
111
- const floatingReference = useFloatingReference()
112
- const { setReference } = $derived(floatingReference)
113
- $effect(() => {
114
- setReference(ref)
115
- })
116
- $effect(() => {
117
- if (isWithinPanel) return
118
- ref
119
- untrack(() => {
120
- if (ref) {
121
- context.buttons.push(uniqueIdentifier)
122
- } else {
123
- let idx = context.buttons.indexOf(uniqueIdentifier)
124
- if (idx !== -1) context.buttons.splice(idx, 1)
125
- }
126
-
127
- if (context.buttons.length > 1) {
128
- console.warn("You are already using a <PopoverButton /> but only 1 <PopoverButton /> is supported.")
129
- }
130
-
131
- if (ref) context.setButton(ref)
132
- })
133
- })
134
- const ownerDocument = $derived(getOwnerDocument(ref))
135
-
136
- const handleKeyDown = (event: KeyboardEvent) => {
137
- if (isWithinPanel) {
138
- if (context.popoverState === PopoverStates.Closed) return
139
- switch (event.key) {
140
- case "Space":
141
- case "Enter":
142
- event.preventDefault() // Prevent triggering a *click* event
143
- // @ts-expect-error
144
- event.target.click?.()
145
- context.closePopover()
146
- context.button?.focus() // Re-focus the original opening Button
147
- break
148
- }
4
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BUTTON_TAG">import { useId } from "../hooks/use-id.js";
5
+ import {
6
+ PopoverStates,
7
+ usePopoverAPIContext,
8
+ usePopoverContext,
9
+ usePopoverGroupContext,
10
+ usePopoverPanelContext
11
+ } from "./context.svelte.js";
12
+ import { useFloatingReference } from "../internal/floating.svelte.js";
13
+ import { untrack } from "svelte";
14
+ import { getOwnerDocument } from "../utils/owner.js";
15
+ import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
16
+ import { useHover } from "../hooks/use-hover.svelte.js";
17
+ import { useActivePress } from "../hooks/use-active-press.svelte.js";
18
+ import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js";
19
+ import { mergeProps } from "../utils/render.js";
20
+ import { useTabDirection, Direction as TabDirection } from "../hooks/use-tab-direction.svelte.js";
21
+ import { match } from "../utils/match.js";
22
+ import { Focus, focusIn, FocusResult, getFocusableElements } from "../utils/focus-management.js";
23
+ import { microTask } from "../utils/microTask.js";
24
+ import Hidden, { HiddenFeatures } from "../internal/Hidden.svelte";
25
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
26
+ const internalId = useId();
27
+ let {
28
+ ref = $bindable(),
29
+ id = `headlessui-popover-button-${internalId}`,
30
+ disabled = false,
31
+ autofocus = false,
32
+ ...theirProps
33
+ } = $props();
34
+ const context = usePopoverContext("PopoverButton");
35
+ const api = usePopoverAPIContext("PopoverButton");
36
+ const { isPortalled } = $derived(api);
37
+ const sentinelId = `headlessui-focus-sentinel-${useId()}`;
38
+ const groupContext = usePopoverGroupContext();
39
+ const closeOthers = $derived(groupContext?.closeOthers);
40
+ const panelContext = usePopoverPanelContext();
41
+ const isWithinPanel = panelContext !== void 0;
42
+ $effect(() => {
43
+ if (isWithinPanel) return;
44
+ id;
45
+ return untrack(() => {
46
+ context.setButtonId(id);
47
+ return () => {
48
+ context.setButtonId(void 0);
49
+ };
50
+ });
51
+ });
52
+ const uniqueIdentifier = Symbol();
53
+ const floatingReference = useFloatingReference();
54
+ const { setReference } = $derived(floatingReference);
55
+ $effect(() => {
56
+ setReference(ref);
57
+ });
58
+ $effect(() => {
59
+ if (isWithinPanel) return;
60
+ ref;
61
+ untrack(() => {
62
+ if (ref) {
63
+ context.buttons.push(uniqueIdentifier);
149
64
  } else {
150
- switch (event.key) {
151
- case "Space":
152
- case "Enter":
153
- event.preventDefault() // Prevent triggering a *click* event
154
- event.stopPropagation()
155
- if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId!)
156
- context.togglePopover()
157
- break
158
-
159
- case "Escape":
160
- if (context.popoverState !== PopoverStates.Open) return closeOthers?.(context.buttonId!)
161
- if (!ref) return
162
- if (ownerDocument?.activeElement && !ref.contains(ownerDocument.activeElement)) {
163
- return
164
- }
165
- event.preventDefault()
166
- event.stopPropagation()
167
- context.closePopover()
168
- break
169
- }
65
+ let idx = context.buttons.indexOf(uniqueIdentifier);
66
+ if (idx !== -1) context.buttons.splice(idx, 1);
170
67
  }
171
- }
172
-
173
- const handleKeyUp = (event: KeyboardEvent) => {
174
- if (isWithinPanel) return
175
- if (event.key === "Space") {
176
- // Required for firefox, event.preventDefault() in handleKeyDown for
177
- // the Space key doesn't cancel the handleKeyUp, which in turn
178
- // triggers a *click*.
179
- event.preventDefault()
68
+ if (context.buttons.length > 1) {
69
+ console.warn("You are already using a <PopoverButton /> but only 1 <PopoverButton /> is supported.");
180
70
  }
181
- }
182
-
183
- const handleClick = (event: MouseEvent) => {
184
- //if (isDisabledReactIssue7711(event.currentTarget)) return
185
- if (disabled) return
186
- if (isWithinPanel) {
187
- context.closePopover()
188
- context.button?.focus() // Re-focus the original opening Button
189
- } else {
190
- event.preventDefault()
191
- event.stopPropagation()
192
- if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId!)
193
- context.togglePopover()
194
- context.button?.focus()
71
+ if (ref) context.setButton(ref);
72
+ });
73
+ });
74
+ const ownerDocument = $derived(getOwnerDocument(ref));
75
+ const handleKeyDown = (event) => {
76
+ if (isWithinPanel) {
77
+ if (context.popoverState === PopoverStates.Closed) return;
78
+ switch (event.key) {
79
+ case "Space":
80
+ case "Enter":
81
+ event.preventDefault();
82
+ event.target.click?.();
83
+ context.closePopover();
84
+ context.button?.focus();
85
+ break;
86
+ }
87
+ } else {
88
+ switch (event.key) {
89
+ case "Space":
90
+ case "Enter":
91
+ event.preventDefault();
92
+ event.stopPropagation();
93
+ if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId);
94
+ context.togglePopover();
95
+ break;
96
+ case "Escape":
97
+ if (context.popoverState !== PopoverStates.Open) return closeOthers?.(context.buttonId);
98
+ if (!ref) return;
99
+ if (ownerDocument?.activeElement && !ref.contains(ownerDocument.activeElement)) {
100
+ return;
101
+ }
102
+ event.preventDefault();
103
+ event.stopPropagation();
104
+ context.closePopover();
105
+ break;
195
106
  }
196
107
  }
197
-
198
- const handleMouseDown = (event: MouseEvent) => {
199
- event.preventDefault()
200
- event.stopPropagation()
108
+ };
109
+ const handleKeyUp = (event) => {
110
+ if (isWithinPanel) return;
111
+ if (event.key === "Space") {
112
+ event.preventDefault();
201
113
  }
202
-
203
- const { isFocusVisible: focus, focusProps } = $derived(
204
- useFocusRing({
205
- get autofocus() {
206
- return autofocus
207
- },
208
- })
209
- )
210
- const { isHovered: hover, hoverProps } = $derived(
211
- useHover({
212
- get disabled() {
213
- return disabled
214
- },
215
- })
216
- )
217
- const { pressed: active, pressProps } = $derived(
218
- useActivePress({
219
- get disabled() {
220
- return disabled
221
- },
222
- })
223
- )
224
-
225
- const visible = $derived(context.popoverState === PopoverStates.Open)
226
- const slot = $derived({
227
- open: visible,
228
- active: active || visible,
229
- disabled,
230
- hover,
231
- focus,
232
- autofocus,
233
- } satisfies PopoverButtonSlot)
234
-
235
- const type = useResolveButtonType({
236
- get props() {
237
- return { type: theirProps.type, as: theirProps.as }
114
+ };
115
+ const handleClick = (event) => {
116
+ if (disabled) return;
117
+ if (isWithinPanel) {
118
+ context.closePopover();
119
+ context.button?.focus();
120
+ } else {
121
+ event.preventDefault();
122
+ event.stopPropagation();
123
+ if (context.popoverState === PopoverStates.Closed) closeOthers?.(context.buttonId);
124
+ context.togglePopover();
125
+ context.button?.focus();
126
+ }
127
+ };
128
+ const handleMouseDown = (event) => {
129
+ event.preventDefault();
130
+ event.stopPropagation();
131
+ };
132
+ const { isFocusVisible: focus, focusProps } = $derived(
133
+ useFocusRing({
134
+ get autofocus() {
135
+ return autofocus;
136
+ }
137
+ })
138
+ );
139
+ const { isHovered: hover, hoverProps } = $derived(
140
+ useHover({
141
+ get disabled() {
142
+ return disabled;
143
+ }
144
+ })
145
+ );
146
+ const { pressed: active, pressProps } = $derived(
147
+ useActivePress({
148
+ get disabled() {
149
+ return disabled;
150
+ }
151
+ })
152
+ );
153
+ const visible = $derived(context.popoverState === PopoverStates.Open);
154
+ const slot = $derived({
155
+ open: visible,
156
+ active: active || visible,
157
+ disabled,
158
+ hover,
159
+ focus,
160
+ autofocus
161
+ });
162
+ const type = useResolveButtonType({
163
+ get props() {
164
+ return { type: theirProps.type, as: theirProps.as };
165
+ },
166
+ get ref() {
167
+ return { current: context.button };
168
+ }
169
+ });
170
+ const ourProps = $derived(
171
+ isWithinPanel ? mergeProps(
172
+ {
173
+ type,
174
+ onkeydown: handleKeyDown,
175
+ onclick: handleClick,
176
+ disabled: disabled || void 0,
177
+ autofocus
238
178
  },
239
- get ref() {
240
- return { current: context.button }
179
+ focusProps,
180
+ hoverProps,
181
+ pressProps
182
+ ) : mergeProps(
183
+ {
184
+ id: context.buttonId,
185
+ type,
186
+ "aria-expanded": context.popoverState === PopoverStates.Open,
187
+ "aria-controls": context.panel ? context.panelId : void 0,
188
+ disabled: disabled || void 0,
189
+ autofocus,
190
+ onkeydown: handleKeyDown,
191
+ onkeyup: handleKeyUp,
192
+ onclick: handleClick,
193
+ onmousedown: handleMouseDown
241
194
  },
242
- })
243
- const ourProps = $derived(
244
- isWithinPanel
245
- ? mergeProps(
246
- {
247
- type,
248
- onkeydown: handleKeyDown,
249
- onclick: handleClick,
250
- disabled: disabled || undefined,
251
- autofocus,
252
- },
253
- focusProps,
254
- hoverProps,
255
- pressProps
256
- )
257
- : mergeProps(
258
- {
259
- id: context.buttonId,
260
- type,
261
- "aria-expanded": context.popoverState === PopoverStates.Open,
262
- "aria-controls": context.panel ? context.panelId : undefined,
263
- disabled: disabled || undefined,
264
- autofocus,
265
- onkeydown: handleKeyDown,
266
- onkeyup: handleKeyUp,
267
- onclick: handleClick,
268
- onmousedown: handleMouseDown,
269
- },
270
- focusProps,
271
- hoverProps,
272
- pressProps
273
- )
195
+ focusProps,
196
+ hoverProps,
197
+ pressProps
274
198
  )
275
-
276
- const direction = useTabDirection()
277
- const handleFocus = () => {
278
- const el = context.panel as HTMLElement
279
- if (!el) return
280
-
281
- function run() {
282
- let result = match(direction.current, {
283
- [TabDirection.Forwards]: () => focusIn(el, Focus.First),
284
- [TabDirection.Backwards]: () => focusIn(el, Focus.Last),
285
- })
286
-
287
- if (result === FocusResult.Error) {
288
- focusIn(
289
- getFocusableElements().filter((el) => el.dataset.headlessuiFocusGuard !== "true"),
290
- match(direction.current, {
291
- [TabDirection.Forwards]: Focus.Next,
292
- [TabDirection.Backwards]: Focus.Previous,
293
- }),
294
- { relativeTo: context.button }
295
- )
296
- }
297
- }
298
-
299
- // TODO: Cleanup once we are using real browser tests
300
- if (process.env.NODE_ENV === "test") {
301
- microTask(run)
302
- } else {
303
- run()
199
+ );
200
+ const direction = useTabDirection();
201
+ const handleFocus = () => {
202
+ const el = context.panel;
203
+ if (!el) return;
204
+ function run() {
205
+ let result = match(direction.current, {
206
+ [TabDirection.Forwards]: () => focusIn(el, Focus.First),
207
+ [TabDirection.Backwards]: () => focusIn(el, Focus.Last)
208
+ });
209
+ if (result === FocusResult.Error) {
210
+ focusIn(
211
+ getFocusableElements().filter((el2) => el2.dataset.headlessuiFocusGuard !== "true"),
212
+ match(direction.current, {
213
+ [TabDirection.Forwards]: Focus.Next,
214
+ [TabDirection.Backwards]: Focus.Previous
215
+ }),
216
+ { relativeTo: context.button }
217
+ );
304
218
  }
305
219
  }
220
+ if (process.env.NODE_ENV === "test") {
221
+ microTask(run);
222
+ } else {
223
+ run();
224
+ }
225
+ };
306
226
  </script>
307
227
 
308
228
  <ElementOrComponent
@@ -1,68 +1,41 @@
1
- <script lang="ts" module>
2
- import type { ElementType, Props } from "../utils/types.js"
3
- import { setContext } from "svelte"
4
-
5
- const DEFAULT_GROUP_TAG = "div" as const
6
- type GroupRenderPropArg = {}
7
- type GroupPropsWeControl = never
8
-
9
- export type PopoverGroupProps<TTag extends ElementType = typeof DEFAULT_GROUP_TAG> = Props<
10
- TTag,
11
- GroupRenderPropArg,
12
- GroupPropsWeControl
13
- >
1
+ <script lang="ts" module>import { setContext } from "svelte";
2
+ const DEFAULT_GROUP_TAG = "div";
14
3
  </script>
15
4
 
16
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_GROUP_TAG">
17
- import type { PopoverGroupContext, PopoverRegisterBag } from "./context.svelte"
18
- import MainTreeProvider from "../internal/MainTreeProvider.svelte"
19
- import ElementOrComponent from "../utils/ElementOrComponent.svelte"
20
- import { getOwnerDocument } from "../utils/owner.js"
21
-
22
- let { ref = $bindable(), ...theirProps }: { as?: TTag } & PopoverGroupProps<TTag> = $props()
23
-
24
- const popovers = $state<PopoverRegisterBag[]>([])
25
-
26
- const unregisterPopover = (registerBag: PopoverRegisterBag) => {
27
- const idx = popovers.indexOf(registerBag)
28
- if (idx !== -1) popovers.splice(idx, 1)
29
- }
30
-
31
- const registerPopover = (registerBag: PopoverRegisterBag) => {
32
- popovers.push(registerBag)
33
- return () => unregisterPopover(registerBag)
5
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_GROUP_TAG">import MainTreeProvider from "../internal/MainTreeProvider.svelte";
6
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
7
+ import { getOwnerDocument } from "../utils/owner.js";
8
+ let { ref = $bindable(), ...theirProps } = $props();
9
+ const popovers = $state([]);
10
+ const unregisterPopover = (registerBag) => {
11
+ const idx = popovers.indexOf(registerBag);
12
+ if (idx !== -1) popovers.splice(idx, 1);
13
+ };
14
+ const registerPopover = (registerBag) => {
15
+ popovers.push(registerBag);
16
+ return () => unregisterPopover(registerBag);
17
+ };
18
+ const isFocusWithinPopoverGroup = () => {
19
+ const ownerDocument = getOwnerDocument(ref);
20
+ if (!ownerDocument) return false;
21
+ let element = ownerDocument.activeElement;
22
+ if (ref?.contains(element)) return true;
23
+ return popovers.some((bag) => {
24
+ return ownerDocument.getElementById(bag.buttonId)?.contains(element) || ownerDocument.getElementById(bag.panelId)?.contains(element);
25
+ });
26
+ };
27
+ const closeOthers = (buttonId) => {
28
+ for (const popover of popovers) {
29
+ if (popover.buttonId !== buttonId) popover.close();
34
30
  }
35
-
36
- const isFocusWithinPopoverGroup = () => {
37
- const ownerDocument = getOwnerDocument(ref)
38
- if (!ownerDocument) return false
39
- let element = ownerDocument.activeElement
40
-
41
- if (ref?.contains(element)) return true
42
-
43
- // Check if the focus is in one of the button or panel elements. This is important in case you are rendering inside a Portal.
44
- return popovers.some((bag) => {
45
- return (
46
- ownerDocument!.getElementById(bag.buttonId!)?.contains(element) ||
47
- ownerDocument!.getElementById(bag.panelId!)?.contains(element)
48
- )
49
- })
50
- }
51
-
52
- const closeOthers = (buttonId: string) => {
53
- for (const popover of popovers) {
54
- if (popover.buttonId !== buttonId) popover.close()
55
- }
56
- }
57
-
58
- setContext<PopoverGroupContext>("PopoverGroupContext", {
59
- registerPopover,
60
- unregisterPopover,
61
- isFocusWithinPopoverGroup,
62
- closeOthers,
63
- })
64
-
65
- const slot = {} satisfies GroupRenderPropArg
31
+ };
32
+ setContext("PopoverGroupContext", {
33
+ registerPopover,
34
+ unregisterPopover,
35
+ isFocusWithinPopoverGroup,
36
+ closeOthers
37
+ });
38
+ const slot = {};
66
39
  </script>
67
40
 
68
41
  <MainTreeProvider>