@uipath/apollo-wind 2.61.0 → 2.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/components/ui/checkbox.cjs +10 -5
  2. package/dist/components/ui/checkbox.js +12 -7
  3. package/dist/components/ui/folder-picker/components/folder-breadcrumb.cjs +72 -0
  4. package/dist/components/ui/folder-picker/components/folder-breadcrumb.d.ts +14 -0
  5. package/dist/components/ui/folder-picker/components/folder-breadcrumb.js +38 -0
  6. package/dist/components/ui/folder-picker/components/folder-picker-empty-state.cjs +75 -0
  7. package/dist/components/ui/folder-picker/components/folder-picker-empty-state.d.ts +26 -0
  8. package/dist/components/ui/folder-picker/components/folder-picker-empty-state.js +41 -0
  9. package/dist/components/ui/folder-picker/components/folder-picker-footer.cjs +70 -0
  10. package/dist/components/ui/folder-picker/components/folder-picker-footer.d.ts +20 -0
  11. package/dist/components/ui/folder-picker/components/folder-picker-footer.js +36 -0
  12. package/dist/components/ui/folder-picker/components/folder-picker-search.cjs +79 -0
  13. package/dist/components/ui/folder-picker/components/folder-picker-search.d.ts +14 -0
  14. package/dist/components/ui/folder-picker/components/folder-picker-search.js +45 -0
  15. package/dist/components/ui/folder-picker/components/folder-row.cjs +107 -0
  16. package/dist/components/ui/folder-picker/components/folder-row.d.ts +27 -0
  17. package/dist/components/ui/folder-picker/components/folder-row.js +73 -0
  18. package/dist/components/ui/folder-picker/folder-picker.cjs +465 -0
  19. package/dist/components/ui/folder-picker/folder-picker.d.ts +34 -0
  20. package/dist/components/ui/folder-picker/folder-picker.js +425 -0
  21. package/dist/components/ui/folder-picker/index.cjs +42 -0
  22. package/dist/components/ui/folder-picker/index.d.ts +2 -0
  23. package/dist/components/ui/folder-picker/index.js +2 -0
  24. package/dist/components/ui/folder-picker/types.cjs +44 -0
  25. package/dist/components/ui/folder-picker/types.d.ts +97 -0
  26. package/dist/components/ui/folder-picker/types.js +4 -0
  27. package/dist/components/ui/index.cjs +18 -18
  28. package/dist/index.cjs +13 -3
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.js +2 -1
  31. package/dist/styles.css +74 -0
  32. package/package.json +1 -1
