@fayz-ai/ui 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/analytics/AnalyticsControls.d.ts +5 -1
  2. package/dist/analytics/AnalyticsControls.d.ts.map +1 -1
  3. package/dist/{chunk-JGJNRNQW.js → chunk-2EFRFYGF.js} +117 -41
  4. package/dist/chunk-2EFRFYGF.js.map +1 -0
  5. package/dist/{chunk-7BMXN7MP.js → chunk-46UZAKFJ.js} +24 -24
  6. package/dist/chunk-46UZAKFJ.js.map +1 -0
  7. package/dist/chunk-5KAGNW45.js +152 -0
  8. package/dist/chunk-5KAGNW45.js.map +1 -0
  9. package/dist/{chunk-7BHG3XGJ.js → chunk-77CUIMOI.js} +201 -119
  10. package/dist/chunk-77CUIMOI.js.map +1 -0
  11. package/dist/chunk-LFZFBN3P.js +142 -0
  12. package/dist/chunk-LFZFBN3P.js.map +1 -0
  13. package/dist/{chunk-ZDRHCKRK.js → chunk-MVH64JFG.js} +1029 -767
  14. package/dist/chunk-MVH64JFG.js.map +1 -0
  15. package/dist/{chunk-22EVFMS3.js → chunk-UZYXFEQS.js} +4 -3
  16. package/dist/chunk-UZYXFEQS.js.map +1 -0
  17. package/dist/dashboard/DashboardCanvas.d.ts.map +1 -1
  18. package/dist/dashboard/DashboardCustomizeMenu.d.ts.map +1 -1
  19. package/dist/dashboard/DashboardRange.d.ts +8 -2
  20. package/dist/dashboard/DashboardRange.d.ts.map +1 -1
  21. package/dist/dashboard/index.js +4 -5
  22. package/dist/icons.js +1 -1
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +69 -96
  26. package/dist/index.js.map +1 -1
  27. package/dist/layout/AppShell.d.ts +1 -0
  28. package/dist/layout/AppShell.d.ts.map +1 -1
  29. package/dist/layout/ModulePage.d.ts +24 -1
  30. package/dist/layout/ModulePage.d.ts.map +1 -1
  31. package/dist/layout/Sidebar.d.ts.map +1 -1
  32. package/dist/layout/index.d.ts +2 -1
  33. package/dist/layout/index.d.ts.map +1 -1
  34. package/dist/layout/index.js +4 -5
  35. package/dist/layout/rail-flyout.d.ts +10 -0
  36. package/dist/layout/rail-flyout.d.ts.map +1 -1
  37. package/dist/primitives/bulk-action-bar.d.ts +3 -1
  38. package/dist/primitives/bulk-action-bar.d.ts.map +1 -1
  39. package/dist/primitives/header-tabs.d.ts +36 -6
  40. package/dist/primitives/header-tabs.d.ts.map +1 -1
  41. package/dist/primitives/index.d.ts +2 -1
  42. package/dist/primitives/index.d.ts.map +1 -1
  43. package/dist/primitives/index.js +5 -4
  44. package/dist/primitives/list-view.d.ts +3 -1
  45. package/dist/primitives/list-view.d.ts.map +1 -1
  46. package/dist/primitives/page-toolbar.d.ts +61 -0
  47. package/dist/primitives/page-toolbar.d.ts.map +1 -0
  48. package/dist/primitives/search-select.d.ts +3 -1
  49. package/dist/primitives/search-select.d.ts.map +1 -1
  50. package/dist/primitives/tabs.d.ts.map +1 -1
  51. package/dist/stores/index.d.ts +1 -1
  52. package/dist/stores/index.d.ts.map +1 -1
  53. package/dist/stores/page-header.store.d.ts +26 -2
  54. package/dist/stores/page-header.store.d.ts.map +1 -1
  55. package/dist/styles.css +54 -17
  56. package/package.json +5 -5
  57. package/dist/chunk-22EVFMS3.js.map +0 -1
  58. package/dist/chunk-7BHG3XGJ.js.map +0 -1
  59. package/dist/chunk-7BMXN7MP.js.map +0 -1
  60. package/dist/chunk-JGJNRNQW.js.map +0 -1
  61. package/dist/chunk-OKZ6WQB3.js +0 -57
  62. package/dist/chunk-OKZ6WQB3.js.map +0 -1
  63. package/dist/chunk-VAKWUUVC.js +0 -425
  64. package/dist/chunk-VAKWUUVC.js.map +0 -1
  65. package/dist/chunk-ZBQ772DU.js +0 -17
  66. package/dist/chunk-ZBQ772DU.js.map +0 -1
  67. package/dist/chunk-ZDRHCKRK.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import { useSaveBarVisible, useCrossModuleBack, useBackHandler, HeaderTabs } from './chunk-VAKWUUVC.js';
