@pzerelles/headlessui-svelte 2.1.2-next.7 → 2.1.2-next.8

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 (55) hide show
  1. package/dist/button/Button.svelte +54 -84
  2. package/dist/checkbox/Checkbox.svelte +120 -174
  3. package/dist/close-button/CloseButton.svelte +6 -12
  4. package/dist/combobox/Combobox.svelte +3 -50
  5. package/dist/data-interactive/DataInteractive.svelte +29 -57
  6. package/dist/description/Description.svelte +21 -32
  7. package/dist/dialog/Dialog.svelte +34 -69
  8. package/dist/dialog/DialogBackdrop.svelte +12 -29
  9. package/dist/dialog/DialogPanel.svelte +26 -49
  10. package/dist/dialog/DialogTitle.svelte +23 -38
  11. package/dist/dialog/InternalDialog.svelte +202 -263
  12. package/dist/field/Field.svelte +26 -49
  13. package/dist/fieldset/Fieldset.svelte +29 -50
  14. package/dist/focus-trap/FocusTrap.svelte +283 -419
  15. package/dist/input/Input.svelte +53 -84
  16. package/dist/internal/FocusSentinel.svelte +8 -16
  17. package/dist/internal/ForcePortalRoot.svelte +3 -7
  18. package/dist/internal/FormFields.svelte +20 -31
  19. package/dist/internal/FormResolver.svelte +15 -20
  20. package/dist/internal/Hidden.svelte +23 -44
  21. package/dist/internal/HoistFormFields.svelte +4 -7
  22. package/dist/internal/MainTreeProvider.svelte +36 -89
  23. package/dist/internal/Portal.svelte +14 -18
  24. package/dist/label/Label.svelte +57 -91
  25. package/dist/legend/Legend.svelte +3 -18
  26. package/dist/listbox/Listbox.svelte +396 -588
  27. package/dist/listbox/ListboxButton.svelte +127 -176
  28. package/dist/listbox/ListboxOption.svelte +125 -166
  29. package/dist/listbox/ListboxOptions.svelte +244 -340
  30. package/dist/listbox/ListboxSelectedOption.svelte +15 -38
  31. package/dist/menu/Menu.svelte +218 -307
  32. package/dist/menu/MenuButton.svelte +115 -157
  33. package/dist/menu/MenuHeading.svelte +14 -34
  34. package/dist/menu/MenuItem.svelte +107 -145
  35. package/dist/menu/MenuItems.svelte +224 -298
  36. package/dist/menu/MenuSection.svelte +9 -26
  37. package/dist/menu/MenuSeparator.svelte +4 -20
  38. package/dist/portal/InternalPortal.svelte +85 -141
  39. package/dist/portal/Portal.svelte +2 -5
  40. package/dist/portal/PortalGroup.svelte +9 -30
  41. package/dist/switch/Switch.svelte +132 -179
  42. package/dist/switch/SwitchGroup.svelte +31 -44
  43. package/dist/tabs/Tab.svelte +143 -195
  44. package/dist/tabs/TabGroup.svelte +205 -292
  45. package/dist/tabs/TabList.svelte +11 -31
  46. package/dist/tabs/TabPanel.svelte +43 -68
  47. package/dist/tabs/TabPanels.svelte +7 -18
  48. package/dist/textarea/Textarea.svelte +53 -84
  49. package/dist/transition/InternalTransitionChild.svelte +170 -259
  50. package/dist/transition/Transition.svelte +66 -96
  51. package/dist/transition/TransitionChild.svelte +11 -31
  52. package/dist/utils/ElementOrComponent.svelte +23 -44
  53. package/dist/utils/Generic.svelte +17 -29
  54. package/dist/utils/StableCollection.svelte +36 -54
  55. package/package.json +1 -1
