@mediaradar/design-components 0.19.0 → 0.21.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
@@ -37,11 +37,13 @@ __export(index_exports, {
37
37
  DateRangeFilter: () => DateRangeFilter,
38
38
  DateRangePicker: () => DateRangePicker,
39
39
  Delta: () => Delta,
40
+ EmptyState: () => EmptyState,
40
41
  FilterChipBar: () => FilterChipBar,
41
42
  FilterDropdownFooter: () => FilterDropdownFooter,
42
43
  Freshness: () => Freshness,
43
44
  InfoTip: () => InfoTip,
44
45
  LineChartPlaceholder: () => LineChartPlaceholder,
46
+ Modal: () => Modal,
45
47
  MultiSelectFilter: () => MultiSelectFilter,
46
48
  NO_RESULTS_BODY: () => NO_RESULTS_BODY,
47
49
  NO_RESULTS_TITLE: () => NO_RESULTS_TITLE,
@@ -56,6 +58,7 @@ __export(index_exports, {
56
58
  SearchBar: () => SearchBar,
57
59
  SectionHeading: () => SectionHeading,
58
60
  SectionRail: () => SectionRail,
61
+ SegmentedControl: () => SegmentedControl,
59
62
  SelectAllVisible: () => SelectAllVisible,
60
63
  SelectFilter: () => SelectFilter,
61
64
  SelectedSection: () => SelectedSection,
@@ -63,7 +66,10 @@ __export(index_exports, {
63
66
  SortButton: () => SortButton,
64
67
  StackedColumnPlaceholder: () => StackedColumnPlaceholder,
65
68
  TablePagination: () => TablePagination,
69
+ Tabs: () => Tabs,
66
70
  Tag: () => Tag,
71
+ TextField: () => TextField,
72
+ Toast: () => Toast,
67
73
  Toggle: () => Toggle,
68
74
  Tooltip: () => Tooltip,
69
75
  WorkspaceAvatar: () => WorkspaceAvatar,
@@ -311,7 +317,7 @@ function AdvertiserQuickFilter({
311
317
  "aria-label": caption,
312
318
  "data-testid": testIdPrefix && `${testIdPrefix}-popover`,
313
319
  children: [
314
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "border-b border-border-default p-2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex h-9 items-center gap-2 rounded-control border border-border-strong bg-input px-2.5 focus-within:border-border-focus focus-within:ring-2 focus-within:ring-border-focus/30", children: [
320
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "border-b border-border-default p-2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex h-8 items-center gap-2 rounded-control border border-border-strong bg-input px-2.5 focus-within:outline-2 focus-within:outline-offset-1 focus-within:outline-border-focus", children: [
315
321
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.Search, { size: 14, className: "shrink-0 text-text-secondary", "aria-hidden": "true" }),
316
322
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
317
323
  "input",
@@ -990,6 +996,7 @@ function NavBtn({ children, onClick, ...rest }) {
990
996
  var import_react4 = require("react");
991
997
  var import_lucide_react7 = require("lucide-react");
992
998
  var import_jsx_runtime8 = require("react/jsx-runtime");
999
+ var HEIGHT = { sm: "h-8", md: "h-10", lg: "h-11" };
993
1000
  var DEFAULT_SEARCH_MATCH = { mode: "anyWord", wordJoin: "Or" };
994
1001
  var MODE_LABEL = {
995
1002
  anyWord: "Any Word",
@@ -1005,6 +1012,7 @@ function SearchBar({
1005
1012
  value,
1006
1013
  onChange,
1007
1014
  variant = "default",
1015
+ size = "lg",
1008
1016
  matchValue,
1009
1017
  onMatchChange,
1010
1018
  className,
@@ -1012,6 +1020,7 @@ function SearchBar({
1012
1020
  }) {
1013
1021
  const [open, setOpen] = (0, import_react4.useState)(false);
1014
1022
  const ref = (0, import_react4.useRef)(null);
1023
+ const input = (0, import_react4.useRef)(null);
1015
1024
  (0, import_react4.useEffect)(() => {
1016
1025
  if (!open) return;
1017
1026
  const onKey = (e) => e.key === "Escape" && setOpen(false);
@@ -1030,7 +1039,8 @@ function SearchBar({
1030
1039
  "div",
1031
1040
  {
1032
1041
  className: cx2(
1033
- "flex h-11 min-w-[200px] flex-1 items-stretch rounded-control border border-border-strong bg-input",
1042
+ "flex min-w-[200px] flex-1 items-stretch rounded-control border border-border-strong bg-input focus-within:outline-2 focus-within:outline-offset-1 focus-within:outline-border-focus",
1043
+ HEIGHT[size],
1034
1044
  className
1035
1045
  ),
1036
1046
  children: [
@@ -1039,16 +1049,31 @@ function SearchBar({
1039
1049
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1040
1050
  "input",
1041
1051
  {
1052
+ ref: input,
1042
1053
  type: "text",
1043
1054
  value,
1044
1055
  onChange: (e) => onChange?.(e.target.value),
1045
1056
  placeholder,
1046
1057
  "aria-label": placeholder,
1047
1058
  "data-testid": testIdPrefix && `${testIdPrefix}-search`,
1048
- className: "min-w-0 flex-1 bg-transparent text-[13px] text-text-primary outline-hidden placeholder:text-text-tertiary"
1059
+ className: "min-w-0 flex-1 bg-transparent text-dense text-text-primary outline-hidden placeholder:text-text-tertiary"
1049
1060
  }
1050
1061
  )
1051
1062
  ] }),
1063
+ value && onChange && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1064
+ "button",
1065
+ {
1066
+ type: "button",
1067
+ onClick: () => {
1068
+ onChange("");
1069
+ input.current?.focus();
1070
+ },
1071
+ "aria-label": "Clear search",
1072
+ "data-testid": testIdPrefix && `${testIdPrefix}-clear`,
1073
+ className: "mr-1.5 flex size-6 shrink-0 items-center justify-center self-center rounded-control text-text-tertiary hover:bg-subtle hover:text-text-primary focus-visible:outline-2 focus-visible:outline-border-focus",
1074
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react7.X, { size: 14, "aria-hidden": "true" })
1075
+ }
1076
+ ),
1052
1077
  showMatch && // border-border-default, not the bare `border-border` both source
1053
1078
  // implementations used -- confirmed by actually compiling against
1054
1079
  // @mediaradar/design-tokens' real published theme.css (not assumed):
@@ -2400,7 +2425,7 @@ function SelectionPicker({
2400
2425
  }) }),
2401
2426
  source === "search" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-w-0 flex-col gap-3", children: [
2402
2427
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
2403
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-9 min-w-[200px] flex-1 items-center gap-2 rounded-control border border-border-strong bg-input px-3", children: [
2428
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-8 min-w-[200px] flex-1 items-center gap-2 rounded-control border border-border-strong bg-input px-3 focus-within:outline-2 focus-within:outline-offset-1 focus-within:outline-border-focus", children: [
2404
2429
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react15.Search, { size: 15, className: "text-text-secondary", "aria-hidden": "true" }),
2405
2430
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2406
2431
  "input",
@@ -2714,7 +2739,7 @@ function FilterDropdown({
2714
2739
  onClick: () => setOpen((v) => !v),
2715
2740
  "aria-expanded": open,
2716
2741
  "data-testid": testIdPrefix && `${testIdPrefix}-filter-${filterSlug}`,
2717
- className: "inline-flex h-9 items-center gap-1.5 whitespace-nowrap rounded-control border border-border-strong bg-input px-3 text-[13px] font-medium text-text-secondary transition-colors hover:bg-subtle",
2742
+ className: "inline-flex h-8 items-center gap-1.5 whitespace-nowrap rounded-control border border-border-strong bg-input px-3 text-[13px] font-medium text-text-secondary transition-colors hover:bg-subtle",
2718
2743
  children: [
2719
2744
  label,
2720
2745
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react15.ChevronDown, { size: 13, "aria-hidden": "true", className: cx8("transition-transform", open && "rotate-180") })
@@ -2920,7 +2945,10 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
2920
2945
  size: {
2921
2946
  xs: "h-6 px-2 text-xs",
2922
2947
  sm: "h-8 px-3 text-sm",
2923
- md: "h-10 px-4 text-sm"
2948
+ md: "h-10 px-4 text-sm",
2949
+ // 44, the filter row's height, so a button at the end of a row of
2950
+ // filter dropdowns lines up with them. One control scale: 32 / 40 / 44.
2951
+ lg: "h-11 px-5 text-sm"
2924
2952
  },
2925
2953
  // Shape is orthogonal to size. As a fourth SIZE, `icon` could only ever
2926
2954
  // be one dimension, so an icon button never lined up with the labelled
@@ -2935,6 +2963,7 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
2935
2963
  { size: "xs", iconOnly: true, class: "w-6" },
2936
2964
  { size: "sm", iconOnly: true, class: "w-8" },
2937
2965
  { size: "md", iconOnly: true, class: "w-10" },
2966
+ { size: "lg", iconOnly: true, class: "w-11" },
2938
2967
  // A boxed button is a target you aim at, so its label carries the weight
2939
2968
  // of one. `link` sits inline in a sentence, where semibold reads as
2940
2969
  // emphasis on the words rather than as a control.
@@ -3048,7 +3077,7 @@ function NameListModal({
3048
3077
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3049
3078
  "div",
3050
3079
  {
3051
- className: "fixed inset-0 z-70 flex items-center justify-center bg-scrim px-4",
3080
+ className: "fixed inset-0 z-modal flex items-center justify-center bg-scrim px-4",
3052
3081
  onMouseDown: (e) => e.target === e.currentTarget && onCancel(),
3053
3082
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3054
3083
  "div",
@@ -3058,7 +3087,7 @@ function NameListModal({
3058
3087
  "aria-modal": "true",
3059
3088
  "aria-labelledby": titleId,
3060
3089
  onKeyDown: trapTab,
3061
- className: "w-full max-w-[420px] rounded-card border border-border-default bg-surface p-5 shadow-overlay",
3090
+ className: "w-full max-w-110 rounded-card border border-border-default bg-surface p-5 shadow-overlay",
3062
3091
  children: [
3063
3092
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { id: titleId, className: "text-[16px] font-semibold text-text-primary", children: title }),
3064
3093
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "mt-4 flex flex-col gap-1.5", children: [
@@ -3071,7 +3100,7 @@ function NameListModal({
3071
3100
  value: name,
3072
3101
  onChange: (e) => setName(e.target.value),
3073
3102
  placeholder,
3074
- className: "h-10 rounded-control border border-border-strong bg-input px-3 text-sm outline-hidden focus:border-brand-primaryAction"
3103
+ className: "h-10 rounded-control border border-border-strong bg-input px-3 text-dense focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus"
3075
3104
  }
3076
3105
  )
3077
3106
  ] }),
@@ -3348,10 +3377,83 @@ function WorkspaceAvatar({ name, size = "md" }) {
3348
3377
  );
3349
3378
  }
3350
3379
 
3351
- // src/Tag.tsx
3380
+ // src/Toast.tsx
3381
+ var import_react15 = require("react");
3382
+ var import_react_dom6 = require("react-dom");
3383
+ var import_lucide_react20 = require("lucide-react");
3352
3384
  var import_jsx_runtime34 = require("react/jsx-runtime");
3385
+ var ICON = {
3386
+ neutral: null,
3387
+ success: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react20.Check, { size: 15, className: "shrink-0", "aria-hidden": "true" }),
3388
+ warning: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react20.AlertTriangle, { size: 15, className: "shrink-0", "aria-hidden": "true" })
3389
+ };
3390
+ function Toast({ message, action, onClose, tone = "neutral", duration, className }) {
3391
+ const ms = duration ?? (action ? 1e4 : 5e3);
3392
+ const [paused, setPaused] = (0, import_react15.useState)(false);
3393
+ const closed = (0, import_react15.useRef)(false);
3394
+ (0, import_react15.useEffect)(() => {
3395
+ if (paused) return;
3396
+ const t = window.setTimeout(() => {
3397
+ if (closed.current) return;
3398
+ closed.current = true;
3399
+ onClose();
3400
+ }, ms);
3401
+ return () => window.clearTimeout(t);
3402
+ }, [message, ms, paused]);
3403
+ return (0, import_react_dom6.createPortal)(
3404
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
3405
+ "div",
3406
+ {
3407
+ role: "status",
3408
+ "aria-live": "polite",
3409
+ onMouseEnter: () => setPaused(true),
3410
+ onMouseLeave: () => setPaused(false),
3411
+ onFocusCapture: () => setPaused(true),
3412
+ onBlurCapture: () => setPaused(false),
3413
+ className: cn(
3414
+ "fixed bottom-6 left-1/2 z-toast flex max-w-[92vw] -translate-x-1/2 items-center gap-2.5",
3415
+ "rounded-control bg-inverseSurface py-2.5 pl-4 pr-2.5 text-sm font-medium text-text-inverse shadow-overlay",
3416
+ className
3417
+ ),
3418
+ children: [
3419
+ ICON[tone] && // The inverse pair, not text-success / text-warning: those are tuned
3420
+ // for the page, and on the toast's flipped surface amber drops to 2:1.
3421
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3422
+ "span",
3423
+ {
3424
+ className: cn(
3425
+ "flex",
3426
+ tone === "success" ? "text-text-inverseSuccess" : "text-text-inverseWarning"
3427
+ ),
3428
+ children: ICON[tone]
3429
+ }
3430
+ ),
3431
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "min-w-0", children: message }),
3432
+ action && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3433
+ "button",
3434
+ {
3435
+ type: "button",
3436
+ onClick: () => {
3437
+ if (!closed.current) {
3438
+ closed.current = true;
3439
+ action.onClick();
3440
+ }
3441
+ },
3442
+ className: "shrink-0 rounded-control px-2.5 py-1 text-sm font-semibold text-text-inverse underline-offset-2 transition-colors duration-(--mr-motion-duration-interactive) ease-interactive hover:bg-text-inverse/15 hover:underline focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-border-focus",
3443
+ children: action.label
3444
+ }
3445
+ )
3446
+ ]
3447
+ }
3448
+ ),
3449
+ document.body
3450
+ );
3451
+ }
3452
+
3453
+ // src/Tag.tsx
3454
+ var import_jsx_runtime35 = require("react/jsx-runtime");
3353
3455
  function Tag({ children, className }) {
3354
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3456
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3355
3457
  "span",
3356
3458
  {
3357
3459
  className: cn(
@@ -3370,8 +3472,8 @@ function Tag({ children, className }) {
3370
3472
  }
3371
3473
 
3372
3474
  // src/TablePagination.tsx
3373
- var import_lucide_react20 = require("lucide-react");
3374
- var import_jsx_runtime35 = require("react/jsx-runtime");
3475
+ var import_lucide_react21 = require("lucide-react");
3476
+ var import_jsx_runtime36 = require("react/jsx-runtime");
3375
3477
  function TablePagination({
3376
3478
  page,
3377
3479
  perPage,
@@ -3392,10 +3494,10 @@ function TablePagination({
3392
3494
  btn,
3393
3495
  "text-text-secondary hover:bg-subtle hover:text-text-primary disabled:pointer-events-none disabled:opacity-30"
3394
3496
  );
3395
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: cn("flex flex-wrap items-center justify-between gap-x-4 gap-y-2", className), "data-testid": testIdPrefix, children: [
3396
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-text-secondary", children: [
3397
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "relative", children: [
3398
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3497
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn("flex flex-wrap items-center justify-between gap-x-4 gap-y-2", className), "data-testid": testIdPrefix, children: [
3498
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-text-secondary", children: [
3499
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "relative", children: [
3500
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3399
3501
  "select",
3400
3502
  {
3401
3503
  value: perPage,
@@ -3403,11 +3505,11 @@ function TablePagination({
3403
3505
  "aria-label": "Items per page",
3404
3506
  "data-testid": testIdPrefix && `${testIdPrefix}-per-page`,
3405
3507
  className: "appearance-none rounded-control border border-border-strong bg-input py-1 pl-2.5 pr-7 text-[13px] font-medium text-text-primary focus:outline focus:outline-2 focus:outline-border-focus",
3406
- children: perPageOptions.map((n) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("option", { value: n, children: n }, n))
3508
+ children: perPageOptions.map((n) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: n, children: n }, n))
3407
3509
  }
3408
3510
  ),
3409
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3410
- import_lucide_react20.ChevronDown,
3511
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3512
+ import_lucide_react21.ChevronDown,
3411
3513
  {
3412
3514
  size: 13,
3413
3515
  "aria-hidden": "true",
@@ -3417,8 +3519,8 @@ function TablePagination({
3417
3519
  ] }),
3418
3520
  "items per page"
3419
3521
  ] }),
3420
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("nav", { className: "flex items-center gap-1", "aria-label": "Pagination", children: [
3421
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3522
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("nav", { className: "flex items-center gap-1", "aria-label": "Pagination", children: [
3523
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3422
3524
  "button",
3423
3525
  {
3424
3526
  type: "button",
@@ -3427,10 +3529,10 @@ function TablePagination({
3427
3529
  "aria-label": "First page",
3428
3530
  "data-testid": testIdPrefix && `${testIdPrefix}-first`,
3429
3531
  className: stepBtn,
3430
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronFirst, { size: 16, "aria-hidden": "true" })
3532
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react21.ChevronFirst, { size: 16, "aria-hidden": "true" })
3431
3533
  }
3432
3534
  ),
3433
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3535
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3434
3536
  "button",
3435
3537
  {
3436
3538
  type: "button",
@@ -3439,11 +3541,11 @@ function TablePagination({
3439
3541
  "aria-label": "Previous page",
3440
3542
  "data-testid": testIdPrefix && `${testIdPrefix}-prev`,
3441
3543
  className: stepBtn,
3442
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronLeft, { size: 16, "aria-hidden": "true" })
3544
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react21.ChevronLeft, { size: 16, "aria-hidden": "true" })
3443
3545
  }
3444
3546
  ),
3445
3547
  pageWindow(current, totalPages).map(
3446
- (p) => typeof p === "string" ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "px-1 text-[13px] text-text-tertiary", children: "\u2026" }, p) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3548
+ (p) => typeof p === "string" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "px-1 text-[13px] text-text-tertiary", children: "\u2026" }, p) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3447
3549
  "button",
3448
3550
  {
3449
3551
  type: "button",
@@ -3459,7 +3561,7 @@ function TablePagination({
3459
3561
  p
3460
3562
  )
3461
3563
  ),
3462
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3564
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3463
3565
  "button",
3464
3566
  {
3465
3567
  type: "button",
@@ -3468,10 +3570,10 @@ function TablePagination({
3468
3570
  "aria-label": "Next page",
3469
3571
  "data-testid": testIdPrefix && `${testIdPrefix}-next`,
3470
3572
  className: stepBtn,
3471
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronRight, { size: 16, "aria-hidden": "true" })
3573
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react21.ChevronRight, { size: 16, "aria-hidden": "true" })
3472
3574
  }
3473
3575
  ),
3474
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3576
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3475
3577
  "button",
3476
3578
  {
3477
3579
  type: "button",
@@ -3480,11 +3582,11 @@ function TablePagination({
3480
3582
  "aria-label": "Last page",
3481
3583
  "data-testid": testIdPrefix && `${testIdPrefix}-last`,
3482
3584
  className: stepBtn,
3483
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react20.ChevronLast, { size: 16, "aria-hidden": "true" })
3585
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react21.ChevronLast, { size: 16, "aria-hidden": "true" })
3484
3586
  }
3485
3587
  )
3486
3588
  ] }),
3487
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-[13px] text-text-tertiary tabular-nums", children: [
3589
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "text-[13px] text-text-tertiary tabular-nums", children: [
3488
3590
  rangeStart.toLocaleString(),
3489
3591
  " \u2013 ",
3490
3592
  rangeEnd.toLocaleString(),
@@ -3497,9 +3599,9 @@ function TablePagination({
3497
3599
  }
3498
3600
 
3499
3601
  // src/DateRangePicker.tsx
3500
- var import_react15 = require("react");
3501
- var import_lucide_react21 = require("lucide-react");
3502
- var import_jsx_runtime36 = require("react/jsx-runtime");
3602
+ var import_react16 = require("react");
3603
+ var import_lucide_react22 = require("lucide-react");
3604
+ var import_jsx_runtime37 = require("react/jsx-runtime");
3503
3605
  var MONTH_ABBR = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
3504
3606
  var QUARTER_ABBR = ["Q1", "Q2", "Q3", "Q4"];
3505
3607
  var PRESETS = ["Rolling 3 months", "Rolling 6 months", "Rolling 12 months"];
@@ -3535,7 +3637,7 @@ function spanLabel(label, today) {
3535
3637
  return `${fmtDate(s)} \u2013 ${fmtDate(e)}`;
3536
3638
  }
3537
3639
  function MiniSelect({ value, onChange, options }) {
3538
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3640
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3539
3641
  "select",
3540
3642
  {
3541
3643
  value: String(value),
@@ -3543,8 +3645,8 @@ function MiniSelect({ value, onChange, options }) {
3543
3645
  const opt = options.find((o) => String(o.value) === e.target.value);
3544
3646
  if (opt) onChange(opt.value);
3545
3647
  },
3546
- className: "rounded-control border border-border-strong bg-input px-1.5 py-1 text-[12px] text-text-primary outline-hidden focus:border-border-focus",
3547
- children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: String(o.value), children: o.label }, String(o.value)))
3648
+ className: "rounded-control border border-border-strong bg-input px-1.5 py-1 text-[12px] text-text-primary focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus",
3649
+ children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: String(o.value), children: o.label }, String(o.value)))
3548
3650
  }
3549
3651
  );
3550
3652
  }
@@ -3559,19 +3661,19 @@ function DateRangePicker({
3559
3661
  today,
3560
3662
  years
3561
3663
  }) {
3562
- const end = (0, import_react15.useMemo)(() => today ?? startOfToday(), [today]);
3664
+ const end = (0, import_react16.useMemo)(() => today ?? startOfToday(), [today]);
3563
3665
  const yearOptions = years ?? [3, 2, 1, 0].map((n) => end.getFullYear() - n);
3564
- const [open, setOpen] = (0, import_react15.useState)(false);
3565
- const [value, setValue] = (0, import_react15.useState)(defaultValue);
3566
- const [draft, setDraft] = (0, import_react15.useState)(defaultValue);
3567
- const ref = (0, import_react15.useRef)(null);
3568
- const [fromMo, setFromMo] = (0, import_react15.useState)(end.getMonth());
3569
- const [fromYr, setFromYr] = (0, import_react15.useState)(end.getFullYear() - 1);
3570
- const [toMo, setToMo] = (0, import_react15.useState)(end.getMonth());
3571
- const [toYr, setToYr] = (0, import_react15.useState)(end.getFullYear());
3572
- const [fromQ, setFromQ] = (0, import_react15.useState)(Math.floor(end.getMonth() / 3));
3573
- const [toQ, setToQ] = (0, import_react15.useState)(Math.floor(end.getMonth() / 3));
3574
- (0, import_react15.useEffect)(() => {
3666
+ const [open, setOpen] = (0, import_react16.useState)(false);
3667
+ const [value, setValue] = (0, import_react16.useState)(defaultValue);
3668
+ const [draft, setDraft] = (0, import_react16.useState)(defaultValue);
3669
+ const ref = (0, import_react16.useRef)(null);
3670
+ const [fromMo, setFromMo] = (0, import_react16.useState)(end.getMonth());
3671
+ const [fromYr, setFromYr] = (0, import_react16.useState)(end.getFullYear() - 1);
3672
+ const [toMo, setToMo] = (0, import_react16.useState)(end.getMonth());
3673
+ const [toYr, setToYr] = (0, import_react16.useState)(end.getFullYear());
3674
+ const [fromQ, setFromQ] = (0, import_react16.useState)(Math.floor(end.getMonth() / 3));
3675
+ const [toQ, setToQ] = (0, import_react16.useState)(Math.floor(end.getMonth() / 3));
3676
+ (0, import_react16.useEffect)(() => {
3575
3677
  const [s, e] = resolveRange(value, end);
3576
3678
  onRangeChange?.(s, e);
3577
3679
  }, [value]);
@@ -3579,7 +3681,7 @@ function DateRangePicker({
3579
3681
  if (!open) setDraft(value);
3580
3682
  setOpen((o) => !o);
3581
3683
  };
3582
- (0, import_react15.useEffect)(() => {
3684
+ (0, import_react16.useEffect)(() => {
3583
3685
  if (!open) return;
3584
3686
  const onDown = (e) => {
3585
3687
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -3605,8 +3707,8 @@ function DateRangePicker({
3605
3707
  if (showFooter) setDraft(label);
3606
3708
  else commit(label);
3607
3709
  };
3608
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "relative", ref, children: [
3609
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
3710
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "relative", ref, children: [
3711
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3610
3712
  "button",
3611
3713
  {
3612
3714
  type: "button",
@@ -3615,16 +3717,16 @@ function DateRangePicker({
3615
3717
  "aria-haspopup": "listbox",
3616
3718
  className: chipTriggerClass(),
3617
3719
  children: [
3618
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "flex flex-col gap-1 text-left leading-none", children: [
3619
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-control-caption text-text-tertiary", children: spanLabel(value, end) }),
3620
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-[12px] font-medium text-text-primary", children: value })
3720
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex flex-col gap-1 text-left leading-none", children: [
3721
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-control-caption text-text-tertiary", children: spanLabel(value, end) }),
3722
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-[12px] font-medium text-text-primary", children: value })
3621
3723
  ] }),
3622
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react21.ChevronDown, { size: 14, "aria-hidden": "true", className: cn("shrink-0 text-text-secondary transition-transform", open && "rotate-180") })
3724
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react22.ChevronDown, { size: 14, "aria-hidden": "true", className: cn("shrink-0 text-text-secondary transition-transform", open && "rotate-180") })
3623
3725
  ]
3624
3726
  }
3625
3727
  ),
3626
- open && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn("absolute top-[calc(100%+8px)] z-30 w-[280px] overflow-hidden rounded-card border border-border-default bg-surface py-1 shadow-overlay", align === "right" ? "right-0" : "left-0"), children: [
3627
- presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3728
+ open && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn("absolute top-[calc(100%+8px)] z-30 w-[280px] overflow-hidden rounded-card border border-border-default bg-surface py-1 shadow-overlay", align === "right" ? "right-0" : "left-0"), children: [
3729
+ presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3628
3730
  "button",
3629
3731
  {
3630
3732
  type: "button",
@@ -3634,26 +3736,26 @@ function DateRangePicker({
3634
3736
  },
3635
3737
  p
3636
3738
  )),
3637
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-1 border-t border-border-default px-3 pb-2 pt-2", children: [
3638
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "text-[13px] font-semibold text-text-primary", children: "Custom Range" }),
3639
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-2 flex flex-col gap-2", children: [
3640
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3739
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-1 border-t border-border-default px-3 pb-2 pt-2", children: [
3740
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "text-[13px] font-semibold text-text-primary", children: "Custom Range" }),
3741
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-2 flex flex-col gap-2", children: [
3742
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3641
3743
  "From",
3642
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "flex gap-1", children: [
3643
- granularity === "month" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MiniSelect, { value: fromMo, onChange: setFromMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3644
- granularity === "quarter" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MiniSelect, { value: fromQ, onChange: setFromQ, options: QUARTER_ABBR.map((qq, i) => ({ label: qq, value: i })) }),
3645
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MiniSelect, { value: fromYr, onChange: setFromYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3744
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex gap-1", children: [
3745
+ granularity === "month" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MiniSelect, { value: fromMo, onChange: setFromMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3746
+ granularity === "quarter" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MiniSelect, { value: fromQ, onChange: setFromQ, options: QUARTER_ABBR.map((qq, i) => ({ label: qq, value: i })) }),
3747
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MiniSelect, { value: fromYr, onChange: setFromYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3646
3748
  ] })
3647
3749
  ] }),
3648
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3750
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3649
3751
  "To",
3650
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "flex gap-1", children: [
3651
- granularity === "month" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MiniSelect, { value: toMo, onChange: setToMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3652
- granularity === "quarter" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MiniSelect, { value: toQ, onChange: setToQ, options: QUARTER_ABBR.map((qq, i) => ({ label: qq, value: i })) }),
3653
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MiniSelect, { value: toYr, onChange: setToYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3752
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex gap-1", children: [
3753
+ granularity === "month" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MiniSelect, { value: toMo, onChange: setToMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3754
+ granularity === "quarter" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MiniSelect, { value: toQ, onChange: setToQ, options: QUARTER_ABBR.map((qq, i) => ({ label: qq, value: i })) }),
3755
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MiniSelect, { value: toYr, onChange: setToYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3654
3756
  ] })
3655
3757
  ] }),
3656
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3758
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3657
3759
  "button",
3658
3760
  {
3659
3761
  type: "button",
@@ -3665,15 +3767,15 @@ function DateRangePicker({
3665
3767
  )
3666
3768
  ] })
3667
3769
  ] }),
3668
- showFooter && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(FilterDropdownFooter, { onApply: () => commit(draft) })
3770
+ showFooter && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FilterDropdownFooter, { onApply: () => commit(draft) })
3669
3771
  ] })
3670
3772
  ] });
