@assure-one/design-system 0.14.0 → 0.15.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.js CHANGED
@@ -2189,6 +2189,27 @@ function TrendingDownIcon({ size = 24, ...props }) {
2189
2189
  }
2190
2190
  ) });
2191
2191
  }
2192
+ function PlayIcon({ size = 24, ...props }) {
2193
+ return /* @__PURE__ */ jsx(Icon, { size, ...props, children: /* @__PURE__ */ jsx(
2194
+ "path",
2195
+ {
2196
+ d: "M8 5.14v13.72a1 1 0 001.54.84l10.78-6.86a1 1 0 000-1.68L9.54 4.3A1 1 0 008 5.14z",
2197
+ fill: "currentColor",
2198
+ stroke: "currentColor",
2199
+ strokeWidth: "1.5",
2200
+ strokeLinejoin: "round"
2201
+ }
2202
+ ) });
2203
+ }
2204
+ function PauseIcon({ size = 24, ...props }) {
2205
+ return /* @__PURE__ */ jsxs(Icon, { size, ...props, children: [
2206
+ /* @__PURE__ */ jsx("rect", { x: "7", y: "5", width: "3.5", height: "14", rx: "1", fill: "currentColor" }),
2207
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "5", width: "3.5", height: "14", rx: "1", fill: "currentColor" })
2208
+ ] });
2209
+ }
2210
+ function StopIcon({ size = 24, ...props }) {
2211
+ return /* @__PURE__ */ jsx(Icon, { size, ...props, children: /* @__PURE__ */ jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2", fill: "currentColor" }) });
2212
+ }
2192
2213
  var Accordion = React36.forwardRef(function Accordion2({ className, ...props }, ref) {
2193
2214
  return /* @__PURE__ */ jsx(
2194
2215
  AccordionPrimitive.Root,
@@ -2434,7 +2455,7 @@ var AlertTitle = forwardRef(
2434
2455
  );
2435
2456
  AlertTitle.displayName = "AlertTitle";
2436
2457
  var AlertDescription = forwardRef(function AlertDescription2({ className, ...props }, ref) {
2437
- return /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm opacity-90", className), ...props });
2458
+ return /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm", className), ...props });
2438
2459
  });
2439
2460
  AlertDescription.displayName = "AlertDescription";
2440
2461
  var AspectRatio = React36.forwardRef(function AspectRatio2({ className, ratio = 16 / 9, ...props }, ref) {
@@ -2530,7 +2551,8 @@ var Avatar = React36.forwardRef(
2530
2551
  statusDotSizes[resolvedSize],
2531
2552
  statusStyles[status]
2532
2553
  ),
2533
- "aria-label": status
2554
+ role: "img",
2555
+ "aria-label": `${status} status`
2534
2556
  }
2535
2557
  )
2536
2558
  ] });
@@ -2713,6 +2735,48 @@ var BreadcrumbSeparator = forwardRef(
2713
2735
  }
2714
2736
  );
2715
2737
  BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
2738
+ var spinnerVariants = cva(
2739
+ "inline-flex shrink-0 items-center justify-center [&_svg]:motion-reduce:animate-none",
2740
+ {
2741
+ variants: {
2742
+ size: {
2743
+ xs: "[&_svg]:size-3",
2744
+ sm: "[&_svg]:size-4",
2745
+ md: "[&_svg]:size-5",
2746
+ lg: "[&_svg]:size-6"
2747
+ },
2748
+ tone: {
2749
+ current: "text-current",
2750
+ muted: "text-fg-3",
2751
+ accent: "text-accent",
2752
+ success: "text-success-fg",
2753
+ warning: "text-warning-fg",
2754
+ destructive: "text-danger-fg"
2755
+ }
2756
+ },
2757
+ defaultVariants: {
2758
+ size: "md",
2759
+ tone: "current"
2760
+ }
2761
+ }
2762
+ );
2763
+ var Spinner = forwardRef(function Spinner2({ size, tone, label, className, ...props }, ref) {
2764
+ return /* @__PURE__ */ jsxs(
2765
+ "span",
2766
+ {
2767
+ ref,
2768
+ role: label ? "status" : void 0,
2769
+ "aria-live": label ? "polite" : void 0,
2770
+ className: cn(spinnerVariants({ size, tone }), className),
2771
+ ...props,
2772
+ children: [
2773
+ /* @__PURE__ */ jsx(LoaderIcon, { className: "animate-spin", "aria-hidden": "true" }),
2774
+ label && /* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
2775
+ ]
2776
+ }
2777
+ );
2778
+ });
2779
+ Spinner.displayName = "Spinner";
2716
2780
  var buttonVariants = cva(
2717
2781
  cn(
2718
2782
  "inline-flex items-center justify-center rounded-btn font-medium whitespace-nowrap",
@@ -2726,14 +2790,14 @@ var buttonVariants = cva(
2726
2790
  variants: {
2727
2791
  variant: {
2728
2792
  primary: "bg-pro-fg text-fg-on-pro hover:bg-pro-hover active:bg-pro-active",
2729
- secondary: "bg-bg-2 text-fg-2 border border-rule hover:bg-bg-3 hover:border-rule-strong",
2730
- destructive: "bg-danger-fg text-white hover:bg-danger-fg/90 active:bg-danger-fg/80",
2731
- success: "bg-success-fg text-white hover:bg-success-fg/90 active:bg-success-fg/80",
2732
- ghost: "bg-transparent text-fg-2 hover:bg-bg-2 hover:text-fg",
2733
- outline: "border border-rule-strong bg-bg text-fg-2 hover:bg-bg-2 hover:border-fg-4",
2793
+ secondary: "bg-control-secondary-bg text-control-fg border border-control-border hover:bg-control-active-bg hover:border-control-border-strong",
2794
+ destructive: "bg-danger-fg text-fg-on-danger hover:bg-danger-fg-hover active:bg-danger-fg-active",
2795
+ success: "bg-success-fg text-fg-on-success hover:bg-success-fg-hover active:bg-success-fg-active",
2796
+ ghost: "bg-control-bg text-control-fg hover:bg-control-hover-bg hover:text-control-hover-fg",
2797
+ outline: "border border-control-border-strong bg-control-bg text-control-fg hover:bg-control-hover-bg hover:border-control-border-hover",
2734
2798
  link: "bg-transparent text-accent underline-offset-4 hover:underline p-0 h-auto",
2735
2799
  accent: "bg-accent text-fg-on-accent hover:bg-accent-hover active:bg-accent-active",
2736
- dashed: "border-2 border-dashed border-rule bg-transparent text-fg-3 hover:border-fg-4 hover:bg-bg-2 hover:text-fg"
2800
+ dashed: "border-2 border-dashed border-control-border bg-control-bg text-control-muted-fg hover:border-control-border-hover hover:bg-control-hover-bg hover:text-control-hover-fg"
2737
2801
  },
2738
2802
  size: {
2739
2803
  sm: "h-8 px-3 text-[13px] gap-1.5",
@@ -2753,30 +2817,6 @@ var buttonVariants = cva(
2753
2817
  }
2754
2818
  }
2755
2819
  );
2756
- var Spinner = () => /* @__PURE__ */ jsxs("svg", { className: "size-4 animate-spin", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
2757
- /* @__PURE__ */ jsx(
2758
- "circle",
2759
- {
2760
- cx: "12",
2761
- cy: "12",
2762
- r: "10",
2763
- stroke: "currentColor",
2764
- strokeWidth: "3",
2765
- strokeLinecap: "round",
2766
- className: "opacity-25"
2767
- }
2768
- ),
2769
- /* @__PURE__ */ jsx(
2770
- "path",
2771
- {
2772
- d: "M4 12a8 8 0 018-8",
2773
- stroke: "currentColor",
2774
- strokeWidth: "3",
2775
- strokeLinecap: "round",
2776
- className: "opacity-75"
2777
- }
2778
- )
2779
- ] });
2780
2820
  var Button = forwardRef(function Button2({
2781
2821
  variant,
2782
2822
  size,
@@ -2801,7 +2841,7 @@ var Button = forwardRef(function Button2({
2801
2841
  className: cn(buttonVariants({ variant, size }), className),
2802
2842
  ...props,
2803
2843
  children: [
2804
- loading ? /* @__PURE__ */ jsx(Spinner, {}) : iconLeft && /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", "aria-hidden": "true", children: iconLeft }),
2844
+ loading ? /* @__PURE__ */ jsx(Spinner, { size: "sm" }) : iconLeft && /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", "aria-hidden": "true", children: iconLeft }),
2805
2845
  children,
2806
2846
  iconRight && !loading && /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", "aria-hidden": "true", children: iconRight })
2807
2847
  ]
@@ -2890,7 +2930,7 @@ function Calendar({
2890
2930
  ),
2891
2931
  today: "[&_button]:font-semibold [&_button]:text-accent",
2892
2932
  selected: "[&_button]:bg-pro-fg [&_button]:text-fg-on-pro [&_button]:hover:bg-pro-hover [&_button]:focus-visible:bg-pro-fg",
2893
- outside: "[&_button]:text-fg-5",
2933
+ outside: "[&_button]:text-fg-4",
2894
2934
  disabled: "[&_button]:text-fg-disabled",
2895
2935
  hidden: "invisible",
2896
2936
  ...classNames
@@ -3176,7 +3216,7 @@ function Select({
3176
3216
  SelectTrigger,
3177
3217
  {
3178
3218
  "aria-invalid": ariaInvalid || void 0,
3179
- "aria-label": ariaLabel,
3219
+ "aria-label": ariaLabel ?? placeholder,
3180
3220
  className: cn(triggerClassName, className),
3181
3221
  children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
3182
3222
  }
@@ -3590,16 +3630,30 @@ function ConfirmActionButton({
3590
3630
  cancelLabel = "Cancel",
3591
3631
  onConfirm,
3592
3632
  destructive = true,
3593
- contentClassName
3633
+ contentClassName,
3634
+ open,
3635
+ defaultOpen = false,
3636
+ onOpenChange
3594
3637
  }) {
3595
- const [open, setOpen] = React36.useState(false);
3638
+ const isControlled = open !== void 0;
3639
+ const [uncontrolledOpen, setUncontrolledOpen] = React36.useState(defaultOpen);
3640
+ const resolvedOpen = isControlled ? open : uncontrolledOpen;
3596
3641
  const [pending, setPending] = React36.useState(false);
3642
+ const setDialogOpen = React36.useCallback(
3643
+ (nextOpen) => {
3644
+ onOpenChange?.(nextOpen);
3645
+ if (!isControlled) {
3646
+ setUncontrolledOpen(nextOpen);
3647
+ }
3648
+ },
3649
+ [isControlled, onOpenChange]
3650
+ );
3597
3651
  const handleConfirm = async (event) => {
3598
3652
  event.preventDefault();
3599
3653
  setPending(true);
3600
3654
  try {
3601
3655
  await onConfirm();
3602
- setOpen(false);
3656
+ setDialogOpen(false);
3603
3657
  } finally {
3604
3658
  setPending(false);
3605
3659
  }
@@ -3607,10 +3661,10 @@ function ConfirmActionButton({
3607
3661
  return /* @__PURE__ */ jsxs(
3608
3662
  AlertDialog,
3609
3663
  {
3610
- open,
3664
+ open: resolvedOpen,
3611
3665
  onOpenChange: (next) => {
3612
3666
  if (pending) return;
3613
- setOpen(next);
3667
+ setDialogOpen(next);
3614
3668
  },
3615
3669
  children: [
3616
3670
  /* @__PURE__ */ jsx(AlertDialogTrigger, { asChild: true, children: trigger }),
@@ -4443,9 +4497,9 @@ var DropdownMenuSubTrigger = React36.forwardRef(({ className, inset, children, .
4443
4497
  ref,
4444
4498
  className: cn(
4445
4499
  "rounded-pill flex cursor-default items-center gap-2 px-2 py-1.5 text-sm outline-none select-none",
4446
- "text-fg-2 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4447
- "focus:bg-bg-2 focus:text-fg",
4448
- "data-[state=open]:bg-bg-2 data-[state=open]:text-fg",
4500
+ "text-menu-item-fg transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4501
+ "focus:bg-menu-item-hover-bg focus:text-menu-item-hover-fg",
4502
+ "data-[state=open]:bg-menu-item-hover-bg data-[state=open]:text-menu-item-hover-fg",
4449
4503
  "data-[disabled]:text-fg-disabled data-[disabled]:pointer-events-none",
4450
4504
  inset && "pl-8",
4451
4505
  className
@@ -4469,7 +4523,7 @@ var DropdownMenuSubContent = React36.forwardRef(({ className, ...props }, ref) =
4469
4523
  {
4470
4524
  ref,
4471
4525
  className: cn(
4472
- "rounded-card border-rule bg-surface text-fg shadow-pop z-[var(--z-dropdown)] min-w-[8rem] overflow-hidden border p-1",
4526
+ "rounded-card border-menu-border bg-menu-bg text-menu-fg shadow-pop z-[var(--z-dropdown)] min-w-[8rem] overflow-hidden border p-1",
4473
4527
  "transition-[opacity,transform] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
4474
4528
  "data-[state=closed]:scale-95 data-[state=closed]:opacity-0",
4475
4529
  "data-[state=open]:scale-100 data-[state=open]:opacity-100",
@@ -4488,7 +4542,7 @@ var DropdownMenuContent = React36.forwardRef(({ className, sideOffset = 6, align
4488
4542
  sideOffset,
4489
4543
  align,
4490
4544
  className: cn(
4491
- "rounded-card border-rule bg-surface text-fg shadow-pop z-[var(--z-dropdown)] min-w-[10rem] overflow-hidden border p-1",
4545
+ "rounded-card border-menu-border bg-menu-bg text-menu-fg shadow-pop z-[var(--z-dropdown)] min-w-[10rem] overflow-hidden border p-1",
4492
4546
  "transition-[opacity,transform] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
4493
4547
  "data-[state=closed]:scale-95 data-[state=closed]:opacity-0",
4494
4548
  "data-[state=open]:scale-100 data-[state=open]:opacity-100",
@@ -4505,12 +4559,12 @@ var DropdownMenuItem = React36.forwardRef(({ className, destructive, inset, ...p
4505
4559
  ref,
4506
4560
  className: cn(
4507
4561
  "rounded-pill relative flex cursor-default items-center gap-2 px-2 py-1.5 text-sm outline-none select-none",
4508
- "text-fg-2 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4509
- "focus:bg-bg-2 focus:text-fg",
4562
+ "text-menu-item-fg transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4563
+ "focus:bg-menu-item-hover-bg focus:text-menu-item-hover-fg",
4510
4564
  "data-[disabled]:text-fg-disabled data-[disabled]:pointer-events-none",
4511
4565
  "[&_svg]:size-4 [&_svg]:shrink-0",
4512
4566
  inset && "pl-8",
4513
- destructive && "text-danger-fg focus:bg-danger-bg focus:text-danger-fg",
4567
+ destructive && "text-menu-item-destructive-fg focus:bg-menu-item-destructive-hover-bg focus:text-menu-item-destructive-hover-fg",
4514
4568
  className
4515
4569
  ),
4516
4570
  ...props
@@ -4524,8 +4578,8 @@ var DropdownMenuCheckboxItem = React36.forwardRef(({ className, children, checke
4524
4578
  checked,
4525
4579
  className: cn(
4526
4580
  "rounded-pill relative flex cursor-default items-center gap-2 py-1.5 pr-2 pl-8 text-sm outline-none select-none",
4527
- "text-fg-2 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4528
- "focus:bg-bg-2 focus:text-fg",
4581
+ "text-menu-item-fg transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4582
+ "focus:bg-menu-item-hover-bg focus:text-menu-item-hover-fg",
4529
4583
  "data-[disabled]:text-fg-disabled data-[disabled]:pointer-events-none",
4530
4584
  className
4531
4585
  ),
@@ -4543,8 +4597,8 @@ var DropdownMenuRadioItem = React36.forwardRef(({ className, children, ...props
4543
4597
  ref,
4544
4598
  className: cn(
4545
4599
  "rounded-pill relative flex cursor-default items-center gap-2 py-1.5 pr-2 pl-8 text-sm outline-none select-none",
4546
- "text-fg-2 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4547
- "focus:bg-bg-2 focus:text-fg",
4600
+ "text-menu-item-fg transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
4601
+ "focus:bg-menu-item-hover-bg focus:text-menu-item-hover-fg",
4548
4602
  "data-[disabled]:text-fg-disabled data-[disabled]:pointer-events-none",
4549
4603
  className
4550
4604
  ),
@@ -4561,7 +4615,7 @@ var DropdownMenuLabel = React36.forwardRef(({ className, inset, ...props }, ref)
4561
4615
  {
4562
4616
  ref,
4563
4617
  className: cn(
4564
- "text-fg-3 px-2 py-1.5 font-mono text-[11px] tracking-wider uppercase",
4618
+ "text-menu-label-fg px-2 py-1.5 font-mono text-[11px] tracking-wider uppercase",
4565
4619
  inset && "pl-8",
4566
4620
  className
4567
4621
  ),
@@ -4573,7 +4627,7 @@ var DropdownMenuSeparator = React36.forwardRef(({ className, ...props }, ref) =>
4573
4627
  DropdownMenuPrimitive.Separator,
4574
4628
  {
4575
4629
  ref,
4576
- className: cn("bg-rule -mx-1 my-1 h-px", className),
4630
+ className: cn("bg-menu-border -mx-1 my-1 h-px", className),
4577
4631
  ...props
4578
4632
  }
4579
4633
  ));
@@ -4581,7 +4635,7 @@ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
4581
4635
  var DropdownMenuShortcut = ({ className, ...props }) => /* @__PURE__ */ jsx(
4582
4636
  "span",
4583
4637
  {
4584
- className: cn("text-fg-4 ml-auto font-mono text-[11px] tracking-wider", className),
4638
+ className: cn("text-menu-shortcut-fg ml-auto font-mono text-[11px] tracking-wider", className),
4585
4639
  ...props
4586
4640
  }
4587
4641
  );
@@ -5137,7 +5191,7 @@ function Logo({
5137
5191
  /* @__PURE__ */ jsx("span", { children: "Assure" }),
5138
5192
  productName && /* @__PURE__ */ jsxs(Fragment, { children: [
5139
5193
  " ",
5140
- /* @__PURE__ */ jsx("span", { className: "text-pro-fg font-medium", children: productName })
5194
+ /* @__PURE__ */ jsx("span", { className: cn("font-medium", inverted ? "text-[#d8cfff]" : "text-pro-fg"), children: productName })
5141
5195
  ] })
5142
5196
  ]
5143
5197
  }
@@ -5163,37 +5217,35 @@ function MultiFilterPill({
5163
5217
  const active = selected.size > 0;
5164
5218
  const displayLabel = active ? selected.size === 1 ? options.find((o) => o.key === [...selected][0])?.label ?? label : `${label} \xB7 ${selected.size}` : label;
5165
5219
  return /* @__PURE__ */ jsxs(Popover, { children: [
5166
- /* @__PURE__ */ jsxs(
5167
- PopoverTrigger,
5220
+ active ? /* @__PURE__ */ jsxs(
5221
+ "div",
5168
5222
  {
5169
5223
  className: cn(
5170
5224
  "rounded-pill font-body inline-flex items-center border font-medium",
5171
5225
  TRIGGER_SIZE[size],
5226
+ "border-pro-line bg-pro-bg text-pro-fg hover:bg-pro-bg-hover",
5172
5227
  "transition-[color,background-color,border-color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
5173
- "motion-reduce:transition-none",
5174
- "focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
5175
- active ? "border-pro-line bg-pro-bg text-pro-fg hover:bg-pro-bg-hover" : "border-rule bg-surface text-fg-2 hover:border-rule-strong hover:bg-bg-2 hover:text-fg"
5228
+ "motion-reduce:transition-none"
5176
5229
  ),
5177
5230
  children: [
5178
- icon && /* @__PURE__ */ jsx("span", { className: "[&>svg]:size-3.5", "aria-hidden": "true", children: icon }),
5179
- /* @__PURE__ */ jsx("span", { className: "line-clamp-1", children: displayLabel }),
5180
- active ? /* @__PURE__ */ jsx(
5181
- "span",
5231
+ /* @__PURE__ */ jsxs(
5232
+ PopoverTrigger,
5182
5233
  {
5183
- role: "button",
5184
- tabIndex: 0,
5185
- onClick: (e) => {
5186
- e.stopPropagation();
5187
- e.preventDefault();
5188
- onClear();
5189
- },
5190
- onKeyDown: (e) => {
5191
- if (e.key === "Enter" || e.key === " ") {
5192
- e.stopPropagation();
5193
- e.preventDefault();
5194
- onClear();
5195
- }
5196
- },
5234
+ className: cn(
5235
+ "inline-flex min-w-0 flex-1 items-center gap-1.5 rounded-pill outline-none",
5236
+ "focus-visible:[box-shadow:var(--shadow-focus-ring)]"
5237
+ ),
5238
+ children: [
5239
+ icon && /* @__PURE__ */ jsx("span", { className: "[&>svg]:size-3.5", "aria-hidden": "true", children: icon }),
5240
+ /* @__PURE__ */ jsx("span", { className: "line-clamp-1", children: displayLabel })
5241
+ ]
5242
+ }
5243
+ ),
5244
+ /* @__PURE__ */ jsx(
5245
+ "button",
5246
+ {
5247
+ type: "button",
5248
+ onClick: onClear,
5197
5249
  className: cn(
5198
5250
  "ml-0.5 inline-flex size-4 items-center justify-center rounded-full",
5199
5251
  "text-pro-fg transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
@@ -5204,7 +5256,24 @@ function MultiFilterPill({
5204
5256
  "aria-label": `Clear ${label} filter`,
5205
5257
  children: /* @__PURE__ */ jsx(XIcon, { className: "size-3", "aria-hidden": "true" })
5206
5258
  }
5207
- ) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "text-fg-4 size-3 shrink-0", "aria-hidden": "true" })
5259
+ )
5260
+ ]
5261
+ }
5262
+ ) : /* @__PURE__ */ jsxs(
5263
+ PopoverTrigger,
5264
+ {
5265
+ className: cn(
5266
+ "rounded-pill font-body inline-flex items-center border font-medium",
5267
+ TRIGGER_SIZE[size],
5268
+ "border-rule bg-surface text-fg-2 hover:border-rule-strong hover:bg-bg-2 hover:text-fg",
5269
+ "transition-[color,background-color,border-color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
5270
+ "motion-reduce:transition-none",
5271
+ "focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none"
5272
+ ),
5273
+ children: [
5274
+ icon && /* @__PURE__ */ jsx("span", { className: "[&>svg]:size-3.5", "aria-hidden": "true", children: icon }),
5275
+ /* @__PURE__ */ jsx("span", { className: "line-clamp-1", children: displayLabel }),
5276
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "text-fg-4 size-3 shrink-0", "aria-hidden": "true" })
5208
5277
  ]
5209
5278
  }
5210
5279
  ),
@@ -5355,7 +5424,8 @@ function OTPInput({
5355
5424
  onChange,
5356
5425
  onComplete,
5357
5426
  id,
5358
- disabled
5427
+ disabled,
5428
+ "aria-label": ariaLabel
5359
5429
  }) {
5360
5430
  const errorId = id ? `${id}-error` : void 0;
5361
5431
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
@@ -5374,6 +5444,7 @@ function OTPInput({
5374
5444
  onChange,
5375
5445
  onComplete,
5376
5446
  disabled,
5447
+ "aria-label": ariaLabel ?? "One-time password",
5377
5448
  "aria-invalid": error ? true : void 0,
5378
5449
  "aria-describedby": error ? errorId : void 0,
5379
5450
  containerClassName: cn(
@@ -5476,7 +5547,7 @@ var Pagination = forwardRef(function Pagination2({
5476
5547
  "nav",
5477
5548
  {
5478
5549
  ref,
5479
- "aria-label": "Pagination",
5550
+ "aria-label": `Pagination, page ${currentPage} of ${totalPages}`,
5480
5551
  className: cn("flex items-center justify-between gap-4", className),
5481
5552
  ...props,
5482
5553
  children: [
@@ -5823,7 +5894,14 @@ var ScrollArea = React36.forwardRef(function ScrollArea2({ className, children,
5823
5894
  className: cn("relative overflow-hidden", className),
5824
5895
  ...props,
5825
5896
  children: [
5826
- /* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
5897
+ /* @__PURE__ */ jsx(
5898
+ ScrollAreaPrimitive.Viewport,
5899
+ {
5900
+ tabIndex: 0,
5901
+ className: "h-full w-full rounded-[inherit] focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
5902
+ children
5903
+ }
5904
+ ),
5827
5905
  /* @__PURE__ */ jsx(ScrollBar, {}),
5828
5906
  /* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
5829
5907
  ]
@@ -6070,8 +6148,21 @@ function SearchSelect({
6070
6148
  }
6071
6149
  }, [onCreate, trimmedSearch]);
6072
6150
  const inputRef = React36.useRef(null);
6151
+ const listboxId = React36.useId();
6152
+ const setInputRef = React36.useCallback((node) => {
6153
+ inputRef.current = node;
6154
+ node?.removeAttribute("aria-labelledby");
6155
+ node?.setAttribute("aria-controls", listboxId);
6156
+ node?.removeAttribute("aria-activedescendant");
6157
+ }, [listboxId]);
6073
6158
  const singleValue = closeOnSelect ? selected[0] ?? null : null;
6074
6159
  const showValue = singleValue !== null && !open;
6160
+ const popoverOpen = open && !disabled;
6161
+ React36.useEffect(() => {
6162
+ inputRef.current?.removeAttribute("aria-labelledby");
6163
+ inputRef.current?.setAttribute("aria-controls", listboxId);
6164
+ inputRef.current?.removeAttribute("aria-activedescendant");
6165
+ });
6075
6166
  React36.useEffect(() => {
6076
6167
  if (open && closeOnSelect) {
6077
6168
  const raf = requestAnimationFrame(() => inputRef.current?.focus());
@@ -6110,10 +6201,12 @@ function SearchSelect({
6110
6201
  },
6111
6202
  item.id
6112
6203
  )) }),
6113
- /* @__PURE__ */ jsx(Popover, { open: open && !disabled, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(
6204
+ !popoverOpen && /* @__PURE__ */ jsx("div", { id: listboxId, role: "listbox", hidden: true }),
6205
+ /* @__PURE__ */ jsx(Popover, { open: popoverOpen, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(
6114
6206
  Command,
6115
6207
  {
6116
6208
  shouldFilter: true,
6209
+ label: placeholder,
6117
6210
  className: "overflow-visible bg-transparent",
6118
6211
  onKeyDown: (e) => {
6119
6212
  if (e.key === "Escape") {
@@ -6210,7 +6303,7 @@ function SearchSelect({
6210
6303
  /* @__PURE__ */ jsx(
6211
6304
  Command.Input,
6212
6305
  {
6213
- ref: inputRef,
6306
+ ref: setInputRef,
6214
6307
  value: search,
6215
6308
  onValueChange: (v) => {
6216
6309
  setSearch(v);
@@ -6220,6 +6313,8 @@ function SearchSelect({
6220
6313
  if (!disabled) setOpen(true);
6221
6314
  },
6222
6315
  placeholder,
6316
+ "aria-label": placeholder,
6317
+ "aria-controls": listboxId,
6223
6318
  disabled,
6224
6319
  className: cn(
6225
6320
  "font-body text-fg flex-1 bg-transparent py-2 pr-3 pl-9 text-[13px] outline-none",
@@ -6268,6 +6363,7 @@ function SearchSelect({
6268
6363
  /* @__PURE__ */ jsxs(
6269
6364
  Command.List,
6270
6365
  {
6366
+ id: listboxId,
6271
6367
  className: cn(
6272
6368
  // No top padding: a sticky group heading pins at top-0, so any
6273
6369
  // top padding would leave a strip above it where the previous
@@ -6533,38 +6629,51 @@ var sheetVariants = cva(
6533
6629
  defaultVariants: { side: "right" }
6534
6630
  }
6535
6631
  );
6536
- var SheetContent = React36.forwardRef(({ side, className, children, showCloseButton = true, ...props }, ref) => {
6537
- const ctx = React36.use(SheetSideContext);
6538
- const resolvedSide = side ?? ctx.side ?? "right";
6539
- return /* @__PURE__ */ jsxs(SheetPortal, { children: [
6540
- /* @__PURE__ */ jsx(SheetOverlay, {}),
6541
- /* @__PURE__ */ jsxs(
6542
- DialogPrimitive.Content,
6543
- {
6544
- ref,
6545
- className: cn(sheetVariants({ side: resolvedSide }), className),
6546
- ...props,
6547
- children: [
6548
- children,
6549
- showCloseButton && /* @__PURE__ */ jsx(
6550
- DialogPrimitive.Close,
6551
- {
6552
- className: cn(
6553
- "absolute top-4 right-4 inline-flex size-7 items-center justify-center",
6554
- "rounded-icon text-fg-4 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
6555
- "hover:bg-overlay-hover hover:text-fg",
6556
- "focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
6557
- "disabled:pointer-events-none"
6558
- ),
6559
- "aria-label": "Close",
6560
- children: /* @__PURE__ */ jsx(XIcon, { className: "size-4", "aria-hidden": "true" })
6561
- }
6562
- )
6563
- ]
6564
- }
6565
- )
6566
- ] });
6567
- });
6632
+ var sheetWidthClasses = {
6633
+ sm: "w-[95vw] max-w-[95vw] sm:w-[420px]",
6634
+ md: "w-[95vw] max-w-[95vw] sm:w-[520px]",
6635
+ lg: "w-[95vw] max-w-[95vw] sm:w-[640px]",
6636
+ xl: "w-[95vw] max-w-[95vw] sm:w-[760px]",
6637
+ full: "w-full max-w-none"
6638
+ };
6639
+ var SheetContent = React36.forwardRef(
6640
+ ({ side, width = "default", customWidth, className, children, showCloseButton = true, style, ...props }, ref) => {
6641
+ const ctx = React36.use(SheetSideContext);
6642
+ const resolvedSide = side ?? ctx.side ?? "right";
6643
+ const supportsWidth = resolvedSide === "left" || resolvedSide === "right";
6644
+ const widthClass = supportsWidth && width !== "default" ? sheetWidthClasses[width] : null;
6645
+ const widthStyle = supportsWidth && customWidth ? { width: customWidth, maxWidth: "95vw", ...style } : style;
6646
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
6647
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
6648
+ /* @__PURE__ */ jsxs(
6649
+ DialogPrimitive.Content,
6650
+ {
6651
+ ref,
6652
+ className: cn(sheetVariants({ side: resolvedSide }), widthClass, className),
6653
+ style: widthStyle,
6654
+ ...props,
6655
+ children: [
6656
+ children,
6657
+ showCloseButton && /* @__PURE__ */ jsx(
6658
+ DialogPrimitive.Close,
6659
+ {
6660
+ className: cn(
6661
+ "absolute top-4 right-4 inline-flex size-7 items-center justify-center",
6662
+ "rounded-icon text-fg-4 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
6663
+ "hover:bg-overlay-hover hover:text-fg",
6664
+ "focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
6665
+ "disabled:pointer-events-none"
6666
+ ),
6667
+ "aria-label": "Close",
6668
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-4", "aria-hidden": "true" })
6669
+ }
6670
+ )
6671
+ ]
6672
+ }
6673
+ )
6674
+ ] });
6675
+ }
6676
+ );
6568
6677
  SheetContent.displayName = DialogPrimitive.Content.displayName;
6569
6678
  var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1.5 p-6 pr-12 pb-0", className), ...props });
6570
6679
  SheetHeader.displayName = "SheetHeader";
@@ -6728,6 +6837,7 @@ var Slider = React36.forwardRef(
6728
6837
  if (typeof v === "number") return v;
6729
6838
  return min;
6730
6839
  })();
6840
+ const accessibleName = props["aria-label"] ?? label ?? "Slider value";
6731
6841
  return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
6732
6842
  (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
6733
6843
  label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-fg text-[13px] leading-none font-medium", children: label }) : /* @__PURE__ */ jsx("span", {}),
@@ -6762,7 +6872,7 @@ var Slider = React36.forwardRef(
6762
6872
  "data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed",
6763
6873
  "data-[disabled]:border-fg-disabled data-[disabled]:bg-bg-disabled"
6764
6874
  ),
6765
- "aria-label": label
6875
+ "aria-label": accessibleName
6766
6876
  }
6767
6877
  )
6768
6878
  ]
@@ -7527,6 +7637,7 @@ function ToastProvider({ children }) {
7527
7637
  "div",
7528
7638
  {
7529
7639
  className: "pointer-events-none fixed top-4 right-4 z-[var(--z-toast)] flex flex-col gap-2",
7640
+ role: "region",
7530
7641
  "aria-live": "polite",
7531
7642
  "aria-label": "Notifications",
7532
7643
  children: toasts.map((t) => /* @__PURE__ */ jsx(ToastItem, { toast: t, onDismiss: removeToast }, t.id))
@@ -7753,13 +7864,21 @@ var Main = forwardRef(function Main2({ className, ...props }, ref) {
7753
7864
  );
7754
7865
  });
7755
7866
  Main.displayName = "Main";
7756
- var Content15 = forwardRef(function Content16({ padBottom, className, style, ...props }, ref) {
7867
+ var Content15 = forwardRef(function Content16({ padTop, padBottom, className, style, ...props }, ref) {
7868
+ const paddingStyle = padTop || padBottom ? {
7869
+ ...padTop ? { paddingTop: padTop } : null,
7870
+ ...padBottom ? { paddingBottom: padBottom } : null,
7871
+ ...style
7872
+ } : style;
7757
7873
  return /* @__PURE__ */ jsx(
7758
7874
  "div",
7759
7875
  {
7760
7876
  ref,
7877
+ role: "region",
7878
+ "aria-label": "Page content",
7879
+ tabIndex: 0,
7761
7880
  className: cn("flex-1 overflow-y-auto p-[var(--content-pad)]", className),
7762
- style: padBottom ? { paddingBottom: padBottom, ...style } : style,
7881
+ style: paddingStyle,
7763
7882
  ...props
7764
7883
  }
7765
7884
  );
@@ -8172,9 +8291,19 @@ var SidebarSection = React36.forwardRef(
8172
8291
  }
8173
8292
  );
8174
8293
  SidebarSection.displayName = "SidebarSection";
8294
+ function getTextContent(node) {
8295
+ if (node == null || typeof node === "boolean") return "";
8296
+ if (typeof node === "string" || typeof node === "number") return String(node);
8297
+ if (Array.isArray(node)) return node.map(getTextContent).filter(Boolean).join(" ");
8298
+ if (React36.isValidElement(node)) {
8299
+ return getTextContent(node.props.children);
8300
+ }
8301
+ return "";
8302
+ }
8175
8303
  var SidebarLink = React36.forwardRef(
8176
- function SidebarLink2({ href, icon, active = false, asChild, className, children, ...props }, ref) {
8304
+ function SidebarLink2({ href, icon, active = false, asChild, className, children, "aria-label": ariaLabel, ...props }, ref) {
8177
8305
  const Comp = asChild ? Slot : "a";
8306
+ const accessibleLabel = ariaLabel ?? (asChild ? void 0 : getTextContent(children) || void 0);
8178
8307
  return /* @__PURE__ */ jsx(
8179
8308
  Comp,
8180
8309
  {
@@ -8182,6 +8311,7 @@ var SidebarLink = React36.forwardRef(
8182
8311
  ...asChild ? {} : { href },
8183
8312
  "data-active": active ? "true" : void 0,
8184
8313
  "aria-current": active ? "page" : void 0,
8314
+ "aria-label": accessibleLabel,
8185
8315
  className: cn(
8186
8316
  "group/link relative mb-px flex items-center gap-2.5 rounded-md px-2.5 py-1.5",
8187
8317
  "text-fg-2 text-[13px] font-normal no-underline",
@@ -8381,6 +8511,7 @@ var SidebarLinkGroup = React36.forwardRef(
8381
8511
  href,
8382
8512
  "data-active": active ? "true" : void 0,
8383
8513
  "aria-current": active ? "page" : void 0,
8514
+ "aria-label": getTextContent(label) || void 0,
8384
8515
  onClick: handleBodyClick,
8385
8516
  className: bodyClassName,
8386
8517
  children: [
@@ -8875,11 +9006,21 @@ function Sparkline({ data, className }) {
8875
9006
  }
8876
9007
  );
8877
9008
  }
8878
- var KpiCard = forwardRef(function KpiCard2({ label, value, icon, tone = "muted", delta, trend, hint, action, toneValue, className, ...props }, ref) {
9009
+ function KpiCardBody({
9010
+ label,
9011
+ value,
9012
+ icon,
9013
+ tone = "muted",
9014
+ delta,
9015
+ trend,
9016
+ hint,
9017
+ action,
9018
+ toneValue
9019
+ }) {
8879
9020
  const deltaSentiment = delta ? delta.sentiment ?? directionToSentiment[delta.direction] : null;
8880
9021
  const DeltaIcon = delta ? directionToIcon[delta.direction] : null;
8881
9022
  const sparkColor = deltaSentiment ? sentimentText[deltaSentiment] : toneToValue[tone];
8882
- return /* @__PURE__ */ jsxs(Card, { ref, className: cn("p-4", className), ...props, children: [
9023
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
8883
9024
  /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
8884
9025
  icon && /* @__PURE__ */ jsx(
8885
9026
  "div",
@@ -8923,15 +9064,82 @@ var KpiCard = forwardRef(function KpiCard2({ label, value, icon, tone = "muted",
8923
9064
  )
8924
9065
  ] }),
8925
9066
  /* @__PURE__ */ jsx("p", { className: "text-fg-3 text-xs", children: label }),
8926
- delta?.label && /* @__PURE__ */ jsx("p", { className: "text-fg-4 mt-0.5 text-[11px]", children: delta.label }),
8927
- hint && /* @__PURE__ */ jsx("p", { className: "text-fg-4 mt-0.5 text-[11px]", children: hint })
9067
+ delta?.label && /* @__PURE__ */ jsx("p", { className: "text-fg-3 mt-0.5 text-[11px]", children: delta.label }),
9068
+ hint && /* @__PURE__ */ jsx("p", { className: "text-fg-3 mt-0.5 text-[11px]", children: hint })
8928
9069
  ] }),
8929
9070
  action && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action })
8930
9071
  ] }),
8931
9072
  trend && trend.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: trend, className: cn("mt-3", sparkColor) })
8932
9073
  ] });
9074
+ }
9075
+ var KpiCard = forwardRef(function KpiCard2({ label, value, icon, tone = "muted", delta, trend, hint, action, toneValue, className, ...props }, ref) {
9076
+ return /* @__PURE__ */ jsx(Card, { ref, className: cn("p-4", className), ...props, children: /* @__PURE__ */ jsx(
9077
+ KpiCardBody,
9078
+ {
9079
+ label,
9080
+ value,
9081
+ icon,
9082
+ tone,
9083
+ delta,
9084
+ trend,
9085
+ hint,
9086
+ action,
9087
+ toneValue
9088
+ }
9089
+ ) });
8933
9090
  });
8934
9091
  KpiCard.displayName = "KpiCard";
9092
+ var SelectableKpiCard = forwardRef(
9093
+ function SelectableKpiCard2({
9094
+ label,
9095
+ value,
9096
+ icon,
9097
+ tone = "muted",
9098
+ delta,
9099
+ trend,
9100
+ hint,
9101
+ action,
9102
+ toneValue,
9103
+ selected = false,
9104
+ className,
9105
+ type,
9106
+ ...props
9107
+ }, ref) {
9108
+ return /* @__PURE__ */ jsx(
9109
+ "button",
9110
+ {
9111
+ ref,
9112
+ type: type ?? "button",
9113
+ "aria-pressed": selected,
9114
+ "data-selected": selected ? "true" : "false",
9115
+ className: cn(
9116
+ cardVariants({ variant: "interactive" }),
9117
+ "block w-full p-4 text-left",
9118
+ "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
9119
+ "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-fg-disabled disabled:shadow-none",
9120
+ selected && "border-pro-fg/40 bg-pro-bg hover:bg-pro-bg-hover ring-1 ring-pro-fg/30",
9121
+ className
9122
+ ),
9123
+ ...props,
9124
+ children: /* @__PURE__ */ jsx(
9125
+ KpiCardBody,
9126
+ {
9127
+ label,
9128
+ value,
9129
+ icon,
9130
+ tone,
9131
+ delta,
9132
+ trend,
9133
+ hint,
9134
+ action,
9135
+ toneValue
9136
+ }
9137
+ )
9138
+ }
9139
+ );
9140
+ }
9141
+ );
9142
+ SelectableKpiCard.displayName = "SelectableKpiCard";
8935
9143
  var DataTable = forwardRef(function DataTable2({ withToolbar, className, children, ...props }, ref) {
8936
9144
  return /* @__PURE__ */ jsx(
8937
9145
  "div",
@@ -9394,7 +9602,21 @@ var ActivityEventItem = forwardRef(
9394
9602
  );
9395
9603
  ActivityEventItem.displayName = "ActivityEventItem";
9396
9604
  var Kanban = forwardRef(function Kanban2({ className, children, ...props }, ref) {
9397
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-start gap-4 overflow-x-auto", className), ...props, children });
9605
+ return /* @__PURE__ */ jsx(
9606
+ "div",
9607
+ {
9608
+ ref,
9609
+ role: "region",
9610
+ tabIndex: 0,
9611
+ "aria-label": "Kanban board",
9612
+ className: cn(
9613
+ "flex items-start gap-4 overflow-x-auto focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
9614
+ className
9615
+ ),
9616
+ ...props,
9617
+ children
9618
+ }
9619
+ );
9398
9620
  });
9399
9621
  Kanban.displayName = "Kanban";
9400
9622
  var KanbanColumn = forwardRef(function KanbanColumn2({ title, count, className, children, ...props }, ref) {
@@ -9803,6 +10025,511 @@ var NotificationItem = forwardRef(
9803
10025
  }
9804
10026
  );
9805
10027
  NotificationItem.displayName = "NotificationItem";
10028
+ var padded = (n) => String(n).padStart(2, "0");
10029
+ function formatClock(ms) {
10030
+ const total = Math.max(0, Math.floor(ms / 1e3));
10031
+ return `${Math.floor(total / 3600)}:${padded(Math.floor(total % 3600 / 60))}:${padded(total % 60)}`;
10032
+ }
10033
+ function formatDuration(totalSeconds) {
10034
+ const minutes = Math.round(totalSeconds / 60);
10035
+ const h = Math.floor(minutes / 60);
10036
+ const m = minutes % 60;
10037
+ if (h && m) return `${h}h ${m}m`;
10038
+ if (h) return `${h}h`;
10039
+ return `${m}m`;
10040
+ }
10041
+ function parseDuration(input) {
10042
+ const text = input.trim().toLowerCase();
10043
+ if (!text) return null;
10044
+ const clock = text.match(/^(\d{1,2}):(\d{2})$/);
10045
+ if (clock) return (Number(clock[1]) * 60 + Number(clock[2])) * 60;
10046
+ let seconds = 0;
10047
+ let matched = false;
10048
+ const unit = /(\d+(?:\.\d+)?)\s*(h|hr|hrs|hour|hours|m|min|mins|minute|minutes|s|sec|secs)/g;
10049
+ let part;
10050
+ while ((part = unit.exec(text)) !== null) {
10051
+ matched = true;
10052
+ const value = parseFloat(part[1]);
10053
+ if (part[2].startsWith("h")) seconds += value * 3600;
10054
+ else if (part[2].startsWith("m")) seconds += value * 60;
10055
+ else seconds += value;
10056
+ }
10057
+ if (!matched && /^\d+$/.test(text)) return Number(text) * 60;
10058
+ return matched ? Math.round(seconds) : null;
10059
+ }
10060
+ function formatCurrency(amount, currency = "USD") {
10061
+ try {
10062
+ return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
10063
+ } catch {
10064
+ return `$${amount.toFixed(2)}`;
10065
+ }
10066
+ }
10067
+ var TICK_MS = 250;
10068
+ function useStopwatch() {
10069
+ const [phase, setPhaseState] = useState("idle");
10070
+ const [elapsedMs, setElapsedMs] = useState(0);
10071
+ const accumulatedRef = useRef(0);
10072
+ const startedAtRef = useRef(0);
10073
+ const phaseRef = useRef("idle");
10074
+ const setPhase = useCallback((next) => {
10075
+ phaseRef.current = next;
10076
+ setPhaseState(next);
10077
+ }, []);
10078
+ useEffect(() => {
10079
+ if (phase !== "running") return;
10080
+ const id = setInterval(() => {
10081
+ setElapsedMs(accumulatedRef.current + (Date.now() - startedAtRef.current));
10082
+ }, TICK_MS);
10083
+ return () => clearInterval(id);
10084
+ }, [phase]);
10085
+ const start = useCallback(
10086
+ (fromMs = 0) => {
10087
+ accumulatedRef.current = fromMs;
10088
+ startedAtRef.current = Date.now();
10089
+ setElapsedMs(fromMs);
10090
+ setPhase("running");
10091
+ },
10092
+ [setPhase]
10093
+ );
10094
+ const pause = useCallback(() => {
10095
+ if (phaseRef.current !== "running") return;
10096
+ accumulatedRef.current += Date.now() - startedAtRef.current;
10097
+ setElapsedMs(accumulatedRef.current);
10098
+ setPhase("paused");
10099
+ }, [setPhase]);
10100
+ const resume = useCallback(() => {
10101
+ if (phaseRef.current !== "paused") return;
10102
+ startedAtRef.current = Date.now();
10103
+ setPhase("running");
10104
+ }, [setPhase]);
10105
+ const stop = useCallback(() => {
10106
+ if (phaseRef.current === "idle") return;
10107
+ if (phaseRef.current === "running") {
10108
+ accumulatedRef.current += Date.now() - startedAtRef.current;
10109
+ setElapsedMs(accumulatedRef.current);
10110
+ }
10111
+ setPhase("stopped");
10112
+ }, [setPhase]);
10113
+ const reset = useCallback(() => {
10114
+ accumulatedRef.current = 0;
10115
+ startedAtRef.current = 0;
10116
+ setElapsedMs(0);
10117
+ setPhase("idle");
10118
+ }, [setPhase]);
10119
+ return { phase, elapsedMs, isRunning: phase === "running", start, pause, resume, stop, reset };
10120
+ }
10121
+ var TimeLogger = forwardRef(function TimeLogger2({ className, children, ...props }, ref) {
10122
+ return /* @__PURE__ */ jsx(
10123
+ "div",
10124
+ {
10125
+ ref,
10126
+ className: cn("bg-surface text-fg-2 flex w-full flex-col", className),
10127
+ ...props,
10128
+ children
10129
+ }
10130
+ );
10131
+ });
10132
+ TimeLogger.displayName = "TimeLogger";
10133
+ var TimeLoggerHeader = forwardRef(
10134
+ function TimeLoggerHeader2({ title = "Track Time", icon, loggedMinutes = 0, goalMinutes, className, ...props }, ref) {
10135
+ const hasGoal = goalMinutes != null;
10136
+ const pct = hasGoal && goalMinutes > 0 ? Math.min(100, loggedMinutes / goalMinutes * 100) : 0;
10137
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col", className), ...props, children: [
10138
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [
10139
+ /* @__PURE__ */ jsxs("div", { className: "text-fg flex items-center gap-2 text-base font-semibold [&_svg]:size-[18px]", children: [
10140
+ /* @__PURE__ */ jsx("span", { className: "text-pro-fg", "aria-hidden": "true", children: icon ?? /* @__PURE__ */ jsx(ClockIcon, {}) }),
10141
+ title
10142
+ ] }),
10143
+ hasGoal && /* @__PURE__ */ jsxs("div", { className: "text-fg-3 font-mono text-[13px] tabular-nums", children: [
10144
+ /* @__PURE__ */ jsx("b", { className: "text-fg font-medium", children: formatDuration(loggedMinutes * 60) }),
10145
+ " /",
10146
+ " ",
10147
+ formatDuration(goalMinutes * 60)
10148
+ ] })
10149
+ ] }),
10150
+ hasGoal && /* @__PURE__ */ jsx(
10151
+ "div",
10152
+ {
10153
+ className: "bg-bg-3 relative h-[3px] w-full",
10154
+ role: "progressbar",
10155
+ "aria-label": "Daily goal progress",
10156
+ "aria-valuemin": 0,
10157
+ "aria-valuemax": goalMinutes,
10158
+ "aria-valuenow": Math.min(loggedMinutes, goalMinutes),
10159
+ children: /* @__PURE__ */ jsx(
10160
+ "div",
10161
+ {
10162
+ className: "bg-pro-fg h-full rounded-r-full transition-[width] duration-[var(--duration-normal)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
10163
+ style: { width: `${pct}%` }
10164
+ }
10165
+ )
10166
+ }
10167
+ )
10168
+ ] });
10169
+ }
10170
+ );
10171
+ TimeLoggerHeader.displayName = "TimeLoggerHeader";
10172
+ var TimeLoggerContextRow = forwardRef(
10173
+ function TimeLoggerContextRow2({ client, engagement, avatar, onClientSelect, member, className, ...props }, ref) {
10174
+ const text = /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
10175
+ /* @__PURE__ */ jsx("span", { className: "text-fg block truncate text-sm font-medium", children: client }),
10176
+ engagement && /* @__PURE__ */ jsx("span", { className: "text-fg-3 block truncate text-xs", children: engagement })
10177
+ ] });
10178
+ return /* @__PURE__ */ jsxs(
10179
+ "div",
10180
+ {
10181
+ ref,
10182
+ className: cn("border-rule-soft flex items-center gap-2.5 border-t px-4 py-2.5", className),
10183
+ ...props,
10184
+ children: [
10185
+ onClientSelect ? /* @__PURE__ */ jsxs(
10186
+ "button",
10187
+ {
10188
+ type: "button",
10189
+ onClick: onClientSelect,
10190
+ className: "rounded-btn hover:bg-surface-2 focus-visible:bg-surface-2 -m-1 flex min-w-0 flex-1 items-center gap-2.5 p-1 text-left transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)] motion-reduce:transition-none",
10191
+ children: [
10192
+ avatar,
10193
+ text
10194
+ ]
10195
+ }
10196
+ ) : /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
10197
+ avatar,
10198
+ text
10199
+ ] }),
10200
+ member && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: member })
10201
+ ]
10202
+ }
10203
+ );
10204
+ }
10205
+ );
10206
+ TimeLoggerContextRow.displayName = "TimeLoggerContextRow";
10207
+ var TimeLoggerTimer = forwardRef(
10208
+ function TimeLoggerTimer2({
10209
+ phase,
10210
+ elapsedMs,
10211
+ value,
10212
+ onValueChange,
10213
+ placeholder = "Enter time (ex: 3h 20m) or start timer",
10214
+ onStart,
10215
+ onPause,
10216
+ onResume,
10217
+ onStop,
10218
+ className,
10219
+ ...props
10220
+ }, ref) {
10221
+ const showClock = phase !== "idle";
10222
+ const canStop = phase === "running" || phase === "paused";
10223
+ return /* @__PURE__ */ jsxs(
10224
+ "div",
10225
+ {
10226
+ ref,
10227
+ className: cn("border-rule-soft flex items-center gap-2 border-t px-4 py-2.5", className),
10228
+ ...props,
10229
+ children: [
10230
+ /* @__PURE__ */ jsx(
10231
+ "input",
10232
+ {
10233
+ className: cn(
10234
+ "text-fg placeholder:text-fg-4 min-w-0 flex-1 border-0 bg-transparent outline-none",
10235
+ showClock ? "font-mono text-[22px] font-medium tracking-tight tabular-nums" : "text-[15px]"
10236
+ ),
10237
+ value: showClock ? formatClock(elapsedMs) : value ?? "",
10238
+ onChange: (event) => onValueChange?.(event.target.value),
10239
+ placeholder,
10240
+ readOnly: showClock,
10241
+ "aria-label": "Tracked time"
10242
+ }
10243
+ ),
10244
+ /* @__PURE__ */ jsx(
10245
+ Button,
10246
+ {
10247
+ type: "button",
10248
+ variant: "secondary",
10249
+ size: "icon",
10250
+ className: "rounded-full",
10251
+ "aria-label": phase === "paused" ? "Resume timer" : "Pause timer",
10252
+ disabled: phase === "idle" || phase === "stopped",
10253
+ onClick: phase === "paused" ? onResume : onPause,
10254
+ children: phase === "paused" ? /* @__PURE__ */ jsx(PlayIcon, {}) : /* @__PURE__ */ jsx(PauseIcon, {})
10255
+ }
10256
+ ),
10257
+ canStop ? /* @__PURE__ */ jsx(
10258
+ Button,
10259
+ {
10260
+ type: "button",
10261
+ variant: "destructive",
10262
+ size: "icon",
10263
+ className: "rounded-full",
10264
+ "aria-label": "Stop timer",
10265
+ onClick: onStop,
10266
+ children: /* @__PURE__ */ jsx(StopIcon, {})
10267
+ }
10268
+ ) : /* @__PURE__ */ jsx(
10269
+ Button,
10270
+ {
10271
+ type: "button",
10272
+ variant: "primary",
10273
+ size: "icon",
10274
+ className: "rounded-full",
10275
+ "aria-label": "Start timer",
10276
+ onClick: onStart,
10277
+ children: /* @__PURE__ */ jsx(PlayIcon, {})
10278
+ }
10279
+ )
10280
+ ]
10281
+ }
10282
+ );
10283
+ }
10284
+ );
10285
+ TimeLoggerTimer.displayName = "TimeLoggerTimer";
10286
+ var TimeLoggerField = forwardRef(
10287
+ function TimeLoggerField2({ icon, label, onSelect, trailing, muted, className, children, ...props }, ref) {
10288
+ const interactive = Boolean(onSelect);
10289
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
10290
+ icon && /* @__PURE__ */ jsx(
10291
+ "span",
10292
+ {
10293
+ className: "text-fg-4 flex size-[17px] shrink-0 items-center justify-center [&_svg]:size-[17px]",
10294
+ "aria-hidden": "true",
10295
+ children: icon
10296
+ }
10297
+ ),
10298
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
10299
+ label && /* @__PURE__ */ jsx("span", { className: "text-fg-3 block text-[11px] leading-tight", children: label }),
10300
+ /* @__PURE__ */ jsx("span", { className: cn("block truncate", muted ? "text-fg-3" : "text-fg-2"), children })
10301
+ ] }),
10302
+ trailing !== void 0 ? trailing : interactive ? /* @__PURE__ */ jsx(ChevronRightIcon, { className: "text-fg-4 size-4 shrink-0" }) : null
10303
+ ] });
10304
+ const classes = cn(
10305
+ "border-rule-soft flex w-full items-center gap-3 border-t px-4 py-2.5 text-left",
10306
+ interactive && "hover:bg-surface-2 focus-visible:bg-surface-2 cursor-pointer transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] outline-none motion-reduce:transition-none",
10307
+ className
10308
+ );
10309
+ if (interactive) {
10310
+ return /* @__PURE__ */ jsx(
10311
+ "button",
10312
+ {
10313
+ ref,
10314
+ type: "button",
10315
+ onClick: onSelect,
10316
+ className: classes,
10317
+ ...props,
10318
+ children: inner
10319
+ }
10320
+ );
10321
+ }
10322
+ return /* @__PURE__ */ jsx("div", { ref, className: classes, ...props, children: inner });
10323
+ }
10324
+ );
10325
+ TimeLoggerField.displayName = "TimeLoggerField";
10326
+ var TimeLoggerNotes = forwardRef(
10327
+ function TimeLoggerNotes2({ value, onValueChange, icon, placeholder = "Add notes", className, ...props }, ref) {
10328
+ return /* @__PURE__ */ jsxs("div", { className: "border-rule-soft flex items-center gap-3 border-t px-4 py-2.5", children: [
10329
+ /* @__PURE__ */ jsx(
10330
+ "span",
10331
+ {
10332
+ className: "text-fg-4 flex size-[17px] shrink-0 items-center justify-center [&_svg]:size-[17px]",
10333
+ "aria-hidden": "true",
10334
+ children: icon ?? /* @__PURE__ */ jsx(FileTextIcon, {})
10335
+ }
10336
+ ),
10337
+ /* @__PURE__ */ jsx(
10338
+ "input",
10339
+ {
10340
+ ref,
10341
+ type: "text",
10342
+ value: value ?? "",
10343
+ onChange: (event) => onValueChange?.(event.target.value),
10344
+ placeholder,
10345
+ "aria-label": "Notes",
10346
+ className: cn(
10347
+ "text-fg placeholder:text-fg-4 min-w-0 flex-1 border-0 bg-transparent text-sm outline-none",
10348
+ className
10349
+ ),
10350
+ ...props
10351
+ }
10352
+ )
10353
+ ] });
10354
+ }
10355
+ );
10356
+ TimeLoggerNotes.displayName = "TimeLoggerNotes";
10357
+ var TimeLoggerBillable = forwardRef(
10358
+ function TimeLoggerBillable2({
10359
+ billable,
10360
+ onBillableChange,
10361
+ label,
10362
+ tiers,
10363
+ tierId,
10364
+ onTierChange,
10365
+ currency = "USD",
10366
+ amount,
10367
+ className,
10368
+ ...props
10369
+ }, ref) {
10370
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex min-w-0 items-center gap-2.5", className), ...props, children: [
10371
+ /* @__PURE__ */ jsx(
10372
+ Switch,
10373
+ {
10374
+ size: "sm",
10375
+ checked: billable,
10376
+ onCheckedChange: onBillableChange,
10377
+ "aria-label": "Billable"
10378
+ }
10379
+ ),
10380
+ /* @__PURE__ */ jsx("span", { className: "text-fg-3 text-[13px] whitespace-nowrap", children: label ?? (billable ? "Billable" : "Non-billable") }),
10381
+ tiers && tiers.length > 0 && /* @__PURE__ */ jsxs(Popover, { children: [
10382
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
10383
+ "button",
10384
+ {
10385
+ type: "button",
10386
+ "aria-label": "Billing settings",
10387
+ className: "text-fg-4 hover:text-fg-2 hover:bg-bg-2 rounded-btn flex size-6 items-center justify-center transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)] motion-reduce:transition-none [&_svg]:size-4",
10388
+ children: /* @__PURE__ */ jsx(SettingsIcon, {})
10389
+ }
10390
+ ) }),
10391
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "start", side: "top", className: "w-56 p-1.5", children: [
10392
+ /* @__PURE__ */ jsxs("p", { className: "text-fg-3 px-2 pt-1 pb-1.5 font-mono text-[10px] tracking-wider uppercase", children: [
10393
+ "Pricing tier \xB7 ",
10394
+ currency
10395
+ ] }),
10396
+ tiers.map((tier) => {
10397
+ const selected = tier.id === tierId;
10398
+ return /* @__PURE__ */ jsx(PopoverClose, { asChild: true, children: /* @__PURE__ */ jsxs(
10399
+ "button",
10400
+ {
10401
+ type: "button",
10402
+ onClick: () => onTierChange?.(tier.id),
10403
+ className: "hover:bg-surface-2 flex w-full items-center gap-2 rounded-md px-2 py-2 text-left transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)] motion-reduce:transition-none",
10404
+ children: [
10405
+ /* @__PURE__ */ jsx(
10406
+ "span",
10407
+ {
10408
+ className: cn(
10409
+ "flex-1 truncate text-[13px]",
10410
+ selected ? "text-pro-fg font-medium" : "text-fg"
10411
+ ),
10412
+ children: tier.name
10413
+ }
10414
+ ),
10415
+ /* @__PURE__ */ jsxs("span", { className: "text-fg-3 font-mono text-[12.5px] tabular-nums", children: [
10416
+ formatCurrency(tier.rate, currency),
10417
+ "/hr"
10418
+ ] }),
10419
+ /* @__PURE__ */ jsx(
10420
+ CheckIcon,
10421
+ {
10422
+ className: cn(
10423
+ "text-pro-fg size-4 shrink-0",
10424
+ selected ? "opacity-100" : "opacity-0"
10425
+ )
10426
+ }
10427
+ )
10428
+ ]
10429
+ }
10430
+ ) }, tier.id);
10431
+ })
10432
+ ] })
10433
+ ] }),
10434
+ amount != null && /* @__PURE__ */ jsx("span", { className: "text-fg-2 font-mono text-[12.5px] font-medium tabular-nums", children: amount })
10435
+ ] });
10436
+ }
10437
+ );
10438
+ TimeLoggerBillable.displayName = "TimeLoggerBillable";
10439
+ var TimeLoggerActions = forwardRef(
10440
+ function TimeLoggerActions2({ className, children, ...props }, ref) {
10441
+ return /* @__PURE__ */ jsx(
10442
+ "div",
10443
+ {
10444
+ ref,
10445
+ className: cn(
10446
+ "border-rule bg-surface-2 flex items-center gap-2 border-t px-4 py-2.5",
10447
+ className
10448
+ ),
10449
+ ...props,
10450
+ children
10451
+ }
10452
+ );
10453
+ }
10454
+ );
10455
+ TimeLoggerActions.displayName = "TimeLoggerActions";
10456
+ var TimeLoggerEntryList = forwardRef(
10457
+ function TimeLoggerEntryList2({ dayLabel, total, className, children, ...props }, ref) {
10458
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("border-bg-2 border-t-[7px]", className), ...props, children: [
10459
+ (dayLabel || total) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 pt-2.5 pb-1 text-xs", children: [
10460
+ dayLabel && /* @__PURE__ */ jsx("span", { className: "text-fg-3 font-medium", children: dayLabel }),
10461
+ total && /* @__PURE__ */ jsx("span", { className: "text-fg-2 font-mono tabular-nums", children: total })
10462
+ ] }),
10463
+ children
10464
+ ] });
10465
+ }
10466
+ );
10467
+ TimeLoggerEntryList.displayName = "TimeLoggerEntryList";
10468
+ var TimeLoggerEntry = forwardRef(
10469
+ function TimeLoggerEntry2({ title, meta, duration, onResume, onDelete, className, ...props }, ref) {
10470
+ return /* @__PURE__ */ jsxs(
10471
+ "div",
10472
+ {
10473
+ ref,
10474
+ className: cn("border-rule-soft flex items-center gap-3 border-t px-4 py-2", className),
10475
+ ...props,
10476
+ children: [
10477
+ /* @__PURE__ */ jsx(
10478
+ "span",
10479
+ {
10480
+ "aria-hidden": "true",
10481
+ className: "border-pro-fg size-[15px] shrink-0 rounded-full border-[1.5px] shadow-[inset_0_0_0_3px_var(--color-pro-fg)]"
10482
+ }
10483
+ ),
10484
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
10485
+ /* @__PURE__ */ jsx("p", { className: "text-fg truncate text-[13px]", children: title }),
10486
+ meta && /* @__PURE__ */ jsx("p", { className: "text-fg-3 truncate text-[11.5px]", children: meta })
10487
+ ] }),
10488
+ /* @__PURE__ */ jsx("span", { className: "text-fg-2 font-mono text-[13px] tabular-nums", children: duration }),
10489
+ onResume && /* @__PURE__ */ jsx(
10490
+ Button,
10491
+ {
10492
+ type: "button",
10493
+ variant: "ghost",
10494
+ size: "icon-sm",
10495
+ className: "text-fg-3 hover:text-pro-fg hover:bg-pro-bg rounded-full",
10496
+ "aria-label": "Resume entry",
10497
+ onClick: onResume,
10498
+ children: /* @__PURE__ */ jsx(PlayIcon, {})
10499
+ }
10500
+ ),
10501
+ onDelete && /* @__PURE__ */ jsx(
10502
+ Button,
10503
+ {
10504
+ type: "button",
10505
+ variant: "ghost",
10506
+ size: "icon-sm",
10507
+ className: "text-fg-3 hover:text-danger-fg hover:bg-danger-bg rounded-full",
10508
+ "aria-label": "Delete entry",
10509
+ onClick: onDelete,
10510
+ children: /* @__PURE__ */ jsx(Trash2Icon, {})
10511
+ }
10512
+ )
10513
+ ]
10514
+ }
10515
+ );
10516
+ }
10517
+ );
10518
+ TimeLoggerEntry.displayName = "TimeLoggerEntry";
10519
+ var TimeLoggerFooter = forwardRef(
10520
+ function TimeLoggerFooter2({ className, children, ...props }, ref) {
10521
+ return /* @__PURE__ */ jsx(
10522
+ "div",
10523
+ {
10524
+ ref,
10525
+ className: cn("border-rule flex gap-2 border-t px-4 py-2.5 [&>*]:flex-1", className),
10526
+ ...props,
10527
+ children
10528
+ }
10529
+ );
10530
+ }
10531
+ );
10532
+ TimeLoggerFooter.displayName = "TimeLoggerFooter";
9806
10533
  var Toolbar = forwardRef(function Toolbar2({ className, children, ...props }, ref) {
9807
10534
  return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center gap-2", className), ...props, children });
9808
10535
  });
@@ -9852,6 +10579,151 @@ var FilterChip = forwardRef(function FilterChip2({ active = false, size, count,
9852
10579
  );
9853
10580
  });
9854
10581
  FilterChip.displayName = "FilterChip";
10582
+ var BulkActionBarContext = React36.createContext({ tone: "surface" });
10583
+ function actionClasses(tone, destructive) {
10584
+ const base = cn(
10585
+ "inline-flex h-8 items-center gap-1.5 rounded-btn px-3 text-[13px] font-medium",
10586
+ "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
10587
+ "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
10588
+ "disabled:pointer-events-none disabled:opacity-45",
10589
+ "motion-reduce:transition-none",
10590
+ "[&_svg]:size-4 [&_svg]:shrink-0"
10591
+ );
10592
+ if (tone === "inverse") {
10593
+ return cn(
10594
+ base,
10595
+ "data-[state=open]:bg-selection-floating-active-bg",
10596
+ destructive ? "bg-danger-fg text-fg-on-danger hover:bg-danger-fg-hover active:bg-danger-fg-active" : "text-selection-floating-muted-fg hover:bg-selection-floating-hover-bg hover:text-selection-floating-fg"
10597
+ );
10598
+ }
10599
+ return cn(
10600
+ base,
10601
+ "data-[state=open]:bg-control-active-bg",
10602
+ destructive ? "text-control-destructive-fg hover:bg-control-destructive-hover-bg" : "text-control-fg hover:bg-control-hover-bg hover:text-control-hover-fg"
10603
+ );
10604
+ }
10605
+ var BulkActionBarAction = React36.forwardRef(function BulkActionBarAction2({ asChild = false, destructive, className, type, ...props }, ref) {
10606
+ const { tone } = React36.use(BulkActionBarContext);
10607
+ const Comp = asChild ? Slot : "button";
10608
+ return /* @__PURE__ */ jsx(
10609
+ Comp,
10610
+ {
10611
+ ref,
10612
+ type: asChild ? void 0 : type ?? "button",
10613
+ className: cn(actionClasses(tone, destructive), className),
10614
+ ...props
10615
+ }
10616
+ );
10617
+ });
10618
+ BulkActionBarAction.displayName = "BulkActionBarAction";
10619
+ function BulkActionBarSeparator({ className }) {
10620
+ const { tone } = React36.use(BulkActionBarContext);
10621
+ return /* @__PURE__ */ jsx(
10622
+ "span",
10623
+ {
10624
+ "aria-hidden": "true",
10625
+ className: cn(
10626
+ "h-4 w-px shrink-0",
10627
+ tone === "inverse" ? "bg-selection-floating-rule" : "bg-control-border",
10628
+ className
10629
+ )
10630
+ }
10631
+ );
10632
+ }
10633
+ function BulkActionBarClear({
10634
+ variant,
10635
+ clearLabel,
10636
+ clearDisabled,
10637
+ onClear
10638
+ }) {
10639
+ if (variant === "page-floating") {
10640
+ return /* @__PURE__ */ jsx(
10641
+ "button",
10642
+ {
10643
+ type: "button",
10644
+ onClick: onClear,
10645
+ disabled: clearDisabled,
10646
+ className: cn(
10647
+ "text-selection-floating-muted-fg ml-1 inline-flex size-7 items-center justify-center rounded-icon",
10648
+ "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
10649
+ "hover:bg-selection-floating-hover-bg hover:text-selection-floating-fg",
10650
+ "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
10651
+ "disabled:pointer-events-none disabled:opacity-45 motion-reduce:transition-none"
10652
+ ),
10653
+ "aria-label": clearLabel,
10654
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-4", "aria-hidden": "true" })
10655
+ }
10656
+ );
10657
+ }
10658
+ return /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClear, disabled: clearDisabled, children: clearLabel });
10659
+ }
10660
+ function BulkActionBar({
10661
+ variant = "table-inline",
10662
+ selectedCount,
10663
+ label,
10664
+ children,
10665
+ onClear,
10666
+ clearLabel = "Clear selection",
10667
+ clearDisabled,
10668
+ footer,
10669
+ className,
10670
+ ...props
10671
+ }) {
10672
+ if (selectedCount === 0) return null;
10673
+ const labelText = label ?? `${selectedCount} selected`;
10674
+ const tone = variant === "page-floating" ? "inverse" : "surface";
10675
+ const content = /* @__PURE__ */ jsxs(BulkActionBarContext, { value: { tone }, children: [
10676
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tabular-nums", children: labelText }),
10677
+ /* @__PURE__ */ jsx(BulkActionBarSeparator, {}),
10678
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1", children }),
10679
+ /* @__PURE__ */ jsx("div", { className: "min-w-2 flex-1" }),
10680
+ /* @__PURE__ */ jsx(
10681
+ BulkActionBarClear,
10682
+ {
10683
+ variant,
10684
+ clearLabel,
10685
+ clearDisabled,
10686
+ onClear
10687
+ }
10688
+ )
10689
+ ] });
10690
+ if (variant === "sidebar-anchored") {
10691
+ return /* @__PURE__ */ jsxs(
10692
+ "div",
10693
+ {
10694
+ className: cn(
10695
+ "fixed right-6 bottom-6 left-[calc(var(--shell-sidebar-w)+1.5rem)] z-[var(--z-sticky)]",
10696
+ className
10697
+ ),
10698
+ ...props,
10699
+ children: [
10700
+ /* @__PURE__ */ jsx("div", { className: "border-rule bg-surface text-fg flex items-center gap-3 rounded-card border px-6 py-3 shadow-card", children: content }),
10701
+ footer
10702
+ ]
10703
+ }
10704
+ );
10705
+ }
10706
+ if (variant === "page-floating") {
10707
+ return /* @__PURE__ */ jsxs(
10708
+ "div",
10709
+ {
10710
+ className: cn(
10711
+ "fixed bottom-4 left-1/2 z-[var(--z-sticky)] -translate-x-1/2",
10712
+ className
10713
+ ),
10714
+ ...props,
10715
+ children: [
10716
+ /* @__PURE__ */ jsx("div", { className: "bg-selection-floating-bg text-selection-floating-fg flex items-center gap-2 rounded-card px-3.5 py-1.5 shadow-pop", children: content }),
10717
+ footer
10718
+ ]
10719
+ }
10720
+ );
10721
+ }
10722
+ return /* @__PURE__ */ jsxs("div", { className: cn("sticky bottom-4 z-[var(--z-sticky)] mt-3", className), ...props, children: [
10723
+ /* @__PURE__ */ jsx("div", { className: "border-rule bg-surface mx-auto flex max-w-3xl flex-wrap items-center gap-3 rounded-full border px-4 py-2 shadow-card", children: content }),
10724
+ footer
10725
+ ] });
10726
+ }
9855
10727
  var PrimaryAction = forwardRef(
9856
10728
  function PrimaryAction2({ arrow, iconRight, children, className, ...props }, ref) {
9857
10729
  return /* @__PURE__ */ jsx(
@@ -9938,6 +10810,6 @@ var KbdHint = forwardRef(function KbdHint2({ className, children, ...props }, re
9938
10810
  });
9939
10811
  KbdHint.displayName = "KbdHint";
9940
10812
 
9941
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityEventItem, ActivityItem, ActivityList, Alert, AlertCircleIcon, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AlertTriangleIcon, AlertTriangleSolidIcon, AppHeader, AppHeaderActions, AppHeaderBreadcrumb, AppHeaderSearch, AppHeaderTitle, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowRightSmallIcon, ArrowUpIcon, AspectRatio, AssureAuditBrandIcon, AssureBooksBrandIcon, AssureProBrandIcon, AssureTaxBrandIcon, AtSignIcon, Avatar, Badge, BarChartIcon, BellIcon, Blockquote, BoldIcon, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BriefcaseIcon, Building2Icon, BuildingIcon, Button, Calendar, CalendarIcon, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatBubbleIcon, CheckCircle2Icon, CheckCircleSolidIcon, CheckIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsUpDownIcon, CircleDotIcon, CircleIcon, ClientSelect, ClipboardCheckIcon, ClockIcon, CloseIcon, Collapsible, CollapsibleContent, CollapsibleTrigger, ComingSoon, CommandIcon, CommandPalette, ConfirmActionButton, Content15 as Content, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, CopyIcon, CornerDownLeftIcon, CreditCardIcon, DATE_DISPLAY_PLACEHOLDER, DangerAction, DataItem, DataTable, DataTableBody, DataTableCell, DataTableCellDue, DataTableCellId, DataTableCellMono, DataTableCellName, DataTableCheckbox, DataTableHead, DataTableHeader, DataTablePagination, DataTableResultsCount, DataTableRow, DataTableSearch, DataTableSpacer, DataTableToolbar, DatePicker, DateRangePicker, DetailGrid, DetailMain, DetailSpine, DetailSpineHeader, DetailSpineSection, DetailSpineStats, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DismissibleChip, DocumentIcon, DollarSignIcon, DownloadIcon, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EyeIcon, EyeOffIcon, Eyebrow, FileIcon, FileReturnIcon, FileTextIcon, FileUpload, FilterChip, FilterIcon, FlagIcon, FolderClosedIcon, FolderOpenIcon, FolderPlusIcon, FormError, FormSection, FormSuccess, GlobeIcon, GoogleBrandIcon, HelpCircleIcon, HistoryIcon, HomeIcon, HoverCard, HoverCardContent, HoverCardPortal, HoverCardTrigger, IconAction, InboxIcon, InfoCircleSolidIcon, InfoIcon, Input, ItalicIcon, Kanban, KanbanCard, KanbanColumn, KanbanIcon, KbdHint, KeyIcon, KeyboardShortcutsDialog, KpiCard, Label4 as Label, LayoutDashboardIcon, LayoutGridIcon, LayoutListIcon, LightningIcon, Link2Icon, LinkAction, LinkButton, LinkIcon, ListChecksIcon, ListIcon, ListOrderedIcon, LoaderIcon, LoadingRows, LockIcon, LockKeyholeIcon, LockOpenIcon, LogOutIcon, Logo, MailIcon, Main, MapPinIcon, MenuIcon, MessageBubble, MessageBubbleAction, MessageBubbleTombstone, MessageCircleIcon, MessageCircleWarningIcon, MessageComposer, MetadataGrid, MicrosoftBrandIcon, MinusIcon, MonitorIcon, MoonIcon, MoreHorizontalIcon, MoveIcon, MultiFilterPill, MultiSelectField, MutedSpec, NotificationFilter, NotificationItem, NotificationList, NotificationPanel, NotificationPanelHeader, Numeric, OTPInput, PageHeader, PageHeaderSep, PageHeaderSpec, Pagination, PaletteIcon, PanelLeftCloseIcon, PanelLeftIcon, PaperclipIcon, PenSignIcon, PencilIcon, PhoneIcon, PhoneInput, PlusIcon, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverPortal, PopoverTrigger, PrimaryAction, PriorityIcon, ProgressBar, ProgressRing, RadioGroup3 as RadioGroup, RadioGroupItem, ReceiptIcon, ReplyIcon, RotateCcwIcon, SaveIcon, ScrollArea, ScrollBar, SearchIcon, SearchInput, SearchSelect, SecondaryAction, Section, SectionHead, SectionHeader, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SendIcon, Separator4 as Separator, SettingsIcon, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Shell, ShieldIcon, SideDrawer, Sidebar, SidebarBrand, SidebarBrandSwitcher, SidebarBrandSwitcherTile, SidebarBrandText, SidebarFooter, SidebarLink, SidebarLinkAction, SidebarLinkBadge, SidebarLinkGroup, SidebarLinkLabel, SidebarPinButton, SidebarProvider, SidebarSection, SidebarTrigger, SidebarUser, Skeleton, SkeletonCircle, SkeletonText, SlashIcon, Slider, SmartphoneIcon, SparkleIcon, SparklesIcon, StarIcon, StarRating, Stat, StatusIcon, Stepper, StrikethroughIcon, SubmitButton, SunIcon, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableIcon, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagIcon, TeamIcon, TeamMemberSelect, Textarea, ToastProvider, ToggleGroup, ToggleGroupItem, Toolbar, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, Trash2Icon, TrashIcon, TrendingDownIcon, TrendingUpIcon, UnderlineIcon, UploadIcon, UserCircleIcon, UserIcon, UsersIcon, VisuallyHidden, WorkflowIcon, XCircleSolidIcon, XIcon, YEAR_DISPLAY_PLACEHOLDER, ZoomInIcon, ZoomOutIcon, alertVariants, applyMask, applyYearMask, badgeVariants, buttonVariants, cardVariants, cn, colors, dateToIso, displayToIso, filterChipVariants, inputVariants, isoToDate, isoToDisplay, isoToYear, labelVariants, progressBarVariants, progressRingVariants, radii, reference, searchInputVariants, shadows, sidebarLinkBadgeVariants, spacing, starRatingVariants, surfaces, systemTokens, textareaVariants, typography, useSidebarPeekLock, useSidebarState, useToast, yearToIso };
10813
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityEventItem, ActivityItem, ActivityList, Alert, AlertCircleIcon, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AlertTriangleIcon, AlertTriangleSolidIcon, AppHeader, AppHeaderActions, AppHeaderBreadcrumb, AppHeaderSearch, AppHeaderTitle, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowRightSmallIcon, ArrowUpIcon, AspectRatio, AssureAuditBrandIcon, AssureBooksBrandIcon, AssureProBrandIcon, AssureTaxBrandIcon, AtSignIcon, Avatar, Badge, BarChartIcon, BellIcon, Blockquote, BoldIcon, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BriefcaseIcon, Building2Icon, BuildingIcon, BulkActionBar, BulkActionBarAction, BulkActionBarSeparator, Button, Calendar, CalendarIcon, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatBubbleIcon, CheckCircle2Icon, CheckCircleSolidIcon, CheckIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsUpDownIcon, CircleDotIcon, CircleIcon, ClientSelect, ClipboardCheckIcon, ClockIcon, CloseIcon, Collapsible, CollapsibleContent, CollapsibleTrigger, ComingSoon, CommandIcon, CommandPalette, ConfirmActionButton, Content15 as Content, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, CopyIcon, CornerDownLeftIcon, CreditCardIcon, DATE_DISPLAY_PLACEHOLDER, DangerAction, DataItem, DataTable, DataTableBody, DataTableCell, DataTableCellDue, DataTableCellId, DataTableCellMono, DataTableCellName, DataTableCheckbox, DataTableHead, DataTableHeader, DataTablePagination, DataTableResultsCount, DataTableRow, DataTableSearch, DataTableSpacer, DataTableToolbar, DatePicker, DateRangePicker, DetailGrid, DetailMain, DetailSpine, DetailSpineHeader, DetailSpineSection, DetailSpineStats, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DismissibleChip, DocumentIcon, DollarSignIcon, DownloadIcon, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EyeIcon, EyeOffIcon, Eyebrow, FileIcon, FileReturnIcon, FileTextIcon, FileUpload, FilterChip, FilterIcon, FlagIcon, FolderClosedIcon, FolderOpenIcon, FolderPlusIcon, FormError, FormSection, FormSuccess, GlobeIcon, GoogleBrandIcon, HelpCircleIcon, HistoryIcon, HomeIcon, HoverCard, HoverCardContent, HoverCardPortal, HoverCardTrigger, IconAction, InboxIcon, InfoCircleSolidIcon, InfoIcon, Input, ItalicIcon, Kanban, KanbanCard, KanbanColumn, KanbanIcon, KbdHint, KeyIcon, KeyboardShortcutsDialog, KpiCard, Label4 as Label, LayoutDashboardIcon, LayoutGridIcon, LayoutListIcon, LightningIcon, Link2Icon, LinkAction, LinkButton, LinkIcon, ListChecksIcon, ListIcon, ListOrderedIcon, LoaderIcon, LoadingRows, LockIcon, LockKeyholeIcon, LockOpenIcon, LogOutIcon, Logo, MailIcon, Main, MapPinIcon, MenuIcon, MessageBubble, MessageBubbleAction, MessageBubbleTombstone, MessageCircleIcon, MessageCircleWarningIcon, MessageComposer, MetadataGrid, MicrosoftBrandIcon, MinusIcon, MonitorIcon, MoonIcon, MoreHorizontalIcon, MoveIcon, MultiFilterPill, MultiSelectField, MutedSpec, NotificationFilter, NotificationItem, NotificationList, NotificationPanel, NotificationPanelHeader, Numeric, OTPInput, PageHeader, PageHeaderSep, PageHeaderSpec, Pagination, PaletteIcon, PanelLeftCloseIcon, PanelLeftIcon, PaperclipIcon, PauseIcon, PenSignIcon, PencilIcon, PhoneIcon, PhoneInput, PlayIcon, PlusIcon, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverPortal, PopoverTrigger, PrimaryAction, PriorityIcon, ProgressBar, ProgressRing, RadioGroup3 as RadioGroup, RadioGroupItem, ReceiptIcon, ReplyIcon, RotateCcwIcon, SaveIcon, ScrollArea, ScrollBar, SearchIcon, SearchInput, SearchSelect, SecondaryAction, Section, SectionHead, SectionHeader, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SelectableKpiCard, SendIcon, Separator4 as Separator, SettingsIcon, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Shell, ShieldIcon, SideDrawer, Sidebar, SidebarBrand, SidebarBrandSwitcher, SidebarBrandSwitcherTile, SidebarBrandText, SidebarFooter, SidebarLink, SidebarLinkAction, SidebarLinkBadge, SidebarLinkGroup, SidebarLinkLabel, SidebarPinButton, SidebarProvider, SidebarSection, SidebarTrigger, SidebarUser, Skeleton, SkeletonCircle, SkeletonText, SlashIcon, Slider, SmartphoneIcon, SparkleIcon, SparklesIcon, Spinner, StarIcon, StarRating, Stat, StatusIcon, Stepper, StopIcon, StrikethroughIcon, SubmitButton, SunIcon, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableIcon, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagIcon, TeamIcon, TeamMemberSelect, Textarea, TimeLogger, TimeLoggerActions, TimeLoggerBillable, TimeLoggerContextRow, TimeLoggerEntry, TimeLoggerEntryList, TimeLoggerField, TimeLoggerFooter, TimeLoggerHeader, TimeLoggerNotes, TimeLoggerTimer, ToastProvider, ToggleGroup, ToggleGroupItem, Toolbar, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger, Trash2Icon, TrashIcon, TrendingDownIcon, TrendingUpIcon, UnderlineIcon, UploadIcon, UserCircleIcon, UserIcon, UsersIcon, VisuallyHidden, WorkflowIcon, XCircleSolidIcon, XIcon, YEAR_DISPLAY_PLACEHOLDER, ZoomInIcon, ZoomOutIcon, alertVariants, applyMask, applyYearMask, badgeVariants, buttonVariants, cardVariants, cn, colors, dateToIso, displayToIso, filterChipVariants, formatClock, formatCurrency, formatDuration, inputVariants, isoToDate, isoToDisplay, isoToYear, labelVariants, parseDuration, progressBarVariants, progressRingVariants, radii, reference, searchInputVariants, shadows, sidebarLinkBadgeVariants, spacing, spinnerVariants, starRatingVariants, surfaces, systemTokens, textareaVariants, typography, useSidebarPeekLock, useSidebarState, useStopwatch, useToast, yearToIso };
9942
10814
  //# sourceMappingURL=index.js.map
9943
10815
  //# sourceMappingURL=index.js.map