@pzerelles/headlessui-svelte 2.1.2-next.10 → 2.1.2-next.12

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 (69) hide show
  1. package/dist/hooks/use-controllable.svelte.js +2 -1
  2. package/dist/hooks/use-did-element-move.svelte.js +5 -10
  3. package/dist/internal/FloatingProvider.svelte +12 -0
  4. package/dist/internal/FloatingProvider.svelte.d.ts +22 -0
  5. package/dist/internal/floating-provider.svelte.d.ts +3 -0
  6. package/dist/internal/floating-provider.svelte.js +206 -0
  7. package/dist/internal/floating.svelte.d.ts +48 -23
  8. package/dist/internal/floating.svelte.js +78 -260
  9. package/dist/internal/inner.svelte.d.ts +91 -0
  10. package/dist/internal/inner.svelte.js +202 -0
  11. package/dist/listbox/Listbox.svelte +38 -52
  12. package/dist/listbox/Listbox.svelte.d.ts +3 -54
  13. package/dist/listbox/ListboxButton.svelte +7 -6
  14. package/dist/listbox/ListboxOption.svelte +7 -3
  15. package/dist/listbox/ListboxOptions.svelte +50 -50
  16. package/dist/listbox/context.svelte.d.ts +75 -0
  17. package/dist/listbox/context.svelte.js +36 -0
  18. package/dist/menu/Menu.svelte +2 -2
  19. package/dist/menu/MenuButton.svelte +4 -2
  20. package/dist/menu/MenuItems.svelte +15 -11
  21. package/dist/tabs/TabGroup.svelte.d.ts +1 -1
  22. package/dist/utils/ElementOrComponent.svelte +1 -1
  23. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +17 -0
  24. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte.d.ts +23 -0
  25. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +50 -0
  26. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte.d.ts +41 -0
  27. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.d.ts +6 -0
  28. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +158 -0
  29. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.d.ts +11 -0
  30. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +53 -0
  31. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.d.ts +9 -0
  32. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.js +28 -0
  33. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.d.ts +23 -0
  34. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.js +72 -0
  35. package/dist/utils/floating-ui/svelte/index.d.ts +5 -0
  36. package/dist/utils/floating-ui/svelte/index.js +5 -0
  37. package/dist/utils/floating-ui/svelte/inner.svelte.d.ts +83 -0
  38. package/dist/utils/floating-ui/svelte/inner.svelte.js +178 -0
  39. package/dist/utils/floating-ui/svelte/types.d.ts +114 -0
  40. package/dist/utils/floating-ui/svelte/types.js +1 -0
  41. package/dist/utils/floating-ui/svelte/utils/createPubSub.d.ts +5 -0
  42. package/dist/utils/floating-ui/svelte/utils/createPubSub.js +14 -0
  43. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.d.ts +2 -0
  44. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.js +13 -0
  45. package/dist/utils/floating-ui/svelte/utils/log.d.ts +2 -0
  46. package/dist/utils/floating-ui/svelte/utils/log.js +19 -0
  47. package/dist/utils/floating-ui/svelte/utils.d.ts +19 -0
  48. package/dist/utils/floating-ui/svelte/utils.js +136 -0
  49. package/dist/utils/floating-ui/svelte-dom/arrow.d.ts +22 -0
  50. package/dist/utils/floating-ui/svelte-dom/arrow.js +29 -0
  51. package/dist/utils/floating-ui/svelte-dom/index.d.ts +2 -0
  52. package/dist/utils/floating-ui/svelte-dom/index.js +2 -0
  53. package/dist/utils/floating-ui/svelte-dom/types.d.ts +80 -0
  54. package/dist/utils/floating-ui/svelte-dom/types.js +3 -0
  55. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.d.ts +6 -0
  56. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +182 -0
  57. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.d.ts +1 -0
  58. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.js +50 -0
  59. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.d.ts +1 -0
  60. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.js +7 -0
  61. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.d.ts +1 -0
  62. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.js +5 -0
  63. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.d.ts +4 -0
  64. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.js +7 -0
  65. package/dist/utils/style.d.ts +2 -0
  66. package/dist/utils/style.js +6 -0
  67. package/package.json +3 -2
  68. package/dist/listbox/ListboxStates.d.ts +0 -12
  69. package/dist/listbox/ListboxStates.js +0 -15