3671
3773
  }
3672
3774
 
3673
3775
  // src/MultiSelectFilter.tsx
3674
- var import_react16 = require("react");
3675
- var import_lucide_react22 = require("lucide-react");
3676
- var import_jsx_runtime37 = require("react/jsx-runtime");
3776
+ var import_react17 = require("react");
3777
+ var import_lucide_react23 = require("lucide-react");
3778
+ var import_jsx_runtime38 = require("react/jsx-runtime");
3677
3779
  function MultiSelectFilter({
3678
3780
  caption,
3679
3781
  options = [],
@@ -3697,11 +3799,11 @@ function MultiSelectFilter({
3697
3799
  }) {
3698
3800
  const groupLeaves = (g) => g.children.length ? g.children : [{ id: g.id, label: g.label }];
3699
3801
  const leafOptions = groups ? groups.flatMap(groupLeaves) : options;
3700
- const [open, setOpen] = (0, import_react16.useState)(false);
3701
- const [q, setQ] = (0, import_react16.useState)("");
3702
- const [draft, setDraft] = (0, import_react16.useState)(selected);
3703
- const ref = (0, import_react16.useRef)(null);
3704
- const close = (0, import_react16.useCallback)(() => {
3802
+ const [open, setOpen] = (0, import_react17.useState)(false);
3803
+ const [q, setQ] = (0, import_react17.useState)("");
3804
+ const [draft, setDraft] = (0, import_react17.useState)(selected);
3805
+ const ref = (0, import_react17.useRef)(null);
3806
+ const close = (0, import_react17.useCallback)(() => {
3705
3807
  setOpen(false);
3706
3808
  setQ("");
3707
3809
  if (showFooter) return;
@@ -3718,7 +3820,7 @@ function MultiSelectFilter({
3718
3820
  setOpen(false);
3719
3821
  setQ("");
3720
3822
  };
3721
- (0, import_react16.useEffect)(() => {
3823
+ (0, import_react17.useEffect)(() => {
3722
3824
  if (!open) return;
3723
3825
  const onKey = (e) => e.key === "Escape" && close();
3724
3826
  const onClick = (e) => {
@@ -3764,8 +3866,8 @@ function MultiSelectFilter({
3764
3866
  const kids = live.filter((c) => c.label.toLowerCase().includes(ql));
3765
3867
  return kids.length ? { ...g, children: kids } : null;
3766
3868
  }).filter((g) => g !== null) : [];
3767
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn("relative", fullWidth && "w-full"), ref, children: [
3768
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3869
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: cn("relative", fullWidth && "w-full"), ref, children: [
3870
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3769
3871
  "button",
3770
3872
  {
3771
3873
  type: "button",
@@ -3773,9 +3875,9 @@ function MultiSelectFilter({
3773
3875
  "aria-expanded": open,
3774
3876
  className: cn(chipTriggerClass(variant), fullWidth && "w-full justify-between"),
3775
3877
  children: [
3776
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ChipContent, { caption, value, icon }),
3777
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3778
- import_lucide_react22.ChevronDown,
3878
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ChipContent, { caption, value, icon }),
3879
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3880
+ import_lucide_react23.ChevronDown,
3779
3881
  {
3780
3882
  size: 14,
3781
3883
  "aria-hidden": "true",
@@ -3785,7 +3887,7 @@ function MultiSelectFilter({
3785
3887
  ]
3786
3888
  }
3787
3889
  ),
3788
- open && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3890
+ open && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3789
3891
  "div",
3790
3892
  {
3791
3893
  className: cn(
@@ -3796,9 +3898,9 @@ function MultiSelectFilter({
3796
3898
  role: "dialog",
3797
3899
  "aria-label": caption,
3798
3900
  children: [
3799
- searchable && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "border-b border-border-default p-2", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex h-9 items-center gap-2 rounded-control border border-border-strong bg-input px-2.5", children: [
3800
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react22.Search, { size: 14, className: "text-text-secondary", "aria-hidden": "true" }),
3801
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3901
+ searchable && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "border-b border-border-default p-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex h-8 items-center gap-2 rounded-control border border-border-strong bg-input px-2.5 focus-within:outline-2 focus-within:outline-offset-1 focus-within:outline-border-focus", children: [
3902
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react23.Search, { size: 14, className: "text-text-secondary", "aria-hidden": "true" }),
3903
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3802
3904
  "input",
3803
3905
  {
3804
3906
  type: "text",
@@ -3808,37 +3910,37 @@ function MultiSelectFilter({
3808
3910
  className: "h-full flex-1 bg-transparent text-[13px] outline-hidden placeholder:text-text-tertiary"
3809
3911
  }
3810
3912
  ),
3811
- q && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("button", { type: "button", onClick: () => setQ(""), "aria-label": "Clear search", className: "text-text-tertiary hover:text-text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react22.X, { size: 13 }) })
3913
+ q && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", onClick: () => setQ(""), "aria-label": "Clear search", className: "text-text-tertiary hover:text-text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react23.X, { size: 13 }) })
3812
3914
  ] }) }),
3813
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "max-h-[280px] overflow-y-auto p-1", children: [
3915
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "max-h-[280px] overflow-y-auto p-1", children: [
3814
3916
  groups ? visibleGroups.map((g) => {
3815
3917
  const state = groupState(g);
3816
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
3817
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3918
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { children: [
3919
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3818
3920
  "button",
3819
3921
  {
3820
3922
  type: "button",
3821
3923
  onClick: () => toggleGroup(g),
3822
3924
  className: "flex w-full items-center gap-2.5 rounded-control px-2 py-2 text-left transition-colors hover:bg-subtle",
3823
3925
  children: [
3824
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(TriCheck, { state }),
3825
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: cn("flex-1 text-[14px] text-text-primary", !plainParent && "font-semibold"), children: g.label }),
3826
- counts && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(OptionCount, { n: countFor(g.id) })
3926
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(TriCheck, { state }),
3927
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: cn("flex-1 text-[14px] text-text-primary", !plainParent && "font-semibold"), children: g.label }),
3928
+ counts && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(OptionCount, { n: countFor(g.id) })
3827
3929
  ]
3828
3930
  }
3829
3931
  ),
3830
3932
  g.children.map((c) => {
3831
3933
  const checked = draft.includes(c.id);
3832
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3934
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3833
3935
  "button",
3834
3936
  {
3835
3937
  type: "button",
3836
3938
  onClick: () => toggle(c.id),
3837
3939
  className: "flex w-full items-center gap-2.5 rounded-control py-2 pl-9 pr-2 text-left transition-colors hover:bg-subtle",
3838
3940
  children: [
3839
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(TriCheck, { state: checked ? "all" : "none" }),
3840
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "flex-1 text-[14px] text-text-primary", children: c.label }),
3841
- counts && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(OptionCount, { n: countFor(c.id) })
3941
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(TriCheck, { state: checked ? "all" : "none" }),
3942
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "flex-1 text-[14px] text-text-primary", children: c.label }),
3943
+ counts && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(OptionCount, { n: countFor(c.id) })
3842
3944
  ]
3843
3945
  },
3844
3946
  c.id
@@ -3847,33 +3949,33 @@ function MultiSelectFilter({
3847
3949
  ] }, g.id);
3848
3950
  }) : items.map((o) => {
3849
3951
  const checked = draft.includes(o.id);
3850
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3952
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3851
3953
  "button",
3852
3954
  {
3853
3955
  type: "button",
3854
3956
  onClick: () => toggle(o.id),
3855
3957
  className: "flex w-full items-center gap-2.5 rounded-control px-2 py-2 text-left transition-colors hover:bg-subtle",
3856
3958
  children: [
3857
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3959
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3858
3960
  "span",
3859
3961
  {
3860
3962
  className: cn(
3861
3963
  "flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-[5px] border transition-colors",
3862
3964
  checked ? "border-transparent bg-brand-primaryAction text-brand-onprimary" : "border-border-interactive bg-input"
3863
3965
  ),
3864
- children: checked && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react22.Check, { size: 13, strokeWidth: 3 })
3966
+ children: checked && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react23.Check, { size: 13, strokeWidth: 3 })
3865
3967
  }
3866
3968
  ),
3867
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "flex-1 text-[14px] text-text-primary", children: o.label }),
3868
- counts && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(OptionCount, { n: countFor(o.id) })
3969
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "flex-1 text-[14px] text-text-primary", children: o.label }),
3970
+ counts && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(OptionCount, { n: countFor(o.id) })
3869
3971
  ]
3870
3972
  },
3871
3973
  o.id
3872
3974
  );
3873
3975
  }),
3874
- (groups && !visibleGroups.length || !groups && !items.length) && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "py-6 text-center text-[13px] text-text-tertiary", children: "No matches." })
3976
+ (groups && !visibleGroups.length || !groups && !items.length) && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "py-6 text-center text-[13px] text-text-tertiary", children: "No matches." })
3875
3977
  ] }),
