@assure-one/design-system 0.14.0 → 0.15.1

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
  ]
@@ -5984,7 +6062,8 @@ function SearchSelect({
5984
6062
  closeOnSelect: closeOnSelectProp = false,
5985
6063
  showGroupCounts = false,
5986
6064
  onCreateNew,
5987
- createNewLabel = "Create new"
6065
+ createNewLabel = "Create new",
6066
+ descriptionVariant = "inline"
5988
6067
  }) {
5989
6068
  const isSingleMode = value !== void 0 || onValueChange !== void 0;
5990
6069
  const singleSelectedOption = React36.useMemo(
@@ -6070,8 +6149,21 @@ function SearchSelect({
6070
6149
  }
6071
6150
  }, [onCreate, trimmedSearch]);
6072
6151
  const inputRef = React36.useRef(null);
6152
+ const listboxId = React36.useId();
6153
+ const setInputRef = React36.useCallback((node) => {
6154
+ inputRef.current = node;
6155
+ node?.removeAttribute("aria-labelledby");
6156
+ node?.setAttribute("aria-controls", listboxId);
6157
+ node?.removeAttribute("aria-activedescendant");
6158
+ }, [listboxId]);
6073
6159
  const singleValue = closeOnSelect ? selected[0] ?? null : null;
6074
6160
  const showValue = singleValue !== null && !open;
6161
+ const popoverOpen = open && !disabled;
6162
+ React36.useEffect(() => {
6163
+ inputRef.current?.removeAttribute("aria-labelledby");
6164
+ inputRef.current?.setAttribute("aria-controls", listboxId);
6165
+ inputRef.current?.removeAttribute("aria-activedescendant");
6166
+ });
6075
6167
  React36.useEffect(() => {
6076
6168
  if (open && closeOnSelect) {
6077
6169
  const raf = requestAnimationFrame(() => inputRef.current?.focus());
@@ -6110,10 +6202,12 @@ function SearchSelect({
6110
6202
  },
6111
6203
  item.id
6112
6204
  )) }),
6113
- /* @__PURE__ */ jsx(Popover, { open: open && !disabled, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(
6205
+ !popoverOpen && /* @__PURE__ */ jsx("div", { id: listboxId, role: "listbox", hidden: true }),
6206
+ /* @__PURE__ */ jsx(Popover, { open: popoverOpen, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(
6114
6207
  Command,
6115
6208
  {
6116
6209
  shouldFilter: true,
6210
+ label: placeholder,
6117
6211
  className: "overflow-visible bg-transparent",
6118
6212
  onKeyDown: (e) => {
6119
6213
  if (e.key === "Escape") {
@@ -6140,7 +6234,7 @@ function SearchSelect({
6140
6234
  type: "button",
6141
6235
  onClick: () => !disabled && setOpen(true),
6142
6236
  disabled,
6143
- className: "flex h-full flex-1 items-center gap-2 text-left outline-none disabled:cursor-not-allowed",
6237
+ className: "flex h-full min-w-0 flex-1 items-center gap-2 text-left outline-none disabled:cursor-not-allowed",
6144
6238
  children: [
6145
6239
  singleValue.icon && /* @__PURE__ */ jsx(
6146
6240
  "span",
@@ -6153,7 +6247,15 @@ function SearchSelect({
6153
6247
  children: singleValue.icon
6154
6248
  }
6155
6249
  ),
6156
- /* @__PURE__ */ jsxs("span", { className: "text-fg flex-1 truncate text-[13px]", children: [
6250
+ descriptionVariant === "pill" && singleValue.description ? (
6251
+ // Pill variant: label truncates, description rides after it
6252
+ // as a discrete shrink-0 badge so dense metadata reads as a
6253
+ // tag instead of running into the label.
6254
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-[13px]", children: [
6255
+ /* @__PURE__ */ jsx("span", { className: "text-fg truncate", children: singleValue.label }),
6256
+ /* @__PURE__ */ jsx("span", { className: "rounded-pill border-rule bg-bg-2 text-fg-3 shrink-0 border px-1.5 py-0.5 text-[11px] leading-none", children: singleValue.description })
6257
+ ] })
6258
+ ) : /* @__PURE__ */ jsxs("span", { className: "text-fg min-w-0 flex-1 truncate text-[13px]", children: [
6157
6259
  singleValue.label,
6158
6260
  singleValue.description && /* @__PURE__ */ jsxs("span", { className: "text-fg-4", children: [
6159
6261
  " \xB7 ",
@@ -6210,7 +6312,7 @@ function SearchSelect({
6210
6312
  /* @__PURE__ */ jsx(
6211
6313
  Command.Input,
6212
6314
  {
6213
- ref: inputRef,
6315
+ ref: setInputRef,
6214
6316
  value: search,
6215
6317
  onValueChange: (v) => {
6216
6318
  setSearch(v);
@@ -6220,6 +6322,8 @@ function SearchSelect({
6220
6322
  if (!disabled) setOpen(true);
6221
6323
  },
6222
6324
  placeholder,
6325
+ "aria-label": placeholder,
6326
+ "aria-controls": listboxId,
6223
6327
  disabled,
6224
6328
  className: cn(
6225
6329
  "font-body text-fg flex-1 bg-transparent py-2 pr-3 pl-9 text-[13px] outline-none",
@@ -6268,6 +6372,7 @@ function SearchSelect({
6268
6372
  /* @__PURE__ */ jsxs(
6269
6373
  Command.List,
6270
6374
  {
6375
+ id: listboxId,
6271
6376
  className: cn(
6272
6377
  // No top padding: a sticky group heading pins at top-0, so any
6273
6378
  // top padding would leave a strip above it where the previous
@@ -6533,38 +6638,51 @@ var sheetVariants = cva(
6533
6638
  defaultVariants: { side: "right" }
6534
6639
  }
6535
6640
  );
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
- });
6641
+ var sheetWidthClasses = {
6642
+ sm: "w-[95vw] max-w-[95vw] sm:w-[420px]",
6643
+ md: "w-[95vw] max-w-[95vw] sm:w-[520px]",
6644
+ lg: "w-[95vw] max-w-[95vw] sm:w-[640px]",
6645
+ xl: "w-[95vw] max-w-[95vw] sm:w-[760px]",
6646
+ full: "w-full max-w-none"
6647
+ };
6648
+ var SheetContent = React36.forwardRef(
6649
+ ({ side, width = "default", customWidth, className, children, showCloseButton = true, style, ...props }, ref) => {
6650
+ const ctx = React36.use(SheetSideContext);
6651
+ const resolvedSide = side ?? ctx.side ?? "right";
6652
+ const supportsWidth = resolvedSide === "left" || resolvedSide === "right";
6653
+ const widthClass = supportsWidth && width !== "default" ? sheetWidthClasses[width] : null;
6654
+ const widthStyle = supportsWidth && customWidth ? { width: customWidth, maxWidth: "95vw", ...style } : style;
6655
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
6656
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
6657
+ /* @__PURE__ */ jsxs(
6658
+ DialogPrimitive.Content,
6659
+ {
6660
+ ref,
6661
+ className: cn(sheetVariants({ side: resolvedSide }), widthClass, className),
6662
+ style: widthStyle,
6663
+ ...props,
6664
+ children: [
6665
+ children,
6666
+ showCloseButton && /* @__PURE__ */ jsx(
6667
+ DialogPrimitive.Close,
6668
+ {
6669
+ className: cn(
6670
+ "absolute top-4 right-4 inline-flex size-7 items-center justify-center",
6671
+ "rounded-icon text-fg-4 transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
6672
+ "hover:bg-overlay-hover hover:text-fg",
6673
+ "focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
6674
+ "disabled:pointer-events-none"
6675
+ ),
6676
+ "aria-label": "Close",
6677
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-4", "aria-hidden": "true" })
6678
+ }
6679
+ )
6680
+ ]
6681
+ }
6682
+ )
6683
+ ] });
6684
+ }
6685
+ );
6568
6686
  SheetContent.displayName = DialogPrimitive.Content.displayName;
6569
6687
  var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1.5 p-6 pr-12 pb-0", className), ...props });
6570
6688
  SheetHeader.displayName = "SheetHeader";
@@ -6728,6 +6846,7 @@ var Slider = React36.forwardRef(
6728
6846
  if (typeof v === "number") return v;
6729
6847
  return min;
6730
6848
  })();
6849
+ const accessibleName = props["aria-label"] ?? label ?? "Slider value";
6731
6850
  return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
6732
6851
  (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
6733
6852
  label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-fg text-[13px] leading-none font-medium", children: label }) : /* @__PURE__ */ jsx("span", {}),
@@ -6762,7 +6881,7 @@ var Slider = React36.forwardRef(
6762
6881
  "data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed",
6763
6882
  "data-[disabled]:border-fg-disabled data-[disabled]:bg-bg-disabled"
6764
6883
  ),
6765
- "aria-label": label
6884
+ "aria-label": accessibleName
6766
6885
  }
6767
6886
  )
6768
6887
  ]
@@ -7527,6 +7646,7 @@ function ToastProvider({ children }) {
7527
7646
  "div",
7528
7647
  {
7529
7648
  className: "pointer-events-none fixed top-4 right-4 z-[var(--z-toast)] flex flex-col gap-2",
7649
+ role: "region",
7530
7650
  "aria-live": "polite",
7531
7651
  "aria-label": "Notifications",
7532
7652
  children: toasts.map((t) => /* @__PURE__ */ jsx(ToastItem, { toast: t, onDismiss: removeToast }, t.id))
@@ -7753,13 +7873,21 @@ var Main = forwardRef(function Main2({ className, ...props }, ref) {
7753
7873
  );
7754
7874
  });
7755
7875
  Main.displayName = "Main";
7756
- var Content15 = forwardRef(function Content16({ padBottom, className, style, ...props }, ref) {
7876
+ var Content15 = forwardRef(function Content16({ padTop, padBottom, className, style, ...props }, ref) {
7877
+ const paddingStyle = padTop || padBottom ? {
7878
+ ...padTop ? { paddingTop: padTop } : null,
7879
+ ...padBottom ? { paddingBottom: padBottom } : null,
7880
+ ...style
7881
+ } : style;
7757
7882
  return /* @__PURE__ */ jsx(
7758
7883
  "div",
7759
7884
  {
7760
7885
  ref,
7886
+ role: "region",
7887
+ "aria-label": "Page content",
7888
+ tabIndex: 0,
7761
7889
  className: cn("flex-1 overflow-y-auto p-[var(--content-pad)]", className),
7762
- style: padBottom ? { paddingBottom: padBottom, ...style } : style,
7890
+ style: paddingStyle,
7763
7891
  ...props
7764
7892
  }
7765
7893
  );
@@ -8172,9 +8300,19 @@ var SidebarSection = React36.forwardRef(
8172
8300
  }
8173
8301
  );
8174
8302
  SidebarSection.displayName = "SidebarSection";
8303
+ function getTextContent(node) {
8304
+ if (node == null || typeof node === "boolean") return "";
8305
+ if (typeof node === "string" || typeof node === "number") return String(node);
8306
+ if (Array.isArray(node)) return node.map(getTextContent).filter(Boolean).join(" ");
8307
+ if (React36.isValidElement(node)) {
8308
+ return getTextContent(node.props.children);
8309
+ }
8310
+ return "";
8311
+ }
8175
8312
  var SidebarLink = React36.forwardRef(
8176
- function SidebarLink2({ href, icon, active = false, asChild, className, children, ...props }, ref) {
8313
+ function SidebarLink2({ href, icon, active = false, asChild, className, children, "aria-label": ariaLabel, ...props }, ref) {
8177
8314
  const Comp = asChild ? Slot : "a";
8315
+ const accessibleLabel = ariaLabel ?? (asChild ? void 0 : getTextContent(children) || void 0);
8178
8316
  return /* @__PURE__ */ jsx(
8179
8317
  Comp,
8180
8318
  {
@@ -8182,6 +8320,7 @@ var SidebarLink = React36.forwardRef(
8182
8320
  ...asChild ? {} : { href },
8183
8321
  "data-active": active ? "true" : void 0,
8184
8322
  "aria-current": active ? "page" : void 0,
8323
+ "aria-label": accessibleLabel,
8185
8324
  className: cn(
8186
8325
  "group/link relative mb-px flex items-center gap-2.5 rounded-md px-2.5 py-1.5",
8187
8326
  "text-fg-2 text-[13px] font-normal no-underline",
@@ -8381,6 +8520,7 @@ var SidebarLinkGroup = React36.forwardRef(
8381
8520
  href,
8382
8521
  "data-active": active ? "true" : void 0,
8383
8522
  "aria-current": active ? "page" : void 0,
8523
+ "aria-label": getTextContent(label) || void 0,
8384
8524
  onClick: handleBodyClick,
8385
8525
  className: bodyClassName,
8386
8526
  children: [
@@ -8875,11 +9015,21 @@ function Sparkline({ data, className }) {
8875
9015
  }
8876
9016
  );
8877
9017
  }
8878
- var KpiCard = forwardRef(function KpiCard2({ label, value, icon, tone = "muted", delta, trend, hint, action, toneValue, className, ...props }, ref) {
9018
+ function KpiCardBody({
9019
+ label,
9020
+ value,
9021
+ icon,
9022
+ tone = "muted",
9023
+ delta,
9024
+ trend,
9025
+ hint,
9026
+ action,
9027
+ toneValue
9028
+ }) {
8879
9029
  const deltaSentiment = delta ? delta.sentiment ?? directionToSentiment[delta.direction] : null;
8880
9030
  const DeltaIcon = delta ? directionToIcon[delta.direction] : null;
8881
9031
  const sparkColor = deltaSentiment ? sentimentText[deltaSentiment] : toneToValue[tone];
8882
- return /* @__PURE__ */ jsxs(Card, { ref, className: cn("p-4", className), ...props, children: [
9032
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
8883
9033
  /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
8884
9034
  icon && /* @__PURE__ */ jsx(
8885
9035
  "div",
@@ -8923,15 +9073,82 @@ var KpiCard = forwardRef(function KpiCard2({ label, value, icon, tone = "muted",
8923
9073
  )
8924
9074
  ] }),
8925
9075
  /* @__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 })
9076
+ delta?.label && /* @__PURE__ */ jsx("p", { className: "text-fg-3 mt-0.5 text-[11px]", children: delta.label }),
9077
+ hint && /* @__PURE__ */ jsx("p", { className: "text-fg-3 mt-0.5 text-[11px]", children: hint })
8928
9078
  ] }),
8929
9079
  action && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action })
8930
9080
  ] }),
8931
9081
  trend && trend.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: trend, className: cn("mt-3", sparkColor) })
8932
9082
  ] });
9083
+ }
9084
+ var KpiCard = forwardRef(function KpiCard2({ label, value, icon, tone = "muted", delta, trend, hint, action, toneValue, className, ...props }, ref) {
9085
+ return /* @__PURE__ */ jsx(Card, { ref, className: cn("p-4", className), ...props, children: /* @__PURE__ */ jsx(
9086
+ KpiCardBody,
9087
+ {
9088
+ label,
9089
+ value,
9090
+ icon,
9091
+ tone,
9092
+ delta,
9093
+ trend,
9094
+ hint,
9095
+ action,
9096
+ toneValue
9097
+ }
9098
+ ) });
8933
9099
  });
8934
9100
  KpiCard.displayName = "KpiCard";
9101
+ var SelectableKpiCard = forwardRef(
9102
+ function SelectableKpiCard2({
9103
+ label,
9104
+ value,
9105
+ icon,
9106
+ tone = "muted",
9107
+ delta,
9108
+ trend,
9109
+ hint,
9110
+ action,
9111
+ toneValue,
9112
+ selected = false,
9113
+ className,
9114
+ type,
9115
+ ...props
9116
+ }, ref) {
9117
+ return /* @__PURE__ */ jsx(
9118
+ "button",
9119
+ {
9120
+ ref,
9121
+ type: type ?? "button",
9122
+ "aria-pressed": selected,
9123
+ "data-selected": selected ? "true" : "false",
9124
+ className: cn(
9125
+ cardVariants({ variant: "interactive" }),
9126
+ "block w-full p-4 text-left",
9127
+ "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
9128
+ "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-fg-disabled disabled:shadow-none",
9129
+ selected && "border-pro-fg/40 bg-pro-bg hover:bg-pro-bg-hover ring-1 ring-pro-fg/30",
9130
+ className
9131
+ ),
9132
+ ...props,
9133
+ children: /* @__PURE__ */ jsx(
9134
+ KpiCardBody,
9135
+ {
9136
+ label,
9137
+ value,
9138
+ icon,
9139
+ tone,
9140
+ delta,
9141
+ trend,
9142
+ hint,
9143
+ action,
9144
+ toneValue
9145
+ }
9146
+ )
9147
+ }
9148
+ );
9149
+ }
9150
+ );
9151
+ SelectableKpiCard.displayName = "SelectableKpiCard";
8935
9152
  var DataTable = forwardRef(function DataTable2({ withToolbar, className, children, ...props }, ref) {
8936
9153
  return /* @__PURE__ */ jsx(
8937
9154
  "div",
@@ -9394,7 +9611,21 @@ var ActivityEventItem = forwardRef(
9394
9611
  );
9395
9612
  ActivityEventItem.displayName = "ActivityEventItem";
9396
9613
  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 });
9614
+ return /* @__PURE__ */ jsx(
9615
+ "div",
9616
+ {
9617
+ ref,
9618
+ role: "region",
9619
+ tabIndex: 0,
9620
+ "aria-label": "Kanban board",
9621
+ className: cn(
9622
+ "flex items-start gap-4 overflow-x-auto focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
9623
+ className
9624
+ ),
9625
+ ...props,
9626
+ children
9627
+ }
9628
+ );
9398
9629
  });
9399
9630
  Kanban.displayName = "Kanban";
9400
9631
  var KanbanColumn = forwardRef(function KanbanColumn2({ title, count, className, children, ...props }, ref) {
@@ -9803,6 +10034,511 @@ var NotificationItem = forwardRef(
9803
10034
  }
9804
10035
  );
9805
10036
  NotificationItem.displayName = "NotificationItem";
10037
+ var padded = (n) => String(n).padStart(2, "0");
10038
+ function formatClock(ms) {
10039
+ const total = Math.max(0, Math.floor(ms / 1e3));
10040
+ return `${Math.floor(total / 3600)}:${padded(Math.floor(total % 3600 / 60))}:${padded(total % 60)}`;
10041
+ }
10042
+ function formatDuration(totalSeconds) {
10043
+ const minutes = Math.round(totalSeconds / 60);
10044
+ const h = Math.floor(minutes / 60);
10045
+ const m = minutes % 60;
10046
+ if (h && m) return `${h}h ${m}m`;
10047
+ if (h) return `${h}h`;
10048
+ return `${m}m`;
10049
+ }
10050
+ function parseDuration(input) {
10051
+ const text = input.trim().toLowerCase();
10052
+ if (!text) return null;
10053
+ const clock = text.match(/^(\d{1,2}):(\d{2})$/);
10054
+ if (clock) return (Number(clock[1]) * 60 + Number(clock[2])) * 60;
10055
+ let seconds = 0;
10056
+ let matched = false;
10057
+ const unit = /(\d+(?:\.\d+)?)\s*(h|hr|hrs|hour|hours|m|min|mins|minute|minutes|s|sec|secs)/g;
10058
+ let part;
10059
+ while ((part = unit.exec(text)) !== null) {
10060
+ matched = true;
10061
+ const value = parseFloat(part[1]);
10062
+ if (part[2].startsWith("h")) seconds += value * 3600;
10063
+ else if (part[2].startsWith("m")) seconds += value * 60;
10064
+ else seconds += value;
10065
+ }
10066
+ if (!matched && /^\d+$/.test(text)) return Number(text) * 60;
10067
+ return matched ? Math.round(seconds) : null;
10068
+ }
10069
+ function formatCurrency(amount, currency = "USD") {
10070
+ try {
10071
+ return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
10072
+ } catch {
10073
+ return `$${amount.toFixed(2)}`;
10074
+ }
10075
+ }
10076
+ var TICK_MS = 250;
10077
+ function useStopwatch() {
10078
+ const [phase, setPhaseState] = useState("idle");
10079
+ const [elapsedMs, setElapsedMs] = useState(0);
10080
+ const accumulatedRef = useRef(0);
10081
+ const startedAtRef = useRef(0);
10082
+ const phaseRef = useRef("idle");
10083
+ const setPhase = useCallback((next) => {
10084
+ phaseRef.current = next;
10085
+ setPhaseState(next);
10086
+ }, []);
10087
+ useEffect(() => {
10088
+ if (phase !== "running") return;
10089
+ const id = setInterval(() => {
10090
+ setElapsedMs(accumulatedRef.current + (Date.now() - startedAtRef.current));
10091
+ }, TICK_MS);
10092
+ return () => clearInterval(id);
10093
+ }, [phase]);
10094
+ const start = useCallback(
10095
+ (fromMs = 0) => {
10096
+ accumulatedRef.current = fromMs;
10097
+ startedAtRef.current = Date.now();
10098
+ setElapsedMs(fromMs);
10099
+ setPhase("running");
10100
+ },
10101
+ [setPhase]
10102
+ );
10103
+ const pause = useCallback(() => {
10104
+ if (phaseRef.current !== "running") return;
10105
+ accumulatedRef.current += Date.now() - startedAtRef.current;
10106
+ setElapsedMs(accumulatedRef.current);
10107
+ setPhase("paused");
10108
+ }, [setPhase]);
10109
+ const resume = useCallback(() => {
10110
+ if (phaseRef.current !== "paused") return;
10111
+ startedAtRef.current = Date.now();
10112
+ setPhase("running");
10113
+ }, [setPhase]);
10114
+ const stop = useCallback(() => {
10115
+ if (phaseRef.current === "idle") return;
10116
+ if (phaseRef.current === "running") {
10117
+ accumulatedRef.current += Date.now() - startedAtRef.current;
10118
+ setElapsedMs(accumulatedRef.current);
10119
+ }
10120
+ setPhase("stopped");
10121
+ }, [setPhase]);
10122
+ const reset = useCallback(() => {
10123
+ accumulatedRef.current = 0;
10124
+ startedAtRef.current = 0;
10125
+ setElapsedMs(0);
10126
+ setPhase("idle");
10127
+ }, [setPhase]);
10128
+ return { phase, elapsedMs, isRunning: phase === "running", start, pause, resume, stop, reset };
10129
+ }
10130
+ var TimeLogger = forwardRef(function TimeLogger2({ className, children, ...props }, ref) {
10131
+ return /* @__PURE__ */ jsx(
10132
+ "div",
10133
+ {
10134
+ ref,
10135
+ className: cn("bg-surface text-fg-2 flex w-full flex-col", className),
10136
+ ...props,
10137
+ children
10138
+ }
10139
+ );
10140
+ });
10141
+ TimeLogger.displayName = "TimeLogger";
10142
+ var TimeLoggerHeader = forwardRef(
10143
+ function TimeLoggerHeader2({ title = "Track Time", icon, loggedMinutes = 0, goalMinutes, className, ...props }, ref) {
10144
+ const hasGoal = goalMinutes != null;
10145
+ const pct = hasGoal && goalMinutes > 0 ? Math.min(100, loggedMinutes / goalMinutes * 100) : 0;
10146
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col", className), ...props, children: [
10147
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [
10148
+ /* @__PURE__ */ jsxs("div", { className: "text-fg flex items-center gap-2 text-base font-semibold [&_svg]:size-[18px]", children: [
10149
+ /* @__PURE__ */ jsx("span", { className: "text-pro-fg", "aria-hidden": "true", children: icon ?? /* @__PURE__ */ jsx(ClockIcon, {}) }),
10150
+ title
10151
+ ] }),
10152
+ hasGoal && /* @__PURE__ */ jsxs("div", { className: "text-fg-3 font-mono text-[13px] tabular-nums", children: [
10153
+ /* @__PURE__ */ jsx("b", { className: "text-fg font-medium", children: formatDuration(loggedMinutes * 60) }),
10154
+ " /",
10155
+ " ",
10156
+ formatDuration(goalMinutes * 60)
10157
+ ] })
10158
+ ] }),
10159
+ hasGoal && /* @__PURE__ */ jsx(
10160
+ "div",
10161
+ {
10162
+ className: "bg-bg-3 relative h-[3px] w-full",
10163
+ role: "progressbar",
10164
+ "aria-label": "Daily goal progress",
10165
+ "aria-valuemin": 0,
10166
+ "aria-valuemax": goalMinutes,
10167
+ "aria-valuenow": Math.min(loggedMinutes, goalMinutes),
10168
+ children: /* @__PURE__ */ jsx(
10169
+ "div",
10170
+ {
10171
+ className: "bg-pro-fg h-full rounded-r-full transition-[width] duration-[var(--duration-normal)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
10172
+ style: { width: `${pct}%` }
10173
+ }
10174
+ )
10175
+ }
10176
+ )
10177
+ ] });
10178
+ }
10179
+ );
10180
+ TimeLoggerHeader.displayName = "TimeLoggerHeader";
10181
+ var TimeLoggerContextRow = forwardRef(
10182
+ function TimeLoggerContextRow2({ client, engagement, avatar, onClientSelect, member, className, ...props }, ref) {
10183
+ const text = /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
10184
+ /* @__PURE__ */ jsx("span", { className: "text-fg block truncate text-sm font-medium", children: client }),
10185
+ engagement && /* @__PURE__ */ jsx("span", { className: "text-fg-3 block truncate text-xs", children: engagement })
10186
+ ] });
10187
+ return /* @__PURE__ */ jsxs(
10188
+ "div",
10189
+ {
10190
+ ref,
10191
+ className: cn("border-rule-soft flex items-center gap-2.5 border-t px-4 py-2.5", className),
10192
+ ...props,
10193
+ children: [
10194
+ onClientSelect ? /* @__PURE__ */ jsxs(
10195
+ "button",
10196
+ {
10197
+ type: "button",
10198
+ onClick: onClientSelect,
10199
+ 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",
10200
+ children: [
10201
+ avatar,
10202
+ text
10203
+ ]
10204
+ }
10205
+ ) : /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
10206
+ avatar,
10207
+ text
10208
+ ] }),
10209
+ member && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: member })
10210
+ ]
10211
+ }
10212
+ );
10213
+ }
10214
+ );
10215
+ TimeLoggerContextRow.displayName = "TimeLoggerContextRow";
10216
+ var TimeLoggerTimer = forwardRef(
10217
+ function TimeLoggerTimer2({
10218
+ phase,
10219
+ elapsedMs,
10220
+ value,
10221
+ onValueChange,
10222
+ placeholder = "Enter time (ex: 3h 20m) or start timer",
10223
+ onStart,
10224
+ onPause,
10225
+ onResume,
10226
+ onStop,
10227
+ className,
10228
+ ...props
10229
+ }, ref) {
10230
+ const showClock = phase !== "idle";
10231
+ const canStop = phase === "running" || phase === "paused";
10232
+ return /* @__PURE__ */ jsxs(
10233
+ "div",
10234
+ {
10235
+ ref,
10236
+ className: cn("border-rule-soft flex items-center gap-2 border-t px-4 py-2.5", className),
10237
+ ...props,
10238
+ children: [
10239
+ /* @__PURE__ */ jsx(
10240
+ "input",
10241
+ {
10242
+ className: cn(
10243
+ "text-fg placeholder:text-fg-4 min-w-0 flex-1 border-0 bg-transparent outline-none",
10244
+ showClock ? "font-mono text-[22px] font-medium tracking-tight tabular-nums" : "text-[15px]"
10245
+ ),
10246
+ value: showClock ? formatClock(elapsedMs) : value ?? "",
10247
+ onChange: (event) => onValueChange?.(event.target.value),
10248
+ placeholder,
10249
+ readOnly: showClock,
10250
+ "aria-label": "Tracked time"
10251
+ }
10252
+ ),
10253
+ /* @__PURE__ */ jsx(
10254
+ Button,
10255
+ {
10256
+ type: "button",
10257
+ variant: "secondary",
10258
+ size: "icon",
10259
+ className: "rounded-full",
10260
+ "aria-label": phase === "paused" ? "Resume timer" : "Pause timer",
10261
+ disabled: phase === "idle" || phase === "stopped",
10262
+ onClick: phase === "paused" ? onResume : onPause,
10263
+ children: phase === "paused" ? /* @__PURE__ */ jsx(PlayIcon, {}) : /* @__PURE__ */ jsx(PauseIcon, {})
10264
+ }
10265
+ ),
10266
+ canStop ? /* @__PURE__ */ jsx(
10267
+ Button,
10268
+ {
10269
+ type: "button",
10270
+ variant: "destructive",
10271
+ size: "icon",
10272
+ className: "rounded-full",
10273
+ "aria-label": "Stop timer",
10274
+ onClick: onStop,
10275
+ children: /* @__PURE__ */ jsx(StopIcon, {})
10276
+ }
10277
+ ) : /* @__PURE__ */ jsx(
10278
+ Button,
10279
+ {
10280
+ type: "button",
10281
+ variant: "primary",
10282
+ size: "icon",
10283
+ className: "rounded-full",
10284
+ "aria-label": "Start timer",
10285
+ onClick: onStart,
10286
+ children: /* @__PURE__ */ jsx(PlayIcon, {})
10287
+ }
10288
+ )
10289
+ ]
10290
+ }
10291
+ );
10292
+ }
10293
+ );
10294
+ TimeLoggerTimer.displayName = "TimeLoggerTimer";
10295
+ var TimeLoggerField = forwardRef(
10296
+ function TimeLoggerField2({ icon, label, onSelect, trailing, muted, className, children, ...props }, ref) {
10297
+ const interactive = Boolean(onSelect);
10298
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
10299
+ icon && /* @__PURE__ */ jsx(
10300
+ "span",
10301
+ {
10302
+ className: "text-fg-4 flex size-[17px] shrink-0 items-center justify-center [&_svg]:size-[17px]",
10303
+ "aria-hidden": "true",
10304
+ children: icon
10305
+ }
10306
+ ),
10307
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
10308
+ label && /* @__PURE__ */ jsx("span", { className: "text-fg-3 block text-[11px] leading-tight", children: label }),
10309
+ /* @__PURE__ */ jsx("span", { className: cn("block truncate", muted ? "text-fg-3" : "text-fg-2"), children })
10310
+ ] }),
10311
+ trailing !== void 0 ? trailing : interactive ? /* @__PURE__ */ jsx(ChevronRightIcon, { className: "text-fg-4 size-4 shrink-0" }) : null
10312
+ ] });
10313
+ const classes = cn(
10314
+ "border-rule-soft flex w-full items-center gap-3 border-t px-4 py-2.5 text-left",
10315
+ 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",
10316
+ className
10317
+ );
10318
+ if (interactive) {
10319
+ return /* @__PURE__ */ jsx(
10320
+ "button",
10321
+ {
10322
+ ref,
10323
+ type: "button",
10324
+ onClick: onSelect,
10325
+ className: classes,
10326
+ ...props,
10327
+ children: inner
10328
+ }
10329
+ );
10330
+ }
10331
+ return /* @__PURE__ */ jsx("div", { ref, className: classes, ...props, children: inner });
10332
+ }
10333
+ );
10334
+ TimeLoggerField.displayName = "TimeLoggerField";
10335
+ var TimeLoggerNotes = forwardRef(
10336
+ function TimeLoggerNotes2({ value, onValueChange, icon, placeholder = "Add notes", className, ...props }, ref) {
10337
+ return /* @__PURE__ */ jsxs("div", { className: "border-rule-soft flex items-center gap-3 border-t px-4 py-2.5", children: [
10338
+ /* @__PURE__ */ jsx(
10339
+ "span",
10340
+ {
10341
+ className: "text-fg-4 flex size-[17px] shrink-0 items-center justify-center [&_svg]:size-[17px]",
10342
+ "aria-hidden": "true",
10343
+ children: icon ?? /* @__PURE__ */ jsx(FileTextIcon, {})
10344
+ }
10345
+ ),
10346
+ /* @__PURE__ */ jsx(
10347
+ "input",
10348
+ {
10349
+ ref,
10350
+ type: "text",
10351
+ value: value ?? "",
10352
+ onChange: (event) => onValueChange?.(event.target.value),
10353
+ placeholder,
10354
+ "aria-label": "Notes",
10355
+ className: cn(
10356
+ "text-fg placeholder:text-fg-4 min-w-0 flex-1 border-0 bg-transparent text-sm outline-none",
10357
+ className
10358
+ ),
10359
+ ...props
10360
+ }
10361
+ )
10362
+ ] });
10363
+ }
10364
+ );
10365
+ TimeLoggerNotes.displayName = "TimeLoggerNotes";
10366
+ var TimeLoggerBillable = forwardRef(
10367
+ function TimeLoggerBillable2({
10368
+ billable,
10369
+ onBillableChange,
10370
+ label,
10371
+ tiers,
10372
+ tierId,
10373
+ onTierChange,
10374
+ currency = "USD",
10375
+ amount,
10376
+ className,
10377
+ ...props
10378
+ }, ref) {
10379
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex min-w-0 items-center gap-2.5", className), ...props, children: [
10380
+ /* @__PURE__ */ jsx(
10381
+ Switch,
10382
+ {
10383
+ size: "sm",
10384
+ checked: billable,
10385
+ onCheckedChange: onBillableChange,
10386
+ "aria-label": "Billable"
10387
+ }
10388
+ ),
10389
+ /* @__PURE__ */ jsx("span", { className: "text-fg-3 text-[13px] whitespace-nowrap", children: label ?? (billable ? "Billable" : "Non-billable") }),
10390
+ tiers && tiers.length > 0 && /* @__PURE__ */ jsxs(Popover, { children: [
10391
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
10392
+ "button",
10393
+ {
10394
+ type: "button",
10395
+ "aria-label": "Billing settings",
10396
+ 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",
10397
+ children: /* @__PURE__ */ jsx(SettingsIcon, {})
10398
+ }
10399
+ ) }),
10400
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "start", side: "top", className: "w-56 p-1.5", children: [
10401
+ /* @__PURE__ */ jsxs("p", { className: "text-fg-3 px-2 pt-1 pb-1.5 font-mono text-[10px] tracking-wider uppercase", children: [
10402
+ "Pricing tier \xB7 ",
10403
+ currency
10404
+ ] }),
10405
+ tiers.map((tier) => {
10406
+ const selected = tier.id === tierId;
10407
+ return /* @__PURE__ */ jsx(PopoverClose, { asChild: true, children: /* @__PURE__ */ jsxs(
10408
+ "button",
10409
+ {
10410
+ type: "button",
10411
+ onClick: () => onTierChange?.(tier.id),
10412
+ 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",
10413
+ children: [
10414
+ /* @__PURE__ */ jsx(
10415
+ "span",
10416
+ {
10417
+ className: cn(
10418
+ "flex-1 truncate text-[13px]",
10419
+ selected ? "text-pro-fg font-medium" : "text-fg"
10420
+ ),
10421
+ children: tier.name
10422
+ }
10423
+ ),
10424
+ /* @__PURE__ */ jsxs("span", { className: "text-fg-3 font-mono text-[12.5px] tabular-nums", children: [
10425
+ formatCurrency(tier.rate, currency),
10426
+ "/hr"
10427
+ ] }),
10428
+ /* @__PURE__ */ jsx(
10429
+ CheckIcon,
10430
+ {
10431
+ className: cn(
10432
+ "text-pro-fg size-4 shrink-0",
10433
+ selected ? "opacity-100" : "opacity-0"
10434
+ )
10435
+ }
10436
+ )
10437
+ ]
10438
+ }
10439
+ ) }, tier.id);
10440
+ })
10441
+ ] })
10442
+ ] }),
10443
+ amount != null && /* @__PURE__ */ jsx("span", { className: "text-fg-2 font-mono text-[12.5px] font-medium tabular-nums", children: amount })
10444
+ ] });
10445
+ }
10446
+ );
10447
+ TimeLoggerBillable.displayName = "TimeLoggerBillable";
10448
+ var TimeLoggerActions = forwardRef(
10449
+ function TimeLoggerActions2({ className, children, ...props }, ref) {
10450
+ return /* @__PURE__ */ jsx(
10451
+ "div",
10452
+ {
10453
+ ref,
10454
+ className: cn(
10455
+ "border-rule bg-surface-2 flex items-center gap-2 border-t px-4 py-2.5",
10456
+ className
10457
+ ),
10458
+ ...props,
10459
+ children
10460
+ }
10461
+ );
10462
+ }
10463
+ );
10464
+ TimeLoggerActions.displayName = "TimeLoggerActions";
10465
+ var TimeLoggerEntryList = forwardRef(
10466
+ function TimeLoggerEntryList2({ dayLabel, total, className, children, ...props }, ref) {
10467
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("border-bg-2 border-t-[7px]", className), ...props, children: [
10468
+ (dayLabel || total) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 pt-2.5 pb-1 text-xs", children: [
10469
+ dayLabel && /* @__PURE__ */ jsx("span", { className: "text-fg-3 font-medium", children: dayLabel }),
10470
+ total && /* @__PURE__ */ jsx("span", { className: "text-fg-2 font-mono tabular-nums", children: total })
10471
+ ] }),
10472
+ children
10473
+ ] });
10474
+ }
10475
+ );
10476
+ TimeLoggerEntryList.displayName = "TimeLoggerEntryList";
10477
+ var TimeLoggerEntry = forwardRef(
10478
+ function TimeLoggerEntry2({ title, meta, duration, onResume, onDelete, className, ...props }, ref) {
10479
+ return /* @__PURE__ */ jsxs(
10480
+ "div",
10481
+ {
10482
+ ref,
10483
+ className: cn("border-rule-soft flex items-center gap-3 border-t px-4 py-2", className),
10484
+ ...props,
10485
+ children: [
10486
+ /* @__PURE__ */ jsx(
10487
+ "span",
10488
+ {
10489
+ "aria-hidden": "true",
10490
+ className: "border-pro-fg size-[15px] shrink-0 rounded-full border-[1.5px] shadow-[inset_0_0_0_3px_var(--color-pro-fg)]"
10491
+ }
10492
+ ),
10493
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
10494
+ /* @__PURE__ */ jsx("p", { className: "text-fg truncate text-[13px]", children: title }),
10495
+ meta && /* @__PURE__ */ jsx("p", { className: "text-fg-3 truncate text-[11.5px]", children: meta })
10496
+ ] }),
10497
+ /* @__PURE__ */ jsx("span", { className: "text-fg-2 font-mono text-[13px] tabular-nums", children: duration }),
10498
+ onResume && /* @__PURE__ */ jsx(
10499
+ Button,
10500
+ {
10501
+ type: "button",
10502
+ variant: "ghost",
10503
+ size: "icon-sm",
10504
+ className: "text-fg-3 hover:text-pro-fg hover:bg-pro-bg rounded-full",
10505
+ "aria-label": "Resume entry",
10506
+ onClick: onResume,
10507
+ children: /* @__PURE__ */ jsx(PlayIcon, {})
10508
+ }
10509
+ ),
10510
+ onDelete && /* @__PURE__ */ jsx(
10511
+ Button,
10512
+ {
10513
+ type: "button",
10514
+ variant: "ghost",
10515
+ size: "icon-sm",
10516
+ className: "text-fg-3 hover:text-danger-fg hover:bg-danger-bg rounded-full",
10517
+ "aria-label": "Delete entry",
10518
+ onClick: onDelete,
10519
+ children: /* @__PURE__ */ jsx(Trash2Icon, {})
10520
+ }
10521
+ )
10522
+ ]
10523
+ }
10524
+ );
10525
+ }
10526
+ );
10527
+ TimeLoggerEntry.displayName = "TimeLoggerEntry";
10528
+ var TimeLoggerFooter = forwardRef(
10529
+ function TimeLoggerFooter2({ className, children, ...props }, ref) {
10530
+ return /* @__PURE__ */ jsx(
10531
+ "div",
10532
+ {
10533
+ ref,
10534
+ className: cn("border-rule flex gap-2 border-t px-4 py-2.5 [&>*]:flex-1", className),
10535
+ ...props,
10536
+ children
10537
+ }
10538
+ );
10539
+ }
10540
+ );
10541
+ TimeLoggerFooter.displayName = "TimeLoggerFooter";
9806
10542
  var Toolbar = forwardRef(function Toolbar2({ className, children, ...props }, ref) {
9807
10543
  return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center gap-2", className), ...props, children });
9808
10544
  });