@@ -0,0 +1,202 @@
1
+ import { evaluate, max, min, round } from "@floating-ui/utils";
2
+ import { DEV } from "esm-env";
3
+ import { detectOverflow, offset, } from "@floating-ui/dom";
4
+ import { tick, untrack } from "svelte";
5
+ let devMessageSet;
6
+ if (DEV) {
7
+ devMessageSet = new Set();
8
+ }
9
+ export function warn(...messages) {
10
+ const message = `Floating UI: ${messages.join(" ")}`;
11
+ if (!devMessageSet?.has(message)) {
12
+ devMessageSet?.add(message);
13
+ console.warn(message);
14
+ }
15
+ }
16
+ export function error(...messages) {
17
+ const message = `Floating UI: ${messages.join(" ")}`;
18
+ if (!devMessageSet?.has(message)) {
19
+ devMessageSet?.add(message);
20
+ console.error(message);
21
+ }
22
+ }
23
+ export function getUserAgent() {
24
+ const uaData = navigator.userAgentData;
25
+ if (uaData && Array.isArray(uaData.brands)) {
26
+ return uaData.brands.map(({ brand, version }) => `${brand}/${version}`).join(" ");
27
+ }
28
+ return navigator.userAgent;
29
+ }
30
+ // ------
31
+ function getArgsWithCustomFloatingHeight(state, height) {
32
+ return {
33
+ ...state,
34
+ rects: {
35
+ ...state.rects,
36
+ floating: {
37
+ ...state.rects.floating,
38
+ height,
39
+ },
40
+ },
41
+ };
42
+ }
43
+ /**
44
+ * Positions the floating element such that an inner element inside of it is
45
+ * anchored to the reference element.
46
+ * @see https://floating-ui.com/docs/inner
47
+ */
48
+ export const inner = (props) => ({
49
+ name: "inner",
50
+ options: props,
51
+ async fn(state) {
52
+ const { listRef, overflowRef, onFallbackChange, offset: innerOffset = 0, index = 0, minItemsVisible = 4, referenceOverflowThreshold = 0, scrollRef, ...detectOverflowOptions } = evaluate(props, state);
53
+ const { rects, elements: { floating }, } = state;
54
+ const item = listRef.current[index];
55
+ const scrollEl = scrollRef?.current || floating;
56
+ // Valid combinations:
57
+ // 1. Floating element is the scrollRef and has a border (default)
58
+ // 2. Floating element is not the scrollRef, floating element has a border
59
+ // 3. Floating element is not the scrollRef, scrollRef has a border
60
+ // Floating > {...getFloatingProps()} wrapper > scrollRef > items is not
61
+ // allowed as VoiceOver doesn't work.
62
+ const clientTop = floating.clientTop || scrollEl.clientTop;
63
+ const floatingIsBordered = floating.clientTop !== 0;
64
+ const scrollElIsBordered = scrollEl.clientTop !== 0;
65
+ const floatingIsScrollEl = floating === scrollEl;
66
+ if (DEV) {
67
+ if (!state.placement.startsWith("bottom")) {
68
+ warn('`placement` side must be "bottom" when using the `inner`', "middleware.");
69
+ }
70
+ }
71
+ if (!item) {
72
+ return {};
73
+ }
74
+ const nextArgs = {
75
+ ...state,
76
+ ...(await offset(-item.offsetTop - floating.clientTop - rects.reference.height / 2 - item.offsetHeight / 2 - innerOffset).fn(state)),
77
+ };
78
+ const overflow = await detectOverflow(getArgsWithCustomFloatingHeight(nextArgs, scrollEl.scrollHeight + clientTop + floating.clientTop), detectOverflowOptions);
79
+ const refOverflow = await detectOverflow(nextArgs, {
80
+ ...detectOverflowOptions,
81
+ elementContext: "reference",
82
+ });
83
+ const diffY = max(0, overflow.top);
84
+ const nextY = nextArgs.y + diffY;
85
+ const maxHeight = round(max(0, scrollEl.scrollHeight +
86
+ ((floatingIsBordered && floatingIsScrollEl) || scrollElIsBordered ? clientTop * 2 : 0) -
87
+ diffY -
88
+ max(0, overflow.bottom)));
89
+ scrollEl.style.maxHeight = `${maxHeight}px`;
90
+ scrollEl.scrollTop = diffY;
91
+ // There is not enough space, fallback to standard anchored positioning
92
+ if (onFallbackChange) {
93
+ const shouldFallback = (scrollEl.scrollHeight > scrollEl.offsetHeight &&
94
+ scrollEl.offsetHeight < item.offsetHeight * minItemsVisible - 1) ||
95
+ refOverflow.top >= -referenceOverflowThreshold ||
96
+ refOverflow.bottom >= -referenceOverflowThreshold;
97
+ onFallbackChange(shouldFallback);
98
+ await tick();
99
+ }
100
+ if (overflowRef) {
101
+ overflowRef.current = await detectOverflow(getArgsWithCustomFloatingHeight({ ...nextArgs, y: nextY }, scrollEl.offsetHeight + clientTop + floating.clientTop), detectOverflowOptions);
102
+ }
103
+ return {
104
+ y: nextY,
105
+ };
106
+ },
107
+ });
108
+ /**
109
+ * Changes the `inner` middleware's `offset` upon a `wheel` event to
110
+ * expand the floating element's height, revealing more list items.
111
+ * @see https://floating-ui.com/docs/inner
112
+ */
113
+ export function useInnerOffset(options) {
114
+ const { context, props } = $derived(options);
115
+ const { open, elements } = $derived(context);
116
+ const { enabled = true, overflowRef, scrollRef, onChange: unstable_onChange } = $derived(props);
117
+ const onChange = unstable_onChange;
118
+ let controlledScrollingRef = $state(false);
119
+ let prevScrollTopRef = $state(null);
120
+ let initialOverflowRef = $state(null);
121
+ $effect(() => {
122
+ if (!enabled)
123
+ return;
124
+ [open, elements.floating, overflowRef, scrollRef, onChange];
125
+ untrack(() => {
126
+ function onWheel(e) {
127
+ if (e.ctrlKey || !el || overflowRef.current == null) {
128
+ return;
129
+ }
130
+ const dY = e.deltaY;
131
+ const isAtTop = overflowRef.current.top >= -0.5;
132
+ const isAtBottom = overflowRef.current.bottom >= -0.5;
133
+ const remainingScroll = el.scrollHeight - el.clientHeight;
134
+ const sign = dY < 0 ? -1 : 1;
135
+ const method = dY < 0 ? "max" : "min";
136
+ if (el.scrollHeight <= el.clientHeight) {
137
+ return;
138
+ }
139
+ if ((!isAtTop && dY > 0) || (!isAtBottom && dY < 0)) {
140
+ e.preventDefault();
141
+ onChange((d) => d + Math[method](dY, remainingScroll * sign));
142
+ tick();
143
+ }
144
+ else if (/firefox/i.test(getUserAgent())) {
145
+ // Needed to propagate scrolling during momentum scrolling phase once
146
+ // it gets limited by the boundary. UX improvement, not critical.
147
+ el.scrollTop += dY;
148
+ }
149
+ }
150
+ const el = scrollRef?.current || elements.floating;
151
+ if (open && el) {
152
+ el.addEventListener("wheel", onWheel);
153
+ // Wait for the position to be ready.
154
+ requestAnimationFrame(() => {
155
+ prevScrollTopRef = el.scrollTop;
156
+ if (overflowRef.current != null) {
157
+ initialOverflowRef = { ...overflowRef.current };
158
+ }
159
+ });
160
+ return () => {
161
+ prevScrollTopRef = null;
162
+ initialOverflowRef = null;
163
+ el.removeEventListener("wheel", onWheel);
164
+ };
165
+ }
166
+ });
167
+ });
168
+ const floating = $derived({
169
+ onKeyDown() {
170
+ controlledScrollingRef = true;
171
+ },
172
+ onWheel() {
173
+ controlledScrollingRef = false;
174
+ },
175
+ onPointerMove() {
176
+ controlledScrollingRef = false;
177
+ },
178
+ async onScroll() {
179
+ const el = scrollRef?.current || elements.floating;
180
+ if (!overflowRef.current || !el || !controlledScrollingRef) {
181
+ return;
182
+ }
183
+ if (prevScrollTopRef !== null) {
184
+ const scrollDiff = el.scrollTop - prevScrollTopRef;
185
+ if ((overflowRef.current.bottom < -0.5 && scrollDiff < -1) ||
186
+ (overflowRef.current.top < -0.5 && scrollDiff > 1)) {
187
+ onChange((d) => d + scrollDiff);
188
+ await tick();
189
+ }
190
+ }
191
+ // [Firefox] Wait for the height change to have been applied.
192
+ requestAnimationFrame(() => {
193
+ prevScrollTopRef = el.scrollTop;
194
+ });
195
+ },
196
+ });
197
+ return {
198
+ get floating() {
199
+ return enabled ? floating : undefined;
200
+ },
201
+ };
202
+ }
@@ -4,38 +4,20 @@ import { useDisabled } from "../hooks/use-disabled.js";
4
4
  import { calculateActiveIndex, Focus } from "../utils/calculate-active-index.js";
