@pzerelles/headlessui-svelte 2.1.2-next.5 → 2.1.2-next.50

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 (267) hide show
  1. package/dist/button/Button.svelte +16 -19
  2. package/dist/button/Button.svelte.d.ts +8 -36
  3. package/dist/button/index.d.ts +1 -1
  4. package/dist/button/index.js +1 -1
  5. package/dist/checkbox/Checkbox.svelte +31 -27
  6. package/dist/checkbox/Checkbox.svelte.d.ts +17 -38
  7. package/dist/checkbox/index.d.ts +1 -1
  8. package/dist/checkbox/index.js +1 -1
  9. package/dist/close-button/CloseButton.svelte +4 -7
  10. package/dist/close-button/CloseButton.svelte.d.ts +3 -46
  11. package/dist/close-button/index.d.ts +1 -0
  12. package/dist/close-button/index.js +1 -0
  13. package/dist/data-interactive/DataInteractive.svelte +6 -22
  14. package/dist/data-interactive/DataInteractive.svelte.d.ts +9 -34
  15. package/dist/data-interactive/index.d.ts +1 -1
  16. package/dist/data-interactive/index.js +1 -1
  17. package/dist/description/Description.svelte +29 -24
  18. package/dist/description/Description.svelte.d.ts +9 -30
  19. package/dist/description/context.svelte.js +14 -16
  20. package/dist/description/index.d.ts +1 -1
  21. package/dist/dialog/Dialog.svelte +315 -31
  22. package/dist/dialog/Dialog.svelte.d.ts +7 -45
  23. package/dist/dialog/DialogBackdrop.svelte +11 -14
  24. package/dist/dialog/DialogBackdrop.svelte.d.ts +8 -33
  25. package/dist/dialog/DialogPanel.svelte +23 -19
  26. package/dist/dialog/DialogPanel.svelte.d.ts +8 -34
  27. package/dist/dialog/DialogTitle.svelte +17 -8
  28. package/dist/dialog/DialogTitle.svelte.d.ts +9 -30
  29. package/dist/dialog/context.svelte.js +2 -2
  30. package/dist/dialog/index.d.ts +4 -4
  31. package/dist/dialog/index.js +4 -4
  32. package/dist/disclosure/Disclosure.svelte +61 -0
  33. package/dist/disclosure/Disclosure.svelte.d.ts +14 -0
  34. package/dist/disclosure/DisclosureButton.svelte +191 -0
  35. package/dist/disclosure/DisclosureButton.svelte.d.ts +19 -0
  36. package/dist/disclosure/DisclosurePanel.svelte +98 -0
  37. package/dist/disclosure/DisclosurePanel.svelte.d.ts +16 -0
  38. package/dist/disclosure/context.svelte.d.ts +32 -0
  39. package/dist/disclosure/context.svelte.js +94 -0
  40. package/dist/disclosure/index.d.ts +3 -0
  41. package/dist/disclosure/index.js +3 -0
  42. package/dist/field/Field.svelte +27 -26
  43. package/dist/field/Field.svelte.d.ts +7 -34
  44. package/dist/field/index.d.ts +1 -1
  45. package/dist/fieldset/Fieldset.svelte +21 -20
  46. package/dist/fieldset/Fieldset.svelte.d.ts +8 -35
  47. package/dist/fieldset/index.d.ts +1 -1
  48. package/dist/focus-trap/FocusTrap.svelte +29 -36
  49. package/dist/focus-trap/FocusTrap.svelte.d.ts +8 -38
  50. package/dist/hooks/use-controllable.svelte.js +3 -2
  51. package/dist/hooks/use-did-element-move.svelte.js +5 -10
  52. package/dist/hooks/use-disabled.d.ts +6 -1
  53. package/dist/hooks/use-disabled.js +10 -5
  54. package/dist/hooks/use-element-size.svelte.js +1 -1
  55. package/dist/hooks/use-event-listener.svelte.d.ts +1 -1
  56. package/dist/hooks/use-event-listener.svelte.js +3 -1
  57. package/dist/hooks/use-focus-ring.svelte.js +1 -1
  58. package/dist/hooks/use-inert-others.svelte.js +10 -10
  59. package/dist/hooks/use-is-top-layer.svelte.js +2 -2
  60. package/dist/hooks/use-resolve-button-type.svelte.js +0 -1
  61. package/dist/hooks/use-root-containers.svelte.d.ts +2 -2
  62. package/dist/hooks/use-root-containers.svelte.js +5 -5
  63. package/dist/hooks/use-tab-direction.svelte.js +1 -1
  64. package/dist/hooks/use-transition.svelte.js +2 -2
  65. package/dist/index.d.ts +6 -2
  66. package/dist/index.js +6 -2
  67. package/dist/input/Input.svelte +28 -21
  68. package/dist/input/Input.svelte.d.ts +16 -33
  69. package/dist/input/index.d.ts +1 -1
  70. package/dist/input/index.js +1 -1
  71. package/dist/internal/FloatingProvider.svelte +17 -0
  72. package/dist/internal/FloatingProvider.svelte.d.ts +8 -0
  73. package/dist/internal/FocusSentinel.svelte +33 -32
  74. package/dist/internal/FocusSentinel.svelte.d.ts +4 -18
  75. package/dist/internal/ForcePortalRoot.svelte.d.ts +4 -18
  76. package/dist/internal/FormFields.svelte +18 -13
  77. package/dist/internal/FormFields.svelte.d.ts +4 -18
  78. package/dist/internal/FormFieldsProvider.svelte +17 -0
  79. package/dist/internal/FormFieldsProvider.svelte.d.ts +7 -0
  80. package/dist/internal/FormResolver.svelte +6 -2
  81. package/dist/internal/FormResolver.svelte.d.ts +4 -18
  82. package/dist/internal/Hidden.svelte +10 -10
  83. package/dist/internal/Hidden.svelte.d.ts +6 -33
  84. package/dist/internal/MainTreeProvider.svelte +1 -1
  85. package/dist/internal/MainTreeProvider.svelte.d.ts +4 -18
  86. package/dist/internal/Portal.svelte.d.ts +4 -18
  87. package/dist/internal/floating-provider.svelte.d.ts +3 -0
  88. package/dist/internal/floating-provider.svelte.js +206 -0
  89. package/dist/internal/floating.svelte.d.ts +46 -22
  90. package/dist/internal/floating.svelte.js +90 -272
  91. package/dist/internal/form-fields.svelte.d.ts +10 -0
  92. package/dist/internal/form-fields.svelte.js +23 -0
  93. package/dist/internal/frozen.svelte.js +1 -1
  94. package/dist/label/Label.svelte +17 -13
  95. package/dist/label/Label.svelte.d.ts +8 -33
  96. package/dist/label/context.svelte.js +1 -1
  97. package/dist/label/index.d.ts +1 -1
  98. package/dist/legend/Legend.svelte +22 -15
  99. package/dist/legend/Legend.svelte.d.ts +10 -34
  100. package/dist/listbox/Listbox.svelte +79 -151
  101. package/dist/listbox/Listbox.svelte.d.ts +16 -91
  102. package/dist/listbox/ListboxButton.svelte +31 -29
  103. package/dist/listbox/ListboxButton.svelte.d.ts +8 -38
  104. package/dist/listbox/ListboxOption.svelte +40 -27
  105. package/dist/listbox/ListboxOption.svelte.d.ts +16 -32
  106. package/dist/listbox/ListboxOptions.svelte +126 -72
  107. package/dist/listbox/ListboxOptions.svelte.d.ts +8 -43
  108. package/dist/listbox/ListboxSelectedOption.svelte +24 -26
  109. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +14 -39
  110. package/dist/listbox/context.svelte.d.ts +76 -0
  111. package/dist/listbox/context.svelte.js +36 -0
  112. package/dist/listbox/index.d.ts +5 -5
  113. package/dist/listbox/index.js +4 -4
  114. package/dist/menu/Menu.svelte +22 -266
  115. package/dist/menu/Menu.svelte.d.ts +7 -37
  116. package/dist/menu/MenuButton.svelte +29 -24
  117. package/dist/menu/MenuButton.svelte.d.ts +8 -39
  118. package/dist/menu/MenuHeading.svelte +12 -16
  119. package/dist/menu/MenuHeading.svelte.d.ts +7 -36
  120. package/dist/menu/MenuItem.svelte +18 -23
  121. package/dist/menu/MenuItem.svelte.d.ts +9 -39
  122. package/dist/menu/MenuItems.svelte +33 -34
  123. package/dist/menu/MenuItems.svelte.d.ts +8 -43
  124. package/dist/menu/MenuSection.svelte +9 -12
  125. package/dist/menu/MenuSection.svelte.d.ts +7 -33
  126. package/dist/menu/MenuSeparator.svelte +9 -12
  127. package/dist/menu/MenuSeparator.svelte.d.ts +7 -33
  128. package/dist/menu/context.svelte.d.ts +2 -1
  129. package/dist/menu/context.svelte.js +212 -2
  130. package/dist/menu/index.d.ts +7 -7
  131. package/dist/menu/index.js +3 -3
  132. package/dist/popover/Popover.svelte +228 -0
  133. package/dist/popover/Popover.svelte.d.ts +15 -0
  134. package/dist/popover/PopoverBackdrop.svelte +83 -0
  135. package/dist/popover/PopoverBackdrop.svelte.d.ts +17 -0
  136. package/dist/popover/PopoverButton.svelte +324 -0
  137. package/dist/popover/PopoverButton.svelte.d.ts +21 -0
  138. package/dist/popover/PopoverGroup.svelte +66 -0
  139. package/dist/popover/PopoverGroup.svelte.d.ts +9 -0
  140. package/dist/popover/PopoverPanel.svelte +359 -0
  141. package/dist/popover/PopoverPanel.svelte.d.ts +22 -0
  142. package/dist/popover/context.svelte.d.ts +51 -0
  143. package/dist/popover/context.svelte.js +108 -0
  144. package/dist/popover/index.d.ts +5 -0
  145. package/dist/popover/index.js +5 -0
  146. package/dist/portal/InternalPortal.svelte +17 -17
  147. package/dist/portal/InternalPortal.svelte.d.ts +6 -33
  148. package/dist/portal/Portal.svelte +7 -6
  149. package/dist/portal/Portal.svelte.d.ts +3 -22
  150. package/dist/portal/PortalGroup.svelte +6 -14
  151. package/dist/portal/PortalGroup.svelte.d.ts +5 -34
  152. package/dist/radio-group/Radio.svelte +142 -0
  153. package/dist/radio-group/Radio.svelte.d.ts +35 -0
  154. package/dist/radio-group/RadioGroup.svelte +222 -0
  155. package/dist/radio-group/RadioGroup.svelte.d.ts +34 -0
  156. package/dist/radio-group/RadioOption.svelte +145 -0
  157. package/dist/radio-group/RadioOption.svelte.d.ts +37 -0
  158. package/dist/radio-group/contest.svelte.d.ts +30 -0
  159. package/dist/radio-group/contest.svelte.js +40 -0
  160. package/dist/radio-group/index.d.ts +3 -0
  161. package/dist/radio-group/index.js +3 -0
  162. package/dist/select/Select.svelte +112 -0
  163. package/dist/select/Select.svelte.d.ts +21 -0
  164. package/dist/select/index.d.ts +1 -0
  165. package/dist/select/index.js +1 -0
  166. package/dist/switch/Switch.svelte +27 -28
  167. package/dist/switch/Switch.svelte.d.ts +9 -42
  168. package/dist/switch/SwitchGroup.svelte +5 -5
  169. package/dist/switch/SwitchGroup.svelte.d.ts +8 -30
  170. package/dist/switch/index.d.ts +1 -1
  171. package/dist/switch/index.js +1 -1
  172. package/dist/tabs/Tab.svelte +28 -31
  173. package/dist/tabs/Tab.svelte.d.ts +8 -36
  174. package/dist/tabs/TabGroup.svelte +42 -264
  175. package/dist/tabs/TabGroup.svelte.d.ts +7 -57
  176. package/dist/tabs/TabList.svelte +13 -16
  177. package/dist/tabs/TabList.svelte.d.ts +8 -31
  178. package/dist/tabs/TabPanel.svelte +20 -20
  179. package/dist/tabs/TabPanel.svelte.d.ts +8 -38
  180. package/dist/tabs/TabPanels.svelte +11 -9
  181. package/dist/tabs/TabPanels.svelte.d.ts +8 -30
  182. package/dist/tabs/context.svelte.d.ts +31 -0
  183. package/dist/tabs/context.svelte.js +134 -0
  184. package/dist/tabs/index.d.ts +5 -5
  185. package/dist/tabs/index.js +4 -4
  186. package/dist/textarea/Textarea.svelte +24 -20
  187. package/dist/textarea/Textarea.svelte.d.ts +18 -30
  188. package/dist/textarea/index.d.ts +1 -1
  189. package/dist/textarea/index.js +1 -1
  190. package/dist/transition/InternalTransitionChild.svelte +36 -22
  191. package/dist/transition/InternalTransitionChild.svelte.d.ts +6 -37
  192. package/dist/transition/Transition.svelte +16 -17
  193. package/dist/transition/Transition.svelte.d.ts +8 -38
  194. package/dist/transition/TransitionChild.svelte +13 -12
  195. package/dist/transition/TransitionChild.svelte.d.ts +11 -38
  196. package/dist/transition/context.svelte.js +11 -11
  197. package/dist/transition/index.d.ts +2 -2
  198. package/dist/transition/index.js +2 -2
  199. package/dist/utils/DisabledProvider.svelte +10 -0
  200. package/dist/utils/DisabledProvider.svelte.d.ts +8 -0
  201. package/dist/utils/ElementOrComponent.svelte +58 -17
  202. package/dist/utils/ElementOrComponent.svelte.d.ts +19 -30
  203. package/dist/utils/StableCollection.svelte.d.ts +4 -18
  204. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +32 -0
  205. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte.d.ts +8 -0
  206. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +94 -0
  207. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte.d.ts +26 -0
  208. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.d.ts +6 -0
  209. package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +158 -0
  210. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.d.ts +11 -0
  211. package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +53 -0
  212. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.d.ts +9 -0
  213. package/dist/utils/floating-ui/svelte/hooks/useId.svelte.js +28 -0
  214. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.d.ts +23 -0
  215. package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.js +72 -0
  216. package/dist/utils/floating-ui/svelte/index.d.ts +5 -0
  217. package/dist/utils/floating-ui/svelte/index.js +5 -0
  218. package/dist/utils/floating-ui/svelte/inner.svelte.d.ts +83 -0
  219. package/dist/utils/floating-ui/svelte/inner.svelte.js +178 -0
  220. package/dist/utils/floating-ui/svelte/types.d.ts +114 -0
  221. package/dist/utils/floating-ui/svelte/utils/createPubSub.d.ts +5 -0
  222. package/dist/utils/floating-ui/svelte/utils/createPubSub.js +14 -0
  223. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.d.ts +2 -0
  224. package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.js +13 -0
  225. package/dist/utils/floating-ui/svelte/utils/log.d.ts +2 -0
  226. package/dist/utils/floating-ui/svelte/utils/log.js +19 -0
  227. package/dist/utils/floating-ui/svelte/utils.d.ts +19 -0
  228. package/dist/utils/floating-ui/svelte/utils.js +136 -0
  229. package/dist/utils/floating-ui/svelte-dom/arrow.d.ts +22 -0
  230. package/dist/utils/floating-ui/svelte-dom/arrow.js +29 -0
  231. package/dist/utils/floating-ui/svelte-dom/index.d.ts +2 -0
  232. package/dist/utils/floating-ui/svelte-dom/index.js +2 -0
  233. package/dist/utils/floating-ui/svelte-dom/types.d.ts +80 -0
  234. package/dist/utils/floating-ui/svelte-dom/types.js +3 -0
  235. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.d.ts +6 -0
  236. package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +183 -0
  237. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.d.ts +1 -0
  238. package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.js +50 -0
  239. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.d.ts +1 -0
  240. package/dist/utils/floating-ui/svelte-dom/utils/getDPR.js +7 -0
  241. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.d.ts +1 -0
  242. package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.js +5 -0
  243. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.d.ts +4 -0
  244. package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.js +7 -0
  245. package/dist/utils/id.d.ts +1 -1
  246. package/dist/utils/id.js +1 -1
  247. package/dist/utils/index.d.ts +3 -0
  248. package/dist/utils/index.js +3 -0
  249. package/dist/utils/state.js +4 -4
  250. package/dist/utils/style.d.ts +2 -0
  251. package/dist/utils/style.js +6 -0
  252. package/dist/utils/types.d.ts +13 -19
  253. package/package.json +54 -53
  254. package/dist/combobox/Combobox.svelte +0 -53
  255. package/dist/combobox/Combobox.svelte.d.ts +0 -50
  256. package/dist/dialog/InternalDialog.svelte +0 -294
  257. package/dist/dialog/InternalDialog.svelte.d.ts +0 -42
  258. package/dist/internal/HoistFormFields.svelte +0 -14
  259. package/dist/internal/HoistFormFields.svelte.d.ts +0 -21
  260. package/dist/internal/id.d.ts +0 -8
  261. package/dist/internal/id.js +0 -11
  262. package/dist/listbox/ListboxStates.d.ts +0 -12
  263. package/dist/listbox/ListboxStates.js +0 -15
  264. package/dist/utils/Generic.svelte +0 -56
  265. package/dist/utils/Generic.svelte.d.ts +0 -35
  266. package/dist/utils/alternative-types.d.ts +0 -21
  267. /package/dist/utils/{alternative-types.js → floating-ui/svelte/types.js} +0 -0
