@pzerelles/headlessui-svelte 2.1.2-next.22 → 2.1.2-next.24

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 (132) hide show
  1. package/dist/button/Button.svelte +84 -54
  2. package/dist/button/Button.svelte.d.ts +7 -4
  3. package/dist/checkbox/Checkbox.svelte +173 -120
  4. package/dist/checkbox/Checkbox.svelte.d.ts +7 -4
  5. package/dist/close-button/CloseButton.svelte +12 -6
  6. package/dist/close-button/CloseButton.svelte.d.ts +13 -10
  7. package/dist/combobox/Combobox.svelte +50 -3
  8. package/dist/data-interactive/DataInteractive.svelte +55 -29
  9. package/dist/data-interactive/DataInteractive.svelte.d.ts +7 -5
  10. package/dist/description/Description.svelte +39 -24
  11. package/dist/description/Description.svelte.d.ts +8 -5
  12. package/dist/description/context.svelte.js +13 -15
  13. package/dist/dialog/Dialog.svelte +358 -38
  14. package/dist/dialog/Dialog.svelte.d.ts +10 -7
  15. package/dist/dialog/DialogBackdrop.svelte +30 -13
  16. package/dist/dialog/DialogBackdrop.svelte.d.ts +7 -4
  17. package/dist/dialog/DialogPanel.svelte +49 -26
  18. package/dist/dialog/DialogPanel.svelte.d.ts +7 -4
  19. package/dist/dialog/DialogTitle.svelte +38 -23
  20. package/dist/dialog/DialogTitle.svelte.d.ts +7 -4
  21. package/dist/field/Field.svelte +50 -34
  22. package/dist/field/Field.svelte.d.ts +7 -4
  23. package/dist/fieldset/Fieldset.svelte +50 -29
  24. package/dist/fieldset/Fieldset.svelte.d.ts +7 -4
  25. package/dist/focus-trap/FocusTrap.svelte +419 -283
  26. package/dist/focus-trap/FocusTrap.svelte.d.ts +7 -4
  27. package/dist/hooks/use-disabled.d.ts +4 -1
  28. package/dist/hooks/use-disabled.js +10 -5
  29. package/dist/input/Input.svelte +84 -53
  30. package/dist/input/Input.svelte.d.ts +7 -4
  31. package/dist/internal/FloatingProvider.svelte +14 -9
  32. package/dist/internal/FocusSentinel.svelte +16 -8
  33. package/dist/internal/ForcePortalRoot.svelte +7 -3
  34. package/dist/internal/FormFields.svelte +47 -34
  35. package/dist/internal/FormFieldsProvider.svelte +9 -5
  36. package/dist/internal/FormResolver.svelte +20 -15
  37. package/dist/internal/Hidden.svelte +50 -29
  38. package/dist/internal/Hidden.svelte.d.ts +7 -4
  39. package/dist/internal/MainTreeProvider.svelte +89 -36
  40. package/dist/internal/Portal.svelte +18 -14
  41. package/dist/internal/floating-provider.svelte.js +1 -1
  42. package/dist/internal/floating.svelte.d.ts +5 -5
  43. package/dist/internal/floating.svelte.js +17 -17
  44. package/dist/label/Label.svelte +93 -58
  45. package/dist/label/Label.svelte.d.ts +7 -4
  46. package/dist/legend/Legend.svelte +12 -3
  47. package/dist/listbox/Listbox.svelte +525 -387
  48. package/dist/listbox/Listbox.svelte.d.ts +7 -5
  49. package/dist/listbox/ListboxButton.svelte +173 -127
  50. package/dist/listbox/ListboxButton.svelte.d.ts +7 -5
  51. package/dist/listbox/ListboxOption.svelte +170 -129
  52. package/dist/listbox/ListboxOption.svelte.d.ts +7 -5
  53. package/dist/listbox/ListboxOptions.svelte +400 -304
  54. package/dist/listbox/ListboxOptions.svelte.d.ts +7 -5
  55. package/dist/listbox/ListboxSelectedOption.svelte +38 -15
  56. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +7 -4
  57. package/dist/listbox/index.d.ts +4 -4
  58. package/dist/listbox/index.js +1 -1
  59. package/dist/menu/Menu.svelte +78 -57
  60. package/dist/menu/Menu.svelte.d.ts +7 -5
  61. package/dist/menu/MenuButton.svelte +157 -117
  62. package/dist/menu/MenuButton.svelte.d.ts +7 -5
  63. package/dist/menu/MenuHeading.svelte +32 -14
  64. package/dist/menu/MenuHeading.svelte.d.ts +7 -5
  65. package/dist/menu/MenuItem.svelte +142 -107
  66. package/dist/menu/MenuItem.svelte.d.ts +8 -8
  67. package/dist/menu/MenuItems.svelte +301 -229
  68. package/dist/menu/MenuItems.svelte.d.ts +7 -5
  69. package/dist/menu/MenuSection.svelte +24 -9
  70. package/dist/menu/MenuSection.svelte.d.ts +7 -5
  71. package/dist/menu/MenuSeparator.svelte +17 -4
  72. package/dist/menu/MenuSeparator.svelte.d.ts +7 -6
  73. package/dist/menu/context.svelte.d.ts +1 -29
  74. package/dist/menu/context.svelte.js +29 -27
  75. package/dist/menu/index.d.ts +7 -7
  76. package/dist/popover/Popover.svelte +216 -150
  77. package/dist/popover/Popover.svelte.d.ts +7 -4
  78. package/dist/popover/PopoverBackdrop.svelte +67 -41
  79. package/dist/popover/PopoverBackdrop.svelte.d.ts +7 -4
  80. package/dist/popover/PopoverButton.svelte +292 -212
  81. package/dist/popover/PopoverButton.svelte.d.ts +7 -4
  82. package/dist/popover/PopoverGroup.svelte +62 -35
  83. package/dist/popover/PopoverGroup.svelte.d.ts +7 -4
  84. package/dist/popover/PopoverPanel.svelte +311 -229
  85. package/dist/popover/PopoverPanel.svelte.d.ts +7 -4
  86. package/dist/portal/InternalPortal.svelte +141 -85
  87. package/dist/portal/InternalPortal.svelte.d.ts +7 -4
  88. package/dist/portal/Portal.svelte +5 -2
  89. package/dist/portal/PortalGroup.svelte +30 -9
  90. package/dist/portal/PortalGroup.svelte.d.ts +7 -4
  91. package/dist/select/Select.svelte +98 -68
  92. package/dist/select/Select.svelte.d.ts +7 -4
  93. package/dist/switch/Switch.svelte +179 -132
  94. package/dist/switch/Switch.svelte.d.ts +7 -4
  95. package/dist/switch/SwitchGroup.svelte +44 -31
  96. package/dist/switch/SwitchGroup.svelte.d.ts +7 -4
  97. package/dist/tabs/Tab.svelte +194 -143
  98. package/dist/tabs/Tab.svelte.d.ts +7 -4
  99. package/dist/tabs/TabGroup.svelte +81 -214
  100. package/dist/tabs/TabGroup.svelte.d.ts +7 -24
  101. package/dist/tabs/TabList.svelte +31 -11
  102. package/dist/tabs/TabList.svelte.d.ts +7 -4
  103. package/dist/tabs/TabPanel.svelte +67 -43
  104. package/dist/tabs/TabPanel.svelte.d.ts +7 -4
  105. package/dist/tabs/TabPanels.svelte +18 -7
  106. package/dist/tabs/TabPanels.svelte.d.ts +7 -4
  107. package/dist/tabs/context.svelte.d.ts +31 -0
  108. package/dist/tabs/context.svelte.js +134 -0
  109. package/dist/textarea/Textarea.svelte +84 -53
  110. package/dist/textarea/Textarea.svelte.d.ts +7 -4
  111. package/dist/transition/InternalTransitionChild.svelte +259 -170
  112. package/dist/transition/InternalTransitionChild.svelte.d.ts +7 -4
  113. package/dist/transition/Transition.svelte +96 -66
  114. package/dist/transition/Transition.svelte.d.ts +7 -4
  115. package/dist/transition/TransitionChild.svelte +31 -11
  116. package/dist/transition/TransitionChild.svelte.d.ts +7 -4
  117. package/dist/utils/ElementOrComponent.svelte +43 -23
  118. package/dist/utils/ElementOrComponent.svelte.d.ts +10 -4
  119. package/dist/utils/Generic.svelte +36 -22
  120. package/dist/utils/Generic.svelte.d.ts +7 -4
  121. package/dist/utils/StableCollection.svelte +54 -36
  122. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +27 -12
  123. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +88 -44
  124. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +7 -7
  125. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +1 -1
  126. package/dist/utils/floating-ui/svelte/types.d.ts +4 -4
  127. package/dist/utils/floating-ui/svelte-dom/types.d.ts +2 -2
  128. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +6 -6
  129. package/dist/utils/types.d.ts +11 -4
  130. package/package.json +2 -2
  131. package/dist/dialog/InternalDialog.svelte +0 -233
  132. package/dist/dialog/InternalDialog.svelte.d.ts +0 -42