5
5
  import { FocusableMode, isFocusableElement, sortByDomNode } from "../utils/focus-management.js";
6
6
  import { match } from "../utils/match.js";
7
- import { useRef } from "../utils/ref.svelte.js";
8
- import { getContext, setContext } from "svelte";
9
- import { ActivationTrigger, ListboxStates, ValueMode } from "./ListboxStates.js";
7
+ import { setContext } from "svelte";
8
+ import { ActivationTrigger, ListboxStates, ValueMode } from "./context.svelte.js";
10
9
  let DEFAULT_LISTBOX_TAG = "svelte:fragment";
11
- export * from "./ListboxStates.js";
12
- export function useActions(component) {
13
- const context = getContext("ListboxActionsContext");
14
- if (!context) {
15
- let err = new Error(`<${component} /> is missing a parent <Listbox /> component.`);
16
- if (Error.captureStackTrace) Error.captureStackTrace(err, useActions);
17
- throw err;
18
- }
19
- return context;
20
- }
21
- export function useData(component) {
22
- const context = getContext("ListboxData");
23
- if (context === null) {
24
- let err = new Error(`<${component} /> is missing a parent <Listbox /> component.`);
25
- if (Error.captureStackTrace) Error.captureStackTrace(err, useData);
26
- throw err;
27
- }
28
- return context;
29
- }
10
+ export * from "./context.svelte.js";
30
11
  </script>