2
- import { Dropdown, DropdownTrigger, DropdownContent, DropdownItem, Card, DataTable, SegmentedControl } from './chunk-JGJNRNQW.js';
3
- import { cn, Button } from './chunk-OKZ6WQB3.js';
1
+ import { useSaveBarVisible, useCrossModuleBack, useBackHandler, PageHeaderActions } from './chunk-MVH64JFG.js';
2
+ import { Dropdown, DropdownTrigger, DropdownContent, DropdownItem, Card, DataTable } from './chunk-2EFRFYGF.js';
3
+ import { cn, Button } from './chunk-LFZFBN3P.js';
4
4
  import * as React14 from 'react';
5
5
  import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -320,7 +320,9 @@ var TabsList = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__
320
320
  {
321
321
  ref,
322
322
  className: cn(
323
- "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
323
+ // Theme radius, not a fixed one: the chip and its track are controls, and
324
+ // an app that states 12px corners had these two answering 6px.
325
+ "inline-flex h-10 items-center justify-center rounded-button bg-muted p-1 text-muted-foreground",
324
326
  className
325
327
  ),
326
328
  ...props
@@ -332,7 +334,7 @@ var TabsTrigger = React14.forwardRef(({ className, ...props }, ref) => /* @__PUR
332
334
  {
333
335
  ref,
334
336
  className: cn(
335
- "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
337
+ "inline-flex items-center justify-center whitespace-nowrap rounded-button px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-card data-[state=active]:text-foreground data-[state=active]:shadow-sm",
336
338
  className
337
339
  ),
338
340
  ...props
@@ -531,6 +533,7 @@ function BulkActionBar({
531
533
  onSelectAll,
532
534
  onClear,
533
535
  actions = [],
536
+ variant = "band",
534
537
  className
535
538
  }) {
536
539
  const t = useTranslation();
@@ -541,7 +544,8 @@ function BulkActionBar({
541
544
  "div",
542
545
  {
543
546
  className: cn(
544
- "flex flex-wrap items-center justify-between gap-2 rounded-lg border border-border bg-muted/30 px-3 py-2",
547
+ "flex flex-wrap items-center justify-between gap-2",
548
+ variant === "band" ? "rounded-lg border border-border bg-muted/30 px-3 py-2" : "w-full min-h-8",
545
549
  className
546
550
  ),
547
551
  role: "region",
@@ -918,7 +922,39 @@ function TimePicker({ value, onChange, interval = 15, min = "00:00", max = "23:4
918
922
  )
919
923
  ] });
920
924
  }
921
- var ALL_TAG = "__all__";
925
+ function FilterChip({ allLabel, options, value, onChange, label, icon: Icon2, className }) {
926
+ const active = value != null && value !== "";
927
+ const current = options.find((o) => o.value === value);
928
+ return /* @__PURE__ */ jsxs(Dropdown, { children: [
929
+ /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
930
+ "button",
931
+ {
932
+ type: "button",
933
+ "aria-label": label,
934
+ className: cn(
935
+ "inline-flex shrink-0 items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",
936
+ active ? "border-primary/30 bg-primary/10 text-primary hover:bg-primary/15" : "border-transparent bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground",
937
+ className
938
+ ),
939
+ children: [
940
+ Icon2 && /* @__PURE__ */ jsx(Icon2, { className: "h-3 w-3 shrink-0 opacity-70" }),
941
+ /* @__PURE__ */ jsx("span", { className: "max-w-[12rem] truncate", children: current?.label ?? allLabel }),
942
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0 opacity-60" })
943
+ ]
944
+ }
945
+ ) }),
946
+ /* @__PURE__ */ jsxs(DropdownContent, { align: "start", children: [
947
+ /* @__PURE__ */ jsxs(DropdownItem, { onClick: () => onChange(void 0), children: [
948
+ allLabel,
949
+ !active && /* @__PURE__ */ jsx(Check, { className: "ml-auto h-3.5 w-3.5 shrink-0 pl-1" })
950
+ ] }),
951
+ options.map((o) => /* @__PURE__ */ jsxs(DropdownItem, { onClick: () => onChange(o.value), children: [
952
+ o.label,
953
+ value === o.value && /* @__PURE__ */ jsx(Check, { className: "ml-auto h-3.5 w-3.5 shrink-0 pl-1" })
954
+ ] }, o.value))
955
+ ] })
956
+ ] });
957
+ }
922
958
  var ICON_BTN = "flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground";