@@ -1,16 +1,36 @@
1
- <script lang="ts" module>import { RenderFeatures } from "../utils/render.js";
2
- export const DEFAULT_TRANSITION_CHILD_TAG = "svelte:fragment";
3
- export const TransitionChildRenderFeatures = RenderFeatures.RenderStrategy;
1
+ <script lang="ts" module>
2
+ import type { ElementType, Props } from "../utils/types.js"
3
+ import { RenderFeatures, type PropsForFeatures } from "../utils/render.js"
4
+ import type { TransitionEvents, TransitionClasses } from "./context.svelte.js"
5
+
6
+ type TransitionChildPropsWeControl = never
7
+
8
+ export type TransitionChildProps<TTag extends ElementType> = Props<
9
+ TTag,
10
+ TransitionChildRenderPropArg,
11
+ TransitionChildPropsWeControl,
12
+ PropsForFeatures<typeof TransitionChildRenderFeatures> &
13
+ TransitionClasses &
14
+ TransitionEvents & { transition?: boolean; appear?: boolean }
15
+ >
16
+
17
+ export const DEFAULT_TRANSITION_CHILD_TAG = "svelte:fragment"
18
+ export type TransitionChildRenderPropArg = HTMLElement
19
+ export const TransitionChildRenderFeatures = RenderFeatures.RenderStrategy
4
20
  </script>