3876
- showFooter ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FilterDropdownFooter, { onClear: () => setDraft(clearValue), onApply: apply }) : min === 0 && draft.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "border-t border-border-default p-2", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3978
+ showFooter ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FilterDropdownFooter, { onClear: () => setDraft(clearValue), onApply: apply }) : min === 0 && draft.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "border-t border-border-default p-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3877
3979
  "button",
3878
3980
  {
3879
3981
  type: "button",
@@ -3892,7 +3994,7 @@ function MultiSelectFilter({
3892
3994
  }
3893
3995
  function TriCheck({ state }) {
3894
3996
  const filled = state !== "none";
3895
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3997
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3896
3998
  "span",
3897
3999
  {
3898
4000
  className: cn(
@@ -3900,14 +4002,14 @@ function TriCheck({ state }) {
3900
4002
  filled ? "border-transparent bg-brand-primaryAction text-brand-onprimary" : "border-border-interactive bg-input"
3901
4003
  ),
3902
4004
  children: [
3903
- state === "all" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react22.Check, { size: 13, strokeWidth: 3 }),
3904
- state === "some" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react22.Minus, { size: 13, strokeWidth: 3 })
4005
+ state === "all" && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react23.Check, { size: 13, strokeWidth: 3 }),
4006
+ state === "some" && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react23.Minus, { size: 13, strokeWidth: 3 })
3905
4007
  ]
3906
4008
  }