923
959
  function ListView({
924
960
  columns,
@@ -930,6 +966,7 @@ function ListView({
930
966
  searchDebounce = 300,
931
967
  tags,
932
968
  allTagLabel = "All",
969
+ tagsLabel,
933
970
  activeTag,
934
971
  onTagChange,
935
972
  newLabel,
@@ -971,8 +1008,16 @@ function ListView({
971
1008
  const showPagination = onPageChange && totalItems > pageSize;
972
1009
  const showSearch = !!onSearchChange;
973
1010
  const showTags = tags && tags.length > 0 && onTagChange;
974
- const showHeader = showTags || onNew && newLabel || headerActions;
975
- const headerTabs = showTags ? [{ value: ALL_TAG, label: allTagLabel }, ...tags.map((t) => ({ value: t.value, label: t.label }))] : null;
1011
+ const tagFilter = showTags ? /* @__PURE__ */ jsx(
1012
+ FilterChip,
1013
+ {
1014
+ label: tagsLabel,
1015
+ allLabel: allTagLabel,
1016
+ options: tags.map((t) => ({ value: t.value, label: t.label })),
1017
+ value: activeTag,
1018
+ onChange: (next) => onTagChange(next)
1019
+ }
1020
+ ) : null;
976
1021
  const emptyState = /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-6", children: [
977
1022
  EmptyIcon && /* @__PURE__ */ jsx(EmptyIcon, { className: "mb-2 h-9 w-9 text-muted-foreground/40" }),
978
1023
  /* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-foreground", children: emptyMessage }),
@@ -982,26 +1027,16 @@ function ListView({
982
1027
  ] })
983
1028
  ] });
984
1029
  return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
985
- showHeader && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
986
- headerTabs ? /* @__PURE__ */ jsx(
987
- HeaderTabs,
988
- {
989
- tabs: headerTabs,
990
- value: activeTag ?? ALL_TAG,
991
- onChange: (next) => onTagChange(next === ALL_TAG ? void 0 : next)
992
- }
993
- ) : /* @__PURE__ */ jsx("div", {}),
994
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
995
- headerActions,
996
- onNew && newLabel && /* @__PURE__ */ jsxs(Button, { variant: "default", size: "default", onClick: onNew, className: "shrink-0", children: [
997
- /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
998
- newLabel
999
- ] })
1030
+ (headerActions || onNew && newLabel) && /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1031
+ headerActions,
1032
+ onNew && newLabel && /* @__PURE__ */ jsxs(Button, { variant: "default", size: "default", onClick: onNew, className: "shrink-0", children: [
1033
+ /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
1034
+ newLabel
1000
1035
  ] })
1001
- ] }),
1036
+ ] }) }),
1002
1037
  toolbar,
