@bazza-ui/react 0.0.0 → 0.1.0-canary.2
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/ListboxStore-BtcTXpzi.d.cts +351 -0
- package/dist/ListboxStore-DPqpLlAL.d.ts +351 -0
- package/dist/adapters/index.cjs +2 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +363 -0
- package/dist/adapters/index.d.ts +363 -0
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/chunk-4C666HHU.js +2 -0
- package/dist/chunk-4C666HHU.js.map +1 -0
- package/dist/chunk-AVZ64JQ3.js +2 -0
- package/dist/chunk-AVZ64JQ3.js.map +1 -0
- package/dist/chunk-BGJJC6GX.cjs +2 -0
- package/dist/chunk-BGJJC6GX.cjs.map +1 -0
- package/dist/chunk-FWWOE2SW.cjs +2 -0
- package/dist/chunk-FWWOE2SW.cjs.map +1 -0
- package/dist/chunk-JSPKF52O.cjs +2 -0
- package/dist/chunk-JSPKF52O.cjs.map +1 -0
- package/dist/chunk-KWGD24VS.js +2 -0
- package/dist/chunk-KWGD24VS.js.map +1 -0
- package/dist/chunk-M4G6J7DP.cjs +2 -0
- package/dist/chunk-M4G6J7DP.cjs.map +1 -0
- package/dist/chunk-WKAPAKUL.js +2 -0
- package/dist/chunk-WKAPAKUL.js.map +1 -0
- package/dist/combobox/index.cjs +2 -0
- package/dist/combobox/index.cjs.map +1 -0
- package/dist/combobox/index.d.cts +1039 -0
- package/dist/combobox/index.d.ts +1039 -0
- package/dist/combobox/index.js +2 -0
- package/dist/combobox/index.js.map +1 -0
- package/dist/command-score-Dgo3ZS3Z.d.ts +36 -0
- package/dist/command-score-YjNr3ZWi.d.cts +36 -0
- package/dist/context-menu/index.cjs +2 -0
- package/dist/context-menu/index.cjs.map +1 -0
- package/dist/context-menu/index.d.cts +658 -0
- package/dist/context-menu/index.d.ts +658 -0
- package/dist/context-menu/index.js +2 -0
- package/dist/context-menu/index.js.map +1 -0
- package/dist/data-surface-B-eIGTBi.d.cts +678 -0
- package/dist/data-surface-D1OilMDu.d.ts +678 -0
- package/dist/dropdown-menu/index.cjs +2 -0
- package/dist/dropdown-menu/index.cjs.map +1 -0
- package/dist/dropdown-menu/index.d.cts +700 -0
- package/dist/dropdown-menu/index.d.ts +700 -0
- package/dist/dropdown-menu/index.js +2 -0
- package/dist/dropdown-menu/index.js.map +1 -0
- package/dist/events-BPr8sRGH.d.cts +166 -0
- package/dist/events-BPr8sRGH.d.ts +166 -0
- package/dist/input-BoIK003I.d.cts +41 -0
- package/dist/input-DF7D8YzW.d.ts +41 -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 +269 -0
- package/dist/internal/listbox/index.d.ts +269 -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 +846 -0
- package/dist/internal/popup-menu/index.d.ts +846 -0
- package/dist/internal/popup-menu/index.js +2 -0
- package/dist/internal/popup-menu/index.js.map +1 -0
- package/dist/item-equality-B6TbXlBT.d.cts +7 -0
- package/dist/item-equality-B6TbXlBT.d.ts +7 -0
- package/dist/loading-DphSt8MY.d.cts +27 -0
- package/dist/loading-TsgH6v92.d.ts +27 -0
- package/dist/select/index.cjs +2 -0
- package/dist/select/index.cjs.map +1 -0
- package/dist/select/index.d.cts +927 -0
- package/dist/select/index.d.ts +927 -0
- package/dist/select/index.js +2 -0
- package/dist/select/index.js.map +1 -0
- package/dist/separator-B4Ot84B0.d.ts +748 -0
- package/dist/separator-BmbUeeaT.d.cts +748 -0
- package/dist/types-9vS1uLIK.d.cts +1557 -0
- package/dist/types-lQCIvWW8.d.ts +1557 -0
- package/dist/use-listbox-item-BIi4eRPI.d.cts +182 -0
- package/dist/use-listbox-item-BIi4eRPI.d.ts +182 -0
- package/package.json +50 -12
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
|
@@ -0,0 +1,1557 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { u as CheckedChangeEventDetails, r as RadioValueChangeEventDetails } from './events-BPr8sRGH.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Render function that receives props and state, returns a React element.
|
|
6
|
+
*/
|
|
7
|
+
type ComponentRenderFn<Props, State> = (props: Props, state: State) => React.ReactElement<unknown>;
|
|
8
|
+
/**
|
|
9
|
+
* HTML props with ref support.
|
|
10
|
+
*/
|
|
11
|
+
type HTMLProps<T = any> = React.HTMLAttributes<T> & {
|
|
12
|
+
ref?: React.Ref<T> | undefined;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Props shared by all Bazza UI components.
|
|
16
|
+
* Includes className (string or state-based function), render prop, and style (object or state-based function).
|
|
17
|
+
*/
|
|
18
|
+
type ComponentProps<ElementType extends React.ElementType, State, RenderFunctionProps = HTMLProps> = Omit<React.ComponentPropsWithRef<ElementType>, 'className' | 'color' | 'defaultValue' | 'defaultChecked'> & {
|
|
19
|
+
/**
|
|
20
|
+
* CSS class applied to the element, or a function that
|
|
21
|
+
* returns a class based on the component's state.
|
|
22
|
+
*/
|
|
23
|
+
className?: string | ((state: State) => string | undefined);
|
|
24
|
+
/**
|
|
25
|
+
* Allows you to replace the component's HTML element
|
|
26
|
+
* with a different tag, or compose it with another component.
|
|
27
|
+
*
|
|
28
|
+
* Accepts a `ReactElement` or a function that returns the element to render.
|
|
29
|
+
*/
|
|
30
|
+
render?: ComponentRenderFn<RenderFunctionProps, State> | React.ReactElement;
|
|
31
|
+
/**
|
|
32
|
+
* Style applied to the element, or a function that
|
|
33
|
+
* returns a style object based on the component's state.
|
|
34
|
+
*/
|
|
35
|
+
style?: React.CSSProperties | ((state: State) => React.CSSProperties | undefined);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
interface PopupMenuCheckboxItemState extends Record<string, unknown> {
|
|
39
|
+
/**
|
|
40
|
+
* Whether the item is highlighted (via keyboard or pointer).
|
|
41
|
+
*/
|
|
42
|
+
highlighted: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the item is disabled.
|
|
45
|
+
*/
|
|
46
|
+
disabled: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the item is currently checked.
|
|
49
|
+
*/
|
|
50
|
+
checked: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface PopupMenuCheckboxItemProps extends ComponentProps<'div', PopupMenuCheckboxItem.State> {
|
|
53
|
+
/**
|
|
54
|
+
* The controlled checked state.
|
|
55
|
+
*/
|
|
56
|
+
checked?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The default checked state for uncontrolled mode.
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
defaultChecked?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Callback fired when the checked state changes.
|
|
64
|
+
* The second parameter contains event details including the reason for the change.
|
|
65
|
+
*/
|
|
66
|
+
onCheckedChange?: (checked: boolean, eventDetails: CheckedChangeEventDetails) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Additional keywords to match against when filtering.
|
|
69
|
+
* Useful for aliases or synonyms.
|
|
70
|
+
*/
|
|
71
|
+
keywords?: string[];
|
|
72
|
+
/**
|
|
73
|
+
* Whether this item is disabled.
|
|
74
|
+
* Disabled items are not selectable and are skipped during keyboard navigation.
|
|
75
|
+
* @default false
|
|
76
|
+
*/
|
|
77
|
+
disabled?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Callback when this item is selected (via click or Enter key).
|
|
80
|
+
*/
|
|
81
|
+
onSelect?: () => void;
|
|
82
|
+
/**
|
|
83
|
+
* Whether to force render this item regardless of filter results.
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
forceMount?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Whether clicking this item should close the menu.
|
|
89
|
+
* @default false
|
|
90
|
+
*/
|
|
91
|
+
closeOnClick?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Keyboard shortcut to trigger this item.
|
|
94
|
+
* When the menu is focused and the user presses this key, the item will be selected.
|
|
95
|
+
* Should be a single character (e.g., "1", "a", etc.).
|
|
96
|
+
*/
|
|
97
|
+
shortcut?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Forces this row's relative order during score-based sorting.
|
|
100
|
+
* Lower values appear earlier.
|
|
101
|
+
* @default 0
|
|
102
|
+
*/
|
|
103
|
+
forceOrder?: number;
|
|
104
|
+
/**
|
|
105
|
+
* Overrides this row's computed fuzzy-match score.
|
|
106
|
+
*/
|
|
107
|
+
forceScore?: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* A selectable checkbox item within a popup menu.
|
|
111
|
+
* Manages its own checked state independently.
|
|
112
|
+
* Renders a `<div>` element with role="menuitemcheckbox".
|
|
113
|
+
*/
|
|
114
|
+
declare const PopupMenuCheckboxItem: React.ForwardRefExoticComponent<Omit<PopupMenuCheckboxItem.Props, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
115
|
+
declare namespace PopupMenuCheckboxItem {
|
|
116
|
+
type State = PopupMenuCheckboxItemState;
|
|
117
|
+
interface Props extends PopupMenuCheckboxItemProps {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface PopupMenuItemState extends Record<string, unknown> {
|
|
122
|
+
/**
|
|
123
|
+
* Whether the item is highlighted (via keyboard or pointer).
|
|
124
|
+
*/
|
|
125
|
+
highlighted: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Whether the item is disabled.
|
|
128
|
+
*/
|
|
129
|
+
disabled: boolean;
|
|
130
|
+
}
|
|
131
|
+
interface PopupMenuItemProps extends ComponentProps<'div', PopupMenuItem.State> {
|
|
132
|
+
/**
|
|
133
|
+
* Unique value for this item used for filtering.
|
|
134
|
+
* If not provided, will be inferred from textContent.
|
|
135
|
+
*/
|
|
136
|
+
value?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Additional keywords to match against when filtering.
|
|
139
|
+
* Useful for aliases or synonyms.
|
|
140
|
+
*/
|
|
141
|
+
keywords?: string[];
|
|
142
|
+
/**
|
|
143
|
+
* Whether this item is disabled.
|
|
144
|
+
* Disabled items are not selectable and are skipped during keyboard navigation.
|
|
145
|
+
*/
|
|
146
|
+
disabled?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Callback when this item is selected (via click or Enter key).
|
|
149
|
+
*/
|
|
150
|
+
onSelect?: () => void;
|
|
151
|
+
/**
|
|
152
|
+
* Whether to force render this item regardless of filter results.
|
|
153
|
+
* @default false
|
|
154
|
+
*/
|
|
155
|
+
forceMount?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Whether clicking this item should close the menu.
|
|
158
|
+
* @default true
|
|
159
|
+
*/
|
|
160
|
+
closeOnClick?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Keyboard shortcut to trigger this item.
|
|
163
|
+
* When the menu is focused and the user presses this key, the item will be selected.
|
|
164
|
+
* Should be a single character (e.g., "1", "a", etc.).
|
|
165
|
+
*/
|
|
166
|
+
shortcut?: string;
|
|
167
|
+
/**
|
|
168
|
+
* Forces this row's relative order during score-based sorting.
|
|
169
|
+
* Lower values appear earlier.
|
|
170
|
+
* @default 0
|
|
171
|
+
*/
|
|
172
|
+
forceOrder?: number;
|
|
173
|
+
/**
|
|
174
|
+
* Overrides this row's computed fuzzy-match score.
|
|
175
|
+
*/
|
|
176
|
+
forceScore?: number;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A selectable item in the popup menu.
|
|
180
|
+
* Renders a `<div>` element with role="option".
|
|
181
|
+
*/
|
|
182
|
+
declare const PopupMenuItem: React.ForwardRefExoticComponent<Omit<PopupMenuItem.Props, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
183
|
+
declare namespace PopupMenuItem {
|
|
184
|
+
type State = PopupMenuItemState;
|
|
185
|
+
interface Props extends PopupMenuItemProps {
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
interface PopupMenuRadioGroupState extends Record<string, unknown> {
|
|
190
|
+
/**
|
|
191
|
+
* Whether the radio group is disabled.
|
|
192
|
+
*/
|
|
193
|
+
disabled: boolean;
|
|
194
|
+
}
|
|
195
|
+
interface PopupMenuRadioGroupProps extends ComponentProps<'div', PopupMenuRadioGroup.State> {
|
|
196
|
+
/**
|
|
197
|
+
* The controlled selected value.
|
|
198
|
+
*/
|
|
199
|
+
value?: string;
|
|
200
|
+
/**
|
|
201
|
+
* The default value for uncontrolled mode.
|
|
202
|
+
*/
|
|
203
|
+
defaultValue?: string;
|
|
204
|
+
/**
|
|
205
|
+
* Callback fired when the selected value changes.
|
|
206
|
+
* The second parameter contains event details including the reason for the change.
|
|
207
|
+
*/
|
|
208
|
+
onValueChange?: (value: string, eventDetails: RadioValueChangeEventDetails) => void;
|
|
209
|
+
/**
|
|
210
|
+
* Whether all items in this group are disabled.
|
|
211
|
+
* @default false
|
|
212
|
+
*/
|
|
213
|
+
disabled?: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Whether to force render this group regardless of filter results.
|
|
216
|
+
* @default false
|
|
217
|
+
*/
|
|
218
|
+
forceMount?: boolean;
|
|
219
|
+
children: React.ReactNode;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Groups radio items together and manages the selected value.
|
|
223
|
+
* Only one item can be selected at a time within a radio group.
|
|
224
|
+
* Renders a `<div>` element with role="group".
|
|
225
|
+
*/
|
|
226
|
+
declare const PopupMenuRadioGroup: React.ForwardRefExoticComponent<Omit<PopupMenuRadioGroupProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
227
|
+
declare namespace PopupMenuRadioGroup {
|
|
228
|
+
type State = PopupMenuRadioGroupState;
|
|
229
|
+
interface Props extends PopupMenuRadioGroupProps {
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
interface PopupMenuRadioItemState extends Record<string, unknown> {
|
|
234
|
+
/**
|
|
235
|
+
* Whether the item is highlighted (via keyboard or pointer).
|
|
236
|
+
*/
|
|
237
|
+
highlighted: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Whether the item is disabled.
|
|
240
|
+
*/
|
|
241
|
+
disabled: boolean;
|
|
242
|
+
/**
|
|
243
|
+
* Whether the item is currently selected/checked.
|
|
244
|
+
*/
|
|
245
|
+
checked: boolean;
|
|
246
|
+
}
|
|
247
|
+
interface PopupMenuRadioItemProps extends ComponentProps<'div', PopupMenuRadioItem.State> {
|
|
248
|
+
/**
|
|
249
|
+
* The value to set when this item is selected.
|
|
250
|
+
* This is required and must be unique within the RadioGroup.
|
|
251
|
+
*/
|
|
252
|
+
value: string;
|
|
253
|
+
/**
|
|
254
|
+
* Additional keywords to match against when filtering.
|
|
255
|
+
* Useful for aliases or synonyms.
|
|
256
|
+
*/
|
|
257
|
+
keywords?: string[];
|
|
258
|
+
/**
|
|
259
|
+
* Whether this item is disabled.
|
|
260
|
+
* Disabled items are not selectable and are skipped during keyboard navigation.
|
|
261
|
+
* @default false
|
|
262
|
+
*/
|
|
263
|
+
disabled?: boolean;
|
|
264
|
+
/**
|
|
265
|
+
* Callback when this item is selected.
|
|
266
|
+
*/
|
|
267
|
+
onSelect?: () => void;
|
|
268
|
+
/**
|
|
269
|
+
* Whether to force render this item regardless of filter results.
|
|
270
|
+
* @default false
|
|
271
|
+
*/
|
|
272
|
+
forceMount?: boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Whether clicking this item should close the menu.
|
|
275
|
+
* @default false
|
|
276
|
+
*/
|
|
277
|
+
closeOnClick?: boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Keyboard shortcut to trigger this item.
|
|
280
|
+
* When the menu is focused and the user presses this key, the item will be selected.
|
|
281
|
+
* Should be a single character (e.g., "1", "a", etc.).
|
|
282
|
+
*/
|
|
283
|
+
shortcut?: string;
|
|
284
|
+
/**
|
|
285
|
+
* Forces this row's relative order during score-based sorting.
|
|
286
|
+
* Lower values appear earlier.
|
|
287
|
+
* @default 0
|
|
288
|
+
*/
|
|
289
|
+
forceOrder?: number;
|
|
290
|
+
/**
|
|
291
|
+
* Overrides this row's computed fuzzy-match score.
|
|
292
|
+
*/
|
|
293
|
+
forceScore?: number;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* A selectable radio item within a RadioGroup.
|
|
297
|
+
* Only one RadioItem can be selected at a time within a RadioGroup.
|
|
298
|
+
* Renders a `<div>` element with role="menuitemradio".
|
|
299
|
+
*/
|
|
300
|
+
declare const PopupMenuRadioItem: React.ForwardRefExoticComponent<Omit<PopupMenuRadioItemProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
301
|
+
declare namespace PopupMenuRadioItem {
|
|
302
|
+
type State = PopupMenuRadioItemState;
|
|
303
|
+
interface Props extends PopupMenuRadioItemProps {
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
interface PopupMenuSubmenuTriggerState extends Record<string, unknown> {
|
|
308
|
+
/**
|
|
309
|
+
* Whether this is a submenu trigger (always true).
|
|
310
|
+
*/
|
|
311
|
+
submenuTrigger: boolean;
|
|
312
|
+
/**
|
|
313
|
+
* Whether the submenu popup is open.
|
|
314
|
+
*/
|
|
315
|
+
popupOpen: boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Whether the submenu owns keyboard focus.
|
|
318
|
+
*/
|
|
319
|
+
popupFocused: boolean;
|
|
320
|
+
/**
|
|
321
|
+
* Whether the item is highlighted.
|
|
322
|
+
*/
|
|
323
|
+
highlighted: boolean;
|
|
324
|
+
/**
|
|
325
|
+
* Whether the item is disabled.
|
|
326
|
+
*/
|
|
327
|
+
disabled: boolean;
|
|
328
|
+
}
|
|
329
|
+
interface PopupMenuSubmenuTriggerProps extends ComponentProps<'div', PopupMenuSubmenuTrigger.State> {
|
|
330
|
+
/**
|
|
331
|
+
* Explicit unique identifier for this item in the store.
|
|
332
|
+
* When provided (e.g., from data-first API's computed composite ID),
|
|
333
|
+
* this takes priority over `value` for store registration.
|
|
334
|
+
*/
|
|
335
|
+
id?: string;
|
|
336
|
+
/**
|
|
337
|
+
* Unique value for this item used for filtering.
|
|
338
|
+
* If not provided, will be inferred from textContent.
|
|
339
|
+
*/
|
|
340
|
+
value?: string;
|
|
341
|
+
/**
|
|
342
|
+
* Additional keywords to match against when filtering.
|
|
343
|
+
* Useful for aliases or synonyms.
|
|
344
|
+
*/
|
|
345
|
+
keywords?: string[];
|
|
346
|
+
/**
|
|
347
|
+
* Whether this item is disabled.
|
|
348
|
+
* Disabled items are not selectable and are skipped during keyboard navigation.
|
|
349
|
+
*/
|
|
350
|
+
disabled?: boolean;
|
|
351
|
+
/**
|
|
352
|
+
* Whether to force render this item regardless of filter results.
|
|
353
|
+
* @default false
|
|
354
|
+
*/
|
|
355
|
+
forceMount?: boolean;
|
|
356
|
+
/**
|
|
357
|
+
* Whether the submenu opens when this trigger is highlighted.
|
|
358
|
+
* @default true
|
|
359
|
+
*/
|
|
360
|
+
openOnHighlight?: boolean;
|
|
361
|
+
/**
|
|
362
|
+
* Delay before opening the submenu (in milliseconds).
|
|
363
|
+
* Can be a number (applies to both pointer and keyboard) or an object
|
|
364
|
+
* with separate `pointer` and `keyboard` values.
|
|
365
|
+
* @default { pointer: 0, keyboard: 150 }
|
|
366
|
+
*/
|
|
367
|
+
delay?: number | {
|
|
368
|
+
pointer?: number;
|
|
369
|
+
keyboard?: number;
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* Delay before closing the submenu when pointer leaves (in milliseconds).
|
|
373
|
+
* @default 0
|
|
374
|
+
*/
|
|
375
|
+
closeDelay?: number;
|
|
376
|
+
/**
|
|
377
|
+
* Forces this row's relative order during score-based sorting.
|
|
378
|
+
* Lower values appear earlier.
|
|
379
|
+
* @default 0
|
|
380
|
+
*/
|
|
381
|
+
forceOrder?: number;
|
|
382
|
+
/**
|
|
383
|
+
* Overrides this row's computed fuzzy-match score.
|
|
384
|
+
*/
|
|
385
|
+
forceScore?: number;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* A menu item that opens a submenu when hovered.
|
|
389
|
+
* Must be used within PopupMenu.Submenu.
|
|
390
|
+
* Renders a `<div>` element with role="menuitem" wrapped in Popover.Trigger.
|
|
391
|
+
*/
|
|
392
|
+
declare const PopupMenuSubmenuTrigger: React.ForwardRefExoticComponent<Omit<PopupMenuSubmenuTrigger.Props, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
393
|
+
declare namespace PopupMenuSubmenuTrigger {
|
|
394
|
+
type State = PopupMenuSubmenuTriggerState;
|
|
395
|
+
interface Props extends PopupMenuSubmenuTriggerProps {
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
interface PopupMenuSubpageTriggerState extends Record<string, unknown> {
|
|
400
|
+
/** Whether this is a subpage trigger (always true). */
|
|
401
|
+
subpageTrigger: boolean;
|
|
402
|
+
/** Whether the target page is active. */
|
|
403
|
+
popupOpen: boolean;
|
|
404
|
+
/** Whether the target page owns keyboard focus. */
|
|
405
|
+
popupFocused: boolean;
|
|
406
|
+
/** Whether the item is highlighted. */
|
|
407
|
+
highlighted: boolean;
|
|
408
|
+
/** Whether the item is disabled. */
|
|
409
|
+
disabled: boolean;
|
|
410
|
+
}
|
|
411
|
+
interface PopupMenuSubpageTriggerProps extends ComponentProps<'div', PopupMenuSubpageTrigger.State> {
|
|
412
|
+
/** Explicit unique identifier for this item in the store. */
|
|
413
|
+
id?: string;
|
|
414
|
+
/** Unique value for this item used for filtering. */
|
|
415
|
+
value?: string;
|
|
416
|
+
/** Additional keywords to match against when filtering. */
|
|
417
|
+
keywords?: string[];
|
|
418
|
+
/** Whether this item is disabled. */
|
|
419
|
+
disabled?: boolean;
|
|
420
|
+
/** Whether to force render this item regardless of filter results. */
|
|
421
|
+
forceMount?: boolean;
|
|
422
|
+
/**
|
|
423
|
+
* Forces this row's relative order during score-based sorting.
|
|
424
|
+
* Lower values appear earlier.
|
|
425
|
+
* @default 0
|
|
426
|
+
*/
|
|
427
|
+
forceOrder?: number;
|
|
428
|
+
/**
|
|
429
|
+
* Overrides this row's computed fuzzy-match score.
|
|
430
|
+
*/
|
|
431
|
+
forceScore?: number;
|
|
432
|
+
/** Target page ID to open when this trigger is selected. */
|
|
433
|
+
targetPageId: string;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* A menu item that pushes a new page in the same popup.
|
|
437
|
+
* Renders a `<div>` element with role="menuitem".
|
|
438
|
+
*/
|
|
439
|
+
declare const PopupMenuSubpageTrigger: React.ForwardRefExoticComponent<Omit<PopupMenuSubpageTrigger.Props, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
440
|
+
declare namespace PopupMenuSubpageTrigger {
|
|
441
|
+
type State = PopupMenuSubpageTriggerState;
|
|
442
|
+
interface Props extends PopupMenuSubpageTriggerProps {
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Library-agnostic result from an async loader.
|
|
448
|
+
* Compatible with TanStack Query, SWR, and custom loaders.
|
|
449
|
+
*/
|
|
450
|
+
type AsyncLoaderSource = 'tanstack-query' | 'swr' | 'vanilla' | 'custom';
|
|
451
|
+
/**
|
|
452
|
+
* Canonical async loader status.
|
|
453
|
+
* - 'idle': no request has been executed yet
|
|
454
|
+
* - 'pending': request in progress and no successful data yet
|
|
455
|
+
* - 'success': last resolved state has data
|
|
456
|
+
* - 'error': last resolved state errored
|
|
457
|
+
*/
|
|
458
|
+
type AsyncLoaderStatus = 'idle' | 'pending' | 'success' | 'error';
|
|
459
|
+
/**
|
|
460
|
+
* Canonical fetch status.
|
|
461
|
+
*/
|
|
462
|
+
type AsyncLoaderFetchStatus = 'idle' | 'fetching' | 'paused';
|
|
463
|
+
/**
|
|
464
|
+
* Loading phase for distinguishing first-load from background revalidation.
|
|
465
|
+
*/
|
|
466
|
+
type AsyncLoaderLoadingPhase = 'none' | 'initial' | 'background';
|
|
467
|
+
interface AsyncLoaderResult<TData, TRaw = unknown> {
|
|
468
|
+
/** The loaded data, undefined while loading or on error */
|
|
469
|
+
data: TData | undefined;
|
|
470
|
+
/** Raw result object returned by the underlying data library */
|
|
471
|
+
raw?: TRaw;
|
|
472
|
+
/** Source data library backing this result */
|
|
473
|
+
source?: AsyncLoaderSource;
|
|
474
|
+
/** Error if the load failed, null otherwise */
|
|
475
|
+
error: Error | null;
|
|
476
|
+
/** Canonical status state */
|
|
477
|
+
status: AsyncLoaderStatus;
|
|
478
|
+
/** Canonical fetch state */
|
|
479
|
+
fetchStatus: AsyncLoaderFetchStatus;
|
|
480
|
+
/** Distinguishes initial load vs background fetch */
|
|
481
|
+
loadingPhase: AsyncLoaderLoadingPhase;
|
|
482
|
+
/** True during the initial loading phase (TanStack-aligned semantics) */
|
|
483
|
+
isLoading: boolean;
|
|
484
|
+
/** Whether any fetch is currently in-flight */
|
|
485
|
+
isFetching: boolean;
|
|
486
|
+
/** Alias of `isLoading` for explicit phase naming */
|
|
487
|
+
isInitialLoading: boolean;
|
|
488
|
+
/** True when background re-fetch is in-flight */
|
|
489
|
+
isRefetching: boolean;
|
|
490
|
+
/** Whether query state is pending */
|
|
491
|
+
isPending: boolean;
|
|
492
|
+
/** Whether query state is successful */
|
|
493
|
+
isSuccess: boolean;
|
|
494
|
+
/** Whether the loader encountered an error */
|
|
495
|
+
isError: boolean;
|
|
496
|
+
/** Whether fetching is paused */
|
|
497
|
+
isPaused: boolean;
|
|
498
|
+
/** Whether data is currently available */
|
|
499
|
+
hasData: boolean;
|
|
500
|
+
/** Whether any fetch has completed at least once */
|
|
501
|
+
hasFetched: boolean;
|
|
502
|
+
/** Optional function to refetch the data */
|
|
503
|
+
refetch?: () => unknown;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Props passed to loader components.
|
|
507
|
+
* The component should call hooks internally and pass the result to children.
|
|
508
|
+
*/
|
|
509
|
+
interface LoaderComponentProps {
|
|
510
|
+
/** Search query (for query-dependent loaders) */
|
|
511
|
+
query: string;
|
|
512
|
+
/** Whether the loader should execute its fetch/query hook */
|
|
513
|
+
enabled?: boolean;
|
|
514
|
+
/** Render function receiving loader state */
|
|
515
|
+
children: (state: AsyncLoaderResult<NodeDef[]>) => React.ReactNode;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Controls query-loader behavior before users type an active query.
|
|
519
|
+
*/
|
|
520
|
+
interface InitialQueryBehavior {
|
|
521
|
+
/**
|
|
522
|
+
* Query value used before user input reaches minQueryLength.
|
|
523
|
+
* Defaults to '' (top/default results).
|
|
524
|
+
* @default ''
|
|
525
|
+
*/
|
|
526
|
+
value?: string;
|
|
527
|
+
/**
|
|
528
|
+
* When the initial query should load.
|
|
529
|
+
* - 'needed': when submenu is explicitly opened or needed for deep-search execution
|
|
530
|
+
* - 'parent-open': eagerly when direct parent opens
|
|
531
|
+
* @default 'needed'
|
|
532
|
+
*/
|
|
533
|
+
loadWhen?: 'needed' | 'parent-open';
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Static loader configuration.
|
|
537
|
+
* Loads data once, then filters client-side.
|
|
538
|
+
*/
|
|
539
|
+
interface StaticLoaderConfig {
|
|
540
|
+
type: 'static';
|
|
541
|
+
/**
|
|
542
|
+
* Component that calls hooks and provides loader state.
|
|
543
|
+
* This component pattern allows hooks to be called legally within React's rules.
|
|
544
|
+
*/
|
|
545
|
+
Loader: React.ComponentType<LoaderComponentProps>;
|
|
546
|
+
/**
|
|
547
|
+
* When to trigger the loader:
|
|
548
|
+
* - 'eager': Load when menu opens (good for deep search)
|
|
549
|
+
* - 'lazy': Load when submenu opens (default)
|
|
550
|
+
* @default 'lazy'
|
|
551
|
+
*/
|
|
552
|
+
loadStrategy?: 'eager' | 'lazy';
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Query-dependent loader configuration.
|
|
556
|
+
* Refetches based on search query - server does the filtering.
|
|
557
|
+
*/
|
|
558
|
+
interface QueryDependentLoaderConfig {
|
|
559
|
+
type: 'query';
|
|
560
|
+
/**
|
|
561
|
+
* Component that calls hooks and provides loader state.
|
|
562
|
+
* Receives the current search query as a prop.
|
|
563
|
+
*/
|
|
564
|
+
Loader: React.ComponentType<LoaderComponentProps>;
|
|
565
|
+
/**
|
|
566
|
+
* Minimum query length before fetching.
|
|
567
|
+
* @default 1
|
|
568
|
+
*/
|
|
569
|
+
minQueryLength?: number;
|
|
570
|
+
/**
|
|
571
|
+
* Defines behavior before user query reaches minQueryLength.
|
|
572
|
+
* - object: executes query loader with the configured initial value (default behavior)
|
|
573
|
+
* - false: disables initial fetch until query reaches minQueryLength
|
|
574
|
+
* @default { value: '', loadWhen: 'needed' }
|
|
575
|
+
*/
|
|
576
|
+
initialQueryBehavior?: InitialQueryBehavior | false;
|
|
577
|
+
/**
|
|
578
|
+
* @deprecated Use `initialQueryBehavior` instead.
|
|
579
|
+
*/
|
|
580
|
+
initialQuery?: string;
|
|
581
|
+
/**
|
|
582
|
+
* When to trigger the loader:
|
|
583
|
+
* - 'eager': Load when root menu opens (good for deep search)
|
|
584
|
+
* - 'lazy': Load when submenu opens (default)
|
|
585
|
+
* @default 'lazy'
|
|
586
|
+
*/
|
|
587
|
+
loadStrategy?: 'eager' | 'lazy';
|
|
588
|
+
/**
|
|
589
|
+
* What to show when query is below minQueryLength.
|
|
590
|
+
* - 'empty': Show nothing
|
|
591
|
+
* - 'placeholder': Show placeholderNodes
|
|
592
|
+
* @default 'empty'
|
|
593
|
+
*/
|
|
594
|
+
belowMinBehavior?: 'empty' | 'placeholder';
|
|
595
|
+
/**
|
|
596
|
+
* Placeholder nodes shown when query is below minQueryLength.
|
|
597
|
+
*/
|
|
598
|
+
placeholderNodes?: NodeDef[];
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Controls how submenu content participates in ancestor deep search results.
|
|
602
|
+
* - `true`: include submenu trigger and descendants
|
|
603
|
+
* - `'trigger-only'`: include submenu trigger only
|
|
604
|
+
* - `false`: exclude submenu trigger and descendants
|
|
605
|
+
*/
|
|
606
|
+
type IncludeInDeepSearch = true | 'trigger-only' | false;
|
|
607
|
+
/**
|
|
608
|
+
* Union of all async loader configurations.
|
|
609
|
+
*/
|
|
610
|
+
type AsyncLoaderConfig = StaticLoaderConfig | QueryDependentLoaderConfig;
|
|
611
|
+
/**
|
|
612
|
+
* Static async nodes configuration for submenus.
|
|
613
|
+
*/
|
|
614
|
+
type StaticAsyncNodesConfig = StaticLoaderConfig;
|
|
615
|
+
/**
|
|
616
|
+
* Query-dependent async nodes configuration for submenus.
|
|
617
|
+
*/
|
|
618
|
+
type QueryAsyncNodesConfig = QueryDependentLoaderConfig;
|
|
619
|
+
/**
|
|
620
|
+
* Async nodes configuration for submenus.
|
|
621
|
+
* Union of static and query-dependent loader configs.
|
|
622
|
+
*/
|
|
623
|
+
type AsyncNodesConfig = StaticAsyncNodesConfig | QueryAsyncNodesConfig;
|
|
624
|
+
/**
|
|
625
|
+
* Async state exposed to submenu render functions.
|
|
626
|
+
*/
|
|
627
|
+
interface AsyncRenderState {
|
|
628
|
+
/** Canonical status state */
|
|
629
|
+
status: AsyncLoaderStatus;
|
|
630
|
+
/** Canonical fetch state */
|
|
631
|
+
fetchStatus: AsyncLoaderFetchStatus;
|
|
632
|
+
/** Distinguishes initial load vs background fetch */
|
|
633
|
+
loadingPhase: AsyncLoaderLoadingPhase;
|
|
634
|
+
/** True during the initial loading phase */
|
|
635
|
+
isLoading: boolean;
|
|
636
|
+
/** Whether any fetch is currently in-flight */
|
|
637
|
+
isFetching: boolean;
|
|
638
|
+
/** Alias of `isLoading` for explicit phase naming */
|
|
639
|
+
isInitialLoading: boolean;
|
|
640
|
+
/** True when background re-fetch is in-flight */
|
|
641
|
+
isRefetching: boolean;
|
|
642
|
+
/** Whether the loader encountered an error */
|
|
643
|
+
isError: boolean;
|
|
644
|
+
/** The error if any */
|
|
645
|
+
error: Error | null;
|
|
646
|
+
/** For query loaders: whether query is below minQueryLength */
|
|
647
|
+
isBelowMinLength?: boolean;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Aggregate async state exposed to DataList children.
|
|
651
|
+
*/
|
|
652
|
+
interface AsyncState {
|
|
653
|
+
/** Any loader is currently in initial loading phase */
|
|
654
|
+
isLoading: boolean;
|
|
655
|
+
/** Any loader is currently fetching */
|
|
656
|
+
isFetching: boolean;
|
|
657
|
+
/** Any loader is in first-load phase */
|
|
658
|
+
isInitialLoading: boolean;
|
|
659
|
+
/** Any loader is in background refetch phase */
|
|
660
|
+
isRefetching: boolean;
|
|
661
|
+
/** All registered loaders are in background refetch phase */
|
|
662
|
+
isAllRefetching: boolean;
|
|
663
|
+
/** Static loaders specifically are loading */
|
|
664
|
+
isStaticLoading: boolean;
|
|
665
|
+
/** Static loaders in first-load phase */
|
|
666
|
+
isStaticInitialLoading: boolean;
|
|
667
|
+
/** Static loaders in background refetch phase */
|
|
668
|
+
isStaticRefetching: boolean;
|
|
669
|
+
/** Query loaders specifically are loading */
|
|
670
|
+
isQueryLoading: boolean;
|
|
671
|
+
/** Query loaders in first-load phase */
|
|
672
|
+
isQueryInitialLoading: boolean;
|
|
673
|
+
/** Query loaders in background refetch phase */
|
|
674
|
+
isQueryRefetching: boolean;
|
|
675
|
+
/** Menus that failed (skipped from results) */
|
|
676
|
+
skippedMenus: Array<{
|
|
677
|
+
id: string;
|
|
678
|
+
reason: 'error';
|
|
679
|
+
}>;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Branch node info passed in breadcrumbs context.
|
|
683
|
+
* Contains the full submenu/subpage definition for maximum flexibility.
|
|
684
|
+
*/
|
|
685
|
+
interface BreadcrumbNode {
|
|
686
|
+
/** The branch node definition */
|
|
687
|
+
node: SubmenuDef | SubpageDef;
|
|
688
|
+
/** The branch node's value */
|
|
689
|
+
value: string;
|
|
690
|
+
/** The branch node's explicit id (if provided) */
|
|
691
|
+
id?: string;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Context passed to the getQualifiedRowId function.
|
|
695
|
+
* Provides all information needed to generate a unique ID for a row.
|
|
696
|
+
*/
|
|
697
|
+
interface GetQualifiedRowIdContext {
|
|
698
|
+
/** The node definition */
|
|
699
|
+
node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef | SubpageDef;
|
|
700
|
+
/** The node's value (node.value) - used for search/filtering and as fallback identifier */
|
|
701
|
+
value: string;
|
|
702
|
+
/** The node's explicit id (node.id) - if provided, treated as globally unique */
|
|
703
|
+
id: string | undefined;
|
|
704
|
+
/** Position in the flattened display list (0-based) */
|
|
705
|
+
index: number;
|
|
706
|
+
/**
|
|
707
|
+
* Breadcrumb nodes from root to parent.
|
|
708
|
+
* Contains full submenu/subpage node definitions for maximum flexibility.
|
|
709
|
+
*/
|
|
710
|
+
breadcrumbs: BreadcrumbNode[];
|
|
711
|
+
/** Whether deep search is currently active (search query meets minLength threshold) */
|
|
712
|
+
isDeepSearching: boolean;
|
|
713
|
+
/** Search context, null if browsing */
|
|
714
|
+
search: {
|
|
715
|
+
query: string;
|
|
716
|
+
score: number;
|
|
717
|
+
} | null;
|
|
718
|
+
/** Whether surfaced via deep search (rendered outside its home menu) */
|
|
719
|
+
isDeepSearchResult: boolean;
|
|
720
|
+
/** Group context, if any */
|
|
721
|
+
group: {
|
|
722
|
+
id: string;
|
|
723
|
+
label?: string;
|
|
724
|
+
} | null;
|
|
725
|
+
/** Radio group context, if any */
|
|
726
|
+
radioGroup: {
|
|
727
|
+
id: string;
|
|
728
|
+
label?: string;
|
|
729
|
+
} | null;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Function that generates a unique qualified ID for a row.
|
|
733
|
+
* Used for React keys, store registration, and DOM id attributes.
|
|
734
|
+
*
|
|
735
|
+
* Default behavior:
|
|
736
|
+
* - If node.id is provided, use it as-is (treat as globally unique)
|
|
737
|
+
* - Otherwise, compute from breadcrumbs + value when deep searching
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* ```ts
|
|
741
|
+
* // Custom implementation
|
|
742
|
+
* const getQualifiedRowId: GetQualifiedRowIdFn = (ctx) => {
|
|
743
|
+
* // Use explicit id if provided
|
|
744
|
+
* if (ctx.id) return ctx.id
|
|
745
|
+
*
|
|
746
|
+
* // Otherwise, build from breadcrumbs + value
|
|
747
|
+
* const path = ctx.breadcrumbs.map(b => b.id ?? slugify(b.value))
|
|
748
|
+
* return [...path, slugify(ctx.value)].join('.')
|
|
749
|
+
* }
|
|
750
|
+
* ```
|
|
751
|
+
*/
|
|
752
|
+
type GetQualifiedRowIdFn = (context: GetQualifiedRowIdContext) => string;
|
|
753
|
+
/**
|
|
754
|
+
* Context passed to item, submenu, and subpage render functions.
|
|
755
|
+
* Provides information about the current rendering context (search, breadcrumbs, state).
|
|
756
|
+
*/
|
|
757
|
+
interface RowRenderContext {
|
|
758
|
+
/**
|
|
759
|
+
* Search context - the query in the menu where this row is being rendered.
|
|
760
|
+
* `null` if no active search (browsing mode).
|
|
761
|
+
*/
|
|
762
|
+
search: {
|
|
763
|
+
/** Current search query */
|
|
764
|
+
query: string;
|
|
765
|
+
/** Match score for this row (higher = better match). */
|
|
766
|
+
score: number;
|
|
767
|
+
} | null;
|
|
768
|
+
/**
|
|
769
|
+
* Full path of branch nodes from root to this row's parent.
|
|
770
|
+
* Contains the full submenu/subpage node definitions for maximum flexibility.
|
|
771
|
+
* Empty array [] for items directly in root menu.
|
|
772
|
+
*/
|
|
773
|
+
breadcrumbs: BreadcrumbNode[];
|
|
774
|
+
/**
|
|
775
|
+
* True if this row is being rendered outside its "home" menu
|
|
776
|
+
* (surfaced via deep search from an ancestor menu).
|
|
777
|
+
*/
|
|
778
|
+
isDeepSearchResult: boolean;
|
|
779
|
+
/** Whether this row is currently highlighted/focused */
|
|
780
|
+
highlighted: boolean;
|
|
781
|
+
/** Whether this row is disabled */
|
|
782
|
+
disabled: boolean;
|
|
783
|
+
/**
|
|
784
|
+
* The group this item belongs to, if any.
|
|
785
|
+
* `null` if the item is not inside a group.
|
|
786
|
+
*/
|
|
787
|
+
group: {
|
|
788
|
+
id: string;
|
|
789
|
+
label?: string;
|
|
790
|
+
} | null;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Props to spread onto the Item component.
|
|
794
|
+
* Derived from PopupMenuItemProps.
|
|
795
|
+
*/
|
|
796
|
+
type ItemRenderProps = {
|
|
797
|
+
/**
|
|
798
|
+
* Qualified unique ID for the item.
|
|
799
|
+
* Must be passed to the rendered component for navigation to work.
|
|
800
|
+
* This is the computed qualified ID (includes breadcrumb path for deep search results).
|
|
801
|
+
*/
|
|
802
|
+
id: string;
|
|
803
|
+
/**
|
|
804
|
+
* The original value from the node definition.
|
|
805
|
+
* Use this for display, search matching, or any logic that needs the raw value.
|
|
806
|
+
*/
|
|
807
|
+
value: string;
|
|
808
|
+
} & Required<Pick<PopupMenuItemProps, 'disabled'>> & Pick<PopupMenuItemProps, 'closeOnClick' | 'onSelect' | 'shortcut' | 'forceOrder' | 'forceScore'>;
|
|
809
|
+
/**
|
|
810
|
+
* Parameters passed to item render functions.
|
|
811
|
+
*/
|
|
812
|
+
interface ItemRenderParams {
|
|
813
|
+
/** Props to spread onto the Item component */
|
|
814
|
+
props: ItemRenderProps;
|
|
815
|
+
/** Context for conditional rendering (includes props values for convenience) */
|
|
816
|
+
context: RowRenderContext & {
|
|
817
|
+
/** The node's value (ItemDef.value) */
|
|
818
|
+
value: string;
|
|
819
|
+
disabled: boolean;
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Props to spread onto the RadioItem component.
|
|
824
|
+
* Derived from PopupMenuRadioItemProps.
|
|
825
|
+
*/
|
|
826
|
+
type RadioItemRenderProps = {
|
|
827
|
+
/**
|
|
828
|
+
* Qualified unique ID for the radio item.
|
|
829
|
+
* Must be passed to the rendered component for navigation to work.
|
|
830
|
+
*/
|
|
831
|
+
id: string;
|
|
832
|
+
} & Required<Pick<PopupMenuRadioItemProps, 'value' | 'disabled'>> & Pick<PopupMenuRadioItemProps, 'closeOnClick' | 'onSelect' | 'shortcut' | 'forceOrder' | 'forceScore'>;
|
|
833
|
+
/**
|
|
834
|
+
* Parameters passed to radio item render functions.
|
|
835
|
+
*/
|
|
836
|
+
interface RadioItemRenderParams {
|
|
837
|
+
/** Props to spread onto the RadioItem component */
|
|
838
|
+
props: RadioItemRenderProps;
|
|
839
|
+
/** Context for conditional rendering (includes props values for convenience) */
|
|
840
|
+
context: RowRenderContext & {
|
|
841
|
+
/** The node's value (RadioItemDef.value) */
|
|
842
|
+
value: string;
|
|
843
|
+
disabled: boolean;
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Props to spread onto the SubmenuTrigger component.
|
|
848
|
+
* Derived from PopupMenuSubmenuTriggerProps.
|
|
849
|
+
*/
|
|
850
|
+
type SubmenuRenderProps = {
|
|
851
|
+
/**
|
|
852
|
+
* Qualified unique ID for the submenu trigger.
|
|
853
|
+
* Must be passed to the rendered component for navigation to work.
|
|
854
|
+
*/
|
|
855
|
+
id: string;
|
|
856
|
+
/**
|
|
857
|
+
* The original value from the node definition.
|
|
858
|
+
*/
|
|
859
|
+
value: string;
|
|
860
|
+
} & Required<Pick<PopupMenuSubmenuTriggerProps, 'disabled'>> & Pick<PopupMenuSubmenuTriggerProps, 'forceOrder' | 'forceScore'>;
|
|
861
|
+
/**
|
|
862
|
+
* Parameters passed to submenu render functions.
|
|
863
|
+
* Includes context plus the submenu's child nodes and render function.
|
|
864
|
+
*/
|
|
865
|
+
interface SubmenuRenderParams {
|
|
866
|
+
/** Props to spread onto the SubmenuTrigger */
|
|
867
|
+
props: SubmenuRenderProps;
|
|
868
|
+
/** Context for conditional rendering (includes props values for convenience) */
|
|
869
|
+
context: RowRenderContext & {
|
|
870
|
+
/** The node's value (SubmenuDef.value) */
|
|
871
|
+
value: string;
|
|
872
|
+
disabled: boolean;
|
|
873
|
+
/** Async loading state (if asyncNodes configured) */
|
|
874
|
+
async?: AsyncRenderState;
|
|
875
|
+
};
|
|
876
|
+
/**
|
|
877
|
+
* The submenu's static child node definitions.
|
|
878
|
+
* Does NOT include async results - use `asyncContent` for that.
|
|
879
|
+
*/
|
|
880
|
+
nodes: NodeDef[];
|
|
881
|
+
/**
|
|
882
|
+
* Async content configuration for this submenu.
|
|
883
|
+
* Pass this to the submenu's DataSurface to enable async loading
|
|
884
|
+
* with the submenu's own search query (independent of parent search).
|
|
885
|
+
*/
|
|
886
|
+
asyncContent?: AsyncNodesConfig;
|
|
887
|
+
/**
|
|
888
|
+
* Function to render a child node.
|
|
889
|
+
* Call this for each node in the submenu's list.
|
|
890
|
+
*/
|
|
891
|
+
renderNode: (node: NodeDef) => React.ReactNode;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Props to spread onto the SubpageTrigger component.
|
|
895
|
+
* Derived from PopupMenuSubpageTriggerProps.
|
|
896
|
+
*/
|
|
897
|
+
type SubpageTriggerRenderProps = {
|
|
898
|
+
/**
|
|
899
|
+
* Qualified unique ID for the subpage trigger.
|
|
900
|
+
* Must be passed to the rendered component for navigation to work.
|
|
901
|
+
*/
|
|
902
|
+
id: string;
|
|
903
|
+
/**
|
|
904
|
+
* The original value from the node definition.
|
|
905
|
+
*/
|
|
906
|
+
value: string;
|
|
907
|
+
/**
|
|
908
|
+
* Computed page ID for the associated Subpage content.
|
|
909
|
+
* Must be passed to `targetPageId` on SubpageTrigger.
|
|
910
|
+
*/
|
|
911
|
+
targetPageId: string;
|
|
912
|
+
} & Required<Pick<PopupMenuSubpageTriggerProps, 'disabled'>>;
|
|
913
|
+
/**
|
|
914
|
+
* Parameters passed to subpage trigger render functions.
|
|
915
|
+
*/
|
|
916
|
+
interface SubpageTriggerRenderParams {
|
|
917
|
+
/** Props to spread onto the SubpageTrigger */
|
|
918
|
+
props: SubpageTriggerRenderProps;
|
|
919
|
+
/** Context for conditional rendering (includes props values for convenience) */
|
|
920
|
+
context: RowRenderContext & {
|
|
921
|
+
/** The node's value (SubpageDef.value) */
|
|
922
|
+
value: string;
|
|
923
|
+
disabled: boolean;
|
|
924
|
+
/** Async loading state (if asyncNodes configured) */
|
|
925
|
+
async?: AsyncRenderState;
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Parameters passed to subpage content render functions.
|
|
930
|
+
* The returned JSX should include a `<PopupMenu.Subpage pageId={pageId}>` wrapper.
|
|
931
|
+
*/
|
|
932
|
+
interface SubpageContentRenderParams {
|
|
933
|
+
/** Computed page ID for this subpage */
|
|
934
|
+
pageId: string;
|
|
935
|
+
/** Context for conditional rendering */
|
|
936
|
+
context: RowRenderContext & {
|
|
937
|
+
/** The node's value (SubpageDef.value) */
|
|
938
|
+
value: string;
|
|
939
|
+
disabled: boolean;
|
|
940
|
+
/** Async loading state (if asyncNodes configured) */
|
|
941
|
+
async?: AsyncRenderState;
|
|
942
|
+
};
|
|
943
|
+
/**
|
|
944
|
+
* The subpage's static child node definitions.
|
|
945
|
+
* Does NOT include async results - use `asyncContent` for that.
|
|
946
|
+
*/
|
|
947
|
+
nodes: NodeDef[];
|
|
948
|
+
/**
|
|
949
|
+
* Async content configuration for this subpage.
|
|
950
|
+
* Pass this to the subpage's DataSurface to enable async loading
|
|
951
|
+
* with the subpage's own search query (independent of parent search).
|
|
952
|
+
*/
|
|
953
|
+
asyncContent?: AsyncNodesConfig;
|
|
954
|
+
/**
|
|
955
|
+
* Function to render a child node.
|
|
956
|
+
* Call this for each node in the subpage's list.
|
|
957
|
+
*/
|
|
958
|
+
renderNode: (node: NodeDef) => React.ReactNode;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Context passed to group render functions.
|
|
962
|
+
* Contains information about the group's state during search.
|
|
963
|
+
*/
|
|
964
|
+
interface GroupRenderContext {
|
|
965
|
+
/**
|
|
966
|
+
* Search context with the best match score among items in this group.
|
|
967
|
+
* `null` if no active search (browsing mode).
|
|
968
|
+
*/
|
|
969
|
+
search: {
|
|
970
|
+
/** Current search query */
|
|
971
|
+
query: string;
|
|
972
|
+
/** Best match score among items in this group (higher = better match). */
|
|
973
|
+
bestScore: number;
|
|
974
|
+
} | null;
|
|
975
|
+
/** Number of matching items in this group */
|
|
976
|
+
matchCount: number;
|
|
977
|
+
/**
|
|
978
|
+
* Breadcrumb nodes if this group is from a surfaced submenu.
|
|
979
|
+
* Empty array [] for groups in the root menu.
|
|
980
|
+
*/
|
|
981
|
+
breadcrumbs: BreadcrumbNode[];
|
|
982
|
+
/** Whether this group is from deep search (surfaced from a submenu) */
|
|
983
|
+
isDeepSearchResult: boolean;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Parameters passed to group render functions.
|
|
987
|
+
*/
|
|
988
|
+
interface GroupRenderParams {
|
|
989
|
+
/** Props (empty for groups, but consistent structure) */
|
|
990
|
+
props: Record<string, never>;
|
|
991
|
+
/** Context for conditional rendering (includes label for convenience) */
|
|
992
|
+
context: GroupRenderContext & {
|
|
993
|
+
/** The group's label */
|
|
994
|
+
label?: string;
|
|
995
|
+
};
|
|
996
|
+
/** Pre-rendered matching children */
|
|
997
|
+
children: React.ReactNode;
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Props to spread onto the CheckboxItem component.
|
|
1001
|
+
* Derived from PopupMenuCheckboxItemProps.
|
|
1002
|
+
*/
|
|
1003
|
+
type CheckboxItemRenderProps = {
|
|
1004
|
+
/**
|
|
1005
|
+
* Qualified unique ID for the checkbox item.
|
|
1006
|
+
* Must be passed to the rendered component for navigation to work.
|
|
1007
|
+
*/
|
|
1008
|
+
id: string;
|
|
1009
|
+
/**
|
|
1010
|
+
* The original value from the node definition.
|
|
1011
|
+
*/
|
|
1012
|
+
value: string;
|
|
1013
|
+
} & Required<Pick<PopupMenuCheckboxItemProps, 'disabled'>> & Pick<PopupMenuCheckboxItemProps, 'checked' | 'onCheckedChange' | 'closeOnClick' | 'forceOrder' | 'forceScore'>;
|
|
1014
|
+
/**
|
|
1015
|
+
* Parameters passed to checkbox item render functions.
|
|
1016
|
+
*/
|
|
1017
|
+
interface CheckboxItemRenderParams {
|
|
1018
|
+
/** Props to spread onto the CheckboxItem component */
|
|
1019
|
+
props: CheckboxItemRenderProps;
|
|
1020
|
+
/** Context for conditional rendering (includes props values for convenience) */
|
|
1021
|
+
context: RowRenderContext & {
|
|
1022
|
+
/** The node's value (CheckboxItemDef.value) */
|
|
1023
|
+
value: string;
|
|
1024
|
+
checked?: boolean;
|
|
1025
|
+
disabled: boolean;
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Props to spread onto the RadioGroup component.
|
|
1030
|
+
* Derived from PopupMenuRadioGroupProps.
|
|
1031
|
+
*/
|
|
1032
|
+
type RadioGroupRenderProps = Required<Pick<PopupMenuRadioGroupProps, 'disabled'>> & Pick<PopupMenuRadioGroupProps, 'value' | 'onValueChange'>;
|
|
1033
|
+
/**
|
|
1034
|
+
* Parameters passed to radio group render functions.
|
|
1035
|
+
*/
|
|
1036
|
+
interface RadioGroupRenderParams {
|
|
1037
|
+
/** Props to spread onto the RadioGroup component */
|
|
1038
|
+
props: RadioGroupRenderProps;
|
|
1039
|
+
/** Context for conditional rendering */
|
|
1040
|
+
context: GroupRenderContext & {
|
|
1041
|
+
/** The radio group's label */
|
|
1042
|
+
label?: string;
|
|
1043
|
+
/** Current selected value */
|
|
1044
|
+
value?: string;
|
|
1045
|
+
/** Whether the radio group is disabled */
|
|
1046
|
+
disabled: boolean;
|
|
1047
|
+
};
|
|
1048
|
+
/** Pre-rendered radio items */
|
|
1049
|
+
children: React.ReactNode;
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Base properties shared by all node types.
|
|
1053
|
+
*/
|
|
1054
|
+
interface BaseNodeDef {
|
|
1055
|
+
/**
|
|
1056
|
+
* Unique identifier for this node.
|
|
1057
|
+
* If not provided, a composite ID is generated from the `value` and breadcrumbs
|
|
1058
|
+
* using the `getItemId` function.
|
|
1059
|
+
*/
|
|
1060
|
+
id?: string;
|
|
1061
|
+
/** Whether this node is hidden */
|
|
1062
|
+
hidden?: boolean;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Item node definition.
|
|
1066
|
+
* Represents a selectable menu item.
|
|
1067
|
+
* Props derived from PopupMenuItemProps.
|
|
1068
|
+
*/
|
|
1069
|
+
interface ItemDef extends BaseNodeDef, Required<Pick<PopupMenuItemProps, 'value'>>, Pick<PopupMenuItemProps, 'keywords' | 'disabled' | 'onSelect' | 'closeOnClick' | 'shortcut' | 'forceOrder' | 'forceScore'> {
|
|
1070
|
+
kind: 'item';
|
|
1071
|
+
/**
|
|
1072
|
+
* Render function for this item row.
|
|
1073
|
+
* Returns the JSX for the item.
|
|
1074
|
+
*/
|
|
1075
|
+
render: (params: ItemRenderParams) => React.ReactNode;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Radio item node definition.
|
|
1079
|
+
* Represents a selectable radio menu item for use within RadioGroupDef.
|
|
1080
|
+
* Props derived from PopupMenuRadioItemProps.
|
|
1081
|
+
*/
|
|
1082
|
+
interface RadioItemDef extends BaseNodeDef, Required<Pick<PopupMenuRadioItemProps, 'value'>>, Pick<PopupMenuRadioItemProps, 'keywords' | 'disabled' | 'onSelect' | 'closeOnClick' | 'shortcut' | 'forceOrder' | 'forceScore'> {
|
|
1083
|
+
kind: 'radio-item';
|
|
1084
|
+
/**
|
|
1085
|
+
* Render function for this radio item row.
|
|
1086
|
+
* Returns the JSX for the radio item.
|
|
1087
|
+
*/
|
|
1088
|
+
render: (params: RadioItemRenderParams) => React.ReactNode;
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Checkbox item node definition.
|
|
1092
|
+
* Represents a toggleable checkbox menu item.
|
|
1093
|
+
* Props derived from PopupMenuCheckboxItemProps.
|
|
1094
|
+
*/
|
|
1095
|
+
interface CheckboxItemDef extends BaseNodeDef, Pick<PopupMenuCheckboxItemProps, 'keywords' | 'disabled' | 'checked' | 'onCheckedChange' | 'closeOnClick' | 'forceOrder' | 'forceScore'> {
|
|
1096
|
+
kind: 'checkbox-item';
|
|
1097
|
+
/**
|
|
1098
|
+
* Primary identifier and search text for this checkbox item.
|
|
1099
|
+
* Used for search matching and as the default identifier.
|
|
1100
|
+
*/
|
|
1101
|
+
value: string;
|
|
1102
|
+
/**
|
|
1103
|
+
* Render function for this checkbox item row.
|
|
1104
|
+
* Returns the JSX for the checkbox item.
|
|
1105
|
+
*/
|
|
1106
|
+
render: (params: CheckboxItemRenderParams) => React.ReactNode;
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* Submenu node definition.
|
|
1110
|
+
* Represents a submenu trigger that opens a nested menu.
|
|
1111
|
+
* Props derived from PopupMenuSubmenuTriggerProps.
|
|
1112
|
+
*/
|
|
1113
|
+
interface SubmenuDef extends BaseNodeDef, Required<Pick<PopupMenuSubmenuTriggerProps, 'value'>>, Pick<PopupMenuSubmenuTriggerProps, 'keywords' | 'disabled' | 'forceOrder' | 'forceScore'> {
|
|
1114
|
+
kind: 'submenu';
|
|
1115
|
+
/** Static child nodes */
|
|
1116
|
+
nodes?: NodeDef[];
|
|
1117
|
+
/**
|
|
1118
|
+
* Async child nodes configuration.
|
|
1119
|
+
* When provided, the Loader component will be rendered to fetch async data.
|
|
1120
|
+
* Async nodes are merged with static nodes.
|
|
1121
|
+
*/
|
|
1122
|
+
asyncNodes?: AsyncNodesConfig;
|
|
1123
|
+
/**
|
|
1124
|
+
* Whether to include this submenu's descendants in deep search.
|
|
1125
|
+
* @default true
|
|
1126
|
+
*/
|
|
1127
|
+
deepSearch?: boolean;
|
|
1128
|
+
/**
|
|
1129
|
+
* Whether this submenu is included in ancestor deep search results.
|
|
1130
|
+
* - `true`: include submenu trigger and descendants
|
|
1131
|
+
* - `'trigger-only'`: include submenu trigger only
|
|
1132
|
+
* - `false`: exclude submenu trigger and descendants
|
|
1133
|
+
* @default true
|
|
1134
|
+
*/
|
|
1135
|
+
includeInDeepSearch?: IncludeInDeepSearch;
|
|
1136
|
+
/**
|
|
1137
|
+
* Render function for the entire submenu structure.
|
|
1138
|
+
* Should return the complete submenu: trigger, portal, positioner, popup, surface, list.
|
|
1139
|
+
*/
|
|
1140
|
+
render: (params: SubmenuRenderParams) => React.ReactNode;
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Subpage node definition.
|
|
1144
|
+
* Represents a trigger row that opens a page in the same popup.
|
|
1145
|
+
* Props derived from PopupMenuSubpageTriggerProps.
|
|
1146
|
+
*/
|
|
1147
|
+
interface SubpageDef extends BaseNodeDef, Required<Pick<PopupMenuSubpageTriggerProps, 'value'>>, Pick<PopupMenuSubpageTriggerProps, 'keywords' | 'disabled' | 'forceOrder' | 'forceScore'> {
|
|
1148
|
+
kind: 'subpage';
|
|
1149
|
+
/**
|
|
1150
|
+
* Optional explicit page ID for this subpage.
|
|
1151
|
+
* If omitted, a deterministic page ID is generated from id/value + breadcrumbs.
|
|
1152
|
+
*/
|
|
1153
|
+
pageId?: string;
|
|
1154
|
+
/** Static child nodes */
|
|
1155
|
+
nodes?: NodeDef[];
|
|
1156
|
+
/**
|
|
1157
|
+
* Async child nodes configuration.
|
|
1158
|
+
* When provided, the Loader component will be rendered to fetch async data.
|
|
1159
|
+
* Async nodes are merged with static nodes.
|
|
1160
|
+
*/
|
|
1161
|
+
asyncNodes?: AsyncNodesConfig;
|
|
1162
|
+
/**
|
|
1163
|
+
* Whether to include this subpage's descendants in deep search.
|
|
1164
|
+
* @default true
|
|
1165
|
+
*/
|
|
1166
|
+
deepSearch?: boolean;
|
|
1167
|
+
/**
|
|
1168
|
+
* Whether this subpage is included in ancestor deep search results.
|
|
1169
|
+
* - `true`: include subpage trigger and descendants
|
|
1170
|
+
* - `'trigger-only'`: include subpage trigger only
|
|
1171
|
+
* - `false`: exclude subpage trigger and descendants
|
|
1172
|
+
* @default true
|
|
1173
|
+
*/
|
|
1174
|
+
includeInDeepSearch?: IncludeInDeepSearch;
|
|
1175
|
+
/**
|
|
1176
|
+
* Render function for the trigger row.
|
|
1177
|
+
* Should return a `SubpageTrigger`.
|
|
1178
|
+
*/
|
|
1179
|
+
renderTrigger: (params: SubpageTriggerRenderParams) => React.ReactNode;
|
|
1180
|
+
/**
|
|
1181
|
+
* Render function for the subpage content.
|
|
1182
|
+
* Should return a `Subpage` rendered alongside the root Surface in Popup.
|
|
1183
|
+
*/
|
|
1184
|
+
renderContent: (params: SubpageContentRenderParams) => React.ReactNode;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Render params for separator nodes.
|
|
1188
|
+
*/
|
|
1189
|
+
interface SeparatorRenderParams {
|
|
1190
|
+
/** Props to spread on the separator element */
|
|
1191
|
+
props: {
|
|
1192
|
+
/** Unique identifier */
|
|
1193
|
+
id?: string;
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Separator node definition.
|
|
1198
|
+
* Represents a visual separator between items.
|
|
1199
|
+
*/
|
|
1200
|
+
interface SeparatorDef {
|
|
1201
|
+
kind: 'separator';
|
|
1202
|
+
/** Optional identifier */
|
|
1203
|
+
id?: string;
|
|
1204
|
+
/** Optional render function for custom separator rendering */
|
|
1205
|
+
render?: (params: SeparatorRenderParams) => React.ReactNode;
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Group node definition.
|
|
1209
|
+
* Represents a group of items with an optional label.
|
|
1210
|
+
*/
|
|
1211
|
+
interface GroupDef {
|
|
1212
|
+
kind: 'group';
|
|
1213
|
+
/** Unique identifier for this group */
|
|
1214
|
+
id: string;
|
|
1215
|
+
/** Optional group heading/label */
|
|
1216
|
+
label?: string;
|
|
1217
|
+
/** Child nodes in this group */
|
|
1218
|
+
nodes: NodeDef[];
|
|
1219
|
+
/** Optional render function for the group container */
|
|
1220
|
+
render?: (params: GroupRenderParams) => React.ReactNode;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Radio group node definition.
|
|
1224
|
+
* Represents a group of radio items where only one can be selected.
|
|
1225
|
+
* Props derived from PopupMenuRadioGroupProps.
|
|
1226
|
+
*/
|
|
1227
|
+
interface RadioGroupDef extends Pick<PopupMenuRadioGroupProps, 'value' | 'onValueChange' | 'disabled'> {
|
|
1228
|
+
kind: 'radio-group';
|
|
1229
|
+
/** Unique identifier for this radio group */
|
|
1230
|
+
id: string;
|
|
1231
|
+
/** Optional group heading/label */
|
|
1232
|
+
label?: string;
|
|
1233
|
+
/** Whether the radio group is hidden */
|
|
1234
|
+
hidden?: boolean;
|
|
1235
|
+
/** Child nodes in this radio group - must be RadioItemDef nodes */
|
|
1236
|
+
nodes: RadioItemDef[];
|
|
1237
|
+
/** Optional render function for the radio group container */
|
|
1238
|
+
render?: (params: RadioGroupRenderParams) => React.ReactNode;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Helper function to create a radio group definition with proper typing.
|
|
1242
|
+
*/
|
|
1243
|
+
declare function defineRadioGroup(def: RadioGroupDef): RadioGroupDef;
|
|
1244
|
+
/**
|
|
1245
|
+
* Union of all node definition types.
|
|
1246
|
+
*/
|
|
1247
|
+
type NodeDef = ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef | SubpageDef | SeparatorDef | GroupDef | RadioGroupDef;
|
|
1248
|
+
/**
|
|
1249
|
+
* A node with its search score and breadcrumb path.
|
|
1250
|
+
* Used internally during filtering and scoring.
|
|
1251
|
+
*/
|
|
1252
|
+
interface ScoredNode {
|
|
1253
|
+
/** The original node definition */
|
|
1254
|
+
node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef | SubpageDef;
|
|
1255
|
+
/** Search match score (higher = better match). */
|
|
1256
|
+
score: number;
|
|
1257
|
+
/**
|
|
1258
|
+
* Breadcrumb nodes leading to this node.
|
|
1259
|
+
* Contains the full submenu definitions for maximum flexibility.
|
|
1260
|
+
*/
|
|
1261
|
+
breadcrumbs: BreadcrumbNode[];
|
|
1262
|
+
/** The group this node belongs to, if any */
|
|
1263
|
+
group: {
|
|
1264
|
+
id: string;
|
|
1265
|
+
label?: string;
|
|
1266
|
+
groupDef: GroupDef;
|
|
1267
|
+
} | null;
|
|
1268
|
+
/** The radio group this node belongs to, if any */
|
|
1269
|
+
radioGroup: {
|
|
1270
|
+
id: string;
|
|
1271
|
+
label?: string;
|
|
1272
|
+
radioGroupDef: RadioGroupDef;
|
|
1273
|
+
} | null;
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* A row node ready for display with its render context.
|
|
1277
|
+
* Used for items, radio items, checkbox items, and submenu triggers.
|
|
1278
|
+
*/
|
|
1279
|
+
interface DisplayRowNode {
|
|
1280
|
+
/** The original node definition */
|
|
1281
|
+
node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef | SubpageDef;
|
|
1282
|
+
/** Pre-computed render context for this node */
|
|
1283
|
+
context: RowRenderContext;
|
|
1284
|
+
/** Radio group this node belongs to, if rendering inside one */
|
|
1285
|
+
radioGroup?: {
|
|
1286
|
+
id: string;
|
|
1287
|
+
label?: string;
|
|
1288
|
+
};
|
|
1289
|
+
/**
|
|
1290
|
+
* Computed composite ID for this node.
|
|
1291
|
+
* Includes breadcrumb path for deep search results (e.g., "status.in-progress").
|
|
1292
|
+
* Set after filtering via `computeItemIds`.
|
|
1293
|
+
*/
|
|
1294
|
+
compositeId?: string;
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* A subpage content node ready for display with its render context.
|
|
1298
|
+
* Used by DataSubpages to render subpage content alongside the root Surface.
|
|
1299
|
+
*/
|
|
1300
|
+
interface DisplaySubpageNode {
|
|
1301
|
+
/** The original subpage definition */
|
|
1302
|
+
node: SubpageDef;
|
|
1303
|
+
/** Pre-computed render context for this subpage trigger/content */
|
|
1304
|
+
context: RowRenderContext;
|
|
1305
|
+
/** Computed page ID for this subpage */
|
|
1306
|
+
pageId: string;
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* A group node ready for display with its render context.
|
|
1310
|
+
* Contains the group definition and its matching items.
|
|
1311
|
+
*/
|
|
1312
|
+
interface DisplayGroupNode {
|
|
1313
|
+
kind: 'group';
|
|
1314
|
+
/** The group definition */
|
|
1315
|
+
group: GroupDef;
|
|
1316
|
+
/** Pre-computed render context for this group */
|
|
1317
|
+
context: GroupRenderContext;
|
|
1318
|
+
/** Display nodes for items within this group */
|
|
1319
|
+
items: DisplayRowNode[];
|
|
1320
|
+
/** Best match score among items in this group */
|
|
1321
|
+
bestScore: number;
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* A radio group node ready for display with its render context.
|
|
1325
|
+
* Contains the radio group definition and its items.
|
|
1326
|
+
*/
|
|
1327
|
+
interface DisplayRadioGroupNode {
|
|
1328
|
+
kind: 'radio-group';
|
|
1329
|
+
/** The radio group definition */
|
|
1330
|
+
radioGroup: RadioGroupDef;
|
|
1331
|
+
/** Pre-computed render context for this radio group */
|
|
1332
|
+
context: GroupRenderContext;
|
|
1333
|
+
/** Display nodes for items within this radio group */
|
|
1334
|
+
items: DisplayRowNode[];
|
|
1335
|
+
/** Best match score among items in this radio group */
|
|
1336
|
+
bestScore: number;
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* A separator node ready for display.
|
|
1340
|
+
*/
|
|
1341
|
+
interface DisplaySeparatorNode {
|
|
1342
|
+
kind: 'separator';
|
|
1343
|
+
/** The separator definition */
|
|
1344
|
+
separator: SeparatorDef;
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Union of all display node types.
|
|
1348
|
+
* Can be a row node (item/submenu/subpage), group node, radio group node, or separator.
|
|
1349
|
+
*/
|
|
1350
|
+
type DisplayNode = DisplayRowNode | DisplayGroupNode | DisplayRadioGroupNode | DisplaySeparatorNode;
|
|
1351
|
+
/**
|
|
1352
|
+
* Type guard for DisplayGroupNode.
|
|
1353
|
+
*/
|
|
1354
|
+
declare function isDisplayGroupNode(node: DisplayNode): node is DisplayGroupNode;
|
|
1355
|
+
/**
|
|
1356
|
+
* Type guard for DisplayRadioGroupNode.
|
|
1357
|
+
*/
|
|
1358
|
+
declare function isDisplayRadioGroupNode(node: DisplayNode): node is DisplayRadioGroupNode;
|
|
1359
|
+
/**
|
|
1360
|
+
* Type guard for DisplaySeparatorNode.
|
|
1361
|
+
*/
|
|
1362
|
+
declare function isDisplaySeparatorNode(node: DisplayNode): node is DisplaySeparatorNode;
|
|
1363
|
+
/**
|
|
1364
|
+
* Type guard for DisplayRowNode (items, checkbox items, submenus, subpages).
|
|
1365
|
+
*/
|
|
1366
|
+
declare function isDisplayRowNode(node: DisplayNode): node is DisplayRowNode;
|
|
1367
|
+
/**
|
|
1368
|
+
* Defines how groups behave during deep search.
|
|
1369
|
+
* - 'flatten': Groups become invisible, items shown in flat list by score.
|
|
1370
|
+
* - 'preserve': Groups are shown as containers with their matching items.
|
|
1371
|
+
* Note: Radio groups are ALWAYS preserved regardless of this setting.
|
|
1372
|
+
*/
|
|
1373
|
+
type GroupBehavior = 'flatten' | 'preserve';
|
|
1374
|
+
/**
|
|
1375
|
+
* Defines how radio groups behave during deep search.
|
|
1376
|
+
* - 'flatten': Radio group items are shown individually in the flat list (not recommended).
|
|
1377
|
+
* - 'preserve': Radio group is shown with only matching items visible.
|
|
1378
|
+
* - 'preserve-show-all': Radio group is shown with ALL items visible when any item matches.
|
|
1379
|
+
* This is useful when you want users to see all options in a radio group.
|
|
1380
|
+
*/
|
|
1381
|
+
type RadioGroupBehavior = 'flatten' | 'preserve' | 'preserve-show-all';
|
|
1382
|
+
/**
|
|
1383
|
+
* Defines how deep-search async results are revealed.
|
|
1384
|
+
* - 'stream': show available results immediately and append new async batches as they resolve.
|
|
1385
|
+
* - 'block': hide all deep-search rows until every participating async loader resolves.
|
|
1386
|
+
*/
|
|
1387
|
+
type AsyncResultBehavior = 'stream' | 'block';
|
|
1388
|
+
/**
|
|
1389
|
+
* Configuration for deep search behavior.
|
|
1390
|
+
*/
|
|
1391
|
+
interface DeepSearchConfig {
|
|
1392
|
+
/** Whether deep search is enabled */
|
|
1393
|
+
enabled?: boolean;
|
|
1394
|
+
/** Minimum query length before deep search activates */
|
|
1395
|
+
minLength?: number;
|
|
1396
|
+
/**
|
|
1397
|
+
* How groups behave during search results.
|
|
1398
|
+
* Only affects search mode - groups are always shown in browse mode.
|
|
1399
|
+
* Note: Radio groups have their own behavior controlled by radioGroupSearchBehavior.
|
|
1400
|
+
* @default 'preserve'
|
|
1401
|
+
*/
|
|
1402
|
+
groupSearchBehavior?: GroupBehavior;
|
|
1403
|
+
/**
|
|
1404
|
+
* How radio groups behave during search results.
|
|
1405
|
+
* - 'flatten': Radio items shown individually (not recommended).
|
|
1406
|
+
* - 'preserve': Only matching radio items are shown (default).
|
|
1407
|
+
* - 'preserve-show-all': All radio items are shown when any item matches.
|
|
1408
|
+
* @default 'preserve'
|
|
1409
|
+
*/
|
|
1410
|
+
radioGroupSearchBehavior?: RadioGroupBehavior;
|
|
1411
|
+
/**
|
|
1412
|
+
* Whether to sort groups by their best-matching item's score.
|
|
1413
|
+
* Only applies when groupSearchBehavior: 'preserve'.
|
|
1414
|
+
* @default true
|
|
1415
|
+
*/
|
|
1416
|
+
sortGroups?: boolean;
|
|
1417
|
+
/**
|
|
1418
|
+
* How async deep-search results are revealed.
|
|
1419
|
+
* - 'stream': emit available results immediately, append later async batches (default)
|
|
1420
|
+
* - 'block': show loading state only until all loaders resolve, then render once
|
|
1421
|
+
* @default 'stream'
|
|
1422
|
+
*/
|
|
1423
|
+
asyncResultBehavior?: AsyncResultBehavior;
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* Props for the DataSurface component.
|
|
1427
|
+
*/
|
|
1428
|
+
interface DataSurfaceProps {
|
|
1429
|
+
/** The menu content (node definitions with render functions) */
|
|
1430
|
+
content?: NodeDef[];
|
|
1431
|
+
/**
|
|
1432
|
+
* Async content configuration for root-level async loading.
|
|
1433
|
+
* When provided, the Loader component will be rendered to fetch async data.
|
|
1434
|
+
* Async content is merged with static content.
|
|
1435
|
+
*/
|
|
1436
|
+
asyncContent?: AsyncLoaderConfig;
|
|
1437
|
+
/** Deep search configuration */
|
|
1438
|
+
deepSearch?: DeepSearchConfig | boolean;
|
|
1439
|
+
/**
|
|
1440
|
+
* Default inclusion mode for descendant branch nodes in deep search results.
|
|
1441
|
+
* Submenus/subpages can override via `includeInDeepSearch`.
|
|
1442
|
+
* @default true
|
|
1443
|
+
*/
|
|
1444
|
+
includeInDeepSearch?: IncludeInDeepSearch;
|
|
1445
|
+
/** Filter function or false to disable filtering */
|
|
1446
|
+
filter?: ((value: string, search: string, keywords?: string[]) => number) | false;
|
|
1447
|
+
/**
|
|
1448
|
+
* Transforms search input before filtering and visibility logic.
|
|
1449
|
+
* @default trim whitespace (`search.trim()`)
|
|
1450
|
+
*/
|
|
1451
|
+
normalizeSearch?: (search: string) => string;
|
|
1452
|
+
/** Controlled search value */
|
|
1453
|
+
search?: string;
|
|
1454
|
+
/** Callback when search value changes */
|
|
1455
|
+
onSearchChange?: (search: string) => void;
|
|
1456
|
+
/** Default search value for uncontrolled usage */
|
|
1457
|
+
defaultSearch?: string;
|
|
1458
|
+
/** Whether navigation should loop */
|
|
1459
|
+
loop?: boolean;
|
|
1460
|
+
/** Auto-highlight behavior when menu opens */
|
|
1461
|
+
autoHighlightFirst?: boolean | string;
|
|
1462
|
+
/**
|
|
1463
|
+
* Whether to clear search on close.
|
|
1464
|
+
* - `true`: clear immediately when menu closes (default)
|
|
1465
|
+
* - `false`: preserve search when menu closes
|
|
1466
|
+
* - `'after-exit'`: clear after exit animation completes
|
|
1467
|
+
*/
|
|
1468
|
+
clearSearchOnClose?: boolean | 'after-exit';
|
|
1469
|
+
/**
|
|
1470
|
+
* Function to generate qualified IDs for row items.
|
|
1471
|
+
* Called for each item when rendering to produce IDs for:
|
|
1472
|
+
* - React keys
|
|
1473
|
+
* - Store registration
|
|
1474
|
+
* - DOM id attributes
|
|
1475
|
+
*
|
|
1476
|
+
* @default Uses node.id if provided, otherwise qualifies with breadcrumbs + slugified value
|
|
1477
|
+
*/
|
|
1478
|
+
getQualifiedRowId?: GetQualifiedRowIdFn;
|
|
1479
|
+
/** Children (Input, List, etc.) */
|
|
1480
|
+
children: React.ReactNode;
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* State passed to the DataList render function.
|
|
1484
|
+
*/
|
|
1485
|
+
interface DataListChildrenState {
|
|
1486
|
+
/** Current search query (empty string if browsing) */
|
|
1487
|
+
search: string;
|
|
1488
|
+
/**
|
|
1489
|
+
* Display nodes (filtered and scored if searching).
|
|
1490
|
+
* Can include groups (DisplayGroupNode) or radio groups (DisplayRadioGroupNode)
|
|
1491
|
+
* when groupSearchBehavior: 'preserve'.
|
|
1492
|
+
*/
|
|
1493
|
+
nodes: DisplayNode[];
|
|
1494
|
+
/**
|
|
1495
|
+
* Function to render a node.
|
|
1496
|
+
* Handles items, submenus, groups, and radio groups, calling their render functions with context.
|
|
1497
|
+
*/
|
|
1498
|
+
renderNode: (displayNode: DisplayNode) => React.ReactNode;
|
|
1499
|
+
/** Number of visible items (counting items inside groups) */
|
|
1500
|
+
count: number;
|
|
1501
|
+
/** Whether deep search is active (query length >= minLength) */
|
|
1502
|
+
isDeepSearching: boolean;
|
|
1503
|
+
/** Aggregate async loading state across all menus */
|
|
1504
|
+
async: AsyncState;
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* Props for the DataList component.
|
|
1508
|
+
*/
|
|
1509
|
+
interface DataListProps {
|
|
1510
|
+
/**
|
|
1511
|
+
* Render function for the list content.
|
|
1512
|
+
* Receives the current state and returns JSX.
|
|
1513
|
+
*/
|
|
1514
|
+
children: (state: DataListChildrenState) => React.ReactNode;
|
|
1515
|
+
/** Accessible label for the listbox */
|
|
1516
|
+
label?: string;
|
|
1517
|
+
/** Additional class name */
|
|
1518
|
+
className?: string;
|
|
1519
|
+
/** Additional styles */
|
|
1520
|
+
style?: React.CSSProperties;
|
|
1521
|
+
/**
|
|
1522
|
+
* When true, measures row widths and applies `--row-width` CSS variable.
|
|
1523
|
+
* Keeps the list at the maximum width seen while scrolling.
|
|
1524
|
+
* Useful for virtualized lists where content width varies.
|
|
1525
|
+
* @default true
|
|
1526
|
+
*/
|
|
1527
|
+
measureRowWidth?: boolean;
|
|
1528
|
+
/**
|
|
1529
|
+
* Maximum width cap for row measurement (in pixels).
|
|
1530
|
+
* Only used when `measureRowWidth` is true.
|
|
1531
|
+
*/
|
|
1532
|
+
maxRowWidth?: number;
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* State passed to the DataSubpages render function.
|
|
1536
|
+
*/
|
|
1537
|
+
interface DataSubpagesChildrenState {
|
|
1538
|
+
/** All subpage content nodes discovered in the current content tree. */
|
|
1539
|
+
subpages: DisplaySubpageNode[];
|
|
1540
|
+
/**
|
|
1541
|
+
* Function to render a subpage content node.
|
|
1542
|
+
* Calls the node's `renderContent` callback with page context and child renderer.
|
|
1543
|
+
*/
|
|
1544
|
+
renderSubpageContent: (subpage: DisplaySubpageNode) => React.ReactNode;
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Props for the DataSubpages component.
|
|
1548
|
+
*/
|
|
1549
|
+
interface DataSubpagesProps {
|
|
1550
|
+
/**
|
|
1551
|
+
* Optional render function.
|
|
1552
|
+
* If omitted, all subpage contents are rendered by default.
|
|
1553
|
+
*/
|
|
1554
|
+
children?: (state: DataSubpagesChildrenState) => React.ReactNode;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
export { type ItemRenderParams as $, type AsyncLoaderConfig as A, type BreadcrumbNode as B, type ComponentProps as C, type CheckboxItemDef as D, type CheckboxItemRenderParams as E, type CheckboxItemRenderProps as F, type GetQualifiedRowIdFn as G, type DataListChildrenState as H, type DataListProps as I, type DataSubpagesChildrenState as J, type DataSubpagesProps as K, type DataSurfaceProps as L, type DeepSearchConfig as M, type DisplayGroupNode as N, type DisplayNode as O, PopupMenuCheckboxItem as P, type DisplayRadioGroupNode as Q, type DisplayRowNode as R, type DisplaySeparatorNode as S, type DisplaySubpageNode as T, type GroupBehavior as U, type GroupDef as V, type GroupRenderContext as W, type GroupRenderParams as X, type IncludeInDeepSearch as Y, type InitialQueryBehavior as Z, type ItemDef as _, PopupMenuItem as a, type ItemRenderProps as a0, type LoaderComponentProps as a1, type NodeDef as a2, type QueryAsyncNodesConfig as a3, type QueryDependentLoaderConfig as a4, type RadioGroupBehavior as a5, type RadioGroupDef as a6, type RadioGroupRenderParams as a7, type RadioGroupRenderProps as a8, type RadioItemDef as a9, type RadioItemRenderParams as aa, type RadioItemRenderProps as ab, type RowRenderContext as ac, type ScoredNode as ad, type SeparatorDef as ae, type SeparatorRenderParams as af, type StaticAsyncNodesConfig as ag, type StaticLoaderConfig as ah, type SubmenuDef as ai, type SubmenuRenderParams as aj, type SubmenuRenderProps as ak, type SubpageContentRenderParams as al, type SubpageDef as am, type SubpageTriggerRenderParams as an, type SubpageTriggerRenderProps as ao, defineRadioGroup as ap, isDisplayGroupNode as aq, isDisplayRadioGroupNode as ar, isDisplayRowNode as as, isDisplaySeparatorNode as at, type GetQualifiedRowIdContext as au, type ComponentRenderFn as av, PopupMenuRadioGroup as b, PopupMenuRadioItem as c, PopupMenuSubmenuTrigger as d, PopupMenuSubpageTrigger as e, type PopupMenuCheckboxItemProps as f, type PopupMenuCheckboxItemState as g, type PopupMenuItemProps as h, type PopupMenuItemState as i, type PopupMenuRadioGroupProps as j, type PopupMenuRadioGroupState as k, type PopupMenuRadioItemProps as l, type PopupMenuRadioItemState as m, type PopupMenuSubmenuTriggerProps as n, type PopupMenuSubmenuTriggerState as o, type PopupMenuSubpageTriggerProps as p, type PopupMenuSubpageTriggerState as q, type AsyncLoaderFetchStatus as r, type AsyncLoaderLoadingPhase as s, type AsyncLoaderResult as t, type AsyncLoaderSource as u, type AsyncLoaderStatus as v, type AsyncNodesConfig as w, type AsyncRenderState as x, type AsyncResultBehavior as y, type AsyncState as z };
|