@campminder/ds 0.1.0 → 0.3.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 CHANGED
@@ -18,6 +18,7 @@ var zod = require('zod');
18
18
  var input = require('@base-ui/react/input');
19
19
  var select = require('@base-ui/react/select');
20
20
  var checkbox = require('@base-ui/react/checkbox');
21
+ var popover = require('@base-ui/react/popover');
21
22
  var cmdk = require('cmdk');
22
23
  var dialog = require('@base-ui/react/dialog');
23
24
  var menu = require('@base-ui/react/menu');
@@ -25,9 +26,10 @@ var separator = require('@base-ui/react/separator');
25
26
  var RPNInput = require('react-phone-number-input');
26
27
  var flags = require('react-phone-number-input/flags');
27
28
  var en = require('react-phone-number-input/locale/en.json');
28
- var popover = require('@base-ui/react/popover');
29
29
  var scrollArea = require('@base-ui/react/scroll-area');
30
30
  var progress = require('@base-ui/react/progress');
31
+ var radioGroup = require('@base-ui/react/radio-group');
32
+ var radio = require('@base-ui/react/radio');
31
33
  var tooltip = require('@base-ui/react/tooltip');
32
34
  var sonner = require('sonner');
33
35
  var _switch = require('@base-ui/react/switch');
@@ -1200,6 +1202,397 @@ function Checkbox({ className, ...props }) {
1200
1202
  }
1201
1203
  );
1202
1204
  }