@@ -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, type MenuRenderPropArg as MenuSlot, type MenuOwnProps } from "./Menu.svelte";
2
+ export { default as MenuButton, type MenuButtonProps, type ButtonRenderPropArg as MenuButtonSlot, type MenuButtonOwnProps, } from "./MenuButton.svelte";
3
+ export { default as MenuHeading, type MenuHeadingProps, type MenuHeadingOwnProps } from "./MenuHeading.svelte";
4
+ export { default as MenuItem, type MenuItemProps, type ItemRenderPropArg as MenuItemSlot, type MenuItemOwnProps, } from "./MenuItem.svelte";
5
+ export { default as MenuItems, type MenuItemsProps, type ItemsRenderPropArg as MenuItemsSlot, type MenuItemsOwnProps, } from "./MenuItems.svelte";
6
+ export { default as MenuSection, type MenuSectionProps, type MenuSectionOwnProps } from "./MenuSection.svelte";
7
+ export { default as MenuSeparator, type MenuSeparatorProps, type MenuSeparatorOwnProps } from "./MenuSeparator.svelte";
@@ -1,7 +1,7 @@
1
1
  export { default as Menu } from "./Menu.svelte";
2
- export { default as MenuButton } from "./MenuButton.svelte";
2
+ export { default as MenuButton, } from "./MenuButton.svelte";
3
3
  export { default as MenuHeading } from "./MenuHeading.svelte";
