@bazza-ui/react 0.0.0-snapshot-20260205122957
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/command-score-BuKQkUmS.d.cts +36 -0
- package/dist/command-score-C6nHV08C.d.ts +36 -0
- package/dist/data-surface-Dki7544r.d.ts +2136 -0
- package/dist/data-surface-Dyb-d-72.d.cts +2136 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3296 -0
- package/dist/index.d.ts +3296 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/listbox/index.cjs +2 -0
- package/dist/internal/listbox/index.cjs.map +1 -0
- package/dist/internal/listbox/index.d.cts +253 -0
- package/dist/internal/listbox/index.d.ts +253 -0
- package/dist/internal/listbox/index.js +2 -0
- package/dist/internal/listbox/index.js.map +1 -0
- package/dist/internal/popup-menu/index.cjs +2 -0
- package/dist/internal/popup-menu/index.cjs.map +1 -0
- package/dist/internal/popup-menu/index.d.cts +925 -0
- package/dist/internal/popup-menu/index.d.ts +925 -0
- package/dist/internal/popup-menu/index.js +2 -0
- package/dist/internal/popup-menu/index.js.map +1 -0
- package/dist/use-listbox-item-bi01_uzf.d.cts +659 -0
- package/dist/use-listbox-item-bi01_uzf.d.ts +659 -0
- package/package.json +62 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { r as ListboxStore, V as VirtualItem, H as HighlightChangeEventDetails } from '../../use-listbox-item-bi01_uzf.cjs';
|
|
3
|
+
export { A as AimGuardRefs, L as Context, D as DOMRefs, F as FilterFn, B as HighlightSource, x as ItemContext, u as ItemContextValue, I as ItemRegistration, L as ListboxContext, q as ListboxState, q as State, U as UseListboxItemParams, y as UseListboxItemReturn, v as useItemContext, z as useListboxItem, w as useMaybeItemContext } from '../../use-listbox-item-bi01_uzf.cjs';
|
|
4
|
+
export { b as SurfaceContext, S as SurfaceContextValue, c as commandScore, d as defaultFilter, u as useMaybeSurfaceContext, a as useSurfaceContext } from '../../command-score-BuKQkUmS.cjs';
|
|
5
|
+
import '@base-ui/utils/store';
|
|
6
|
+
|
|
7
|
+
interface GroupContextValue {
|
|
8
|
+
groupId: string;
|
|
9
|
+
}
|
|
10
|
+
declare const GroupContext: React.Context<GroupContextValue | null>;
|
|
11
|
+
declare function useGroupContext(): GroupContextValue | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Virtualization configuration passed from Root/Submenu to Surface.
|
|
15
|
+
*/
|
|
16
|
+
interface VirtualizationConfig {
|
|
17
|
+
/** Whether virtualization mode is enabled */
|
|
18
|
+
virtualized: boolean;
|
|
19
|
+
/** Pre-registered items for virtualization */
|
|
20
|
+
items: VirtualItem[];
|
|
21
|
+
/**
|
|
22
|
+
* Callback when highlighted item changes (for scroll sync).
|
|
23
|
+
* The third parameter contains event details including the reason for the change.
|
|
24
|
+
*/
|
|
25
|
+
onHighlightChange?: (id: string | null, index: number, eventDetails: HighlightChangeEventDetails) => void;
|
|
26
|
+
}
|
|
27
|
+
interface ListboxContextValue {
|
|
28
|
+
/** The Listbox store instance */
|
|
29
|
+
store: ListboxStore;
|
|
30
|
+
/** Nesting depth: 0 = root menu, 1+ = submenu */
|
|
31
|
+
depth: number;
|
|
32
|
+
/** Close the entire menu tree (deepest submenu to root, sequentially) */
|
|
33
|
+
closeAll: () => void;
|
|
34
|
+
/** Register a surface (submenu) for closeAll tracking. Returns unregister function. */
|
|
35
|
+
registerSurface: (depth: number, setOpen: (open: boolean) => void) => () => void;
|
|
36
|
+
/** Virtualization configuration (if enabled) */
|
|
37
|
+
virtualization?: VirtualizationConfig;
|
|
38
|
+
}
|
|
39
|
+
declare const ListboxContext: React.Context<ListboxContextValue | null>;
|
|
40
|
+
declare function useListboxContext(): ListboxContextValue;
|
|
41
|
+
declare function useMaybeListboxContext(): ListboxContextValue | null;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Context value for row width measurement.
|
|
45
|
+
* Provided by List when `measureRowWidth` is enabled.
|
|
46
|
+
*/
|
|
47
|
+
interface RowWidthContextValue {
|
|
48
|
+
/**
|
|
49
|
+
* Queue a row element for width measurement.
|
|
50
|
+
* Call this when a row mounts or becomes visible.
|
|
51
|
+
*
|
|
52
|
+
* @param element - The DOM element to measure
|
|
53
|
+
* @param id - Unique identifier for this row (used to avoid re-measuring)
|
|
54
|
+
*/
|
|
55
|
+
queueMeasurement: (element: HTMLElement, id: string) => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Context for row width measurement.
|
|
59
|
+
* Items use this to self-register for measurement.
|
|
60
|
+
*/
|
|
61
|
+
declare const RowWidthContext: React.Context<RowWidthContextValue | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Hook to get the row width context.
|
|
64
|
+
* Throws an error if used outside of a List with `measureRowWidth` enabled.
|
|
65
|
+
*/
|
|
66
|
+
declare function useRowWidthContext(): RowWidthContextValue;
|
|
67
|
+
/**
|
|
68
|
+
* Hook to optionally get the row width context.
|
|
69
|
+
* Returns null if not within a List with `measureRowWidth` enabled.
|
|
70
|
+
* This is the preferred hook for items that should work both with and without measurement.
|
|
71
|
+
*/
|
|
72
|
+
declare function useMaybeRowWidthContext(): RowWidthContextValue | null;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Focus owner interface for keyboard handling.
|
|
76
|
+
* Optional - only needed for popup menus with multiple surfaces.
|
|
77
|
+
*/
|
|
78
|
+
interface FocusOwnerInterface {
|
|
79
|
+
/** Check if a surface is the current owner */
|
|
80
|
+
useState: (selector: 'isOwner', surfaceId: string) => boolean;
|
|
81
|
+
/** Set the owner surface ID */
|
|
82
|
+
setOwnerId: (id: string | null) => void;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Submenu context interface for keyboard handling.
|
|
86
|
+
* Optional - only needed for popup menus with submenus.
|
|
87
|
+
*/
|
|
88
|
+
interface SubmenuInterface {
|
|
89
|
+
/** Close this submenu */
|
|
90
|
+
setOpen: (open: boolean) => void;
|
|
91
|
+
/** Parent surface ID for focus transfer */
|
|
92
|
+
parentSurfaceId: string;
|
|
93
|
+
/** Whether Escape closes the root menu or just this submenu */
|
|
94
|
+
closeRootOnEsc?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface UseListboxKeyboardParams {
|
|
97
|
+
/** The Listbox store instance */
|
|
98
|
+
store: ListboxStore;
|
|
99
|
+
/** Unique identifier for this surface */
|
|
100
|
+
surfaceId: string;
|
|
101
|
+
/** Whether keyboard handling is enabled */
|
|
102
|
+
enabled: boolean;
|
|
103
|
+
/** User's onKeyDown handler to compose with */
|
|
104
|
+
onKeyDown?: React.KeyboardEventHandler;
|
|
105
|
+
/**
|
|
106
|
+
* Callback when an item is selected via keyboard (Enter or shortcut).
|
|
107
|
+
* Called with selection details. The consumer handles any
|
|
108
|
+
* post-selection behavior like closing menus.
|
|
109
|
+
*/
|
|
110
|
+
onSelect?: (details: {
|
|
111
|
+
itemId: string | null;
|
|
112
|
+
closeOnClick: boolean;
|
|
113
|
+
}) => void;
|
|
114
|
+
/**
|
|
115
|
+
* Callback to close the entire menu tree from the root.
|
|
116
|
+
* Used when Escape is pressed and closeRootOnEsc is true (default).
|
|
117
|
+
*/
|
|
118
|
+
closeAll: () => void;
|
|
119
|
+
/** The FocusOwner store for managing focus ownership (optional) */
|
|
120
|
+
focusOwner?: FocusOwnerInterface;
|
|
121
|
+
/** Menu depth (0 for root, >0 for submenus) - defaults to 0 */
|
|
122
|
+
depth?: number;
|
|
123
|
+
/** Submenu context for ArrowLeft navigation back to parent (optional) */
|
|
124
|
+
submenuContext?: SubmenuInterface | null;
|
|
125
|
+
/**
|
|
126
|
+
* Whether to enable type-to-search behavior.
|
|
127
|
+
* When true, printable characters will activate the input and set pending search.
|
|
128
|
+
* Used by List when hideUntilActive is enabled and input is not yet active.
|
|
129
|
+
* @default false
|
|
130
|
+
*/
|
|
131
|
+
enableTypeToSearch?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Whether to skip the focus owner check.
|
|
134
|
+
* When true, keyboard handling will work based on `enabled` prop alone,
|
|
135
|
+
* ignoring focus ownership. Useful for Combobox where the input is outside
|
|
136
|
+
* the Surface but should still handle keyboard navigation.
|
|
137
|
+
* @default false
|
|
138
|
+
*/
|
|
139
|
+
skipFocusOwnerCheck?: boolean;
|
|
140
|
+
}
|
|
141
|
+
interface UseListboxKeyboardReturn {
|
|
142
|
+
/** Keyboard event handler to attach to the element */
|
|
143
|
+
handleKeyDown: React.KeyboardEventHandler;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Centralized keyboard navigation hook for listbox-like components.
|
|
147
|
+
* Handles arrow navigation, vim bindings, submenu open/close, and selection.
|
|
148
|
+
*
|
|
149
|
+
* This hook can be used standalone (for simple listboxes like Select/Command)
|
|
150
|
+
* or with focus owner and submenu support (for popup menus with nested menus).
|
|
151
|
+
*/
|
|
152
|
+
declare function useListboxKeyboard(params: UseListboxKeyboardParams): UseListboxKeyboardReturn;
|
|
153
|
+
|
|
154
|
+
interface UseStickyRowWidthOptions {
|
|
155
|
+
/**
|
|
156
|
+
* Ref to the list container element.
|
|
157
|
+
* Used to measure row widths and as a fallback target for the CSS variable.
|
|
158
|
+
*/
|
|
159
|
+
listRef: React.RefObject<HTMLElement | null>;
|
|
160
|
+
/**
|
|
161
|
+
* Optional ref to the element where `--row-width` CSS variable should be applied.
|
|
162
|
+
* If not provided, uses the listRef element.
|
|
163
|
+
* Useful for applying the variable to a parent Popup element.
|
|
164
|
+
*/
|
|
165
|
+
targetRef?: React.RefObject<HTMLElement | null>;
|
|
166
|
+
/**
|
|
167
|
+
* Optional maximum width cap in pixels.
|
|
168
|
+
* The measured width will never exceed this value.
|
|
169
|
+
*/
|
|
170
|
+
maxWidth?: number;
|
|
171
|
+
/**
|
|
172
|
+
* Whether measurement is enabled.
|
|
173
|
+
* @default true
|
|
174
|
+
*/
|
|
175
|
+
enabled?: boolean;
|
|
176
|
+
}
|
|
177
|
+
interface UseStickyRowWidthReturn {
|
|
178
|
+
/**
|
|
179
|
+
* Queue a row element for measurement.
|
|
180
|
+
* The element's natural width will be measured and tracked.
|
|
181
|
+
* Call this when a row mounts or becomes visible.
|
|
182
|
+
*/
|
|
183
|
+
queueMeasurement: (element: HTMLElement, id: string) => void;
|
|
184
|
+
/**
|
|
185
|
+
* Reset all measurements.
|
|
186
|
+
* Call this when the menu closes to start fresh on next open.
|
|
187
|
+
*/
|
|
188
|
+
resetMeasurements: () => void;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Hook that measures row widths and maintains a sticky maximum width.
|
|
192
|
+
*
|
|
193
|
+
* This is useful for virtualized lists where the popup width should adapt
|
|
194
|
+
* to the content but never shrink as the user scrolls through items.
|
|
195
|
+
*
|
|
196
|
+
* The hook:
|
|
197
|
+
* 1. Measures each row's natural width (using `max-content`)
|
|
198
|
+
* 2. Tracks the maximum width seen across all rows
|
|
199
|
+
* 3. Applies `--row-width` CSS variable to the list element
|
|
200
|
+
* 4. Only grows the width, never shrinks (until reset)
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```tsx
|
|
204
|
+
* const { queueMeasurement, resetMeasurements } = useStickyRowWidth({
|
|
205
|
+
* listRef: myListRef,
|
|
206
|
+
* maxWidth: 500,
|
|
207
|
+
* })
|
|
208
|
+
*
|
|
209
|
+
* // Queue items for measurement
|
|
210
|
+
* useLayoutEffect(() => {
|
|
211
|
+
* if (itemRef.current) {
|
|
212
|
+
* queueMeasurement(itemRef.current, itemId)
|
|
213
|
+
* }
|
|
214
|
+
* }, [itemId])
|
|
215
|
+
*
|
|
216
|
+
* // Reset on menu close
|
|
217
|
+
* useEffect(() => {
|
|
218
|
+
* if (!isOpen) {
|
|
219
|
+
* resetMeasurements()
|
|
220
|
+
* }
|
|
221
|
+
* }, [isOpen])
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function useStickyRowWidth(options: UseStickyRowWidthOptions): UseStickyRowWidthReturn;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Normalizes a value string for use in filtering and identification.
|
|
228
|
+
* Trims leading/trailing whitespace to match cmdk's behavior.
|
|
229
|
+
*
|
|
230
|
+
* @param value - The value to normalize
|
|
231
|
+
* @returns The trimmed value, or empty string if value is nullish
|
|
232
|
+
*/
|
|
233
|
+
declare function normalizeValue(value: string | undefined | null): string;
|
|
234
|
+
/**
|
|
235
|
+
* Converts a value string to a URL-safe slug for use in IDs.
|
|
236
|
+
* - Trims whitespace
|
|
237
|
+
* - Converts to lowercase
|
|
238
|
+
* - Replaces spaces with hyphens
|
|
239
|
+
* - Removes non-alphanumeric characters (except hyphens)
|
|
240
|
+
* - Collapses multiple hyphens into one
|
|
241
|
+
* - Removes leading/trailing hyphens
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* slugify("User Settings") // "user-settings"
|
|
245
|
+
* slugify(" Hello World! ") // "hello-world"
|
|
246
|
+
* slugify("Café & Co.") // "caf-co"
|
|
247
|
+
*
|
|
248
|
+
* @param value - The value to slugify
|
|
249
|
+
* @returns The slugified value, or empty string if value is nullish
|
|
250
|
+
*/
|
|
251
|
+
declare function slugify(value: string | undefined | null): string;
|
|
252
|
+
|
|
253
|
+
export { type FocusOwnerInterface, GroupContext, type GroupContextValue, ListboxContext as ListboxContextProvider, type ListboxContextValue, ListboxStore, RowWidthContext, type RowWidthContextValue, type SubmenuInterface, type UseListboxKeyboardParams, type UseListboxKeyboardReturn, type UseStickyRowWidthOptions, type UseStickyRowWidthReturn, VirtualItem, type VirtualizationConfig, normalizeValue, slugify, useGroupContext, useListboxContext, useListboxKeyboard, useMaybeListboxContext, useMaybeRowWidthContext, useRowWidthContext, useStickyRowWidth };
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { r as ListboxStore, V as VirtualItem, H as HighlightChangeEventDetails } from '../../use-listbox-item-bi01_uzf.js';
|
|
3
|
+
export { A as AimGuardRefs, L as Context, D as DOMRefs, F as FilterFn, B as HighlightSource, x as ItemContext, u as ItemContextValue, I as ItemRegistration, L as ListboxContext, q as ListboxState, q as State, U as UseListboxItemParams, y as UseListboxItemReturn, v as useItemContext, z as useListboxItem, w as useMaybeItemContext } from '../../use-listbox-item-bi01_uzf.js';
|
|
4
|
+
export { b as SurfaceContext, S as SurfaceContextValue, c as commandScore, d as defaultFilter, u as useMaybeSurfaceContext, a as useSurfaceContext } from '../../command-score-C6nHV08C.js';
|
|
5
|
+
import '@base-ui/utils/store';
|
|
6
|
+
|
|
7
|
+
interface GroupContextValue {
|
|
8
|
+
groupId: string;
|
|
9
|
+
}
|
|
10
|
+
declare const GroupContext: React.Context<GroupContextValue | null>;
|
|
11
|
+
declare function useGroupContext(): GroupContextValue | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Virtualization configuration passed from Root/Submenu to Surface.
|
|
15
|
+
*/
|
|
16
|
+
interface VirtualizationConfig {
|
|
17
|
+
/** Whether virtualization mode is enabled */
|
|
18
|
+
virtualized: boolean;
|
|
19
|
+
/** Pre-registered items for virtualization */
|
|
20
|
+
items: VirtualItem[];
|
|
21
|
+
/**
|
|
22
|
+
* Callback when highlighted item changes (for scroll sync).
|
|
23
|
+
* The third parameter contains event details including the reason for the change.
|
|
24
|
+
*/
|
|
25
|
+
onHighlightChange?: (id: string | null, index: number, eventDetails: HighlightChangeEventDetails) => void;
|
|
26
|
+
}
|
|
27
|
+
interface ListboxContextValue {
|
|
28
|
+
/** The Listbox store instance */
|
|
29
|
+
store: ListboxStore;
|
|
30
|
+
/** Nesting depth: 0 = root menu, 1+ = submenu */
|
|
31
|
+
depth: number;
|
|
32
|
+
/** Close the entire menu tree (deepest submenu to root, sequentially) */
|
|
33
|
+
closeAll: () => void;
|
|
34
|
+
/** Register a surface (submenu) for closeAll tracking. Returns unregister function. */
|
|
35
|
+
registerSurface: (depth: number, setOpen: (open: boolean) => void) => () => void;
|
|
36
|
+
/** Virtualization configuration (if enabled) */
|
|
37
|
+
virtualization?: VirtualizationConfig;
|
|
38
|
+
}
|
|
39
|
+
declare const ListboxContext: React.Context<ListboxContextValue | null>;
|
|
40
|
+
declare function useListboxContext(): ListboxContextValue;
|
|
41
|
+
declare function useMaybeListboxContext(): ListboxContextValue | null;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Context value for row width measurement.
|
|
45
|
+
* Provided by List when `measureRowWidth` is enabled.
|
|
46
|
+
*/
|
|
47
|
+
interface RowWidthContextValue {
|
|
48
|
+
/**
|
|
49
|
+
* Queue a row element for width measurement.
|
|
50
|
+
* Call this when a row mounts or becomes visible.
|
|
51
|
+
*
|
|
52
|
+
* @param element - The DOM element to measure
|
|
53
|
+
* @param id - Unique identifier for this row (used to avoid re-measuring)
|
|
54
|
+
*/
|
|
55
|
+
queueMeasurement: (element: HTMLElement, id: string) => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Context for row width measurement.
|
|
59
|
+
* Items use this to self-register for measurement.
|
|
60
|
+
*/
|
|
61
|
+
declare const RowWidthContext: React.Context<RowWidthContextValue | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Hook to get the row width context.
|
|
64
|
+
* Throws an error if used outside of a List with `measureRowWidth` enabled.
|
|
65
|
+
*/
|
|
66
|
+
declare function useRowWidthContext(): RowWidthContextValue;
|
|
67
|
+
/**
|
|
68
|
+
* Hook to optionally get the row width context.
|
|
69
|
+
* Returns null if not within a List with `measureRowWidth` enabled.
|
|
70
|
+
* This is the preferred hook for items that should work both with and without measurement.
|
|
71
|
+
*/
|
|
72
|
+
declare function useMaybeRowWidthContext(): RowWidthContextValue | null;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Focus owner interface for keyboard handling.
|
|
76
|
+
* Optional - only needed for popup menus with multiple surfaces.
|
|
77
|
+
*/
|
|
78
|
+
interface FocusOwnerInterface {
|
|
79
|
+
/** Check if a surface is the current owner */
|
|
80
|
+
useState: (selector: 'isOwner', surfaceId: string) => boolean;
|
|
81
|
+
/** Set the owner surface ID */
|
|
82
|
+
setOwnerId: (id: string | null) => void;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Submenu context interface for keyboard handling.
|
|
86
|
+
* Optional - only needed for popup menus with submenus.
|
|
87
|
+
*/
|
|
88
|
+
interface SubmenuInterface {
|
|
89
|
+
/** Close this submenu */
|
|
90
|
+
setOpen: (open: boolean) => void;
|
|
91
|
+
/** Parent surface ID for focus transfer */
|
|
92
|
+
parentSurfaceId: string;
|
|
93
|
+
/** Whether Escape closes the root menu or just this submenu */
|
|
94
|
+
closeRootOnEsc?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface UseListboxKeyboardParams {
|
|
97
|
+
/** The Listbox store instance */
|
|
98
|
+
store: ListboxStore;
|
|
99
|
+
/** Unique identifier for this surface */
|
|
100
|
+
surfaceId: string;
|
|
101
|
+
/** Whether keyboard handling is enabled */
|
|
102
|
+
enabled: boolean;
|
|
103
|
+
/** User's onKeyDown handler to compose with */
|
|
104
|
+
onKeyDown?: React.KeyboardEventHandler;
|
|
105
|
+
/**
|
|
106
|
+
* Callback when an item is selected via keyboard (Enter or shortcut).
|
|
107
|
+
* Called with selection details. The consumer handles any
|
|
108
|
+
* post-selection behavior like closing menus.
|
|
109
|
+
*/
|
|
110
|
+
onSelect?: (details: {
|
|
111
|
+
itemId: string | null;
|
|
112
|
+
closeOnClick: boolean;
|
|
113
|
+
}) => void;
|
|
114
|
+
/**
|
|
115
|
+
* Callback to close the entire menu tree from the root.
|
|
116
|
+
* Used when Escape is pressed and closeRootOnEsc is true (default).
|
|
117
|
+
*/
|
|
118
|
+
closeAll: () => void;
|
|
119
|
+
/** The FocusOwner store for managing focus ownership (optional) */
|
|
120
|
+
focusOwner?: FocusOwnerInterface;
|
|
121
|
+
/** Menu depth (0 for root, >0 for submenus) - defaults to 0 */
|
|
122
|
+
depth?: number;
|
|
123
|
+
/** Submenu context for ArrowLeft navigation back to parent (optional) */
|
|
124
|
+
submenuContext?: SubmenuInterface | null;
|
|
125
|
+
/**
|
|
126
|
+
* Whether to enable type-to-search behavior.
|
|
127
|
+
* When true, printable characters will activate the input and set pending search.
|
|
128
|
+
* Used by List when hideUntilActive is enabled and input is not yet active.
|
|
129
|
+
* @default false
|
|
130
|
+
*/
|
|
131
|
+
enableTypeToSearch?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Whether to skip the focus owner check.
|
|
134
|
+
* When true, keyboard handling will work based on `enabled` prop alone,
|
|
135
|
+
* ignoring focus ownership. Useful for Combobox where the input is outside
|
|
136
|
+
* the Surface but should still handle keyboard navigation.
|
|
137
|
+
* @default false
|
|
138
|
+
*/
|
|
139
|
+
skipFocusOwnerCheck?: boolean;
|
|
140
|
+
}
|
|
141
|
+
interface UseListboxKeyboardReturn {
|
|
142
|
+
/** Keyboard event handler to attach to the element */
|
|
143
|
+
handleKeyDown: React.KeyboardEventHandler;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Centralized keyboard navigation hook for listbox-like components.
|
|
147
|
+
* Handles arrow navigation, vim bindings, submenu open/close, and selection.
|
|
148
|
+
*
|
|
149
|
+
* This hook can be used standalone (for simple listboxes like Select/Command)
|
|
150
|
+
* or with focus owner and submenu support (for popup menus with nested menus).
|
|
151
|
+
*/
|
|
152
|
+
declare function useListboxKeyboard(params: UseListboxKeyboardParams): UseListboxKeyboardReturn;
|
|
153
|
+
|
|
154
|
+
interface UseStickyRowWidthOptions {
|
|
155
|
+
/**
|
|
156
|
+
* Ref to the list container element.
|
|
157
|
+
* Used to measure row widths and as a fallback target for the CSS variable.
|
|
158
|
+
*/
|
|
159
|
+
listRef: React.RefObject<HTMLElement | null>;
|
|
160
|
+
/**
|
|
161
|
+
* Optional ref to the element where `--row-width` CSS variable should be applied.
|
|
162
|
+
* If not provided, uses the listRef element.
|
|
163
|
+
* Useful for applying the variable to a parent Popup element.
|
|
164
|
+
*/
|
|
165
|
+
targetRef?: React.RefObject<HTMLElement | null>;
|
|
166
|
+
/**
|
|
167
|
+
* Optional maximum width cap in pixels.
|
|
168
|
+
* The measured width will never exceed this value.
|
|
169
|
+
*/
|
|
170
|
+
maxWidth?: number;
|
|
171
|
+
/**
|
|
172
|
+
* Whether measurement is enabled.
|
|
173
|
+
* @default true
|
|
174
|
+
*/
|
|
175
|
+
enabled?: boolean;
|
|
176
|
+
}
|
|
177
|
+
interface UseStickyRowWidthReturn {
|
|
178
|
+
/**
|
|
179
|
+
* Queue a row element for measurement.
|
|
180
|
+
* The element's natural width will be measured and tracked.
|
|
181
|
+
* Call this when a row mounts or becomes visible.
|
|
182
|
+
*/
|
|
183
|
+
queueMeasurement: (element: HTMLElement, id: string) => void;
|
|
184
|
+
/**
|
|
185
|
+
* Reset all measurements.
|
|
186
|
+
* Call this when the menu closes to start fresh on next open.
|
|
187
|
+
*/
|
|
188
|
+
resetMeasurements: () => void;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Hook that measures row widths and maintains a sticky maximum width.
|
|
192
|
+
*
|
|
193
|
+
* This is useful for virtualized lists where the popup width should adapt
|
|
194
|
+
* to the content but never shrink as the user scrolls through items.
|
|
195
|
+
*
|
|
196
|
+
* The hook:
|
|
197
|
+
* 1. Measures each row's natural width (using `max-content`)
|
|
198
|
+
* 2. Tracks the maximum width seen across all rows
|
|
199
|
+
* 3. Applies `--row-width` CSS variable to the list element
|
|
200
|
+
* 4. Only grows the width, never shrinks (until reset)
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```tsx
|
|
204
|
+
* const { queueMeasurement, resetMeasurements } = useStickyRowWidth({
|
|
205
|
+
* listRef: myListRef,
|
|
206
|
+
* maxWidth: 500,
|
|
207
|
+
* })
|
|
208
|
+
*
|
|
209
|
+
* // Queue items for measurement
|
|
210
|
+
* useLayoutEffect(() => {
|
|
211
|
+
* if (itemRef.current) {
|
|
212
|
+
* queueMeasurement(itemRef.current, itemId)
|
|
213
|
+
* }
|
|
214
|
+
* }, [itemId])
|
|
215
|
+
*
|
|
216
|
+
* // Reset on menu close
|
|
217
|
+
* useEffect(() => {
|
|
218
|
+
* if (!isOpen) {
|
|
219
|
+
* resetMeasurements()
|
|
220
|
+
* }
|
|
221
|
+
* }, [isOpen])
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function useStickyRowWidth(options: UseStickyRowWidthOptions): UseStickyRowWidthReturn;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Normalizes a value string for use in filtering and identification.
|
|
228
|
+
* Trims leading/trailing whitespace to match cmdk's behavior.
|
|
229
|
+
*
|
|
230
|
+
* @param value - The value to normalize
|
|
231
|
+
* @returns The trimmed value, or empty string if value is nullish
|
|
232
|
+
*/
|
|
233
|
+
declare function normalizeValue(value: string | undefined | null): string;
|
|
234
|
+
/**
|
|
235
|
+
* Converts a value string to a URL-safe slug for use in IDs.
|
|
236
|
+
* - Trims whitespace
|
|
237
|
+
* - Converts to lowercase
|
|
238
|
+
* - Replaces spaces with hyphens
|
|
239
|
+
* - Removes non-alphanumeric characters (except hyphens)
|
|
240
|
+
* - Collapses multiple hyphens into one
|
|
241
|
+
* - Removes leading/trailing hyphens
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* slugify("User Settings") // "user-settings"
|
|
245
|
+
* slugify(" Hello World! ") // "hello-world"
|
|
246
|
+
* slugify("Café & Co.") // "caf-co"
|
|
247
|
+
*
|
|
248
|
+
* @param value - The value to slugify
|
|
249
|
+
* @returns The slugified value, or empty string if value is nullish
|
|
250
|
+
*/
|
|
251
|
+
declare function slugify(value: string | undefined | null): string;
|
|
252
|
+
|
|
253
|
+
export { type FocusOwnerInterface, GroupContext, type GroupContextValue, ListboxContext as ListboxContextProvider, type ListboxContextValue, ListboxStore, RowWidthContext, type RowWidthContextValue, type SubmenuInterface, type UseListboxKeyboardParams, type UseListboxKeyboardReturn, type UseStickyRowWidthOptions, type UseStickyRowWidthReturn, VirtualItem, type VirtualizationConfig, normalizeValue, slugify, useGroupContext, useListboxContext, useListboxKeyboard, useMaybeListboxContext, useMaybeRowWidthContext, useRowWidthContext, useStickyRowWidth };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var pe=Object.defineProperty;var me=(n,e)=>{for(var t in e)pe(n,t,{get:e[t],enumerable:!0})};import*as N from"react";var ee=N.createContext(null);function K(){return N.useContext(ee)}import*as L from"react";var U=L.createContext(null);function xe(){let n=L.useContext(U);if(!n)throw new Error("Item child components must be used within an Item");return n}function be(){return L.useContext(U)}import*as A from"react";var G=A.createContext(null);function j(){let n=A.useContext(G);if(!n)throw new Error("Listbox components must be used within a Listbox provider");return n}function Ie(){return A.useContext(G)}import*as H from"react";var W=H.createContext(null);process.env.NODE_ENV!=="production"&&(W.displayName="RowWidthContext");function Se(){let n=H.useContext(W);if(!n)throw new Error("useRowWidthContext must be used within a List with measureRowWidth enabled");return n}function z(){return H.useContext(W)}import*as k from"react";var q=k.createContext(null);function B(){let n=k.useContext(q);if(!n)throw new Error("Listbox components must be used within a Surface provider");return n}function Re(){return k.useContext(q)}import*as I from"react";function _(n){return n?.trim()??""}function Ce(n){return n?n.trim().toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"").replace(/-+/g,"-").replace(/^-|-$/g,""):""}function ve(n){let{id:e,value:t,keywords:s,disabled:i=!1,forceMount:o=!1,shortcut:a,isSubmenuTrigger:h=!1,onSelect:p,closeOnClick:u=!0,onAfterSelect:m,children:g,aimGuard:S}=n,{store:d}=B(),b=K(),{depth:r}=j(),l=I.useRef(null),[x,f]=I.useState("");I.useLayoutEffect(()=>{if(e===void 0&&t===void 0&&l.current){let R=l.current.textContent?.trim()??"";f(R)}},[e,t,g]);let c=e??(_(t)||x),w=I.useId(),O=e??`item-${w}`,y=s?.map(R=>_(R)).filter(Boolean),V=y?JSON.stringify(y):void 0;I.useEffect(()=>!c&&!o?void 0:d.registerItem(c,{value:c,keywords:y,groupId:b?.groupId,disabled:i,isSubmenuTrigger:h,shortcut:a,closeOnClick:u}),[c,V,b?.groupId,i,h,a,u,d,o]),I.useEffect(()=>{if(c)return d.registerItemRef(c,l)},[c,d]);let M=z();I.useLayoutEffect(()=>{M&&l.current&&c&&M.queueMeasurement(l.current,c)},[M,c]),I.useEffect(()=>{if(!(!p||!c))return d.registerItemSelect(c,p)},[c,p,d]);let D=d.useState("search"),F=d.useState("isHighlighted",c),ae=d.useState("getItemScore",c),le=d.isFilterDisabled(),ue=D.length>0,ce=o||le||!ue||ae>0,J=I.useCallback(R=>{if(R.defaultPrevented||i||!c)return;R.preventDefault(),d.context.itemSelects.get(c)?.(),m?.(c)},[i,d,c,m]),X=I.useCallback(R=>{R.preventDefault()},[]),Q=I.useCallback(R=>{if(!R.defaultPrevented&&!i&&c){if(S){let{aimGuardActiveRef:Z,guardedDepthRef:fe}=S;if(Z.current&&fe.current===r)return}d.shouldAllowPointerHighlight(R.clientX,R.clientY)&&d.setHighlightedId(c)}},[i,S,r,d,c]),he=I.useMemo(()=>({id:O,highlighted:F,disabled:i,shortcut:a}),[O,F,i,a]),de=I.useCallback(R=>c?d.registerItemSelect(c,R):()=>{},[d,c]),ge=I.useMemo(()=>({onClick:J,onPointerMove:Q,onPointerDown:X}),[J,Q,X]);return{id:O,storeId:c,ref:l,isHighlighted:F,isVisible:ce,contextValue:he,handlers:ge,registerSelect:de}}import*as te from"react";function Ee(n){let{store:e,surfaceId:t,enabled:s,onKeyDown:i,onSelect:o,closeAll:a,focusOwner:h,depth:p=0,submenuContext:u,enableTypeToSearch:m=!1,skipFocusOwnerCheck:g=!1}=n,S=h?.useState("isOwner",t)??!0,d=g?!0:S;return{handleKeyDown:te.useCallback(r=>{if(i?.(r),!r.defaultPrevented&&s&&d&&!(r.nativeEvent.isComposing||r.keyCode===229)){if(m){let l=e.context.hideUntilActive,x=e.state.inputActive;if(l&&!x&&r.key.length===1&&!r.ctrlKey&&!r.metaKey&&!r.altKey){let c=e.context.shortcuts.get(r.key.toLowerCase());if(c&&e.selectByShortcut(r.key)){r.preventDefault();let w=e.context.items.get(c);o?.({itemId:c,closeOnClick:w?.closeOnClick??!0});return}r.preventDefault(),e.setPendingSearch(r.key),e.setInputActive(!0);return}}switch(r.key){case"ArrowDown":{r.preventDefault(),e.highlightNext();break}case"ArrowUp":{r.preventDefault(),e.highlightPrev();break}case"n":{r.ctrlKey&&(r.preventDefault(),e.highlightNext());break}case"p":{r.ctrlKey&&(r.preventDefault(),e.highlightPrev());break}case"ArrowRight":{e.isHighlightedSubmenuTrigger()&&(r.preventDefault(),e.openSubmenuForHighlighted());break}case"l":{r.ctrlKey&&e.isHighlightedSubmenuTrigger()&&(r.preventDefault(),e.openSubmenuForHighlighted());break}case"ArrowLeft":{p>0&&u&&h&&(r.preventDefault(),u.setOpen(!1),h.setOwnerId(u.parentSurfaceId));break}case"h":{r.ctrlKey&&p>0&&u&&h&&(r.preventDefault(),u.setOpen(!1),h.setOwnerId(u.parentSurfaceId));break}case"Enter":{r.preventDefault();let l=e.state.highlightedId,x=e.getHighlightedItem();e.selectHighlighted(),o?.({itemId:l,closeOnClick:x?.closeOnClick??!0});break}case"Home":{r.preventDefault(),e.setHighlightedId(null),e.highlightNext();break}case"End":{r.preventDefault(),e.setHighlightedId(null),e.highlightPrev();break}case"Escape":{if(p===0)break;r.preventDefault(),r.stopPropagation(),u?.closeRootOnEsc!==!1?a():(u.setOpen(!1),h&&h.setOwnerId(u.parentSurfaceId));break}default:{let l=e.state.search.length>0;if(r.key.length===1&&!r.ctrlKey&&!r.metaKey&&!r.altKey&&!l){let f=e.context.shortcuts.get(r.key.toLowerCase());if(f&&e.selectByShortcut(r.key)){r.preventDefault();let c=e.context.items.get(f);o?.({itemId:f,closeOnClick:c?.closeOnClick??!0})}}break}}}},[i,s,d,m,e,p,u,h,o,a])}}import*as v from"react";var ye=!1,Oe=!1;function E(...n){ye&&console.log("[useStickyRowWidth]",...n)}function ne(n){return`${Math.ceil(n)}px`}function we(n){let{listRef:e,targetRef:t,maxWidth:s,enabled:i=!0}=n,o=v.useCallback(()=>t?.current??e.current,[t,e]),a=v.useRef(0),h=v.useRef([]),p=v.useRef([]),u=v.useRef(!1),m=v.useRef(new Set),g=v.useCallback(r=>{let l=o();if(!l)return;let x=s!==void 0?Math.min(r,s):r;E("--row-width updated:",{rawWidth:r,cappedWidth:x,cssValue:ne(x),maxWidthCap:s,targetElement:l.tagName+(l.className?`.${l.className.split(" ").join(".")}`:"")}),l.style.setProperty("--row-width",ne(x))},[o,s]),S=v.useCallback(()=>{u.current||(u.current=!0,requestAnimationFrame(()=>{let r=h.current,l=a.current,x=!1;if(r.length>0){E("Measuring batch of",r.length,"rows");for(let{element:f,id:c}of r){if(m.current.has(c))continue;if(!f.isConnected){E("Row skipped (unmounted):",{id:c});continue}let w=f.style.width,O=f.style.maxWidth;f.setAttribute("data-measuring",""),f.style.maxWidth="none",f.style.width="max-content";let y=Math.max(f.scrollWidth,f.offsetWidth)+1,V=getComputedStyle(f);if(E("Row measurement details:",{id:c,measuredWidth:y,scrollWidth:f.scrollWidth,offsetWidth:f.offsetWidth,computedWidth:V.width,computedMaxWidth:V.maxWidth,inlineMaxWidth:O,textContent:f.textContent?.slice(0,50)}),Oe||(f.style.width=w,f.style.maxWidth=O,f.removeAttribute("data-measuring")),y<=1){let M=f.getBoundingClientRect(),D=getComputedStyle(f);E("Row skipped (0-width, will retry):",{id:c,width:y,scrollWidth:f.scrollWidth,offsetWidth:f.offsetWidth,boundingRect:{width:M.width,height:M.height},display:D.display,visibility:D.visibility,innerHTML:f.innerHTML.slice(0,100),isConnected:f.isConnected,parentElement:f.parentElement?.tagName});continue}E("Row measured:",{id:c,width:y,currentMax:l,isNewMax:y>l}),y>l&&(l=y,x=!0),m.current.add(c)}h.current=[]}x&&(E("New max width found:",{previousMax:a.current,newMax:l,totalMeasured:m.current.size}),a.current=l,p.current.push(()=>g(l)));for(let f of p.current)f();p.current=[],u.current=!1}))},[g]),d=v.useCallback((r,l)=>{if(!i){E("queueMeasurement skipped (disabled):",l);return}if(m.current.has(l)){E("queueMeasurement skipped (already measured):",l);return}E("queueMeasurement:",{id:l,queueSize:h.current.length+1,element:r.tagName}),h.current.push({element:r,id:l}),S()},[i,S]),b=v.useCallback(()=>{let r=a.current,l=m.current.size;m.current.clear(),a.current=0;let x=o();x&&x.style.removeProperty("--row-width"),E("Measurements reset:",{previousMaxWidth:r,previousMeasuredCount:l,targetElement:x?.tagName})},[o]);return v.useEffect(()=>{if(!i)return;let r=o();if(!r||typeof ResizeObserver>"u")return;let l=null,x=new ResizeObserver(f=>{l!==null&&cancelAnimationFrame(l),l=requestAnimationFrame(()=>{l=null,a.current>0&&(E("ResizeObserver triggered re-apply:",{currentMax:a.current,containerSize:f[0]?.contentRect}),g(a.current))})});return x.observe(r),()=>{l!==null&&cancelAnimationFrame(l),x.disconnect()}},[o,i,g]),{queueMeasurement:d,resetMeasurements:b}}import{createSelector as C,ReactStore as Ze}from"@base-ui/utils/store";import{useRefWithInit as et}from"@base-ui/utils/useRefWithInit";var P={};me(P,{auto:()=>qe,clearPress:()=>Fe,closePress:()=>Ne,escapeKey:()=>He,focusOut:()=>Te,imperativeAction:()=>Be,inputChange:()=>We,inputClear:()=>_e,itemKeyboardSelect:()=>De,itemPress:()=>Ve,keyboard:()=>ze,listNavigation:()=>Ke,none:()=>Ye,outsidePress:()=>ke,pointer:()=>je,siblingOpen:()=>Ge,submenuTrigger:()=>Ue,triggerContextMenu:()=>Ae,triggerFocus:()=>Le,triggerHover:()=>Me,triggerPress:()=>Pe});var Pe="trigger-press",Me="trigger-hover",Le="trigger-focus",Ae="trigger-context-menu",He="escape-key",ke="outside-press",Te="focus-out",Ve="item-press",De="item-keyboard-select",Ne="close-press",We="input-change",_e="input-clear",Fe="clear-press",Ke="list-navigation",Ue="submenu-trigger",Ge="sibling-open",je="pointer",ze="keyboard",qe="auto",Be="imperative-action",Ye="none";function se(n,e,t,s){let i=!1,o=!1;return{reason:n,event:e??new Event("ui-event"),cancel(){i=!0},allowPropagation(){o=!0},get isCanceled(){return i},get isPropagationAllowed(){return o},trigger:t,...s}}function ie(n,e,t){return{reason:n,event:e??new Event("ui-event"),...t}}var $e=/[\\/_+.#"@[({&]/,Je=/[\\/_+.#"@[({&]/g,Xe=/[\s-]/,oe=/[\s-]/g;function Y(n,e,t,s,i,o,a){if(o===e.length)return i===n.length?1:.99;let h=`${i},${o}`;if(a[h]!==void 0)return a[h];let p=s.charAt(o),u=t.indexOf(p,i),m=0,g,S,d,b;for(;u>=0;)g=Y(n,e,t,s,u+1,o+1,a),g>m&&(u===i?g*=1:$e.test(n.charAt(u-1))?(g*=.8,d=n.slice(i,u-1).match(Je),d&&i>0&&(g*=.999**d.length)):Xe.test(n.charAt(u-1))?(g*=.9,b=n.slice(i,u-1).match(oe),b&&i>0&&(g*=.999**b.length)):(g*=.17,i>0&&(g*=.999**(u-i))),n.charAt(u)!==e.charAt(o)&&(g*=.9999)),(g<.1&&t.charAt(u-1)===s.charAt(o+1)||s.charAt(o+1)===s.charAt(o)&&t.charAt(u-1)!==s.charAt(o))&&(S=Y(n,e,t,s,u+1,o+2,a),S*.1>g&&(g=S*.1)),g>m&&(m=g),u=t.indexOf(p,u+1);return a[h]=m,m}function re(n){return n.toLowerCase().replace(oe," ")}function T(n,e,t){if(!e)return 1;if(!n)return 0;let s=t&&t.length>0?`${n} ${t.join(" ")}`:n;return Y(s,e,re(s),re(e),0,0,{})}var Qe=T;var tt={open:C(n=>n.open),search:C(n=>n.search),highlightedId:C(n=>n.highlightedId),highlightSource:C(n=>n.highlightSource),hasInput:C(n=>n.hasInput),inputActive:C(n=>n.inputActive),pendingSearch:C(n=>n.pendingSearch),filteredCount:C(n=>n.filteredCount),filteredItems:C(n=>n.filteredItems),visibleGroups:C(n=>n.visibleGroups),virtualized:C(n=>n.virtualized),isHighlighted:C((n,e)=>n.highlightedId===e),isGroupVisible:C((n,e)=>n.search.length===0||n.visibleGroups.has(e)),getItemScore:C((n,e)=>n.search.length===0?1:n.filteredItems.get(e)??0),hasSearchWithNoResults:C(n=>n.search.length===0?!1:n.virtualized&&n.virtualItemsCount>=0?n.virtualItemsCount===0:n.filteredCount===0)},$=class n extends Ze{constructor(e,t){let s={filter:T,loop:!0,autoHighlightFirst:!0,clearSearchOnClose:!0,hideUntilActive:!1,listId:"",inputId:"",items:new Map,groups:new Map,itemSelects:new Map,submenuOpens:new Map,submenuCloses:new Map,shortcuts:new Map,onOpenChange:()=>{},onSearchChange:void 0,virtualItems:[],orderedItems:[],onHighlightChange:void 0,refs:{listRef:{current:null},itemRefs:new Map},onCloseComplete:void 0,lastPointerPosition:null};super({...nt(),...e},{...s,...t},tt),this.observe("open",i=>{if(i)this.resetPointerPosition(),this.context.autoHighlightFirst===!0&&this.highlightFirstItem();else{this.context.clearSearchOnClose===!0&&this.setSearch("");let o=this.context.clearSearchOnClose==="after-exit";this.update({highlightedId:null,highlightSource:null,inputActive:o?this.state.inputActive:!1,pendingSearch:""})}}),this.observe("search",(i,o)=>{i!==o&&(this.resetPointerPosition(),this.recomputeFilteredItems(o))})}setOpen(e,t=P.none,s){let i=se(t,s);this.context.onOpenChange(e,i),!i.isCanceled&&this.set("open",e)}setSearch(e){this.set("search",e),this.context.onSearchChange?.(e)}setHighlightedId(e,t="pointer"){this.state.highlightedId!==e&&(this.closeSiblingSubmenus(e),this.update({highlightedId:e,highlightSource:t}),this.notifyHighlightChange(e,t),t==="keyboard"&&e!==null&&this.scrollItemIntoView(e))}notifyHighlightChange(e,t){let{onHighlightChange:s}=this.context;if(!s)return;let i=t==="keyboard"?P.keyboard:t==="pointer"?P.pointer:P.auto,o=e===null?-1:this.state.virtualized?this.getVirtualItemIndex(e):this.getVisibleItemIndex(e),a=ie(i,void 0,{index:o});s(e,o,a)}scrollItemIntoView(e){let{refs:t}=this.context,s=t.listRef.current,o=t.itemRefs.get(e)?.current;if(o&&s)try{s.contains(o)&&o.scrollIntoView({block:"nearest"})}catch{}}setHasInput(e){this.set("hasInput",e)}setInputActive(e){this.set("inputActive",e)}setPendingSearch(e){this.set("pendingSearch",e)}setHideUntilActive(e){this.context.hideUntilActive=e,e&&this.state.search.length>0&&this.setInputActive(!0)}setVirtualized(e){this.set("virtualized",e)}setVirtualItems(e){let t=this.context.virtualItems;if(this.context.virtualItems=e,this.set("virtualItemsCount",e.length),this.preRegisterVirtualItems(),e===t||!this.state.virtualized||!this.state.open||e.length===0)return;let s=t.find(a=>!a.disabled),o=e.find(a=>!a.disabled)?.value!==s?.value;this.validateHighlight({forceFirst:o})}setOrderedItems(e){let t=this.context.orderedItems;if(this.context.orderedItems=e,e!==t&&this.state.open)if(e.length>0){let s=e.find(i=>this.context.items.has(i));s!==void 0?this.setHighlightedId(s,"auto"):this.setHighlightedId(null)}else this.setHighlightedId(null)}maybeAutoHighlightOnRegister(e){if(this.context.filter!==!1||!this.state.open||this.state.highlightedId!==null||!this.context.autoHighlightFirst)return;let t=this.context.orderedItems;if(t.length===0)return;t.find(i=>this.context.items.has(i))===e&&this.setHighlightedId(e,"auto")}setOnHighlightChange(e){this.context.onHighlightChange=e}setListRef(e){this.context.refs.listRef=e}registerItemRef(e,t){return this.context.refs.itemRefs.set(e,t),()=>{this.context.refs.itemRefs.delete(e)}}shouldAllowPointerHighlight(e,t){let s=this.context.lastPointerPosition;if(s===null)return this.context.lastPointerPosition={x:e,y:t},!0;let i=Math.abs(e-s.x),o=Math.abs(t-s.y);return i>1||o>1?(this.context.lastPointerPosition={x:e,y:t},!0):!1}resetPointerPosition(){this.context.lastPointerPosition=null}preRegisterVirtualItems(){let e=this.context.virtualItems;if(e.length!==0){for(let t of e)this.context.items.has(t.value)||this.context.items.set(t.value,{value:t.value,keywords:t.keywords,disabled:t.disabled});this.recomputeFilteredItems()}}registerItem(e,t){let s=this.context.items.get(e);if(s&&s.value===t.value&&s.disabled===t.disabled&&s.groupId===t.groupId&&s.shortcut===t.shortcut)return()=>{this.context.items.get(e)===s&&(this.context.items.delete(e),this.context.itemSelects.delete(e),t.groupId&&this.context.groups.get(t.groupId)?.delete(e),t.shortcut&&this.context.shortcuts.delete(t.shortcut.toLowerCase()),this.recomputeFilteredItems())};if(this.context.items.set(e,t),t.groupId){let o=this.context.groups.get(t.groupId);o&&o.add(e)}if(t.shortcut){let o=t.shortcut.toLowerCase();this.context.shortcuts.set(o,e)}return this.recomputeFilteredItems(),this.maybeAutoHighlightOnRegister(e),()=>{if(this.context.items.delete(e),this.context.itemSelects.delete(e),t.groupId){let o=this.context.groups.get(t.groupId);o&&o.delete(e)}if(t.shortcut){let o=t.shortcut.toLowerCase();this.context.shortcuts.delete(o)}this.recomputeFilteredItems()}}registerGroup(e){return this.context.groups.set(e,new Set),()=>{this.context.groups.delete(e)}}registerItemSelect(e,t){return t&&this.context.itemSelects.set(e,t),()=>{this.context.itemSelects.delete(e)}}registerSubmenuOpen(e,t){return t&&this.context.submenuOpens.set(e,t),()=>{this.context.submenuOpens.delete(e)}}registerSubmenuClose(e,t){return t&&this.context.submenuCloses.set(e,t),()=>{this.context.submenuCloses.delete(e)}}closeSiblingSubmenus(e){for(let[t,s]of this.context.submenuCloses)if(t!==e)try{s()}catch{}}highlightNext(){let e=this.getVisibleItemIds();if(e.length===0)return;let s=(this.state.highlightedId?e.indexOf(this.state.highlightedId):-1)+1;s>=e.length&&(s=this.context.loop?0:e.length-1);let i=e[s];i&&this.setHighlightedId(i,"keyboard")}highlightPrev(){let e=this.getVisibleItemIds();if(e.length===0)return;let s=(this.state.highlightedId?e.indexOf(this.state.highlightedId):e.length)-1;s<0&&(s=this.context.loop?e.length-1:0);let i=e[s];i&&this.setHighlightedId(i,"keyboard")}selectHighlighted(){this.state.highlightedId&&this.context.itemSelects.get(this.state.highlightedId)?.()}selectByShortcut(e){let t=this.context.shortcuts.get(e.toLowerCase());if(!t)return!1;let s=this.context.items.get(t);if(!s||s.disabled)return!1;let i=this.state.filteredItems.get(t)??0;return this.state.search.length===0||i>0?(this.context.itemSelects.get(t)?.(),!0):!1}openSubmenuForHighlighted(){this.state.highlightedId&&this.context.submenuOpens.get(this.state.highlightedId)?.()}isHighlightedSubmenuTrigger(){return this.state.highlightedId?this.context.items.get(this.state.highlightedId)?.isSubmenuTrigger??!1:!1}getHighlightedItem(){if(this.state.highlightedId)return this.context.items.get(this.state.highlightedId)}clearSearch(){this.setSearch("")}highlightFirstItem(){let e=this.getVisibleItemIds();e.length>0&&e[0]?this.update({highlightedId:e[0],highlightSource:null}):this.update({highlightedId:null,highlightSource:null})}applyAutoHighlight(){if(!this.state.open)return;let e=this.context.autoHighlightFirst;e===!0?this.highlightFirstItem():typeof e=="string"&&this.highlightItemByValue(e)}highlightItemByValue(e){let t=this.getVisibleItemIds(),s=null;t.includes(e)?s=e:t.length>0&&t[0]&&(s=t[0]),this.update({highlightedId:s,highlightSource:null}),s&&requestAnimationFrame(()=>{this.scrollItemIntoView(s)})}isFilterDisabled(){return this.context.filter===!1}getVisibleItemIds(){let e=[],t=this.state.search,s=this.state.filteredItems,i=this.context.virtualItems,o=this.context.orderedItems;if(this.state.virtualized&&i.length>0){for(let a of i){let h=s.get(a.value)??0;(t.length===0||h>0)&&!a.disabled&&e.push(a.value)}return e}if(this.context.filter===!1&&o.length>0){let a=[];for(let h of o){let p=this.context.items.get(h);p&&!p.disabled?e.push(h):p||a.push(h)}if(process.env.NODE_ENV!=="production"&&a.length>0&&e.length>0)for(let h of a)console.warn(`[ListboxStore] Item "${h}" is in orderedItems but not registered. This may cause keyboard navigation to skip this item. Make sure the render function passes the \`id\` prop: <Item {...props}>...</Item>`);return e}return this.context.items.forEach((a,h)=>{let p=s.get(h)??0;(t.length===0||p>0)&&!a.disabled&&e.push(h)}),e}getVisibleItemIndex(e){return this.getVisibleItemIds().indexOf(e)}getVirtualItemIndex(e){return this.state.virtualized?this.context.virtualItems.findIndex(t=>t.value===e):-1}validateHighlight(e={}){let{forceFirst:t=!1,filteredItems:s=this.state.filteredItems,newSearch:i,prevSearch:o}=e,a=o!==void 0?o:this.state.search,h=i!==void 0?i:a,p=i!==void 0&&i!==a;if(!this.state.open||!this.context.autoHighlightFirst)return this.state.highlightedId;let u=this.state.highlightedId,{filter:m}=this.context,g=t||p,S=!1;if(u&&!g){let b=s.get(u)??0,r=h.length===0||m===!1||b>0,l=this.context.items.get(u),x=this.context.virtualItems.find(O=>O.value===u),f=l?.disabled??x?.disabled??!1,c=this.state.virtualized||l!==void 0,w=!this.state.virtualized||this.context.virtualItems.length===0||x!==void 0;S=r&&!f&&c&&w}if(S)return u;let d=null;if(this.state.virtualized&&this.context.virtualItems.length>0)for(let b of this.context.virtualItems){let r=s.get(b.value)??0;if((h.length===0||m===!1||r>0)&&!b.disabled){d=b.value;break}}else if(m===!1&&this.context.orderedItems.length>0)for(let b of this.context.orderedItems){let r=this.context.items.get(b);if(r&&!r.disabled){d=b;break}}else for(let[b,r]of this.context.items){let l=s.get(b)??0;if((h.length===0||l>0)&&!r.disabled){d=b;break}}return d!==u&&this.update({highlightedId:d,highlightSource:null}),d}recomputeFilteredItems(e){let{filter:t}=this.context,s=this.state.search,i=this.context.items,o=this.context.groups,a=new Map,h=new Set,p=0;if(!s||t===!1){if(this.state.virtualized&&this.context.virtualItems.length>0)for(let m of this.context.virtualItems)a.set(m.value,1),p++;else i.forEach((m,g)=>{a.set(g,1),p++});o.forEach((m,g)=>{h.add(g)})}else{let m=t||T;i.forEach((g,S)=>{let d=m(g.value,s,g.keywords);a.set(S,d),d>0&&(p++,g.groupId&&h.add(g.groupId))})}if(t===!1){this.update({filteredItems:a,visibleGroups:h,filteredCount:p,filterTrigger:this.state.filterTrigger+1});return}let u=this.validateHighlight({filteredItems:a,newSearch:s,prevSearch:e});this.update({filteredItems:a,visibleGroups:h,filteredCount:p,filterTrigger:this.state.filterTrigger+1,highlightedId:u,highlightSource:null})}static useStore(e,t,s){return et(()=>e??new n(t,s)).current}};function nt(){return{open:!1,search:"",highlightedId:null,highlightSource:null,hasInput:!1,inputActive:!1,pendingSearch:"",filteredItems:new Map,visibleGroups:new Set,filteredCount:0,filterTrigger:0,virtualized:!1,virtualItemsCount:0}}export{ee as GroupContext,U as ItemContext,G as ListboxContextProvider,$ as ListboxStore,W as RowWidthContext,q as SurfaceContext,T as commandScore,Qe as defaultFilter,_ as normalizeValue,Ce as slugify,K as useGroupContext,xe as useItemContext,j as useListboxContext,ve as useListboxItem,Ee as useListboxKeyboard,be as useMaybeItemContext,Ie as useMaybeListboxContext,z as useMaybeRowWidthContext,Re as useMaybeSurfaceContext,Se as useRowWidthContext,we as useStickyRowWidth,B as useSurfaceContext};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|