@pzerelles/headlessui-svelte 2.1.2-next.3 → 2.1.2-next.31

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 (197) hide show
  1. package/dist/button/Button.svelte +1 -1
  2. package/dist/button/Button.svelte.d.ts +9 -11
  3. package/dist/checkbox/Checkbox.svelte +4 -4
  4. package/dist/checkbox/Checkbox.svelte.d.ts +10 -14
  5. package/dist/close-button/CloseButton.svelte.d.ts +16 -18
  6. package/dist/data-interactive/DataInteractive.svelte.d.ts +8 -11
  7. package/dist/description/Description.svelte +19 -14
  8. package/dist/description/Description.svelte.d.ts +9 -11
  9. package/dist/description/context.svelte.js +14 -16
  10. package/dist/dialog/Dialog.svelte +245 -17
  11. package/dist/dialog/Dialog.svelte.d.ts +12 -14
  12. package/dist/dialog/DialogBackdrop.svelte +1 -1
  13. package/dist/dialog/DialogBackdrop.svelte.d.ts +9 -11
  14. package/dist/dialog/DialogPanel.svelte +1 -2
  15. package/dist/dialog/DialogPanel.svelte.d.ts +9 -11
  16. package/dist/dialog/DialogTitle.svelte.d.ts +8 -10
  17. package/dist/dialog/context.svelte.js +1 -1
  18. package/dist/field/Field.svelte +24 -12
  19. package/dist/field/Field.svelte.d.ts +9 -11
  20. package/dist/fieldset/Fieldset.svelte +1 -1
  21. package/dist/fieldset/Fieldset.svelte.d.ts +9 -11
  22. package/dist/focus-trap/FocusTrap.svelte +7 -14
  23. package/dist/focus-trap/FocusTrap.svelte.d.ts +11 -25
  24. package/dist/focus-trap/FocusTrapFeatures.d.ts +14 -0
  25. package/dist/focus-trap/FocusTrapFeatures.js +15 -0
  26. package/dist/hooks/use-controllable.svelte.js +2 -1
  27. package/dist/hooks/use-did-element-move.svelte.js +5 -10
  28. package/dist/hooks/use-disabled.d.ts +6 -1
  29. package/dist/hooks/use-disabled.js +10 -5
  30. package/dist/hooks/use-event-listener.svelte.d.ts +1 -1
  31. package/dist/hooks/use-event-listener.svelte.js +3 -1
  32. package/dist/hooks/use-root-containers.svelte.d.ts +2 -2
  33. package/dist/hooks/use-root-containers.svelte.js +5 -5
  34. package/dist/hooks/use-tab-direction.svelte.js +1 -1
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js +4 -2
  37. package/dist/input/Input.svelte +3 -3
  38. package/dist/input/Input.svelte.d.ts +10 -14
  39. package/dist/internal/FloatingProvider.svelte +12 -0
  40. package/dist/internal/FloatingProvider.svelte.d.ts +6 -0
  41. package/dist/internal/FocusSentinel.svelte.d.ts +2 -18
  42. package/dist/internal/ForcePortalRoot.svelte.d.ts +2 -18
  43. package/dist/internal/FormFields.svelte +22 -19
  44. package/dist/internal/FormFields.svelte.d.ts +2 -18
  45. package/dist/internal/FormFieldsProvider.svelte +13 -0
  46. package/dist/internal/FormFieldsProvider.svelte.d.ts +5 -0
  47. package/dist/internal/FormResolver.svelte.d.ts +2 -18
  48. package/dist/internal/Hidden.svelte +18 -8
  49. package/dist/internal/Hidden.svelte.d.ts +11 -16
  50. package/dist/internal/HiddenFeatures.d.ts +5 -0
  51. package/dist/internal/HiddenFeatures.js +9 -0
  52. package/dist/internal/MainTreeProvider.svelte.d.ts +2 -18
  53. package/dist/internal/Portal.svelte.d.ts +2 -18
  54. package/dist/internal/floating-provider.svelte.d.ts +3 -0
  55. package/dist/internal/floating-provider.svelte.js +206 -0
  56. package/dist/internal/floating.svelte.d.ts +46 -22
  57. package/dist/internal/floating.svelte.js +90 -272
  58. package/dist/internal/form-fields.svelte.d.ts +10 -0
  59. package/dist/internal/form-fields.svelte.js +23 -0
  60. package/dist/label/Label.svelte +6 -5
  61. package/dist/label/Label.svelte.d.ts +9 -11
  62. package/dist/label/context.svelte.js +1 -1
  63. package/dist/legend/Legend.svelte +2 -2
  64. package/dist/legend/Legend.svelte.d.ts +4 -32
  65. package/dist/listbox/Listbox.svelte +47 -68
  66. package/dist/listbox/Listbox.svelte.d.ts +18 -80
  67. package/dist/listbox/ListboxButton.svelte +10 -10
  68. package/dist/listbox/ListboxButton.svelte.d.ts +10 -15
  69. package/dist/listbox/ListboxOption.svelte +10 -6
  70. package/dist/listbox/ListboxOption.svelte.d.ts +9 -12
  71. package/dist/listbox/ListboxOptions.svelte +108 -54
  72. package/dist/listbox/ListboxOptions.svelte.d.ts +9 -12
  73. package/dist/listbox/ListboxSelectedOption.svelte +2 -4
  74. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +14 -16
  75. package/dist/listbox/context.svelte.d.ts +76 -0
  76. package/dist/listbox/context.svelte.js +36 -0
  77. package/dist/listbox/index.d.ts +4 -4
  78. package/dist/listbox/index.js +1 -1
  79. package/dist/menu/Menu.svelte +13 -191
  80. package/dist/menu/Menu.svelte.d.ts +9 -13
  81. package/dist/menu/MenuButton.svelte +4 -2
  82. package/dist/menu/MenuButton.svelte.d.ts +9 -12
  83. package/dist/menu/MenuHeading.svelte.d.ts +9 -12
  84. package/dist/menu/MenuItem.svelte.d.ts +11 -16
  85. package/dist/menu/MenuItems.svelte +15 -11
  86. package/dist/menu/MenuItems.svelte.d.ts +9 -12
  87. package/dist/menu/MenuSection.svelte.d.ts +8 -11
  88. package/dist/menu/MenuSeparator.svelte.d.ts +8 -12
  89. package/dist/menu/context.svelte.d.ts +2 -1
  90. package/dist/menu/context.svelte.js +212 -2
  91. package/dist/menu/index.d.ts +7 -7
  92. package/dist/popover/Popover.svelte +161 -0
  93. package/dist/popover/Popover.svelte.d.ts +39 -0
  94. package/dist/popover/PopoverBackdrop.svelte +56 -0
  95. package/dist/popover/PopoverBackdrop.svelte.d.ts +43 -0
  96. package/dist/popover/PopoverButton.svelte +246 -0
  97. package/dist/popover/PopoverButton.svelte.d.ts +42 -0
  98. package/dist/popover/PopoverGroup.svelte +43 -0
  99. package/dist/popover/PopoverGroup.svelte.d.ts +31 -0
  100. package/dist/popover/PopoverPanel.svelte +274 -0
  101. package/dist/popover/PopoverPanel.svelte.d.ts +51 -0
  102. package/dist/popover/context.svelte.d.ts +51 -0
  103. package/dist/popover/context.svelte.js +108 -0
  104. package/dist/popover/index.d.ts +5 -0
  105. package/dist/popover/index.js +5 -0
  106. package/dist/portal/InternalPortal.svelte.d.ts +9 -11
  107. package/dist/portal/Portal.svelte.d.ts +2 -6
  108. package/dist/portal/PortalGroup.svelte.d.ts +9 -11
  109. package/dist/select/Select.svelte +74 -0
  110. package/dist/select/Select.svelte.d.ts +46 -0
  111. package/dist/select/index.d.ts +1 -0
  112. package/dist/select/index.js +1 -0
  113. package/dist/switch/Switch.svelte +30 -20
  114. package/dist/switch/Switch.svelte.d.ts +10 -12
  115. package/dist/switch/SwitchGroup.svelte.d.ts +8 -10
  116. package/dist/tabs/Tab.svelte +8 -9
  117. package/dist/tabs/Tab.svelte.d.ts +9 -11
  118. package/dist/tabs/TabGroup.svelte +27 -190
  119. package/dist/tabs/TabGroup.svelte.d.ts +9 -31
  120. package/dist/tabs/TabList.svelte +4 -4
  121. package/dist/tabs/TabList.svelte.d.ts +8 -10
  122. package/dist/tabs/TabPanel.svelte +4 -5
  123. package/dist/tabs/TabPanel.svelte.d.ts +9 -11
  124. package/dist/tabs/TabPanels.svelte +3 -3
  125. package/dist/tabs/TabPanels.svelte.d.ts +8 -10
  126. package/dist/tabs/context.svelte.d.ts +31 -0
  127. package/dist/tabs/context.svelte.js +134 -0
  128. package/dist/textarea/Textarea.svelte +4 -4
  129. package/dist/textarea/Textarea.svelte.d.ts +21 -20
  130. package/dist/transition/InternalTransitionChild.svelte.d.ts +9 -11
  131. package/dist/transition/Transition.svelte.d.ts +9 -11
  132. package/dist/transition/TransitionChild.svelte.d.ts +9 -11
  133. package/dist/transition/context.svelte.js +2 -2
  134. package/dist/utils/DisabledProvider.svelte +6 -0
  135. package/dist/utils/DisabledProvider.svelte.d.ts +6 -0
  136. package/dist/utils/ElementOrComponent.svelte +2 -2
  137. package/dist/utils/ElementOrComponent.svelte.d.ts +12 -11
  138. package/dist/utils/Generic.svelte +10 -8
  139. package/dist/utils/Generic.svelte.d.ts +12 -15
  140. package/dist/utils/StableCollection.svelte.d.ts +2 -18
  141. package/dist/utils/alternative-types.d.ts +1 -2
  142. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +17 -0
  143. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte.d.ts +7 -0
  144. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +50 -0
  145. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte.d.ts +25 -0
  146. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.d.ts +6 -0
  147. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +158 -0
  148. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.d.ts +11 -0
  149. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +53 -0
  150. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.d.ts +9 -0
  151. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.js +28 -0
  152. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.d.ts +23 -0
  153. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.js +72 -0
  154. package/dist/utils/floating-ui/svelte/index.d.ts +5 -0
  155. package/dist/utils/floating-ui/svelte/index.js +5 -0
  156. package/dist/utils/floating-ui/svelte/inner.svelte.d.ts +83 -0
  157. package/dist/utils/floating-ui/svelte/inner.svelte.js +178 -0
  158. package/dist/utils/floating-ui/svelte/types.d.ts +114 -0
  159. package/dist/utils/floating-ui/svelte/types.js +1 -0
  160. package/dist/utils/floating-ui/svelte/utils/createPubSub.d.ts +5 -0
  161. package/dist/utils/floating-ui/svelte/utils/createPubSub.js +14 -0
  162. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.d.ts +2 -0
  163. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.js +13 -0
  164. package/dist/utils/floating-ui/svelte/utils/log.d.ts +2 -0
  165. package/dist/utils/floating-ui/svelte/utils/log.js +19 -0
  166. package/dist/utils/floating-ui/svelte/utils.d.ts +19 -0
  167. package/dist/utils/floating-ui/svelte/utils.js +136 -0
  168. package/dist/utils/floating-ui/svelte-dom/arrow.d.ts +22 -0
  169. package/dist/utils/floating-ui/svelte-dom/arrow.js +29 -0
  170. package/dist/utils/floating-ui/svelte-dom/index.d.ts +2 -0
  171. package/dist/utils/floating-ui/svelte-dom/index.js +2 -0
  172. package/dist/utils/floating-ui/svelte-dom/types.d.ts +80 -0
  173. package/dist/utils/floating-ui/svelte-dom/types.js +3 -0
  174. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.d.ts +6 -0
  175. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +182 -0
  176. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.d.ts +1 -0
  177. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.js +50 -0
  178. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.d.ts +1 -0
  179. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.js +7 -0
  180. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.d.ts +1 -0
  181. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.js +5 -0
  182. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.d.ts +4 -0
  183. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.js +7 -0
  184. package/dist/utils/id.d.ts +1 -1
  185. package/dist/utils/id.js +1 -1
  186. package/dist/utils/index.d.ts +3 -0
  187. package/dist/utils/index.js +3 -0
  188. package/dist/utils/style.d.ts +2 -0
  189. package/dist/utils/style.js +6 -0
  190. package/dist/utils/types.d.ts +9 -13
  191. package/package.json +27 -26
  192. package/dist/dialog/InternalDialog.svelte +0 -233
  193. package/dist/dialog/InternalDialog.svelte.d.ts +0 -42
  194. package/dist/internal/HoistFormFields.svelte +0 -11
  195. package/dist/internal/HoistFormFields.svelte.d.ts +0 -21
  196. package/dist/internal/id.d.ts +0 -8
  197. package/dist/internal/id.js +0 -11