1205
+ function Popover({ ...props }) {
1206
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Root, { "data-slot": "popover", ...props });
1207
+ }
1208
+ function PopoverTrigger({ ...props }) {
1209
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { "data-slot": "popover-trigger", ...props });
1210
+ }
1211
+ function PopoverContent({
1212
+ className,
1213
+ align = "center",
1214
+ alignOffset = 0,
1215
+ side = "bottom",
1216
+ sideOffset = 4,
1217
+ ...props
1218
+ }) {
1219
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1220
+ popover.Popover.Positioner,
1221
+ {
1222
+ align,
1223
+ alignOffset,
1224
+ side,
1225
+ sideOffset,
1226
+ className: "isolate z-50",
1227
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1228
+ popover.Popover.Popup,
1229
+ {
1230
+ "data-slot": "popover-content",
1231
+ className: cn(
1232
+ "z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
1233
+ className
1234
+ ),
1235
+ ...props
1236
+ }
1237
+ )
1238
+ }
1239
+ ) });
1240
+ }
1241
+ function PopoverHeader({ className, ...props }) {
1242
+ return /* @__PURE__ */ jsxRuntime.jsx(
1243
+ "div",
1244
+ {
1245
+ "data-slot": "popover-header",
1246
+ className: cn("flex flex-col gap-0.5 text-sm", className),
1247
+ ...props
1248
+ }
1249
+ );
1250
+ }
1251
+ function PopoverTitle({ className, ...props }) {
1252
+ return /* @__PURE__ */ jsxRuntime.jsx(
1253
+ popover.Popover.Title,
1254
+ {
1255
+ "data-slot": "popover-title",
1256
+ className: cn("font-medium", className),
1257
+ ...props
1258
+ }
1259
+ );
1260
+ }
1261
+ function PopoverDescription({
1262
+ className,
1263
+ ...props
1264
+ }) {
1265
+ return /* @__PURE__ */ jsxRuntime.jsx(
1266
+ popover.Popover.Description,
1267
+ {
1268
+ "data-slot": "popover-description",
1269
+ className: cn("text-muted-foreground", className),
1270
+ ...props
1271
+ }
1272
+ );
1273
+ }
1274
+ var ALL_GROUPS = "__all__";
1275
+ function ColumnCustomizer({
1276
+ columns,
1277
+ value,
1278
+ onApply,
1279
+ groupOrder,
1280
+ title = "Customize columns",
1281
+ searchPlaceholder = "Search for a column",
1282
+ allGroupsLabel = "All columns",
1283
+ align = "end",
1284
+ trigger
1285
+ }) {
1286
+ const [open, setOpen] = React3.useState(false);
1287
+ const [draft, setDraft] = React3.useState(value);
1288
+ const [query, setQuery] = React3.useState("");
1289
+ const [group, setGroup] = React3.useState(ALL_GROUPS);
1290
+ const [dragIndex, setDragIndex] = React3.useState(null);
1291
+ const q = query.trim().toLowerCase();
1292
+ const searching = q !== "";
1293
+ const labelFor = React3.useMemo(() => {
1294
+ const m = /* @__PURE__ */ new Map();
1295
+ for (const c of columns) m.set(c.key, c.label);
1296
+ return m;
1297
+ }, [columns]);
1298
+ const groupKeys = React3.useMemo(() => {
1299
+ if (groupOrder?.length) return groupOrder;
1300
+ const seen = [];
1301
+ for (const c of columns) if (!seen.includes(c.group)) seen.push(c.group);
1302
+ return seen;
1303
+ }, [columns, groupOrder]);
1304
+ const groups = React3.useMemo(
1305
+ () => [
1306
+ { key: ALL_GROUPS, label: allGroupsLabel, count: columns.length },
1307
+ ...groupKeys.map((g) => ({
1308
+ key: g,
1309
+ label: g,
1310
+ count: columns.filter((c) => c.group === g).length
1311
+ }))
1312
+ ],
1313
+ [columns, groupKeys, allGroupsLabel]
1314
+ );
1315
+ const handleOpenChange = (next) => {
1316
+ if (next) {
1317
+ setDraft(value);
1318
+ setQuery("");
1319
+ setGroup(ALL_GROUPS);
1320
+ }
1321
+ setOpen(next);
1322
+ };
1323
+ const toggle = (k) => setDraft(
1324
+ (cur) => cur.includes(k) ? cur.filter((c) => c !== k) : [...cur, k]
1325
+ );
1326
+ const remove = (k) => setDraft((cur) => cur.filter((c) => c !== k));
1327
+ const reorder = (from, to) => setDraft((cur) => {
1328
+ const next = [...cur];
1329
+ const [moved] = next.splice(from, 1);
1330
+ next.splice(to, 0, moved);
1331
+ return next;
1332
+ });
1333
+ const visibleCols = React3.useMemo(() => {
1334
+ const base = searching || group === ALL_GROUPS ? columns : columns.filter((c) => c.group === group);
1335
+ return searching ? base.filter((c) => c.label.toLowerCase().includes(q)) : base;
1336
+ }, [columns, q, group, searching]);
1337
+ const showSource = searching || group === ALL_GROUPS;
1338
+ const allChecked = visibleCols.length > 0 && visibleCols.every((c) => draft.includes(c.key));
1339
+ const toggleAll = () => setDraft(
1340
+ (cur) => allChecked ? cur.filter((k) => !visibleCols.some((c) => c.key === k)) : [
1341
+ ...cur,
1342
+ ...visibleCols.map((c) => c.key).filter((k) => !cur.includes(k))
1343
+ ]
1344
+ );
1345
+ const activeGroupLabel = groups.find((g) => g.key === group)?.label;
1346
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
1347
+ trigger ? /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { render: trigger }) : /* @__PURE__ */ jsxRuntime.jsxs(
1348
+ PopoverTrigger,
1349
+ {
1350
+ type: "button",
1351
+ className: cn(
1352
+ buttonVariants({ variant: "outline" }),
1353
+ "h-9 gap-1.5 text-muted-foreground"
1354
+ ),
1355
+ children: [
1356
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Columns3, { className: "size-4" }),
1357
+ "Columns"
1358
+ ]
1359
+ }
1360
+ ),
1361
+ /* @__PURE__ */ jsxRuntime.jsxs(
1362
+ PopoverContent,
1363
+ {
1364
+ align,
1365
+ className: "w-[720px] max-w-[calc(100vw-2rem)] gap-0 p-0",
1366
+ children: [
1367
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTitle, { className: "px-4 pt-4 pb-3 text-sm font-semibold", children: title }),
1368
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1369
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" }),
1370
+ /* @__PURE__ */ jsxRuntime.jsx(
1371
+ Input,
1372
+ {
1373
+ value: query,
1374
+ onChange: (e) => setQuery(e.target.value),
1375
+ placeholder: searchPlaceholder,
1376
+ "aria-label": searchPlaceholder,
1377
+ className: "h-10 pl-9"
1378
+ }
1379
+ )
1380
+ ] }) }),
1381
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid h-[380px] grid-cols-[12rem_1fr_16rem] border-y", children: [
1382
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto border-r p-2", children: groups.map((gr) => /* @__PURE__ */ jsxRuntime.jsxs(
1383
+ "button",
1384
+ {
1385
+ type: "button",
1386
+ disabled: searching,
1387
+ onClick: () => setGroup(gr.key),
1388
+ className: cn(
1389
+ "flex w-full items-center justify-between gap-2 rounded-md px-3 py-2 text-left text-sm hover:bg-muted/60",
1390
+ !searching && group === gr.key && "bg-muted font-medium",
1391
+ searching && "opacity-40"
1392
+ ),
1393
+ children: [
1394
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: gr.label }),
1395
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded-md bg-muted px-1.5 text-xs tabular-nums text-muted-foreground", children: gr.count })
1396
+ ]
1397
+ },
1398
+ gr.key
1399
+ )) }),
1400
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 overflow-y-auto p-3", children: [
1401
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 pb-1 text-sm font-semibold", children: searching ? "Search results" : activeGroupLabel }),
1402
+ !searching && visibleCols.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex cursor-pointer items-center gap-2.5 border-b px-1 py-2 text-sm", children: [
1403
+ /* @__PURE__ */ jsxRuntime.jsx(
1404
+ Checkbox,
1405
+ {
1406
+ checked: allChecked,
1407
+ onCheckedChange: () => toggleAll()
1408
+ }
1409
+ ),
1410
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Select all" })
1411
+ ] }),
1412
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-1", children: visibleCols.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-1 py-6 text-center text-sm text-muted-foreground", children: [
1413
+ "No columns match \u201C",
1414
+ query,
1415
+ "\u201D."
1416
+ ] }) : visibleCols.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
1417
+ "label",
1418
+ {
1419
+ className: "flex cursor-pointer items-center gap-2.5 rounded-md px-1 py-2 text-sm hover:bg-muted/60",
1420
+ children: [
1421
+ /* @__PURE__ */ jsxRuntime.jsx(
1422
+ Checkbox,
1423
+ {
1424
+ checked: draft.includes(c.key),
1425
+ onCheckedChange: () => toggle(c.key)
1426
+ }
1427
+ ),
1428
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: c.label }),
1429
+ showSource && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: c.group })
1430
+ ]
1431
+ },
1432
+ c.key
1433
+ )) })
1434
+ ] }),
1435
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col border-l", children: [
1436
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 py-2.5", children: [
1437
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold", children: [
1438
+ draft.length,
1439
+ " selected"
1440
+ ] }),
1441
+ draft.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1442
+ "button",
1443
+ {
1444
+ type: "button",
1445
+ onClick: () => setDraft([]),
1446
+ className: "text-xs font-medium text-primary hover:underline",
1447
+ children: "Clear all"
1448
+ }
1449
+ )
1450
+ ] }),
1451
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 space-y-1.5 overflow-y-auto px-3 pb-3", children: draft.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 py-6 text-center text-sm text-muted-foreground", children: "No columns selected." }) : draft.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(
1452
+ "div",
1453
+ {
1454
+ draggable: true,
1455
+ onDragStart: () => setDragIndex(i),
1456
+ onDragOver: (e) => e.preventDefault(),
1457
+ onDrop: () => {
1458
+ if (dragIndex !== null && dragIndex !== i)
1459
+ reorder(dragIndex, i);
1460
+ setDragIndex(null);
1461
+ },
1462
+ onDragEnd: () => setDragIndex(null),
1463
+ className: cn(
1464
+ "flex items-center gap-2 rounded-md border bg-background px-2.5 py-2 text-sm",
1465
+ dragIndex === i && "opacity-50"
1466
+ ),
1467
+ children: [
1468
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { className: "size-3.5 shrink-0 cursor-grab text-muted-foreground" }),
1469
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: labelFor.get(k) ?? k }),
1470
+ /* @__PURE__ */ jsxRuntime.jsx(
1471
+ "button",
1472
+ {
1473
+ type: "button",
1474
+ onClick: () => remove(k),
1475
+ "aria-label": `Remove ${labelFor.get(k) ?? k}`,
1476
+ className: "shrink-0 rounded-sm p-0.5 text-muted-foreground hover:text-foreground",
1477
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" })
1478
+ }
1479
+ )
1480
+ ]
1481
+ },
1482
+ k
1483
+ )) })
1484
+ ] })
1485
+ ] }),
1486
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2 px-4 py-3", children: [
1487
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: () => setOpen(false), children: "Cancel" }),
1488
+ /* @__PURE__ */ jsxRuntime.jsx(
1489
+ Button,
1490
+ {
1491
+ onClick: () => {
1492
+ onApply(draft);
1493
+ setOpen(false);
1494
+ },
1495
+ children: "Apply"
1496
+ }
1497
+ )
1498
+ ] })
1499
+ ]
1500
+ }
1501
+ )
1502
+ ] });
1503
+ }
1504
+ function ColumnPicker({
1505
+ columns,
1506
+ value,
1507
+ onChange,
1508
+ title = "Columns",
1509
+ searchPlaceholder = "Search columns",
1510
+ align = "end",
1511
+ trigger
1512
+ }) {
1513
+ const [query, setQuery] = React3.useState("");
1514
+ const q = query.trim().toLowerCase();
1515
+ const visible = React3.useMemo(() => new Set(value), [value]);
1516
+ const filtered = React3.useMemo(
1517
+ () => q ? columns.filter((c) => c.label.toLowerCase().includes(q)) : columns,
1518
+ [columns, q]
1519
+ );
1520
+ const emit = (next) => onChange(columns.filter((c) => next.has(c.key)).map((c) => c.key));
1521
+ const toggle = (key) => {
1522
+ const next = new Set(visible);
1523
+ if (next.has(key)) next.delete(key);
1524
+ else next.add(key);
1525
+ emit(next);
1526
+ };
1527
+ const allChecked = filtered.length > 0 && filtered.every((c) => visible.has(c.key));
1528
+ const toggleAll = () => {
1529
+ const next = new Set(visible);
1530
+ for (const c of filtered) {
1531
+ if (allChecked) next.delete(c.key);
1532
+ else next.add(c.key);
1533
+ }
1534
+ emit(next);
1535
+ };
1536
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
1537
+ trigger ? /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { render: trigger }) : /* @__PURE__ */ jsxRuntime.jsxs(
1538
+ PopoverTrigger,
1539
+ {
1540
+ type: "button",
1541
+ className: cn(
1542
+ buttonVariants({ variant: "outline" }),
1543
+ "h-9 gap-1.5 text-muted-foreground"
1544
+ ),
1545
+ children: [
1546
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Columns3, { className: "size-4" }),
1547
+ "Columns"
1548
+ ]
1549
+ }
1550
+ ),
1551
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align, className: "w-72 gap-0 p-0", children: [
1552
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTitle, { className: "px-3 pt-3 pb-2 text-sm font-semibold", children: title }),
1553
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1554
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" }),
1555
+ /* @__PURE__ */ jsxRuntime.jsx(
1556
+ Input,
1557
+ {
1558
+ value: query,
1559
+ onChange: (e) => setQuery(e.target.value),
1560
+ placeholder: searchPlaceholder,
1561
+ "aria-label": searchPlaceholder,
1562
+ className: "h-9 pl-9"
1563
+ }
1564
+ )
1565
+ ] }) }),
1566
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[320px] overflow-y-auto border-t px-1.5 py-1.5", children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-2 py-6 text-center text-sm text-muted-foreground", children: [
1567
+ "No columns match \u201C",
1568
+ query,
1569
+ "\u201D."
1570
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1571
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-sm hover:bg-muted/60", children: [
1572
+ /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { checked: allChecked, onCheckedChange: () => toggleAll() }),
1573
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Select all" })
1574
+ ] }),
1575
+ filtered.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
1576
+ "label",
1577
+ {
1578
+ className: "flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-sm hover:bg-muted/60",
1579
+ children: [
1580
+ /* @__PURE__ */ jsxRuntime.jsx(
1581
+ Checkbox,
1582
+ {
1583
+ checked: visible.has(c.key),
1584
+ onCheckedChange: () => toggle(c.key)
1585
+ }
1586
+ ),
1587
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: c.label })
1588
+ ]
1589
+ },
1590
+ c.key
1591
+ ))
1592
+ ] }) })
1593
+ ] })
1594
+ ] });
1595
+ }
1203
1596
  function Dialog({ ...props }) {
1204
1597
  return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog.Root, { "data-slot": "dialog", ...props });