@@ -9852,6 +10588,151 @@ var FilterChip = forwardRef(function FilterChip2({ active = false, size, count,
9852
10588
  );
9853
10589
  });
9854
10590
  FilterChip.displayName = "FilterChip";
10591
+ var BulkActionBarContext = React36.createContext({ tone: "surface" });
10592
+ function actionClasses(tone, destructive) {
10593
+ const base = cn(
10594
+ "inline-flex h-8 items-center gap-1.5 rounded-btn px-3 text-[13px] font-medium",
10595
+ "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
10596
+ "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
10597
+ "disabled:pointer-events-none disabled:opacity-45",
10598
+ "motion-reduce:transition-none",
10599
+ "[&_svg]:size-4 [&_svg]:shrink-0"
10600
+ );
10601
+ if (tone === "inverse") {
10602
+ return cn(
10603
+ base,
10604
+ "data-[state=open]:bg-selection-floating-active-bg",
10605
+ 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"
10606
+ );
10607
+ }
10608
+ return cn(
10609
+ base,
10610
+ "data-[state=open]:bg-control-active-bg",
10611
+ destructive ? "text-control-destructive-fg hover:bg-control-destructive-hover-bg" : "text-control-fg hover:bg-control-hover-bg hover:text-control-hover-fg"
10612
+ );
10613
+ }
10614
+ var BulkActionBarAction = React36.forwardRef(function BulkActionBarAction2({ asChild = false, destructive, className, type, ...props }, ref) {
10615
+ const { tone } = React36.use(BulkActionBarContext);
10616
+ const Comp = asChild ? Slot : "button";
10617
+ return /* @__PURE__ */ jsx(
10618
+ Comp,
10619
+ {
10620
+ ref,
10621
+ type: asChild ? void 0 : type ?? "button",
10622
+ className: cn(actionClasses(tone, destructive), className),
10623
+ ...props
10624
+ }
10625
+ );
10626
+ });
10627
+ BulkActionBarAction.displayName = "BulkActionBarAction";
10628
+ function BulkActionBarSeparator({ className }) {
10629
+ const { tone } = React36.use(BulkActionBarContext);
10630
+ return /* @__PURE__ */ jsx(
10631
+ "span",
10632
+ {
10633
+ "aria-hidden": "true",
10634
+ className: cn(
10635
+ "h-4 w-px shrink-0",
10636
+ tone === "inverse" ? "bg-selection-floating-rule" : "bg-control-border",
10637
+ className
10638
+ )
10639
+ }
10640
+ );
10641
+ }
10642
+ function BulkActionBarClear({
10643
+ variant,
10644
+ clearLabel,
10645
+ clearDisabled,
10646
+ onClear
10647
+ }) {
10648
+ if (variant === "page-floating") {
10649
+ return /* @__PURE__ */ jsx(
10650
+ "button",
10651
+ {
10652
+ type: "button",
10653
+ onClick: onClear,
10654
+ disabled: clearDisabled,
10655
+ className: cn(
10656
+ "text-selection-floating-muted-fg ml-1 inline-flex size-7 items-center justify-center rounded-icon",
10657
+ "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
10658
+ "hover:bg-selection-floating-hover-bg hover:text-selection-floating-fg",
10659
+ "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
10660
+ "disabled:pointer-events-none disabled:opacity-45 motion-reduce:transition-none"
10661
+ ),
10662
+ "aria-label": clearLabel,
10663
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-4", "aria-hidden": "true" })
10664
+ }
10665
+ );
10666
+ }
10667
+ return /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClear, disabled: clearDisabled, children: clearLabel });
10668
+ }
10669
+ function BulkActionBar({
10670
+ variant = "table-inline",
10671
+ selectedCount,
10672
+ label,
10673
+ children,
10674
+ onClear,
10675
+ clearLabel = "Clear selection",
10676
+ clearDisabled,
10677
+ footer,
10678
+ className,
10679
+ ...props
10680
+ }) {
10681
+ if (selectedCount === 0) return null;
10682
+ const labelText = label ?? `${selectedCount} selected`;
10683
+ const tone = variant === "page-floating" ? "inverse" : "surface";
10684
+ const content = /* @__PURE__ */ jsxs(BulkActionBarContext, { value: { tone }, children: [
10685
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tabular-nums", children: labelText }),
10686
+ /* @__PURE__ */ jsx(BulkActionBarSeparator, {}),
10687
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1", children }),
10688
+ /* @__PURE__ */ jsx("div", { className: "min-w-2 flex-1" }),
10689
+ /* @__PURE__ */ jsx(
10690
+ BulkActionBarClear,
10691
+ {
10692
+ variant,
10693
+ clearLabel,
10694
+ clearDisabled,
10695
+ onClear
10696
+ }
10697
+ )
10698
+ ] });
10699
+ if (variant === "sidebar-anchored") {
10700
+ return /* @__PURE__ */ jsxs(
10701
+ "div",
10702
+ {
10703
+ className: cn(
10704
+ "fixed right-6 bottom-6 left-[calc(var(--shell-sidebar-w)+1.5rem)] z-[var(--z-sticky)]",
10705
+ className
10706
+ ),
10707
+ ...props,
10708
+ children: [
10709
+ /* @__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 }),
10710
+ footer
10711
+ ]
10712
+ }
10713
+ );
10714
+ }
10715
+ if (variant === "page-floating") {
10716
+ return /* @__PURE__ */ jsxs(
10717
+ "div",
10718
+ {
10719
+ className: cn(
10720
+ "fixed bottom-4 left-1/2 z-[var(--z-sticky)] -translate-x-1/2",
10721
+ className
10722
+ ),
10723
+ ...props,
10724
+ children: [
10725
+ /* @__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 }),
10726
+ footer
10727
+ ]
10728
+ }
10729
+ );
10730
+ }
10731
+ return /* @__PURE__ */ jsxs("div", { className: cn("sticky bottom-4 z-[var(--z-sticky)] mt-3", className), ...props, children: [
10732
+ /* @__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 }),
10733
+ footer
10734
+ ] });
10735
+ }
9855
10736
  var PrimaryAction = forwardRef(
9856
10737
  function PrimaryAction2({ arrow, iconRight, children, className, ...props }, ref) {
9857
10738
  return /* @__PURE__ */ jsx(
@@ -9938,6 +10819,6 @@ var KbdHint = forwardRef(function KbdHint2({ className, children, ...props }, re
9938
10819
  });
9939
10820
  KbdHint.displayName = "KbdHint";
9940
10821
 
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 };
10822
+ 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
10823
  //# sourceMappingURL=index.js.map
9943
10824
  //# sourceMappingURL=index.js.map