@@ -1,4 +1,6 @@
1
- import { getContext } from "svelte";
1
+ import { calculateActiveIndex, Focus } from "../utils/calculate-active-index.js";
2
+ import { sortByDomNode } from "../utils/focus-management.js";
3
+ import { getContext, setContext } from "svelte";
2
4
  export var MenuStates;
3
5
  (function (MenuStates) {
4
6
  MenuStates[MenuStates["Open"] = 0] = "Open";
@@ -12,10 +14,218 @@ export var ActivationTrigger;
12
14
  export function useMenuContext(component) {
13
15
  const context = getContext("MenuContext");
14
16
  if (!context) {
15
- let err = new Error(`<${component} /> is missing a parent <Menu /> component.`);
17
+ const err = new Error(`<${component} /> is missing a parent <Menu /> component.`);
16
18
  if (Error.captureStackTrace)
17
19
  Error.captureStackTrace(err, useMenuContext);
18
20
  throw err;
19
21
  }
20
22
  return context;
21
23
  }
24
+ function adjustOrderedState(state, adjustment = (i) => i) {
25
+ const currentActiveItem = state.activeItemIndex !== null ? state.items[state.activeItemIndex] : null;
26
+ const sortedItems = sortByDomNode(adjustment(state.items.slice()), (item) => item.dataRef.current.domRef.current);
27
+ // If we inserted an item before the current active item then the active item index
28
+ // would be wrong. To fix this, we will re-lookup the correct index.
29
+ let adjustedActiveItemIndex = currentActiveItem ? sortedItems.indexOf(currentActiveItem) : null;
30
+ // Reset to `null` in case the currentActiveItem was removed.
31
+ if (adjustedActiveItemIndex === -1) {
32
+ adjustedActiveItemIndex = null;
33
+ }
34
+ return {
35
+ items: sortedItems,
36
+ activeItemIndex: adjustedActiveItemIndex,
37
+ };
38
+ }
39
+ export const createMenuContext = (initialState) => {
40
+ const _state = $state(initialState);
41
+ const context = {
42
+ get menuState() {
43
+ return _state.menuState;
44
+ },
45
+ get buttonElement() {
46
+ return _state.buttonElement;
47
+ },
48
+ get itemsElement() {
49
+ return _state.itemsElement;
50
+ },
51
+ get items() {
52
+ return _state.items;
53
+ },
54
+ get searchQuery() {
55
+ return _state.searchQuery;
56
+ },
57
+ get activeItemIndex() {
58
+ return _state.activeItemIndex;
59
+ },
60
+ get activationTrigger() {
61
+ return _state.activationTrigger;
62
+ },
63
+ get __demoMode() {
64
+ return _state.__demoMode;
65
+ },
66
+ closeMenu() {
67
+ if (_state.menuState === MenuStates.Closed)
68
+ return _state;
69
+ _state.activeItemIndex = null;
70
+ _state.menuState = MenuStates.Closed;
71
+ return _state;
72
+ },
73
+ openMenu() {
74
+ if (_state.menuState === MenuStates.Open)
75
+ return _state;
76
+ /* We can turn off demo mode once we re-open the `Menu` */
77
+ _state.__demoMode = false;
78
+ _state.menuState = MenuStates.Open;
79
+ return _state;
80
+ },
81
+ goToItem(action) {
82
+ if (_state.menuState === MenuStates.Closed)
83
+ return _state;
84
+ _state.searchQuery = "";
85
+ _state.activationTrigger = action.trigger ?? ActivationTrigger.Other;
86
+ _state.__demoMode = false;
87
+ // Optimization:
88
+ //
89
+ // There is no need to sort the DOM nodes if we know that we don't want to focus anything
90
+ if (action.focus === Focus.Nothing) {
91
+ _state.activeItemIndex = null;
92
+ return _state;
93
+ }
94
+ // Optimization:
95
+ //
96
+ // There is no need to sort the DOM nodes if we know exactly where to go
97
+ if (action.focus === Focus.Specific) {
98
+ _state.activeItemIndex = _state.items.findIndex((o) => o.id === action.id);
99
+ return _state;
100
+ }
101
+ // Optimization:
102
+ //
103
+ // If the current DOM node and the previous DOM node are next to each other,
104
+ // or if the previous DOM node is already the first DOM node, then we don't
105
+ // have to sort all the DOM nodes.
106
+ else if (action.focus === Focus.Previous) {
107
+ const activeItemIdx = _state.activeItemIndex;
108
+ if (activeItemIdx !== null) {
109
+ const currentDom = _state.items[activeItemIdx].dataRef.current.domRef;
110
+ const previousItemIndex = calculateActiveIndex(action, {
111
+ resolveItems: () => _state.items,
112
+ resolveActiveIndex: () => _state.activeItemIndex,
113
+ resolveId: (item) => item.id,
114
+ resolveDisabled: (item) => item.dataRef.current.disabled,
115
+ });
116
+ if (previousItemIndex !== null) {
117
+ const previousDom = _state.items[previousItemIndex].dataRef.current.domRef;
118
+ if (
119
+ // Next to each other
120
+ currentDom.current?.previousElementSibling === previousDom.current ||
121
+ // Or already the first element
122
+ previousDom.current?.previousElementSibling === null) {
123
+ _state.activeItemIndex = previousItemIndex;
124
+ return _state;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ // Optimization:
130
+ //
131
+ // If the current DOM node and the next DOM node are next to each other, or
132
+ // if the next DOM node is already the last DOM node, then we don't have to
133
+ // sort all the DOM nodes.
134
+ else if (action.focus === Focus.Next) {
135
+ const activeItemIdx = _state.activeItemIndex;
136
+ if (activeItemIdx !== null) {
137
+ const currentDom = _state.items[activeItemIdx].dataRef.current.domRef;
138
+ const nextItemIndex = calculateActiveIndex(action, {
139
+ resolveItems: () => _state.items,
140
+ resolveActiveIndex: () => _state.activeItemIndex,
141
+ resolveId: (item) => item.id,
142
+ resolveDisabled: (item) => item.dataRef.current.disabled,
143
+ });
144
+ if (nextItemIndex !== null) {
145
+ const nextDom = _state.items[nextItemIndex].dataRef.current.domRef;
146
+ if (
147
+ // Next to each other
148
+ currentDom.current?.nextElementSibling === nextDom.current ||
149
+ // Or already the last element
150
+ nextDom.current?.nextElementSibling === null) {
151
+ _state.activeItemIndex = nextItemIndex;
152
+ return _state;
153
+ }
154
+ }
155
+ }
156
+ }
157
+ // Slow path:
158
+ //
159
+ // Ensure all the items are correctly sorted according to DOM position
160
+ const adjustedState = adjustOrderedState(_state);
161
+ const activeItemIndex = calculateActiveIndex(action, {
162
+ resolveItems: () => adjustedState.items,
163
+ resolveActiveIndex: () => adjustedState.activeItemIndex,
164
+ resolveId: (item) => item.id,
165
+ resolveDisabled: (item) => item.dataRef.current.disabled,
166
+ });
167
+ _state.items = adjustedState.items;
168
+ _state.activeItemIndex = activeItemIndex;
169
+ return _state;
170
+ },
171
+ search(value) {
172
+ const wasAlreadySearching = _state.searchQuery !== "";
173
+ const offset = wasAlreadySearching ? 0 : 1;
174
+ const searchQuery = _state.searchQuery + value.toLowerCase();
175
+ const reOrderedItems = _state.activeItemIndex !== null
176
+ ? _state.items
177
+ .slice(_state.activeItemIndex + offset)
178
+ .concat(_state.items.slice(0, _state.activeItemIndex + offset))
179
+ : _state.items;
180
+ const matchingItem = reOrderedItems.find((item) => item.dataRef.current.textValue?.startsWith(searchQuery) && !item.dataRef.current.disabled);
181
+ const matchIdx = matchingItem ? _state.items.indexOf(matchingItem) : -1;
182
+ if (matchIdx === -1 || matchIdx === _state.activeItemIndex) {
183
+ _state.searchQuery = searchQuery;
184
+ return _state;
185
+ }
186
+ _state.searchQuery = searchQuery;
187
+ _state.activeItemIndex = matchIdx;
188
+ _state.activationTrigger = ActivationTrigger.Other;
189
+ return _state;
190
+ },
191
+ clearSearch() {
192
+ if (_state.searchQuery === "")
193
+ return _state;
194
+ _state.searchQuery = "";
195
+ return _state;
196
+ },
197
+ registerItem(id, dataRef) {
198
+ const item = { id, dataRef };
199
+ const adjustedState = adjustOrderedState(_state, (items) => [...items, item]);
200
+ _state.items = adjustedState.items;
201
+ _state.activeItemIndex = adjustedState.activeItemIndex;
202
+ return _state;
203
+ },
204
+ unregisterItem(id) {
205
+ const adjustedState = adjustOrderedState(_state, (items) => {
206
+ const idx = items.findIndex((a) => a.id === id);
207
+ if (idx !== -1)
208
+ items.splice(idx, 1);
209
+ return items;
210
+ });
211
+ _state.items = adjustedState.items;
212
+ _state.activeItemIndex = adjustedState.activeItemIndex;
213
+ _state.activationTrigger = ActivationTrigger.Other;
214
+ return _state;
215
+ },
216
+ setButtonElement(element) {
217
+ if (_state.buttonElement === element)
218
+ return _state;
219
+ _state.buttonElement = element;
220
+ return _state;
221
+ },
222
+ setItemsElement(element) {
223
+ if (_state.itemsElement === element)
224
+ return _state;
225
+ _state.itemsElement = element;
226
+ return _state;
227
+ },
228
+ };
229
+ setContext("MenuContext", context);
230
+ return context;
231
+ };
@@ -1,7 +1,7 @@
1
- export { default as Menu, type MenuProps, type MenuChildren } from "./Menu.svelte";
2
- export { default as MenuButton, type MenuButtonProps, type MenuButtonChildren } from "./MenuButton.svelte";
3
- export { default as MenuHeading, type MenuHeadingProps, type MenuHeadingChildren } from "./MenuHeading.svelte";
4
- export { default as MenuItem, type MenuItemProps, type MenuItemChildren } from "./MenuItem.svelte";
5
- export { default as MenuItems, type MenuItemsProps, type MenuItemsChildren } from "./MenuItems.svelte";
6
- export { default as MenuSection, type MenuSectionProps, type MenuSectionChildren } from "./MenuSection.svelte";
7
- export { default as MenuSeparator, type MenuSeparatorProps, type MenuSeparatorChildren } from "./MenuSeparator.svelte";
1
+ export { default as Menu, type MenuProps } from "./Menu.svelte";
2
+ export { default as MenuButton, type MenuButtonProps } from "./MenuButton.svelte";
3
+ export { default as MenuHeading, type MenuHeadingProps } from "./MenuHeading.svelte";
4
+ export { default as MenuItem, type MenuItemProps } from "./MenuItem.svelte";
5
+ export { default as MenuItems, type MenuItemsProps } from "./MenuItems.svelte";
6
+ export { default as MenuSection, type MenuSectionProps } from "./MenuSection.svelte";
7
+ export { default as MenuSeparator, type MenuSeparatorProps } from "./MenuSeparator.svelte";
@@ -0,0 +1,161 @@
1
+ <script lang="ts" module>export const DEFAULT_POPOVER_TAG = "div";
2
+ </script>
3
+
4
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_POPOVER_TAG">import { getOwnerDocument } from "../utils/owner.js";
5
+ import { setContext, untrack } from "svelte";
6
+ import {
7
+ createPopoverContext,
8
+ PopoverStates,
9
+ usePopoverGroupContext
10
+ } from "./context.svelte.js";
11
+ import { FocusableMode, getFocusableElements, isFocusableElement } from "../utils/focus-management.js";
12
+ import { useNestedPortals } from "../portal/InternalPortal.svelte";
13
+ import MainTreeProvider, { useMainTreeNode } from "../internal/MainTreeProvider.svelte";
14
+ import { useRootContainers } from "../hooks/use-root-containers.svelte.js";
15
+ import { useEventListener } from "../hooks/use-event-listener.svelte.js";
16
+ import { useOutsideClick } from "../hooks/use-outside-click.svelte.js";
17
+ import { useFloatingProvider } from "../internal/floating-provider.svelte.js";
18
+ import { createCloseContext } from "../internal/close-provider.js";
19
+ import { createOpenClosedContext, State } from "../internal/open-closed.js";
20
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
21
+ let { ref = $bindable(), __demoMode = false, ...theirProps } = $props();
22
+ let buttons = $state([]);
23
+ const context = createPopoverContext({
24
+ __demoMode,
25
+ popoverState: __demoMode ? PopoverStates.Open : PopoverStates.Closed,
26
+ buttons
27
+ });
28
+ const {
29
+ popoverState,
30
+ button,
31
+ buttonId,
32
+ panel,
33
+ panelId,
34
+ beforePanelSentinel,
35
+ afterPanelSentinel,
36
+ afterButtonSentinel
37
+ } = $derived(context);
38
+ const ownerDocument = $derived(getOwnerDocument(ref ?? button));
39
+ const isPortalled = $derived.by(() => {
40
+ if (!button) return false;
41
+ if (!panel) return false;
42
+ return untrack(() => {
43
+ for (let root2 of document.querySelectorAll("body > *")) {
44
+ if (Number(root2?.contains(button)) ^ Number(root2?.contains(panel))) {
45
+ return true;
46
+ }
47
+ }
48
+ let elements = getFocusableElements();
49
+ let buttonIdx = elements.indexOf(button);
50
+ let beforeIdx = (buttonIdx + elements.length - 1) % elements.length;
51
+ let afterIdx = (buttonIdx + 1) % elements.length;
52
+ let beforeElement = elements[beforeIdx];
53
+ let afterElement = elements[afterIdx];
54
+ if (!panel.contains(beforeElement) && !panel.contains(afterElement)) {
55
+ return true;
56
+ }
57
+ return false;
58
+ });
59
+ });
60
+ const registerBag = $derived({
61
+ buttonId,
62
+ panelId,
63
+ close: () => context.closePopover()
64
+ });
65
+ const groupContext = usePopoverGroupContext();
66
+ const registerPopover = $derived(groupContext?.registerPopover);
67
+ const isFocusWithinPopoverGroup = () => {
68
+ return groupContext?.isFocusWithinPopoverGroup() ?? (ownerDocument?.activeElement && (button?.contains(ownerDocument.activeElement) || panel?.contains(ownerDocument.activeElement)));
69
+ };
70
+ $effect(() => registerPopover?.(registerBag));
71
+ const nestedPortals = useNestedPortals();
72
+ const { portals } = $derived(nestedPortals);
73
+ const mainTreeNode = useMainTreeNode({
74
+ get fallbackMainTreeNode() {
75
+ return button;
76
+ }
77
+ });
78
+ const root = useRootContainers({
79
+ get mainTreeNode() {
80
+ return mainTreeNode.node;
81
+ },
82
+ get portals() {
83
+ return portals;
84
+ },
85
+ get defaultContainers() {
86
+ return [button, panel];
87
+ }
88
+ });
89
+ useEventListener({
90
+ get element() {
91
+ return ownerDocument?.defaultView;
92
+ },
93
+ type: "focus",
94
+ listener: (event) => {
95
+ if (event.target === window) return;
96
+ if (!(event.target instanceof HTMLElement)) return;
97
+ if (popoverState !== PopoverStates.Open) return;
98
+ if (isFocusWithinPopoverGroup()) return;
99
+ if (!button) return;
100
+ if (!panel) return;
101
+ if (root.contains(event.target)) return;
102
+ if (beforePanelSentinel?.contains?.(event.target)) return;
103
+ if (afterPanelSentinel?.contains?.(event.target)) return;
104
+ if (afterButtonSentinel?.contains?.(event.target)) return;
105
+ context.closePopover();
106
+ },
107
+ options: true
108
+ });
109
+ const outsideClickEnabled = $derived(popoverState === PopoverStates.Open);
110
+ useOutsideClick({
111
+ get enabled() {
112
+ return outsideClickEnabled;
113
+ },
114
+ get containers() {
115
+ return root.resolvedContainers;
116
+ },
117
+ cb: (event, target) => {
118
+ context.closePopover();
119
+ if (!isFocusableElement(target, FocusableMode.Loose)) {
120
+ event.preventDefault();
121
+ button?.focus();
122
+ }
123
+ }
124
+ });
125
+ const close = (focusableElement) => {
126
+ context.closePopover();
127
+ const restoreElement = (() => {
128
+ if (!focusableElement) return button;
129
+ if (focusableElement instanceof HTMLElement) return focusableElement;
130
+ return button;
131
+ })();
132
+ restoreElement?.focus();
133
+ };
134
+ const api = {
135
+ close,
136
+ get isPortalled() {
137
+ return isPortalled;
138
+ }
139
+ };
140
+ setContext("PopoverAPIContext", api);
141
+ const slot = $derived({
142
+ open: popoverState === PopoverStates.Open,
143
+ close
144
+ });
145
+ useFloatingProvider();
146
+ setContext("PopoverPanelContext", void 0);
147
+ createCloseContext({
148
+ get close() {
149
+ return close;
150
+ }
151
+ });
152
+ createOpenClosedContext({
153
+ get value() {
154
+ return context.popoverState === PopoverStates.Open ? State.Open : State.Closed;
155
+ }
156
+ });
157
+ </script>
158
+
159
+ <MainTreeProvider node={mainTreeNode.node}>
160
+ <ElementOrComponent {theirProps} slots={slot} defaultTag={DEFAULT_POPOVER_TAG} name="Popover" bind:ref />
161
+ </MainTreeProvider>
@@ -0,0 +1,39 @@
1
+ import type { ElementType, Props } from "../utils/types.js";
2
+ export declare const DEFAULT_POPOVER_TAG: "div";
3
+ type PopoverRenderPropArg = {
4
+ open: boolean;
5
+ close(focusableElement?: HTMLElement | MouseEvent<HTMLElement>): void;
6
+ };
7
+ type PopoverPropsWeControl = never;
8
+ export type PopoverProps<TTag extends ElementType = typeof DEFAULT_POPOVER_TAG> = Props<TTag, PopoverRenderPropArg, PopoverPropsWeControl, {
9
+ __demoMode?: boolean;
10
+ }>;
11
+ import { type MouseEvent } from "./context.svelte.js";
12
+ declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_POPOVER_TAG> {
13
+ props(): {
14
+ as?: TTag | undefined;
15
+ } & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("slot" | "as" | "children" | "class" | "ref") | "__demoMode"> 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: PopoverRenderPropArg;
18
+ props: Record<string, any>;
19
+ }]> | undefined;
20
+ class?: string | ((bag: PopoverRenderPropArg) => string) | null | undefined;
21
+ ref?: HTMLElement;
22
+ } & {
23
+ __demoMode?: boolean;
24
+ };
25
+ events(): {};
26
+ slots(): {};
27
+ bindings(): "ref";
28
+ exports(): {};
29
+ }
30
+ interface $$IsomorphicComponent {
31
+ new <TTag extends ElementType = typeof DEFAULT_POPOVER_TAG>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
32
+ $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
33
+ } & ReturnType<__sveltets_Render<TTag>['exports']>;
34
+ <TTag extends ElementType = typeof DEFAULT_POPOVER_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {}): ReturnType<__sveltets_Render<TTag>['exports']>;
35
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
36
+ }
37
+ declare const Popover: $$IsomorphicComponent;
38
+ type Popover<TTag extends ElementType = typeof DEFAULT_POPOVER_TAG> = InstanceType<typeof Popover<TTag>>;
39
+ export default Popover;
@@ -0,0 +1,56 @@
1
+ <script lang="ts" module>import { RenderFeatures } from "../utils/render.js";
2
+ let DEFAULT_BACKDROP_TAG = "div";
3
+ const BackdropRenderFeatures = RenderFeatures.RenderStrategy | RenderFeatures.Static;
4
+ </script>
5
+
6
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG">import ElementOrComponent from "../utils/ElementOrComponent.svelte";
7
+ import { useId } from "../hooks/use-id.js";
8
+ import { PopoverStates, usePopoverContext } from "./context.svelte.js";
9
+ import { State, useOpenClosed } from "../internal/open-closed.js";
10
+ import { transitionDataAttributes, useTransition } from "../hooks/use-transition.svelte.js";
11
+ const internalId = useId();
12
+ let {
13
+ ref = $bindable(),
14
+ id = `headlessui-popover-backdrop-${internalId}`,
15
+ transition = false,
16
+ ...theirProps
17
+ } = $props();
18
+ const context = usePopoverContext("PopoverBackdrop");
19
+ const { popoverState } = $derived(context);
20
+ const usesOpenClosedState = useOpenClosed();
21
+ const _transition = useTransition({
22
+ get enabled() {
23
+ return transition;
24
+ },
25
+ get element() {
26
+ return ref;
27
+ },
28
+ get show() {
29
+ return usesOpenClosedState !== null ? (usesOpenClosedState.value & State.Open) === State.Open : popoverState === PopoverStates.Open;
30
+ }
31
+ });
32
+ const { visible, data: transitionData } = $derived(_transition);
33
+ const handleClick = (event) => {
34
+ context.closePopover();
35
+ };
36
+ const slot = $derived({
37
+ open: popoverState === PopoverStates.Open
38
+ });
39
+ const ourProps = $derived({
40
+ id,
41
+ "aria-hidden": true,
42
+ onclick: handleClick,
43
+ ...transitionDataAttributes(transitionData)
44
+ });
45
+ </script>
46
+
47
+ <ElementOrComponent
48
+ {ourProps}
49
+ {theirProps}
50
+ slots={slot}
51
+ defaultTag={DEFAULT_BACKDROP_TAG}
52
+ features={BackdropRenderFeatures}
53
+ name="PopoverBackdrop"
54
+ {visible}
55
+ bind:ref
56
+ />
@@ -0,0 +1,43 @@
1
+ import type { ElementType, Props, PropsOf } from "../utils/types.js";
2
+ import { type PropsForFeatures } from "../utils/render.js";
3
+ declare let DEFAULT_BACKDROP_TAG: "div";
4
+ type BackdropRenderPropArg = {
5
+ open: boolean;
6
+ };
7
+ type BackdropPropsWeControl = "aria-hidden";
8
+ declare const BackdropRenderFeatures: number;
9
+ export type PopoverBackdropProps<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> = Props<TTag, BackdropRenderPropArg, BackdropPropsWeControl, {
10
+ transition?: boolean;
11
+ } & PropsForFeatures<typeof BackdropRenderFeatures>>;
12
+ export type PopoverOverlayProps<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> = PopoverBackdropProps<TTag>;
13
+ declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> {
14
+ props(): {
15
+ as?: TTag | undefined;
16
+ } & (Exclude<keyof PropsOf<TTag>, ("slot" | "as" | "children" | "class" | "ref") | "unmount" | "static" | "aria-hidden" | "transition"> extends infer T extends keyof PropsOf<TTag> ? { [P in T]: PropsOf<TTag>[P]; } : never) & {
17
+ children?: import("svelte").Snippet<[{
18
+ slot: BackdropRenderPropArg;
19
+ props: Record<string, any>;
20
+ }]> | undefined;
21
+ class?: string | ((bag: BackdropRenderPropArg) => string) | null | undefined;
22
+ ref?: HTMLElement;
23
+ } & {
24
+ transition?: boolean;
25
+ } & {
26
+ static?: boolean | undefined;
27
+ unmount?: boolean | undefined;
28
+ };
29
+ events(): {};
30
+ slots(): {};
31
+ bindings(): "ref";
32
+ exports(): {};
33
+ }
34
+ interface $$IsomorphicComponent {
35
+ new <TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
36
+ $$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
37
+ } & ReturnType<__sveltets_Render<TTag>['exports']>;
38
+ <TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {}): ReturnType<__sveltets_Render<TTag>['exports']>;
39
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
40
+ }
41
+ declare const PopoverBackdrop: $$IsomorphicComponent;
42
+ type PopoverBackdrop<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG> = InstanceType<typeof PopoverBackdrop<TTag>>;
43
+ export default PopoverBackdrop;