31
12
 
32
13
  <script lang="ts" generics="TType, TActualType, TTag extends ElementType = typeof DEFAULT_LISTBOX_TAG">import { disposables } from "../utils/disposables.js";
33
14
  import FormFields from "../internal/FormFields.svelte";
34
- import { createFloatingContext } from "../internal/floating.svelte.js";
15
+ import { useFloatingProvider } from "../internal/floating.svelte.js";
35
16
  import { createOpenClosedContext, State } from "../internal/open-closed.js";
36
17
  import { useLabels } from "../label/context.svelte.js";
37
18
  import { useOutsideClick } from "../hooks/use-outside-click.svelte.js";
38
19
  import ElementOrComponent from "../utils/ElementOrComponent.svelte";
20
+ import { SvelteMap } from "svelte/reactivity";
39
21
  function adjustOrderedState(state, adjustment = (i) => i) {
40
22
  let currentActiveOption = state.activeOptionIndex !== null ? state.options[state.activeOptionIndex] : null;
41
23
  let sortedOptions = sortByDomNode(
@@ -189,11 +171,11 @@ const stateReducer = (initialState) => {
189
171
  _state2.searchQuery = "";
190
172
  return _state2;
191
173
  },
192
- registerOption(action) {
193
- let option = { id: action.id, dataRef: action.dataRef };
174
+ registerOption(id, dataRef) {
175
+ let option = { id, dataRef };
194
176
  let adjustedState = adjustOrderedState(_state2, (options) => [...options, option]);
195
177
  if (_state2.activeOptionIndex === null) {
196
- if (isSelected(action.dataRef.current.value)) {
178
+ if (isSelected(dataRef.current.value)) {
197
179
  adjustedState.activeOptionIndex = adjustedState.options.indexOf(option);
198
180
  }
199
181
  }
@@ -201,9 +183,9 @@ const stateReducer = (initialState) => {
201
183
  _state2.activeOptionIndex = adjustedState.activeOptionIndex;
202
184
  return _state2;
203
185
  },
204
- unregisterOption(action) {
186
+ unregisterOption(id) {
205
187
  let adjustedState = adjustOrderedState(_state2, (options) => {
206
- let idx = options.findIndex((a) => a.id === action.id);
188
+ let idx = options.findIndex((a) => a.id === id);
207
189
  if (idx !== -1) options.splice(idx, 1);
208
190
  return options;
209
191
  });
@@ -214,13 +196,9 @@ const stateReducer = (initialState) => {
214
196
  }
215
197
  };
216
198
  };
217
- const listboxActionsContext = null;
218
- setContext("ListboxActionsContext", listboxActionsContext);
219
- const listboxDataContext = null;
220
- setContext("ListboxDataContext", listboxDataContext);
221
199
  let {
222
200
  ref = $bindable(),
223
- value: controlledValue,
201
+ value: controlledValue = $bindable(),
224
202
  defaultValue,
225
203
  form,
226
204
  name,
@@ -240,6 +218,9 @@ const controllable = useControllable(
240
218
  {
241
219
  get controlledValue() {
242
220
  return controlledValue;
221
+ },
222
+ set controlledValue(value2) {
223
+ controlledValue = value2;
243
224
  }
244
225
  },
245
226
  controlledOnChange,
@@ -255,10 +236,10 @@ const _state = stateReducer({
255
236
  optionsVisible: false,
256
237
  __demoMode
257
238
  });
258
- const optionsPropsRef = useRef({ static: false, hold: false });
259
- const buttonRef = useRef(null);
260
- const optionsRef = useRef(null);
261
- const listRef = useRef(/* @__PURE__ */ new Map());
239
+ const optionsProps = $state({ static: false, hold: false });
240
+ let buttonElement = $state(null);
241
+ let optionsElement = $state(null);
242
+ const listElements = new SvelteMap();
262
243
  const compare = useByComparator(by);
263
244
  const isSelected = (compareValue) => match(data.mode, {
264
245
  [ValueMode.Multi]: () => {
@@ -304,34 +285,39 @@ const data = {
304
285
  },
305
286
  compare,
306
287
  isSelected,
307
- get optionsPropsRef() {
308
- return optionsPropsRef;
288
+ get optionsProps() {
289
+ return optionsProps;
290
+ },
291
+ get buttonElement() {
292
+ return buttonElement;
293
+ },
294
+ set buttonElement(value2) {
295
+ buttonElement = value2;
309
296
  },
310
- get buttonRef() {
311
- return buttonRef;
297
+ get optionsElement() {
298
+ return optionsElement;
312
299
  },
313
- get optionsRef() {
314
- return optionsRef;
300
+ set optionsElement(value2) {
301
+ optionsElement = value2;
315
302
  },
316
- get listRef() {
317
- return listRef;
303
+ get listElements() {
304
+ return listElements;
318
305
  }
319
306
  };
320
307
  setContext("ListboxDataContext", data);
321
- setContext("ListboxData", data);
322
308
  const outsideClickEnabled = $derived(data.listboxState === ListboxStates.Open);
323
309
  useOutsideClick({
324
310
  get enabled() {
325
311
  return outsideClickEnabled;
326
312
  },
327
313
  get containers() {
328
- return [data.buttonRef, data.optionsRef];
314
+ return [data.buttonElement, data.optionsElement];
329
315
  },
330
316
  cb: (event, target) => {
331
317
  _state.closeListbox();
332
318
  if (!isFocusableElement(target, FocusableMode.Loose)) {
333
319
  event.preventDefault();
334
- data.buttonRef.current?.focus();
320
+ data.buttonElement?.focus();
335
321
  }
336
322
  }
337
323
  });
@@ -363,8 +349,8 @@ const goToOption = (focus, id, trigger) => {
363
349
  });
364
350
  };
365
351
  const registerOption = (id, dataRef) => {
366
- _state.registerOption({ id, dataRef });
367
- return () => _state.unregisterOption({ id });
352
+ _state.registerOption(id, dataRef);
353
+ return () => _state.unregisterOption(id);
368
354
  };
369
355
  const onChange = (value2) => {
370
356
  return match(data.mode, {
@@ -394,7 +380,7 @@ setContext("ListboxActionsContext", {
394
380
  search: _state.search,
395
381
  clearSearch: _state.clearSearch
396
382
  });
397
- createFloatingContext();
383
+ useFloatingProvider();
398
384
  const openClosed = $derived(
399
385
  match(data.listboxState, {
400
386
  [ListboxStates.Open]: State.Open,
@@ -410,7 +396,7 @@ useLabels({
410
396
  inherit: true,
411
397
  props: {
412
398
  get htmlFor() {
413
- return data.buttonRef.current?.id;
399
+ return data.buttonElement?.id;
414
400
  }
415
401
  },
416
402
  slot: {
@@ -1,9 +1,6 @@
1
1
  import { type ByComparator } from "../hooks/use-by-comparator.js";
2
- import { Focus } from "../utils/calculate-active-index.js";
3
- import { type MutableRefObject } from "../utils/ref.svelte.js";
4
2
  import type { ElementType, Props } from "../utils/types.js";
5
3
  import { type Snippet } from "svelte";
6
- import { ActivationTrigger, ListboxStates, ValueMode } from "./ListboxStates.js";
7
4
  declare let DEFAULT_LISTBOX_TAG: string;
8
5
  type ListboxRenderPropArg<T> = {
9
6
  open: boolean;
@@ -25,59 +22,11 @@ export type ListboxProps<TTag extends ElementType = typeof DEFAULT_LISTBOX_TAG,
25
22
  __demoMode?: boolean;
26
23
  }>;
27
24
  export type ListboxChildren<T> = Snippet<[ListboxRenderPropArg<T>]>;
28
- export * from "./ListboxStates.js";
29
- export type ListboxOptionDataRef<T> = MutableRefObject<{
30
- textValue?: string;
31
- disabled: boolean;
32
- value: T;
33
- domRef: MutableRefObject<HTMLElement | null>;
34
- }>;
35
- interface StateDefinition<T> {
36
- listboxState: ListboxStates;
37
- options: {
38
- id: string;
39
- dataRef: ListboxOptionDataRef<T>;
40
- }[];
41
- searchQuery: string;
42
- activeOptionIndex: number | null;
43
- activationTrigger: ActivationTrigger;
44
- __demoMode: boolean;
45
- }
46
- type ListboxActionsContext = {
47
- openListbox(): void;
48
- closeListbox(): void;
49
- registerOption(id: string, dataRef: ListboxOptionDataRef<unknown>): () => void;
50
- goToOption(focus: Focus.Specific, id: string, trigger?: ActivationTrigger): void;
51
- goToOption(focus: Focus, id?: string, trigger?: ActivationTrigger): void;
52
- selectOption(id: string): void;
53
- selectActiveOption(): void;
54
- onChange(value: unknown): void;
55
- search(query: string): void;
56
- clearSearch(): void;
57
- };
58
- export declare function useActions(component: string): ListboxActionsContext;
59
- export type ListboxDataContext = {
60
- value: unknown;
61
- disabled: boolean;
62
- invalid: boolean;
63
- mode: ValueMode;
64
- orientation: "horizontal" | "vertical";
65
- activeOptionIndex: number | null;
66
- compare(a: unknown, z: unknown): boolean;
67
- isSelected(value: unknown): boolean;
68
- optionsPropsRef: MutableRefObject<{
69
- static: boolean;
70
- hold: boolean;
71
- }>;
72
- listRef: MutableRefObject<Map<string, HTMLElement | null>>;
73
- buttonRef: MutableRefObject<HTMLElement | null>;
74
- optionsRef: MutableRefObject<HTMLElement | null>;
75
- } & Omit<StateDefinition<unknown>, "dataRef">;
76
- export declare function useData(component: string): ListboxDataContext;
25
+ export * from "./context.svelte.js";
77
26
  declare class __sveltets_Render<TType, TActualType, TTag extends ElementType = typeof DEFAULT_LISTBOX_TAG> {
78
27
  props(): {
79
28
  as?: TTag | undefined;
80
- } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, "form" | ("as" | "children" | "refName" | "class") | "invalid" | "disabled" | "name" | "value" | "onchange" | "multiple" | "__demoMode" | "defaultValue" | "by" | "horizontal"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
29
+ } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, "form" | ("as" | "children" | "refName" | "class") | "invalid" | "disabled" | "name" | "value" | "onchange" | "multiple" | "__demoMode" | "horizontal" | "defaultValue" | "by"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
81
30
  children?: import("../utils/types.js").Children<ListboxRenderPropArg<TType>> | undefined;
82
31
  ref?: HTMLElement;
83
32
  } & (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) ? {
@@ -99,7 +48,7 @@ declare class __sveltets_Render<TType, TActualType, TTag extends ElementType = t
99
48
  [evt: string]: CustomEvent<any>;
100
49
  };
101
50
  slots(): {};
102
- bindings(): "ref";
51
+ bindings(): "ref" | "value";
103
52
  exports(): {};
104
53
  }
105
54
  interface $$IsomorphicComponent {
@@ -6,7 +6,7 @@ import { Focus } from "../utils/calculate-active-index.js";
6
6
  import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
7
7
  import { useActivePress } from "../hooks/use-active-press.svelte.js";
8
8
  import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js";
9
- import { useFloating } from "../internal/floating.svelte.js";
9
+ import { useFloatingReference, useFloatingReferenceProps } from "../internal/floating.svelte.js";
10
10
  import { stateFromSlot } from "../utils/state.js";
11
11
  import { useLabelledBy } from "../label/context.svelte.js";
12
12
  import { useDescribedBy } from "../description/context.svelte.js";
@@ -27,9 +27,10 @@ let {
27
27
  autofocus = false,
28
28
  ...theirProps
29
29
  } = $props();
30
- const { setReference, getReferenceProps: getFloatingReferenceProps } = useFloating();
30
+ const { setReference } = useFloatingReference();
31
+ const { getReferenceProps: getFloatingReferenceProps } = useFloatingReferenceProps();
31
32
  $effect(() => {
32
- data.buttonRef.current = ref || null;
33
+ data.buttonElement = ref || null;
33
34
  setReference(ref);
34
35
  });
35
36
  const disabled = $derived(data.disabled || ownDisabled);
@@ -61,7 +62,7 @@ const handleKeyUp = (event) => {
61
62
  const handleClick = (event) => {
62
63
  if (data.listboxState === ListboxStates.Open) {
63
64
  actions.closeListbox();
64
- data.buttonRef.current?.focus({ preventScroll: true });
65
+ data.buttonElement?.focus({ preventScroll: true });
65
66
  } else {
66
67
  event.preventDefault();
67
68
  actions.openListbox();
@@ -106,7 +107,7 @@ const buttonType = useResolveButtonType({
106
107
  return { type: theirProps.type, as: theirProps.as };
107
108
  },
108
109
  get ref() {
109
- return data.buttonRef;
110
+ return { current: data.buttonElement };
110
111
  }
111
112
  });
112
113
  const ourProps = $derived(
@@ -116,7 +117,7 @@ const ourProps = $derived(
116
117
  id,
117
118
  type: buttonType.type,
118
119
  "aria-haspopup": "listbox",
119
- "aria-controls": data.optionsRef.current?.id,
120
+ "aria-controls": data.optionsElement?.id,
120
121
  "aria-expanded": data.listboxState === ListboxStates.Open,
121
122
  "aria-labelledby": labelledBy.value,
122
123
  "aria-describedby": describedBy.value,
@@ -43,11 +43,15 @@ const bag = $derived({
43
43
  }
44
44
  });
45
45
  $effect(() => {
46
+ if (usedInSelectedOption) return;
46
47
  if (!ref) {
47
- data.listRef.current.delete(id);
48
+ data.listElements.delete(id);
48
49
  } else {
49
- data.listRef.current.set(id, ref);
50
+ data.listElements.set(id, ref);
50
51
  }
52
+ return () => {
53
+ if (ref) data.listElements.delete(id);
54
+ };
51
55
  });
52
56
  $effect(() => {
53
57
  if (data.__demoMode) return;
@@ -72,7 +76,7 @@ const handleClick = (event) => {
72
76
  actions.onChange(value);
73
77
  if (data.mode === ValueMode.Single) {
74
78
  actions.closeListbox();
75
- data.buttonRef.current?.focus({ preventScroll: true });
79
+ data.buttonElement?.focus({ preventScroll: true });
76
80
  }
77
81
  };
78
82
  const handleFocus = () => {