@kinetixui/ui 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/index.js +377 -237
  2. package/package.json +2 -2
  3. package/src/components/audio-player.tsx +2 -2
  4. package/src/components/badge.tsx +1 -1
  5. package/src/components/banner.tsx +1 -1
  6. package/src/components/button.tsx +8 -8
  7. package/src/components/calendar.tsx +1 -1
  8. package/src/components/chart.tsx +2 -2
  9. package/src/components/checkbox.tsx +2 -2
  10. package/src/components/circular-progress.tsx +1 -1
  11. package/src/components/code-block.tsx +1 -1
  12. package/src/components/color-picker.tsx +4 -0
  13. package/src/components/data-grid.tsx +169 -25
  14. package/src/components/diff-viewer.tsx +9 -8
  15. package/src/components/fab.tsx +1 -1
  16. package/src/components/file-upload.tsx +13 -15
  17. package/src/components/input-group.tsx +1 -1
  18. package/src/components/input-otp.tsx +2 -1
  19. package/src/components/input.tsx +2 -2
  20. package/src/components/json-viewer.tsx +12 -10
  21. package/src/components/list.tsx +41 -27
  22. package/src/components/markdown-editor.tsx +3 -2
  23. package/src/components/message-bubble.tsx +3 -3
  24. package/src/components/multi-select.tsx +14 -3
  25. package/src/components/native-select.tsx +2 -2
  26. package/src/components/notification-center.tsx +2 -2
  27. package/src/components/progress.tsx +1 -1
  28. package/src/components/radio-group.tsx +3 -3
  29. package/src/components/scroll-area.tsx +1 -1
  30. package/src/components/select.tsx +2 -2
  31. package/src/components/skeleton.tsx +1 -1
  32. package/src/components/slider.tsx +2 -2
  33. package/src/components/sonner.tsx +1 -1
  34. package/src/components/spinner.tsx +3 -3
  35. package/src/components/stepper.tsx +3 -3
  36. package/src/components/switch.tsx +1 -1
  37. package/src/components/tab-bar.tsx +1 -1
  38. package/src/components/table-of-contents.tsx +1 -1
  39. package/src/components/textarea.tsx +2 -2
  40. package/src/components/timeline.tsx +1 -1
  41. package/src/components/tooltip.tsx +1 -1
  42. package/src/components/virtual-list.tsx +2 -1
  43. package/src/components-a11y.test.tsx +4 -25
  44. package/src/components-behavior.test.tsx +1 -1
  45. package/src/components-keyboard.test.tsx +236 -33
  46. package/src/stories/AppBar.stories.tsx +1 -1
  47. package/src/stories/Checkbox.stories.tsx +1 -1
  48. package/src/stories/CircularProgress.stories.tsx +4 -4
  49. package/src/stories/InputOTP.stories.tsx +2 -2
  50. package/src/stories/List.stories.tsx +2 -2
  51. package/src/stories/MarkdownEditor.stories.tsx +1 -1
  52. package/src/stories/MultiSelect.stories.tsx +1 -0
  53. package/src/stories/NativeSelect.stories.tsx +1 -1
  54. package/src/stories/NumberInput.stories.tsx +3 -3
  55. package/src/stories/Progress.stories.tsx +3 -3
  56. package/src/stories/Select.stories.tsx +2 -2
  57. package/src/stories/Slider.stories.tsx +3 -3
  58. package/src/stories/Switch.stories.tsx +1 -1
  59. package/src/stories/ToggleGroup.stories.tsx +6 -6
  60. package/tailwind.config.ts +14 -0
