@pzerelles/headlessui-svelte 2.1.2-next.2 → 2.1.2-next.21

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 (168) hide show
  1. package/dist/button/Button.svelte.d.ts +1 -1
  2. package/dist/checkbox/Checkbox.svelte +4 -4
  3. package/dist/checkbox/Checkbox.svelte.d.ts +5 -7
  4. package/dist/close-button/CloseButton.svelte.d.ts +2 -2
  5. package/dist/data-interactive/DataInteractive.svelte.d.ts +1 -1
  6. package/dist/description/Description.svelte.d.ts +1 -1
  7. package/dist/description/context.svelte.js +1 -1
  8. package/dist/dialog/Dialog.svelte.d.ts +1 -1
  9. package/dist/dialog/DialogBackdrop.svelte.d.ts +1 -1
  10. package/dist/dialog/DialogPanel.svelte +0 -1
  11. package/dist/dialog/DialogPanel.svelte.d.ts +1 -1
  12. package/dist/dialog/DialogTitle.svelte.d.ts +1 -1
  13. package/dist/dialog/InternalDialog.svelte.d.ts +1 -1
  14. package/dist/dialog/context.svelte.js +1 -1
  15. package/dist/field/Field.svelte +21 -3
  16. package/dist/field/Field.svelte.d.ts +1 -1
  17. package/dist/fieldset/Fieldset.svelte.d.ts +1 -1
  18. package/dist/focus-trap/FocusTrap.svelte +7 -14
  19. package/dist/focus-trap/FocusTrap.svelte.d.ts +3 -15
  20. package/dist/focus-trap/FocusTrapFeatures.d.ts +14 -0
  21. package/dist/focus-trap/FocusTrapFeatures.js +15 -0
  22. package/dist/hooks/use-controllable.svelte.js +2 -1
  23. package/dist/hooks/use-did-element-move.svelte.js +5 -10
  24. package/dist/hooks/use-event-listener.svelte.d.ts +1 -1
  25. package/dist/hooks/use-event-listener.svelte.js +3 -1
  26. package/dist/hooks/use-root-containers.svelte.d.ts +2 -2
  27. package/dist/hooks/use-root-containers.svelte.js +5 -5
  28. package/dist/hooks/use-tab-direction.svelte.js +1 -1
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.js +3 -0
  31. package/dist/input/Input.svelte +2 -2
  32. package/dist/input/Input.svelte.d.ts +5 -7
  33. package/dist/internal/FloatingProvider.svelte +12 -0
  34. package/dist/internal/{HoistFormFields.svelte.d.ts → FloatingProvider.svelte.d.ts} +5 -4
  35. package/dist/internal/FormFields.svelte +22 -19
  36. package/dist/internal/FormFieldsProvider.svelte +13 -0
  37. package/dist/internal/FormFieldsProvider.svelte.d.ts +21 -0
  38. package/dist/internal/Hidden.svelte +18 -8
  39. package/dist/internal/Hidden.svelte.d.ts +3 -6
  40. package/dist/internal/HiddenFeatures.d.ts +5 -0
  41. package/dist/internal/HiddenFeatures.js +9 -0
  42. package/dist/internal/floating-provider.svelte.d.ts +3 -0
  43. package/dist/internal/floating-provider.svelte.js +206 -0
  44. package/dist/internal/floating.svelte.d.ts +48 -23
  45. package/dist/internal/floating.svelte.js +79 -260
  46. package/dist/internal/form-fields.svelte.d.ts +10 -0
  47. package/dist/internal/form-fields.svelte.js +23 -0
  48. package/dist/label/Label.svelte +5 -4
  49. package/dist/label/Label.svelte.d.ts +1 -1
  50. package/dist/label/context.svelte.js +1 -1
  51. package/dist/legend/Legend.svelte +2 -2
  52. package/dist/legend/Legend.svelte.d.ts +18 -30
  53. package/dist/listbox/Listbox.svelte +42 -66
  54. package/dist/listbox/Listbox.svelte.d.ts +6 -65
  55. package/dist/listbox/ListboxButton.svelte +10 -10
  56. package/dist/listbox/ListboxButton.svelte.d.ts +5 -7
  57. package/dist/listbox/ListboxOption.svelte +10 -6
  58. package/dist/listbox/ListboxOption.svelte.d.ts +1 -1
  59. package/dist/listbox/ListboxOptions.svelte +108 -54
  60. package/dist/listbox/ListboxOptions.svelte.d.ts +1 -1
  61. package/dist/listbox/ListboxSelectedOption.svelte +2 -4
  62. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +6 -6
  63. package/dist/listbox/context.svelte.d.ts +76 -0
  64. package/dist/listbox/context.svelte.js +36 -0
  65. package/dist/menu/Menu.svelte +5 -177
  66. package/dist/menu/Menu.svelte.d.ts +1 -1
  67. package/dist/menu/MenuButton.svelte +4 -2
  68. package/dist/menu/MenuButton.svelte.d.ts +1 -1
  69. package/dist/menu/MenuHeading.svelte.d.ts +1 -1
  70. package/dist/menu/MenuItem.svelte.d.ts +6 -5
  71. package/dist/menu/MenuItems.svelte +15 -11
  72. package/dist/menu/MenuItems.svelte.d.ts +1 -1
  73. package/dist/menu/MenuSection.svelte.d.ts +1 -1
  74. package/dist/menu/MenuSeparator.svelte.d.ts +1 -1
  75. package/dist/menu/context.svelte.d.ts +30 -1
  76. package/dist/menu/context.svelte.js +208 -0
  77. package/dist/popover/Popover.svelte +161 -0
  78. package/dist/popover/Popover.svelte.d.ts +41 -0
  79. package/dist/popover/PopoverBackdrop.svelte +56 -0
  80. package/dist/popover/PopoverBackdrop.svelte.d.ts +45 -0
  81. package/dist/popover/PopoverButton.svelte +246 -0
  82. package/dist/popover/PopoverButton.svelte.d.ts +44 -0
  83. package/dist/popover/PopoverGroup.svelte +43 -0
  84. package/dist/popover/PopoverGroup.svelte.d.ts +33 -0
  85. package/dist/popover/PopoverPanel.svelte +274 -0
  86. package/dist/popover/PopoverPanel.svelte.d.ts +53 -0
  87. package/dist/popover/context.svelte.d.ts +51 -0
  88. package/dist/popover/context.svelte.js +108 -0
  89. package/dist/popover/index.d.ts +5 -0
  90. package/dist/popover/index.js +5 -0
  91. package/dist/portal/InternalPortal.svelte.d.ts +1 -1
  92. package/dist/portal/PortalGroup.svelte.d.ts +1 -1
  93. package/dist/select/Select.svelte +74 -0
  94. package/dist/select/Select.svelte.d.ts +48 -0
  95. package/dist/select/index.d.ts +1 -0
  96. package/dist/select/index.js +1 -0
  97. package/dist/switch/Switch.svelte +30 -20
  98. package/dist/switch/Switch.svelte.d.ts +5 -5
  99. package/dist/switch/SwitchGroup.svelte.d.ts +1 -1
  100. package/dist/tabs/Tab.svelte.d.ts +1 -1
  101. package/dist/tabs/TabGroup.svelte.d.ts +2 -2
  102. package/dist/tabs/TabList.svelte.d.ts +1 -1
  103. package/dist/tabs/TabPanel.svelte.d.ts +1 -1
  104. package/dist/tabs/TabPanels.svelte.d.ts +1 -1
  105. package/dist/textarea/Textarea.svelte +67 -0
  106. package/dist/textarea/Textarea.svelte.d.ts +50 -0
  107. package/dist/textarea/index.d.ts +1 -0
  108. package/dist/textarea/index.js +1 -0
  109. package/dist/transition/InternalTransitionChild.svelte.d.ts +1 -1
  110. package/dist/transition/Transition.svelte.d.ts +1 -1
  111. package/dist/transition/TransitionChild.svelte.d.ts +1 -1
  112. package/dist/transition/context.svelte.js +2 -2
  113. package/dist/utils/ElementOrComponent.svelte +2 -2
  114. package/dist/utils/ElementOrComponent.svelte.d.ts +2 -2
  115. package/dist/utils/Generic.svelte +0 -1
  116. package/dist/utils/Generic.svelte.d.ts +1 -2
  117. package/dist/utils/alternative-types.d.ts +1 -2
  118. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +17 -0
  119. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte.d.ts +23 -0
  120. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +50 -0
  121. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte.d.ts +41 -0
  122. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.d.ts +6 -0
  123. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +158 -0
  124. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.d.ts +11 -0
  125. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +53 -0
  126. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.d.ts +9 -0
  127. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.js +28 -0
  128. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.d.ts +23 -0
  129. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.js +72 -0
  130. package/dist/utils/floating-ui/svelte/index.d.ts +5 -0
  131. package/dist/utils/floating-ui/svelte/index.js +5 -0
  132. package/dist/utils/floating-ui/svelte/inner.svelte.d.ts +83 -0
  133. package/dist/utils/floating-ui/svelte/inner.svelte.js +178 -0
  134. package/dist/utils/floating-ui/svelte/types.d.ts +114 -0
  135. package/dist/utils/floating-ui/svelte/types.js +1 -0
  136. package/dist/utils/floating-ui/svelte/utils/createPubSub.d.ts +5 -0
  137. package/dist/utils/floating-ui/svelte/utils/createPubSub.js +14 -0
  138. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.d.ts +2 -0
  139. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.js +13 -0
  140. package/dist/utils/floating-ui/svelte/utils/log.d.ts +2 -0
  141. package/dist/utils/floating-ui/svelte/utils/log.js +19 -0
  142. package/dist/utils/floating-ui/svelte/utils.d.ts +19 -0
  143. package/dist/utils/floating-ui/svelte/utils.js +136 -0
  144. package/dist/utils/floating-ui/svelte-dom/arrow.d.ts +22 -0
  145. package/dist/utils/floating-ui/svelte-dom/arrow.js +29 -0
  146. package/dist/utils/floating-ui/svelte-dom/index.d.ts +2 -0
  147. package/dist/utils/floating-ui/svelte-dom/index.js +2 -0
  148. package/dist/utils/floating-ui/svelte-dom/types.d.ts +80 -0
  149. package/dist/utils/floating-ui/svelte-dom/types.js +3 -0
  150. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.d.ts +6 -0
  151. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +182 -0
  152. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.d.ts +1 -0
  153. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.js +50 -0
  154. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.d.ts +1 -0
  155. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.js +7 -0
  156. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.d.ts +1 -0
  157. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.js +5 -0
  158. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.d.ts +4 -0
  159. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.js +7 -0
  160. package/dist/utils/id.d.ts +1 -1
  161. package/dist/utils/id.js +1 -1
  162. package/dist/utils/style.d.ts +2 -0
  163. package/dist/utils/style.js +6 -0
  164. package/dist/utils/types.d.ts +1 -2
  165. package/package.json +25 -24
  166. package/dist/internal/HoistFormFields.svelte +0 -11
  167. package/dist/internal/id.d.ts +0 -8
  168. package/dist/internal/id.js +0 -11