3907
4009
  );
3908
4010
  }
3909
4011
  function OptionCount({ n }) {
3910
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "shrink-0 text-[12px] tabular-nums text-text-tertiary", children: [
4012
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "shrink-0 text-[12px] tabular-nums text-text-tertiary", children: [
3911
4013
  "(",
3912
4014
  n.toLocaleString(),
3913
4015
  ")"
@@ -3915,7 +4017,7 @@ function OptionCount({ n }) {
3915
4017
  }
3916
4018
 
3917
4019
  // src/Toggle.tsx
3918
- var import_jsx_runtime38 = require("react/jsx-runtime");
4020
+ var import_jsx_runtime39 = require("react/jsx-runtime");
3919
4021
  var SIZES2 = {
3920
4022
  sm: { track: "h-5 w-9", knob: "h-4 w-4", on: "translate-x-[18px]" },
3921
4023
  md: { track: "h-6 w-11", knob: "h-5 w-5", on: "translate-x-[22px]" }
@@ -3923,7 +4025,7 @@ var SIZES2 = {
3923
4025
  var OFF_TRACK = "color-mix(in srgb, var(--mr-color-border-interactive) 70%, var(--mr-color-text-secondary))";
3924
4026
  function Toggle({ checked, onChange, label, size = "md", disabled, className, testIdPrefix }) {
3925
4027
  const s = SIZES2[size];
3926
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
4028
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3927
4029
  "button",
3928
4030
  {
3929
4031
  type: "button",
@@ -3941,7 +4043,7 @@ function Toggle({ checked, onChange, label, size = "md", disabled, className, te
3941
4043
  disabled && "cursor-not-allowed opacity-50",
3942
4044
  className
3943
4045
  ),
3944
- children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
4046
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3945
4047
  "span",
3946
4048
  {
3947
4049
  className: cn(
@@ -3956,22 +4058,22 @@ function Toggle({ checked, onChange, label, size = "md", disabled, className, te
3956
4058
  }
3957
4059
 
3958
4060
  // src/AISpark.tsx
3959
- var import_react17 = require("react");
3960
- var import_lucide_react23 = require("lucide-react");
3961
- var import_jsx_runtime39 = require("react/jsx-runtime");
4061
+ var import_react18 = require("react");
4062
+ var import_lucide_react24 = require("lucide-react");
4063
+ var import_jsx_runtime40 = require("react/jsx-runtime");
3962
4064
  function AISpark({ size = 16, className }) {
3963
- const id = (0, import_react17.useId)();
3964
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
3965
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("svg", { width: "0", height: "0", "aria-hidden": "true", style: { position: "absolute" }, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("linearGradient", { id, x1: "0", y1: "0", x2: "1", y2: "1", children: [
3966
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("stop", { offset: "0%", stopColor: "var(--mr-color-brand-primary)" }),
3967
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("stop", { offset: "100%", className: "[stop-color:#9474ff] in-data-[theme=dark]:[stop-color:#a488ff]" })
4065
+ const id = (0, import_react18.useId)();
4066
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
4067
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("svg", { width: "0", height: "0", "aria-hidden": "true", style: { position: "absolute" }, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("linearGradient", { id, x1: "0", y1: "0", x2: "1", y2: "1", children: [
4068
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("stop", { offset: "0%", stopColor: "var(--mr-color-brand-primary)" }),
4069
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("stop", { offset: "100%", className: "[stop-color:#9474ff] in-data-[theme=dark]:[stop-color:#a488ff]" })
3968
4070
  ] }) }) }),
3969
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react23.Sparkles, { size, stroke: `url(#${id})`, className, "aria-hidden": "true" })
4071
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react24.Sparkles, { size, stroke: `url(#${id})`, className, "aria-hidden": "true" })
3970
4072
  ] });
3971
4073
  }
3972
4074
 
3973
4075
  // src/Freshness.tsx
3974
- var import_jsx_runtime40 = require("react/jsx-runtime");
4076
+ var import_jsx_runtime41 = require("react/jsx-runtime");
3975
4077
  var dotColor = {
3976
4078
  fresh: "bg-status-success",
3977
4079
  recent: "bg-status-warning",
@@ -3983,7 +4085,7 @@ var srLabel = {
3983
4085
  stale: "Older than a day"
3984
4086
  };
3985
4087
  function Freshness({ level }) {
3986
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
4088
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3987
4089
  "span",
3988
4090
  {
3989
4091
  className: cn("inline-block h-1.5 w-1.5 shrink-0 rounded-full", dotColor[level]),
@@ -3994,28 +4096,306 @@ function Freshness({ level }) {
3994
4096
  }
3995
4097
 
3996
4098
  // src/SectionHeading.tsx
3997
- var import_jsx_runtime41 = require("react/jsx-runtime");
4099
+ var import_jsx_runtime42 = require("react/jsx-runtime");
3998
4100
  function SectionHeading({ title, description, actions, as: Tag2 = "h2", id, className }) {
3999
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: cn("flex flex-wrap items-end justify-between gap-x-4 gap-y-2", className), children: [
4000
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "min-w-0", children: [
4001
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Tag2, { id, className: "text-base font-semibold text-text-primary", children: title }),
4002
- description && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "mt-0.5 text-dense text-text-secondary", children: description })
4101
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: cn("flex flex-wrap items-end justify-between gap-x-4 gap-y-2", className), children: [
4102
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "min-w-0", children: [
4103
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Tag2, { id, className: "text-base font-semibold text-text-primary", children: title }),
4104
+ description && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mt-0.5 text-dense text-text-secondary", children: description })
4003
4105
  ] }),
4004
- actions && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex shrink-0 items-center gap-2", children: actions })
4106
+ actions && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex shrink-0 items-center gap-2", children: actions })
4005
4107
  ] });
4006
4108
  }
4007
4109
 
4008
4110
  // src/PageHeader.tsx
4009
- var import_jsx_runtime42 = require("react/jsx-runtime");
4010
- function PageHeader({ title, description, actions, className }) {
4011
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("header", { className: cn("flex flex-wrap items-center justify-between gap-x-6 gap-y-3", className), children: [
4012
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "min-w-0", children: [
4013
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h1", { className: "text-xl font-semibold tracking-tight text-text-primary", children: title }),
4014
- description && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mt-0.5 max-w-2xl text-sm text-text-secondary", children: description })
4111
+ var import_lucide_react25 = require("lucide-react");
4112
+ var import_jsx_runtime43 = require("react/jsx-runtime");
4113
+ function PageHeader({ title, description, actions, back, className }) {
4114
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("header", { className: cn("flex flex-wrap items-center justify-between gap-x-6 gap-y-3", className), children: [
4115
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "min-w-0", children: [
4116
+ back && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
4117
+ "a",
4118
+ {
4119
+ href: back.href ?? "#",
4120
+ onClick: back.onClick,
4121
+ className: "mb-1.5 inline-flex items-center gap-1.5 rounded-control text-micro font-semibold uppercase tracking-wider text-text-tertiary hover:text-text-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-border-focus",
4122
+ children: [
4123
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react25.ArrowLeft, { size: 13, "aria-hidden": "true" }),
4124
+ back.label
4125
+ ]
4126
+ }
4127
+ ),
4128
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h1", { className: "text-xl font-semibold tracking-tight text-text-primary", children: title }),
4129
+ description && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "mt-0.5 max-w-2xl text-sm text-text-secondary", children: description })
4015
4130
  ] }),
4016
- actions && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex shrink-0 items-center gap-2", children: actions })
4131
+ actions && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex shrink-0 items-center gap-2", children: actions })
4017
4132
  ] });
4018
4133
  }
4134
+
4135
+ // src/Modal.tsx
4136
+ var import_react19 = require("react");
4137
+ var import_react_dom7 = require("react-dom");
4138
+ var import_lucide_react26 = require("lucide-react");
4139
+ var import_jsx_runtime44 = require("react/jsx-runtime");
4140
+ var WIDTH = {
4141
+ sm: "max-w-110",
4142
+ md: "max-w-160",
4143
+ lg: "max-w-220"
4144
+ };
4145
+ var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
4146
+ function Modal({ open, onClose, title, description, size = "md", footer, children, className }) {
4147
+ const titleId = (0, import_react19.useId)();
4148
+ const descId = (0, import_react19.useId)();
4149
+ const panel = (0, import_react19.useRef)(null);
4150
+ const close = (0, import_react19.useRef)(onClose);
4151
+ close.current = onClose;
4152
+ (0, import_react19.useEffect)(() => {
4153
+ if (!open) return;
4154
+ const opener = document.activeElement;
4155
+ const first = panel.current?.querySelector(`[data-modal-body] :is(${FOCUSABLE})`) ?? panel.current?.querySelector(`[data-modal-footer] :is(${FOCUSABLE})`);
4156
+ (first ?? panel.current)?.focus();
4157
+ const overflow = document.body.style.overflow;
4158
+ document.body.style.overflow = "hidden";
4159
+ const onKey = (e) => {
4160
+ if (e.key === "Escape") {
4161
+ e.stopPropagation();
4162
+ close.current();
4163
+ return;
4164
+ }
4165
+ if (e.key !== "Tab" || !panel.current) return;
4166
+ const items = Array.from(panel.current.querySelectorAll(FOCUSABLE));
4167
+ if (items.length === 0) return;
4168
+ const [head, tail] = [items[0], items[items.length - 1]];
4169
+ if (e.shiftKey && document.activeElement === head) {
4170
+ e.preventDefault();
4171
+ tail.focus();
4172
+ } else if (!e.shiftKey && document.activeElement === tail) {
4173
+ e.preventDefault();
4174
+ head.focus();
4175
+ }
4176
+ };
4177
+ document.addEventListener("keydown", onKey);
4178
+ return () => {
4179
+ document.removeEventListener("keydown", onKey);
4180
+ document.body.style.overflow = overflow;
4181
+ opener?.focus?.();
4182
+ };
4183
+ }, [open]);
4184
+ if (!open || typeof document === "undefined") return null;
4185
+ return (0, import_react_dom7.createPortal)(
4186
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4187
+ "div",
4188
+ {
4189
+ className: "fixed inset-0 z-modal flex items-center justify-center bg-scrim px-4 py-6",
4190
+ onMouseDown: (e) => e.target === e.currentTarget && onClose(),
4191
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
4192
+ "div",
4193
+ {
4194
+ ref: panel,
4195
+ role: "dialog",
4196
+ "aria-modal": "true",
4197
+ "aria-labelledby": titleId,
4198
+ "aria-describedby": description ? descId : void 0,
4199
+ tabIndex: -1,
4200
+ className: cn(
4201
+ "flex max-h-full w-full flex-col rounded-card border border-border-default bg-surface shadow-overlay outline-hidden",
4202
+ WIDTH[size],
4203
+ className
4204
+ ),
4205
+ children: [
4206
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-start gap-3 px-5 pt-5 pb-3", children: [
4207
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "min-w-0 flex-1", children: [
4208
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h2", { id: titleId, className: "text-base font-semibold text-text-primary", children: title }),
4209
+ description && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { id: descId, className: "mt-0.5 text-sm text-text-secondary", children: description })
4210
+ ] }),
4211
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4212
+ "button",
4213
+ {
4214
+ type: "button",
4215
+ onClick: onClose,
4216
+ "aria-label": "Close",
4217
+ className: "-mr-1.5 -mt-1 flex size-8 shrink-0 items-center justify-center rounded-control text-text-tertiary hover:bg-subtle hover:text-text-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-border-focus",
4218
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react26.X, { size: 16, "aria-hidden": "true" })
4219
+ }
4220
+ )
4221
+ ] }),
4222
+ children && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { "data-modal-body": true, className: "min-h-0 flex-1 overflow-y-auto px-5 pb-5 text-sm text-text-primary", children }),
4223
+ footer && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { "data-modal-footer": true, className: "flex items-center justify-end gap-2 border-t border-border-default px-5 py-3", children: footer })
4224
+ ]
4225
+ }
4226
+ )
4227
+ }
4228
+ ),
4229
+ document.body
4230
+ );
4231
+ }
4232
+
4233
+ // src/EmptyState.tsx
4234
+ var import_jsx_runtime45 = require("react/jsx-runtime");
4235
+ function EmptyState({ icon, title, description, action, size = "sm", className }) {
4236
+ const md = size === "md";
4237
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
4238
+ "div",
4239
+ {
4240
+ className: cn(
4241
+ "flex flex-col items-center text-center",
4242
+ md ? "gap-2 px-6 py-16" : "gap-1.5 px-4 py-8",
4243
+ className
4244
+ ),
4245
+ children: [
4246
+ icon && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4247
+ "span",
4248
+ {
4249
+ "aria-hidden": "true",
4250
+ className: cn(
4251
+ "flex items-center justify-center text-text-tertiary",
4252
+ md && "mb-1 size-11 rounded-full bg-subtle"
4253
+ ),
4254
+ children: icon
4255
+ }
4256
+ ),
4257
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: cn("font-semibold text-text-primary", md ? "text-base" : "text-sm"), children: title }),
4258
+ description && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: cn("max-w-sm text-text-secondary", md ? "text-sm" : "text-xs"), children: description }),
4259
+ action && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: md ? "mt-3" : "mt-2", children: action })
4260
+ ]
4261
+ }
4262
+ );
4263
+ }
4264
+
4265
+ // src/Tabs.tsx
4266
+ var import_react20 = require("react");
4267
+ var import_jsx_runtime46 = require("react/jsx-runtime");
4268
+ function arrowKeys(e, row) {
4269
+ if (!row || !["ArrowLeft", "ArrowRight", "Home", "End"].includes(e.key)) return;
4270
+ const items = Array.from(row.querySelectorAll("button:not([disabled])"));
4271
+ const at = items.indexOf(document.activeElement);
4272
+ const next = e.key === "Home" ? 0 : e.key === "End" ? items.length - 1 : (at + (e.key === "ArrowRight" ? 1 : -1) + items.length) % items.length;
4273
+ e.preventDefault();
4274
+ items[next]?.focus();
4275
+ items[next]?.click();
4276
+ }
4277
+ function Tabs({ items, value, onChange, idPrefix = "tabs", className, ...rest }) {
4278
+ const row = (0, import_react20.useRef)(null);
4279
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
4280
+ "div",
4281
+ {
4282
+ ref: row,
4283
+ role: "tablist",
4284
+ "aria-label": rest["aria-label"],
4285
+ onKeyDown: (e) => arrowKeys(e, row.current),
4286
+ className: cn("flex gap-6 border-b border-border-default", className),
4287
+ children: items.map((item) => {
4288
+ const on = item.value === value;
4289
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
4290
+ "button",
4291
+ {
4292
+ type: "button",
4293
+ role: "tab",
4294
+ id: `${idPrefix}-tab-${item.value}`,
4295
+ "aria-controls": `${idPrefix}-panel-${item.value}`,
4296
+ "aria-selected": on,
4297
+ tabIndex: on ? 0 : -1,
4298
+ disabled: item.disabled,
4299
+ onClick: () => onChange(item.value),
4300
+ className: cn(
4301
+ "-mb-px flex items-center gap-1.5 rounded-control border-b-2 pt-1 pb-2.5 text-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-border-focus disabled:opacity-50",
4302
+ on ? "border-brand-primaryAction font-semibold text-text-primary" : "border-transparent text-text-secondary hover:text-text-primary"
4303
+ ),
4304
+ children: [
4305
+ item.label,
4306
+ item.count !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-xs text-text-tertiary", children: item.count })
4307
+ ]
4308
+ },
4309
+ item.value
4310
+ );
4311
+ })
4312
+ }
4313
+ );
4314
+ }
4315
+ function SegmentedControl({
4316
+ options,
4317
+ value,
4318
+ onChange,
4319
+ size = "sm",
4320
+ className,
4321
+ ...rest
4322
+ }) {
4323
+ const row = (0, import_react20.useRef)(null);
4324
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
4325
+ "div",
4326
+ {
4327
+ ref: row,
4328
+ role: "radiogroup",
4329
+ "aria-label": rest["aria-label"],
4330
+ onKeyDown: (e) => arrowKeys(e, row.current),
4331
+ className: cn("inline-flex w-fit items-stretch gap-0.5 rounded-full bg-subtle p-1", size === "md" ? "h-10" : "h-8", className),
4332
+ children: options.map((o) => {
4333
+ const on = o.value === value;
4334
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
4335
+ "button",
4336
+ {
4337
+ type: "button",
4338
+ role: "radio",
4339
+ "aria-checked": on,
4340
+ tabIndex: on ? 0 : -1,
4341
+ onClick: () => onChange(o.value),
4342
+ className: cn(
4343
+ "rounded-full px-3 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus",
4344
+ size === "md" ? "text-sm" : "text-xs",
4345
+ on ? "bg-surface font-semibold text-text-primary shadow-raised" : "text-text-secondary hover:text-text-primary"
4346
+ ),
4347
+ children: o.label
4348
+ },
4349
+ o.value
4350
+ );
4351
+ })
4352
+ }
4353
+ );
4354
+ }
4355
+
4356
+ // src/TextField.tsx
4357
+ var import_react21 = require("react");
4358
+ var import_jsx_runtime47 = require("react/jsx-runtime");
4359
+ var HEIGHT2 = { sm: "h-8", md: "h-10", lg: "h-11" };
4360
+ var TextField = (0, import_react21.forwardRef)(
4361
+ ({ label, hint, error, size = "md", icon, className, id, disabled, ...props }, ref) => {
4362
+ const auto = (0, import_react21.useId)();
4363
+ const fieldId = id ?? auto;
4364
+ const noteId = `${fieldId}-note`;
4365
+ const note = error ?? hint;
4366
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: cn("flex flex-col gap-1.5", className), children: [
4367
+ label && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor: fieldId, className: "text-xs font-medium text-text-secondary", children: label }),
4368
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
4369
+ "div",
4370
+ {
4371
+ className: cn(
4372
+ "flex items-center gap-2 rounded-control border bg-input px-3 focus-within:outline-2 focus-within:outline-offset-1 focus-within:outline-border-focus",
4373
+ HEIGHT2[size],
4374
+ error ? "border-status-danger" : "border-border-strong",
4375
+ disabled && "opacity-50"
4376
+ ),
4377
+ children: [
4378
+ icon && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-hidden": "true", className: "flex shrink-0 text-text-tertiary", children: icon }),
4379
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
4380
+ "input",
4381
+ {
4382
+ ref,
4383
+ id: fieldId,
4384
+ disabled,
4385
+ "aria-invalid": error ? true : void 0,
4386
+ "aria-describedby": note ? noteId : void 0,
4387
+ className: "min-w-0 flex-1 bg-transparent text-dense text-text-primary outline-hidden placeholder:text-text-tertiary",
4388
+ ...props
4389
+ }
4390
+ )
4391
+ ]
4392
+ }
4393
+ ),
4394
+ note && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { id: noteId, className: cn("text-xs", error ? "text-text-danger" : "text-text-tertiary"), children: note })
4395
+ ] });
4396
+ }
4397
+ );
4398
+ TextField.displayName = "TextField";
4019
4399
  // Annotate the CommonJS export names for ESM import in node:
