@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.
- package/dist/button/Button.svelte +1 -1
- package/dist/button/Button.svelte.d.ts +9 -11
- package/dist/checkbox/Checkbox.svelte +4 -4
- package/dist/checkbox/Checkbox.svelte.d.ts +10 -14
- package/dist/close-button/CloseButton.svelte.d.ts +16 -18
- package/dist/data-interactive/DataInteractive.svelte.d.ts +8 -11
- package/dist/description/Description.svelte +19 -14
- package/dist/description/Description.svelte.d.ts +9 -11
- package/dist/description/context.svelte.js +14 -16
- package/dist/dialog/Dialog.svelte +245 -17
- package/dist/dialog/Dialog.svelte.d.ts +12 -14
- package/dist/dialog/DialogBackdrop.svelte +1 -1
- package/dist/dialog/DialogBackdrop.svelte.d.ts +9 -11
- package/dist/dialog/DialogPanel.svelte +1 -2
- package/dist/dialog/DialogPanel.svelte.d.ts +9 -11
- package/dist/dialog/DialogTitle.svelte.d.ts +8 -10
- package/dist/dialog/context.svelte.js +1 -1
- package/dist/field/Field.svelte +24 -12
- package/dist/field/Field.svelte.d.ts +9 -11
- package/dist/fieldset/Fieldset.svelte +1 -1
- package/dist/fieldset/Fieldset.svelte.d.ts +9 -11
- package/dist/focus-trap/FocusTrap.svelte +7 -14
- package/dist/focus-trap/FocusTrap.svelte.d.ts +11 -25
- package/dist/focus-trap/FocusTrapFeatures.d.ts +14 -0
- package/dist/focus-trap/FocusTrapFeatures.js +15 -0
- package/dist/hooks/use-controllable.svelte.js +2 -1
- package/dist/hooks/use-did-element-move.svelte.js +5 -10
- package/dist/hooks/use-disabled.d.ts +6 -1
- package/dist/hooks/use-disabled.js +10 -5
- package/dist/hooks/use-event-listener.svelte.d.ts +1 -1
- package/dist/hooks/use-event-listener.svelte.js +3 -1
- package/dist/hooks/use-root-containers.svelte.d.ts +2 -2
- package/dist/hooks/use-root-containers.svelte.js +5 -5
- package/dist/hooks/use-tab-direction.svelte.js +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/input/Input.svelte +3 -3
- package/dist/input/Input.svelte.d.ts +10 -14
- package/dist/internal/FloatingProvider.svelte +12 -0
- package/dist/internal/FloatingProvider.svelte.d.ts +6 -0
- package/dist/internal/FocusSentinel.svelte.d.ts +2 -18
- package/dist/internal/ForcePortalRoot.svelte.d.ts +2 -18
- package/dist/internal/FormFields.svelte +22 -19
- package/dist/internal/FormFields.svelte.d.ts +2 -18
- package/dist/internal/FormFieldsProvider.svelte +13 -0
- package/dist/internal/FormFieldsProvider.svelte.d.ts +5 -0
- package/dist/internal/FormResolver.svelte.d.ts +2 -18
- package/dist/internal/Hidden.svelte +18 -8
- package/dist/internal/Hidden.svelte.d.ts +11 -16
- package/dist/internal/HiddenFeatures.d.ts +5 -0
- package/dist/internal/HiddenFeatures.js +9 -0
- package/dist/internal/MainTreeProvider.svelte.d.ts +2 -18
- package/dist/internal/Portal.svelte.d.ts +2 -18
- package/dist/internal/floating-provider.svelte.d.ts +3 -0
- package/dist/internal/floating-provider.svelte.js +206 -0
- package/dist/internal/floating.svelte.d.ts +46 -22
- package/dist/internal/floating.svelte.js +90 -272
- package/dist/internal/form-fields.svelte.d.ts +10 -0
- package/dist/internal/form-fields.svelte.js +23 -0
- package/dist/label/Label.svelte +6 -5
- package/dist/label/Label.svelte.d.ts +9 -11
- package/dist/label/context.svelte.js +1 -1
- package/dist/legend/Legend.svelte +2 -2
- package/dist/legend/Legend.svelte.d.ts +4 -32
- package/dist/listbox/Listbox.svelte +47 -68
- package/dist/listbox/Listbox.svelte.d.ts +18 -80
- package/dist/listbox/ListboxButton.svelte +10 -10
- package/dist/listbox/ListboxButton.svelte.d.ts +10 -15
- package/dist/listbox/ListboxOption.svelte +10 -6
- package/dist/listbox/ListboxOption.svelte.d.ts +9 -12
- package/dist/listbox/ListboxOptions.svelte +108 -54
- package/dist/listbox/ListboxOptions.svelte.d.ts +9 -12
- package/dist/listbox/ListboxSelectedOption.svelte +2 -4
- package/dist/listbox/ListboxSelectedOption.svelte.d.ts +14 -16
- package/dist/listbox/context.svelte.d.ts +76 -0
- package/dist/listbox/context.svelte.js +36 -0
- package/dist/listbox/index.d.ts +4 -4
- package/dist/listbox/index.js +1 -1
- package/dist/menu/Menu.svelte +13 -191
- package/dist/menu/Menu.svelte.d.ts +9 -13
- package/dist/menu/MenuButton.svelte +4 -2
- package/dist/menu/MenuButton.svelte.d.ts +9 -12
- package/dist/menu/MenuHeading.svelte.d.ts +9 -12
- package/dist/menu/MenuItem.svelte.d.ts +11 -16
- package/dist/menu/MenuItems.svelte +15 -11
- package/dist/menu/MenuItems.svelte.d.ts +9 -12
- package/dist/menu/MenuSection.svelte.d.ts +8 -11
- package/dist/menu/MenuSeparator.svelte.d.ts +8 -12
- package/dist/menu/context.svelte.d.ts +2 -1
- package/dist/menu/context.svelte.js +212 -2
- package/dist/menu/index.d.ts +7 -7
- package/dist/popover/Popover.svelte +161 -0
- package/dist/popover/Popover.svelte.d.ts +39 -0
- package/dist/popover/PopoverBackdrop.svelte +56 -0
- package/dist/popover/PopoverBackdrop.svelte.d.ts +43 -0
- package/dist/popover/PopoverButton.svelte +246 -0
- package/dist/popover/PopoverButton.svelte.d.ts +42 -0
- package/dist/popover/PopoverGroup.svelte +43 -0
- package/dist/popover/PopoverGroup.svelte.d.ts +31 -0
- package/dist/popover/PopoverPanel.svelte +274 -0
- package/dist/popover/PopoverPanel.svelte.d.ts +51 -0
- package/dist/popover/context.svelte.d.ts +51 -0
- package/dist/popover/context.svelte.js +108 -0
- package/dist/popover/index.d.ts +5 -0
- package/dist/popover/index.js +5 -0
- package/dist/portal/InternalPortal.svelte.d.ts +9 -11
- package/dist/portal/Portal.svelte.d.ts +2 -6
- package/dist/portal/PortalGroup.svelte.d.ts +9 -11
- package/dist/select/Select.svelte +74 -0
- package/dist/select/Select.svelte.d.ts +46 -0
- package/dist/select/index.d.ts +1 -0
- package/dist/select/index.js +1 -0
- package/dist/switch/Switch.svelte +30 -20
- package/dist/switch/Switch.svelte.d.ts +10 -12
- package/dist/switch/SwitchGroup.svelte.d.ts +8 -10
- package/dist/tabs/Tab.svelte +8 -9
- package/dist/tabs/Tab.svelte.d.ts +9 -11
- package/dist/tabs/TabGroup.svelte +27 -190
- package/dist/tabs/TabGroup.svelte.d.ts +9 -31
- package/dist/tabs/TabList.svelte +4 -4
- package/dist/tabs/TabList.svelte.d.ts +8 -10
- package/dist/tabs/TabPanel.svelte +4 -5
- package/dist/tabs/TabPanel.svelte.d.ts +9 -11
- package/dist/tabs/TabPanels.svelte +3 -3
- package/dist/tabs/TabPanels.svelte.d.ts +8 -10
- package/dist/tabs/context.svelte.d.ts +31 -0
- package/dist/tabs/context.svelte.js +134 -0
- package/dist/textarea/Textarea.svelte +4 -4
- package/dist/textarea/Textarea.svelte.d.ts +21 -20
- package/dist/transition/InternalTransitionChild.svelte.d.ts +9 -11
- package/dist/transition/Transition.svelte.d.ts +9 -11
- package/dist/transition/TransitionChild.svelte.d.ts +9 -11
- package/dist/transition/context.svelte.js +2 -2
- package/dist/utils/DisabledProvider.svelte +6 -0
- package/dist/utils/DisabledProvider.svelte.d.ts +6 -0
- package/dist/utils/ElementOrComponent.svelte +2 -2
- package/dist/utils/ElementOrComponent.svelte.d.ts +12 -11
- package/dist/utils/Generic.svelte +10 -8
- package/dist/utils/Generic.svelte.d.ts +12 -15
- package/dist/utils/StableCollection.svelte.d.ts +2 -18
- package/dist/utils/alternative-types.d.ts +1 -2
- package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +17 -0
- package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte.d.ts +7 -0
- package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +50 -0
- package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte.d.ts +25 -0
- package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.d.ts +6 -0
- package/dist/utils/floating-ui/svelte/hooks/useFloating.svelte.js +158 -0
- package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.d.ts +11 -0
- package/dist/utils/floating-ui/svelte/hooks/useFloatingRootContext.svelte.js +53 -0
- package/dist/utils/floating-ui/svelte/hooks/useId.svelte.d.ts +9 -0
- package/dist/utils/floating-ui/svelte/hooks/useId.svelte.js +28 -0
- package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.d.ts +23 -0
- package/dist/utils/floating-ui/svelte/hooks/useInteractions.svelte.js +72 -0
- package/dist/utils/floating-ui/svelte/index.d.ts +5 -0
- package/dist/utils/floating-ui/svelte/index.js +5 -0
- package/dist/utils/floating-ui/svelte/inner.svelte.d.ts +83 -0
- package/dist/utils/floating-ui/svelte/inner.svelte.js +178 -0
- package/dist/utils/floating-ui/svelte/types.d.ts +114 -0
- package/dist/utils/floating-ui/svelte/types.js +1 -0
- package/dist/utils/floating-ui/svelte/utils/createPubSub.d.ts +5 -0
- package/dist/utils/floating-ui/svelte/utils/createPubSub.js +14 -0
- package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.d.ts +2 -0
- package/dist/utils/floating-ui/svelte/utils/getFloatingFocusElement.js +13 -0
- package/dist/utils/floating-ui/svelte/utils/log.d.ts +2 -0
- package/dist/utils/floating-ui/svelte/utils/log.js +19 -0
- package/dist/utils/floating-ui/svelte/utils.d.ts +19 -0
- package/dist/utils/floating-ui/svelte/utils.js +136 -0
- package/dist/utils/floating-ui/svelte-dom/arrow.d.ts +22 -0
- package/dist/utils/floating-ui/svelte-dom/arrow.js +29 -0
- package/dist/utils/floating-ui/svelte-dom/index.d.ts +2 -0
- package/dist/utils/floating-ui/svelte-dom/index.js +2 -0
- package/dist/utils/floating-ui/svelte-dom/types.d.ts +80 -0
- package/dist/utils/floating-ui/svelte-dom/types.js +3 -0
- package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.d.ts +6 -0
- package/dist/utils/floating-ui/svelte-dom/useFloating.svelte.js +182 -0
- package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.d.ts +1 -0
- package/dist/utils/floating-ui/svelte-dom/utils/deepEqual.js +50 -0
- package/dist/utils/floating-ui/svelte-dom/utils/getDPR.d.ts +1 -0
- package/dist/utils/floating-ui/svelte-dom/utils/getDPR.js +7 -0
- package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.d.ts +1 -0
- package/dist/utils/floating-ui/svelte-dom/utils/roundByDPR.js +5 -0
- package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.d.ts +4 -0
- package/dist/utils/floating-ui/svelte-dom/utils/useLatestRef.js +7 -0
- package/dist/utils/id.d.ts +1 -1
- package/dist/utils/id.js +1 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/style.d.ts +2 -0
- package/dist/utils/style.js +6 -0
- package/dist/utils/types.d.ts +9 -13
- package/package.json +27 -26
- package/dist/dialog/InternalDialog.svelte +0 -233
- package/dist/dialog/InternalDialog.svelte.d.ts +0 -42
- package/dist/internal/HoistFormFields.svelte +0 -11
- package/dist/internal/HoistFormFields.svelte.d.ts +0 -21
- package/dist/internal/id.d.ts +0 -8
- package/dist/internal/id.js +0 -11
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
+
};
|
package/dist/menu/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { default as Menu, type MenuProps
|
|
2
|
-
export { default as MenuButton, type MenuButtonProps
|
|
3
|
-
export { default as MenuHeading, type MenuHeadingProps
|
|
4
|
-
export { default as MenuItem, type MenuItemProps
|
|
5
|
-
export { default as MenuItems, type MenuItemsProps
|
|
6
|
-
export { default as MenuSection, type MenuSectionProps
|
|
7
|
-
export { default as MenuSeparator, type MenuSeparatorProps
|
|
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;
|