1205
1598
  }
@@ -1294,7 +1687,7 @@ function DialogFooter({
1294
1687
  {
1295
1688
  "data-slot": "dialog-footer",
1296
1689
  className: cn(
1297
- "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
1690
+ "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t border-border bg-muted/50 p-4 sm:flex-row sm:justify-end",
1298
1691
  className
1299
1692
  ),
1300
1693
  ...props,
@@ -1633,85 +2026,528 @@ function CommandShortcut({
1633
2026
  }
1634
2027
  );
1635
2028
  }
1636
- function DropdownMenu(props) {
1637
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
1638
- }
1639
- function DropdownMenuTrigger({ ...props }) {
1640
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1641
- }
1642
- function DropdownMenuGroup(props) {
1643
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Group, { "data-slot": "dropdown-menu-group", ...props });
1644
- }
1645
- function DropdownMenuContent({
1646
- className,
1647
- sideOffset = 4,
1648
- align = "start",
1649
- ...props
1650
- }) {
1651
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1652
- menu.Menu.Positioner,
2029
+ function Table({ className, ...props }) {
2030
+ return /* @__PURE__ */ jsxRuntime.jsx(
2031
+ "div",
1653
2032
  {
1654
- sideOffset,
1655
- align,
1656
- className: "z-50",
2033
+ "data-slot": "table-container",
2034
+ className: "relative w-full overflow-x-auto",
1657
2035
  children: /* @__PURE__ */ jsxRuntime.jsx(
1658
- menu.Menu.Popup,
2036
+ "table",
1659
2037
  {
1660
- "data-slot": "dropdown-menu-content",
1661
- className: cn(
1662
- "bg-popover text-popover-foreground border-border z-50 min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md outline-none",
1663
- className
1664
- ),
2038
+ "data-slot": "table",
2039
+ className: cn("w-full caption-bottom text-sm", className),
1665
2040
  ...props
1666
2041
  }
1667
2042
  )
1668
2043
  }
1669
- ) });
2044
+ );
1670
2045
  }