1003
1038
  /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
1004
- (showSearch || filters || onRefresh || onExport) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: [
1039
+ (showSearch || tagFilter || filters || onRefresh || onExport) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: [
1005
1040
  showSearch && /* @__PURE__ */ jsxs("div", { className: "relative min-w-0 flex-1", children: [
1006
1041
  /* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }),
1007
1042
  /* @__PURE__ */ jsx(
@@ -1015,7 +1050,8 @@ function ListView({
1015
1050
  }
1016
1051
  )
1017
1052
  ] }),
1018
- (filters || onRefresh || onExport) && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex flex-wrap items-center justify-end gap-2", children: [
1053
+ (tagFilter || filters || onRefresh || onExport) && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex flex-wrap items-center justify-end gap-2", children: [
1054
+ tagFilter,
1019
1055
  filters,
1020
1056
  onRefresh && /* @__PURE__ */ jsx("button", { type: "button", "aria-label": refreshLabel, title: refreshLabel, onClick: onRefresh, className: ICON_BTN, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }),
1021
1057
  onExport && /* @__PURE__ */ jsx("button", { type: "button", "aria-label": exportLabel, title: exportLabel, onClick: onExport, className: ICON_BTN, children: /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" }) })
@@ -1252,6 +1288,7 @@ function DatePicker({ value, onChange, className, variant = "input", defaultOpen
1252
1288
  )
1253
1289
  ] });
1254
1290
  }
1291
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React14.useLayoutEffect : React14.useEffect;
1255
1292
  function SearchSelect({
1256
1293
  value,
1257
1294
  displayValue,
@@ -1266,12 +1303,14 @@ function SearchSelect({
1266
1303
  searchingLabel = "Searching...",
1267
1304
  allowCreate,
1268
1305
  createLabel = "Add",
1306
+ clearLabel = "Clear",
1269
1307
  onCreate,
1270
1308
  renderOption,
1271
1309
  loadOnOpen = true,
1272
1310
  className,
1273
1311
  disabled
1274
1312
  }) {
1313
+ const canCreate = !!onCreate && allowCreate !== false;
1275
1314
  const [open, setOpen] = React14.useState(false);
1276
1315
  const [query, setQuery] = React14.useState("");
1277
1316
  const [results, setResults] = React14.useState([]);
@@ -1281,11 +1320,14 @@ function SearchSelect({
1281
1320
  const containerRef = React14.useRef(null);
1282
1321
  const inputRef = React14.useRef(null);
1283
1322
  const timerRef = React14.useRef();
1323
+ const [rect, setRect] = React14.useState(null);
1324
+ const dropdownRef = React14.useRef(null);
1284
1325
  React14.useEffect(() => {
1285
1326
  function handler(e) {
1286
- if (containerRef.current && !containerRef.current.contains(e.target)) {
1287
- setOpen(false);
1288
- }
1327
+ const target = e.target;
1328
+ if (containerRef.current?.contains(target)) return;
1329
+ if (dropdownRef.current?.contains(target)) return;
1330
+ setOpen(false);
1289
1331
  }
1290
1332
  document.addEventListener("mousedown", handler);
1291
1333
  return () => document.removeEventListener("mousedown", handler);
@@ -1362,6 +1404,27 @@ function SearchSelect({
1362
1404
  }, [results]);
1363
1405
  const hasValue = !!value && !!selectedLabel;
1364
1406
  const showDropdown = open && (query.length >= minChars || loadOnOpen);
1407
+ useIsomorphicLayoutEffect(() => {
1408
+ if (!showDropdown) {
1409
+ setRect(null);
1410
+ return;
1411
+ }
1412
+ const measure = () => {
1413
+ const el = containerRef.current;
1414
+ if (!el) return;
1415
+ const r = el.getBoundingClientRect();
1416
+ const below = window.innerHeight - r.bottom;
1417
+ const above = below < 240 && r.top > below;
1418
+ setRect({ left: r.left, top: above ? r.top : r.bottom, width: r.width, above });
1419
+ };
1420
+ measure();
1421
+ window.addEventListener("scroll", measure, true);
1422
+ window.addEventListener("resize", measure);
1423
+ return () => {
1424
+ window.removeEventListener("scroll", measure, true);
1425
+ window.removeEventListener("resize", measure);
1426
+ };
1427
+ }, [showDropdown]);
1365
1428
  return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cn("relative", className), children: [
1366
1429
  label && /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-muted-foreground", children: [
1367
1430
  label,
@@ -1408,65 +1471,72 @@ function SearchSelect({
1408
1471
  ]
1409
1472
  }
1410
1473
  ),
1411
- showDropdown && /* @__PURE__ */ jsx("div", { className: "fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg overflow-hidden", children: loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-6 text-xs text-muted-foreground", children: [
1412
- /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
1413
- " ",
1414
- searchingLabel
1415
- ] }) : results.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "px-4 py-4 text-center", children: [
1416
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: noResultsLabel ?? (query ? `No results for "${query}"` : "No results") }),
1417
- allowCreate && onCreate && /* @__PURE__ */ jsxs(
1418
- "button",
1474
+ showDropdown && rect && createPortal(
1475
+ /* @__PURE__ */ jsxs(
1476
+ "div",
1419
1477
  {
1420
- onClick: () => handleCreate(query),
1421
- className: "mt-2 text-xs text-primary hover:underline",
1422
- children: [
1423
- "+ ",
1424
- createLabel,
1425
- ' "',
1426
- query,
1427
- '"'
1428
- ]
1429
- }
1430
- )
1431
- ] }) : /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-auto py-1", children: [
1432
- [...groups.entries()].map(([group, options]) => /* @__PURE__ */ jsxs(React14.Fragment, { children: [
1433
- group && /* @__PURE__ */ jsx("div", { className: "sticky top-0 bg-muted/50 px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
1434
- options.map((opt) => /* @__PURE__ */ jsx(
1435
- "button",
1436
- {
1437
- onClick: () => handleSelect(opt),
1438
- disabled: opt.disabled,
1439
- className: cn(
1440
- "w-full text-left px-3 py-2 hover:bg-muted/50 transition-colors flex items-center gap-2.5",
1441
- opt.disabled && "opacity-40 cursor-not-allowed",
1442
- opt.id === value && "bg-muted/30"
1443
- ),
1444
- children: renderOption ? renderOption(opt) : /* @__PURE__ */ jsxs(Fragment, { children: [
1445
- opt.icon,
1446
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1447
- /* @__PURE__ */ jsx("p", { className: "text-sm truncate", children: opt.label }),
1448
- opt.subtitle && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground truncate", children: opt.subtitle })
1449
- ] })
1450
- ] })
1478
+ ref: dropdownRef,
1479
+ style: {
1480
+ position: "fixed",
1481
+ left: rect.left,
1482
+ width: rect.width,
1483
+ ...rect.above ? { bottom: window.innerHeight - rect.top + 4 } : { top: rect.top + 4 }
1451
1484
  },
1452
- opt.id
1453
- ))
1454
- ] }, group)),
1455
- allowCreate && onCreate && /* @__PURE__ */ jsxs(
1456
- "button",
1457
- {
1458
- onClick: () => handleCreate(query),
1459
- className: "w-full text-left px-3 py-2 text-xs text-primary hover:bg-muted/50 transition-colors border-t",
1485
+ className: "fayz-glass-surface z-[60] overflow-hidden rounded-lg border bg-popover shadow-lg",
1460
1486
  children: [
1461
- "+ ",
1462
- createLabel,
1463
- ' "',
1464
- query,
1465
- '"'
1487
+ loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-6 text-xs text-muted-foreground", children: [
1488
+ /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
1489
+ " ",
1490
+ searchingLabel
1491
+ ] }) : results.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-4 py-4 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: noResultsLabel ?? (query ? `No results for "${query}"` : "No results") }) }) : /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-auto py-1", children: [...groups.entries()].map(([group, options]) => /* @__PURE__ */ jsxs(React14.Fragment, { children: [
1492
+ group && /* @__PURE__ */ jsx("div", { className: "sticky top-0 bg-muted/50 px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
1493
+ options.map((opt) => /* @__PURE__ */ jsx(
1494
+ "button",
1495
+ {
1496
+ onClick: () => handleSelect(opt),
1497
+ disabled: opt.disabled,
1498
+ className: cn(
1499
+ "w-full text-left px-3 py-2 hover:bg-muted/50 transition-colors flex items-center gap-2.5",
1500
+ opt.disabled && "opacity-40 cursor-not-allowed",
1501
+ opt.id === value && "bg-muted/30"
1502
+ ),
1503
+ children: renderOption ? renderOption(opt) : /* @__PURE__ */ jsxs(Fragment, { children: [
1504
+ opt.icon,
1505
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1506
+ /* @__PURE__ */ jsx("p", { className: "text-sm truncate", children: opt.label }),
1507
+ opt.subtitle && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground truncate", children: opt.subtitle })
1508
+ ] })
1509
+ ] })
1510
+ },
1511
+ opt.id
1512
+ ))
1513
+ ] }, group)) }),
1514
+ (canCreate || hasValue || query.trim()) && !loading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 border-t bg-muted/20 px-1.5 py-1", children: [
1515
+ hasValue || query.trim() ? /* @__PURE__ */ jsx(
1516
+ "button",
1517
+ {
1518
+ onClick: handleClear,
1519
+ className: "rounded-md px-2 py-1.5 text-xs text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
1520
+ children: clearLabel
1521
+ }
1522
+ ) : /* @__PURE__ */ jsx("span", {}),
1523
+ canCreate && /* @__PURE__ */ jsxs(
1524
+ "button",
1525
+ {
1526
+ onClick: () => handleCreate(query),
1527
+ className: "inline-flex items-center gap-1 rounded-md px-2 py-1.5 text-xs font-medium text-primary transition-colors hover:bg-primary/10",
1528
+ children: [
1529
+ /* @__PURE__ */ jsx(Plus, { className: "h-3 w-3" }),
1530
+ query.trim() ? `${createLabel} "${query.trim()}"` : createLabel
1531
+ ]
1532
+ }
1533
+ )
1534
+ ] })
1466
1535
  ]