@@ -0,0 +1,34 @@
1
+ import type { FolderPickerContentProps, FolderPickerProps } from './types';
2
+ /**
3
+ * Browsing surface for embedding in a consumer-owned popover, dialog or sheet.
4
+ *
5
+ * Follows the platform chooser convention: a single click highlights a row as
6
+ * the pending selection, a double click or the trailing chevron opens it, the
7
+ * breadcrumb jumps back up, and the footer confirms. With nothing highlighted,
8
+ * Select confirms the folder currently being browsed, so a folder can be chosen
9
+ * by opening it. At the root with no highlight there is nothing valid to
10
+ * confirm and Select is disabled.
11
+ */
12
+ export declare function FolderPickerContent({ onLoadChildren, onSelect, onCancel, initialPath, rootLabel, breadcrumbLabel, searchPlaceholder, clearSearchLabel, initialSearch, emptyText, noMatchText, openFolderLabel, loadingText, loadErrorText, retryLabel, listLabel, footerLeading, cancelLabel, selectLabel, className, }: FolderPickerContentProps): import("react/jsx-runtime").JSX.Element;
13
+ /**
14
+ * Holds a Radix surface open while the picker's search has text, so Escape
15
+ * clears the search instead of dismissing, wherever focus is in the picker.
16
+ * Radix hears Escape in the capture phase, before the picker's own handlers,
17
+ * so the picker cannot stop the dismissal itself. It clears the search as the
18
+ * key reaches it.
19
+ *
20
+ * `FolderPicker` applies it to its popover. Pass it as `onEscapeKeyDown` to a
21
+ * Dialog, Sheet or Popover that hosts `FolderPickerContent`.
22
+ */
23
+ export declare function keepFolderSearchOnEscape(event: {
24
+ target: EventTarget | null;
25
+ preventDefault(): void;
26
+ }): void;
27
+ /**
28
+ * Field-and-popover folder picker over a lazily loaded tree.
29
+ *
30
+ * The trigger leads with its icon and then the value, matching the date field,
31
+ * so an empty folder field does not read as bare chrome next to it.
32
+ */
33
+ export declare function FolderPicker({ value, placeholder, disabled, clearable, clearAriaLabel, dialogLabel, children, align, open: controlledOpen, onOpenChange, trailingAdornment, contentClassName, className, id, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, onSelect, ...contentProps }: FolderPickerProps): import("react/jsx-runtime").JSX.Element;
34
+ export type { FolderPickerContentProps, FolderPickerEntry, FolderPickerLoadChildren, FolderPickerProps, } from './types';
@@ -0,0 +1,425 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { FolderOpen, X } from "lucide-react";
4
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
5
+ import { Popover, PopoverContent, PopoverTrigger } from "../popover.js";
6
+ import { cn } from "../../../lib/index.js";
7
+ import { FolderBreadcrumb } from "./components/folder-breadcrumb.js";
8
+ import { FolderPickerEmptyState } from "./components/folder-picker-empty-state.js";
9
+ import { FolderPickerFooter } from "./components/folder-picker-footer.js";
10
+ import { FolderPickerSearch } from "./components/folder-picker-search.js";
11
+ import { FolderRow } from "./components/folder-row.js";
12
+ import { cacheKey, isValidSegment, joinPath } from "./types.js";
13
+ const listedDraft = (current, entries, segments)=>entries.some((entry)=>!entry.disabled && joinPath([
14
+ ...segments,
15
+ entry.name
16
+ ]) === current) ? current : null;
17
+ function FolderPickerContent({ onLoadChildren, onSelect, onCancel, initialPath, rootLabel = 'Root', breadcrumbLabel, searchPlaceholder = 'Search...', clearSearchLabel, initialSearch = '', emptyText = 'No subfolders.', noMatchText, openFolderLabel, loadingText = 'Loading…', loadErrorText = 'Could not load this folder.', retryLabel = 'Retry', listLabel = 'Folders', footerLeading, cancelLabel = 'Cancel', selectLabel = 'Select', className }) {
18
+ const initialSegments = useMemo(()=>(initialPath ?? '').split('/').filter(Boolean), [
19
+ initialPath
20
+ ]);
21
+ const [pathStack, setPathStack] = useState(()=>initialSegments.slice(0, -1));
22
+ const [draft, setDraft] = useState(()=>initialSegments.length > 0 ? joinPath(initialSegments) : null);
23
+ const [search, setSearch] = useState(initialSearch);
24
+ const [levels, setLevels] = useState(()=>new Map());
25
+ const [loadingPath, setLoadingPath] = useState(()=>joinPath(initialSegments.slice(0, -1)));
26
+ const [error, setError] = useState(null);
27
+ const [activeName, setActiveName] = useState(()=>initialSegments[initialSegments.length - 1] ?? null);
28
+ const rowRefs = useRef(new Map());
29
+ const listRef = useRef(null);
30
+ const rootRef = useRef(null);
31
+ const focusAfterNavigateRef = useRef(false);
32
+ const requestRef = useRef(0);
33
+ const mountedRef = useRef(true);
34
+ useEffect(()=>{
35
+ mountedRef.current = true;
36
+ return ()=>{
37
+ mountedRef.current = false;
38
+ };
39
+ }, []);
40
+ const loadLevel = useCallback(async (segments, { keepDraft = false, keepSearch = false, nextActive } = {})=>{
41
+ const key = cacheKey(segments);
42
+ const requestId = ++requestRef.current;
43
+ const cached = levels.get(key);
44
+ if (cached) {
45
+ setLoadingPath(null);
46
+ setError(null);
47
+ setPathStack(segments);
48
+ if (void 0 !== nextActive) setActiveName(nextActive);
49
+ if (keepDraft) setDraft((current)=>listedDraft(current, cached, segments));
50
+ return;
51
+ }
52
+ setLoadingPath(joinPath(segments));
53
+ setError(null);
54
+ try {
55
+ const loaded = await onLoadChildren(segments);
56
+ if (!mountedRef.current || requestRef.current !== requestId) return;
57
+ const seen = new Set();
58
+ const entries = loaded.filter((entry)=>{
59
+ if (!isValidSegment(entry.name) || seen.has(entry.name)) return false;
60
+ seen.add(entry.name);
61
+ return true;
62
+ });
63
+ if (entries.length < loaded.length) console.warn('FolderPicker: dropped entries whose name is empty, contains "/" or repeats a sibling, which paths cannot represent.');
64
+ setLevels((current)=>new Map(current).set(key, entries));
65
+ setPathStack(segments);
66
+ if (void 0 !== nextActive) setActiveName(nextActive);
67
+ if (keepDraft) setDraft((current)=>listedDraft(current, entries, segments));
68
+ else {
69
+ setDraft(null);
70
+ if (!keepSearch) setSearch('');
71
+ }
72
+ } catch (cause) {
73
+ if (!mountedRef.current || requestRef.current !== requestId) return;
74
+ if (keepDraft) setDraft(null);
75
+ setError({
76
+ message: cause instanceof Error && cause.message ? cause.message : loadErrorText,
77
+ segments
78
+ });
79
+ } finally{
80
+ if (mountedRef.current && requestRef.current === requestId) setLoadingPath(null);
81
+ }
82
+ }, [
83
+ levels,
84
+ onLoadChildren,
85
+ loadErrorText
86
+ ]);
87
+ const initialStack = useRef(pathStack);
88
+ const didLoadInitial = useRef(false);
89
+ useEffect(()=>{
90
+ if (didLoadInitial.current) return;
91
+ didLoadInitial.current = true;
92
+ loadLevel(initialStack.current, {
93
+ keepDraft: true
94
+ });
95
+ }, [
96
+ loadLevel
97
+ ]);
98
+ const handleEscape = (event)=>{
99
+ if ('Escape' !== event.key || !search) return;
100
+ event.preventDefault();
101
+ event.stopPropagation();
102
+ setSearch('');
103
+ };
104
+ const navigateTo = (segments)=>{
105
+ if (loadingPath === joinPath(segments)) return;
106
+ setDraft(null);
107
+ setSearch('');
108
+ const isAncestor = segments.every((segment, index)=>pathStack[index] === segment);
109
+ loadLevel(segments, {
110
+ nextActive: isAncestor ? pathStack[segments.length] ?? null : null
111
+ });
112
+ };
113
+ const currentKey = cacheKey(pathStack);
114
+ const entries = levels.get(currentKey) ?? [];
115
+ const isLoadingCurrentLevel = null !== loadingPath && !levels.has(currentKey);
116
+ const levelError = levels.has(currentKey) ? null : error?.message ?? null;
117
+ const drillError = levels.has(currentKey) ? error?.message ?? null : null;
118
+ const normalizedQuery = search.trim().toLowerCase();
119
+ const visibleEntries = normalizedQuery ? entries.filter((entry)=>(entry.label ?? entry.name).toLowerCase().includes(normalizedQuery)) : entries;
120
+ const visibleDraft = visibleEntries.some((entry)=>joinPath([
121
+ ...pathStack,
122
+ entry.name
123
+ ]) === draft) ? draft : null;
124
+ const effectiveSelection = levels.has(currentKey) ? visibleDraft ?? (pathStack.length > 0 ? joinPath(pathStack) : null) : null;
125
+ const focusableEntries = visibleEntries.filter((entry)=>!entry.disabled);
126
+ const activeEntryName = focusableEntries.find((entry)=>entry.name === activeName)?.name ?? focusableEntries[0]?.name ?? null;
127
+ useEffect(()=>{
128
+ if (!focusAfterNavigateRef.current || null !== loadingPath) return;
129
+ focusAfterNavigateRef.current = false;
130
+ const tree = listRef.current;
131
+ const focused = tree?.ownerDocument.activeElement;
132
+ const focusLost = !focused || focused === tree?.ownerDocument.body;
133
+ const onRowOrFallback = focused === tree || focused?.getAttribute('role') === 'treeitem';
134
+ if (!focusLost && !(onRowOrFallback && tree?.contains(focused))) return;
135
+ const row = null === activeEntryName ? void 0 : rowRefs.current.get(activeEntryName);
136
+ (row ?? listRef.current)?.focus();
137
+ });
138
+ const syncedPath = useRef(initialPath);
139
+ useEffect(()=>{
140
+ if (syncedPath.current === initialPath) return;
141
+ syncedPath.current = initialPath;
142
+ const root = rootRef.current;
143
+ if (root?.contains(root.ownerDocument.activeElement)) focusAfterNavigateRef.current = true;
144
+ setDraft(initialSegments.length > 0 ? joinPath(initialSegments) : null);
145
+ setSearch('');
146
+ loadLevel(initialSegments.slice(0, -1), {
147
+ keepDraft: true,
148
+ nextActive: initialSegments[initialSegments.length - 1] ?? null
149
+ });
150
+ }, [
151
+ initialPath,
152
+ initialSegments,
153
+ loadLevel
154
+ ]);
155
+ const focusRow = (name)=>{
156
+ setActiveName(name);
157
+ rowRefs.current.get(name)?.focus();
158
+ };
159
+ const openFolder = (segments)=>{
160
+ focusAfterNavigateRef.current = true;
161
+ navigateTo(segments);
162
+ };
163
+ const handleTreeKeyDown = (event)=>{
164
+ const target = event.target;
165
+ if (target !== listRef.current && 'treeitem' !== target.getAttribute('role')) return;
166
+ const index = target === listRef.current ? -1 : focusableEntries.findIndex((entry)=>entry.name === activeEntryName);
167
+ let next;
168
+ switch(event.key){
169
+ case 'ArrowDown':
170
+ next = focusableEntries[Math.min(index + 1, focusableEntries.length - 1)];
171
+ break;
172
+ case 'ArrowUp':
173
+ next = focusableEntries[Math.max(index - 1, 0)];
174
+ break;
175
+ case 'Home':
176
+ next = focusableEntries[0];
177
+ break;
178
+ case 'End':
179
+ next = focusableEntries[focusableEntries.length - 1];
180
+ break;
181
+ case 'ArrowLeft':
182
+ if (0 === pathStack.length) return;
183
+ event.preventDefault();
184
+ openFolder(pathStack.slice(0, -1));
185
+ return;
186
+ default:
187
+ return;
188
+ }
189
+ event.preventDefault();
190
+ if (next) focusRow(next.name);
191
+ };
192
+ const crumbs = [
193
+ {
194
+ key: '/',
195
+ label: rootLabel,
196
+ stack: []
197
+ },
198
+ ...pathStack.map((segment, index)=>{
199
+ const stack = pathStack.slice(0, index + 1);
200
+ const parent = levels.get(cacheKey(pathStack.slice(0, index)));
201
+ const label = parent?.find((entry)=>entry.name === segment)?.label ?? segment;
202
+ return {
203
+ key: joinPath(stack),
204
+ label,
205
+ stack
206
+ };
207
+ })
208
+ ];
209
+ return /*#__PURE__*/ jsxs("div", {
210
+ ref: rootRef,
211
+ "data-slot": "folder-picker",
212
+ className: cn('flex min-w-0 flex-col overflow-hidden', className),
213
+ onKeyDown: handleEscape,
214
+ children: [
215
+ /*#__PURE__*/ jsx(FolderBreadcrumb, {
216
+ crumbs: crumbs,
217
+ onJump: openFolder,
218
+ label: breadcrumbLabel
219
+ }),
220
+ /*#__PURE__*/ jsx(FolderPickerSearch, {
221
+ value: search,
222
+ onChange: setSearch,
223
+ placeholder: searchPlaceholder,
224
+ clearLabel: clearSearchLabel
225
+ }),
226
+ /*#__PURE__*/ jsxs("div", {
227
+ ref: listRef,
228
+ role: "group",
229
+ "aria-label": listLabel,
230
+ tabIndex: null === activeEntryName ? 0 : -1,
231
+ className: "max-h-56 min-h-0 flex-1 overflow-y-auto py-1 outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
232
+ onKeyDown: handleTreeKeyDown,
233
+ children: [
234
+ 0 === visibleEntries.length && /*#__PURE__*/ jsx(FolderPickerEmptyState, {
235
+ error: levelError,
236
+ loading: isLoadingCurrentLevel,
237
+ query: search.trim(),
238
+ emptyText: emptyText,
239
+ noMatchText: noMatchText,
240
+ loadingText: loadingText,
241
+ retryLabel: retryLabel,
242
+ onRetry: ()=>{
243
+ if (!error) return;
244
+ listRef.current?.focus();
245
+ focusAfterNavigateRef.current = true;
246
+ if (cacheKey(error.segments) === currentKey) loadLevel(pathStack, {
247
+ keepSearch: true
248
+ });
249
+ else navigateTo(error.segments);
250
+ }
251
+ }),
252
+ drillError && /*#__PURE__*/ jsx("div", {
253
+ role: "alert",
254
+ className: "px-3 py-2 text-xs text-destructive",
255
+ children: drillError
256
+ }),
257
+ (visibleEntries.length > 0 || isLoadingCurrentLevel) && /*#__PURE__*/ jsx("div", {
258
+ role: "tree",
259
+ "aria-label": listLabel,
260
+ "aria-busy": isLoadingCurrentLevel || void 0,
261
+ children: visibleEntries.map((entry)=>{
262
+ const segments = [
263
+ ...pathStack,
264
+ entry.name
265
+ ];
266
+ const fullPath = joinPath(segments);
267
+ const isSelected = draft === fullPath;
268
+ return /*#__PURE__*/ jsx(FolderRow, {
269
+ entry: entry,
270
+ level: pathStack.length + 1,
271
+ selected: isSelected,
272
+ active: entry.name === activeEntryName,
273
+ loading: loadingPath === fullPath,
274
+ rowRef: (node)=>{
275
+ if (node) rowRefs.current.set(entry.name, node);
276
+ else rowRefs.current.delete(entry.name);
277
+ },
278
+ onFocus: ()=>setActiveName(entry.name),
279
+ onToggleSelect: ()=>setDraft(isSelected ? null : fullPath),
280
+ onOpen: ()=>openFolder(segments),
281
+ openLabel: openFolderLabel
282
+ }, fullPath);
283
+ })
284
+ })
285
+ ]
286
+ }),
287
+ /*#__PURE__*/ jsx(FolderPickerFooter, {
288
+ leading: footerLeading,
289
+ onCancel: onCancel,
290
+ onSelect: ()=>effectiveSelection && onSelect(effectiveSelection),
291
+ selectDisabled: !effectiveSelection,
292
+ cancelLabel: cancelLabel,
293
+ selectLabel: selectLabel
294
+ })
295
+ ]
296
+ });
297
+ }
298
+ function keepFolderSearchOnEscape(event) {
299
+ const target = event.target;
300
+ if (!(target instanceof Element)) return;
301
+ const search = target.closest('[data-slot="folder-picker"]')?.querySelector('input[data-slot="folder-picker-search"]');
302
+ if (search?.value) event.preventDefault();
303
+ }
304
+ function FolderPicker({ value = '', placeholder = 'Select a folder…', disabled = false, clearable = true, clearAriaLabel = 'Clear folder', dialogLabel = 'Choose a folder', children, align = 'start', open: controlledOpen, onOpenChange, trailingAdornment, contentClassName, className, id, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, onSelect, ...contentProps }) {
305
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
306
+ const requestedOpen = controlledOpen ?? uncontrolledOpen;
307
+ const open = requestedOpen && !disabled;
308
+ const closedByDisable = disabled && requestedOpen;
309
+ useEffect(()=>{
310
+ if (!closedByDisable) return;
311
+ setUncontrolledOpen(false);
312
+ onOpenChange?.(false);
313
+ }, [
314
+ closedByDisable
315
+ ]);
316
+ const contentRef = useRef(null);
317
+ const browsePath = useRef(value);
318
+ if (open) browsePath.current = value;
319
+ const triggerRef = useRef(null);
320
+ const trailingRef = useRef(null);
321
+ const [trailingWidth, setTrailingWidth] = useState(0);
322
+ const showClear = clearable && Boolean(value) && !disabled && !children;
323
+ const showAdornment = Boolean(trailingAdornment) && !children;
324
+ const hasTrailing = showAdornment || showClear;
325
+ useLayoutEffect(()=>{
326
+ const el = trailingRef.current;
327
+ if (!el) return void setTrailingWidth(0);
328
+ setTrailingWidth(el.offsetWidth);
329
+ if ("u" < typeof ResizeObserver) return;
330
+ const observer = new ResizeObserver(()=>setTrailingWidth(el.offsetWidth));
331
+ observer.observe(el);
332
+ return ()=>observer.disconnect();
333
+ }, [
334
+ hasTrailing
335
+ ]);
336
+ const setOpen = (nextOpen)=>{
337
+ if (nextOpen && disabled) return;
338
+ if (void 0 === controlledOpen) setUncontrolledOpen(nextOpen);
339
+ onOpenChange?.(nextOpen);
340
+ };
341
+ return /*#__PURE__*/ jsxs("div", {
342
+ className: cn('group relative min-w-0', className),
343
+ children: [
344
+ /*#__PURE__*/ jsxs(Popover, {
345
+ open: open,
346
+ onOpenChange: setOpen,
347
+ children: [
348
+ /*#__PURE__*/ jsx(PopoverTrigger, {
349
+ asChild: true,
350
+ disabled: disabled,
351
+ children: children ?? /*#__PURE__*/ jsxs("button", {
352
+ ref: triggerRef,
353
+ type: "button",
354
+ disabled: disabled,
355
+ id: id,
356
+ "aria-labelledby": ariaLabelledBy,
357
+ "aria-describedby": ariaDescribedBy,
358
+ role: "combobox",
359
+ "aria-haspopup": "dialog",
360
+ "aria-expanded": open,
361
+ style: trailingWidth > 0 ? {
362
+ paddingRight: trailingWidth + 20
363
+ } : void 0,
364
+ className: cn('flex h-9 w-full min-w-0 cursor-pointer items-center gap-2 rounded-md border border-input bg-transparent pl-3 pr-3 text-left text-base transition-colors md:text-sm', 'focus:outline-none focus:ring-2 focus:ring-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50', 'future:h-10 future:rounded-xl future:border-0 future:bg-surface-overlay future:px-4 future:font-normal future:hover:bg-surface-hover'),
365
+ children: [
366
+ /*#__PURE__*/ jsx(FolderOpen, {
367
+ size: 16,
368
+ className: "shrink-0 text-foreground-muted"
369
+ }),
370
+ /*#__PURE__*/ jsx("span", {
371
+ className: cn('min-w-0 flex-1 truncate', value ? 'text-foreground' : 'text-foreground-subtle'),
372
+ children: value || placeholder
373
+ })
374
+ ]
375
+ })
376
+ }),
377
+ /*#__PURE__*/ jsx(PopoverContent, {
378
+ "aria-label": dialogLabel,
379
+ align: align,
380
+ sideOffset: 4,
381
+ className: cn('w-(--radix-popover-trigger-width) min-w-72 overflow-hidden p-0', contentClassName),
382
+ ref: contentRef,
383
+ onOpenAutoFocus: (event)=>{
384
+ event.preventDefault();
385
+ contentRef.current?.querySelector('input')?.focus();
386
+ },
387
+ onEscapeKeyDown: keepFolderSearchOnEscape,
388
+ children: /*#__PURE__*/ jsx(FolderPickerContent, {
389
+ ...contentProps,
390
+ initialPath: browsePath.current,
391
+ onCancel: ()=>setOpen(false),
392
+ onSelect: (path)=>{
393
+ onSelect(path);
394
+ setOpen(false);
395
+ }
396
+ })
397
+ })
398
+ ]
399
+ }),
400
+ hasTrailing && /*#__PURE__*/ jsxs("span", {
401
+ ref: trailingRef,
402
+ className: "pointer-events-none absolute inset-y-0 right-2 flex items-center gap-0.5",
403
+ children: [
404
+ showClear && /*#__PURE__*/ jsx("button", {
405
+ type: "button",
406
+ "aria-label": clearAriaLabel,
407
+ className: "pointer-events-auto grid size-4 cursor-pointer place-items-center rounded text-foreground-muted opacity-0 transition-opacity hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100",
408
+ onClick: ()=>{
409
+ triggerRef.current?.focus();
410
+ onSelect('');
411
+ },
412
+ children: /*#__PURE__*/ jsx(X, {
413
+ size: 11
414
+ })
415
+ }),
416
+ showAdornment && /*#__PURE__*/ jsx("span", {
417
+ className: "pointer-events-auto flex items-center",
418
+ children: trailingAdornment
419
+ })
420
+ ]
421
+ })
422
+ ]
423
+ });
424
+ }
425
+ export { FolderPicker, FolderPickerContent, keepFolderSearchOnEscape };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ FolderPickerContent: ()=>external_folder_picker_cjs_namespaceObject.FolderPickerContent,
28
+ FolderPicker: ()=>external_folder_picker_cjs_namespaceObject.FolderPicker,
29
+ keepFolderSearchOnEscape: ()=>external_folder_picker_cjs_namespaceObject.keepFolderSearchOnEscape
30
+ });
31
+ const external_folder_picker_cjs_namespaceObject = require("./folder-picker.cjs");
32
+ exports.FolderPicker = __webpack_exports__.FolderPicker;
33
+ exports.FolderPickerContent = __webpack_exports__.FolderPickerContent;
34
+ exports.keepFolderSearchOnEscape = __webpack_exports__.keepFolderSearchOnEscape;
35
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
36
+ "FolderPicker",
37
+ "FolderPickerContent",
38
+ "keepFolderSearchOnEscape"
39
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
40
+ Object.defineProperty(exports, '__esModule', {
41
+ value: true
42
+ });
@@ -0,0 +1,2 @@
1
+ export type { FolderPickerContentProps, FolderPickerEntry, FolderPickerLoadChildren, FolderPickerProps, } from './folder-picker';
2
+ export { FolderPicker, FolderPickerContent, keepFolderSearchOnEscape } from './folder-picker';
@@ -0,0 +1,2 @@
1
+ import { FolderPicker, FolderPickerContent, keepFolderSearchOnEscape } from "./folder-picker.js";
2
+ export { FolderPicker, FolderPickerContent, keepFolderSearchOnEscape };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ cacheKey: ()=>cacheKey,
28
+ isValidSegment: ()=>isValidSegment,
29
+ joinPath: ()=>joinPath
30
+ });
31
+ const joinPath = (segments)=>`/${segments.join('/')}`;
32
+ const cacheKey = (segments)=>JSON.stringify(segments);
33
+ const isValidSegment = (name)=>'' !== name && !name.includes('/');
34
+ exports.cacheKey = __webpack_exports__.cacheKey;
35
+ exports.isValidSegment = __webpack_exports__.isValidSegment;
36
+ exports.joinPath = __webpack_exports__.joinPath;
37
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
38
+ "cacheKey",
39
+ "isValidSegment",
40
+ "joinPath"
41
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
42
+ Object.defineProperty(exports, '__esModule', {
43
+ value: true
44
+ });
@@ -0,0 +1,97 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ export interface FolderPickerEntry {
3
+ /**
4
+ * Segment name as it appears in the path. Unique among its siblings, and
5
+ * non-empty without a `/`, since paths are `/`-joined strings. An entry that
6
+ * breaks this, or repeats an earlier sibling's name, is dropped with a
7
+ * warning rather than collide with another path.
8
+ */
9
+ name: string;
10
+ /** Row label. Defaults to `name`. */
11
+ label?: string;
12
+ /** False marks a known leaf, which hides its open affordance. Unknown by default. */
13
+ hasChildren?: boolean;
14
+ disabled?: boolean;
15
+ }
16
+ /**
17
+ * Loads one level of the tree. The root is requested with an empty path.
18
+ * Resolved levels are cached, so navigating back up does not re-request.
19
+ */
20
+ export type FolderPickerLoadChildren = (path: string[]) => Promise<FolderPickerEntry[]>;
21
+ export interface FolderPickerContentProps {
22
+ /** Loads a level of the tree. Called for the root when the content mounts. */
23
+ onLoadChildren: FolderPickerLoadChildren;
24
+ /** Confirms a folder path, such as `/Finance/Invoices`. */
25
+ onSelect: (path: string) => void;
26
+ /** Closes the surface without confirming. */
27
+ onCancel?: () => void;
28
+ /** Browsing resumes at this path's parent, with the path itself highlighted. */
29
+ initialPath?: string;
30
+ /** Label for the breadcrumb's first segment. */
31
+ rootLabel?: string;
32
+ /** Accessible name for the breadcrumb's navigation landmark. */
33
+ breadcrumbLabel?: string;
34
+ searchPlaceholder?: string;
35
+ /** Accessible name for the search's clear control. */
36
+ clearSearchLabel?: string;
37
+ /** Seeds the search box, as VariablePicker's `initialQuery` does. */
38
+ initialSearch?: string;
39
+ emptyText?: string;
40
+ /** Shown when the search matches no folder in the level being browsed. */
41
+ noMatchText?: (query: string) => string;
42
+ /** Accessible name for a row's Open control, given the row's label. */
43
+ openFolderLabel?: (label: string) => string;
44
+ /** Shown while a level that has never resolved is loading. */
45
+ loadingText?: string;
46
+ /**
47
+ * Shown when a load fails without a message of its own: a rejection that is
48
+ * not an `Error`, or one whose message is empty. Otherwise that message is
49
+ * shown as given.
50
+ */
51
+ loadErrorText?: string;
52
+ /** Action offered when the level being browsed failed to load. */
53
+ retryLabel?: string;
54
+ /** Accessible name for the folder list. */
55
+ listLabel?: string;
56
+ /** Content for the footer's leading slot, such as a count or an "Add new" link. */
57
+ footerLeading?: ReactNode;
58
+ cancelLabel?: string;
59
+ selectLabel?: string;
60
+ className?: string;
61
+ }
62
+ export interface FolderPickerProps extends Omit<FolderPickerContentProps, 'onCancel' | 'initialPath' | 'className'> {
63
+ /** Selected folder path, or an empty string. */
64
+ value?: string;
65
+ placeholder?: string;
66
+ disabled?: boolean;
67
+ /** Hides the field's hover-revealed clear control. */
68
+ clearable?: boolean;
69
+ clearAriaLabel?: string;
70
+ /** Accessible name for the popover, which is a dialog. */
71
+ dialogLabel?: string;
72
+ /**
73
+ * A single element Radix can anchor the popover to. Replaces the default
74
+ * field, along with its clear control and `trailingAdornment`.
75
+ */
76
+ children?: ReactElement;
77
+ align?: 'start' | 'center' | 'end';
78
+ open?: boolean;
79
+ onOpenChange?: (open: boolean) => void;
80
+ /**
81
+ * Rendered inside the default field at its trailing edge, such as a
82
+ * field-mode menu. Ignored with custom `children`, which own their layout.
83
+ */
84
+ trailingAdornment?: ReactNode;
85
+ /** Applied to the default trigger, so a `<label htmlFor>` pointing at it associates correctly. */
86
+ id?: string;
87
+ /** Id of the element naming this control, forwarded to the default trigger. */
88
+ 'aria-labelledby'?: string;
89
+ 'aria-describedby'?: string;
90
+ contentClassName?: string;
91
+ className?: string;
92
+ }
93
+ export declare const joinPath: (segments: string[]) => string;
94
+ /** Collision-free, unlike a `/`-join, should a segment ever contain a `/`. */
95
+ export declare const cacheKey: (segments: string[]) => string;
96
+ /** A name that survives the round trip through a `/`-joined path. */
97
+ export declare const isValidSegment: (name: string) => boolean;
@@ -0,0 +1,4 @@
1
+ const joinPath = (segments)=>`/${segments.join('/')}`;
2
+ const cacheKey = (segments)=>JSON.stringify(segments);
3
+ const isValidSegment = (name)=>'' !== name && !name.includes('/');
4
+ export { cacheKey, isValidSegment, joinPath };