1671
- var itemClasses = "relative flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none select-none transition-colors data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground";
1672
- function DropdownMenuItem({ className, ...props }) {
2046
+ function TableHeader({ className, ...props }) {
1673
2047
  return /* @__PURE__ */ jsxRuntime.jsx(
1674
- menu.Menu.Item,
2048
+ "thead",
1675
2049
  {
1676
- "data-slot": "dropdown-menu-item",
1677
- className: cn(itemClasses, className),
2050
+ "data-slot": "table-header",
2051
+ className: cn("[&_tr]:border-b", className),
1678
2052
  ...props
1679
2053
  }
1680
2054
  );
1681
2055
  }
1682
- function DropdownMenuCheckboxItem({
1683
- className,
1684
- children,
1685
- ...props
1686
- }) {
1687
- return /* @__PURE__ */ jsxRuntime.jsxs(
1688
- menu.Menu.CheckboxItem,
2056
+ function TableBody({ className, ...props }) {
2057
+ return /* @__PURE__ */ jsxRuntime.jsx(
2058
+ "tbody",
1689
2059
  {
1690
- "data-slot": "dropdown-menu-checkbox-item",
1691
- className: cn(itemClasses, "pl-8", className),
1692
- ...props,
1693
- children: [
1694
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4" }) }) }),
1695
- children
1696
- ]
2060
+ "data-slot": "table-body",
2061
+ className: cn("[&_tr:last-child]:border-0", className),
2062
+ ...props
1697
2063
  }
1698
2064
  );
1699
2065
  }
1700
- function DropdownMenuRadioGroup(props) {
1701
- return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.RadioGroup, { "data-slot": "dropdown-menu-radio-group", ...props });
1702
- }
1703
- function DropdownMenuRadioItem({
1704
- className,
1705
- children,
1706
- ...props
1707
- }) {
1708
- return /* @__PURE__ */ jsxRuntime.jsxs(
1709
- menu.Menu.RadioItem,
2066
+ function TableFooter({ className, ...props }) {
2067
+ return /* @__PURE__ */ jsxRuntime.jsx(
2068
+ "tfoot",
1710
2069
  {
1711
- "data-slot": "dropdown-menu-radio-item",
1712
- className: cn(itemClasses, "pl-8", className),
1713
- ...props,
1714
- children: [
2070
+ "data-slot": "table-footer",
2071
+ className: cn(
2072
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
2073
+ className
2074
+ ),
2075
+ ...props
2076
+ }
2077
+ );
2078
+ }
2079
+ function TableRow({ className, ...props }) {
2080
+ return /* @__PURE__ */ jsxRuntime.jsx(
2081
+ "tr",
2082
+ {
2083
+ "data-slot": "table-row",
2084
+ className: cn(
2085
+ "border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
2086
+ className
2087
+ ),
2088
+ ...props
2089
+ }
2090
+ );
2091
+ }
2092
+ function TableHead({ className, ...props }) {
2093
+ return /* @__PURE__ */ jsxRuntime.jsx(
2094
+ "th",
2095
+ {
2096
+ "data-slot": "table-head",
2097
+ className: cn(
2098
+ "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
2099
+ className
2100
+ ),
2101
+ ...props
2102
+ }
2103
+ );
2104
+ }
2105
+ function TableCell({ className, ...props }) {
2106
+ return /* @__PURE__ */ jsxRuntime.jsx(
2107
+ "td",
2108
+ {
2109
+ "data-slot": "table-cell",
2110
+ className: cn(
2111
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
2112
+ className
2113
+ ),
2114
+ ...props
2115
+ }
2116
+ );
2117
+ }
2118
+ function TableCaption({
2119
+ className,
2120
+ ...props
2121
+ }) {
2122
+ return /* @__PURE__ */ jsxRuntime.jsx(
2123
+ "caption",
2124
+ {
2125
+ "data-slot": "table-caption",
2126
+ className: cn("mt-4 text-sm text-muted-foreground", className),
2127
+ ...props
2128
+ }
2129
+ );
2130
+ }
2131
+ var SELECT_COL_PX = 48;
2132
+ var STICKY_UNDERLAP_PX = 8;
2133
+ var selectColStyle = {
2134
+ width: SELECT_COL_PX,
2135
+ minWidth: SELECT_COL_PX,
2136
+ maxWidth: SELECT_COL_PX
2137
+ };
2138
+ var DEFAULT_STICKY_PX = 180;
2139
+ var HEADER_CELL_BG = "bg-[color-mix(in_oklab,var(--color-muted)_40%,var(--color-background))]";
2140
+ function alignClass(align) {
2141
+ return align === "right" ? "text-right" : align === "center" ? "text-center" : "text-left";
2142
+ }
2143
+ function DataTable({
2144
+ data,
2145
+ columns,
2146
+ rowKey,
2147
+ selectable = false,
2148
+ selected: selectedProp,
2149
+ onSelectedChange,
2150
+ bulkActions,
2151
+ sort: sortProp,
2152
+ defaultSort = null,
2153
+ onSortChange,
2154
+ paginated = false,
2155
+ pageSize: pageSizeProp,
2156
+ pageSizeOptions = [25, 50, 100],
2157
+ page: pageProp,
2158
+ onPageChange,
2159
+ toolbar,
2160
+ onRowClick,
2161
+ emptyMessage = "No rows to show.",
2162
+ rowClassName,
2163
+ className
2164
+ }) {
2165
+ const [selInner, setSelInner] = React3.useState(/* @__PURE__ */ new Set());
2166
+ const selected = selectedProp ?? selInner;
2167
+ const setSelected = (next) => {
2168
+ onSelectedChange?.(next);
2169
+ if (selectedProp === void 0) setSelInner(next);
2170
+ };
2171
+ const toggleRow = (id) => {
2172
+ const next = new Set(selected);
2173
+ if (next.has(id)) next.delete(id);
2174
+ else next.add(id);
2175
+ setSelected(next);
2176
+ };
2177
+ const clearSelection = () => setSelected(/* @__PURE__ */ new Set());
2178
+ const [sortInner, setSortInner] = React3.useState(defaultSort);
2179
+ const sort = sortProp !== void 0 ? sortProp : sortInner;
2180
+ const colByKey = React3.useMemo(() => {
2181
+ const m = /* @__PURE__ */ new Map();
2182
+ for (const c of columns) m.set(c.key, c);
2183
+ return m;
2184
+ }, [columns]);
2185
+ const toggleSort = (key) => {
2186
+ const next = sort?.key !== key ? { key, dir: "asc" } : sort.dir === "asc" ? { key, dir: "desc" } : null;
2187
+ onSortChange?.(next);
2188
+ if (sortProp === void 0) setSortInner(next);
2189
+ };
2190
+ const sorted = React3.useMemo(() => {
2191
+ if (!sort) return data;
2192
+ const col = colByKey.get(sort.key);
2193
+ if (!col?.sortValue) return data;
2194
+ const { sortValue } = col;
2195
+ const arr = [...data];
2196
+ arr.sort((a, b) => {
2197
+ const av = sortValue(a);
2198
+ const bv = sortValue(b);
2199
+ const cmp = typeof av === "number" && typeof bv === "number" ? av - bv : String(av).localeCompare(String(bv));
2200
+ return sort.dir === "asc" ? cmp : -cmp;
2201
+ });
2202
+ return arr;
2203
+ }, [data, sort, colByKey]);
2204
+ const [pageSizeInner, setPageSizeInner] = React3.useState(pageSizeProp ?? 25);
2205
+ const pageSize = paginated ? pageSizeInner : sorted.length || 1;
2206
+ const [pageInner, setPageInner] = React3.useState(0);
2207
+ const page = pageProp !== void 0 ? pageProp : pageInner;
2208
+ const setPage = (p) => {
2209
+ onPageChange?.(p);
2210
+ if (pageProp === void 0) setPageInner(p);
2211
+ };
2212
+ const total = sorted.length;
2213
+ const pageCount = Math.max(1, Math.ceil(total / pageSize));
2214
+ const safePage = Math.min(page, pageCount - 1);
2215
+ const pageStart = paginated ? safePage * pageSize : 0;
2216
+ const rows = paginated ? sorted.slice(pageStart, pageStart + pageSize) : sorted;
2217
+ const pageIds = rows.map(rowKey);
2218
+ const allChecked = pageIds.length > 0 && pageIds.every((id) => selected.has(id));
2219
+ const toggleAll = () => {
2220
+ const next = new Set(selected);
2221
+ for (const id of pageIds) {
2222
+ if (allChecked) next.delete(id);
2223
+ else next.add(id);
2224
+ }
2225
+ setSelected(next);
2226
+ };
2227
+ const selectedCount = selected.size;
2228
+ const stickyLeft = React3.useMemo(() => {
2229
+ const offsets = /* @__PURE__ */ new Map();
2230
+ let left = selectable ? SELECT_COL_PX - STICKY_UNDERLAP_PX : 0;
2231
+ for (const col of columns) {
2232
+ if (!col.sticky) continue;
2233
+ offsets.set(col.key, left);
2234
+ left += typeof col.width === "number" ? col.width : DEFAULT_STICKY_PX;
2235
+ }
2236
+ return offsets;
2237
+ }, [columns, selectable]);
2238
+ const colCount = (selectable ? 1 : 0) + columns.length + 1;
2239
+ const sortIcon = (key) => {
2240
+ if (sort?.key !== key)
2241
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { className: "size-3.5 text-muted-foreground/50 opacity-0 transition-opacity group-hover/sort:opacity-100" });
2242
+ return sort.dir === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-3.5" });
2243
+ };
2244
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2", className), children: [
2245
+ toolbar,
2246
+ bulkActions?.length && selectedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-fit flex-wrap items-center gap-2 rounded-lg border border-primary/40 bg-primary/5 px-3 py-1.5", children: [
2247
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium", children: [
2248
+ selectedCount,
2249
+ " selected"
2250
+ ] }),
2251
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "\xB7" }),
2252
+ bulkActions.map(
2253
+ (action, i) => action.options ? /* @__PURE__ */ jsxRuntime.jsxs(
2254
+ Select,
2255
+ {
2256
+ value: "",
2257
+ onValueChange: (v) => v && action.onPick?.(v),
2258
+ children: [
2259
+ /* @__PURE__ */ jsxRuntime.jsx(
2260
+ SelectTrigger,
2261
+ {
2262
+ "aria-label": action.label,
2263
+ className: "h-8 min-w-[130px] bg-background text-sm",
2264
+ children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: action.label })
2265
+ }
2266
+ ),
2267
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "w-auto min-w-(--anchor-width) max-w-[20rem]", children: action.options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
2268
+ ]
2269
+ },
2270
+ i
2271
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2272
+ "button",
2273
+ {
2274
+ type: "button",
2275
+ onClick: action.onClick,
2276
+ className: "inline-flex h-8 items-center rounded-md border bg-background px-2.5 text-sm hover:bg-muted",
2277
+ children: action.label
2278
+ },
2279
+ i
2280
+ )
2281
+ ),
2282
+ /* @__PURE__ */ jsxRuntime.jsxs(
2283
+ "button",
2284
+ {
2285
+ type: "button",
2286
+ onClick: clearSelection,
2287
+ className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground",
2288
+ children: [
2289
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" }),
2290
+ "Clear"
2291
+ ]
2292
+ }
2293
+ )
2294
+ ] }) : null,
2295
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border bg-background overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { className: "border-separate border-spacing-0", children: [
2296
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "text-xs uppercase tracking-wide text-muted-foreground", children: [
2297
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(
2298
+ TableHead,
2299
+ {
2300
+ style: selectColStyle,
2301
+ className: cn(
2302
+ "sticky left-0 z-30 px-0 py-2.5 border-b rounded-tl-xl",
2303
+ HEADER_CELL_BG
2304
+ ),
2305
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
2306
+ Checkbox,
2307
+ {
2308
+ checked: allChecked,
2309
+ onCheckedChange: toggleAll,
2310
+ "aria-label": "Select all"
2311
+ }
2312
+ ) })
2313
+ }
2314
+ ),
2315
+ columns.map((col, colIndex) => {
2316
+ const sortable = col.sortable && col.sortValue;
2317
+ const left = stickyLeft.get(col.key);
2318
+ const isFirstCol = !selectable && colIndex === 0;
2319
+ return /* @__PURE__ */ jsxRuntime.jsx(
2320
+ TableHead,
2321
+ {
2322
+ style: col.sticky ? { left, minWidth: col.width } : { minWidth: col.width },
2323
+ className: cn(
2324
+ "px-4 py-2.5 border-b font-medium text-muted-foreground",
2325
+ HEADER_CELL_BG,
2326
+ alignClass(col.align),
2327
+ col.sticky && "sticky z-20",
2328
+ isFirstCol && "rounded-tl-xl",
2329
+ col.headerClassName
2330
+ ),
2331
+ children: sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
2332
+ "button",
2333
+ {
2334
+ type: "button",
2335
+ onClick: () => toggleSort(col.key),
2336
+ className: "group/sort inline-flex items-center gap-1 hover:text-foreground",
2337
+ children: [
2338
+ col.header,
2339
+ sortIcon(col.key)
2340
+ ]
2341
+ }
2342
+ ) : col.header
2343
+ },
2344
+ col.key
2345
+ );
2346
+ }),
2347
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { "aria-hidden": true, className: cn("w-full border-b", HEADER_CELL_BG) })
2348
+ ] }) }),
2349
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: data.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(
2350
+ TableCell,
2351
+ {
2352
+ colSpan: colCount,
2353
+ className: "py-12 text-center text-sm text-muted-foreground rounded-bl-xl",
2354
+ children: emptyMessage
2355
+ }
2356
+ ) }) : rows.map((row, rowIndex) => {
2357
+ const id = rowKey(row);
2358
+ const isSel = selected.has(id);
2359
+ const rowBg = isSel ? "bg-muted" : "bg-background";
2360
+ const isLastRow = rowIndex === rows.length - 1;
2361
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2362
+ TableRow,
2363
+ {
2364
+ className: cn(
2365
+ "group",
2366
+ rowBg,
2367
+ "hover:bg-muted",
2368
+ rowClassName?.(row)
2369
+ ),
2370
+ children: [
2371
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(
2372
+ TableCell,
2373
+ {
2374
+ style: selectColStyle,
2375
+ className: cn(
2376
+ "sticky left-0 z-20 px-0 py-2.5 border-b group-hover:bg-muted",
2377
+ rowBg,
2378
+ isLastRow && "rounded-bl-xl"
2379
+ ),
2380
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
2381
+ Checkbox,
2382
+ {
2383
+ checked: isSel,
2384
+ onCheckedChange: () => toggleRow(id),
2385
+ "aria-label": "Select row"
2386
+ }
2387
+ ) })
2388
+ }
2389
+ ),
2390
+ columns.map((col, colIndex) => {
2391
+ const left = stickyLeft.get(col.key);
2392
+ const isFirstCol = !selectable && colIndex === 0;
2393
+ return /* @__PURE__ */ jsxRuntime.jsx(
2394
+ TableCell,
2395
+ {
2396
+ style: col.sticky ? { left } : void 0,
2397
+ className: cn(
2398
+ "px-4 py-2.5 border-b align-middle",
2399
+ alignClass(col.align),
2400
+ col.sticky && cn("sticky z-10 group-hover:bg-muted", rowBg),
2401
+ isFirstCol && isLastRow && "rounded-bl-xl",
2402
+ col.className
2403
+ ),
2404
+ onClick: col.sticky && onRowClick ? () => onRowClick(row) : void 0,
2405
+ children: col.render(row)
2406
+ },
2407
+ col.key
2408
+ );
2409
+ }),
2410
+ /* @__PURE__ */ jsxRuntime.jsx(TableCell, { "aria-hidden": true, className: "border-b" })
2411
+ ]
2412
+ },
2413
+ id
2414
+ );
2415
+ }) })
2416
+ ] }) }),
2417
+ paginated && total > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 px-1 text-sm text-muted-foreground", children: [
2418
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2419
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Rows per page" }),
2420
+ /* @__PURE__ */ jsxRuntime.jsxs(
2421
+ Select,
2422
+ {
2423
+ value: String(pageSize),
2424
+ onValueChange: (v) => {
2425
+ if (!v) return;
2426
+ setPageSizeInner(Number(v));
2427
+ setPage(0);
2428
+ },
2429
+ children: [
2430
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { "aria-label": "Rows per page", className: "h-8 w-[70px]", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, {}) }),
2431
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: pageSizeOptions.map((n) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: String(n), children: n }, n)) })
2432
+ ]
2433
+ }
2434
+ )
2435
+ ] }),
2436
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
2437
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums whitespace-nowrap", children: [
2438
+ pageStart + 1,
2439
+ "\u2013",
2440
+ Math.min(pageStart + pageSize, total),
2441
+ " of ",
2442
+ total
2443
+ ] }),
2444
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2445
+ /* @__PURE__ */ jsxRuntime.jsx(
2446
+ "button",
2447
+ {
2448
+ type: "button",
2449
+ onClick: () => setPage(safePage - 1),
2450
+ disabled: safePage === 0,
2451
+ "aria-label": "Previous page",
2452
+ className: "inline-flex size-8 items-center justify-center rounded-md border bg-background hover:bg-muted disabled:pointer-events-none disabled:opacity-40",
2453
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "size-4" })
2454
+ }
2455
+ ),
2456
+ /* @__PURE__ */ jsxRuntime.jsx(
2457
+ "button",
2458
+ {
2459
+ type: "button",
2460
+ onClick: () => setPage(safePage + 1),
2461
+ disabled: safePage >= pageCount - 1,
2462
+ "aria-label": "Next page",
2463
+ className: "inline-flex size-8 items-center justify-center rounded-md border bg-background hover:bg-muted disabled:pointer-events-none disabled:opacity-40",
2464
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-4" })
2465
+ }
2466
+ )
2467
+ ] })
2468
+ ] })
2469
+ ] })
2470
+ ] });
2471
+ }
2472
+ function DropdownMenu(props) {
2473
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
2474
+ }
2475
+ function DropdownMenuTrigger({ ...props }) {
2476
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
2477
+ }
2478
+ function DropdownMenuGroup(props) {
2479
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Group, { "data-slot": "dropdown-menu-group", ...props });
2480
+ }
2481
+ function DropdownMenuContent({
2482
+ className,
2483
+ sideOffset = 4,
2484
+ align = "start",
2485
+ ...props
2486
+ }) {
2487
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
2488
+ menu.Menu.Positioner,
2489
+ {
2490
+ sideOffset,
2491
+ align,
2492
+ className: "z-50",
2493
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2494
+ menu.Menu.Popup,
2495
+ {
2496
+ "data-slot": "dropdown-menu-content",
2497
+ className: cn(
2498
+ "bg-popover text-popover-foreground border-border z-50 min-w-[8rem] overflow-hidden rounded-lg border p-1 shadow-md outline-none",
2499
+ className
2500
+ ),
2501
+ ...props
2502
+ }
2503
+ )
2504
+ }
2505
+ ) });
2506
+ }
2507
+ var itemClasses = "relative flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none select-none transition-colors data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground";
2508
+ function DropdownMenuItem({ className, ...props }) {
2509
+ return /* @__PURE__ */ jsxRuntime.jsx(
2510
+ menu.Menu.Item,
2511
+ {
2512
+ "data-slot": "dropdown-menu-item",
2513
+ className: cn(itemClasses, className),
2514
+ ...props
2515
+ }
2516
+ );
2517
+ }
2518
+ function DropdownMenuCheckboxItem({
2519
+ className,
2520
+ children,
2521
+ ...props
2522
+ }) {
2523
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2524
+ menu.Menu.CheckboxItem,
2525
+ {
2526
+ "data-slot": "dropdown-menu-checkbox-item",
2527
+ className: cn(itemClasses, "pl-8", className),
2528
+ ...props,
2529
+ children: [
2530
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4" }) }) }),
2531
+ children
2532
+ ]
2533
+ }
2534
+ );
2535
+ }
2536
+ function DropdownMenuRadioGroup(props) {
2537
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.RadioGroup, { "data-slot": "dropdown-menu-radio-group", ...props });
2538
+ }
2539
+ function DropdownMenuRadioItem({
2540
+ className,
2541
+ children,
2542
+ ...props
2543
+ }) {
2544
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2545
+ menu.Menu.RadioItem,
2546
+ {
2547
+ "data-slot": "dropdown-menu-radio-item",
2548
+ className: cn(itemClasses, "pl-8", className),
2549
+ ...props,
2550
+ children: [
1715
2551
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.RadioItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Circle, { className: "size-2 fill-current" }) }) }),
1716
2552
  children