@@ -1,324 +1,235 @@
1
- <script lang="ts" module>
2
- import { useOutsideClick } from "../hooks/use-outside-click.svelte.js"
3
- import { createFloatingContext } from "../internal/floating.svelte.js"
4
- import { createOpenClosedContext, State } from "../internal/open-closed.js"
5
- import { calculateActiveIndex, Focus } from "../utils/calculate-active-index.js"
6
- import ElementOrComponent from "../utils/ElementOrComponent.svelte"
7
- import { FocusableMode, isFocusableElement, sortByDomNode } from "../utils/focus-management.js"
8
- import { match } from "../utils/match.js"
9
- import type { ElementType, Props } from "../utils/types.js"
10
- import type { Snippet } from "svelte"
11
-
12
- let DEFAULT_MENU_TAG = "svelte:fragment"
13
- type MenuRenderPropArg = {
14
- open: boolean
15
- close: () => void
16
- }
17
- type MenuPropsWeControl = never
18
-
19
- export type MenuProps<TTag extends ElementType = typeof DEFAULT_MENU_TAG> = Props<
20
- TTag,
21
- MenuRenderPropArg,
22
- MenuPropsWeControl,
23
- {
24
- __demoMode?: boolean
25
- }
26
- >
27
-
28
- export type MenuChildren<T> = Snippet<[MenuRenderPropArg]>
1
+ <script lang="ts" module>import { useOutsideClick } from "../hooks/use-outside-click.svelte.js";
2
+ import { createFloatingContext } from "../internal/floating.svelte.js";
3
+ import { createOpenClosedContext, State } from "../internal/open-closed.js";
4
+ import { calculateActiveIndex, Focus } from "../utils/calculate-active-index.js";
5
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
6
+ import { FocusableMode, isFocusableElement, sortByDomNode } from "../utils/focus-management.js";
7
+ import { match } from "../utils/match.js";
8
+ let DEFAULT_MENU_TAG = "svelte:fragment";
29
9
  </script>
30
10
 
