@wow-two-beta/ui 0.0.41 → 0.0.42

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.
@@ -1,4 +1,4 @@
1
- import { listboxVariants, listboxItemVariants, listboxGroupLabelVariants, listboxSeparatorVariants, listboxEmptyVariants } from './chunk-G4H4EDAC.js';
1
+ import { listboxItemVariants, listboxVariants, listboxGroupLabelVariants, listboxSeparatorVariants, listboxEmptyVariants } from './chunk-G4H4EDAC.js';
2
2
  import { PopoverTrigger, Popover, PopoverContent } from './chunk-VDE5B3IY.js';
3
3
  import { startOfMonth, isSameDay, isToday, isDateDisabled, parseISODate, formatISODate, parseISOTime, Tag, addMonths, Kbd, addDays, buildMonthGrid, MONTHS_LONG, WEEKDAYS_SHORT, formatISOTime, startOfDay, isInRange } from './chunk-LFZV2XTZ.js';
4
4
  import { useControlled } from './chunk-NUMFGKPY.js';
@@ -8,9 +8,9 @@ import { useFormControl, FormControlProvider, RovingFocusGroup, useRovingFocusIt
8
8
  import { useId } from './chunk-KDXJQNB6.js';
9
9
  import { cn, composeRefs } from './chunk-LDRFQG44.js';
10
10
  import * as React from 'react';
11
- import { forwardRef, useRef, useImperativeHandle, useState, Children, isValidElement, cloneElement, useId as useId$1, createContext, useMemo, useCallback, useEffect, Fragment as Fragment$1, useContext } from 'react';
11
+ import { forwardRef, useRef, useImperativeHandle, useState, Children, isValidElement, cloneElement, useId as useId$1, createContext, useEffect, useMemo, useCallback, Fragment as Fragment$1, useContext } from 'react';
12
12
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
- import { Minus, Plus, EyeOff, Eye, Search, X, Check, Upload, ChevronDown, Calendar as Calendar$1, Clock, UploadCloud, ChevronRight, Copy, Zap, Wallet, Video, User, Trash, Tag as Tag$1, Sun, Star, ShoppingCart, Share2, Settings, Send, Play, Pin, Phone, Pencil, Paperclip, Music, Moon, Mic, MessageCircle, Map as Map$1, Mail, Lock, Link2, Lightbulb, Layers, Info, Inbox, Image, Home, Heart, Globe, Folder, File, ExternalLink, Edit, Download, Compass, Coffee, Code, Cloud, Camera, Bookmark, Bell, ChevronLeft, Heading1, Heading2, Bold, Italic, List, Quote } from 'lucide-react';
13
+ import { Minus, Plus, EyeOff, Eye, Search, X, Check, Upload, Loader2, ChevronDown, Calendar as Calendar$1, Clock, UploadCloud, ChevronRight, Copy, Zap, Wallet, Video, User, Trash, Tag as Tag$1, Sun, Star, ShoppingCart, Share2, Settings, Send, Play, Pin, Phone, Pencil, Paperclip, Music, Moon, Mic, MessageCircle, Map as Map$1, Mail, Lock, Link2, Lightbulb, Layers, Info, Inbox, Image, Home, Heart, Globe, Folder, File, ExternalLink, Edit, Download, Compass, Coffee, Code, Cloud, Camera, Bookmark, Bell, ChevronLeft, Heading1, Heading2, Bold, Italic, List, Quote } from 'lucide-react';
14
14
  import { marked } from 'marked';
15
15
 
16
16
  var Label = forwardRef(
@@ -432,13 +432,133 @@ var Textarea = forwardRef(
432
432
  }
433
433
  );
434
434
  Textarea.displayName = "Textarea";
435
+
436
+ // src/forms/checkbox/Checkbox.variants.ts
437
+ var checkboxVariants = tv({
438
+ base: "pointer-events-none grid h-full w-full place-items-center rounded-sm border transition-colors peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-1 peer-disabled:opacity-50",
439
+ variants: {
440
+ variant: {
441
+ solid: "border-input bg-background",
442
+ soft: "border-transparent",
443
+ outline: "bg-transparent",
444
+ ghost: "border-transparent bg-transparent",
445
+ glass: "border-white/40 bg-black/40 backdrop-blur-sm",
446
+ "glass-surface": "border-white/60 bg-black/40 backdrop-blur-sm"
447
+ },
448
+ tone: {
449
+ primary: "",
450
+ neutral: "",
451
+ danger: "",
452
+ success: "",
453
+ warning: ""
454
+ }
455
+ },
456
+ compoundVariants: [
457
+ // === SOLID × tone — bg-background unchecked → tone fill checked ===
458
+ { variant: "solid", tone: "primary", class: "text-primary-foreground peer-checked:border-primary peer-checked:bg-primary" },
459
+ { variant: "solid", tone: "neutral", class: "text-background peer-checked:border-foreground peer-checked:bg-foreground" },
460
+ { variant: "solid", tone: "danger", class: "text-destructive-foreground peer-checked:border-destructive peer-checked:bg-destructive" },
461
+ { variant: "solid", tone: "success", class: "text-success-foreground peer-checked:border-success peer-checked:bg-success" },
462
+ { variant: "solid", tone: "warning", class: "text-warning-foreground peer-checked:border-warning peer-checked:bg-warning" },
463
+ // === SOFT × tone — soft bg unchecked → strong tone fill checked ===
464
+ { variant: "soft", tone: "primary", class: "bg-primary-soft text-primary-soft-foreground peer-checked:bg-primary peer-checked:text-primary-foreground" },
465
+ { variant: "soft", tone: "neutral", class: "bg-muted text-foreground peer-checked:bg-foreground peer-checked:text-background" },
466
+ { variant: "soft", tone: "danger", class: "bg-destructive-soft text-destructive-soft-foreground peer-checked:bg-destructive peer-checked:text-destructive-foreground" },
467
+ { variant: "soft", tone: "success", class: "bg-success-soft text-success-soft-foreground peer-checked:bg-success peer-checked:text-success-foreground" },
468
+ { variant: "soft", tone: "warning", class: "bg-warning-soft text-warning-soft-foreground peer-checked:bg-warning peer-checked:text-warning-foreground" },
469
+ // === OUTLINE × tone — tone border unchecked → tone fill checked ===
470
+ { variant: "outline", tone: "primary", class: "border-primary text-primary peer-checked:bg-primary peer-checked:text-primary-foreground" },
471
+ { variant: "outline", tone: "neutral", class: "border-border-strong text-foreground peer-checked:bg-foreground peer-checked:text-background" },
472
+ { variant: "outline", tone: "danger", class: "border-destructive text-destructive peer-checked:bg-destructive peer-checked:text-destructive-foreground" },
473
+ { variant: "outline", tone: "success", class: "border-success text-success peer-checked:bg-success peer-checked:text-success-foreground" },
474
+ { variant: "outline", tone: "warning", class: "border-warning text-warning peer-checked:bg-warning peer-checked:text-warning-foreground" },
475
+ // === GHOST × tone — no border/bg unchecked → tone-tinted bg + tone check checked ===
476
+ { variant: "ghost", tone: "primary", class: "text-primary peer-checked:bg-primary/10" },
477
+ { variant: "ghost", tone: "neutral", class: "text-foreground peer-checked:bg-muted" },
478
+ { variant: "ghost", tone: "danger", class: "text-destructive peer-checked:bg-destructive/10" },
479
+ { variant: "ghost", tone: "success", class: "text-success peer-checked:bg-success/10" },
480
+ { variant: "ghost", tone: "warning", class: "text-warning peer-checked:bg-warning/10" },
481
+ // === GLASS × tone — dark glass unchecked → tone fill checked, white check throughout ===
482
+ { variant: "glass", tone: "primary", class: "text-white peer-checked:bg-primary peer-checked:border-primary" },
483
+ { variant: "glass", tone: "neutral", class: "text-white peer-checked:bg-foreground peer-checked:border-foreground peer-checked:text-background" },
484
+ { variant: "glass", tone: "danger", class: "text-white peer-checked:bg-destructive peer-checked:border-destructive" },
485
+ { variant: "glass", tone: "success", class: "text-white peer-checked:bg-success peer-checked:border-success" },
486
+ { variant: "glass", tone: "warning", class: "text-white peer-checked:bg-warning peer-checked:border-warning" },
487
+ // === GLASS-SURFACE × tone — same as glass but border stays light when checked ===
488
+ { variant: "glass-surface", tone: "primary", class: "text-white peer-checked:bg-primary peer-checked:border-white/60" },
489
+ { variant: "glass-surface", tone: "neutral", class: "text-white peer-checked:bg-foreground peer-checked:border-white/60 peer-checked:text-background" },
490
+ { variant: "glass-surface", tone: "danger", class: "text-white peer-checked:bg-destructive peer-checked:border-white/60" },
491
+ { variant: "glass-surface", tone: "success", class: "text-white peer-checked:bg-success peer-checked:border-white/60" },
492
+ { variant: "glass-surface", tone: "warning", class: "text-white peer-checked:bg-warning peer-checked:border-white/60" }
493
+ ],
494
+ defaultVariants: {
495
+ variant: "solid",
496
+ tone: "primary"
497
+ }
498
+ });
499
+ var COMPONENT_NAME = "Checkbox";
435
500
  var SIZE_CLASS = {
436
501
  sm: "h-4 w-4",
437
502
  md: "h-5 w-5",
438
503
  lg: "h-6 w-6"
439
504
  };
505
+ var INDETERMINATE_CHECKED_CLASS = {
506
+ solid: {
507
+ primary: "bg-primary border-primary text-primary-foreground",
508
+ neutral: "bg-foreground border-foreground text-background",
509
+ danger: "bg-destructive border-destructive text-destructive-foreground",
510
+ success: "bg-success border-success text-success-foreground",
511
+ warning: "bg-warning border-warning text-warning-foreground"
512
+ },
513
+ soft: {
514
+ primary: "bg-primary text-primary-foreground",
515
+ neutral: "bg-foreground text-background",
516
+ danger: "bg-destructive text-destructive-foreground",
517
+ success: "bg-success text-success-foreground",
518
+ warning: "bg-warning text-warning-foreground"
519
+ },
520
+ outline: {
521
+ primary: "bg-primary text-primary-foreground",
522
+ neutral: "bg-foreground text-background",
523
+ danger: "bg-destructive text-destructive-foreground",
524
+ success: "bg-success text-success-foreground",
525
+ warning: "bg-warning text-warning-foreground"
526
+ },
527
+ ghost: {
528
+ primary: "bg-primary/10 text-primary",
529
+ neutral: "bg-muted text-foreground",
530
+ danger: "bg-destructive/10 text-destructive",
531
+ success: "bg-success/10 text-success",
532
+ warning: "bg-warning/10 text-warning"
533
+ },
534
+ glass: {
535
+ primary: "bg-primary border-primary text-white",
536
+ neutral: "bg-foreground border-foreground text-background",
537
+ danger: "bg-destructive border-destructive text-white",
538
+ success: "bg-success border-success text-white",
539
+ warning: "bg-warning border-warning text-white"
540
+ },
541
+ "glass-surface": {
542
+ primary: "bg-primary border-white/60 text-white",
543
+ neutral: "bg-foreground border-white/60 text-background",
544
+ danger: "bg-destructive border-white/60 text-white",
545
+ success: "bg-success border-white/60 text-white",
546
+ warning: "bg-warning border-white/60 text-white"
547
+ }
548
+ };
440
549
  var Checkbox = forwardRef(
441
- ({ className, size = "md", indeterminate, id, disabled, required, checked, ...props }, ref) => {
550
+ ({
551
+ className,
552
+ size = "md",
553
+ indeterminate,
554
+ variant = "solid",
555
+ tone = "primary",
556
+ id,
557
+ disabled,
558
+ required,
559
+ checked,
560
+ ...props
561
+ }, ref) => {
442
562
  const ctx = useFormControl();
443
563
  const isDisabled = disabled ?? ctx?.isDisabled;
444
564
  return /* @__PURE__ */ jsxs("span", { className: cn("relative inline-flex shrink-0", SIZE_CLASS[size], className), children: [
@@ -462,19 +582,16 @@ var Checkbox = forwardRef(
462
582
  {
463
583
  "aria-hidden": "true",
464
584
  className: cn(
465
- "pointer-events-none grid h-full w-full place-items-center rounded-sm border border-input bg-background text-primary-foreground transition-colors",
466
- "peer-checked:border-primary peer-checked:bg-primary",
467
- "peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-1",
468
- "peer-disabled:opacity-50",
469
- indeterminate && "border-primary bg-primary"
585
+ checkboxVariants({ variant, tone }),
586
+ indeterminate && INDETERMINATE_CHECKED_CLASS[variant][tone]
470
587
  ),
471
- children: indeterminate ? /* @__PURE__ */ jsx(Minus, { size: Math.round(SIZE_CLASS[size].length * 1.4), className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Check, { className: "h-3 w-3 opacity-0 peer-checked:opacity-100" })
588
+ children: indeterminate ? /* @__PURE__ */ jsx(Minus, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Check, { className: "h-3 w-3 opacity-0 peer-checked:opacity-100" })
472
589
  }
473
590
  )
474
591
  ] });
475
592
  }
476
593
  );
477
- Checkbox.displayName = "Checkbox";
594
+ Checkbox.displayName = COMPONENT_NAME;
478
595
  var SIZE_CLASS2 = {
479
596
  sm: "h-4 w-4",
480
597
  md: "h-5 w-5",
@@ -1117,42 +1234,43 @@ var FilePicker = forwardRef(
1117
1234
  }
1118
1235
  );
1119
1236
  FilePicker.displayName = "FilePicker";
1237
+ var defaultEquals = (a, b) => Object.is(a, b);
1120
1238
  var ListboxContext = createContext(null);
1121
1239
  function useListboxContext() {
1122
1240
  const ctx = useContext(ListboxContext);
1123
1241
  if (!ctx) throw new Error("Listbox.Item / Group / Separator must be used inside <Listbox>");
1124
1242
  return ctx;
1125
1243
  }
1126
- var Listbox = forwardRef(function Listbox2(props, ref) {
1244
+ function ListboxImpl(props, ref) {
1127
1245
  const {
1128
1246
  multiple = false,
1129
1247
  value,
1130
1248
  defaultValue,
1131
1249
  onValueChange,
1250
+ isEqual,
1132
1251
  disabled,
1133
1252
  className,
1134
1253
  children,
1135
1254
  onKeyDown,
1136
1255
  ...rest
1137
1256
  } = props;
1138
- const initial = defaultValue ?? (multiple ? [] : "");
1257
+ const equals = isEqual ?? defaultEquals;
1258
+ const initial = defaultValue ?? (multiple ? [] : void 0);
1139
1259
  const [current, setCurrent] = useControlled({
1140
1260
  controlled: value,
1141
1261
  default: initial,
1142
1262
  onChange: onValueChange
1143
1263
  });
1144
- const values = useMemo(
1145
- () => Array.isArray(current) ? current : current ? [current] : [],
1146
- [current]
1147
- );
1264
+ const values = useMemo(() => {
1265
+ if (Array.isArray(current)) return current;
1266
+ return current === void 0 ? [] : [current];
1267
+ }, [current]);
1148
1268
  const items = useRef([]);
1149
1269
  const [activeId, setActiveId] = useState(null);
1150
1270
  const registerItem = useCallback((entry) => {
1151
- if (!items.current.some((i) => i.id === entry.id)) items.current.push(entry);
1152
- }, []);
1153
- const updateItem = useCallback((entry) => {
1154
1271
  const idx = items.current.findIndex((i) => i.id === entry.id);
1155
1272
  if (idx >= 0) items.current[idx] = entry;
1273
+ else items.current.push(entry);
1156
1274
  }, []);
1157
1275
  const unregisterItem = useCallback((id) => {
1158
1276
  items.current = items.current.filter((i) => i.id !== id);
@@ -1161,18 +1279,19 @@ var Listbox = forwardRef(function Listbox2(props, ref) {
1161
1279
  (next) => {
1162
1280
  if (multiple) {
1163
1281
  const cur = Array.isArray(current) ? current : [];
1164
- const has = cur.includes(next);
1165
- setCurrent(has ? cur.filter((v) => v !== next) : [...cur, next]);
1282
+ const has = cur.some((v) => equals(v, next));
1283
+ const out = has ? cur.filter((v) => !equals(v, next)) : [...cur, next];
1284
+ setCurrent(out);
1166
1285
  } else {
1167
1286
  setCurrent(next);
1168
1287
  }
1169
1288
  },
1170
- [multiple, current, setCurrent]
1289
+ [multiple, current, setCurrent, equals]
1171
1290
  );
1172
1291
  useEffect(() => {
1173
1292
  if (activeId) return;
1174
1293
  const firstSelected = items.current.find(
1175
- (i) => !i.disabled && values.includes(i.value)
1294
+ (i) => !i.disabled && values.some((v) => equals(v, i.value))
1176
1295
  );
1177
1296
  const firstEnabled = items.current.find((i) => !i.disabled);
1178
1297
  setActiveId((firstSelected ?? firstEnabled)?.id ?? null);
@@ -1237,17 +1356,14 @@ var Listbox = forwardRef(function Listbox2(props, ref) {
1237
1356
  () => ({
1238
1357
  multiple,
1239
1358
  values,
1359
+ isEqual: equals,
1240
1360
  activeId,
1241
1361
  onItemSelect,
1242
- registerItem: (e) => {
1243
- const existing = items.current.find((i) => i.id === e.id);
1244
- if (existing) updateItem(e);
1245
- else registerItem(e);
1246
- },
1362
+ registerItem,
1247
1363
  unregisterItem,
1248
1364
  setActiveId
1249
1365
  }),
1250
- [multiple, values, activeId, onItemSelect, registerItem, unregisterItem, updateItem]
1366
+ [multiple, values, equals, activeId, onItemSelect, registerItem, unregisterItem]
1251
1367
  );
1252
1368
  return /* @__PURE__ */ jsx(ListboxContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
1253
1369
  "div",
@@ -1264,16 +1380,17 @@ var Listbox = forwardRef(function Listbox2(props, ref) {
1264
1380
  children
1265
1381
  }
1266
1382
  ) });
1267
- });
1383
+ }
1384
+ var ListboxForwardRef = forwardRef(ListboxImpl);
1268
1385
  var ListboxItem = forwardRef(function ListboxItem2({ value, disabled = false, className, children, onClick, onPointerEnter, ...rest }, forwardedRef) {
1269
1386
  const ctx = useListboxContext();
1270
1387
  const id = useId$1();
1271
1388
  const ref = useRef(null);
1272
1389
  useEffect(() => {
1273
- ctx.registerItem({ id, value, disabled, ref: ref.current });
1390
+ ctx.registerItem({ id, value, disabled });
1274
1391
  return () => ctx.unregisterItem(id);
1275
1392
  }, [ctx, id, value, disabled]);
1276
- const isSelected = ctx.values.includes(value);
1393
+ const isSelected = ctx.values.some((v) => ctx.isEqual(v, value));
1277
1394
  const isActive = ctx.activeId === id;
1278
1395
  const state = disabled ? "disabled" : isSelected ? "selected" : isActive ? "active" : "default";
1279
1396
  const setRefs = (node) => {
@@ -1324,6 +1441,7 @@ function ListboxSeparator(props) {
1324
1441
  function ListboxEmpty({ children, className, ...rest }) {
1325
1442
  return /* @__PURE__ */ jsx("div", { role: "presentation", className: cn(listboxEmptyVariants(), className), ...rest, children });
1326
1443
  }
1444
+ var Listbox = ListboxForwardRef;
1327
1445
  Listbox.Item = ListboxItem;
1328
1446
  Listbox.Group = ListboxGroup;
1329
1447
  Listbox.Separator = ListboxSeparator;
@@ -1348,18 +1466,23 @@ var selectTriggerVariants = tv({
1348
1466
  state: "default"
1349
1467
  }
1350
1468
  });
1469
+ var defaultEquals2 = (a, b) => Object.is(a, b);
1351
1470
  var SelectContext = createContext(null);
1352
1471
  function useSelectContext() {
1353
1472
  const ctx = useContext(SelectContext);
1354
1473
  if (!ctx) throw new Error("Select.* must be used inside <Select>");
1355
1474
  return ctx;
1356
1475
  }
1357
- function Select({
1476
+ function SelectImpl({
1358
1477
  value,
1359
1478
  defaultValue,
1360
1479
  onValueChange,
1480
+ isEqual,
1361
1481
  disabled = false,
1482
+ isLoading = false,
1483
+ clearable = false,
1362
1484
  name,
1485
+ serialize,
1363
1486
  invalid,
1364
1487
  defaultOpen = false,
1365
1488
  open: openProp,
@@ -1374,18 +1497,44 @@ function Select({
1374
1497
  });
1375
1498
  const [valueState, setValueState] = useControlled({
1376
1499
  controlled: value,
1377
- default: defaultValue ?? "",
1500
+ default: defaultValue ?? null,
1378
1501
  onChange: onValueChange
1379
1502
  });
1380
- const [labels, setLabels] = useState({});
1381
- const registerLabel = useCallback((v, label) => {
1382
- setLabels((prev) => prev[v] === label ? prev : { ...prev, [v]: label });
1503
+ const [items, setItems] = useState([]);
1504
+ const [query, setQuery] = useState("");
1505
+ const isEqualRef = useRef(isEqual);
1506
+ isEqualRef.current = isEqual;
1507
+ const serializeRef = useRef(serialize);
1508
+ serializeRef.current = serialize;
1509
+ const equals = useCallback((a, b) => {
1510
+ const fn = isEqualRef.current;
1511
+ return (fn ?? defaultEquals2)(a, b);
1383
1512
  }, []);
1384
- const unregisterLabel = useCallback((v) => {
1385
- setLabels((prev) => {
1386
- if (!(v in prev)) return prev;
1387
- const next = { ...prev };
1388
- delete next[v];
1513
+ const serializer = useCallback((v) => {
1514
+ const fn = serializeRef.current;
1515
+ return (fn ?? ((x) => String(x)))(v);
1516
+ }, []);
1517
+ const registerItem = useCallback((entry) => {
1518
+ setItems((prev) => {
1519
+ const idx = prev.findIndex((p) => Object.is(p.value, entry.value));
1520
+ if (idx >= 0) {
1521
+ const existing = prev[idx];
1522
+ if (existing && existing.label === entry.label && existing.text === entry.text) {
1523
+ return prev;
1524
+ }
1525
+ const next = prev.slice();
1526
+ next[idx] = entry;
1527
+ return next;
1528
+ }
1529
+ return [...prev, entry];
1530
+ });
1531
+ }, []);
1532
+ const unregisterItem = useCallback((v) => {
1533
+ setItems((prev) => {
1534
+ const idx = prev.findIndex((p) => Object.is(p.value, v));
1535
+ if (idx === -1) return prev;
1536
+ const next = prev.slice();
1537
+ next.splice(idx, 1);
1389
1538
  return next;
1390
1539
  });
1391
1540
  }, []);
@@ -1393,19 +1542,32 @@ function Select({
1393
1542
  (next) => {
1394
1543
  setValueState(next);
1395
1544
  setOpenState(false);
1545
+ setQuery("");
1396
1546
  },
1397
1547
  [setValueState, setOpenState]
1398
1548
  );
1549
+ const onClear = useCallback(() => {
1550
+ setValueState(null);
1551
+ }, [setValueState]);
1552
+ const hasValue = valueState !== null && valueState !== void 0;
1399
1553
  const ctx = useMemo(
1400
1554
  () => ({
1401
1555
  open: openState,
1402
1556
  setOpen: setOpenState,
1403
1557
  value: valueState,
1558
+ hasValue,
1404
1559
  onSelect,
1405
- labels,
1406
- registerLabel,
1407
- unregisterLabel,
1560
+ onClear,
1561
+ isEqual: equals,
1562
+ items,
1563
+ registerItem,
1564
+ unregisterItem,
1565
+ query,
1566
+ setQuery,
1408
1567
  disabled,
1568
+ isLoading,
1569
+ clearable,
1570
+ serialize: serializer,
1409
1571
  name,
1410
1572
  invalid
1411
1573
  }),
@@ -1413,11 +1575,18 @@ function Select({
1413
1575
  openState,
1414
1576
  setOpenState,
1415
1577
  valueState,
1578
+ hasValue,
1416
1579
  onSelect,
1417
- labels,
1418
- registerLabel,
1419
- unregisterLabel,
1580
+ onClear,
1581
+ equals,
1582
+ items,
1583
+ registerItem,
1584
+ unregisterItem,
1585
+ query,
1420
1586
  disabled,
1587
+ isLoading,
1588
+ clearable,
1589
+ serializer,
1421
1590
  name,
1422
1591
  invalid
1423
1592
  ]
@@ -1426,36 +1595,66 @@ function Select({
1426
1595
  Popover,
1427
1596
  {
1428
1597
  open: openState,
1429
- onOpenChange: setOpenState,
1598
+ onOpenChange: (o) => {
1599
+ setOpenState(o);
1600
+ if (!o) setQuery("");
1601
+ },
1430
1602
  placement,
1431
1603
  offset: 6,
1432
1604
  children
1433
1605
  }
1434
1606
  ) });
1435
1607
  }
1608
+ var Select = SelectImpl;
1436
1609
  var SelectTrigger = forwardRef(
1437
1610
  function SelectTrigger2({ size, state, className, children, ...rest }, ref) {
1438
1611
  const ctx = useSelectContext();
1439
1612
  const triggerState = state ?? (ctx.invalid ? "invalid" : "default");
1613
+ const showClear = ctx.clearable && ctx.hasValue && !ctx.isLoading && !ctx.disabled;
1440
1614
  return /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1441
1615
  "button",
1442
1616
  {
1443
1617
  ref,
1444
1618
  type: "button",
1445
- disabled: ctx.disabled,
1619
+ disabled: ctx.disabled || ctx.isLoading,
1620
+ "aria-busy": ctx.isLoading || void 0,
1446
1621
  className: cn(selectTriggerVariants({ size, state: triggerState }), className),
1447
1622
  ...rest,
1448
1623
  children: [
1449
1624
  children ?? /* @__PURE__ */ jsx(SelectValue, {}),
1450
- /* @__PURE__ */ jsx(
1451
- ChevronDown,
1452
- {
1453
- className: cn(
1454
- "h-4 w-4 text-muted-foreground transition-transform",
1455
- ctx.open && "rotate-180"
1456
- )
1457
- }
1458
- )
1625
+ /* @__PURE__ */ jsxs("span", { className: "ml-auto flex items-center gap-1", children: [
1626
+ showClear && /* @__PURE__ */ jsx(
1627
+ "span",
1628
+ {
1629
+ role: "button",
1630
+ tabIndex: 0,
1631
+ "aria-label": "Clear selection",
1632
+ onClick: (e) => {
1633
+ e.stopPropagation();
1634
+ ctx.onClear();
1635
+ },
1636
+ onPointerDown: (e) => e.stopPropagation(),
1637
+ onKeyDown: (e) => {
1638
+ if (e.key === "Enter" || e.key === " ") {
1639
+ e.preventDefault();
1640
+ e.stopPropagation();
1641
+ ctx.onClear();
1642
+ }
1643
+ },
1644
+ className: "grid h-4 w-4 place-items-center rounded-sm text-subtle-foreground hover:bg-muted hover:text-foreground",
1645
+ children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
1646
+ }
1647
+ ),
1648
+ ctx.isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-subtle-foreground" }) : /* @__PURE__ */ jsx(
1649
+ ChevronDown,
1650
+ {
1651
+ className: cn(
1652
+ "h-4 w-4 text-muted-foreground transition-transform",
1653
+ ctx.open && "rotate-180"
1654
+ )
1655
+ }
1656
+ )
1657
+ ] })
1459
1658
  ]
1460
1659
  }
1461
1660
  ) });
@@ -1464,31 +1663,82 @@ var SelectTrigger = forwardRef(
1464
1663
  function SelectValue({ placeholder, children }) {
1465
1664
  const ctx = useSelectContext();
1466
1665
  if (children) return /* @__PURE__ */ jsx("span", { className: "truncate", children });
1467
- const label = ctx.value ? ctx.labels[ctx.value] ?? ctx.value : null;
1468
- return /* @__PURE__ */ jsx("span", { className: cn("truncate", !label && "text-subtle-foreground"), children: label ?? placeholder });
1666
+ const match = ctx.hasValue ? ctx.items.find((i) => ctx.isEqual(i.value, ctx.value)) : void 0;
1667
+ const label = match?.label ?? (ctx.hasValue ? ctx.serialize(ctx.value) : null);
1668
+ return /* @__PURE__ */ jsx("span", { className: cn("truncate text-left", !label && "text-subtle-foreground"), children: label ?? placeholder });
1469
1669
  }
1470
- function SelectContent({ className, children }) {
1670
+ function SelectContent({
1671
+ className,
1672
+ searchable = false,
1673
+ searchPlaceholder = "Search\u2026",
1674
+ noResultsLabel = "No results",
1675
+ children
1676
+ }) {
1471
1677
  const ctx = useSelectContext();
1472
- return /* @__PURE__ */ jsxs(PopoverContent, { bare: true, children: [
1473
- /* @__PURE__ */ jsx(
1474
- Listbox,
1475
- {
1476
- value: ctx.value,
1477
- onValueChange: (v) => ctx.onSelect(v),
1478
- className: cn("min-w-[var(--anchor-width)]", className),
1479
- children
1480
- }
1481
- ),
1482
- ctx.name && /* @__PURE__ */ jsx("input", { type: "hidden", name: ctx.name, value: ctx.value })
1483
- ] });
1678
+ const hasItems = ctx.items.length > 0;
1679
+ const visibleCount = ctx.query ? ctx.items.filter((i) => i.text.toLowerCase().includes(ctx.query.toLowerCase())).length : ctx.items.length;
1680
+ const showEmpty = hasItems && visibleCount === 0;
1681
+ return /* @__PURE__ */ jsx(PopoverContent, { bare: true, children: /* @__PURE__ */ jsxs(
1682
+ "div",
1683
+ {
1684
+ className: cn("min-w-[var(--anchor-width)] overflow-hidden rounded-md", className),
1685
+ children: [
1686
+ searchable && /* @__PURE__ */ jsx("div", { className: "border-b border-border bg-popover p-1", children: /* @__PURE__ */ jsx(
1687
+ SearchInput,
1688
+ {
1689
+ size: "sm",
1690
+ autoFocus: true,
1691
+ value: ctx.query,
1692
+ onChange: (e) => ctx.setQuery(e.target.value),
1693
+ placeholder: searchPlaceholder,
1694
+ clearable: true,
1695
+ onClear: () => ctx.setQuery(""),
1696
+ className: "rounded-sm"
1697
+ }
1698
+ ) }),
1699
+ /* @__PURE__ */ jsxs(
1700
+ Listbox,
1701
+ {
1702
+ value: ctx.value ?? void 0,
1703
+ onValueChange: (v) => {
1704
+ if (v !== null && v !== void 0) ctx.onSelect(v);
1705
+ },
1706
+ isEqual: ctx.isEqual,
1707
+ className: "border-0 shadow-none rounded-none",
1708
+ children: [
1709
+ children,
1710
+ showEmpty && /* @__PURE__ */ jsx(ListboxEmpty, { children: noResultsLabel })
1711
+ ]
1712
+ }
1713
+ ),
1714
+ ctx.name && ctx.hasValue && /* @__PURE__ */ jsx("input", { type: "hidden", name: ctx.name, value: ctx.serialize(ctx.value) })
1715
+ ]
1716
+ }
1717
+ ) });
1484
1718
  }
1485
- var SelectItem = forwardRef(function SelectItem2(props, ref) {
1719
+ function extractText(node) {
1720
+ if (node == null || typeof node === "boolean") return "";
1721
+ if (typeof node === "string" || typeof node === "number") return String(node);
1722
+ if (Array.isArray(node)) return node.map(extractText).join(" ");
1723
+ if (isValidElement(node)) {
1724
+ const props = node.props;
1725
+ return extractText(props.children);
1726
+ }
1727
+ return "";
1728
+ }
1729
+ var SelectItem = forwardRef(function SelectItem2({ value, disabled, text, className, children }, ref) {
1486
1730
  const ctx = useSelectContext();
1731
+ const itemText = useMemo(
1732
+ () => text ?? extractText(children),
1733
+ [text, children]
1734
+ );
1487
1735
  useEffect(() => {
1488
- ctx.registerLabel(props.value, props.children);
1489
- return () => ctx.unregisterLabel(props.value);
1490
- }, [ctx, props.value, props.children]);
1491
- return /* @__PURE__ */ jsx(ListboxItem, { ref, ...props });
1736
+ ctx.registerItem({ value, label: children, text: itemText });
1737
+ return () => ctx.unregisterItem(value);
1738
+ }, [ctx, value, children, itemText]);
1739
+ const matchesQuery = !ctx.query || itemText.toLowerCase().includes(ctx.query.toLowerCase());
1740
+ if (!matchesQuery) return null;
1741
+ return /* @__PURE__ */ jsx(ListboxItem, { ref, value, disabled, className, children });
1492
1742
  });
1493
1743
  Select.Trigger = SelectTrigger;
1494
1744
  Select.Value = SelectValue;
@@ -6983,5 +7233,5 @@ var ChatComposer = forwardRef(
6983
7233
  ChatComposer.displayName = "ChatComposer";
6984
7234
 
6985
7235
  export { ADDRESS_COUNTRIES, AddressForm, BUILT_IN_EMOJI, BUILT_IN_FONTS, Calendar, CharacterCount, ChatComposer, Checkbox, CheckboxField, CheckboxGroup, ChoiceCard, CodeEditor, ColorArea, ColorField, ColorPicker, ColorSlider, ColorSwatch, ColorSwatchPicker, ColorWheel, Combobox, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxSeparator, CronInput, CurrencyInput, DateField, DatePicker, DateRangePicker, Editable, EditableCancel, EditableInput, EditablePreview, EditableSubmit, EmailInput, EmojiPicker, Fieldset, FilePicker, FileUpload, FontPicker, FormErrorMessage, FormField, FormHelperText, GradientPicker, IconPicker, InputAddon, InputGroup, JSONEditor, KeyboardShortcutPicker, Knob, Label, LabeledInput, Legend, Listbox, ListboxEmpty, ListboxGroup, ListboxItem, ListboxSeparator, MarkdownEditor, MaskedInput, MultiSelect, MultiSelectContent, MultiSelectItem, MultiSelectTags, MultiSelectTrigger, NumberInput, PHONE_COUNTRIES, PasswordInput, PasswordStrength, PercentInput, PhoneInput, PinInput, Radio, RadioField, RadioGroup, RangeCalendar, ReactionPicker, RecurrenceEditor, SearchInput, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Slider, Stepper, StepperList, StepperPanel, StepperStep, Switch, SwitchField, TagsInput, TelInput, TextInput, Textarea, TimeField, TimePicker, UrlInput, Wizard, WizardFooter, WizardStep, WizardSteps, colorSwatchVariants, gradientToCss, useWizard };
6986
- //# sourceMappingURL=chunk-7GDZNTC6.js.map
6987
- //# sourceMappingURL=chunk-7GDZNTC6.js.map
7236
+ //# sourceMappingURL=chunk-I7UOT7TA.js.map
7237
+ //# sourceMappingURL=chunk-I7UOT7TA.js.map