1717
2553
  ]
@@ -1958,42 +2794,401 @@ function FieldSeparator({
1958
2794
  }
1959
2795
  );
1960
2796
  }
1961
- function FieldError({
1962
- className,
1963
- children,
1964
- errors,
1965
- ...props
2797
+ function FieldError({
2798
+ className,
2799
+ children,
2800
+ errors,
2801
+ ...props
2802
+ }) {
2803
+ const content = React3.useMemo(() => {
2804
+ if (children) {
2805
+ return children;
2806
+ }
2807
+ if (!errors?.length) {
2808
+ return null;
2809
+ }
2810
+ const uniqueErrors = [
2811
+ ...new Map(errors.map((error) => [error?.message, error])).values()
2812
+ ];
2813
+ if (uniqueErrors?.length == 1) {
2814
+ return uniqueErrors[0]?.message;
2815
+ }
2816
+ return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "ml-4 flex list-disc flex-col gap-1", children: uniqueErrors.map(
2817
+ (error, index) => error?.message && /* @__PURE__ */ jsxRuntime.jsx("li", { children: error.message }, index)
2818
+ ) });
2819
+ }, [children, errors]);
2820
+ if (!content) {
2821
+ return null;
2822
+ }
2823
+ return /* @__PURE__ */ jsxRuntime.jsx(
2824
+ "div",
2825
+ {
2826
+ role: "alert",
2827
+ "data-slot": "field-error",
2828
+ className: cn("text-sm font-normal text-destructive", className),
2829
+ ...props,
2830
+ children: content
2831
+ }
2832
+ );
2833
+ }
2834
+ function CheckIndicator({ checked }) {
2835
+ return /* @__PURE__ */ jsxRuntime.jsx(
2836
+ "span",
2837
+ {
2838
+ "aria-hidden": true,
2839
+ className: cn(
2840
+ "flex size-4 shrink-0 items-center justify-center rounded-[4px] border transition-colors",
2841
+ checked ? "border-primary bg-primary text-primary-foreground" : "border-input"
2842
+ ),
2843
+ children: checked && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5" })
2844
+ }
2845
+ );
2846
+ }
2847
+ function FilterBar({
2848
+ search,
2849
+ onSearchChange,
2850
+ searchPlaceholder = "Search by name\u2026",
2851
+ showSearch = true,
2852
+ facets = [],
2853
+ values = {},
2854
+ onValuesChange,
2855
+ resultCount,
2856
+ resultNoun = "result",
2857
+ maxVisibleFacets = 3,
2858
+ right,
2859
+ left,
2860
+ filterVariant = "inline",
2861
+ className
2862
+ }) {
2863
+ const visibleFacets = facets.slice(0, maxVisibleFacets);
2864
+ const overflowFacets = facets.slice(maxVisibleFacets);
2865
+ const toggle = (key, value) => {
2866
+ const cur = values[key] ?? [];
2867
+ const next = cur.includes(value) ? cur.filter((v) => v !== value) : [...cur, value];
2868
+ onValuesChange?.({ ...values, [key]: next });
2869
+ };
2870
+ const clearAll = () => onValuesChange?.({});
2871
+ const activeCount = Object.values(values).reduce((n, a) => n + a.length, 0);
2872
+ const searchBox = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-56", children: [
2873
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }),
2874
+ /* @__PURE__ */ jsxRuntime.jsx(
2875
+ Input,
2876
+ {
2877
+ value: search,
2878
+ onChange: (e) => onSearchChange(e.target.value),
2879
+ placeholder: searchPlaceholder,
2880
+ "aria-label": searchPlaceholder,
2881
+ className: "rounded-full bg-background pl-8 pr-8"
2882
+ }
2883
+ ),
2884
+ search && /* @__PURE__ */ jsxRuntime.jsx(
2885
+ "button",
2886
+ {
2887
+ type: "button",
2888
+ onClick: () => onSearchChange(""),
2889
+ "aria-label": "Clear search",
2890
+ className: "absolute right-2 top-1/2 inline-flex size-5 -translate-y-1/2 items-center justify-center rounded-full text-muted-foreground hover:bg-muted hover:text-foreground",
2891
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" })
2892
+ }
2893
+ )
2894
+ ] });
2895
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
2896
+ left,
2897
+ filterVariant === "inline" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2898
+ showSearch && searchBox,
2899
+ visibleFacets.map((facet) => /* @__PURE__ */ jsxRuntime.jsx(
2900
+ FacetDropdown,
2901
+ {
2902
+ facet,
2903
+ selected: values[facet.key] ?? [],
2904
+ onToggle: (value) => toggle(facet.key, value),
2905
+ onClear: () => onValuesChange?.({ ...values, [facet.key]: [] })
2906
+ },
2907
+ facet.key
2908
+ )),
2909
+ overflowFacets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
2910
+ MoreFilters,
2911
+ {
2912
+ facets: overflowFacets,
2913
+ values,
2914
+ onToggle: toggle
2915
+ }
2916
+ ),
2917
+ activeCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
2918
+ "button",
2919
+ {
2920
+ type: "button",
2921
+ onClick: clearAll,
2922
+ "aria-label": "Clear all filters",
2923
+ className: "inline-flex h-7 items-center gap-1 px-2 text-xs text-muted-foreground hover:text-foreground",
2924
+ children: [
2925
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" }),
2926
+ activeCount
2927
+ ]
2928
+ }
2929
+ )
2930
+ ] }),
2931
+ filterVariant === "funnel" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2932
+ showSearch && searchBox,
2933
+ /* @__PURE__ */ jsxRuntime.jsx(
2934
+ FunnelFilter,
2935
+ {
2936
+ facets,
2937
+ values,
2938
+ onToggle: toggle,
2939
+ onClearAll: clearAll
2940
+ }
2941
+ )
2942
+ ] }),
2943
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
2944
+ typeof resultCount === "number" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "whitespace-nowrap text-sm text-muted-foreground", children: [
2945
+ resultCount,
2946
+ " ",
2947
+ resultNoun,
2948
+ resultCount === 1 ? "" : "s"
2949
+ ] }),
2950
+ right
2951
+ ] })
2952
+ ] }) });
2953
+ }
2954
+ function FacetDropdown({
2955
+ facet,
2956
+ selected,
2957
+ onToggle,
2958
+ onClear
2959
+ }) {
2960
+ const count = selected.length;
2961
+ const firstLabel = facet.options.find((o) => o.value === selected[0])?.label ?? selected[0];
2962
+ const summary = count === 0 ? facet.label : `${facet.label}: ${firstLabel}${count > 1 ? ` (+${count - 1})` : ""}`;
2963
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
2964
+ /* @__PURE__ */ jsxRuntime.jsx(
2965
+ PopoverTrigger,
2966
+ {
2967
+ render: /* @__PURE__ */ jsxRuntime.jsxs(
2968
+ "button",
2969
+ {
2970
+ type: "button",
2971
+ className: cn(
2972
+ "inline-flex h-7 max-w-[14rem] items-center gap-1 rounded-full border bg-background px-2.5 text-xs transition-colors",
2973
+ count > 0 ? "border-primary/40 bg-primary/5 text-foreground" : "text-muted-foreground hover:text-foreground"
2974
+ ),
2975
+ children: [
2976
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: summary }),
2977
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-3 shrink-0 opacity-60" })
2978
+ ]
2979
+ }
2980
+ )
2981
+ }
2982
+ ),
2983
+ /* @__PURE__ */ jsxRuntime.jsx(
2984
+ PopoverContent,
2985
+ {
2986
+ className: "w-60 p-0",
2987
+ align: "start",
2988
+ "aria-label": `${facet.label} options`,
2989
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Command, { children: [
2990
+ facet.options.length > 6 && /* @__PURE__ */ jsxRuntime.jsx(CommandInput, { placeholder: `Search ${facet.label.toLowerCase()}\u2026` }),
2991
+ /* @__PURE__ */ jsxRuntime.jsxs(CommandList, { children: [
2992
+ /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: "No options." }),
2993
+ /* @__PURE__ */ jsxRuntime.jsx(CommandGroup, { children: facet.options.map((opt) => {
2994
+ const checked = selected.includes(opt.value);
2995
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2996
+ CommandItem,
2997
+ {
2998
+ value: opt.label,
2999
+ onSelect: () => onToggle(opt.value),
3000
+ className: "gap-2.5",
3001
+ children: [
3002
+ /* @__PURE__ */ jsxRuntime.jsx(CheckIndicator, { checked }),
3003
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: opt.label }),
3004
+ checked && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "selected" })
3005
+ ]
3006
+ },
3007
+ opt.value
3008
+ );
3009
+ }) })
3010
+ ] }),
3011
+ count > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
3012
+ Button,
3013
+ {
3014
+ variant: "ghost",
3015
+ onClick: onClear,
3016
+ className: "w-full justify-center text-primary",
3017
+ children: "Clear"
3018
+ }
3019
+ ) })
3020
+ ] })
3021
+ }
3022
+ )
3023
+ ] });
3024
+ }
3025
+ function FunnelFilter({
3026
+ facets,
3027
+ values,
3028
+ onToggle,
3029
+ onClearAll
3030
+ }) {
3031
+ const [open, setOpen] = React3.useState(false);
3032
+ const [drill, setDrill] = React3.useState(null);
3033
+ const activeCount = Object.values(values).reduce((n, a) => n + a.length, 0);
3034
+ const facet = facets.find((f) => f.key === drill);
3035
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3036
+ Popover,
3037
+ {
3038
+ open,
3039
+ onOpenChange: (o) => {
3040
+ setOpen(o);
3041
+ if (!o) setDrill(null);
3042
+ },
3043
+ children: [
3044
+ /* @__PURE__ */ jsxRuntime.jsx(
3045
+ PopoverTrigger,
3046
+ {
3047
+ render: /* @__PURE__ */ jsxRuntime.jsxs(
3048
+ "button",
3049
+ {
3050
+ type: "button",
3051
+ className: cn(
3052
+ "inline-flex h-9 items-center gap-1.5 rounded-md border bg-background px-3 text-sm transition-colors",
3053
+ activeCount > 0 ? "text-foreground" : "text-muted-foreground hover:text-foreground"
3054
+ ),
3055
+ children: [
3056
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListFilter, { className: "size-4" }),
3057
+ "Filter",
3058
+ activeCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "ml-0.5 h-5 bg-primary px-1.5 text-primary-foreground", children: activeCount })
3059
+ ]
3060
+ }
3061
+ )
3062
+ }
3063
+ ),
3064
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-64 p-1", align: "end", "aria-label": "Filters", children: !facet ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3065
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Add filter" }),
3066
+ facets.map((f) => {
3067
+ const count = values[f.key]?.length ?? 0;
3068
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3069
+ "button",
3070
+ {
3071
+ type: "button",
3072
+ onClick: () => setDrill(f.key),
3073
+ className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted/60",
3074
+ children: [
3075
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: f.label }),
3076
+ count > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-primary", children: count }),
3077
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-3.5 opacity-50" })
3078
+ ]
3079
+ },
3080
+ f.key
3081
+ );
3082
+ }),
3083
+ activeCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3084
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1 border-t" }),
3085
+ /* @__PURE__ */ jsxRuntime.jsx(
3086
+ "button",
3087
+ {
3088
+ type: "button",
3089
+ onClick: onClearAll,
3090
+ className: "w-full rounded-md px-2 py-1.5 text-left text-sm text-muted-foreground hover:bg-muted/60",
3091
+ children: "Clear all filters"
3092
+ }
3093
+ )
3094
+ ] })
3095
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3096
+ /* @__PURE__ */ jsxRuntime.jsxs(
3097
+ "button",
3098
+ {
3099
+ type: "button",
3100
+ onClick: () => setDrill(null),
3101
+ className: "flex w-full items-center gap-1 rounded-md px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground hover:bg-muted/60",
3102
+ children: [
3103
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "size-3.5" }),
3104
+ facet.label
3105
+ ]
3106
+ }
3107
+ ),
3108
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-64 overflow-y-auto", children: facet.options.map((opt) => {
3109
+ const checked = (values[facet.key] ?? []).includes(opt.value);
3110
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3111
+ "button",
3112
+ {
3113
+ type: "button",
3114
+ onClick: () => onToggle(facet.key, opt.value),
3115
+ className: "flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted/60",
3116
+ children: [
3117
+ /* @__PURE__ */ jsxRuntime.jsx(
3118
+ "span",
3119
+ {
3120
+ className: cn(
3121
+ "flex size-4 shrink-0 items-center justify-center rounded border",
3122
+ checked ? "border-primary bg-primary text-primary-foreground" : "border-input"
3123
+ ),
3124
+ children: checked && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3" })
3125
+ }
3126
+ ),
3127
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: opt.label })
3128
+ ]
3129
+ },
3130
+ opt.value
3131
+ );
3132
+ }) })
3133
+ ] }) })
3134
+ ]
3135
+ }
3136
+ );
3137
+ }
3138
+ function MoreFilters({
3139
+ facets,
3140
+ values,
3141
+ onToggle
1966
3142
  }) {
1967
- const content = React3.useMemo(() => {
1968
- if (children) {
1969
- return children;
1970
- }
1971
- if (!errors?.length) {
1972
- return null;
1973
- }
1974
- const uniqueErrors = [
1975
- ...new Map(errors.map((error) => [error?.message, error])).values()
1976
- ];
1977
- if (uniqueErrors?.length == 1) {
1978
- return uniqueErrors[0]?.message;
1979
- }
1980
- return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "ml-4 flex list-disc flex-col gap-1", children: uniqueErrors.map(
1981
- (error, index) => error?.message && /* @__PURE__ */ jsxRuntime.jsx("li", { children: error.message }, index)
1982
- ) });
1983
- }, [children, errors]);
1984
- if (!content) {
1985
- return null;
1986
- }
1987
- return /* @__PURE__ */ jsxRuntime.jsx(
1988
- "div",
1989
- {
1990
- role: "alert",
1991
- "data-slot": "field-error",
1992
- className: cn("text-sm font-normal text-destructive", className),
1993
- ...props,
1994
- children: content
1995
- }
3143
+ const activeCount = facets.reduce(
3144
+ (n, f) => n + (values[f.key]?.length ?? 0),
3145
+ 0
1996
3146
  );
3147
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
3148
+ /* @__PURE__ */ jsxRuntime.jsx(
3149
+ PopoverTrigger,
3150
+ {
3151
+ render: /* @__PURE__ */ jsxRuntime.jsxs(
3152
+ "button",
3153
+ {
3154
+ type: "button",
3155
+ className: cn(
3156
+ "inline-flex h-7 items-center gap-1 rounded-full border bg-background px-2.5 text-xs transition-colors",
3157
+ activeCount > 0 ? "border-primary/40 bg-primary/5 text-foreground" : "text-muted-foreground hover:text-foreground"
3158
+ ),
3159
+ children: [
3160
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListFilter, { className: "size-3.5" }),
3161
+ "More",
3162
+ activeCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "ml-0.5 h-4 bg-primary px-1.5 text-primary-foreground", children: activeCount })
3163
+ ]
3164
+ }
3165
+ )
3166
+ }
3167
+ ),
3168
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-64 p-0", align: "start", "aria-label": "Filters", children: /* @__PURE__ */ jsxRuntime.jsxs(Command, { children: [
3169
+ facets.reduce((n, f) => n + f.options.length, 0) > 8 && /* @__PURE__ */ jsxRuntime.jsx(CommandInput, { placeholder: "Search filters\u2026" }),
3170
+ /* @__PURE__ */ jsxRuntime.jsxs(CommandList, { className: "max-h-[60vh]", children: [
3171
+ /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: "No filters." }),
3172
+ facets.map((facet) => /* @__PURE__ */ jsxRuntime.jsx(CommandGroup, { heading: facet.label, children: facet.options.map((opt) => {
3173
+ const checked = (values[facet.key] ?? []).includes(opt.value);
3174
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3175
+ CommandItem,
3176
+ {
3177
+ value: `${facet.label} ${opt.label}`,
3178
+ onSelect: () => onToggle(facet.key, opt.value),
3179
+ className: "gap-2.5",
3180
+ children: [
3181
+ /* @__PURE__ */ jsxRuntime.jsx(CheckIndicator, { checked }),
3182
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: opt.label }),
3183
+ checked && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "selected" })
3184
+ ]
3185
+ },
3186
+ opt.value
3187
+ );
3188
+ }) }, facet.key))
3189
+ ] })
3190
+ ] }) })
3191
+ ] });
1997
3192
  }