31
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_MENU_TAG">
32
- import { setContext } from "svelte"
33
- import {
34
- ActivationTrigger,
35
- MenuStates,
36
- type MenuContext,
37
- type MenuItemDataRef,
38
- type StateDefinition,
39
- } from "./context.svelte.js"
40
-
41
- function adjustOrderedState(
42
- state: StateDefinition,
43
- adjustment: (items: StateDefinition["items"]) => StateDefinition["items"] = (i) => i
44
- ) {
45
- let currentActiveItem = state.activeItemIndex !== null ? state.items[state.activeItemIndex] : null
46
-
47
- let sortedItems = sortByDomNode(adjustment(state.items.slice()), (item) => item.dataRef.current.domRef.current)
48
-
49
- // If we inserted an item before the current active item then the active item index
50
- // would be wrong. To fix this, we will re-lookup the correct index.
51
- let adjustedActiveItemIndex = currentActiveItem ? sortedItems.indexOf(currentActiveItem) : null
52
-
53
- // Reset to `null` in case the currentActiveItem was removed.
54
- if (adjustedActiveItemIndex === -1) {
55
- adjustedActiveItemIndex = null
56
- }
57
-
58
- return {
59
- items: sortedItems,
60
- activeItemIndex: adjustedActiveItemIndex,
61
- }
11
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_MENU_TAG">import { setContext } from "svelte";
12
+ import {
13
+ ActivationTrigger,
14
+ MenuStates
15
+ } from "./context.svelte.js";
16
+ function adjustOrderedState(state, adjustment = (i) => i) {
17
+ let currentActiveItem = state.activeItemIndex !== null ? state.items[state.activeItemIndex] : null;
18
+ let sortedItems = sortByDomNode(adjustment(state.items.slice()), (item) => item.dataRef.current.domRef.current);
19
+ let adjustedActiveItemIndex = currentActiveItem ? sortedItems.indexOf(currentActiveItem) : null;
20
+ if (adjustedActiveItemIndex === -1) {
21
+ adjustedActiveItemIndex = null;
62
22
  }
63
-
64
- const stateReducer = (initialState: StateDefinition) => {
65
- let _state = $state(initialState)
66
- return {
67
- get menuState() {
68
- return _state.menuState
69
- },
70
- get buttonElement() {
71
- return _state.buttonElement
72
- },
73
- get itemsElement() {
74
- return _state.itemsElement
75
- },
76
- get items() {
77
- return _state.items
78
- },
79
- get searchQuery() {
80
- return _state.searchQuery
81
- },
82
- get activeItemIndex() {
83
- return _state.activeItemIndex
84
- },
85
- get activationTrigger() {
86
- return _state.activationTrigger
87
- },
88
- get __demoMode() {
89
- return _state.__demoMode
90
- },
91
- closeMenu() {
92
- if (_state.menuState === MenuStates.Closed) return _state
93
- _state.activeItemIndex = null
94
- _state.menuState = MenuStates.Closed
95
- return _state
96
- },
97
- openMenu() {
98
- if (_state.menuState === MenuStates.Open) return _state
99
- /* We can turn off demo mode once we re-open the `Menu` */
100
- _state.__demoMode = false
101
- _state.menuState = MenuStates.Open
102
- return _state
103
- },
104
- goToItem(
105
- action:
106
- | { focus: Focus.Specific; id: string; trigger?: ActivationTrigger }
107
- | { focus: Exclude<Focus, Focus.Specific>; trigger?: ActivationTrigger }
108
- ) {
109
- if (_state.menuState === MenuStates.Closed) return _state
110
-
111
- _state.searchQuery = ""
112
- _state.activationTrigger = action.trigger ?? ActivationTrigger.Other
113
- _state.__demoMode = false
114
-
115
- // Optimization:
116
- //
117
- // There is no need to sort the DOM nodes if we know that we don't want to focus anything
118
- if (action.focus === Focus.Nothing) {
119
- _state.activeItemIndex = null
120
- return _state
121
- }
122
-
123
- // Optimization:
124
- //
125
- // There is no need to sort the DOM nodes if we know exactly where to go
126
- if (action.focus === Focus.Specific) {
127
- _state.activeItemIndex = _state.items.findIndex((o) => o.id === action.id)
128
- return _state
129
- }
130
-
131
- // Optimization:
132
- //
133
- // If the current DOM node and the previous DOM node are next to each other,
134
- // or if the previous DOM node is already the first DOM node, then we don't
135
- // have to sort all the DOM nodes.
136
- else if (action.focus === Focus.Previous) {
137
- let activeItemIdx = _state.activeItemIndex
138
- if (activeItemIdx !== null) {
139
- let currentDom = _state.items[activeItemIdx].dataRef.current.domRef
140
- let previousItemIndex = calculateActiveIndex(action, {
141
- resolveItems: () => _state.items,
142
- resolveActiveIndex: () => _state.activeItemIndex,
143
- resolveId: (item) => item.id,
144
- resolveDisabled: (item) => item.dataRef.current.disabled,
145
- })
146
- if (previousItemIndex !== null) {
147
- let previousDom = _state.items[previousItemIndex].dataRef.current.domRef
148
- if (
149
- // Next to each other
150
- currentDom.current?.previousElementSibling === previousDom.current ||
151
- // Or already the first element
152
- previousDom.current?.previousElementSibling === null
153
- ) {
154
- _state.activeItemIndex = previousItemIndex
155
- return _state
156
- }
23
+ return {
24
+ items: sortedItems,
25
+ activeItemIndex: adjustedActiveItemIndex
26
+ };
27
+ }
28
+ const stateReducer = (initialState) => {
29
+ let _state2 = $state(initialState);
30
+ return {
31
+ get menuState() {
32
+ return _state2.menuState;
33
+ },
34
+ get buttonElement() {
35
+ return _state2.buttonElement;
36
+ },
37
+ get itemsElement() {
38
+ return _state2.itemsElement;
39
+ },
40
+ get items() {
41
+ return _state2.items;
42
+ },
43
+ get searchQuery() {
44
+ return _state2.searchQuery;
45
+ },
46
+ get activeItemIndex() {
47
+ return _state2.activeItemIndex;
48
+ },
49
+ get activationTrigger() {
50
+ return _state2.activationTrigger;
51
+ },
52
+ get __demoMode() {
53
+ return _state2.__demoMode;
54
+ },
55
+ closeMenu() {
56
+ if (_state2.menuState === MenuStates.Closed) return _state2;
57
+ _state2.activeItemIndex = null;
58
+ _state2.menuState = MenuStates.Closed;
59
+ return _state2;
60
+ },
61
+ openMenu() {
62
+ if (_state2.menuState === MenuStates.Open) return _state2;
63
+ _state2.__demoMode = false;
64
+ _state2.menuState = MenuStates.Open;
65
+ return _state2;
66
+ },
67
+ goToItem(action) {
68
+ if (_state2.menuState === MenuStates.Closed) return _state2;
69
+ _state2.searchQuery = "";
70
+ _state2.activationTrigger = action.trigger ?? ActivationTrigger.Other;
71
+ _state2.__demoMode = false;
72
+ if (action.focus === Focus.Nothing) {
73
+ _state2.activeItemIndex = null;
74
+ return _state2;
75
+ }
76
+ if (action.focus === Focus.Specific) {
77
+ _state2.activeItemIndex = _state2.items.findIndex((o) => o.id === action.id);
78
+ return _state2;
79
+ } else if (action.focus === Focus.Previous) {
80
+ let activeItemIdx = _state2.activeItemIndex;
81
+ if (activeItemIdx !== null) {
82
+ let currentDom = _state2.items[activeItemIdx].dataRef.current.domRef;
83
+ let previousItemIndex = calculateActiveIndex(action, {
84
+ resolveItems: () => _state2.items,
85
+ resolveActiveIndex: () => _state2.activeItemIndex,
86
+ resolveId: (item) => item.id,
87
+ resolveDisabled: (item) => item.dataRef.current.disabled
88
+ });
89
+ if (previousItemIndex !== null) {
90
+ let previousDom = _state2.items[previousItemIndex].dataRef.current.domRef;
91
+ if (
92
+ // Next to each other
93
+ currentDom.current?.previousElementSibling === previousDom.current || // Or already the first element
94
+ previousDom.current?.previousElementSibling === null
95
+ ) {
96
+ _state2.activeItemIndex = previousItemIndex;
97
+ return _state2;
157
98
  }
158
99
  }
159
100
  }
160
-
161
- // Optimization:
162
- //
163
- // If the current DOM node and the next DOM node are next to each other, or
164
- // if the next DOM node is already the last DOM node, then we don't have to
165
- // sort all the DOM nodes.
166
- else if (action.focus === Focus.Next) {
167
- let activeItemIdx = _state.activeItemIndex
168
- if (activeItemIdx !== null) {
169
- let currentDom = _state.items[activeItemIdx].dataRef.current.domRef
170
- let nextItemIndex = calculateActiveIndex(action, {
171
- resolveItems: () => _state.items,
172
- resolveActiveIndex: () => _state.activeItemIndex,
173
- resolveId: (item) => item.id,
174
- resolveDisabled: (item) => item.dataRef.current.disabled,
175
- })
176
- if (nextItemIndex !== null) {
177
- let nextDom = _state.items[nextItemIndex].dataRef.current.domRef
178
- if (
179
- // Next to each other
180
- currentDom.current?.nextElementSibling === nextDom.current ||
181
- // Or already the last element
182
- nextDom.current?.nextElementSibling === null
183
- ) {
184
- _state.activeItemIndex = nextItemIndex
185
- return _state
186
- }
101
+ } else if (action.focus === Focus.Next) {
102
+ let activeItemIdx = _state2.activeItemIndex;
103
+ if (activeItemIdx !== null) {
104
+ let currentDom = _state2.items[activeItemIdx].dataRef.current.domRef;
105
+ let nextItemIndex = calculateActiveIndex(action, {
106
+ resolveItems: () => _state2.items,
107
+ resolveActiveIndex: () => _state2.activeItemIndex,
108
+ resolveId: (item) => item.id,
109
+ resolveDisabled: (item) => item.dataRef.current.disabled
110
+ });
111
+ if (nextItemIndex !== null) {
112
+ let nextDom = _state2.items[nextItemIndex].dataRef.current.domRef;
113
+ if (
114
+ // Next to each other
115
+ currentDom.current?.nextElementSibling === nextDom.current || // Or already the last element
116
+ nextDom.current?.nextElementSibling === null
117
+ ) {
118
+ _state2.activeItemIndex = nextItemIndex;
119
+ return _state2;
187
120
  }
188
121
  }
189
122
  }
190
-
191
- // Slow path:
192
- //
193
- // Ensure all the items are correctly sorted according to DOM position
194
- let adjustedState = adjustOrderedState(_state)
195
- let activeItemIndex = calculateActiveIndex(action, {
196
- resolveItems: () => adjustedState.items,
197
- resolveActiveIndex: () => adjustedState.activeItemIndex,
198
- resolveId: (item) => item.id,
199
- resolveDisabled: (item) => item.dataRef.current.disabled,
200
- })
201
-
202
- _state.items = adjustedState.items
203
- _state.activeItemIndex = activeItemIndex
204
- return _state
205
- },
206
- search(value: string) {
207
- let wasAlreadySearching = _state.searchQuery !== ""
208
- let offset = wasAlreadySearching ? 0 : 1
209
- let searchQuery = _state.searchQuery + value.toLowerCase()
210
-
211
- let reOrderedItems =
212
- _state.activeItemIndex !== null
213
- ? _state.items
214
- .slice(_state.activeItemIndex + offset)
215
- .concat(_state.items.slice(0, _state.activeItemIndex + offset))
216
- : _state.items
217
-
218
- let matchingItem = reOrderedItems.find(
219
- (item) => item.dataRef.current.textValue?.startsWith(searchQuery) && !item.dataRef.current.disabled
220
- )
221
-
222
- let matchIdx = matchingItem ? _state.items.indexOf(matchingItem) : -1
223
- if (matchIdx === -1 || matchIdx === _state.activeItemIndex) {
224
- _state.searchQuery = searchQuery
225
- return _state
226
- }
227
- _state.searchQuery = searchQuery
228
- _state.activeItemIndex = matchIdx
229
- _state.activationTrigger = ActivationTrigger.Other
230
- return _state
231
- },
232
- clearSearch() {
233
- if (_state.searchQuery === "") return _state
234
- _state.searchQuery = ""
235
- return _state
236
- },
237
- registerItem(id: string, dataRef: MenuItemDataRef) {
238
- let item = { id, dataRef }
239
- let adjustedState = adjustOrderedState(_state, (items) => [...items, item])
240
-
241
- _state.items = adjustedState.items
242
- _state.activeItemIndex = adjustedState.activeItemIndex
243
- return _state
244
- },
245
- unregisterItem(id: string) {
246
- let adjustedState = adjustOrderedState(_state, (items) => {
247
- let idx = items.findIndex((a) => a.id === id)
248
- if (idx !== -1) items.splice(idx, 1)
249
- return items
250
- })
251
-
252
- _state.items = adjustedState.items
253
- _state.activeItemIndex = adjustedState.activeItemIndex
254
- _state.activationTrigger = ActivationTrigger.Other
255
- return _state
256
- },
257
- setButtonElement(element: HTMLButtonElement | null) {
258
- if (_state.buttonElement === element) return _state
259
- _state.buttonElement = element
260
- return _state
261
- },
262
- setItemsElement(element: HTMLElement | null) {
263
- if (_state.itemsElement === element) return _state
264
- _state.itemsElement = element
265
- return _state
266
- },
267
- }
268
- }
269
-
270
- let { ref = $bindable(), __demoMode = false, ...theirProps }: { as?: TTag } & MenuProps<TTag> = $props()
271
-
272
- const _state = stateReducer({
273
- __demoMode,
274
- menuState: __demoMode ? MenuStates.Open : MenuStates.Closed,
275
- buttonElement: null,
276
- itemsElement: null,
277
- items: [],
278
- searchQuery: "",
279
- activeItemIndex: null,
280
- activationTrigger: ActivationTrigger.Other,
281
- } as StateDefinition)
282
- const { menuState, itemsElement, buttonElement } = $derived(_state)
283
- setContext<MenuContext>("MenuContext", _state)
284
-
285
- // Handle outside click
286
- const outsideClickEnabled = $derived(menuState === MenuStates.Open)
287
- useOutsideClick({
288
- get enabled() {
289
- return outsideClickEnabled
290
- },
291
- get containers() {
292
- return [buttonElement, itemsElement]
123
+ }
124
+ let adjustedState = adjustOrderedState(_state2);
125
+ let activeItemIndex = calculateActiveIndex(action, {
126
+ resolveItems: () => adjustedState.items,
127
+ resolveActiveIndex: () => adjustedState.activeItemIndex,
128
+ resolveId: (item) => item.id,
129
+ resolveDisabled: (item) => item.dataRef.current.disabled
130
+ });
131
+ _state2.items = adjustedState.items;
132
+ _state2.activeItemIndex = activeItemIndex;
133
+ return _state2;
293
134
  },
294
- cb: (event, target) => {
295
- _state.closeMenu()
296
-
297
- if (!isFocusableElement(target, FocusableMode.Loose)) {
298
- event.preventDefault()
299
- buttonElement?.focus()
135
+ search(value) {
136
+ let wasAlreadySearching = _state2.searchQuery !== "";
137
+ let offset = wasAlreadySearching ? 0 : 1;
138
+ let searchQuery = _state2.searchQuery + value.toLowerCase();
139
+ let reOrderedItems = _state2.activeItemIndex !== null ? _state2.items.slice(_state2.activeItemIndex + offset).concat(_state2.items.slice(0, _state2.activeItemIndex + offset)) : _state2.items;
140
+ let matchingItem = reOrderedItems.find(
141
+ (item) => item.dataRef.current.textValue?.startsWith(searchQuery) && !item.dataRef.current.disabled
142
+ );
143
+ let matchIdx = matchingItem ? _state2.items.indexOf(matchingItem) : -1;
144
+ if (matchIdx === -1 || matchIdx === _state2.activeItemIndex) {
145
+ _state2.searchQuery = searchQuery;
146
+ return _state2;
300
147
  }
148
+ _state2.searchQuery = searchQuery;
149
+ _state2.activeItemIndex = matchIdx;
150
+ _state2.activationTrigger = ActivationTrigger.Other;
151
+ return _state2;
301
152
  },
302
- })
303
-
304
- const slot = $derived({
305
- open: _state.menuState === MenuStates.Open,
306
- close: _state.closeMenu,
307
- } satisfies MenuRenderPropArg)
308
-
309
- createFloatingContext()
310
-
311
- const openClosed = $derived(
312
- match(menuState, {
313
- [MenuStates.Open]: State.Open,
314
- [MenuStates.Closed]: State.Closed,
315
- })
316
- )
317
- createOpenClosedContext({
318
- get value() {
319
- return openClosed
153
+ clearSearch() {
154
+ if (_state2.searchQuery === "") return _state2;
155
+ _state2.searchQuery = "";
156
+ return _state2;
320
157
  },
158
+ registerItem(id, dataRef) {
159
+ let item = { id, dataRef };
160
+ let adjustedState = adjustOrderedState(_state2, (items) => [...items, item]);
161
+ _state2.items = adjustedState.items;
162
+ _state2.activeItemIndex = adjustedState.activeItemIndex;
163
+ return _state2;
164
+ },
165
+ unregisterItem(id) {
166
+ let adjustedState = adjustOrderedState(_state2, (items) => {
167
+ let idx = items.findIndex((a) => a.id === id);
168
+ if (idx !== -1) items.splice(idx, 1);
169
+ return items;
170
+ });
171
+ _state2.items = adjustedState.items;
172
+ _state2.activeItemIndex = adjustedState.activeItemIndex;
173
+ _state2.activationTrigger = ActivationTrigger.Other;
174
+ return _state2;
175
+ },
176
+ setButtonElement(element) {
177
+ if (_state2.buttonElement === element) return _state2;
178
+ _state2.buttonElement = element;
179
+ return _state2;
180
+ },
181
+ setItemsElement(element) {
182
+ if (_state2.itemsElement === element) return _state2;
183
+ _state2.itemsElement = element;
184
+ return _state2;
185
+ }
186
+ };
187
+ };
188
+ let { ref = $bindable(), __demoMode = false, ...theirProps } = $props();
189
+ const _state = stateReducer({
190
+ __demoMode,
191
+ menuState: __demoMode ? MenuStates.Open : MenuStates.Closed,
192
+ buttonElement: null,
193
+ itemsElement: null,
194
+ items: [],
195
+ searchQuery: "",
196
+ activeItemIndex: null,
197
+ activationTrigger: ActivationTrigger.Other
198
+ });
199
+ const { menuState, itemsElement, buttonElement } = $derived(_state);
200
+ setContext("MenuContext", _state);
201
+ const outsideClickEnabled = $derived(menuState === MenuStates.Open);
202
+ useOutsideClick({
203
+ get enabled() {
204
+ return outsideClickEnabled;
205
+ },
206
+ get containers() {
207
+ return [buttonElement, itemsElement];
208
+ },
209
+ cb: (event, target) => {
210
+ _state.closeMenu();
211
+ if (!isFocusableElement(target, FocusableMode.Loose)) {
212
+ event.preventDefault();
213
+ buttonElement?.focus();
214
+ }
215
+ }
216
+ });
217
+ const slot = $derived({
218
+ open: _state.menuState === MenuStates.Open,
219
+ close: _state.closeMenu
220
+ });
221
+ createFloatingContext();
222
+ const openClosed = $derived(
223
+ match(menuState, {
224
+ [MenuStates.Open]: State.Open,
225
+ [MenuStates.Closed]: State.Closed
321
226
  })
227
+ );
228
+ createOpenClosedContext({
229
+ get value() {
230
+ return openClosed;
231
+ }
232
+ });
322
233
  </script>
323
234
 
324
235
  <ElementOrComponent {theirProps} {slot} defaultTag={DEFAULT_MENU_TAG} name="Menu" bind:ref />