@longd/layout-ui 0.1.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,1098 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ LayoutSelect: () => LayoutSelect,
34
+ LayoutSelectDefault: () => select_default
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/layout/select.tsx
39
+ var React = __toESM(require("react"), 1);
40
+ var import_react = require("react");
41
+ var import_popover = require("@base-ui/react/popover");
42
+ var import_tooltip = require("@base-ui/react/tooltip");
43
+ var import_cmdk = require("cmdk");
44
+ var import_core = require("@dnd-kit/core");
45
+ var import_sortable = require("@dnd-kit/sortable");
46
+ var import_modifiers = require("@dnd-kit/modifiers");
47
+ var import_react_virtual = require("@tanstack/react-virtual");
48
+ var import_lucide_react = require("lucide-react");
49
+
50
+ // src/lib/utils.ts
51
+ var import_clsx = require("clsx");
52
+ var import_tailwind_merge = require("tailwind-merge");
53
+ function cn(...inputs) {
54
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
55
+ }
56
+
57
+ // src/layout/select.tsx
58
+ var import_jsx_runtime = require("react/jsx-runtime");
59
+ function resolveIcon(icon) {
60
+ if (icon === void 0 || icon === null) return null;
61
+ if (typeof icon === "function") return icon();
62
+ return icon;
63
+ }
64
+ function flattenOptions(options) {
65
+ const result = [];
66
+ for (const opt of options) {
67
+ if (opt.children && opt.children.length > 0) {
68
+ result.push(...flattenOptions(opt.children));
69
+ } else {
70
+ result.push(opt);
71
+ }
72
+ }
73
+ return result;
74
+ }
75
+ function buildDisplayRows(options) {
76
+ const rows = [];
77
+ for (const opt of options) {
78
+ if (opt.children && opt.children.length > 0) {
79
+ rows.push({
80
+ kind: "group-header",
81
+ label: opt.label,
82
+ groupValue: opt.value
83
+ });
84
+ for (const child of opt.children) {
85
+ rows.push({ kind: "option", option: child, groupValue: opt.value });
86
+ }
87
+ } else {
88
+ rows.push({ kind: "option", option: opt });
89
+ }
90
+ }
91
+ return rows;
92
+ }
93
+ function hasGroups(options) {
94
+ return options.some((o) => o.children && o.children.length > 0);
95
+ }
96
+ function optionEq(a, b) {
97
+ return a.value === b.value;
98
+ }
99
+ function isSelected(option, value) {
100
+ if (!value) return false;
101
+ if (Array.isArray(value)) return value.some((v) => optionEq(v, option));
102
+ return optionEq(value, option);
103
+ }
104
+ function SortableItem({ id, children, disabled }) {
105
+ const {
106
+ setNodeRef,
107
+ attributes,
108
+ listeners,
109
+ transform,
110
+ transition,
111
+ isDragging
112
+ } = (0, import_sortable.useSortable)({ id, disabled });
113
+ const style = {
114
+ transform: transform ? `translate3d(${transform.x}px, ${transform.y}px, 0)` : void 0,
115
+ transition,
116
+ opacity: isDragging ? 0.5 : 1,
117
+ position: "relative",
118
+ zIndex: isDragging ? 50 : void 0
119
+ };
120
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: setNodeRef, style, className: "flex items-center", children: [
121
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
+ "button",
123
+ {
124
+ type: "button",
125
+ className: "flex shrink-0 cursor-grab items-center px-1 text-muted-foreground hover:text-foreground active:cursor-grabbing",
126
+ ...attributes,
127
+ ...listeners,
128
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.GripVertical, { className: "size-3.5" })
129
+ }
130
+ ),
131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "min-w-0 flex-1", children })
132
+ ] });
133
+ }
134
+ function MaybeTooltip({
135
+ tooltip,
136
+ children
137
+ }) {
138
+ if (!tooltip) return children;
139
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tooltip.Tooltip.Root, { children: [
140
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Trigger, { render: children }),
141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Positioner, { sideOffset: 6, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Popup, { className: "rounded-md bg-foreground px-2.5 py-1 text-xs text-background shadow-md", children: tooltip }) }) })
142
+ ] });
143
+ }
144
+ function Chip({
145
+ option,
146
+ onRemove,
147
+ readOnly,
148
+ disabled,
149
+ className,
150
+ partial
151
+ }) {
152
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
153
+ "span",
154
+ {
155
+ "data-partial-chip": partial || void 0,
156
+ className: cn(
157
+ "inline-flex max-w-35 items-center gap-1 rounded-md border border-border bg-secondary px-2 py-0.5 text-xs leading-5 text-secondary-foreground",
158
+ disabled && "opacity-50",
159
+ className
160
+ ),
161
+ children: [
162
+ option.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex shrink-0 items-center [&_svg]:size-3", children: resolveIcon(option.icon) }),
163
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children: option.label }),
164
+ !readOnly && !disabled && onRemove && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
165
+ "button",
166
+ {
167
+ type: "button",
168
+ className: "ml-0.5 flex shrink-0 items-center rounded-sm text-muted-foreground hover:text-foreground",
169
+ onClick: (e) => {
170
+ e.stopPropagation();
171
+ onRemove();
172
+ },
173
+ tabIndex: -1,
174
+ "aria-label": `Remove ${option.label}`,
175
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "size-3" })
176
+ }
177
+ )
178
+ ]
179
+ }
180
+ );
181
+ }
182
+ function OverflowBadge({
183
+ items,
184
+ onRemove
185
+ }) {
186
+ if (items.length === 0) return null;
187
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tooltip.Tooltip.Root, { children: [
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
189
+ import_tooltip.Tooltip.Trigger,
190
+ {
191
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "inline-flex shrink-0 items-center rounded-md border border-border bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground", children: [
192
+ "+",
193
+ items.length
194
+ ] })
195
+ }
196
+ ),
197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Positioner, { sideOffset: 6, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Popup, { className: "max-w-xs rounded-md bg-foreground px-3 py-2 text-xs text-background shadow-md", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-1", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
198
+ "span",
199
+ {
200
+ className: "inline-flex items-center gap-1 rounded-md border border-background/20 bg-background/10 px-1.5 py-0.5 text-xs leading-4 text-background",
201
+ children: [
202
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex shrink-0 items-center [&_svg]:size-3", children: resolveIcon(item.icon) }),
203
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children: item.label }),
204
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
205
+ "button",
206
+ {
207
+ type: "button",
208
+ className: "ml-0.5 flex shrink-0 items-center rounded-sm text-background/60 hover:text-background",
209
+ onClick: (e) => {
210
+ e.stopPropagation();
211
+ onRemove(item);
212
+ },
213
+ tabIndex: -1,
214
+ "aria-label": `Remove ${item.label}`,
215
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "size-3" })
216
+ }
217
+ )
218
+ ]
219
+ },
220
+ item.value
221
+ )) }) }) }) })
222
+ ] });
223
+ }
224
+ function SingleTriggerContent({
225
+ value,
226
+ placeholder
227
+ }) {
228
+ if (!value) {
229
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate text-muted-foreground", children: placeholder });
230
+ }
231
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-2 truncate", children: [
232
+ value.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex shrink-0 items-center [&_svg]:size-4", children: resolveIcon(value.icon) }),
233
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children: value.label })
234
+ ] });
235
+ }
236
+ function MultipleTriggerContent({
237
+ value,
238
+ placeholder,
239
+ collapsed,
240
+ showItemsLength,
241
+ onRemove,
242
+ readOnly,
243
+ disabled
244
+ }) {
245
+ const chipRowClass = "flex items-center gap-1";
246
+ const wrapperRef = (0, import_react.useRef)(null);
247
+ const measureRef = (0, import_react.useRef)(null);
248
+ const [visibleCount, setVisibleCount] = (0, import_react.useState)(value.length);
249
+ const [lastIsPartial, setLastIsPartial] = (0, import_react.useState)(false);
250
+ const [measured, setMeasured] = (0, import_react.useState)(false);
251
+ const measureCount = Math.min(value.length, 20);
252
+ const calculate = React.useEffectEvent(() => {
253
+ const measureContainer = measureRef.current;
254
+ if (!measureContainer) return;
255
+ const children = Array.from(measureContainer.children);
256
+ const containerRight = measureContainer.getBoundingClientRect().right;
257
+ const gap = parseFloat(getComputedStyle(measureContainer).columnGap) || 0;
258
+ const estimateBadgeWidth = (overflowCount) => overflowCount > 0 ? 14 + 8 * String(overflowCount).length : 0;
259
+ let count = 0;
260
+ let partial = false;
261
+ for (const child of children) {
262
+ const childRight = child.getBoundingClientRect().right;
263
+ const overflow = value.length - (count + 1);
264
+ const reserve = overflow > 0 ? Math.max(40, estimateBadgeWidth(overflow)) : 0;
265
+ if (childRight + reserve <= containerRight) {
266
+ count++;
267
+ } else {
268
+ break;
269
+ }
270
+ }
271
+ count = Math.max(1, count);
272
+ if (count < value.length && children.length >= count) {
273
+ const lastRight = children[count - 1].getBoundingClientRect().right;
274
+ const needsBadge = count + 1 < value.length;
275
+ const badgeReserve = needsBadge ? Math.max(40, estimateBadgeWidth(value.length - count - 1)) : 0;
276
+ const spaceForPartial = containerRight - badgeReserve - lastRight - gap;
277
+ const nextChip = value[count];
278
+ let minPartialWidth = 50;
279
+ if (nextChip.icon && children.length > count) {
280
+ const iconWrapper = children[count].firstElementChild;
281
+ if (iconWrapper) {
282
+ minPartialWidth += iconWrapper.getBoundingClientRect().width + gap;
283
+ }
284
+ }
285
+ if (spaceForPartial >= minPartialWidth) {
286
+ count++;
287
+ partial = true;
288
+ }
289
+ }
290
+ setVisibleCount(count);
291
+ setLastIsPartial(partial);
292
+ setMeasured(true);
293
+ });
294
+ (0, import_react.useLayoutEffect)(() => {
295
+ if (collapsed || value.length === 0) {
296
+ setVisibleCount(value.length);
297
+ setLastIsPartial(false);
298
+ setMeasured(true);
299
+ return;
300
+ }
301
+ const wrapper = wrapperRef.current;
302
+ const container = measureRef.current;
303
+ if (!wrapper || !container) return;
304
+ calculate();
305
+ const observer = new ResizeObserver(calculate);
306
+ observer.observe(wrapper);
307
+ return () => observer.disconnect();
308
+ }, [collapsed, value]);
309
+ if (value.length === 0) {
310
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate text-muted-foreground", children: placeholder });
311
+ }
312
+ const measureLayer = !collapsed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
313
+ "div",
314
+ {
315
+ ref: measureRef,
316
+ className: cn(
317
+ "pointer-events-none absolute inset-0 overflow-hidden opacity-0",
318
+ chipRowClass
319
+ ),
320
+ "aria-hidden": true,
321
+ children: value.slice(0, measureCount).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
322
+ Chip,
323
+ {
324
+ option: opt,
325
+ onRemove: onRemove ? () => {
326
+ } : void 0,
327
+ readOnly,
328
+ disabled,
329
+ className: "shrink-0"
330
+ },
331
+ opt.value
332
+ ))
333
+ }
334
+ );
335
+ const showContent = collapsed || measured;
336
+ if (!showContent) {
337
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
338
+ "div",
339
+ {
340
+ ref: wrapperRef,
341
+ className: cn("relative min-w-0 flex-1 overflow-hidden", chipRowClass),
342
+ children: [
343
+ measureLayer,
344
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "truncate text-muted-foreground", children: [
345
+ value.length,
346
+ " selected"
347
+ ] })
348
+ ]
349
+ }
350
+ );
351
+ }
352
+ let maxVisible = collapsed ? value.length : visibleCount;
353
+ const hasExplicitLimit = !collapsed && showItemsLength !== void 0;
354
+ if (hasExplicitLimit) {
355
+ maxVisible = showItemsLength;
356
+ }
357
+ const hasOverflow = maxVisible < value.length;
358
+ const displayed = value.slice(0, maxVisible);
359
+ const overflowItems = value.slice(maxVisible);
360
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
361
+ "div",
362
+ {
363
+ ref: wrapperRef,
364
+ className: cn("relative min-w-0 flex-1", chipRowClass),
365
+ children: [
366
+ measureLayer,
367
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
368
+ "div",
369
+ {
370
+ className: cn(
371
+ "min-w-0 flex-1",
372
+ chipRowClass,
373
+ collapsed ? "flex-wrap" : "overflow-hidden"
374
+ ),
375
+ children: displayed.map((opt, i) => {
376
+ const isPartial = (hasOverflow || lastIsPartial) && !hasExplicitLimit && i === displayed.length - 1;
377
+ const shouldShrink = isPartial || hasExplicitLimit;
378
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
379
+ Chip,
380
+ {
381
+ option: opt,
382
+ onRemove: onRemove ? () => onRemove(opt) : void 0,
383
+ readOnly,
384
+ disabled,
385
+ partial: isPartial,
386
+ className: shouldShrink ? "min-w-0 shrink" : "shrink-0"
387
+ },
388
+ opt.value
389
+ );
390
+ })
391
+ }
392
+ ),
393
+ overflowItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OverflowBadge, { items: overflowItems, onRemove }) })
394
+ ]
395
+ }
396
+ );
397
+ }
398
+ function OptionRow({
399
+ option,
400
+ selected,
401
+ renderItem,
402
+ onSelect,
403
+ highlighted = false
404
+ }) {
405
+ const content = renderItem ? renderItem(option, {
406
+ selected,
407
+ highlighted,
408
+ disabled: !!option.disabled
409
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
410
+ option.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex shrink-0 items-center [&_svg]:size-4", children: resolveIcon(option.icon) }),
411
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex-1 truncate", children: option.label }),
412
+ selected && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-auto flex shrink-0 items-center text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Check, { className: "size-4" }) })
413
+ ] });
414
+ const row = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
415
+ import_cmdk.Command.Item,
416
+ {
417
+ value: `${option.value}`,
418
+ disabled: option.disabled,
419
+ onSelect: () => {
420
+ if (!option.disabled) onSelect(option);
421
+ },
422
+ className: cn(
423
+ "relative flex w-full cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none",
424
+ "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground",
425
+ option.disabled && "pointer-events-none opacity-50"
426
+ ),
427
+ "data-highlighted": highlighted || void 0,
428
+ children: content
429
+ }
430
+ );
431
+ if (option.disabled && option.disabledTooltip) {
432
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MaybeTooltip, { tooltip: option.disabledTooltip, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: row }) });
433
+ }
434
+ return row;
435
+ }
436
+ function VirtualList({
437
+ options,
438
+ items,
439
+ selectedValue,
440
+ renderItem,
441
+ onSelect,
442
+ sortable,
443
+ sortableAcrossGroups,
444
+ onSortEnd,
445
+ onGroupSortEnd,
446
+ onTreeSort
447
+ }) {
448
+ const parentRef = (0, import_react.useRef)(null);
449
+ const [activeId, setActiveId] = (0, import_react.useState)(null);
450
+ const [dragTree, setDragTree] = (0, import_react.useState)(null);
451
+ const effectiveOptions = dragTree ?? options;
452
+ const grouped = (0, import_react.useMemo)(() => hasGroups(effectiveOptions), [effectiveOptions]);
453
+ const displayRows = (0, import_react.useMemo)(
454
+ () => grouped ? buildDisplayRows(effectiveOptions) : void 0,
455
+ [grouped, effectiveOptions]
456
+ );
457
+ const flatDisplayRows = (0, import_react.useMemo)(
458
+ () => items.map((o) => ({ kind: "option", option: o })),
459
+ [items]
460
+ );
461
+ const virtualItems = displayRows ?? flatDisplayRows;
462
+ const activeIndex = (0, import_react.useMemo)(() => {
463
+ if (!activeId) return null;
464
+ const idx = virtualItems.findIndex(
465
+ (r) => r.kind === "option" && `${r.option.value}` === activeId
466
+ );
467
+ return idx !== -1 ? idx : null;
468
+ }, [activeId, virtualItems]);
469
+ const rangeExtractor = (0, import_react.useCallback)(
470
+ (range) => {
471
+ const result = (0, import_react_virtual.defaultRangeExtractor)(range);
472
+ if (activeIndex !== null && !result.includes(activeIndex)) {
473
+ result.push(activeIndex);
474
+ result.sort((a, b) => a - b);
475
+ }
476
+ return result;
477
+ },
478
+ [activeIndex]
479
+ );
480
+ const virtualizer = (0, import_react_virtual.useVirtualizer)({
481
+ count: virtualItems.length,
482
+ getScrollElement: () => parentRef.current,
483
+ estimateSize: (index) => virtualItems[index].kind === "group-header" ? 28 : 36,
484
+ overscan: 8,
485
+ rangeExtractor
486
+ });
487
+ (0, import_react.useLayoutEffect)(() => {
488
+ virtualizer.measure();
489
+ }, [virtualizer, displayRows]);
490
+ const sensors = (0, import_core.useSensors)(
491
+ (0, import_core.useSensor)(import_core.PointerSensor, { activationConstraint: { distance: 4 } }),
492
+ (0, import_core.useSensor)(import_core.KeyboardSensor)
493
+ );
494
+ const flatSortableIds = (0, import_react.useMemo)(
495
+ () => virtualItems.filter(
496
+ (r) => r.kind === "option"
497
+ ).map((r) => `${r.option.value}`),
498
+ [virtualItems]
499
+ );
500
+ const sameGroupCollision = (0, import_react.useCallback)(
501
+ (args) => {
502
+ if (!displayRows) return (0, import_core.closestCenter)(args);
503
+ const draggedId = args.active.id;
504
+ const activeRow = displayRows.find(
505
+ (r) => r.kind === "option" && `${r.option.value}` === `${draggedId}`
506
+ );
507
+ if (!activeRow || activeRow.kind !== "option") return (0, import_core.closestCenter)(args);
508
+ const activeGroup = activeRow.groupValue;
509
+ const filtered = args.droppableContainers.filter((container) => {
510
+ const row = displayRows.find(
511
+ (r) => r.kind === "option" && `${r.option.value}` === `${container.id}`
512
+ );
513
+ return row && row.kind === "option" && row.groupValue === activeGroup;
514
+ });
515
+ return (0, import_core.closestCenter)({ ...args, droppableContainers: filtered });
516
+ },
517
+ [displayRows]
518
+ );
519
+ const sortingStrategy = (0, import_react.useMemo)(() => {
520
+ if (!grouped || !displayRows) return import_sortable.verticalListSortingStrategy;
521
+ const idToGroup = /* @__PURE__ */ new Map();
522
+ for (const row of displayRows) {
523
+ if (row.kind === "option") {
524
+ idToGroup.set(`${row.option.value}`, row.groupValue);
525
+ }
526
+ }
527
+ const noMove = { x: 0, y: 0, scaleX: 1, scaleY: 1 };
528
+ return (args) => {
529
+ const draggedId = flatSortableIds[args.activeIndex];
530
+ const currentId = flatSortableIds[args.index];
531
+ if (draggedId && currentId && idToGroup.get(draggedId) !== idToGroup.get(currentId)) {
532
+ return noMove;
533
+ }
534
+ return (0, import_sortable.verticalListSortingStrategy)(args);
535
+ };
536
+ }, [grouped, displayRows, flatSortableIds]);
537
+ const handleDragOver = (0, import_react.useCallback)(
538
+ (event) => {
539
+ if (!sortableAcrossGroups || !grouped) return;
540
+ const { active, over } = event;
541
+ if (!over || active.id === over.id) return;
542
+ const currentTree = dragTree ?? options;
543
+ const currentRows = buildDisplayRows(currentTree);
544
+ const activeRow = currentRows.find(
545
+ (r) => r.kind === "option" && `${r.option.value}` === `${active.id}`
546
+ );
547
+ const overRow = currentRows.find(
548
+ (r) => r.kind === "option" && `${r.option.value}` === `${over.id}`
549
+ );
550
+ if (!activeRow || activeRow.kind !== "option" || !overRow || overRow.kind !== "option")
551
+ return;
552
+ if (activeRow.groupValue === overRow.groupValue) return;
553
+ const newTree = currentTree.map((opt) => {
554
+ if (!opt.children) return opt;
555
+ if (opt.value === activeRow.groupValue) {
556
+ return {
557
+ ...opt,
558
+ children: opt.children.filter(
559
+ (c) => `${c.value}` !== `${active.id}`
560
+ )
561
+ };
562
+ }
563
+ if (opt.value === overRow.groupValue) {
564
+ const destChildren = opt.children.filter(
565
+ (c) => `${c.value}` !== `${active.id}`
566
+ );
567
+ const overIdx = destChildren.findIndex(
568
+ (c) => `${c.value}` === `${over.id}`
569
+ );
570
+ destChildren.splice(
571
+ overIdx !== -1 ? overIdx : destChildren.length,
572
+ 0,
573
+ activeRow.option
574
+ );
575
+ return { ...opt, children: destChildren };
576
+ }
577
+ return opt;
578
+ });
579
+ setDragTree(newTree);
580
+ },
581
+ [sortableAcrossGroups, grouped, dragTree, options]
582
+ );
583
+ const handleDragEndFlat = (0, import_react.useCallback)(
584
+ (event) => {
585
+ setActiveId(null);
586
+ setDragTree(null);
587
+ const { active, over } = event;
588
+ if (!over || active.id === over.id || !onSortEnd) return;
589
+ const oldIndex = items.findIndex((i) => `${i.value}` === `${active.id}`);
590
+ const newIndex = items.findIndex((i) => `${i.value}` === `${over.id}`);
591
+ if (oldIndex !== -1 && newIndex !== -1) {
592
+ onSortEnd((0, import_sortable.arrayMove)(items, oldIndex, newIndex));
593
+ }
594
+ },
595
+ [items, onSortEnd]
596
+ );
597
+ const handleDragEndGrouped = (0, import_react.useCallback)(
598
+ (event) => {
599
+ setActiveId(null);
600
+ const { active, over } = event;
601
+ if (!over || active.id === over.id) {
602
+ if (dragTree) onTreeSort?.(dragTree);
603
+ setDragTree(null);
604
+ return;
605
+ }
606
+ if (!displayRows) {
607
+ setDragTree(null);
608
+ return;
609
+ }
610
+ const activeRow = displayRows.find(
611
+ (r) => r.kind === "option" && `${r.option.value}` === `${active.id}`
612
+ );
613
+ const overRow = displayRows.find(
614
+ (r) => r.kind === "option" && `${r.option.value}` === `${over.id}`
615
+ );
616
+ if (!activeRow || activeRow.kind !== "option" || !overRow || overRow.kind !== "option") {
617
+ setDragTree(null);
618
+ return;
619
+ }
620
+ const activeGroup = activeRow.groupValue;
621
+ const overGroup = overRow.groupValue;
622
+ const baseTree = dragTree ?? options;
623
+ if (activeGroup === overGroup) {
624
+ const groupChildren = displayRows.filter(
625
+ (r) => r.kind === "option" && r.groupValue === activeGroup
626
+ ).map((r) => r.option);
627
+ const oldIdx = groupChildren.findIndex(
628
+ (i) => `${i.value}` === `${active.id}`
629
+ );
630
+ const newIdx = groupChildren.findIndex(
631
+ (i) => `${i.value}` === `${over.id}`
632
+ );
633
+ if (oldIdx !== -1 && newIdx !== -1 && oldIdx !== newIdx) {
634
+ const reordered = (0, import_sortable.arrayMove)(groupChildren, oldIdx, newIdx);
635
+ if (dragTree) {
636
+ const finalTree = baseTree.map((opt) => {
637
+ if (opt.value === activeGroup && opt.children) {
638
+ return { ...opt, children: reordered };
639
+ }
640
+ return opt;
641
+ });
642
+ onTreeSort?.(finalTree);
643
+ } else {
644
+ onGroupSortEnd?.(activeGroup, reordered);
645
+ }
646
+ } else if (dragTree) {
647
+ onTreeSort?.(baseTree);
648
+ }
649
+ } else {
650
+ const finalTree = baseTree.map((opt) => {
651
+ if (!opt.children) return opt;
652
+ if (opt.value === activeGroup) {
653
+ return {
654
+ ...opt,
655
+ children: opt.children.filter(
656
+ (c) => `${c.value}` !== `${active.id}`
657
+ )
658
+ };
659
+ }
660
+ if (opt.value === overGroup) {
661
+ const destChildren = [...opt.children];
662
+ const overIdx = destChildren.findIndex(
663
+ (c) => `${c.value}` === `${over.id}`
664
+ );
665
+ destChildren.splice(
666
+ overIdx !== -1 ? overIdx + 1 : destChildren.length,
667
+ 0,
668
+ activeRow.option
669
+ );
670
+ return { ...opt, children: destChildren };
671
+ }
672
+ return opt;
673
+ });
674
+ onTreeSort?.(finalTree);
675
+ }
676
+ setDragTree(null);
677
+ },
678
+ [dragTree, options, displayRows, onTreeSort, onGroupSortEnd]
679
+ );
680
+ const listContent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
681
+ "div",
682
+ {
683
+ ref: parentRef,
684
+ className: cn(
685
+ "max-h-75 overflow-x-hidden",
686
+ activeIndex !== null ? "overflow-y-visible" : "overflow-y-auto"
687
+ ),
688
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
689
+ "div",
690
+ {
691
+ style: {
692
+ height: `${virtualizer.getTotalSize()}px`,
693
+ position: "relative",
694
+ width: "100%"
695
+ },
696
+ children: virtualizer.getVirtualItems().map((vItem) => {
697
+ const displayRow = virtualItems[vItem.index];
698
+ if (displayRow.kind === "group-header") {
699
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
700
+ "div",
701
+ {
702
+ style: {
703
+ position: "absolute",
704
+ top: 0,
705
+ left: 0,
706
+ width: "100%",
707
+ transform: `translateY(${vItem.start}px)`
708
+ },
709
+ "data-index": vItem.index,
710
+ ref: virtualizer.measureElement,
711
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2 py-1 text-xs font-semibold text-muted-foreground", children: displayRow.label })
712
+ },
713
+ `gh-${displayRow.groupValue}`
714
+ );
715
+ }
716
+ const option = displayRow.option;
717
+ const row = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
718
+ OptionRow,
719
+ {
720
+ option,
721
+ selected: isSelected(option, selectedValue),
722
+ renderItem,
723
+ onSelect
724
+ },
725
+ option.value
726
+ );
727
+ const wrappedRow = sortable ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
728
+ SortableItem,
729
+ {
730
+ id: `${option.value}`,
731
+ disabled: option.disabled,
732
+ children: row
733
+ },
734
+ option.value
735
+ ) : row;
736
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
737
+ "div",
738
+ {
739
+ style: {
740
+ position: "absolute",
741
+ top: 0,
742
+ left: 0,
743
+ width: "100%",
744
+ transform: `translateY(${vItem.start}px)`
745
+ },
746
+ "data-index": vItem.index,
747
+ ref: virtualizer.measureElement,
748
+ children: wrappedRow
749
+ },
750
+ option.value
751
+ );
752
+ })
753
+ }
754
+ )
755
+ }
756
+ );
757
+ if (sortable) {
758
+ const handleDragStart = (event) => {
759
+ setActiveId(`${event.active.id}`);
760
+ };
761
+ const handleCancel = () => {
762
+ setActiveId(null);
763
+ setDragTree(null);
764
+ };
765
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
766
+ import_core.DndContext,
767
+ {
768
+ modifiers: [import_modifiers.restrictToVerticalAxis, import_modifiers.restrictToFirstScrollableAncestor],
769
+ sensors,
770
+ collisionDetection: grouped && !sortableAcrossGroups ? sameGroupCollision : import_core.closestCenter,
771
+ onDragStart: handleDragStart,
772
+ onDragOver: handleDragOver,
773
+ onDragEnd: grouped ? handleDragEndGrouped : handleDragEndFlat,
774
+ onDragCancel: handleCancel,
775
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sortable.SortableContext, { items: flatSortableIds, strategy: sortingStrategy, children: listContent })
776
+ }
777
+ );
778
+ }
779
+ return listContent;
780
+ }
781
+ function LayoutSelect(props) {
782
+ const {
783
+ type,
784
+ options,
785
+ placeholder = "Select item",
786
+ disabled = false,
787
+ readOnly = false,
788
+ error = false,
789
+ clearable = false,
790
+ className,
791
+ triggerClassName,
792
+ popupClassName,
793
+ renderTrigger,
794
+ renderItem,
795
+ listPrefix,
796
+ listSuffix,
797
+ queryFn,
798
+ label
799
+ } = props;
800
+ const [open, setOpen] = (0, import_react.useState)(false);
801
+ const [search, setSearch] = (0, import_react.useState)("");
802
+ const [asyncOptions, setAsyncOptions] = (0, import_react.useState)(null);
803
+ const [loading, setLoading] = (0, import_react.useState)(false);
804
+ const [internalSortedOptions, setInternalSortedOptions] = (0, import_react.useState)(null);
805
+ const currentValue = (0, import_react.useMemo)(() => {
806
+ if (type === "single") {
807
+ return props.selectValue ?? null;
808
+ }
809
+ return props.selectValue ?? [];
810
+ }, [type, props]);
811
+ const resolvedOptions = (0, import_react.useMemo)(() => {
812
+ const base = asyncOptions ?? options;
813
+ return internalSortedOptions ?? base;
814
+ }, [asyncOptions, options, internalSortedOptions]);
815
+ const flatOptions = (0, import_react.useMemo)(
816
+ () => flattenOptions(resolvedOptions),
817
+ [resolvedOptions]
818
+ );
819
+ const filteredOptions = (0, import_react.useMemo)(() => {
820
+ if (!search) return flatOptions;
821
+ const q = search.toLowerCase();
822
+ return flatOptions.filter((o) => o.label.toLowerCase().includes(q));
823
+ }, [flatOptions, search]);
824
+ const filteredGroupedOptions = (0, import_react.useMemo)(() => {
825
+ if (!search) return resolvedOptions;
826
+ const q = search.toLowerCase();
827
+ return resolvedOptions.map((opt) => {
828
+ if (opt.children && opt.children.length > 0) {
829
+ const matched = opt.children.filter(
830
+ (c) => c.label.toLowerCase().includes(q)
831
+ );
832
+ if (matched.length === 0) return null;
833
+ return { ...opt, children: matched };
834
+ }
835
+ return opt.label.toLowerCase().includes(q) ? opt : null;
836
+ }).filter(Boolean);
837
+ }, [resolvedOptions, search]);
838
+ (0, import_react.useEffect)(() => {
839
+ if (open && queryFn) {
840
+ let cancelled = false;
841
+ setLoading(true);
842
+ queryFn().then((data) => {
843
+ if (!cancelled) {
844
+ setAsyncOptions(data);
845
+ }
846
+ }).finally(() => {
847
+ if (!cancelled) setLoading(false);
848
+ });
849
+ return () => {
850
+ cancelled = true;
851
+ };
852
+ }
853
+ }, [open, queryFn]);
854
+ (0, import_react.useEffect)(() => {
855
+ if (!open) {
856
+ setSearch("");
857
+ }
858
+ }, [open]);
859
+ const handleSelect = (0, import_react.useCallback)(
860
+ (option) => {
861
+ if (readOnly) return;
862
+ if (type === "single") {
863
+ const onChange = props.onChange;
864
+ const current = currentValue;
865
+ if (clearable && current && optionEq(current, option)) {
866
+ onChange?.(null, option);
867
+ } else {
868
+ onChange?.(option, option);
869
+ }
870
+ setOpen(false);
871
+ } else {
872
+ const onChange = props.onChange;
873
+ const current = currentValue;
874
+ const exists = current.some((v) => optionEq(v, option));
875
+ if (exists) {
876
+ onChange?.(
877
+ current.filter((v) => !optionEq(v, option)),
878
+ option
879
+ );
880
+ } else {
881
+ onChange?.([...current, option], option);
882
+ }
883
+ }
884
+ },
885
+ [type, currentValue, clearable, readOnly, props]
886
+ );
887
+ const handleRemoveChip = (0, import_react.useCallback)(
888
+ (option) => {
889
+ if (type !== "multiple" || readOnly || disabled) return;
890
+ const onChange = props.onChange;
891
+ const current = currentValue;
892
+ onChange?.(
893
+ current.filter((v) => !optionEq(v, option)),
894
+ option
895
+ );
896
+ },
897
+ [type, currentValue, readOnly, disabled, props]
898
+ );
899
+ const handleToggleAll = (0, import_react.useCallback)(() => {
900
+ if (type !== "multiple" || readOnly || disabled) return;
901
+ const onChange = props.onChange;
902
+ const current = currentValue;
903
+ const selectableOptions = flatOptions.filter((o) => !o.disabled);
904
+ const allSelected2 = selectableOptions.length > 0 && selectableOptions.every((o) => current.some((v) => optionEq(v, o)));
905
+ if (allSelected2) {
906
+ const kept = current.filter(
907
+ (v) => selectableOptions.every((o) => !optionEq(o, v))
908
+ );
909
+ onChange?.(kept, selectableOptions[0]);
910
+ } else {
911
+ const missing = selectableOptions.filter(
912
+ (o) => !current.some((v) => optionEq(v, o))
913
+ );
914
+ onChange?.([...current, ...missing], selectableOptions[0]);
915
+ }
916
+ }, [type, currentValue, flatOptions, readOnly, disabled, props]);
917
+ const allSelected = (0, import_react.useMemo)(() => {
918
+ if (type !== "multiple") return false;
919
+ const current = currentValue;
920
+ const selectableOptions = flatOptions.filter((o) => !o.disabled);
921
+ return selectableOptions.length > 0 && selectableOptions.every((o) => current.some((v) => optionEq(v, o)));
922
+ }, [type, currentValue, flatOptions]);
923
+ const sortable = props.sortable ?? false;
924
+ const sortableAcrossGroups = props.sortable ? props.sortableAcrossGroups ?? false : false;
925
+ const consumerOnSortEnd = props.sortable ? props.onSortEnd : void 0;
926
+ const handleSortEnd = (0, import_react.useCallback)(
927
+ (sorted) => {
928
+ setInternalSortedOptions(sorted);
929
+ consumerOnSortEnd?.(sorted);
930
+ },
931
+ [consumerOnSortEnd]
932
+ );
933
+ const handleGroupSortEnd = (0, import_react.useCallback)(
934
+ (groupValue, reorderedChildren) => {
935
+ const updated = resolvedOptions.map((opt) => {
936
+ if (opt.value === groupValue && opt.children) {
937
+ return { ...opt, children: reorderedChildren };
938
+ }
939
+ return opt;
940
+ });
941
+ setInternalSortedOptions(updated);
942
+ consumerOnSortEnd?.(flattenOptions(updated));
943
+ },
944
+ [resolvedOptions, consumerOnSortEnd]
945
+ );
946
+ const handleTreeSort = (0, import_react.useCallback)(
947
+ (newTree) => {
948
+ setInternalSortedOptions(newTree);
949
+ consumerOnSortEnd?.(flattenOptions(newTree));
950
+ },
951
+ [consumerOnSortEnd]
952
+ );
953
+ const handleOpenChange = (0, import_react.useCallback)(
954
+ (nextOpen) => {
955
+ if (disabled || readOnly) return;
956
+ setOpen(nextOpen);
957
+ },
958
+ [disabled, readOnly]
959
+ );
960
+ const triggerContent = (0, import_react.useMemo)(() => {
961
+ if (renderTrigger) {
962
+ return renderTrigger({
963
+ value: currentValue,
964
+ open,
965
+ disabled,
966
+ readOnly,
967
+ error,
968
+ placeholder
969
+ });
970
+ }
971
+ if (type === "single") {
972
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
973
+ SingleTriggerContent,
974
+ {
975
+ value: currentValue,
976
+ placeholder
977
+ }
978
+ );
979
+ }
980
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
981
+ MultipleTriggerContent,
982
+ {
983
+ value: currentValue,
984
+ placeholder,
985
+ collapsed: props.collapsed,
986
+ showItemsLength: props.showItemsLength,
987
+ onRemove: handleRemoveChip,
988
+ readOnly,
989
+ disabled
990
+ }
991
+ );
992
+ }, [
993
+ renderTrigger,
994
+ type,
995
+ currentValue,
996
+ open,
997
+ disabled,
998
+ readOnly,
999
+ error,
1000
+ placeholder,
1001
+ props,
1002
+ handleRemoveChip
1003
+ ]);
1004
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip.Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("relative inline-flex flex-col", className), children: [
1005
+ label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mb-1 text-sm font-medium text-foreground", children: label }),
1006
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_popover.Popover.Root, { open, onOpenChange: handleOpenChange, children: [
1007
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1008
+ import_popover.Popover.Trigger,
1009
+ {
1010
+ disabled,
1011
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1012
+ "button",
1013
+ {
1014
+ type: "button",
1015
+ "aria-expanded": open,
1016
+ "aria-haspopup": "listbox",
1017
+ "aria-invalid": error || void 0,
1018
+ "data-readonly": readOnly || void 0,
1019
+ className: cn(
1020
+ "border-input flex min-h-9 w-full min-w-45 items-center gap-2 rounded-md border bg-transparent px-3 py-1.5 text-sm shadow-xs transition-[color,box-shadow,border-color] outline-none",
1021
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1022
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
1023
+ "data-readonly:pointer-events-none data-readonly:opacity-70",
1024
+ "disabled:cursor-not-allowed disabled:opacity-50",
1025
+ "[&_svg:not([class*='text-'])]:text-muted-foreground",
1026
+ triggerClassName
1027
+ )
1028
+ }
1029
+ ),
1030
+ children: [
1031
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-w-0 flex-1 items-center", children: triggerContent }),
1032
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronDown, { className: "size-4 shrink-0 opacity-50" })
1033
+ ]
1034
+ }
1035
+ ),
1036
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_popover.Popover.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_popover.Popover.Positioner, { sideOffset: 4, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1037
+ import_popover.Popover.Popup,
1038
+ {
1039
+ className: cn(
1040
+ "z-50 min-w-(--anchor-width) rounded-md border bg-popover text-popover-foreground shadow-md outline-none",
1041
+ "data-starting-style:scale-95 data-starting-style:opacity-0",
1042
+ "data-ending-style:scale-95 data-ending-style:opacity-0",
1043
+ "origin-(--transform-origin) transition-[transform,scale,opacity] duration-150",
1044
+ popupClassName
1045
+ ),
1046
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_cmdk.Command, { shouldFilter: false, loop: true, children: [
1047
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border-b p-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1048
+ import_cmdk.Command.Input,
1049
+ {
1050
+ value: search,
1051
+ onValueChange: setSearch,
1052
+ placeholder: "Search...",
1053
+ className: "h-8 w-full rounded-sm bg-transparent px-2 text-sm outline-none placeholder:text-muted-foreground"
1054
+ }
1055
+ ) }),
1056
+ listPrefix && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border-b px-2 py-1.5", children: listPrefix }),
1057
+ type === "multiple" && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border-b px-1 py-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1058
+ "button",
1059
+ {
1060
+ type: "button",
1061
+ onClick: handleToggleAll,
1062
+ className: "w-full rounded-sm px-2 py-1 text-left text-sm text-muted-foreground hover:bg-accent hover:text-accent-foreground",
1063
+ children: allSelected ? "Unselect all" : "Select all"
1064
+ }
1065
+ ) }),
1066
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_cmdk.Command.List, { className: "p-1", children: [
1067
+ loading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_cmdk.Command.Loading, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center justify-center py-4 text-sm text-muted-foreground", children: "Loading\u2026" }) }),
1068
+ !loading && filteredOptions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_cmdk.Command.Empty, { className: "py-4 text-center text-sm text-muted-foreground", children: "No results found." }),
1069
+ !loading && filteredOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1070
+ VirtualList,
1071
+ {
1072
+ options: filteredGroupedOptions,
1073
+ items: filteredOptions,
1074
+ selectedValue: currentValue,
1075
+ renderItem,
1076
+ onSelect: handleSelect,
1077
+ sortable,
1078
+ sortableAcrossGroups,
1079
+ onSortEnd: handleSortEnd,
1080
+ onGroupSortEnd: handleGroupSortEnd,
1081
+ onTreeSort: handleTreeSort
1082
+ }
1083
+ )
1084
+ ] }),
1085
+ listSuffix && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border-t px-2 py-1.5", children: listSuffix })
1086
+ ] })
1087
+ }
1088
+ ) }) })
1089
+ ] })
1090
+ ] }) });
1091
+ }
1092
+ var select_default = LayoutSelect;
1093
+ // Annotate the CommonJS export names for ESM import in node:
1094
+ 0 && (module.exports = {
1095
+ LayoutSelect,
1096
+ LayoutSelectDefault
1097
+ });
1098
+ //# sourceMappingURL=index.cjs.map