5
21
 
6
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TRANSITION_CHILD_TAG">import { useOpenClosed } from "../internal/open-closed.js";
7
- import { getContext } from "svelte";
8
- import InternalTransitionChild from "./InternalTransitionChild.svelte";
9
- import Transition from "./Transition.svelte";
10
- const hasTransitionContext = !!getContext("TransitionContext");
11
- const hasOpenClosedContext = useOpenClosed() !== null;
12
- let { ref = $bindable(), as, ...props } = $props();
13
- const TransitionRootOrChild = !hasTransitionContext && hasOpenClosedContext ? Transition : InternalTransitionChild;
22
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TRANSITION_CHILD_TAG">
23
+ import { useOpenClosed } from "../internal/open-closed.js"
24
+ import { getContext } from "svelte"
25
+ import InternalTransitionChild from "./InternalTransitionChild.svelte"
26
+ import Transition from "./Transition.svelte"
27
+
28
+ const hasTransitionContext = !!getContext("TransitionContext")
29
+ const hasOpenClosedContext = useOpenClosed() !== null
30
+
31
+ let { ref = $bindable(), as, ...props }: { as?: TTag } & TransitionChildProps<TTag> = $props()
32
+
33
+ const TransitionRootOrChild = !hasTransitionContext && hasOpenClosedContext ? Transition : InternalTransitionChild
14
34
  </script>
15
35
 
16
36
  <TransitionRootOrChild bind:ref {...props} />
@@ -12,11 +12,14 @@ export declare const TransitionChildRenderFeatures = RenderFeatures.RenderStrate
12
12
  declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_TRANSITION_CHILD_TAG> {
13
13
  props(): {
14
14
  as?: TTag | undefined;
15
- } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("as" | "children" | "refName" | "class") | "unmount" | "transition" | keyof TransitionClasses | keyof TransitionEvents | "appear"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
16
- children?: import("svelte").Snippet<[HTMLElement, Record<string, any>]> | undefined;
15
+ } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("as" | "children" | "class") | "unmount" | "transition" | keyof TransitionClasses | keyof TransitionEvents | "appear"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
16
+ children?: import("svelte").Snippet<[{
17
+ slot: HTMLElement;
18
+ props: Record<string, any>;
19
+ }]> | undefined;
17
20
  ref?: HTMLElement;