1998
3193
  function PackagePicker({
1999
3194
  packages,
@@ -2961,75 +4156,6 @@ function PersonDropdown({
2961
4156
  }
2962
4157
  );
2963
4158
  }
2964
- function Popover({ ...props }) {
2965
- return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Root, { "data-slot": "popover", ...props });
2966
- }
2967
- function PopoverTrigger({ ...props }) {
2968
- return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { "data-slot": "popover-trigger", ...props });
2969
- }
2970
- function PopoverContent({
2971
- className,
2972
- align = "center",
2973
- alignOffset = 0,
2974
- side = "bottom",
2975
- sideOffset = 4,
2976
- ...props
2977
- }) {
2978
- return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
2979
- popover.Popover.Positioner,
2980
- {
2981
- align,
2982
- alignOffset,
2983
- side,
2984
- sideOffset,
2985
- className: "isolate z-50",
2986
- children: /* @__PURE__ */ jsxRuntime.jsx(
2987
- popover.Popover.Popup,
2988
- {
2989
- "data-slot": "popover-content",
2990
- className: cn(
2991
- "z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
2992
- className
2993
- ),
2994
- ...props
2995
- }
2996
- )
2997
- }
2998
- ) });
2999
- }
3000
- function PopoverHeader({ className, ...props }) {
3001
- return /* @__PURE__ */ jsxRuntime.jsx(
3002
- "div",
3003
- {
3004
- "data-slot": "popover-header",
3005
- className: cn("flex flex-col gap-0.5 text-sm", className),
3006
- ...props
3007
- }
3008
- );
3009
- }
3010
- function PopoverTitle({ className, ...props }) {
3011
- return /* @__PURE__ */ jsxRuntime.jsx(
3012
- popover.Popover.Title,
3013
- {
3014
- "data-slot": "popover-title",
3015
- className: cn("font-medium", className),
3016
- ...props
3017
- }
3018
- );
3019
- }
3020
- function PopoverDescription({
3021
- className,
3022
- ...props
3023
- }) {
3024
- return /* @__PURE__ */ jsxRuntime.jsx(
3025
- popover.Popover.Description,
3026
- {
3027
- "data-slot": "popover-description",
3028
- className: cn("text-muted-foreground", className),
3029
- ...props
3030
- }
3031
- );
3032
- }
3033
4159
  function ScrollArea({
3034
4160
  className,
3035
4161
  children,
@@ -3494,6 +4620,37 @@ function Progress({ className, value, ...props }) {
3494
4620
  }
3495
4621
  );
3496
4622
  }