4
- export { default as MenuItem } from "./MenuItem.svelte";
5
- export { default as MenuItems } from "./MenuItems.svelte";
4
+ export { default as MenuItem, } from "./MenuItem.svelte";
5
+ export { default as MenuItems, } from "./MenuItems.svelte";
6
6
  export { default as MenuSection } from "./MenuSection.svelte";
7
7
  export { default as MenuSeparator } from "./MenuSeparator.svelte";
@@ -0,0 +1,228 @@
1
+ <script lang="ts" module>
2
+ import type { Props } from "../utils/types.js"
3
+
4
+ export const DEFAULT_POPOVER_TAG = "div" as const
5
+ export type PopoverRenderPropArg = {
6
+ open: boolean
7
+ close(focusableElement?: HTMLElement | MouseEvent<HTMLElement>): void
8
+ }
9
+ type PopoverPropsWeControl = never
10
+
11
+ export type PopoverOwnProps = {
12
+ element?: HTMLElement
13
+ __demoMode?: boolean
14
+ }
15
+
16
+ export type PopoverProps = Props<typeof DEFAULT_POPOVER_TAG, PopoverRenderPropArg, PopoverOwnProps>
17
+ </script>
18
+
19
+ <script lang="ts">
20
+ import { getOwnerDocument } from "../utils/owner.js"
21
+
22
+ import { setContext, untrack } from "svelte"
23
+ import {
24
+ createPopoverContext,
25
+ PopoverStates,
26
+ usePopoverGroupContext,
27
+ type MouseEvent,
28
+ type PopoverAPIContext,
29
+ type PopoverPanelContext,
30
+ } from "./context.svelte.js"
31
+ import { FocusableMode, getFocusableElements, isFocusableElement } from "../utils/focus-management.js"
32
+ import { useNestedPortals } from "../portal/InternalPortal.svelte"
33
+ import MainTreeProvider, { useMainTreeNode } from "../internal/MainTreeProvider.svelte"
34
+ import { useRootContainers } from "../hooks/use-root-containers.svelte.js"
35
+ import { useEventListener } from "../hooks/use-event-listener.svelte.js"
36
+ import { useOutsideClick } from "../hooks/use-outside-click.svelte.js"
37
+ import { useFloatingProvider } from "../internal/floating-provider.svelte.js"
38
+ import { createCloseContext } from "../internal/close-provider.js"
39
+ import { createOpenClosedContext, State } from "../internal/open-closed.js"
40
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte"
41
+
42
+ let { element = $bindable(), __demoMode = false, ...theirProps }: PopoverProps = $props()
43
+
44
+ let buttons = $state([])
45
+ const context = createPopoverContext({
46
+ __demoMode,
47
+ popoverState: __demoMode ? PopoverStates.Open : PopoverStates.Closed,
48
+ buttons,
49
+ })
50
+ const {
51
+ popoverState,
52
+ button,
53
+ buttonId,
54
+ panel,
55
+ panelId,
56
+ beforePanelSentinel,
57
+ afterPanelSentinel,
58
+ afterButtonSentinel,
59
+ } = $derived(context)
60
+
61
+ const ownerDocument = $derived(getOwnerDocument(element ?? button))
62
+
63
+ const isPortalled = $derived.by(() => {
64
+ if (!button) return false
65
+ if (!panel) return false
66
+
67
+ return untrack(() => {
68
+ // We are part of a different "root" tree, so therefore we can consider it portalled. This is a
69
+ // heuristic because 3rd party tools could use some form of portal, typically rendered at the
70
+ // end of the body but we don't have an actual reference to that.
71
+ for (let root of document.querySelectorAll("body > *")) {
72
+ if (Number(root?.contains(button)) ^ Number(root?.contains(panel))) {
73
+ return true
74
+ }
75
+ }
76
+
77
+ // Use another heuristic to try and calculate whether or not the focusable
78
+ // elements are near each other (aka, following the default focus/tab order
79
+ // from the browser). If they are then it doesn't really matter if they are
80
+ // portalled or not because we can follow the default tab order. But if they
81
+ // are not, then we can consider it being portalled so that we can ensure
82
+ // that tab and shift+tab (hopefully) go to the correct spot.
83
+ let elements = getFocusableElements()
84
+ let buttonIdx = elements.indexOf(button)
85
+
86
+ let beforeIdx = (buttonIdx + elements.length - 1) % elements.length
87
+ let afterIdx = (buttonIdx + 1) % elements.length
88
+
89
+ let beforeElement = elements[beforeIdx]
90
+ let afterElement = elements[afterIdx]
91
+
92
+ if (!panel.contains(beforeElement) && !panel.contains(afterElement)) {
93
+ return true
94
+ }
95
+
96
+ // It may or may not be portalled, but we don't really know.
97
+ return false
98
+ })
99
+ })
100
+
101
+ const registerBag = $derived({
102
+ buttonId,
103
+ panelId,
104
+ close: () => context.closePopover(),
105
+ })
106
+
107
+ const groupContext = usePopoverGroupContext()
108
+ const registerPopover = $derived(groupContext?.registerPopover)
109
+ const isFocusWithinPopoverGroup = () => {
110
+ return (
111
+ groupContext?.isFocusWithinPopoverGroup() ??
112
+ (ownerDocument?.activeElement &&
113
+ (button?.contains(ownerDocument.activeElement) || panel?.contains(ownerDocument.activeElement)))
114
+ )
115
+ }
116
+
117
+ $effect(() => {
118
+ registerBag
119
+ untrack(() => registerPopover?.(registerBag))
120
+ })
121
+
122
+ const nestedPortals = useNestedPortals()
123
+ const { portals } = $derived(nestedPortals)
124
+ const mainTreeNode = useMainTreeNode({
125
+ get fallbackMainTreeNode() {
126
+ return button
127
+ },
128
+ })
129
+ const root = useRootContainers({
130
+ get mainTreeNode() {
131
+ return mainTreeNode.node
132
+ },
133
+ get portals() {
134
+ return portals
135
+ },
136
+ get defaultContainers() {
137
+ return [button, panel]
138
+ },
139
+ })
140
+
141
+ // Handle focus out
142
+ useEventListener({
143
+ get element() {
144
+ return ownerDocument?.defaultView
145
+ },
146
+ type: "focus",
147
+ listener: (event) => {
148
+ if (event.target === window) return
149
+ if (!(event.target instanceof HTMLElement)) return
150
+ if (popoverState !== PopoverStates.Open) return
151
+ if (isFocusWithinPopoverGroup()) return
152
+ if (!button) return
153
+ if (!panel) return
154
+ if (root.contains(event.target)) return
155
+ if (beforePanelSentinel?.contains?.(event.target)) return
156
+ if (afterPanelSentinel?.contains?.(event.target)) return
157
+ if (afterButtonSentinel?.contains?.(event.target)) return
158
+
159
+ context.closePopover()
160
+ },
161
+ options: true,
162
+ })
163
+
164
+ // Handle outside click
165
+ const outsideClickEnabled = $derived(popoverState === PopoverStates.Open)
166
+ useOutsideClick({
167
+ get enabled() {
168
+ return outsideClickEnabled
169
+ },
170
+ get containers() {
171
+ return root.resolvedContainers
172
+ },
173
+ cb: (event, target) => {
174
+ context.closePopover()
175
+
176
+ if (!isFocusableElement(target, FocusableMode.Loose)) {
177
+ event.preventDefault()
178
+ button?.focus()
179
+ }
180
+ },
181
+ })
182
+
183
+ const close = (focusableElement?: HTMLElement | MouseEvent<HTMLElement>) => {
184
+ context.closePopover()
185
+
186
+ const restoreElement = (() => {
187
+ if (!focusableElement) return button
188
+ if (focusableElement instanceof HTMLElement) return focusableElement
189
+
190
+ return button
191
+ })()
192
+
193
+ restoreElement?.focus()
194
+ }
195
+
196
+ const api: PopoverAPIContext = {
197
+ close,
198
+ get isPortalled() {
199
+ return isPortalled
200
+ },
201
+ }
202
+ setContext("PopoverAPIContext", api)
203
+
204
+ const slot = $derived({
205
+ open: popoverState === PopoverStates.Open,
206
+ close,
207
+ } satisfies PopoverRenderPropArg)
208
+
209
+ useFloatingProvider()
210
+
211
+ setContext<PopoverPanelContext | undefined>("PopoverPanelContext", undefined)
212
+
213
+ createCloseContext({
214
+ get close() {
215
+ return close
216
+ },
217
+ })
218
+
219
+ createOpenClosedContext({
220
+ get value() {
221
+ return context.popoverState === PopoverStates.Open ? State.Open : State.Closed
222
+ },
223
+ })
224
+ </script>
225
+
226
+ <MainTreeProvider node={mainTreeNode.node}>
227
+ <ElementOrComponent {theirProps} slots={slot} defaultTag={DEFAULT_POPOVER_TAG} name="Popover" bind:element />
228
+ </MainTreeProvider>
@@ -0,0 +1,15 @@
1
+ import type { Props } from "../utils/types.js";
2
+ export declare const DEFAULT_POPOVER_TAG: "div";
3
+ export type PopoverRenderPropArg = {
4
+ open: boolean;
5
+ close(focusableElement?: HTMLElement | MouseEvent<HTMLElement>): void;
6
+ };
7
+ export type PopoverOwnProps = {
8
+ element?: HTMLElement;
9
+ __demoMode?: boolean;
10
+ };
11
+ export type PopoverProps = Props<typeof DEFAULT_POPOVER_TAG, PopoverRenderPropArg, PopoverOwnProps>;
12
+ import { type MouseEvent } from "./context.svelte.js";
13
+ declare const Popover: import("svelte").Component<PopoverProps, {}, "element">;
14
+ type Popover = ReturnType<typeof Popover>;
15
+ export default Popover;
@@ -0,0 +1,83 @@
1
+ <script lang="ts" module>
2
+ import type { Props } from "../utils/types.js"
3
+ import { RenderFeatures, type PropsForFeatures } from "../utils/render.js"
4
+
5
+ let DEFAULT_BACKDROP_TAG = "div" as const
6
+ export type BackdropRenderPropArg = {
7
+ open: boolean
8
+ }
9
+ type BackdropPropsWeControl = "aria-hidden"
10
+
11
+ const BackdropRenderFeatures = RenderFeatures.RenderStrategy | RenderFeatures.Static
12
+
13
+ export type PopoverBackdropOwnProps = {
14
+ element?: HTMLElement
15
+ id?: string
16
+ transition?: boolean
17
+ } & PropsForFeatures<typeof BackdropRenderFeatures>
18
+
19
+ export type PopoverBackdropProps = Props<typeof DEFAULT_BACKDROP_TAG, BackdropRenderPropArg, PopoverBackdropOwnProps>
20
+
21
+ export type PopoverOverlayProps = PopoverBackdropProps
22
+ </script>
23
+
24
+ <script lang="ts">
25
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte"
26
+ import { useId } from "../hooks/use-id.js"
27
+ import { PopoverStates, usePopoverContext } from "./context.svelte.js"
28
+ import { State, useOpenClosed } from "../internal/open-closed.js"
29
+ import { transitionDataAttributes, useTransition } from "../hooks/use-transition.svelte.js"
30
+
31
+ const internalId = useId()
32
+ let {
33
+ element = $bindable(),
34
+ id = `headlessui-popover-backdrop-${internalId}`,
35
+ transition = false,
36
+ ...theirProps
37
+ }: PopoverBackdropProps = $props()
38
+ const context = usePopoverContext("PopoverBackdrop")
39
+ const { popoverState } = $derived(context)
40
+
41
+ const usesOpenClosedState = useOpenClosed()
42
+ const _transition = useTransition({
43
+ get enabled() {
44
+ return transition
45
+ },
46
+ get element() {
47
+ return element
48
+ },
49
+ get show() {
50
+ return usesOpenClosedState !== null
51
+ ? (usesOpenClosedState.value & State.Open) === State.Open
52
+ : popoverState === PopoverStates.Open
53
+ },
54
+ })
55
+ const { visible, data: transitionData } = $derived(_transition)
56
+
57
+ const handleClick = (event: MouseEvent) => {
58
+ //if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
59
+ context.closePopover()
60
+ }
61
+
62
+ const slot = $derived({
63
+ open: popoverState === PopoverStates.Open,
64
+ } satisfies BackdropRenderPropArg)
65
+
66
+ const ourProps = $derived({
67
+ id,
68
+ "aria-hidden": true,
69
+ onclick: handleClick,
70
+ ...transitionDataAttributes(transitionData),
71
+ })
72
+ </script>
73
+
74
+ <ElementOrComponent
75
+ {ourProps}
76
+ {theirProps}
77
+ slots={slot}
78
+ defaultTag={DEFAULT_BACKDROP_TAG}
79
+ features={BackdropRenderFeatures}
80
+ name="PopoverBackdrop"
81
+ {visible}
82
+ bind:element
83
+ />
@@ -0,0 +1,17 @@
1
+ import type { Props } from "../utils/types.js";
2
+ import { type PropsForFeatures } from "../utils/render.js";
3
+ declare let DEFAULT_BACKDROP_TAG: "div";
4
+ export type BackdropRenderPropArg = {
5
+ open: boolean;
6
+ };
7
+ declare const BackdropRenderFeatures: number;
8
+ export type PopoverBackdropOwnProps = {
9
+ element?: HTMLElement;
10
+ id?: string;
11
+ transition?: boolean;
12
+ } & PropsForFeatures<typeof BackdropRenderFeatures>;
13
+ export type PopoverBackdropProps = Props<typeof DEFAULT_BACKDROP_TAG, BackdropRenderPropArg, PopoverBackdropOwnProps>;
14
+ export type PopoverOverlayProps = PopoverBackdropProps;
15
+ declare const PopoverBackdrop: import("svelte").Component<PopoverBackdropProps, {}, "element">;
16
+ type PopoverBackdrop = ReturnType<typeof PopoverBackdrop>;
17
+ export default PopoverBackdrop;