1467
1536
  }
1468
- )
1469
- ] }) })
1537
+ ),
1538
+ document.body
1539
+ )
1470
1540
  ] });
1471
1541
  }
1472
1542
  function CurrencyInput({
@@ -1653,38 +1723,50 @@ var PopoverContent = React14.forwardRef(({ className, align = "start", sideOffse
1653
1723
  }
1654
1724
  ) }));
1655
1725
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1656
- function FilterChip({ allLabel, options, value, onChange, label, icon: Icon2, className }) {
1657
- const active = value != null && value !== "";
1658
- const current = options.find((o) => o.value === value);
1659
- return /* @__PURE__ */ jsxs(Dropdown, { children: [
1660
- /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1661
- "button",
1662
- {
1663
- type: "button",
1664
- "aria-label": label,
1665
- className: cn(
1666
- "inline-flex shrink-0 items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",
1667
- active ? "border-primary/30 bg-primary/10 text-primary hover:bg-primary/15" : "border-transparent bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground",
1668
- className
1669
- ),
1670
- children: [
1671
- Icon2 && /* @__PURE__ */ jsx(Icon2, { className: "h-3 w-3 shrink-0 opacity-70" }),
1672
- /* @__PURE__ */ jsx("span", { className: "max-w-[12rem] truncate", children: current?.label ?? allLabel }),
1673
- /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 shrink-0 opacity-60" })
1674
- ]
1675
- }
1676
- ) }),
1677
- /* @__PURE__ */ jsxs(DropdownContent, { align: "start", children: [
1678
- /* @__PURE__ */ jsxs(DropdownItem, { onClick: () => onChange(void 0), children: [
1679
- allLabel,
1680
- !active && /* @__PURE__ */ jsx(Check, { className: "ml-auto h-3.5 w-3.5 shrink-0 pl-1" })
1681
- ] }),
1682
- options.map((o) => /* @__PURE__ */ jsxs(DropdownItem, { onClick: () => onChange(o.value), children: [
1683
- o.label,
1684
- value === o.value && /* @__PURE__ */ jsx(Check, { className: "ml-auto h-3.5 w-3.5 shrink-0 pl-1" })
1685
- ] }, o.value))
1686
- ] })
1687
- ] });
1726
+ var SIZE = {
1727
+ sm: { container: "h-[26px]", segment: "px-2.5 text-xs" },
1728
+ md: { container: "h-[30px]", segment: "px-3 text-sm" }
1729
+ };
1730
+ function SegmentedControl({
1731
+ options,
1732
+ value,
1733
+ onChange,
1734
+ size = "sm",
1735
+ className,
1736
+ ...rest
1737
+ }) {
1738
+ const items = options.map((o) => typeof o === "string" ? { value: o, label: o } : o);
1739
+ return /* @__PURE__ */ jsx(
1740
+ "div",
1741
+ {
1742
+ role: "tablist",
1743
+ "aria-label": rest["aria-label"],
1744
+ className: cn(
1745
+ "inline-flex items-center rounded-button border border-border bg-card p-0.5 shadow-button",
1746
+ SIZE[size].container,
1747
+ className
1748
+ ),
1749
+ children: items.map((item) => {
1750
+ const active = item.value === value;
1751
+ return /* @__PURE__ */ jsx(
1752
+ "button",
1753
+ {
1754
+ type: "button",
1755
+ role: "tab",
1756
+ "aria-selected": active,
1757
+ onClick: () => onChange(item.value),
1758
+ className: cn(
1759
+ "flex h-full items-center rounded-button font-semibold transition-colors",
1760
+ SIZE[size].segment,
1761
+ active ? "bg-foreground text-background" : "text-muted-foreground hover:bg-muted/60"
1762
+ ),
1763
+ children: item.label
1764
+ },
1765
+ item.value
1766
+ );
1767
+ })
1768
+ }
1769
+ );
1688
1770
  }