4623
+ function RadioGroup({ className, ...props }) {
4624
+ return /* @__PURE__ */ jsxRuntime.jsx(
4625
+ radioGroup.RadioGroup,
4626
+ {
4627
+ "data-slot": "radio-group",
4628
+ className: cn("grid gap-3", className),
4629
+ ...props
4630
+ }
4631
+ );
4632
+ }
4633
+ function RadioGroupItem({ className, ...props }) {
4634
+ return /* @__PURE__ */ jsxRuntime.jsx(
4635
+ radio.Radio.Root,
4636
+ {
4637
+ "data-slot": "radio-group-item",
4638
+ className: cn(
4639
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-full border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
4640
+ className
4641
+ ),
4642
+ ...props,
4643
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4644
+ radio.Radio.Indicator,
4645
+ {
4646
+ "data-slot": "radio-group-indicator",
4647
+ className: "grid place-content-center text-current transition-none",
4648
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1.5 rounded-full bg-current" })
4649
+ }
4650
+ )
4651
+ }
4652
+ );
4653
+ }
3497
4654
  function mandatoryTotal(session) {
3498
4655
  return (session.mandatoryFees ?? []).reduce((s, f) => s + f.amount, 0);
3499
4656
  }
@@ -4182,7 +5339,7 @@ function SheetContent({
4182
5339
  "data-slot": "sheet-content",
4183
5340
  "data-side": side,
4184
5341
  className: cn(
4185
- "fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm",
5342
+ "fixed z-50 flex flex-col gap-4 border-border bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm",
4186
5343
  className
4187
5344
  ),
4188
5345
  ...props,
@@ -5225,108 +6382,6 @@ function Switch({
5225
6382
  }
5226
6383
  );
5227
6384
  }
5228
- function Table({ className, ...props }) {
5229
- return /* @__PURE__ */ jsxRuntime.jsx(
5230
- "div",
5231
- {
5232
- "data-slot": "table-container",
5233
- className: "relative w-full overflow-x-auto",
5234
- children: /* @__PURE__ */ jsxRuntime.jsx(
5235
- "table",
5236
- {
5237
- "data-slot": "table",
5238
- className: cn("w-full caption-bottom text-sm", className),
5239
- ...props
5240
- }
5241
- )
5242
- }
5243
- );
5244
- }
5245
- function TableHeader({ className, ...props }) {
5246
- return /* @__PURE__ */ jsxRuntime.jsx(
5247
- "thead",
5248
- {
5249
- "data-slot": "table-header",
5250
- className: cn("[&_tr]:border-b", className),
5251
- ...props
5252
- }
5253
- );
5254
- }
5255
- function TableBody({ className, ...props }) {
5256
- return /* @__PURE__ */ jsxRuntime.jsx(
5257
- "tbody",
5258
- {
5259
- "data-slot": "table-body",
5260
- className: cn("[&_tr:last-child]:border-0", className),
5261
- ...props
5262
- }
5263
- );
5264
- }
5265
- function TableFooter({ className, ...props }) {
5266
- return /* @__PURE__ */ jsxRuntime.jsx(
5267
- "tfoot",
5268
- {
5269
- "data-slot": "table-footer",
5270
- className: cn(
5271
- "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
5272
- className
5273
- ),
5274
- ...props
5275
- }
5276
- );
5277
- }
5278
- function TableRow({ className, ...props }) {
5279
- return /* @__PURE__ */ jsxRuntime.jsx(
5280
- "tr",
5281
- {
5282
- "data-slot": "table-row",
5283
- className: cn(
5284
- "border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
5285
- className
5286
- ),
5287
- ...props
5288
- }
5289
- );
5290
- }
5291
- function TableHead({ className, ...props }) {
5292
- return /* @__PURE__ */ jsxRuntime.jsx(
5293
- "th",
5294
- {
5295
- "data-slot": "table-head",
5296
- className: cn(
5297
- "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
5298
- className
5299
- ),
5300
- ...props
5301
- }
5302
- );
5303
- }
5304
- function TableCell({ className, ...props }) {
5305
- return /* @__PURE__ */ jsxRuntime.jsx(
5306
- "td",
5307
- {
5308
- "data-slot": "table-cell",
5309
- className: cn(
5310
- "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
5311
- className
5312
- ),
5313
- ...props
5314
- }
5315
- );
5316
- }
5317
- function TableCaption({
5318
- className,
5319
- ...props
5320
- }) {
5321
- return /* @__PURE__ */ jsxRuntime.jsx(
5322
- "caption",
5323
- {
5324
- "data-slot": "table-caption",
5325
- className: cn("mt-4 text-sm text-muted-foreground", className),
5326
- ...props
5327
- }
5328
- );
5329
- }
5330
6385
  function Tabs({
5331
6386
  className,
5332
6387
  orientation = "horizontal",
@@ -5438,6 +6493,8 @@ exports.CardFooter = CardFooter;
5438
6493
  exports.CardHeader = CardHeader;
5439
6494
  exports.CardTitle = CardTitle;
5440
6495
  exports.Checkbox = Checkbox;
6496
+ exports.ColumnCustomizer = ColumnCustomizer;
6497
+ exports.ColumnPicker = ColumnPicker;
5441
6498
  exports.Command = Command;
5442
6499
  exports.CommandDialog = CommandDialog;
5443
6500
  exports.CommandEmpty = CommandEmpty;
@@ -5447,6 +6504,7 @@ exports.CommandItem = CommandItem;
5447
6504
  exports.CommandList = CommandList;
5448
6505
  exports.CommandSeparator = CommandSeparator;
5449
6506
  exports.CommandShortcut = CommandShortcut;
6507
+ exports.DataTable = DataTable;
5450
6508
  exports.Dialog = Dialog;
5451
6509
  exports.DialogClose = DialogClose;
5452
6510
  exports.DialogContent = DialogContent;
@@ -5481,6 +6539,7 @@ exports.FieldLegend = FieldLegend;
5481
6539
  exports.FieldSeparator = FieldSeparator;
5482
6540
  exports.FieldSet = FieldSet;
5483
6541
  exports.FieldTitle = FieldTitle;
6542
+ exports.FilterBar = FilterBar;
5484
6543
  exports.InlineAddonPicker = InlineAddonPicker;
5485
6544
  exports.InlineSessionPicker = InlineSessionPicker;
5486
6545
  exports.Input = Input;
@@ -5505,6 +6564,8 @@ exports.PopoverHeader = PopoverHeader;
5505
6564
  exports.PopoverTitle = PopoverTitle;
5506
6565
  exports.PopoverTrigger = PopoverTrigger;
5507
6566
  exports.Progress = Progress;
6567
+ exports.RadioGroup = RadioGroup;
6568
+ exports.RadioGroupItem = RadioGroupItem;
5508
6569
  exports.STATUS_LABEL = STATUS_LABEL;
5509
6570
  exports.ScrollArea = ScrollArea;
5510
6571
  exports.ScrollBar = ScrollBar;