18
- } & (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) ? {
19
- class?: import("../utils/types.js").PropsOf<TTag>["class"] | ((bag: HTMLElement) => string) | undefined;
21
+ } & (true extends (import("svelte/elements.js").SvelteHTMLElements[TTag] extends infer T_1 ? T_1 extends import("svelte/elements.js").SvelteHTMLElements[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) ? {
22
+ class?: string | ((bag: HTMLElement) => string) | null | undefined;
20
23
  } : {}) & {
21
24
  unmount?: boolean | undefined;
22
25
  } & TransitionClasses & TransitionEvents & {
@@ -1,26 +1,46 @@
1
- <script lang="ts" generics="TFeature extends RenderFeatures, TTag extends ElementType, TSlot, TValue">import { mergePropsAdvanced, RenderFeatures } from "./render.js";
2
- import Generic from "./Generic.svelte";
3
- let {
4
- ourProps,
5
- theirProps,
6
- slots,
7
- slot = slots,
8
- defaultTag,
9
- features,
10
- visible = true,
11
- name,
12
- ref = $bindable(),
13
- value = $bindable(),
14
- checked = $bindable()
15
- } = $props();
16
- const featureFlags = $derived(features ?? RenderFeatures.None);
17
- const { static: isStatic = false, unmount = true, ...rest } = $derived(mergePropsAdvanced(theirProps, ourProps ?? {}));
18
- const render = $derived(
19
- visible || featureFlags & RenderFeatures.Static && isStatic || featureFlags & RenderFeatures.RenderStrategy && !unmount
20
- );
21
- const hiddenProps = $derived(
22
- !visible && !(featureFlags & RenderFeatures.Static) && featureFlags & RenderFeatures.RenderStrategy && !unmount ? { hidden: true, style: "display: none;" } : {}
23
- );
1
+ <script lang="ts" generics="TFeature extends RenderFeatures, TTag extends ElementType, TSlot, TValue">
2
+ import type { ElementType, Props } from "./types.js"
3
+ import { mergePropsAdvanced, RenderFeatures, type PropsForFeatures } from "./render.js"
4
+ import Generic from "./Generic.svelte"
5
+
6
+ let {
7
+ ourProps,
8
+ theirProps,
9
+ slots,
10
+ slot = slots,
11
+ defaultTag,
12
+ features,
13
+ visible = true,
14
+ name,
15
+ ref = $bindable(),
16
+ value = $bindable(),
17
+ checked = $bindable(),
18
+ }: {
19
+ ourProps?: Expand<Props<any, TSlot> & PropsForFeatures<TFeature>>
20
+ theirProps: Expand<{ as?: TTag } & Props<any, TSlot, any>>
21
+ slot?: TSlot
22
+ slots?: TSlot
23
+ defaultTag: ElementType
24
+ features?: TFeature
25
+ visible?: boolean
26
+ name: string
27
+ ref?: HTMLElement
28
+ value?: TValue
29
+ checked?: boolean
30
+ } = $props()
31
+
32
+ const featureFlags = $derived(features ?? RenderFeatures.None)
33
+ const { static: isStatic = false, unmount = true, ...rest } = $derived(mergePropsAdvanced(theirProps, ourProps ?? {}))
34
+ const render = $derived(
35
+ visible ||
36
+ (featureFlags & RenderFeatures.Static && isStatic) ||
37
+ (featureFlags & RenderFeatures.RenderStrategy && !unmount)
38
+ )
39
+ const hiddenProps = $derived(
40
+ !visible && !(featureFlags & RenderFeatures.Static) && featureFlags & RenderFeatures.RenderStrategy && !unmount
41
+ ? { hidden: true, style: "display: none;" }
42
+ : {}
43
+ )
24
44
  </script>
25
45
 
26
46
  {#if render}<Generic {...rest} {...hiddenProps} {slot} tag={defaultTag} bind:ref bind:value bind:checked />{/if}
@@ -6,10 +6,13 @@ declare class __sveltets_Render<TFeature extends RenderFeatures, TTag extends El
6
6
  [x: string]: any;
7
7
  [x: number]: any;
8
8
  } & {
9
- children?: import("svelte").Snippet<[TSlot, Record<string, any>]> | undefined;
9
+ children?: import("svelte").Snippet<[{
10
+ slot: TSlot;
11
+ props: Record<string, any>;
12
+ }]> | undefined;
10
13
  ref?: HTMLElement;
11
14
  } & {
12
- class?: any;
15
+ class?: string | ((bag: TSlot) => string) | null | undefined;
13
16
  } & Expand<((TFeature extends RenderFeatures.Static ? {
14
17
  static?: boolean;
15
18
  } : {}) extends infer T ? T extends (TFeature extends RenderFeatures.Static ? {
@@ -21,9 +24,12 @@ declare class __sveltets_Render<TFeature extends RenderFeatures, TTag extends El
21
24
  } : {}) ? T_1 extends any ? (x: T_1) => any : never : never : never) extends (x: infer R) => any ? R : never>> | undefined;
22
25
  theirProps: {
23
26
  as?: TTag | undefined;
24
- children?: import("svelte").Snippet<[TSlot, Record<string, any>]> | undefined;
27
+ children?: import("svelte").Snippet<[{
28
+ slot: TSlot;
29
+ props: Record<string, any>;
30
+ }]> | undefined;
25
31
  ref?: HTMLElement | undefined;
26
- class?: any;
32
+ class?: string | ((bag: TSlot) => string) | null | undefined;
27
33
  };
28
34
  slot?: TSlot | undefined;
29
35
  slots?: TSlot | undefined;
@@ -1,35 +1,49 @@
1
- <script lang="ts" generics="TTag extends keyof SvelteHTMLProps, TSlot, TValue">import { stateFromSlot } from "./state.js";
2
- let {
3
- slot = {},
4
- tag,
5
- ref = $bindable(),
6
- value = $bindable(),
7
- checked = $bindable(),
8
- children,
9
- as = tag,
10
- unmount,
11
- static: isStatic,
12
- ...props
13
- } = $props();
14
- const resolvedClass = $derived(
15
- typeof props.class === "function" ? props.class(slot) : props.class
16
- );
1
+ <script lang="ts" generics="TTag extends keyof SvelteHTMLProps, TSlot, TValue">
2
+ import { stateFromSlot } from "./state.js"
3
+ import type { ElementType, Props, SvelteHTMLProps } from "./types.js"
4
+
5
+ let {
6
+ slot = {} as TSlot,
7
+ tag,
8
+ ref = $bindable(),
9
+ value = $bindable(),
10
+ checked = $bindable(),
11
+ children,
12
+ as = tag as TTag,
13
+ unmount,
14
+ static: isStatic,
15
+ ...props
16
+ }: {
17
+ as?: TTag
18
+ slot: TSlot
19
+ tag: ElementType
20
+ ref?: HTMLElement
21
+ value?: TValue
22
+ checked?: boolean
23
+ } & Props<TTag, TSlot> = $props()
24
+
25
+ const resolvedClass = $derived(
26
+ typeof props.class === "function" ? props.class(slot) : (props.class as string | undefined)
27
+ )
17
28
  </script>
18
29
 
19
30
  {#if as === "svelte:fragment"}
20
- {#if children}{@render children(slot, {
21
- ...props,
22
- ...(resolvedClass ? { class: resolvedClass } : {}),
23
- ...stateFromSlot(slot),
31
+ {#if children}{@render children({
32
+ slot,
33
+ props: {
34
+ ...props,
35
+ ...(resolvedClass ? { class: resolvedClass } : {}),
36
+ ...stateFromSlot(slot),
37
+ },
24
38
  })}{/if}
25
39
  {:else if children}
26
40
  {#if as === "select"}
27
41
  <select bind:this={ref} {...props} class={resolvedClass} {...stateFromSlot(slot)} bind:value>
28
- {@render children(slot, {})}
42
+ {@render children({ slot, props: {} })}
29
43
  </select>
30
44
  {:else}
31
45
  <svelte:element this={as} bind:this={ref} {...props} class={resolvedClass} {...stateFromSlot(slot)}>
32
- {@render children(slot, {})}
46
+ {@render children({ slot, props: {} })}
33
47
  </svelte:element>
34
48
  {/if}
35
49
  {:else if as === "input" && props.type === "checkbox"}
@@ -7,11 +7,14 @@ declare class __sveltets_Render<TTag extends keyof SvelteHTMLProps, TSlot, TValu
7
7
  ref?: HTMLElement;
8
8
  value?: TValue | undefined;
9
9
  checked?: boolean;
10
- } & (Exclude<keyof import("./types.js").PropsOf<TTag>, "as" | "children" | "refName" | "class"> extends infer T extends keyof import("./types.js").PropsOf<TTag> ? { [P in T]: import("./types.js").PropsOf<TTag>[P]; } : never) & {
11
- children?: import("svelte").Snippet<[TSlot, Record<string, any>]> | undefined;
10
+ } & (Exclude<keyof import("./types.js").PropsOf<TTag>, "as" | "children" | "class"> extends infer T extends keyof import("./types.js").PropsOf<TTag> ? { [P in T]: import("./types.js").PropsOf<TTag>[P]; } : never) & {
11
+ children?: import("svelte").Snippet<[{
12
+ slot: TSlot;
13
+ props: Record<string, any>;
14
+ }]> | undefined;
12
15
  ref?: HTMLElement;
13
- } & (true extends (import("./types.js").PropsOf<TTag> extends infer T_1 ? T_1 extends import("./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) ? {
14
- class?: import("./types.js").PropsOf<TTag>["class"] | ((bag: TSlot) => string) | undefined;
16
+ } & (true extends (import("svelte/elements.js").SvelteHTMLElements[TTag] extends infer T_1 ? T_1 extends import("svelte/elements.js").SvelteHTMLElements[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) ? {
17
+ class?: string | ((bag: TSlot) => string) | null | undefined;
15
18
  } : {});
16
19
  events(): {} & {
17
20
  [evt: string]: CustomEvent<any>;
@@ -1,43 +1,61 @@
1
- <script lang="ts" module>import { useId } from "../hooks/use-id.js";
2
- import { getContext, setContext } from "svelte";
3
- function createCollection() {
4
- return {
5
- /** @type {Map<string, Map<string, number>>} */
6
- groups: /* @__PURE__ */ new Map(),
7
- get(group, key) {
8
- let list = this.groups.get(group);
9
- if (!list) {
10
- list = /* @__PURE__ */ new Map();
11
- this.groups.set(group, list);
12
- }
13
- let renders = list.get(key) ?? 0;
14
- list.set(key, renders + 1);
15
- let index = Array.from(list.keys()).indexOf(key);
16
- function release() {
17
- let renders2 = list.get(key);
18
- if (renders2 > 1) {
19
- list.set(key, renders2 - 1);
20
- } else {
21
- list.delete(key);
1
+ <script lang="ts" module>
2
+ import { useId } from "../hooks/use-id.js"
3
+ import { getContext, setContext, type Snippet } from "svelte"
4
+
5
+ type CollectionKey = string | symbol
6
+ type CollectionItem = [number, () => void]
7
+ type Collection = ReturnType<typeof createCollection>
8
+
9
+ function createCollection() {
10
+ return {
11
+ /** @type {Map<string, Map<string, number>>} */
12
+ groups: new Map(),
13
+
14
+ get(group: string, key: CollectionKey): CollectionItem {
15
+ let list = this.groups.get(group)
16
+ if (!list) {
17
+ list = new Map()
18
+ this.groups.set(group, list)
19
+ }
20
+
21
+ let renders = list.get(key) ?? 0
22
+ // FIXME: This is a side-effect during render. `release` is only called in
23
+ // an effect cleanup so we may never release if we had to render multiple
24
+ // times before commit e.g. when a sibling suspends.
25
+ list.set(key, renders + 1)
26
+
27
+ let index = Array.from(list.keys()).indexOf(key)
28
+ function release() {
29
+ let renders = list.get(key)
30
+ if (renders > 1) {
31
+ list.set(key, renders - 1)
32
+ } else {
33
+ list.delete(key)
34
+ }
22
35
  }
23
- }
24
- return [index, release];
36
+
37
+ return [index, release]
38
+ },
25
39
  }
26
- };
27
- }
28
- export function useStableCollectionIndex(group) {
29
- let collection = getContext("StableCollection");
30
- if (!collection) throw new Error("You must wrap your component in a <StableCollection>");
31
- let key = useId();
32
- let [idx, cleanupIdx] = collection.get(group, key);
33
- $effect(() => cleanupIdx);
34
- return idx;
35
- }
40
+ }
41
+
42
+ export function useStableCollectionIndex(group: string) {
43
+ let collection = getContext<Collection>("StableCollection")
44
+ if (!collection) throw new Error("You must wrap your component in a <StableCollection>")
45
+
46
+ let key = useId()
47
+ let [idx, cleanupIdx] = collection.get(group, key)
48
+
49
+ $effect(() => cleanupIdx)
50
+ return idx
51
+ }
36
52
  </script>
37
53
 
38
- <script lang="ts">const collection = createCollection();
39
- setContext("StableCollection", collection);
40
- let { children } = $props();
54
+ <script lang="ts">
55
+ const collection = createCollection()
56
+ setContext<Collection>("StableCollection", collection)
57
+
58
+ let { children }: { children: Snippet } = $props()
41
59
  </script>
42
60
 
43
61
  {#if children}{@render children()}{/if}
@@ -1,17 +1,32 @@
1
- <script lang="ts" module></script>
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte"
2
3
 
3
- <script lang="ts">import { setContext } from "svelte";
4
- import { useFloatingParentNodeId } from "./FloatingTree.svelte";
5
- const { children, id } = $props();
6
- const parentId = useFloatingParentNodeId();
7
- setContext("FloatingNodeContext", {
8
- get id() {
9
- return id;
10
- },
11
- get parentId() {
12
- return parentId.value;
4
+ export interface FloatingNodeProps {
5
+ children?: Snippet
6
+ id: string
13
7
  }
14
- });
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ /**
12
+ * Provides parent node context for nested floating elements.
13
+ * @see https://floating-ui.com/docs/FloatingTree
14
+ */
15
+ import { setContext } from "svelte"
16
+ import type { FloatingNodeType } from "../types.js"
17
+ import { useFloatingParentNodeId } from "./FloatingTree.svelte"
18
+
19
+ const { children, id }: FloatingNodeProps = $props()
20
+
21
+ const parentId = useFloatingParentNodeId()
22
+ setContext<FloatingNodeType>("FloatingNodeContext", {
23
+ get id() {
24
+ return id
25
+ },
26
+ get parentId() {
27
+ return parentId.value
28
+ },
29
+ })
15
30
  </script>
16
31
 
17
32
  {#if children}{@render children()}{/if}
@@ -1,50 +1,94 @@
1
- <script lang="ts" module>import { getContext } from "svelte";
2
- import { useId } from "../hooks/useId.svelte.js";
3
- import { createPubSub } from "../utils/createPubSub.js";
4
- export const useFloatingParentNodeId = () => {
5
- const context = getContext("FloatingNodeContext");
6
- return {
7
- get value() {
8
- return context?.id ?? null;
1
+ <script lang="ts" module>
2
+ import { getContext, type Snippet } from "svelte"
3
+ import { useId } from "../hooks/useId.svelte.js"
4
+ import type { FloatingNodeType, FloatingTreeType, ReferenceType } from "../types.js"
5
+ import { createPubSub } from "../utils/createPubSub.js"
6
+ import type { MutableRefObject } from "../../../ref.svelte.js"
7
+
8
+ //const FloatingNodeContext = React.createContext<FloatingNodeType | null>(null)
9
+ //const FloatingTreeContext = React.createContext<FloatingTreeType | null>(null)
10
+
11
+ /**
12
+ * Returns the parent node id for nested floating elements, if available.
13
+ * Returns `null` for top-level floating elements.
14
+ */
15
+ export const useFloatingParentNodeId = (): { readonly value: string | null } => {
16
+ const context = getContext<FloatingNodeType>("FloatingNodeContext")
17
+ return {
18
+ get value() {
19
+ return context?.id ?? null
20
+ },
9
21
  }
10
- };
11
- };
12
- export const useFloatingTree = () => getContext("FloatingTreeContext") ?? null;
13
- export function useFloatingNodeId(options) {
14
- const { customParentId } = $derived(options);
15
- const id = useId();
16
- const tree = useFloatingTree();
17
- const reactParentId = useFloatingParentNodeId();
18
- const parentId = $derived(customParentId || reactParentId.value);
19
- $effect(() => {
20
- const node = { id, parentId };
21
- tree?.addNode(node);
22
- return () => {
23
- tree?.removeNode(node);
24
- };
25
- });
26
- return id;
27
- }
22
+ }
23
+
24
+ /**
25
+ * Returns the nearest floating tree context, if available.
26
+ */
27
+ export const useFloatingTree = <RT extends ReferenceType = ReferenceType>(): FloatingTreeType<RT> | null =>
28
+ getContext<FloatingTreeType<RT>>("FloatingTreeContext") ?? null
29
+
30
+ /**
31
+ * Registers a node into the `FloatingTree`, returning its id.
32
+ * @see https://floating-ui.com/docs/FloatingTree
33
+ */
34
+ export function useFloatingNodeId(options: { customParentId?: string }): string {
35
+ const { customParentId } = $derived(options)
36
+ const id = useId()
37
+ const tree = useFloatingTree()
38
+ const reactParentId = useFloatingParentNodeId()
39
+ const parentId = $derived(customParentId || reactParentId.value)
40
+
41
+ $effect(() => {
42
+ const node = { id, parentId }
43
+ tree?.addNode(node)
44
+ return () => {
45
+ tree?.removeNode(node)
46
+ }
47
+ }) //, [tree, id, parentId])
48
+
49
+ return id
50
+ }
51
+
52
+ export interface FloatingTreeProps {
53
+ children?: Snippet
54
+ }
28
55
  </script>
29
56
 
30
- <script lang="ts">import { setContext } from "svelte";
31
- const { children } = $props();
32
- const nodesRef = $state({ current: [] });
33
- const addNode = (node) => {
34
- nodesRef.current = [...nodesRef.current, node];
35
- };
36
- const removeNode = (node) => {
37
- nodesRef.current = nodesRef.current.filter((n) => n !== node);
38
- };
39
- const events = createPubSub();
40
- setContext("FloatingTreeContext", {
41
- get nodesRef() {
42
- return nodesRef;
43
- },
44
- addNode,
45
- removeNode,
46
- events
47
- });
57
+ <script lang="ts">
58
+ /**
59
+ * Provides context for nested floating elements when they are not children of
60
+ * each other on the DOM.
61
+ * This is not necessary in all cases, except when there must be explicit communication between parent and child floating elements. It is necessary for:
62
+ * - The `bubbles` option in the `useDismiss()` Hook
63
+ * - Nested virtual list navigation
64
+ * - Nested floating elements that each open on hover
65
+ * - Custom communication between parent and child floating elements
66
+ * @see https://floating-ui.com/docs/FloatingTree
67
+ */
68
+ import { setContext } from "svelte"
69
+
70
+ const { children }: FloatingTreeProps = $props()
71
+
72
+ const nodesRef = $state<MutableRefObject<Array<FloatingNodeType>>>({ current: [] })
73
+
74
+ const addNode = (node: FloatingNodeType) => {
75
+ nodesRef.current = [...nodesRef.current, node]
76
+ }
77
+
78
+ const removeNode = (node: FloatingNodeType) => {
79
+ nodesRef.current = nodesRef.current.filter((n) => n !== node)
80
+ }
81
+
82
+ const events = createPubSub()
83
+
84
+ setContext<FloatingTreeType<ReferenceType>>("FloatingTreeContext", {
85
+ get nodesRef() {
86
+ return nodesRef
87
+ },
88
+ addNode,
89
+ removeNode,
90
+ events,
91
+ })
48
92
  </script>
49
93
 
50
94
  {#if children}{@render children()}{/if}
@@ -28,7 +28,7 @@ export function useFloating(options = {}) {
28
28
  let _domReference = $state(null);
29
29
  const setDomReference = (value) => (_domReference = value);
30
30
  let positionReference = $state(null);
31
- const _setPositionReference = (value) => (positionReference = value);
31
+ const _setPositionReference = (value) => (positionReference = value ?? null);
32
32
  const optionDomReference = $derived(computedElements?.reference);
33
33
  const domReference = $derived((optionDomReference || _domReference));
34
34
  const domReferenceRef = $state({ current: null });
@@ -73,17 +73,17 @@ export function useFloating(options = {}) {
73
73
  getBoundingClientRect: () => node.getBoundingClientRect(),
74
74
  contextElement: node,
75
75
  }
76
- : node;
76
+ : (node ?? null);
77
77
  // Store the positionReference in state if the DOM reference is specified externally via the
78
78
  // `elements.reference` option. This ensures that it won't be overridden on future renders.
79
79
  _setPositionReference(computedPositionReference);
80
80
  position.refs.setReference(computedPositionReference);
81
81
  };
82
82
  const setReference = (node) => {
83
- if (isElement(node) || node === null) {
83
+ if (isElement(node) || !node) {
84
84
  ;
85
- domReferenceRef.current = node;
86
- setDomReference(node);
85
+ domReferenceRef.current = node ?? null;
86
+ setDomReference((node ?? null));
87
87
  }
88
88
  // Backwards-compatibility for passing a virtual element to `reference`
89
89
  // after it has set the DOM reference.
@@ -92,8 +92,8 @@ export function useFloating(options = {}) {
92
92
  // Don't allow setting virtual elements using the old technique back to
93
93
  // `null` to support `positionReference` + an unstable `reference`
94
94
  // callback ref.
95
- (node !== null && !isElement(node))) {
96
- position.refs.setReference(node);
95
+ (node && !isElement(node))) {
96
+ position.refs.setReference(node ?? null);
97
97
  }
98
98
  };
99
99
  const refs = $derived({
@@ -25,7 +25,7 @@ export function useFloatingRootContext(options) {
25
25
  };
26
26
  const refs = {
27
27
  setPositionReference: (value) => {
28
- positionReference = value;
28
+ positionReference = value ?? null;
29
29
  },
30
30
  };
31
31
  const elements = $derived({
@@ -12,9 +12,9 @@ export interface ExtendedRefs<RT> {
12
12
  reference: MutableRefObject<ReferenceType | null>;
13
13
  floating: MutableRefObject<HTMLElement | null>;
14
14
  domReference: MutableRefObject<NarrowedElement<RT> | null>;
15
- setReference(node: RT | null): void;
16
- setFloating(node: HTMLElement | null): void;
17
- setPositionReference(node: ReferenceType | null): void;
15
+ setReference(node: RT | null | undefined): void;
16
+ setFloating(node: HTMLElement | null | undefined): void;
17
+ setPositionReference(node: ReferenceType | null | undefined): void;
18
18
  }
19
19
  export interface ExtendedElements<RT> {
20
20
  reference: ReferenceType | null;
@@ -45,7 +45,7 @@ export interface FloatingRootContext<RT extends ReferenceType = ReferenceType> {
45
45
  events: FloatingEvents;
46
46
  floatingId: string;
47
47
  refs: {
48
- setPositionReference(node: ReferenceType | null): void;
48
+ setPositionReference(node: ReferenceType | null | undefined): void;
49
49
  };
50
50
  }
51
51
  export type FloatingContext<RT extends ReferenceType = ReferenceType> = Omit<UsePositionFloatingReturn<RT>, "refs" | "elements"> & {
@@ -37,11 +37,11 @@ export type UseFloatingReturn<RT extends ReferenceType = ReferenceType> = Pretti
37
37
  /**
38
38
  * A callback to set the reference element (reactive).
39
39
  */
40
- setReference: (node: RT | null) => void;
40
+ setReference: (node: RT | null | undefined) => void;
41
41
  /**
42
42
  * A callback to set the floating element (reactive).
43
43
  */
44
- setFloating: (node: HTMLElement | null) => void;
44
+ setFloating: (node: HTMLElement | null | undefined) => void;
45
45
  };
46
46
  /**
47
47
  * Object containing the reference and floating elements.