1689
1771
  var INLINE_TOKEN = /(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g;
1690
1772
  function renderInline(text, keyPrefix) {
@@ -2047,6 +2129,6 @@ function SearchCombobox({
2047
2129
  ] });
2048
2130
  }
2049
2131
 
2050
- export { Badge, Breadcrumb, BulkActionBar, ChevronPager, ConfirmDialog, CurrencyInput, DatePicker, FilterChip, Hint, Input, ListView, Markdown, MarkdownEditor, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, PhoneField, PhoneLink, Popover, PopoverContent, PopoverTrigger, RefreshButton, SearchCombobox, SearchField, SearchSelect, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, StatTiles, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, formatPhone2 as formatPhone, normalizePhone, renderMarkdown };
2051
- //# sourceMappingURL=chunk-7BHG3XGJ.js.map
2052
- //# sourceMappingURL=chunk-7BHG3XGJ.js.map
2132
+ export { Badge, Breadcrumb, BulkActionBar, ChevronPager, ConfirmDialog, CurrencyInput, DatePicker, FilterChip, Hint, Input, ListView, Markdown, MarkdownEditor, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, PhoneField, PhoneLink, Popover, PopoverContent, PopoverTrigger, RefreshButton, SearchCombobox, SearchField, SearchSelect, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, StatTiles, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, formatPhone2 as formatPhone, normalizePhone, renderMarkdown };
2133
+ //# sourceMappingURL=chunk-77CUIMOI.js.map
2134
+ //# sourceMappingURL=chunk-77CUIMOI.js.map