package/dist/index.js CHANGED
@@ -60,7 +60,7 @@ var buttonVariants = cva(
60
60
  // (light: 90% = 5.05, 85% = 4.54, 80% = 4.11 fails) — enforced by check:contrast.
61
61
  // (the old hover:bg-[--color-blue-600] was a hard-coded dark navy — on dark mode,
62
62
  // where --primary is light, it inverted the button into the near-black background.)
63
- Primary: "bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/85 disabled:bg-border disabled:text-muted-foreground",
63
+ Primary: "bg-action text-action-foreground hover:bg-action/90 active:bg-action/85 disabled:bg-border disabled:text-muted-foreground",
64
64
  // rest = --secondary; hover/active promote to the --secondary-foreground fill with
65
65
  // inverted text — theme-aware, unlike the previous hard-coded green primitives.
66
66
  // Active is solid like hover: dimming it (90% was 3.97:1) drops the text under AA,
@@ -68,12 +68,12 @@ var buttonVariants = cva(
68
68
  Secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-foreground hover:text-secondary active:bg-secondary-foreground active:text-secondary focus-visible:bg-secondary disabled:bg-border disabled:text-muted-foreground",
69
69
  // 1px outline; hover fills with accent + strengthens the edge to --ring so the
70
70
  // state stays visible on the darkest surfaces (WCAG 2.2 SC 1.4.11); active pins primary
71
- Outline: "border border-input bg-transparent text-foreground hover:border-ring hover:bg-accent active:border-primary active:bg-accent active:text-primary disabled:border-input disabled:text-muted-foreground disabled:bg-transparent",
71
+ Outline: "border border-input bg-transparent text-foreground hover:border-ring hover:bg-accent active:border-action active:bg-accent active:text-action disabled:border-input disabled:text-muted-foreground disabled:bg-transparent",
72
72
  Destructive: "bg-destructive text-destructive-foreground hover:brightness-95 active:brightness-90 disabled:bg-border disabled:text-muted-foreground",
73
73
  // transparent rest; hover adds an inset --ring outline (the accent fill alone is
74
74
  // <3:1 against the page on dark) plus the accent fill; active pins primary text
75
- Ghost: "bg-transparent text-foreground hover:bg-accent hover:ring-1 hover:ring-inset hover:ring-ring active:bg-accent active:text-primary active:ring-0 disabled:text-muted-foreground disabled:bg-transparent",
76
- Link: "bg-transparent text-primary underline-offset-4 hover:underline hover:text-foreground rounded-none px-0 disabled:text-muted-foreground disabled:no-underline"
75
+ Ghost: "bg-transparent text-foreground hover:bg-accent hover:ring-1 hover:ring-inset hover:ring-ring active:bg-accent active:text-action active:ring-0 disabled:text-muted-foreground disabled:bg-transparent",
76
+ Link: "bg-transparent text-link underline-offset-4 hover:underline hover:text-foreground rounded-none px-0 disabled:text-muted-foreground disabled:no-underline"
77
77
  },
78
78
  size: {
79
79
  // padding = Figma spacing/3 + spacing/2 ; type = Label Small (11/16, +0.5 tracking)
@@ -102,14 +102,14 @@ var buttonVariants = cva(
102
102
  },
103
103
  compoundVariants: [
104
104
  { variant: "Destructive", class: "focus-visible:shadow-focus-destructive" },
105
- { variant: "Primary", state: "Hover", class: "bg-primary/90" },
106
- { variant: "Primary", state: "Active", class: "bg-primary/85" },
105
+ { variant: "Primary", state: "Hover", class: "bg-action/90" },
106
+ { variant: "Primary", state: "Active", class: "bg-action/85" },
107
107
  { variant: "Secondary", state: "Hover", class: "bg-secondary-foreground text-secondary" },
108
108
  { variant: "Secondary", state: "Active", class: "bg-secondary-foreground text-secondary" },
109
109
  { variant: "Outline", state: "Hover", class: "border-ring bg-accent" },
110
- { variant: "Outline", state: "Active", class: "border-primary bg-accent text-primary" },
110
+ { variant: "Outline", state: "Active", class: "border-action bg-accent text-action" },
111
111
  { variant: "Ghost", state: "Hover", class: "bg-accent ring-1 ring-inset ring-ring" },
112
- { variant: "Ghost", state: "Active", class: "bg-accent text-primary" },
112
+ { variant: "Ghost", state: "Active", class: "bg-accent text-action" },
113
113
  { variant: "Link", state: "Hover", class: "underline text-foreground" },
114
114
  { variant: "Link", size: ["sm", "md", "lg"], class: "py-2 px-0 h-auto" }
115
115
  ],
@@ -145,7 +145,7 @@ var inputVariants = cva2(
145
145
  "font-sans text-body-md text-foreground",
146
146
  "placeholder:text-muted-foreground",
147
147
  "outline-none transition-colors",
148
- "focus-visible:border-primary focus-visible:shadow-focus",
148
+ "focus-visible:border-action focus-visible:shadow-focus",
149
149
  "disabled:cursor-not-allowed disabled:opacity-disabled",
150
150
  "aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive"
151
151
  ],
@@ -153,7 +153,7 @@ var inputVariants = cva2(
153
153
  variants: {
154
154
  state: {
155
155
  Default: "",
156
- Focus: "border-primary shadow-focus",
156
+ Focus: "border-action shadow-focus",
157
157
  Error: "border-destructive",
158
158
  Disabled: "opacity-disabled pointer-events-none"
159
159
  },
@@ -195,7 +195,7 @@ var textareaVariants = cva3(
195
195
  "font-sans text-body-md text-foreground",
196
196
  "placeholder:text-muted-foreground",
197
197
  "outline-none transition-colors",
198
- "focus-visible:border-primary focus-visible:shadow-focus",
198
+ "focus-visible:border-action focus-visible:shadow-focus",
199
199
  "disabled:cursor-not-allowed disabled:opacity-disabled",
200
200
  "aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive"
201
201
  ],
@@ -203,7 +203,7 @@ var textareaVariants = cva3(
203
203
  variants: {
204
204
  state: {
205
205
  Default: "",
206
- Focus: "border-primary shadow-focus",
206
+ Focus: "border-action shadow-focus",
207
207
  Error: "border-destructive",
208
208
  Disabled: "opacity-disabled pointer-events-none resize-none"
209
209
  }
@@ -429,7 +429,7 @@ var badgeVariants = cva5(
429
429
  {
430
430
  variants: {
431
431
  variant: {
432
- default: "bg-primary text-primary-foreground",
432
+ default: "bg-action text-action-foreground",
433
433
  secondary: "bg-secondary-foreground text-secondary",
434
434
  destructive: "bg-destructive text-destructive-foreground",
435
435
  outline: "border border-input text-foreground",
@@ -546,8 +546,8 @@ var Checkbox = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__
546
546
  "peer size-[18px] shrink-0 rounded-sm border-2 border-input outline-none transition-colors",
547
547
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
548
548
  "disabled:cursor-not-allowed disabled:opacity-disabled",
549
- "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
550
- "data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground",
549
+ "data-[state=checked]:border-action data-[state=checked]:bg-action data-[state=checked]:text-action-foreground",
550
+ "data-[state=indeterminate]:border-action data-[state=indeterminate]:bg-action data-[state=indeterminate]:text-action-foreground",
551
551
  "aria-invalid:border-destructive aria-invalid:data-[state=checked]:border-destructive aria-invalid:data-[state=checked]:bg-destructive",
552
552
  className
553
553
  ),
@@ -814,7 +814,7 @@ var Progress = React18.forwardRef(({ className, value, ...props }, ref) => /* @_
814
814
  children: /* @__PURE__ */ jsx19(
815
815
  ProgressPrimitive.Indicator,
816
816
  {
817
- className: "size-full flex-1 bg-primary transition-transform",
817
+ className: "size-full flex-1 bg-action transition-transform",
818
818
  style: { transform: `translateX(-${100 - (value || 0)}%)` }
819
819
  }
820
820
  )
@@ -834,15 +834,15 @@ var RadioGroupItem = React19.forwardRef(({ className, ...props }, ref) => /* @__
834
834
  {
835
835
  ref,
836
836
  className: cn(
837
- "aspect-square size-[18px] rounded-full border-2 border-input text-primary outline-none transition-colors",
837
+ "aspect-square size-[18px] rounded-full border-2 border-input text-action outline-none transition-colors",
838
838
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
839
839
  "disabled:cursor-not-allowed disabled:opacity-disabled",
840
- "data-[state=checked]:border-primary",
840
+ "data-[state=checked]:border-action",
841
841
  "aria-invalid:border-destructive",
842
842
  className
843
843
  ),
844
844
  ...props,
845
- children: /* @__PURE__ */ jsx20(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx20(Circle2, { className: "size-2.5 fill-primary text-primary" }) })
845
+ children: /* @__PURE__ */ jsx20(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx20(Circle2, { className: "size-2.5 fill-action text-action" }) })
846
846
  }
847
847
  ));
848
848
  RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
@@ -852,7 +852,7 @@ import * as React20 from "react";
852
852
  import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
853
853
  import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
854
854
  var ScrollArea = React20.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs8(ScrollAreaPrimitive.Root, { ref, className: cn("relative overflow-hidden", className), ...props, children: [
855
- /* @__PURE__ */ jsx21(ScrollAreaPrimitive.Viewport, { className: "size-full rounded-[inherit]", children }),
855
+ /* @__PURE__ */ jsx21(ScrollAreaPrimitive.Viewport, { tabIndex: 0, className: "size-full rounded-[inherit] outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", children }),
856
856
  /* @__PURE__ */ jsx21(ScrollBar, {}),
857
857
  /* @__PURE__ */ jsx21(ScrollAreaPrimitive.Corner, {})
858
858
  ] }));
@@ -891,8 +891,8 @@ var SelectTrigger = React21.forwardRef(({ className, children, ...props }, ref)
891
891
  "font-sans text-body-md text-foreground",
892
892
  "data-[placeholder]:text-muted-foreground [&>span]:line-clamp-1",
893
893
  "outline-none transition-colors",
894
- "focus:border-primary focus:shadow-focus",
895
- "data-[state=open]:border-primary",
894
+ "focus:border-action focus:shadow-focus",
895
+ "data-[state=open]:border-action",
896
896
  "aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:border-destructive aria-[invalid=true]:focus:shadow-focus-destructive",
897
897
  "disabled:cursor-not-allowed disabled:opacity-disabled",
898
898
  className
@@ -1111,7 +1111,7 @@ function Modal({
1111
1111
  // src/components/skeleton.tsx
1112
1112
  import { jsx as jsx26 } from "react/jsx-runtime";
1113
1113
  function Skeleton({ className, ...props }) {
1114
- return /* @__PURE__ */ jsx26("div", { className: cn("animate-pulse rounded-md bg-muted", className), ...props });
1114
+ return /* @__PURE__ */ jsx26("div", { className: cn("animate-pulse rounded-md bg-muted motion-reduce:animate-none", className), ...props });
1115
1115
  }
1116
1116
 
1117
1117
  // src/components/slider.tsx
@@ -1125,13 +1125,13 @@ var Slider = React24.forwardRef(({ className, "aria-label": ariaLabel, "aria-lab
1125
1125
  className: cn("relative flex w-full touch-none select-none items-center", className),
1126
1126
  ...props,
1127
1127
  children: [
1128
- /* @__PURE__ */ jsx27(SliderPrimitive.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx27(SliderPrimitive.Range, { className: "absolute h-full bg-primary" }) }),
1128
+ /* @__PURE__ */ jsx27(SliderPrimitive.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx27(SliderPrimitive.Range, { className: "absolute h-full bg-action" }) }),
1129
1129
  /* @__PURE__ */ jsx27(
1130
1130
  SliderPrimitive.Thumb,
1131
1131
  {
1132
1132
  "aria-label": ariaLabel,
1133
1133
  "aria-labelledby": ariaLabelledBy,
1134
- className: "block size-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-disabled"
1134
+ className: "block size-4 rounded-full border border-action/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-disabled"
1135
1135
  }
1136
1136
  )
1137
1137
  ]
@@ -1152,7 +1152,7 @@ function Toaster({ theme = "system", ...props }) {
1152
1152
  classNames: {
1153
1153
  toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
1154
1154
  description: "group-[.toast]:text-muted-foreground",
1155
- actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
1155
+ actionButton: "group-[.toast]:bg-action group-[.toast]:text-action-foreground",
1156
1156
  cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground"
1157
1157
  }
1158
1158
  },
@@ -1173,7 +1173,7 @@ var Switch = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
1173
1173
  "peer inline-flex h-6 w-12 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors",
1174
1174
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1175
1175
  "disabled:cursor-not-allowed disabled:opacity-disabled",
1176
- "data-[state=checked]:bg-primary data-[state=unchecked]:bg-tertiary",
1176
+ "data-[state=checked]:bg-action data-[state=unchecked]:bg-tertiary",
1177
1177
  className
1178
1178
  ),
1179
1179
  ...props,
@@ -1386,7 +1386,7 @@ var TooltipContent = React31.forwardRef(({ className, sideOffset = 4, ...props }
1386
1386
  ref,
1387
1387
  sideOffset,
1388
1388
  className: cn(
1389
- "z-overlay overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground font-sans",
1389
+ "z-overlay overflow-hidden rounded-md bg-action px-3 py-1.5 text-xs text-action-foreground font-sans",
1390
1390
  "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1391
1391
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1392
1392
  className
@@ -1438,7 +1438,7 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
1438
1438
  ),
1439
1439
  day_button: cn(
1440
1440
  buttonVariants({ variant: "Ghost", size: "icon" }),
1441
- "size-8 p-0 font-normal group-aria-selected:opacity-visible group-data-[selected=true]:bg-primary group-data-[selected=true]:text-primary-foreground group-data-[selected=true]:hover:bg-primary group-data-[selected=true]:hover:text-primary-foreground group-data-[selected=true]:focus:bg-primary group-data-[selected=true]:focus:text-primary-foreground"
1441
+ "size-8 p-0 font-normal group-aria-selected:opacity-visible group-data-[selected=true]:bg-action group-data-[selected=true]:text-action-foreground group-data-[selected=true]:hover:bg-action group-data-[selected=true]:hover:text-action-foreground group-data-[selected=true]:focus:bg-action group-data-[selected=true]:focus:text-action-foreground"
1442
1442
  ),
1443
1443
  range_start: "day-range-start rounded-l-md",
1444
1444
  range_end: "day-range-end rounded-r-md",
@@ -1662,7 +1662,7 @@ var ChartContainer = React33.forwardRef(({
1662
1662
  role: role ?? "img",
1663
1663
  "aria-label": name,
1664
1664
  className: cn(
1665
- "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
1665
+ "flex aspect-video justify-center text-xs [&_.recharts-surface:focus-visible]:[outline:2px_solid_hsl(var(--ring))] [&_.recharts-surface:focus-visible]:rounded-sm [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
1666
1666
  className
1667
1667
  ),
1668
1668
  ...props,
@@ -1696,7 +1696,7 @@ function ChartState({
1696
1696
  state === "loading" ? /* @__PURE__ */ jsx38("div", { "aria-hidden": true, className: "flex w-full max-w-[220px] items-end justify-between gap-1.5", children: [40, 72, 56, 88, 48, 64, 80].map((h, i) => /* @__PURE__ */ jsx38(
1697
1697
  "span",
1698
1698
  {
1699
- className: "w-full animate-pulse rounded-sm bg-muted",
1699
+ className: "w-full animate-pulse rounded-sm bg-muted motion-reduce:animate-none",
1700
1700
  style: { height: `${h}px`, animationDelay: `${i * 90}ms` }
1701
1701
  },
1702
1702
  i
@@ -2189,7 +2189,7 @@ var InputGroup = React40.forwardRef(
2189
2189
  "data-slot": "input-group",
2190
2190
  className: cn(
2191
2191
  "flex w-full items-center overflow-hidden rounded-sm border border-input bg-background font-sans transition-colors",
2192
- "focus-within:border-primary focus-within:shadow-focus",
2192
+ "focus-within:border-action focus-within:shadow-focus",
2193
2193
  "has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:focus-within:shadow-focus-destructive",
2194
2194
  "has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-disabled",
2195
2195
  className
@@ -2276,7 +2276,8 @@ var InputOTPSlot = React41.forwardRef(({ index, className, ...props }, ref) => {
2276
2276
  ref,
2277
2277
  className: cn(
2278
2278
  "relative flex size-9 items-center justify-center border-y border-r border-input text-sm shadow-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
2279
- isActive && "z-docked ring-1 ring-ring",
2279
+ // ring is a box-shadow, which forced-colors mode strips; the outline survives it
2280
+ isActive && "z-docked ring-1 ring-ring forced-colors:[outline:2px_solid] forced-colors:[outline-offset:-2px]",
2280
2281
  className
2281
2282
  ),
2282
2283
  ...props,
@@ -2826,7 +2827,7 @@ var AudioPlayer = React46.forwardRef(
2826
2827
  type: "button",
2827
2828
  onClick: toggle,
2828
2829
  "aria-label": playing ? "Pause" : "Play",
2829
- className: "grid shrink-0 place-items-center rounded-full bg-primary text-primary-foreground outline-none transition-transform hover:scale-105 focus-visible:shadow-focus",
2830
+ className: "grid shrink-0 place-items-center rounded-full bg-action text-action-foreground outline-none transition-transform hover:scale-105 focus-visible:shadow-focus",
2830
2831
  style: { width: size, height: size },
2831
2832
  children: playing ? /* @__PURE__ */ jsx52(Pause, { className: "size-1/3 fill-current" }) : /* @__PURE__ */ jsx52(Play, { className: "size-1/3 translate-x-px fill-current" })
2832
2833
  }
@@ -2852,7 +2853,7 @@ var AudioPlayer = React46.forwardRef(
2852
2853
  ] }),
2853
2854
  /* @__PURE__ */ jsx52("button", { type: "button", onClick: () => skip(skipBy), "aria-label": `Forward ${skipBy}s`, className: iconBtn, children: /* @__PURE__ */ jsx52(SkipForward, {}) }),
2854
2855
  /* @__PURE__ */ jsx52(PlayPause, { size: 36 }),
2855
- /* @__PURE__ */ jsx52("div", { className: "absolute inset-x-0 bottom-0 h-1 bg-muted", children: /* @__PURE__ */ jsx52("div", { className: "h-full bg-primary transition-[width]", style: { width: `${pct}%` } }) })
2856
+ /* @__PURE__ */ jsx52("div", { className: "absolute inset-x-0 bottom-0 h-1 bg-muted", children: /* @__PURE__ */ jsx52("div", { className: "h-full bg-action transition-[width]", style: { width: `${pct}%` } }) })
2856
2857
  ]
2857
2858
  }
2858
2859
  );
@@ -2936,7 +2937,7 @@ var CircularProgress = React47.forwardRef(
2936
2937
  strokeLinecap: "round",
2937
2938
  strokeDasharray: c,
2938
2939
  strokeDashoffset: c - v / 100 * c,
2939
- className: "stroke-primary transition-[stroke-dashoffset] duration-base"
2940
+ className: "stroke-action transition-[stroke-dashoffset] duration-base"
2940
2941
  }
2941
2942
  )
2942
2943
  ] }),
@@ -3149,7 +3150,7 @@ Rating.displayName = "Rating";
3149
3150
  import * as React51 from "react";
3150
3151
  import { cva as cva16 } from "class-variance-authority";
3151
3152
  import { jsx as jsx57 } from "react/jsx-runtime";
3152
- var spinnerVariants = cva16("inline-block animate-spin rounded-full border-2 border-current border-t-transparent", {
3153
+ var spinnerVariants = cva16("inline-block animate-spin motion-reduce:animate-[spin_3s_linear_infinite] rounded-full border-2 border-current border-t-transparent", {
3153
3154
  variants: {
3154
3155
  size: {
3155
3156
  sm: "size-4",
@@ -3157,9 +3158,9 @@ var spinnerVariants = cva16("inline-block animate-spin rounded-full border-2 bor
3157
3158
  lg: "size-8"
3158
3159
  },
3159
3160
  variant: {
3160
- default: "text-primary",
3161
+ default: "text-action",
3161
3162
  muted: "text-muted-foreground",
3162
- onColor: "text-primary-foreground"
3163
+ onColor: "text-action-foreground"
3163
3164
  }
3164
3165
  },
3165
3166
  defaultVariants: { size: "md", variant: "default" }
@@ -3171,7 +3172,7 @@ Spinner.displayName = "Spinner";
3171
3172
 
3172
3173
  // src/components/list.tsx
3173
3174
  import * as React52 from "react";
3174
- import { jsx as jsx58, jsxs as jsxs29 } from "react/jsx-runtime";
3175
+ import { Fragment, jsx as jsx58, jsxs as jsxs29 } from "react/jsx-runtime";
3175
3176
  var List3 = React52.forwardRef(
3176
3177
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx58("div", { ref, role: "list", className: cn("flex flex-col divide-y divide-border", className), ...props })
3177
3178
  );
@@ -3179,38 +3180,42 @@ List3.displayName = "List";
3179
3180
  var ListItem = React52.forwardRef(
3180
3181
  ({ className, leading, title, description, trailing, disabled, onSelect, ...props }, ref) => {
3181
3182
  const interactive = !!onSelect && !disabled;
3182
- return /* @__PURE__ */ jsxs29(
3183
+ const rowClass = cn(
3184
+ "flex items-center gap-3 px-3 py-3 font-sans outline-none",
3185
+ // ring keeps the highlighted row perceptible where the accent fill is <3:1 (dark)
3186
+ interactive && "cursor-pointer hover:bg-accent hover:ring-1 hover:ring-inset hover:ring-ring focus-visible:bg-accent focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
3187
+ disabled && "pointer-events-none opacity-disabled",
3188
+ className
3189
+ );
3190
+ const content = /* @__PURE__ */ jsxs29(Fragment, { children: [
3191
+ leading && /* @__PURE__ */ jsx58("div", { className: "flex shrink-0 items-center justify-center", children: leading }),
3192
+ /* @__PURE__ */ jsxs29("div", { className: "min-w-0 flex-1", children: [
3193
+ /* @__PURE__ */ jsx58("div", { className: "truncate text-body-md text-foreground", children: title }),
3194
+ description && /* @__PURE__ */ jsx58("div", { className: "truncate text-body-sm text-muted-foreground", children: description })
3195
+ ] }),
3196
+ trailing && /* @__PURE__ */ jsx58("div", { className: "flex shrink-0 items-center gap-2", children: trailing })
3197
+ ] });
3198
+ if (!interactive) {
3199
+ return /* @__PURE__ */ jsx58("div", { ref, role: "listitem", "aria-disabled": disabled, className: rowClass, ...props, children: content });
3200
+ }
3201
+ return /* @__PURE__ */ jsx58("div", { role: "listitem", children: /* @__PURE__ */ jsx58(
3183
3202
  "div",
3184
3203
  {
3185
3204
  ref,
3186
- role: interactive ? "button" : "listitem",
3187
- tabIndex: interactive ? 0 : void 0,
3188
- "aria-disabled": disabled,
3189
- onClick: disabled ? void 0 : onSelect,
3190
- onKeyDown: interactive ? (e) => {
3205
+ role: "button",
3206
+ tabIndex: 0,
3207
+ onClick: onSelect,
3208
+ onKeyDown: (e) => {
3191
3209
  if (e.key === "Enter" || e.key === " ") {
3192
3210
  e.preventDefault();
3193
3211
  onSelect?.();
3194
3212
  }
3195
- } : void 0,
3196
- className: cn(
3197
- "flex items-center gap-3 px-3 py-3 font-sans outline-none",
3198
- // ring keeps the highlighted row perceptible where the accent fill is <3:1 (dark)
3199
- interactive && "cursor-pointer hover:bg-accent hover:ring-1 hover:ring-inset hover:ring-ring focus-visible:bg-accent focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
3200
- disabled && "pointer-events-none opacity-disabled",
3201
- className
3202
- ),
3213
+ },
3214
+ className: rowClass,
3203
3215
  ...props,
3204
- children: [
3205
- leading && /* @__PURE__ */ jsx58("div", { className: "flex shrink-0 items-center justify-center", children: leading }),
3206
- /* @__PURE__ */ jsxs29("div", { className: "min-w-0 flex-1", children: [
3207
- /* @__PURE__ */ jsx58("div", { className: "truncate text-body-md text-foreground", children: title }),
3208
- description && /* @__PURE__ */ jsx58("div", { className: "truncate text-body-sm text-muted-foreground", children: description })
3209
- ] }),
3210
- trailing && /* @__PURE__ */ jsx58("div", { className: "flex shrink-0 items-center gap-2", children: trailing })
3211
- ]
3216
+ children: content
3212
3217
  }
3213
- );
3218
+ ) });
3214
3219
  }
3215
3220
  );
3216
3221
  ListItem.displayName = "ListItem";
@@ -3237,8 +3242,8 @@ var Stepper = React53.forwardRef(
3237
3242
  {
3238
3243
  className: cn(
3239
3244
  "flex size-7 shrink-0 items-center justify-center rounded-full text-label-md font-medium",
3240
- status === "complete" && "bg-primary text-primary-foreground",
3241
- status === "current" && "border-2 border-primary text-primary",
3245
+ status === "complete" && "bg-action text-action-foreground",
3246
+ status === "current" && "border-2 border-action text-action",
3242
3247
  status === "upcoming" && "border border-input text-muted-foreground"
3243
3248
  ),
3244
3249
  children: status === "complete" ? /* @__PURE__ */ jsx59(Check6, { className: "size-4" }) : i + 1
@@ -3251,7 +3256,7 @@ var Stepper = React53.forwardRef(
3251
3256
  className: cn(
3252
3257
  "bg-border",
3253
3258
  vertical ? "my-1 min-h-6 w-px flex-1 self-stretch" : "mt-3.5 h-px flex-1",
3254
- status === "complete" && "bg-primary"
3259
+ status === "complete" && "bg-action"
3255
3260
  )
3256
3261
  }
3257
3262
  )
@@ -3284,7 +3289,7 @@ var fabVariants = cva17(
3284
3289
  {
3285
3290
  variants: {
3286
3291
  variant: {
3287
- Primary: "bg-primary text-primary-foreground hover:bg-[--color-blue-600] active:bg-[--color-blue-700]",
3292
+ Primary: "bg-action text-action-foreground hover:bg-action/90 active:bg-action/85",
3288
3293
  Secondary: "bg-secondary text-secondary-foreground hover:bg-[--color-green-500] hover:text-[--color-green-50] active:bg-[--color-green-600] active:text-[--color-green-50]"
3289
3294
  },
3290
3295
  size: {
@@ -3339,7 +3344,7 @@ var TabBarItem = React55.forwardRef(
3339
3344
  "aria-current": active ? "page" : void 0,
3340
3345
  className: cn(
3341
3346
  "relative flex flex-1 flex-col items-center justify-center gap-1 py-2 text-label-sm outline-none transition-colors",
3342
- active ? "text-primary" : "text-muted-foreground hover:text-foreground",
3347
+ active ? "text-action" : "text-muted-foreground hover:text-foreground",
3343
3348
  "focus-visible:bg-accent",
3344
3349
  className
3345
3350
  ),
@@ -3509,16 +3514,7 @@ var FileUpload = React58.forwardRef(
3509
3514
  /* @__PURE__ */ jsxs34(
3510
3515
  "div",
3511
3516
  {
3512
- role: "button",
3513
- tabIndex: disabled ? -1 : 0,
3514
- "aria-disabled": disabled,
3515
3517
  onClick: () => !disabled && inputRef.current?.click(),
3516
- onKeyDown: (e) => {
3517
- if (!disabled && (e.key === "Enter" || e.key === " ")) {
3518
- e.preventDefault();
3519
- inputRef.current?.click();
3520
- }
3521
- },
3522
3518
  onDragOver: (e) => {
3523
3519
  e.preventDefault();
3524
3520
  if (!disabled) setDragging(true);
@@ -3530,9 +3526,9 @@ var FileUpload = React58.forwardRef(
3530
3526
  if (!disabled) pick(e.dataTransfer.files);
3531
3527
  },
3532
3528
  className: cn(
3533
- "flex flex-col items-center gap-2 rounded-md border border-dashed border-input p-6 text-center outline-none transition-colors",
3534
- !disabled && "cursor-pointer hover:bg-accent/50 focus-visible:shadow-focus",
3535
- dragging && "border-primary bg-accent",
3529
+ "flex flex-col items-center gap-2 rounded-md border border-dashed border-input p-6 text-center transition-colors",
3530
+ !disabled && "cursor-pointer hover:bg-accent/50",
3531
+ dragging && "border-action bg-accent",
3536
3532
  disabled && "pointer-events-none opacity-disabled"
3537
3533
  ),
3538
3534
  children: [
@@ -3565,6 +3561,8 @@ var FileUpload = React58.forwardRef(
3565
3561
  multiple,
3566
3562
  accept,
3567
3563
  disabled,
3564
+ tabIndex: -1,
3565
+ "aria-hidden": "true",
3568
3566
  className: "sr-only",
3569
3567
  onChange: (e) => {
3570
3568
  pick(e.target.files);
@@ -3584,18 +3582,18 @@ function FileUploadItem({ file, onRemove, onRetry }) {
3584
3582
  const isError = file.status === "error";
3585
3583
  const isLoading = file.status === "loading";
3586
3584
  return /* @__PURE__ */ jsxs34("li", { className: cn("flex items-center gap-2.5 rounded-md border p-2.5 text-body-sm", isError ? "border-destructive bg-destructive/5" : "border-input"), children: [
3587
- isLoading ? /* @__PURE__ */ jsx64(Loader2, { className: "size-4 shrink-0 animate-spin text-muted-foreground", "aria-hidden": true }) : isError ? /* @__PURE__ */ jsx64(TriangleAlert3, { className: "size-4 shrink-0 text-destructive", "aria-hidden": true }) : /* @__PURE__ */ jsx64(File, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
3585
+ isLoading ? /* @__PURE__ */ jsx64(Loader2, { className: "size-4 shrink-0 animate-spin motion-reduce:animate-[spin_3s_linear_infinite] text-muted-foreground", "aria-hidden": true }) : isError ? /* @__PURE__ */ jsx64(TriangleAlert3, { className: "size-4 shrink-0 text-destructive", "aria-hidden": true }) : /* @__PURE__ */ jsx64(File, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
3588
3586
  /* @__PURE__ */ jsxs34("div", { className: "min-w-0 flex-1", children: [
3589
3587
  /* @__PURE__ */ jsx64("p", { className: "truncate text-foreground", children: file.name }),
3590
3588
  isError && file.error ? /* @__PURE__ */ jsx64("p", { className: "text-destructive", children: file.error }) : /* @__PURE__ */ jsx64("p", { className: "text-muted-foreground", children: formatBytes(file.size) }),
3591
- isLoading && typeof file.progress === "number" && /* @__PURE__ */ jsx64("div", { className: "mt-1 h-1 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx64("div", { className: "h-full bg-primary transition-[width]", style: { width: `${Math.max(0, Math.min(100, file.progress))}%` } }) })
3589
+ isLoading && typeof file.progress === "number" && /* @__PURE__ */ jsx64("div", { className: "mt-1 h-1 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx64("div", { className: "h-full bg-action transition-[width]", style: { width: `${Math.max(0, Math.min(100, file.progress))}%` } }) })
3592
3590
  ] }),
3593
3591
  isError && onRetry && /* @__PURE__ */ jsx64(
3594
3592
  "button",
3595
3593
  {
3596
3594
  type: "button",
3597
3595
  onClick: () => onRetry(file.id),
3598
- className: "shrink-0 text-label-md font-medium text-primary underline-offset-2 outline-none hover:underline focus-visible:underline",
3596
+ className: "shrink-0 text-label-md font-medium text-link underline-offset-2 outline-none hover:underline focus-visible:underline",
3599
3597
  children: "Retry"
3600
3598
  }
3601
3599
  ),
@@ -3685,7 +3683,7 @@ var CodeBlock = React60.forwardRef(
3685
3683
  onClick: () => setActive(i),
3686
3684
  className: cn(
3687
3685
  "border-b-2 px-3 py-2 text-body-sm transition-colors outline-none",
3688
- i === active ? "border-primary text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3686
+ i === active ? "border-action text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3689
3687
  ),
3690
3688
  children: t.name || "code"
3691
3689
  },
@@ -3908,7 +3906,7 @@ var TableOfContents = React65.forwardRef(
3908
3906
  style: { paddingInlineStart: `${((item.level ?? 1) - 1) * 12 + 12}px` },
3909
3907
  className: cn(
3910
3908
  "-ms-px border-s py-1.5 text-body-sm outline-none transition-colors",
3911
- isActive ? "border-primary font-medium text-primary" : "border-transparent text-muted-foreground hover:text-foreground"
3909
+ isActive ? "border-action font-medium text-action" : "border-transparent text-muted-foreground hover:text-foreground"
3912
3910
  ),
3913
3911
  children: item.label
3914
3912
  },
@@ -4044,7 +4042,7 @@ var nativeSelectVariants = cva19(
4044
4042
  "flex w-full appearance-none border border-input bg-background px-3 py-3 pe-9",
4045
4043
  "font-sans text-body-md text-foreground",
4046
4044
  "outline-none transition-colors",
4047
- "focus-visible:border-primary focus-visible:shadow-focus",
4045
+ "focus-visible:border-action focus-visible:shadow-focus",
4048
4046
  "disabled:cursor-not-allowed disabled:opacity-disabled",
4049
4047
  "aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive aria-[invalid=true]:focus-visible:shadow-focus-destructive"
4050
4048
  ],
@@ -4052,7 +4050,7 @@ var nativeSelectVariants = cva19(
4052
4050
  variants: {
4053
4051
  state: {
4054
4052
  Default: "",
4055
- Focus: "border-primary shadow-focus",
4053
+ Focus: "border-action shadow-focus",
4056
4054
  Error: "border-destructive",
4057
4055
  Disabled: "opacity-disabled pointer-events-none"
4058
4056
  },
@@ -4167,7 +4165,7 @@ var ICON2 = {
4167
4165
  var Banner = React71.forwardRef(
4168
4166
  ({ className, variant = "information", sticky, hideIcon, onDismiss, action, children, ...props }, ref) => {
4169
4167
  const Icon2 = ICON2[variant ?? "information"];
4170
- return /* @__PURE__ */ jsxs43("div", { ref, role: "banner", className: cn(bannerVariants({ variant, sticky }), className), ...props, children: [
4168
+ return /* @__PURE__ */ jsxs43("div", { ref, className: cn(bannerVariants({ variant, sticky }), className), ...props, children: [
4171
4169
  !hideIcon && /* @__PURE__ */ jsx77(Icon2, {}),
4172
4170
  /* @__PURE__ */ jsxs43("div", { className: "mx-auto flex min-w-0 max-w-4xl flex-1 flex-wrap items-center justify-center gap-x-3 gap-y-1 text-center", children: [
4173
4171
  /* @__PURE__ */ jsx77("span", { children }),
@@ -4235,7 +4233,7 @@ var Body = ({ item, align }) => /* @__PURE__ */ jsxs44("div", { className: cn("p
4235
4233
  item.content && /* @__PURE__ */ jsx79("div", { className: "text-body-sm text-muted-foreground", children: item.content })
4236
4234
  ] });
4237
4235
  var Rail = ({ item, isLast }) => /* @__PURE__ */ jsxs44("div", { className: "flex flex-col items-center", children: [
4238
- /* @__PURE__ */ jsx79("span", { className: "flex size-2.5 shrink-0 items-center justify-center rounded-full bg-primary", children: item.icon }),
4236
+ /* @__PURE__ */ jsx79("span", { className: "flex size-2.5 shrink-0 items-center justify-center rounded-full bg-action", children: item.icon }),
4239
4237
  !isLast && /* @__PURE__ */ jsx79("span", { "aria-hidden": true, className: "my-1 w-px flex-1 bg-border" })
4240
4238
  ] });
4241
4239
  var Timeline = React73.forwardRef(
@@ -4413,7 +4411,7 @@ var NotificationCenterContent = React77.forwardRef(
4413
4411
  {
4414
4412
  type: "button",
4415
4413
  onClick: onMarkAllRead,
4416
- className: "text-label-md font-medium text-primary outline-none hover:underline focus-visible:underline",
4414
+ className: "text-label-md font-medium text-link outline-none hover:underline focus-visible:underline",
4417
4415
  children: "Mark all read"
4418
4416
  }
4419
4417
  )
@@ -4445,7 +4443,7 @@ var NotificationItem = React77.forwardRef(
4445
4443
  ),
4446
4444
  ...props,
4447
4445
  children: [
4448
- /* @__PURE__ */ jsx83("span", { className: cn("mt-1.5 size-2 shrink-0 rounded-full", unread ? "bg-primary" : "bg-transparent") }),
4446
+ /* @__PURE__ */ jsx83("span", { className: cn("mt-1.5 size-2 shrink-0 rounded-full", unread ? "bg-action" : "bg-transparent") }),
4449
4447
  /* @__PURE__ */ jsxs48("div", { className: "min-w-0 flex-1", children: [
4450
4448
  /* @__PURE__ */ jsx83("p", { className: cn("truncate text-body-sm", unread ? "font-medium text-foreground" : "text-muted-foreground"), children: title }),
4451
4449
  description && /* @__PURE__ */ jsx83("p", { className: "truncate text-body-sm text-muted-foreground", children: description }),
@@ -4700,8 +4698,8 @@ var MultiSelect = React79.forwardRef(
4700
4698
  },
4701
4699
  className: cn(
4702
4700
  "flex min-h-11 w-full flex-wrap items-center gap-1.5 border border-input bg-background px-3 py-2 font-sans",
4703
- "outline-none focus-visible:border-primary focus-visible:shadow-focus",
4704
- "aria-expanded:border-primary aria-expanded:shadow-focus",
4701
+ "outline-none focus-visible:border-action focus-visible:shadow-focus",
4702
+ "aria-expanded:border-action aria-expanded:shadow-focus",
4705
4703
  className
4706
4704
  ),
4707
4705
  ...props,
@@ -4721,7 +4719,20 @@ var MultiSelect = React79.forwardRef(
4721
4719
  anchorRef.current?.focus();
4722
4720
  },
4723
4721
  children: /* @__PURE__ */ jsxs50(Command, { shouldFilter: !creatable, children: [
4724
- /* @__PURE__ */ jsx85(CommandInput, { placeholder: "Search\u2026", value: query, onValueChange: setQuery }),
4722
+ /* @__PURE__ */ jsx85(
4723
+ CommandInput,
4724
+ {
4725
+ placeholder: "Search\u2026",
4726
+ value: query,
4727
+ onValueChange: setQuery,
4728
+ onKeyDown: (e) => {
4729
+ if (e.key === "Backspace" && query === "" && current.length > 0) {
4730
+ e.preventDefault();
4731
+ remove(current[current.length - 1]);
4732
+ }
4733
+ }
4734
+ }
4735
+ ),
4725
4736
  /* @__PURE__ */ jsxs50(CommandList, { children: [
4726
4737
  /* @__PURE__ */ jsx85(CommandEmpty, { children: canCreate ? /* @__PURE__ */ jsxs50(
4727
4738
  "button",
@@ -4767,7 +4778,7 @@ var MessageBubble = React80.forwardRef(
4767
4778
  {
4768
4779
  className: cn(
4769
4780
  "min-w-0 rounded-2xl px-3.5 py-2 text-body-sm",
4770
- sent ? "bg-primary text-primary-foreground" : "bg-muted text-foreground",
4781
+ sent ? "bg-action text-action-foreground" : "bg-muted text-foreground",
4771
4782
  sent && grouped && "rounded-tr-md",
4772
4783
  !sent && grouped && "rounded-tl-md"
4773
4784
  ),
@@ -4776,7 +4787,7 @@ var MessageBubble = React80.forwardRef(
4776
4787
  ),
4777
4788
  (timestamp || sent && status) && /* @__PURE__ */ jsxs51("div", { className: "flex items-center gap-1 px-1 text-label-sm text-muted-foreground", children: [
4778
4789
  timestamp,
4779
- sent && status && /* @__PURE__ */ jsx86("span", { className: cn(status === "read" && "text-primary"), children: status === "sent" ? /* @__PURE__ */ jsx86(Check9, { className: "size-3.5" }) : /* @__PURE__ */ jsx86(CheckCheck, { className: "size-3.5" }) })
4790
+ sent && status && /* @__PURE__ */ jsx86("span", { className: cn(status === "read" && "text-action"), children: status === "sent" ? /* @__PURE__ */ jsx86(Check9, { className: "size-3.5" }) : /* @__PURE__ */ jsx86(CheckCheck, { className: "size-3.5" }) })
4780
4791
  ] })
4781
4792
  ] })
4782
4793
  ] });
@@ -4796,7 +4807,7 @@ var TypingIndicator = React80.forwardRef(
4796
4807
  "span",
4797
4808
  {
4798
4809
  "aria-hidden": true,
4799
- className: "size-1.5 animate-typing-dot rounded-full bg-muted-foreground",
4810
+ className: "size-1.5 animate-typing-dot motion-reduce:animate-none motion-reduce:opacity-70 rounded-full bg-muted-foreground",
4800
4811
  style: { animationDelay: `${i * 150}ms` }
4801
4812
  },
4802
4813
  i
@@ -4809,7 +4820,7 @@ TypingIndicator.displayName = "TypingIndicator";
4809
4820
  // src/components/tour.tsx
4810
4821
  import * as React81 from "react";
4811
4822
  import { createPortal } from "react-dom";
4812
- import { Fragment, jsx as jsx87, jsxs as jsxs52 } from "react/jsx-runtime";
4823
+ import { Fragment as Fragment2, jsx as jsx87, jsxs as jsxs52 } from "react/jsx-runtime";
4813
4824
  var SPOTLIGHT_PADDING = 8;
4814
4825
  var Tour = ({
4815
4826
  steps,
@@ -4898,7 +4909,7 @@ var Tour = ({
4898
4909
  left: Math.min(Math.max(rect.left, 16), window.innerWidth - 336)
4899
4910
  } : { top: "50%", left: "50%", transform: "translate(-50%, -50%)" };
4900
4911
  return createPortal(
4901
- /* @__PURE__ */ jsxs52(Fragment, { children: [
4912
+ /* @__PURE__ */ jsxs52(Fragment2, { children: [
4902
4913
  /* @__PURE__ */ jsx87(
4903
4914
  "div",
4904
4915
  {
@@ -4929,7 +4940,7 @@ var Tour = ({
4929
4940
  ] }),
4930
4941
  /* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-2", children: [
4931
4942
  !isFirst && /* @__PURE__ */ jsx87(Button, { variant: "Ghost", size: "sm", onClick: () => onStepIndexChange(stepIndex - 1), children: backLabel }),
4932
- !isLast ? /* @__PURE__ */ jsxs52(Fragment, { children: [
4943
+ !isLast ? /* @__PURE__ */ jsxs52(Fragment2, { children: [
4933
4944
  /* @__PURE__ */ jsx87(Button, { variant: "Link", size: "sm", onClick: () => onOpenChange(false), children: skipLabel }),
4934
4945
  /* @__PURE__ */ jsx87(Button, { size: "sm", onClick: () => onStepIndexChange(stepIndex + 1), children: nextLabel })
4935
4946
  ] }) : /* @__PURE__ */ jsx87(Button, { size: "sm", onClick: () => onOpenChange(false), children: doneLabel })
@@ -4981,7 +4992,8 @@ function VirtualList({
4981
4992
  {
4982
4993
  ref: containerRef,
4983
4994
  role: "list",
4984
- className: cn("overflow-y-auto font-sans", className),
4995
+ tabIndex: 0,
4996
+ className: cn("overflow-y-auto font-sans outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", className),
4985
4997
  style: { height, ...style },
4986
4998
  onScroll: (e) => {
4987
4999
  onScroll?.(e);
@@ -5006,7 +5018,7 @@ function VirtualList({
5006
5018
 
5007
5019
  // src/components/data-grid.tsx
5008
5020
  import * as React83 from "react";
5009
- import { jsx as jsx89, jsxs as jsxs53 } from "react/jsx-runtime";
5021
+ import { Fragment as Fragment3, jsx as jsx89, jsxs as jsxs53 } from "react/jsx-runtime";
5010
5022
  var DEFAULT_WIDTH = 160;
5011
5023
  var DEFAULT_MIN_WIDTH = 60;
5012
5024
  var DEFAULT_ROW_HEIGHT = 40;
@@ -5129,136 +5141,258 @@ function DataGrid({
5129
5141
  column.onCellEdit?.(row, rowIndex, value);
5130
5142
  endEdit(restoreFocus);
5131
5143
  }
5132
- return /* @__PURE__ */ jsx89(
5133
- "div",
5134
- {
5135
- ref: containerRef,
5136
- role: "grid",
5137
- className: cn("relative overflow-auto rounded-md border font-sans text-sm", className),
5138
- style: { height },
5139
- onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
5140
- children: /* @__PURE__ */ jsxs53("div", { style: { width: totalWidth, minWidth: "100%" }, children: [
5141
- /* @__PURE__ */ jsx89("div", { role: "row", className: "sticky top-0 z-[2] flex border-b bg-background", children: renderedColumns.map((column) => {
5142
- const width = widths[column.id] ?? column.width ?? DEFAULT_WIDTH;
5143
- const pinnedStyle = column.pinned === "left" ? { position: "sticky", left: leftOffsets[column.id], zIndex: 3 } : column.pinned === "right" ? { position: "sticky", right: rightOffsets[column.id], zIndex: 3 } : {};
5144
- const isSorted = sort?.columnId === column.id;
5145
- return /* @__PURE__ */ jsxs53(
5146
- "div",
5147
- {
5148
- role: "columnheader",
5149
- ...column.sortable ? { "aria-sort": isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" } : {},
5150
- draggable: !column.pinned,
5151
- onDragStart: () => {
5152
- dragIdRef.current = column.id;
5153
- },
5154
- onDragOver: (e) => {
5155
- if (!column.pinned) e.preventDefault();
5156
- },
5157
- onDrop: (e) => {
5158
- e.preventDefault();
5159
- const draggedId = dragIdRef.current;
5160
- dragIdRef.current = null;
5161
- if (!draggedId || draggedId === column.id) return;
5162
- setOrder((prev) => {
5163
- const next = prev.filter((id) => id !== draggedId);
5164
- const targetIndex = next.indexOf(column.id);
5165
- next.splice(targetIndex, 0, draggedId);
5166
- return next;
5167
- });
5168
- },
5169
- onClick: () => column.sortable && toggleSort(column.id),
5170
- tabIndex: column.sortable ? 0 : void 0,
5171
- onKeyDown: (e) => {
5172
- if (column.sortable && e.target === e.currentTarget && (e.key === "Enter" || e.key === " ")) {
5144
+ const HEADER_HEIGHT = 40;
5145
+ const [active, setActive] = React83.useState({ row: -1, columnId: columns[0]?.id ?? "" });
5146
+ const pendingFocusRef = React83.useRef(null);
5147
+ const [announcement, setAnnouncement] = React83.useState("");
5148
+ const rowCount = sortedData.length;
5149
+ const colIds = renderedColumns.map((c) => c.id);
5150
+ const activeCol = colIds.includes(active.columnId) ? active.columnId : colIds[0] ?? "";
5151
+ const activeRow = Math.min(active.row, rowCount - 1);
5152
+ const activeRendered = activeRow < 0 || activeRow >= startIndex && activeRow < endIndex;
5153
+ const tabStop = { row: activeRendered ? activeRow : -1, columnId: activeCol };
5154
+ const pageRows = Math.max(1, Math.floor((viewportHeight - HEADER_HEIGHT) / rowHeight) - 1);
5155
+ const labelOf = (c) => typeof c.header === "string" ? c.header : c.id;
5156
+ function ensureRowVisible(row) {
5157
+ const el = containerRef.current;
5158
+ if (!el) return;
5159
+ if (row < 0) {
5160
+ if (scrollTop !== 0) {
5161
+ el.scrollTop = 0;
5162
+ setScrollTop(0);
5163
+ }
5164
+ return;
5165
+ }
5166
+ const top = HEADER_HEIGHT + row * rowHeight;
5167
+ const bottom = top + rowHeight;
5168
+ let next = scrollTop;
5169
+ if (top < scrollTop + HEADER_HEIGHT) next = row * rowHeight;
5170
+ else if (bottom > scrollTop + viewportHeight) next = bottom - viewportHeight;
5171
+ if (next !== scrollTop) {
5172
+ el.scrollTop = next;
5173
+ setScrollTop(next);
5174
+ }
5175
+ }
5176
+ function moveTo(row, columnId) {
5177
+ const r = Math.max(-1, Math.min(row, rowCount - 1));
5178
+ ensureRowVisible(r);
5179
+ pendingFocusRef.current = { row: r, columnId };
5180
+ setActive({ row: r, columnId });
5181
+ }
5182
+ React83.useEffect(() => {
5183
+ const p = pendingFocusRef.current;
5184
+ if (!p) return;
5185
+ const selector = p.row < 0 ? `[data-header="${p.columnId}"]` : `[data-cell="${p.row}:${p.columnId}"]`;
5186
+ const el = containerRef.current?.querySelector(selector);
5187
+ if (el) {
5188
+ pendingFocusRef.current = null;
5189
+ el.focus();
5190
+ }
5191
+ });
5192
+ function moveColumn(column, dir) {
5193
+ if (column.pinned) return;
5194
+ const ids = unpinnedOrdered.map((c) => c.id);
5195
+ const from = ids.indexOf(column.id);
5196
+ const to = from + dir;
5197
+ if (to < 0 || to >= ids.length) {
5198
+ setAnnouncement(`${labelOf(column)} is already the ${dir < 0 ? "first" : "last"} movable column`);
5199
+ return;
5200
+ }
5201
+ const targetId = ids[to];
5202
+ setOrder((prev) => {
5203
+ const next = prev.filter((id) => id !== column.id);
5204
+ next.splice(next.indexOf(targetId) + (dir > 0 ? 1 : 0), 0, column.id);
5205
+ return next;
5206
+ });
5207
+ pendingFocusRef.current = { row: -1, columnId: column.id };
5208
+ setAnnouncement(`${labelOf(column)} moved to position ${leftPinned.length + to + 1} of ${colIds.length}`);
5209
+ }
5210
+ function resizeColumn(column, delta) {
5211
+ const current = widths[column.id] ?? column.width ?? DEFAULT_WIDTH;
5212
+ const next = Math.max(column.minWidth ?? DEFAULT_MIN_WIDTH, current + delta);
5213
+ setWidths((prev) => ({ ...prev, [column.id]: next }));
5214
+ setAnnouncement(`${labelOf(column)} column width ${next} pixels`);
5215
+ }
5216
+ function onNavKeyDown(e, row, column) {
5217
+ if (e.target !== e.currentTarget) return;
5218
+ const rtl = getComputedStyle(e.currentTarget).direction === "rtl";
5219
+ const idx = colIds.indexOf(column.id);
5220
+ const horizontal = e.key === "ArrowRight" ? rtl ? -1 : 1 : e.key === "ArrowLeft" ? rtl ? 1 : -1 : 0;
5221
+ if (row < 0 && horizontal !== 0 && (e.altKey || e.shiftKey)) {
5222
+ e.preventDefault();
5223
+ if (e.altKey) moveColumn(column, horizontal);
5224
+ else resizeColumn(column, horizontal * 10);
5225
+ return;
5226
+ }
5227
+ const go = (r, i) => {
5228
+ e.preventDefault();
5229
+ moveTo(r, colIds[Math.max(0, Math.min(i, colIds.length - 1))]);
5230
+ };
5231
+ switch (e.key) {
5232
+ case "ArrowRight":
5233
+ case "ArrowLeft":
5234
+ return go(row, idx + horizontal);
5235
+ case "ArrowDown":
5236
+ return go(row + 1, idx);
5237
+ case "ArrowUp":
5238
+ return go(row - 1, idx);
5239
+ case "Home":
5240
+ return go(e.ctrlKey ? -1 : row, 0);
5241
+ case "End":
5242
+ return go(e.ctrlKey ? rowCount - 1 : row, colIds.length - 1);
5243
+ case "PageDown":
5244
+ return go(row + pageRows, idx);
5245
+ case "PageUp":
5246
+ return go(Math.max(row - pageRows, row >= 0 ? 0 : -1), idx);
5247
+ case "Enter":
5248
+ case " ":
5249
+ if (row < 0 && column.sortable) {
5250
+ e.preventDefault();
5251
+ toggleSort(column.id);
5252
+ } else if (row >= 0 && column.editable && e.key === "Enter") {
5253
+ e.preventDefault();
5254
+ setEditing({ rowIndex: row, columnId: column.id });
5255
+ }
5256
+ return;
5257
+ case "F2":
5258
+ if (row >= 0 && column.editable) {
5259
+ e.preventDefault();
5260
+ setEditing({ rowIndex: row, columnId: column.id });
5261
+ }
5262
+ return;
5263
+ }
5264
+ }
5265
+ return /* @__PURE__ */ jsxs53(Fragment3, { children: [
5266
+ /* @__PURE__ */ jsx89(
5267
+ "div",
5268
+ {
5269
+ ref: containerRef,
5270
+ role: "grid",
5271
+ "aria-rowcount": rowCount + 1,
5272
+ "aria-colcount": colIds.length,
5273
+ className: cn("relative overflow-auto rounded-md border font-sans text-sm", className),
5274
+ style: { height },
5275
+ onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
5276
+ children: /* @__PURE__ */ jsxs53("div", { style: { width: totalWidth, minWidth: "100%" }, children: [
5277
+ /* @__PURE__ */ jsx89("div", { role: "row", "aria-rowindex": 1, className: "sticky top-0 z-[2] flex border-b bg-background", children: renderedColumns.map((column, colIdx) => {
5278
+ const width = widths[column.id] ?? column.width ?? DEFAULT_WIDTH;
5279
+ const pinnedStyle = column.pinned === "left" ? { position: "sticky", left: leftOffsets[column.id], zIndex: 3 } : column.pinned === "right" ? { position: "sticky", right: rightOffsets[column.id], zIndex: 3 } : {};
5280
+ const isSorted = sort?.columnId === column.id;
5281
+ return /* @__PURE__ */ jsxs53(
5282
+ "div",
5283
+ {
5284
+ role: "columnheader",
5285
+ "data-header": column.id,
5286
+ "aria-colindex": colIdx + 1,
5287
+ "aria-keyshortcuts": `Shift+ArrowLeft Shift+ArrowRight${column.pinned ? "" : " Alt+ArrowLeft Alt+ArrowRight"}`,
5288
+ ...column.sortable ? { "aria-sort": isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" } : {},
5289
+ draggable: !column.pinned,
5290
+ onDragStart: () => {
5291
+ dragIdRef.current = column.id;
5292
+ },
5293
+ onDragOver: (e) => {
5294
+ if (!column.pinned) e.preventDefault();
5295
+ },
5296
+ onDrop: (e) => {
5173
5297
  e.preventDefault();
5174
- toggleSort(column.id);
5175
- }
5298
+ const draggedId = dragIdRef.current;
5299
+ dragIdRef.current = null;
5300
+ if (!draggedId || draggedId === column.id) return;
5301
+ setOrder((prev) => {
5302
+ const next = prev.filter((id) => id !== draggedId);
5303
+ const targetIndex = next.indexOf(column.id);
5304
+ next.splice(targetIndex, 0, draggedId);
5305
+ return next;
5306
+ });
5307
+ },
5308
+ onClick: () => column.sortable && toggleSort(column.id),
5309
+ tabIndex: tabStop.row === -1 && tabStop.columnId === column.id ? 0 : -1,
5310
+ onFocus: () => setActive({ row: -1, columnId: column.id }),
5311
+ onKeyDown: (e) => onNavKeyDown(e, -1, column),
5312
+ className: cn(
5313
+ "relative flex h-10 shrink-0 select-none items-center gap-1 px-2 font-medium text-muted-foreground outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
5314
+ column.sortable && "cursor-pointer hover:text-foreground",
5315
+ column.pinned && "bg-background"
5316
+ ),
5317
+ style: { width, ...pinnedStyle },
5318
+ children: [
5319
+ /* @__PURE__ */ jsx89("span", { className: "truncate", children: column.header }),
5320
+ column.sortable && isSorted && /* @__PURE__ */ jsx89("span", { "aria-hidden": "true", className: "text-xs", children: sort.direction === "asc" ? "\u25B2" : "\u25BC" }),
5321
+ /* @__PURE__ */ jsx89(
5322
+ "div",
5323
+ {
5324
+ onPointerDown: (e) => {
5325
+ e.stopPropagation();
5326
+ beginResize(column.id, column.minWidth ?? DEFAULT_MIN_WIDTH, e.clientX, width);
5327
+ },
5328
+ className: "absolute right-0 top-0 h-full w-1 touch-none cursor-col-resize hover:bg-action/50"
5329
+ }
5330
+ )
5331
+ ]
5176
5332
  },
5177
- className: cn(
5178
- "relative flex h-10 shrink-0 select-none items-center gap-1 px-2 font-medium text-muted-foreground",
5179
- column.sortable && "cursor-pointer outline-none hover:text-foreground focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
5180
- column.pinned && "bg-background"
5181
- ),
5182
- style: { width, ...pinnedStyle },
5183
- children: [
5184
- /* @__PURE__ */ jsx89("span", { className: "truncate", children: column.header }),
5185
- column.sortable && isSorted && /* @__PURE__ */ jsx89("span", { "aria-hidden": "true", className: "text-xs", children: sort.direction === "asc" ? "\u25B2" : "\u25BC" }),
5186
- /* @__PURE__ */ jsx89(
5187
- "div",
5188
- {
5189
- onPointerDown: (e) => {
5190
- e.stopPropagation();
5191
- beginResize(column.id, column.minWidth ?? DEFAULT_MIN_WIDTH, e.clientX, width);
5192
- },
5193
- className: "absolute right-0 top-0 h-full w-1 touch-none cursor-col-resize hover:bg-primary/50"
5194
- }
5195
- )
5196
- ]
5197
- },
5198
- column.id
5199
- );
5200
- }) }),
5201
- /* @__PURE__ */ jsx89("div", { style: { height: totalHeight, position: "relative" }, children: visibleRows.map((row, i) => {
5202
- const rowIndex = startIndex + i;
5203
- return /* @__PURE__ */ jsx89(
5204
- "div",
5205
- {
5206
- role: "row",
5207
- className: "absolute flex w-full border-b hover:bg-muted/50",
5208
- style: { top: rowIndex * rowHeight, height: rowHeight },
5209
- children: renderedColumns.map((column) => {
5210
- const width = widths[column.id] ?? column.width ?? DEFAULT_WIDTH;
5211
- const pinnedStyle = column.pinned === "left" ? { position: "sticky", left: leftOffsets[column.id], zIndex: 1 } : column.pinned === "right" ? { position: "sticky", right: rightOffsets[column.id], zIndex: 1 } : {};
5212
- const isEditing = editing?.rowIndex === rowIndex && editing.columnId === column.id;
5213
- return /* @__PURE__ */ jsx89(
5214
- "div",
5215
- {
5216
- role: "gridcell",
5217
- "data-cell": `${rowIndex}:${column.id}`,
5218
- onDoubleClick: () => column.editable && setEditing({ rowIndex, columnId: column.id }),
5219
- tabIndex: column.editable ? 0 : void 0,
5220
- onKeyDown: (e) => {
5221
- if (column.editable && e.target === e.currentTarget && (e.key === "Enter" || e.key === "F2")) {
5222
- e.preventDefault();
5223
- setEditing({ rowIndex, columnId: column.id });
5224
- }
5333
+ column.id
5334
+ );
5335
+ }) }),
5336
+ /* @__PURE__ */ jsx89("div", { style: { height: totalHeight, position: "relative" }, children: visibleRows.map((row, i) => {
5337
+ const rowIndex = startIndex + i;
5338
+ return /* @__PURE__ */ jsx89(
5339
+ "div",
5340
+ {
5341
+ role: "row",
5342
+ "aria-rowindex": rowIndex + 2,
5343
+ className: "absolute flex w-full border-b hover:bg-muted/50",
5344
+ style: { top: rowIndex * rowHeight, height: rowHeight },
5345
+ children: renderedColumns.map((column, colIdx) => {
5346
+ const width = widths[column.id] ?? column.width ?? DEFAULT_WIDTH;
5347
+ const pinnedStyle = column.pinned === "left" ? { position: "sticky", left: leftOffsets[column.id], zIndex: 1 } : column.pinned === "right" ? { position: "sticky", right: rightOffsets[column.id], zIndex: 1 } : {};
5348
+ const isEditing = editing?.rowIndex === rowIndex && editing.columnId === column.id;
5349
+ return /* @__PURE__ */ jsx89(
5350
+ "div",
5351
+ {
5352
+ role: "gridcell",
5353
+ "aria-colindex": colIdx + 1,
5354
+ "data-cell": `${rowIndex}:${column.id}`,
5355
+ onDoubleClick: () => column.editable && setEditing({ rowIndex, columnId: column.id }),
5356
+ tabIndex: tabStop.row === rowIndex && tabStop.columnId === column.id ? 0 : -1,
5357
+ onFocus: () => setActive({ row: rowIndex, columnId: column.id }),
5358
+ onKeyDown: (e) => onNavKeyDown(e, rowIndex, column),
5359
+ className: cn(
5360
+ "flex shrink-0 items-center px-2 outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
5361
+ column.pinned && "bg-background"
5362
+ ),
5363
+ style: { width, ...pinnedStyle },
5364
+ children: isEditing ? /* @__PURE__ */ jsx89(
5365
+ "input",
5366
+ {
5367
+ autoFocus: true,
5368
+ defaultValue: column.value ? String(column.value(row)) : "",
5369
+ className: "h-7 w-full rounded-sm border-0 bg-transparent px-1 text-sm outline-none ring-1 ring-inset ring-ring",
5370
+ onKeyDown: (e) => {
5371
+ if (e.key === "Enter") commitEdit(column, row, rowIndex, e.currentTarget.value, true);
5372
+ else if (e.key === "Escape") endEdit(true);
5373
+ },
5374
+ onBlur: (e) => commitEdit(column, row, rowIndex, e.currentTarget.value)
5375
+ }
5376
+ ) : /* @__PURE__ */ jsx89("span", { className: "truncate", children: column.cell(row, rowIndex) })
5225
5377
  },
5226
- className: cn(
5227
- "flex shrink-0 items-center px-2",
5228
- column.editable && "outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
5229
- column.pinned && "bg-background"
5230
- ),
5231
- style: { width, ...pinnedStyle },
5232
- children: isEditing ? /* @__PURE__ */ jsx89(
5233
- "input",
5234
- {
5235
- autoFocus: true,
5236
- defaultValue: column.value ? String(column.value(row)) : "",
5237
- className: "h-7 w-full rounded-sm border-0 bg-transparent px-1 text-sm outline-none ring-1 ring-inset ring-ring",
5238
- onKeyDown: (e) => {
5239
- if (e.key === "Enter") commitEdit(column, row, rowIndex, e.currentTarget.value, true);
5240
- else if (e.key === "Escape") endEdit(true);
5241
- },
5242
- onBlur: (e) => commitEdit(column, row, rowIndex, e.currentTarget.value)
5243
- }
5244
- ) : /* @__PURE__ */ jsx89("span", { className: "truncate", children: column.cell(row, rowIndex) })
5245
- },
5246
- column.id
5247
- );
5248
- })
5249
- },
5250
- getRowId ? getRowId(row, rowIndex) : rowIndex
5251
- );
5252
- }) })
5253
- ] })
5254
- }
5255
- );
5378
+ column.id
5379
+ );
5380
+ })
5381
+ },
5382
+ getRowId ? getRowId(row, rowIndex) : rowIndex
5383
+ );
5384
+ }) })
5385
+ ] })
5386
+ }
5387
+ ),
5388
+ /* @__PURE__ */ jsx89("div", { role: "status", "aria-live": "polite", className: "sr-only", children: announcement })
5389
+ ] });
5256
5390
  }
5257
5391
 
5258
5392
  // src/components/json-viewer.tsx
5259
5393
  import * as React84 from "react";
5260
5394
  import { Check as Check10, ChevronRight as ChevronRight8, Copy as Copy2 } from "lucide-react";
5261
- import { Fragment as Fragment2, jsx as jsx90, jsxs as jsxs54 } from "react/jsx-runtime";
5395
+ import { Fragment as Fragment4, jsx as jsx90, jsxs as jsxs54 } from "react/jsx-runtime";
5262
5396
  var JsonViewer = React84.forwardRef(
5263
5397
  ({ data, expandDepth = 1, hideCopy, className, ...props }, ref) => {
5264
5398
  const [copied, setCopied] = React84.useState(false);
@@ -5360,8 +5494,8 @@ function JsonNode({
5360
5494
  !expanded && !isLast && /* @__PURE__ */ jsx90("span", { className: "text-muted-foreground", children: "," })
5361
5495
  ] })
5362
5496
  ] }),
5363
- expanded && /* @__PURE__ */ jsxs54(Fragment2, { children: [
5364
- entries.map(([key, val], i) => /* @__PURE__ */ jsx90(
5497
+ expanded && /* @__PURE__ */ jsxs54(Fragment4, { children: [
5498
+ /* @__PURE__ */ jsx90("div", { role: "group", children: entries.map(([key, val], i) => /* @__PURE__ */ jsx90(
5365
5499
  JsonNode,
5366
5500
  {
5367
5501
  name: isArray ? void 0 : key,
@@ -5371,7 +5505,7 @@ function JsonNode({
5371
5505
  isLast: i === entries.length - 1
5372
5506
  },
5373
5507
  key
5374
- )),
5508
+ )) }),
5375
5509
  /* @__PURE__ */ jsxs54("div", { style: { paddingLeft: depth * 16 }, children: [
5376
5510
  /* @__PURE__ */ jsx90("span", { children: closeBracket }),
5377
5511
  !isLast && /* @__PURE__ */ jsx90("span", { className: "text-muted-foreground", children: "," })
@@ -5442,11 +5576,12 @@ function UnifiedDiff({ ops }) {
5442
5576
  role: "row",
5443
5577
  className: cn("flex", op.type === "add" && "bg-success/10", op.type === "remove" && "bg-destructive/10"),
5444
5578
  children: [
5445
- /* @__PURE__ */ jsx91("span", { className: "w-9 shrink-0 select-none border-r px-1.5 text-right text-muted-foreground", children: op.type !== "add" ? op.oldLine : "" }),
5446
- /* @__PURE__ */ jsx91("span", { className: "w-9 shrink-0 select-none border-r px-1.5 text-right text-muted-foreground", children: op.type !== "remove" ? op.newLine : "" }),
5579
+ /* @__PURE__ */ jsx91("span", { role: "cell", className: "w-9 shrink-0 select-none border-r px-1.5 text-right text-muted-foreground", children: op.type !== "add" ? op.oldLine : "" }),
5580
+ /* @__PURE__ */ jsx91("span", { role: "cell", className: "w-9 shrink-0 select-none border-r px-1.5 text-right text-muted-foreground", children: op.type !== "remove" ? op.newLine : "" }),
5447
5581
  /* @__PURE__ */ jsx91(
5448
5582
  "span",
5449
5583
  {
5584
+ role: "cell",
5450
5585
  className: cn(
5451
5586
  "w-4 shrink-0 select-none text-center",
5452
5587
  op.type === "add" && "text-success",
@@ -5455,7 +5590,7 @@ function UnifiedDiff({ ops }) {
5455
5590
  children: op.type === "add" ? "+" : op.type === "remove" ? "\u2212" : ""
5456
5591
  }
5457
5592
  ),
5458
- /* @__PURE__ */ jsx91("span", { className: "min-w-0 flex-1 whitespace-pre px-1", children: op.text })
5593
+ /* @__PURE__ */ jsx91("span", { role: "cell", className: "min-w-0 flex-1 whitespace-pre px-1", children: op.text })
5459
5594
  ]
5460
5595
  },
5461
5596
  i
@@ -5463,16 +5598,16 @@ function UnifiedDiff({ ops }) {
5463
5598
  }
5464
5599
  function SplitDiff({ ops, oldLabel, newLabel }) {
5465
5600
  return /* @__PURE__ */ jsxs55("div", { role: "table", children: [
5466
- /* @__PURE__ */ jsxs55("div", { className: "flex border-b bg-muted/40 text-muted-foreground", children: [
5467
- /* @__PURE__ */ jsx91("div", { className: "flex-1 px-2 py-1", children: oldLabel }),
5468
- /* @__PURE__ */ jsx91("div", { className: "flex-1 border-l px-2 py-1", children: newLabel })
5601
+ /* @__PURE__ */ jsxs55("div", { role: "row", className: "flex border-b bg-muted/40 text-muted-foreground", children: [
5602
+ /* @__PURE__ */ jsx91("div", { role: "columnheader", className: "flex-1 px-2 py-1", children: oldLabel }),
5603
+ /* @__PURE__ */ jsx91("div", { role: "columnheader", className: "flex-1 border-l px-2 py-1", children: newLabel })
5469
5604
  ] }),
5470
5605
  ops.map((op, i) => /* @__PURE__ */ jsxs55("div", { role: "row", className: "flex", children: [
5471
- /* @__PURE__ */ jsxs55("div", { className: cn("flex flex-1 items-start", op.type === "remove" && "bg-destructive/10"), children: [
5606
+ /* @__PURE__ */ jsxs55("div", { role: "cell", className: cn("flex flex-1 items-start", op.type === "remove" && "bg-destructive/10"), children: [
5472
5607
  /* @__PURE__ */ jsx91("span", { className: "w-9 shrink-0 select-none px-1.5 text-right text-muted-foreground", children: op.type !== "add" ? op.oldLine : "" }),
5473
5608
  /* @__PURE__ */ jsx91("span", { className: "min-w-0 flex-1 whitespace-pre px-1", children: op.type !== "add" ? op.text : "" })
5474
5609
  ] }),
5475
- /* @__PURE__ */ jsxs55("div", { className: cn("flex flex-1 items-start border-l", op.type === "add" && "bg-success/10"), children: [
5610
+ /* @__PURE__ */ jsxs55("div", { role: "cell", className: cn("flex flex-1 items-start border-l", op.type === "add" && "bg-success/10"), children: [
5476
5611
  /* @__PURE__ */ jsx91("span", { className: "w-9 shrink-0 select-none px-1.5 text-right text-muted-foreground", children: op.type !== "remove" ? op.newLine : "" }),
5477
5612
  /* @__PURE__ */ jsx91("span", { className: "min-w-0 flex-1 whitespace-pre px-1", children: op.type !== "remove" ? op.text : "" })
5478
5613
  ] })
@@ -5625,6 +5760,9 @@ var ColorPicker = React86.forwardRef(
5625
5760
  role: "slider",
5626
5761
  tabIndex: 0,
5627
5762
  "aria-label": "Saturation and value",
5763
+ "aria-valuemin": 0,
5764
+ "aria-valuemax": 100,
5765
+ "aria-valuenow": Math.round(s),
5628
5766
  "aria-valuetext": `saturation ${Math.round(s)}%, value ${Math.round(v)}%`,
5629
5767
  onPointerDown: handleSquarePointerDown,
5630
5768
  onPointerMove: handleSquarePointerMove,
@@ -5762,6 +5900,7 @@ function HexField({
5762
5900
  return /* @__PURE__ */ jsx92(
5763
5901
  Input,
5764
5902
  {
5903
+ "aria-label": "Hex color",
5765
5904
  value: draft,
5766
5905
  onChange: (e) => setDraft(e.target.value.replace(/[^0-9a-fA-F]/g, "").slice(0, alpha ? 8 : 6)),
5767
5906
  onBlur: commit,
@@ -6044,7 +6183,7 @@ function renderMarkdown(source) {
6044
6183
  return out.join("\n");
6045
6184
  }
6046
6185
  var MarkdownEditor = React88.forwardRef(
6047
- ({ value, onChange, placeholder, rows = 10, className, ...props }, ref) => {
6186
+ ({ value, onChange, placeholder, rows = 10, className, "aria-label": ariaLabel = "Markdown", ...props }, ref) => {
6048
6187
  const textareaRef = React88.useRef(null);
6049
6188
  const [showPreview, setShowPreview] = React88.useState(false);
6050
6189
  const pendingSelection = React88.useRef(null);
@@ -6100,13 +6239,14 @@ var MarkdownEditor = React88.forwardRef(
6100
6239
  onChange: (e) => onChange(e.target.value),
6101
6240
  placeholder,
6102
6241
  rows,
6242
+ "aria-label": ariaLabel,
6103
6243
  className: "resize-none rounded-none border-0 font-mono text-[13px] focus-visible:border-transparent focus-visible:shadow-none"
6104
6244
  }
6105
6245
  ),
6106
6246
  showPreview && /* @__PURE__ */ jsx94(
6107
6247
  "div",
6108
6248
  {
6109
- className: "overflow-auto p-3 text-sm [&_a]:text-primary [&_a]:underline [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground [&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.9em] [&_h1]:text-xl [&_h1]:font-semibold [&_h2]:text-lg [&_h2]:font-semibold [&_h3]:font-semibold [&_li]:ml-5 [&_ol]:list-decimal [&_p]:mb-2 [&_pre]:overflow-auto [&_pre]:rounded-sm [&_pre]:bg-muted [&_pre]:p-2 [&_ul]:list-disc",
6249
+ className: "overflow-auto p-3 text-sm [&_a]:text-link [&_a]:underline [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground [&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.9em] [&_h1]:text-xl [&_h1]:font-semibold [&_h2]:text-lg [&_h2]:font-semibold [&_h3]:font-semibold [&_li]:ml-5 [&_ol]:list-decimal [&_p]:mb-2 [&_pre]:overflow-auto [&_pre]:rounded-sm [&_pre]:bg-muted [&_pre]:p-2 [&_ul]:list-disc",
6110
6250
  dangerouslySetInnerHTML: { __html: renderMarkdown(value) }
6111
6251
  }
6112
6252
  )