4020
4400
  0 && (module.exports = {
4021
4401
  AISpark,
@@ -4034,11 +4414,13 @@ function PageHeader({ title, description, actions, className }) {
4034
4414
  DateRangeFilter,
4035
4415
  DateRangePicker,
4036
4416
  Delta,
4417
+ EmptyState,
4037
4418
  FilterChipBar,
4038
4419
  FilterDropdownFooter,
4039
4420
  Freshness,
4040
4421
  InfoTip,
4041
4422
  LineChartPlaceholder,
4423
+ Modal,
4042
4424
  MultiSelectFilter,
4043
4425
  NO_RESULTS_BODY,
4044
4426
  NO_RESULTS_TITLE,
@@ -4053,6 +4435,7 @@ function PageHeader({ title, description, actions, className }) {
4053
4435
  SearchBar,
4054
4436
  SectionHeading,
4055
4437
  SectionRail,
4438
+ SegmentedControl,
4056
4439
  SelectAllVisible,
4057
4440
  SelectFilter,
4058
4441
  SelectedSection,
@@ -4060,7 +4443,10 @@ function PageHeader({ title, description, actions, className }) {
4060
4443
  SortButton,
4061
4444
  StackedColumnPlaceholder,
4062
4445
  TablePagination,
4446
+ Tabs,
4063
4447
  Tag,
4448
+ TextField,
4449
+ Toast,
4064
4450
  Toggle,
4065
4451
  Tooltip,
4066
4452
  WorkspaceAvatar,