@@ -0,0 +1,158 @@
1
+ import { useFloating as usePosition } from "../../svelte-dom/index.js";
2
+ import { isElement } from "@floating-ui/utils/dom";
3
+ import { useFloatingTree } from "../components/FloatingTree.svelte";
4
+ import { useFloatingRootContext } from "./useFloatingRootContext.svelte.js";
5
+ /**
6
+ * Provides data to position a floating element and context to add interactions.
7
+ * @see https://floating-ui.com/docs/useFloating
8
+ */
9
+ export function useFloating(options = {}) {
10
+ const { nodeId } = $derived(options);
11
+ const internalRootContext = useFloatingRootContext({
12
+ get open() {
13
+ return options.open;
14
+ },
15
+ get onOpenChange() {
16
+ return options.onOpenChange;
17
+ },
18
+ get elements() {
19
+ return {
20
+ reference: null,
21
+ floating: null,
22
+ ...options.elements,
23
+ };
24
+ },
25
+ });
26
+ const rootContext = $derived(options.rootContext || internalRootContext);
27
+ const computedElements = $derived(rootContext.elements);
28
+ let _domReference = $state(null);
29
+ const setDomReference = (value) => (_domReference = value);
30
+ let positionReference = $state(null);
31
+ const _setPositionReference = (value) => (positionReference = value);
32
+ const optionDomReference = $derived(computedElements?.reference);
33
+ const domReference = $derived((optionDomReference || _domReference));
34
+ const domReferenceRef = $state({ current: null });
35
+ const tree = useFloatingTree();
36
+ $effect(() => {
37
+ if (domReference) {
38
+ domReferenceRef.current = domReference;
39
+ }
40
+ });
41
+ const position = usePosition({
42
+ get placement() {
43
+ return options.placement;
44
+ },
45
+ get strategy() {
46
+ return options.strategy;
47
+ },
48
+ get middleware() {
49
+ return options.middleware;
50
+ },
51
+ get platform() {
52
+ return options.platform;
53
+ },
54
+ get whileElementsMounted() {
55
+ return options.whileElementsMounted;
56
+ },
57
+ get open() {
58
+ return options.open;
59
+ },
60
+ get transform() {
61
+ return options.transform;
62
+ },
63
+ get elements() {
64
+ return {
65
+ ...computedElements,
66
+ ...(positionReference && { reference: positionReference }),
67
+ };
68
+ },
69
+ });
70
+ const setPositionReference = (node) => {
71
+ const computedPositionReference = isElement(node)
72
+ ? {
73
+ getBoundingClientRect: () => node.getBoundingClientRect(),
74
+ contextElement: node,
75
+ }
76
+ : node;
77
+ // Store the positionReference in state if the DOM reference is specified externally via the
78
+ // `elements.reference` option. This ensures that it won't be overridden on future renders.
79
+ _setPositionReference(computedPositionReference);
80
+ position.refs.setReference(computedPositionReference);
81
+ };
82
+ const setReference = (node) => {
83
+ if (isElement(node) || node === null) {
84
+ ;
85
+ domReferenceRef.current = node;
86
+ setDomReference(node);
87
+ }
88
+ // Backwards-compatibility for passing a virtual element to `reference`
89
+ // after it has set the DOM reference.
90
+ if (isElement(position.refs.reference.current) ||
91
+ position.refs.reference.current === null ||
92
+ // Don't allow setting virtual elements using the old technique back to
93
+ // `null` to support `positionReference` + an unstable `reference`
94
+ // callback ref.
95
+ (node !== null && !isElement(node))) {
96
+ position.refs.setReference(node);
97
+ }
98
+ };
99
+ const refs = $derived({
100
+ ...position.refs,
101
+ setReference,
102
+ setPositionReference,
103
+ domReference: domReferenceRef,
104
+ });
105
+ const elements = $derived({
106
+ ...position.elements,
107
+ domReference: domReference,
108
+ });
109
+ const context = $derived({
110
+ ...position,
111
+ ...rootContext,
112
+ refs,
113
+ elements,
114
+ nodeId,
115
+ });
116
+ $effect(() => {
117
+ rootContext.dataRef.current.floatingContext = context;
118
+ const node = tree?.nodesRef.current.find((node) => node.id === nodeId);
119
+ if (node) {
120
+ node.context = context;
121
+ }
122
+ });
123
+ return {
124
+ get placement() {
125
+ return position.placement;
126
+ },
127
+ get strategy() {
128
+ return position.strategy;
129
+ },
130
+ get middlewareData() {
131
+ return position.middlewareData;
132
+ },
133
+ get x() {
134
+ return position.x;
135
+ },
136
+ get y() {
137
+ return position.y;
138
+ },
139
+ get isPositioned() {
140
+ return position.isPositioned;
141
+ },
142
+ get update() {
143
+ return position.update;
144
+ },
145
+ get floatingStyles() {
146
+ return position.floatingStyles;
147
+ },
148
+ get context() {
149
+ return context;
150
+ },
151
+ get refs() {
152
+ return refs;
153
+ },
154
+ get elements() {
155
+ return elements;
156
+ },
157
+ };
158
+ }
@@ -0,0 +1,11 @@
1
+ import type { FloatingRootContext } from "../types.js";
2
+ import type { OpenChangeReason } from "../types.js";
3
+ export interface UseFloatingRootContextOptions {
4
+ open?: boolean;
5
+ onOpenChange?: (open: boolean, event?: Event, reason?: OpenChangeReason) => void;
6
+ elements: {
7
+ reference: Element | null;
8
+ floating: HTMLElement | null;
9
+ };
10
+ }
11
+ export declare function useFloatingRootContext(options: UseFloatingRootContextOptions): FloatingRootContext;
@@ -0,0 +1,53 @@
1
+ import { isElement } from "@floating-ui/utils/dom";
2
+ //import { useEffectEvent } from "./utils/useEffectEvent"
3
+ import { createPubSub } from "../utils/createPubSub.js";
4
+ import { useId } from "./useId.svelte.js";
5
+ import { useFloatingParentNodeId } from "../components/FloatingTree.svelte";
6
+ import { error } from "../utils/log.js";
7
+ import { DEV } from "esm-env";
8
+ export function useFloatingRootContext(options) {
9
+ const { open = false, onOpenChange: onOpenChangeProp, elements: elementsProp } = options;
10
+ const floatingId = useId();
11
+ const dataRef = $state({ current: {} });
12
+ const events = createPubSub();
13
+ const nested = useFloatingParentNodeId() != null;
14
+ if (DEV) {
15
+ const optionDomReference = elementsProp.reference;
16
+ if (optionDomReference && !isElement(optionDomReference)) {
17
+ error("Cannot pass a virtual element to the `elements.reference` option,", "as it must be a real DOM element. Use `refs.setPositionReference()`", "instead.");
18
+ }
19
+ }
20
+ let positionReference = $state(elementsProp.reference);
21
+ const onOpenChange = (open, event, reason) => {
22
+ dataRef.current.openEvent = open ? event : undefined;
23
+ events.emit("openchange", { open, event, reason, nested });
24
+ onOpenChangeProp?.(open, event, reason);
25
+ };
26
+ const refs = {
27
+ setPositionReference: (value) => {
28
+ positionReference = value;
29
+ },
30
+ };
31
+ const elements = $derived({
32
+ reference: positionReference || elementsProp.reference || null,
33
+ floating: elementsProp.floating || null,
34
+ domReference: elementsProp.reference,
35
+ });
36
+ return {
37
+ get dataRef() {
38
+ return dataRef;
39
+ },
40
+ get open() {
41
+ return open;
42
+ },
43
+ onOpenChange,
44
+ get elements() {
45
+ return elements;
46
+ },
47
+ events,
48
+ get floatingId() {
49
+ return floatingId;
50
+ },
51
+ refs,
52
+ };
53
+ }
@@ -0,0 +1,9 @@
1
+ declare function useFloatingId(): string;
2
+ /**
3
+ * Uses React 18's built-in `useId()` when available, or falls back to a
4
+ * slightly less performant (requiring a double render) implementation for
5
+ * earlier React versions.
6
+ * @see https://floating-ui.com/docs/react-utils#useid
7
+ */
8
+ export declare const useId: typeof useFloatingId;
9
+ export {};
@@ -0,0 +1,28 @@
1
+ let serverHandoffComplete = false;
2
+ let count = 0;
3
+ const genId = () =>
4
+ // Ensure the id is unique with multiple independent versions of Floating UI
5
+ // on <React 18
6
+ `floating-ui-${Math.random().toString(36).slice(2, 6)}${count++}`;
7
+ function useFloatingId() {
8
+ /*let id = $state(serverHandoffComplete ? genId() : undefined)
9
+
10
+ $effect(() => {
11
+ if (id == null) {
12
+ id = genId()
13
+ }
14
+ })
15
+
16
+ $effect(() => {
17
+ serverHandoffComplete = true
18
+ })*/
19
+ return genId();
20
+ }
21
+ //const useReactId = SafeReact.useId as () => string
22
+ /**
23
+ * Uses React 18's built-in `useId()` when available, or falls back to a
24
+ * slightly less performant (requiring a double render) implementation for
25
+ * earlier React versions.
26
+ * @see https://floating-ui.com/docs/react-utils#useid
27
+ */
28
+ export const useId = /*useReactId ||*/ useFloatingId;
@@ -0,0 +1,23 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ import type { ElementProps } from "../types.js";
3
+ declare const ACTIVE_KEY = "active";
4
+ declare const SELECTED_KEY = "selected";
5
+ export type ExtendedUserProps = {
6
+ [ACTIVE_KEY]?: boolean;
7
+ [SELECTED_KEY]?: boolean;
8
+ };
9
+ export interface UseInteractionsReturn {
10
+ getReferenceProps: (userProps?: HTMLAttributes<Element>) => Record<string, unknown>;
11
+ getFloatingProps: (userProps?: HTMLAttributes<HTMLElement>) => Record<string, unknown>;
12
+ getItemProps: (userProps?: Omit<HTMLAttributes<HTMLElement>, "selected" | "active"> & ExtendedUserProps) => Record<string, unknown>;
13
+ }
14
+ /**
15
+ * Merges an array of interaction hooks' props into prop getters, allowing
16
+ * event handler functions to be composed together without overwriting one
17
+ * another.
18
+ * @see https://floating-ui.com/docs/useInteractions
19
+ */
20
+ export declare function useInteractions(options?: {
21
+ propsList: Array<ElementProps | void>;
22
+ }): UseInteractionsReturn;
23
+ export {};
@@ -0,0 +1,72 @@
1
+ import { FOCUSABLE_ATTRIBUTE } from "../utils/getFloatingFocusElement.js";
2
+ const ACTIVE_KEY = "active";
3
+ const SELECTED_KEY = "selected";
4
+ function mergeProps(userProps, propsList, elementKey) {
5
+ const map = new Map();
6
+ const isItem = elementKey === "item";
7
+ let domUserProps = userProps;
8
+ if (isItem && userProps) {
9
+ const { [ACTIVE_KEY]: _, [SELECTED_KEY]: __, ...validProps } = userProps;
10
+ domUserProps = validProps;
11
+ }
12
+ return {
13
+ ...(elementKey === "floating" && {
14
+ tabIndex: -1,
15
+ [FOCUSABLE_ATTRIBUTE]: "",
16
+ }),
17
+ ...domUserProps,
18
+ ...propsList
19
+ .map((value) => {
20
+ const propsOrGetProps = value ? value[elementKey] : null;
21
+ if (typeof propsOrGetProps === "function") {
22
+ return userProps ? propsOrGetProps(userProps) : null;
23
+ }
24
+ return propsOrGetProps;
25
+ })
26
+ .concat(userProps)
27
+ .reduce((acc, props) => {
28
+ if (!props) {
29
+ return acc;
30
+ }
31
+ Object.entries(props).forEach(([key, value]) => {
32
+ if (isItem && [ACTIVE_KEY, SELECTED_KEY].includes(key)) {
33
+ return;
34
+ }
35
+ if (key.indexOf("on") === 0) {
36
+ if (!map.has(key)) {
37
+ map.set(key, []);
38
+ }
39
+ if (typeof value === "function") {
40
+ map.get(key)?.push(value);
41
+ acc[key] = (...args) => {
42
+ return map
43
+ .get(key)
44
+ ?.map((fn) => fn(...args))
45
+ .find((val) => val !== undefined);
46
+ };
47
+ }
48
+ }
49
+ else {
50
+ acc[key] = value;
51
+ }
52
+ });
53
+ return acc;
54
+ }, {}),
55
+ };
56
+ }
57
+ /**
58
+ * Merges an array of interaction hooks' props into prop getters, allowing
59
+ * event handler functions to be composed together without overwriting one
60
+ * another.
61
+ * @see https://floating-ui.com/docs/useInteractions
62
+ */
63
+ export function useInteractions(options = { propsList: [] }) {
64
+ const { propsList } = $derived(options);
65
+ //const referenceDeps = $derived(propsList.map((key) => key?.reference))
66
+ //const floatingDeps = $derived(propsList.map((key) => key?.floating))
67
+ //const itemDeps = $derived(propsList.map((key) => key?.item))
68
+ const getReferenceProps = (userProps) => mergeProps(userProps, propsList, "reference");
69
+ const getFloatingProps = (userProps) => mergeProps(userProps, propsList, "floating");
70
+ const getItemProps = (userProps) => mergeProps(userProps, propsList, "item");
71
+ return { getReferenceProps, getFloatingProps, getItemProps };
72
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./types.js";
2
+ export { useFloating } from "./hooks/useFloating.svelte.js";
3
+ export { useInteractions } from "./hooks/useInteractions.svelte.js";
4
+ export { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, getOverflowAncestors, hide, inline, limitShift, offset, platform, shift, size, } from "../svelte-dom/index.js";
5
+ export { inner, useInnerOffset, type InnerProps, type UseInnerOffsetProps } from "./inner.svelte.js";
@@ -0,0 +1,5 @@
1
+ export * from "./types.js";
2
+ export { useFloating } from "./hooks/useFloating.svelte.js";
3
+ export { useInteractions } from "./hooks/useInteractions.svelte.js";
4
+ export { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, getOverflowAncestors, hide, inline, limitShift, offset, platform, shift, size, } from "../svelte-dom/index.js";
5
+ export { inner, useInnerOffset } from "./inner.svelte.js";
@@ -0,0 +1,83 @@
1
+ import { type Derivable } from "../svelte-dom/index.js";
2
+ import type { DetectOverflowOptions, ElementProps, FloatingRootContext, Middleware, SideObject } from "./types.js";
3
+ import type { MutableRefObject } from "../../ref.svelte.js";
4
+ export interface InnerProps extends DetectOverflowOptions {
5
+ /**
6
+ * A ref which contains an array of HTML elements.
7
+ * @default empty list
8
+ */
9
+ listRef: MutableRefObject<Array<HTMLElement | null>>;
10
+ /**
11
+ * The index of the active (focused or highlighted) item in the list.
12
+ * @default 0
13
+ */
14
+ index: number;
15
+ /**
16
+ * Callback invoked when the fallback state changes.
17
+ */
18
+ onFallbackChange?: null | ((fallback: boolean) => void);
19
+ /**
20
+ * The offset to apply to the floating element.
21
+ * @default 0
22
+ */
23
+ offset?: number;
24
+ /**
25
+ * A ref which contains the overflow of the floating element.
26
+ */
27
+ overflowRef?: MutableRefObject<SideObject | null>;
28
+ /**
29
+ * An optional ref containing an HTMLElement. This may be used as the
30
+ * scrolling container instead of the floating element — for instance,
31
+ * to position inner elements as direct children without being interfered by
32
+ * scrolling layout.
33
+ */
34
+ scrollRef?: MutableRefObject<HTMLElement | null>;
35
+ /**
36
+ * The minimum number of items that should be visible in the list.
37
+ * @default 4
38
+ */
39
+ minItemsVisible?: number;
40
+ /**
41
+ * The threshold for the reference element's overflow in pixels.
42
+ * @default 0
43
+ */
44
+ referenceOverflowThreshold?: number;
45
+ }
46
+ /**
47
+ * Positions the floating element such that an inner element inside of it is
48
+ * anchored to the reference element.
49
+ * @see https://floating-ui.com/docs/inner
50
+ */
51
+ export declare const inner: (props: InnerProps | Derivable<InnerProps>) => Middleware;
52
+ export interface UseInnerOffsetProps {
53
+ /**
54
+ * Whether the Hook is enabled, including all internal Effects and event
55
+ * handlers.
56
+ * @default true
57
+ */
58
+ enabled?: boolean;
59
+ /**
60
+ * A ref which contains the overflow of the floating element.
61
+ */
62
+ overflowRef: MutableRefObject<SideObject | null>;
63
+ /**
64
+ * An optional ref containing an HTMLElement. This may be used as the
65
+ * scrolling container instead of the floating element — for instance,
66
+ * to position inner elements as direct children without being interfered by
67
+ * scrolling layout.
68
+ */
69
+ scrollRef?: MutableRefObject<HTMLElement | null>;
70
+ /**
71
+ * Callback invoked when the offset changes.
72
+ */
73
+ onChange: (offset: number | ((offset: number) => number)) => void;
74
+ }
75
+ /**
76
+ * Changes the `inner` middleware's `offset` upon a `wheel` event to
77
+ * expand the floating element's height, revealing more list items.
78
+ * @see https://floating-ui.com/docs/inner
79
+ */
80
+ export declare function useInnerOffset(options: {
81
+ context: FloatingRootContext;
82
+ props: UseInnerOffsetProps;
83
+ }): ElementProps;
@@ -0,0 +1,178 @@
1
+ import { getUserAgent } from "./utils.js";
2
+ import { evaluate, max, min, round } from "@floating-ui/utils";
3
+ import { detectOverflow, offset } from "../svelte-dom/index.js";
4
+ import { warn } from "./utils/log.js";
5
+ import { DEV } from "esm-env";
6
+ import { tick, untrack } from "svelte";
7
+ function getArgsWithCustomFloatingHeight(state, height) {
8
+ return {
9
+ ...state,
10
+ rects: {
11
+ ...state.rects,
12
+ floating: {
13
+ ...state.rects.floating,
14
+ height,
15
+ },
16
+ },
17
+ };
18
+ }
19
+ /**
20
+ * Positions the floating element such that an inner element inside of it is
21
+ * anchored to the reference element.
22
+ * @see https://floating-ui.com/docs/inner
23
+ */
24
+ export const inner = (props) => ({
25
+ name: "inner",
26
+ options: props,
27
+ async fn(state) {
28
+ const { listRef, overflowRef, onFallbackChange, offset: innerOffset = 0, index = 0, minItemsVisible = 4, referenceOverflowThreshold = 0, scrollRef, ...detectOverflowOptions } = evaluate(props, state);
29
+ const { rects, elements: { floating }, } = state;
30
+ const item = listRef.current[index];
31
+ const scrollEl = scrollRef?.current || floating;
32
+ // Valid combinations:
33
+ // 1. Floating element is the scrollRef and has a border (default)
34
+ // 2. Floating element is not the scrollRef, floating element has a border
35
+ // 3. Floating element is not the scrollRef, scrollRef has a border
36
+ // Floating > {...getFloatingProps()} wrapper > scrollRef > items is not
37
+ // allowed as VoiceOver doesn't work.
38
+ const clientTop = floating.clientTop || scrollEl.clientTop;
39
+ const floatingIsBordered = floating.clientTop !== 0;
40
+ const scrollElIsBordered = scrollEl.clientTop !== 0;
41
+ const floatingIsScrollEl = floating === scrollEl;
42
+ if (DEV) {
43
+ if (!state.placement.startsWith("bottom")) {
44
+ warn('`placement` side must be "bottom" when using the `inner`', "middleware.");
45
+ }
46
+ }
47
+ if (!item) {
48
+ return {};
49
+ }
50
+ const nextArgs = {
51
+ ...state,
52
+ ...(await offset(-item.offsetTop - floating.clientTop - rects.reference.height / 2 - item.offsetHeight / 2 - innerOffset).fn(state)),
53
+ };
54
+ const overflow = await detectOverflow(getArgsWithCustomFloatingHeight(nextArgs, scrollEl.scrollHeight + clientTop + floating.clientTop), detectOverflowOptions);
55
+ const refOverflow = await detectOverflow(nextArgs, {
56
+ ...detectOverflowOptions,
57
+ elementContext: "reference",
58
+ });
59
+ const diffY = max(0, overflow.top);
60
+ const nextY = nextArgs.y + diffY;
61
+ const maxHeight = round(max(0, scrollEl.scrollHeight +
62
+ ((floatingIsBordered && floatingIsScrollEl) || scrollElIsBordered ? clientTop * 2 : 0) -
63
+ diffY -
64
+ max(0, overflow.bottom)));
65
+ scrollEl.style.maxHeight = `${maxHeight}px`;
66
+ scrollEl.scrollTop = diffY;
67
+ // There is not enough space, fallback to standard anchored positioning
68
+ if (onFallbackChange) {
69
+ const shouldFallback = (scrollEl.scrollHeight > scrollEl.offsetHeight &&
70
+ scrollEl.offsetHeight < item.offsetHeight * minItemsVisible - 1) ||
71
+ refOverflow.top >= -referenceOverflowThreshold ||
72
+ refOverflow.bottom >= -referenceOverflowThreshold;
73
+ onFallbackChange(shouldFallback);
74
+ await tick();
75
+ }
76
+ if (overflowRef) {
77
+ overflowRef.current = await detectOverflow(getArgsWithCustomFloatingHeight({ ...nextArgs, y: nextY }, scrollEl.offsetHeight + clientTop + floating.clientTop), detectOverflowOptions);
78
+ }
79
+ return {
80
+ y: nextY,
81
+ };
82
+ },
83
+ });
84
+ /**
85
+ * Changes the `inner` middleware's `offset` upon a `wheel` event to
86
+ * expand the floating element's height, revealing more list items.
87
+ * @see https://floating-ui.com/docs/inner
88
+ */
89
+ export function useInnerOffset(options) {
90
+ const { context, props } = $derived(options);
91
+ const { open, elements } = $derived(context);
92
+ const { enabled = true, overflowRef, scrollRef, onChange: unstable_onChange } = $derived(props);
93
+ const onChange = unstable_onChange;
94
+ const controlledScrollingRef = $state({ current: false });
95
+ const prevScrollTopRef = $state({ current: null });
96
+ const initialOverflowRef = $state({ current: null });
97
+ $effect(() => {
98
+ if (!enabled)
99
+ return;
100
+ [enabled, open, elements.floating, overflowRef, scrollRef, onChange];
101
+ untrack(() => {
102
+ function onWheel(e) {
103
+ if (e.ctrlKey || !el || overflowRef.current == null) {
104
+ return;
105
+ }
106
+ const dY = e.deltaY;
107
+ const isAtTop = overflowRef.current.top >= -0.5;
108
+ const isAtBottom = overflowRef.current.bottom >= -0.5;
109
+ const remainingScroll = el.scrollHeight - el.clientHeight;
110
+ const sign = dY < 0 ? -1 : 1;
111
+ const method = dY < 0 ? "max" : "min";
112
+ if (el.scrollHeight <= el.clientHeight) {
113
+ return;
114
+ }
115
+ if ((!isAtTop && dY > 0) || (!isAtBottom && dY < 0)) {
116
+ e.preventDefault();
117
+ onChange((d) => d + Math[method](dY, remainingScroll * sign));
118
+ tick();
119
+ }
120
+ else if (/firefox/i.test(getUserAgent())) {
121
+ // Needed to propagate scrolling during momentum scrolling phase once
122
+ // it gets limited by the boundary. UX improvement, not critical.
123
+ el.scrollTop += dY;
124
+ }
125
+ }
126
+ const el = scrollRef?.current || elements.floating;
127
+ if (open && el) {
128
+ el.addEventListener("wheel", onWheel);
129
+ // Wait for the position to be ready.
130
+ requestAnimationFrame(() => {
131
+ prevScrollTopRef.current = el.scrollTop;
132
+ if (overflowRef.current != null) {
133
+ initialOverflowRef.current = { ...overflowRef.current };
134
+ }
135
+ });
136
+ return () => {
137
+ prevScrollTopRef.current = null;
138
+ initialOverflowRef.current = null;
139
+ el.removeEventListener("wheel", onWheel);
140
+ };
141
+ }
142
+ });
143
+ });
144
+ const floating = {
145
+ onkeydown() {
146
+ controlledScrollingRef.current = true;
147
+ },
148
+ onwheel() {
149
+ controlledScrollingRef.current = false;
150
+ },
151
+ onpointermove() {
152
+ controlledScrollingRef.current = false;
153
+ },
154
+ async onscroll() {
155
+ const el = scrollRef?.current || elements.floating;
156
+ if (!overflowRef.current || !el || !controlledScrollingRef.current) {
157
+ return;
158
+ }
159
+ if (prevScrollTopRef.current !== null) {
160
+ const scrollDiff = el.scrollTop - prevScrollTopRef.current;
161
+ if ((overflowRef.current.bottom < -0.5 && scrollDiff < -1) ||
162
+ (overflowRef.current.top < -0.5 && scrollDiff > 1)) {
163
+ onChange((d) => d + scrollDiff);
164
+ await tick();
165
+ }
166
+ }
167
+ // [Firefox] Wait for the height change to have been applied.
168
+ requestAnimationFrame(() => {
169
+ prevScrollTopRef.current = el.scrollTop;
170
+ });
171
+ },
172
+ };
173
+ return {
174
+ get floating() {
175
+ return enabled ? floating : undefined;
176
+ },
177
+ };
178
+ }