@ship-it-ui/ui 0.0.1 → 0.0.3

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
@@ -1,30 +1,14 @@
1
- import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
3
- import { forwardRef, Children, isValidElement, cloneElement, useId, useRef, useState, useImperativeHandle, createContext, useMemo, useEffect, Fragment as Fragment$1, useContext, useCallback } from 'react';
4
- import { Slot } from '@radix-ui/react-slot';
5
- import { cva } from 'class-variance-authority';
6
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import * as RadixCheckbox from '@radix-ui/react-checkbox';
8
- import * as RadixRadio from '@radix-ui/react-radio-group';
9
- import * as RadixSelect from '@radix-ui/react-select';
10
- import * as RadixSlider from '@radix-ui/react-slider';
11
- import * as RadixSwitch from '@radix-ui/react-switch';
12
- import * as RadixAvatar from '@radix-ui/react-avatar';
13
- import * as RadixContext from '@radix-ui/react-context-menu';
14
- import * as RadixDialog from '@radix-ui/react-dialog';
15
- import * as RadixAlert from '@radix-ui/react-alert-dialog';
16
- import * as RadixMenu from '@radix-ui/react-dropdown-menu';
17
- import * as RadixHoverCard from '@radix-ui/react-hover-card';
18
- import * as RadixPopover from '@radix-ui/react-popover';
19
- import * as RadixToast from '@radix-ui/react-toast';
20
- import * as RadixTooltip from '@radix-ui/react-tooltip';
21
- import * as RadixMenubar from '@radix-ui/react-menubar';
22
- import * as RadixTabs from '@radix-ui/react-tabs';
1
+ 'use client';
23
2
 
24
3
  // src/utils/cn.ts
4
+ import { clsx } from "clsx";
5
+ import { twMerge } from "tailwind-merge";
25
6
  function cn(...inputs) {
26
7
  return twMerge(clsx(inputs));
27
8
  }
9
+
10
+ // src/hooks/useControllableState.ts
11
+ import { useCallback, useRef, useState } from "react";
28
12
  function useControllableState({
29
13
  value: controlledValue,
30
14
  defaultValue,
@@ -51,31 +35,48 @@ function useControllableState({
51
35
  );
52
36
  return [value, setValue];
53
37
  }
38
+
39
+ // src/hooks/useDisclosure.ts
40
+ import { useCallback as useCallback2, useState as useState2 } from "react";
54
41
  function useDisclosure(initial = false) {
55
- const [open, setOpen] = useState(initial);
56
- const onOpen = useCallback(() => setOpen(true), []);
57
- const onClose = useCallback(() => setOpen(false), []);
58
- const onToggle = useCallback(() => setOpen((o) => !o), []);
42
+ const [open, setOpen] = useState2(initial);
43
+ const onOpen = useCallback2(() => setOpen(true), []);
44
+ const onClose = useCallback2(() => setOpen(false), []);
45
+ const onToggle = useCallback2(() => setOpen((o) => !o), []);
59
46
  return { open, onOpen, onClose, onToggle, setOpen };
60
47
  }
48
+
49
+ // src/hooks/useEscape.ts
50
+ import { useEffect, useRef as useRef2 } from "react";
61
51
  function useEscape(handler, enabled = true) {
52
+ const handlerRef = useRef2(handler);
53
+ useEffect(() => {
54
+ handlerRef.current = handler;
55
+ }, [handler]);
62
56
  useEffect(() => {
63
57
  if (!enabled) return;
64
58
  const onKey = (e) => {
65
- if (e.key === "Escape") handler();
59
+ if (e.key === "Escape") handlerRef.current();
66
60
  };
67
- window.addEventListener("keydown", onKey);
68
- return () => window.removeEventListener("keydown", onKey);
69
- }, [handler, enabled]);
61
+ document.addEventListener("keydown", onKey);
62
+ return () => document.removeEventListener("keydown", onKey);
63
+ }, [enabled]);
70
64
  }
65
+
66
+ // src/hooks/useIsomorphicLayoutEffect.ts
67
+ import { useEffect as useEffect2, useLayoutEffect } from "react";
68
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect2;
69
+
70
+ // src/hooks/useKeyboardList.ts
71
+ import { useCallback as useCallback3, useState as useState3 } from "react";
71
72
  function useKeyboardList({
72
73
  count,
73
74
  loop = true,
74
75
  defaultCursor = 0,
75
76
  onSelect
76
77
  }) {
77
- const [cursor, setCursor] = useState(defaultCursor);
78
- const move = useCallback(
78
+ const [cursor, setCursor] = useState3(defaultCursor);
79
+ const move = useCallback3(
79
80
  (delta) => {
80
81
  if (count <= 0) return;
81
82
  setCursor((c) => {
@@ -86,7 +87,7 @@ function useKeyboardList({
86
87
  },
87
88
  [count, loop]
88
89
  );
89
- const onKeyDown = useCallback(
90
+ const onKeyDown = useCallback3(
90
91
  (event) => {
91
92
  if (count <= 0) return;
92
93
  switch (event.key) {
@@ -112,6 +113,8 @@ function useKeyboardList({
112
113
  onSelect(cursor);
113
114
  }
114
115
  break;
116
+ default:
117
+ break;
115
118
  }
116
119
  },
117
120
  [count, cursor, move, onSelect]
@@ -119,23 +122,30 @@ function useKeyboardList({
119
122
  const safeCursor = count > 0 ? Math.min(cursor, count - 1) : 0;
120
123
  return { cursor: safeCursor, setCursor, onKeyDown };
121
124
  }
125
+
126
+ // src/hooks/useOutsideClick.ts
127
+ import { useEffect as useEffect3 } from "react";
122
128
  function useOutsideClick(ref, handler, enabled = true) {
123
- useEffect(() => {
129
+ useEffect3(() => {
124
130
  if (!enabled) return;
125
131
  const onDown = (e) => {
126
132
  const el = ref.current;
127
133
  if (el && e.target instanceof Node && !el.contains(e.target)) handler();
128
134
  };
129
- document.addEventListener("mousedown", onDown);
130
- return () => document.removeEventListener("mousedown", onDown);
135
+ document.addEventListener("pointerdown", onDown);
136
+ return () => document.removeEventListener("pointerdown", onDown);
131
137
  }, [ref, handler, enabled]);
132
138
  }
139
+
140
+ // src/hooks/useTheme.ts
141
+ import { useCallback as useCallback4, useEffect as useEffect4, useState as useState4 } from "react";
133
142
  function useTheme() {
134
- const [theme, setThemeState] = useState(() => {
135
- if (typeof document === "undefined") return "dark";
136
- return document.documentElement.getAttribute("data-theme") === "light" ? "light" : "dark";
137
- });
138
- const setTheme = useCallback((next) => {
143
+ const [theme, setThemeState] = useState4("dark");
144
+ const setTheme = useCallback4((next) => {
145
+ if (typeof document === "undefined") {
146
+ setThemeState(next);
147
+ return;
148
+ }
139
149
  if (next === "light") {
140
150
  document.documentElement.setAttribute("data-theme", "light");
141
151
  } else {
@@ -143,10 +153,12 @@ function useTheme() {
143
153
  }
144
154
  setThemeState(next);
145
155
  }, []);
146
- const toggle = useCallback(() => {
156
+ const toggle = useCallback4(() => {
147
157
  setTheme(theme === "dark" ? "light" : "dark");
148
158
  }, [theme, setTheme]);
149
- useEffect(() => {
159
+ useEffect4(() => {
160
+ const initial = document.documentElement.getAttribute("data-theme");
161
+ setThemeState(initial === "light" ? "light" : "dark");
150
162
  const observer = new MutationObserver(() => {
151
163
  const attr = document.documentElement.getAttribute("data-theme");
152
164
  setThemeState(attr === "light" ? "light" : "dark");
@@ -159,6 +171,12 @@ function useTheme() {
159
171
  }, []);
160
172
  return { theme, setTheme, toggle };
161
173
  }
174
+
175
+ // src/components/Button/Button.tsx
176
+ import { Slot } from "@radix-ui/react-slot";
177
+ import { cva } from "class-variance-authority";
178
+ import { forwardRef } from "react";
179
+ import { jsx, jsxs } from "react/jsx-runtime";
162
180
  var buttonStyles = cva(
163
181
  [
164
182
  "inline-flex items-center justify-center whitespace-nowrap",
@@ -255,7 +273,12 @@ var Button = forwardRef(function Button2({
255
273
  );
256
274
  });
257
275
  Button.displayName = "Button";
258
- var iconButtonStyles = cva(
276
+
277
+ // src/components/Button/IconButton.tsx
278
+ import { cva as cva2 } from "class-variance-authority";
279
+ import { forwardRef as forwardRef2 } from "react";
280
+ import { jsx as jsx2 } from "react/jsx-runtime";
281
+ var iconButtonStyles = cva2(
259
282
  [
260
283
  "inline-grid place-items-center transition-[background,filter,color] duration-(--duration-micro)",
261
284
  "outline-none focus-visible:ring-[3px] focus-visible:ring-accent-dim",
@@ -263,11 +286,16 @@ var iconButtonStyles = cva(
263
286
  ],
264
287
  {
265
288
  variants: {
289
+ // Mirrors `Button`'s variant set, minus `link` — an underlined link
290
+ // affordance is awkward for an icon-only target, so we omit it
291
+ // intentionally. Use `<Button variant="link" icon={…} />` if you need it.
266
292
  variant: {
267
293
  primary: "bg-accent text-on-accent border border-accent hover:brightness-110",
268
294
  secondary: "bg-panel-2 text-text-muted border border-border hover:bg-[color-mix(in_oklab,var(--color-panel-2),white_4%)]",
269
295
  ghost: "bg-transparent text-text-muted border border-transparent hover:bg-panel-2 hover:text-text",
270
- outline: "bg-transparent text-text-muted border border-border-strong hover:bg-panel-2 hover:text-text"
296
+ outline: "bg-transparent text-text-muted border border-border-strong hover:bg-panel-2 hover:text-text",
297
+ destructive: "bg-err text-on-accent border border-err hover:brightness-110 active:brightness-95",
298
+ success: "bg-ok text-on-accent border border-ok hover:brightness-110 active:brightness-95"
271
299
  },
272
300
  size: {
273
301
  sm: "h-[26px] w-[26px] text-[12px] rounded-[5px]",
@@ -278,8 +306,8 @@ var iconButtonStyles = cva(
278
306
  defaultVariants: { variant: "secondary", size: "md" }
279
307
  }
280
308
  );
281
- var IconButton = forwardRef(function IconButton2({ variant, size, icon, type, className, ...props }, ref) {
282
- return /* @__PURE__ */ jsx(
309
+ var IconButton = forwardRef2(function IconButton2({ variant, size, icon, type, className, ...props }, ref) {
310
+ return /* @__PURE__ */ jsx2(
283
311
  "button",
284
312
  {
285
313
  ref,
@@ -291,9 +319,18 @@ var IconButton = forwardRef(function IconButton2({ variant, size, icon, type, cl
291
319
  );
292
320
  });
293
321
  IconButton.displayName = "IconButton";
294
- var ButtonGroup = forwardRef(function ButtonGroup2({ orientation = "horizontal", className, children, ...props }, ref) {
322
+
323
+ // src/components/Button/ButtonGroup.tsx
324
+ import {
325
+ Children,
326
+ cloneElement,
327
+ forwardRef as forwardRef3,
328
+ isValidElement
329
+ } from "react";
330
+ import { jsx as jsx3 } from "react/jsx-runtime";
331
+ var ButtonGroup = forwardRef3(function ButtonGroup2({ orientation = "horizontal", className, children, ...props }, ref) {
295
332
  const items = Children.toArray(children).filter(isValidElement);
296
- return /* @__PURE__ */ jsx(
333
+ return /* @__PURE__ */ jsx3(
297
334
  "div",
298
335
  {
299
336
  ref,
@@ -320,27 +357,42 @@ var ButtonGroup = forwardRef(function ButtonGroup2({ orientation = "horizontal",
320
357
  );
321
358
  });
322
359
  ButtonGroup.displayName = "ButtonGroup";
323
- var SplitButton = forwardRef(function SplitButton2({ variant = "primary", size = "md", onClick, onMenu, disabled, className, children, ...props }, ref) {
324
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("inline-flex", className), ...props, children: [
325
- /* @__PURE__ */ jsx(
360
+
361
+ // src/components/Button/SplitButton.tsx
362
+ import { forwardRef as forwardRef4 } from "react";
363
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
364
+ var SplitButton = forwardRef4(function SplitButton2({
365
+ variant = "primary",
366
+ size = "md",
367
+ onClick,
368
+ onMenu,
369
+ disabled,
370
+ menuAriaLabel = "More actions",
371
+ className,
372
+ children,
373
+ ...props
374
+ }, ref) {
375
+ const dividerBorder = variant === "primary" || variant === "destructive" || variant === "success" ? "border-r-on-accent/20" : "border-r-border-strong";
376
+ return /* @__PURE__ */ jsxs2("div", { ref, className: cn("inline-flex", className), ...props, children: [
377
+ /* @__PURE__ */ jsx4(
326
378
  Button,
327
379
  {
328
380
  variant,
329
381
  size,
330
382
  onClick,
331
383
  disabled,
332
- className: "rounded-r-none border-r border-r-black/20",
384
+ className: cn("rounded-r-none border-r", dividerBorder),
333
385
  children
334
386
  }
335
387
  ),
336
- /* @__PURE__ */ jsx(
388
+ /* @__PURE__ */ jsx4(
337
389
  Button,
338
390
  {
339
391
  variant,
340
392
  size,
341
393
  onClick: onMenu,
342
394
  disabled,
343
- "aria-label": "More actions",
395
+ "aria-label": menuAriaLabel,
344
396
  className: "rounded-l-none px-2",
345
397
  children: "\u25BE"
346
398
  }
@@ -348,8 +400,12 @@ var SplitButton = forwardRef(function SplitButton2({ variant = "primary", size =
348
400
  ] });
349
401
  });
350
402
  SplitButton.displayName = "SplitButton";
351
- var FAB = forwardRef(function FAB2({ icon = "\u2726", type, className, style, ...props }, ref) {
352
- return /* @__PURE__ */ jsx(
403
+
404
+ // src/components/Button/FAB.tsx
405
+ import { forwardRef as forwardRef5 } from "react";
406
+ import { jsx as jsx5 } from "react/jsx-runtime";
407
+ var FAB = forwardRef5(function FAB2({ icon = "\u2726", type, className, style, ...props }, ref) {
408
+ return /* @__PURE__ */ jsx5(
353
409
  "button",
354
410
  {
355
411
  ref,
@@ -371,10 +427,15 @@ var FAB = forwardRef(function FAB2({ icon = "\u2726", type, className, style, ..
371
427
  );
372
428
  });
373
429
  FAB.displayName = "FAB";
374
- var Checkbox = forwardRef(function Checkbox2({ label, className, id: idProp, ...props }, ref) {
430
+
431
+ // src/components/Checkbox/Checkbox.tsx
432
+ import * as RadixCheckbox from "@radix-ui/react-checkbox";
433
+ import { forwardRef as forwardRef6, useId } from "react";
434
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
435
+ var Checkbox = forwardRef6(function Checkbox2({ label, className, id: idProp, ...props }, ref) {
375
436
  const reactId = useId();
376
437
  const id = idProp ?? `cb-${reactId}`;
377
- return /* @__PURE__ */ jsxs(
438
+ return /* @__PURE__ */ jsxs3(
378
439
  "span",
379
440
  {
380
441
  className: cn(
@@ -383,7 +444,7 @@ var Checkbox = forwardRef(function Checkbox2({ label, className, id: idProp, ...
383
444
  className
384
445
  ),
385
446
  children: [
386
- /* @__PURE__ */ jsx(
447
+ /* @__PURE__ */ jsx6(
387
448
  RadixCheckbox.Root,
388
449
  {
389
450
  ref,
@@ -397,36 +458,45 @@ var Checkbox = forwardRef(function Checkbox2({ label, className, id: idProp, ...
397
458
  "focus-visible:ring-accent-dim outline-none focus-visible:ring-[3px]"
398
459
  ),
399
460
  ...props,
400
- children: /* @__PURE__ */ jsx(RadixCheckbox.Indicator, { className: "text-on-accent text-[11px] leading-none", children: props.checked === "indeterminate" ? "\u2212" : "\u2713" })
461
+ children: /* @__PURE__ */ jsx6(RadixCheckbox.Indicator, { className: "text-on-accent text-[11px] leading-none", children: props.checked === "indeterminate" ? "\u2212" : "\u2713" })
401
462
  }
402
463
  ),
403
- label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "cursor-pointer text-[13px]", children: label })
464
+ label && /* @__PURE__ */ jsx6("label", { htmlFor: id, className: "cursor-pointer text-[13px]", children: label })
404
465
  ]
405
466
  }
406
467
  );
407
468
  });
408
469
  Checkbox.displayName = "Checkbox";
470
+
471
+ // src/components/Field/Field.tsx
472
+ import { useId as useId2 } from "react";
473
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
409
474
  function Field({ label, hint, error, required, className, children, ...props }) {
410
- const reactId = useId();
475
+ const reactId = useId2();
411
476
  const id = `field-${reactId}`;
412
477
  const hintId = hint && !error ? `${id}-hint` : void 0;
413
478
  const errorId = error ? `${id}-error` : void 0;
414
479
  const describedBy = errorId ?? hintId;
415
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-[6px]", className), ...props, children: [
416
- label && /* @__PURE__ */ jsxs("label", { htmlFor: id, className: "text-text-muted text-[11px] font-medium", children: [
480
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col gap-[6px]", className), ...props, children: [
481
+ label && /* @__PURE__ */ jsxs4("label", { htmlFor: id, className: "text-text-muted text-[11px] font-medium", children: [
417
482
  label,
418
- required && /* @__PURE__ */ jsx("span", { className: "text-err ml-1", children: "*" })
483
+ required && /* @__PURE__ */ jsx7("span", { className: "text-err ml-1", children: "*" })
419
484
  ] }),
420
485
  children({
421
486
  id,
422
487
  "aria-describedby": describedBy,
423
488
  "aria-invalid": error ? true : void 0
424
489
  }),
425
- hint && !error && /* @__PURE__ */ jsx("div", { id: hintId, className: "text-text-dim text-[11px]", children: hint }),
426
- error && /* @__PURE__ */ jsx("div", { id: errorId, className: "text-err text-[11px]", children: error })
490
+ hint && !error && /* @__PURE__ */ jsx7("div", { id: hintId, className: "text-text-dim text-[11px]", children: hint }),
491
+ error && /* @__PURE__ */ jsx7("div", { id: errorId, className: "text-err text-[11px]", children: error })
427
492
  ] });
428
493
  }
429
- var inputWrapperStyles = cva(
494
+
495
+ // src/components/Input/Input.tsx
496
+ import { cva as cva3 } from "class-variance-authority";
497
+ import { forwardRef as forwardRef7 } from "react";
498
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
499
+ var inputWrapperStyles = cva3(
430
500
  [
431
501
  "flex items-center gap-[6px] font-sans transition-[border-color,box-shadow] duration-(--duration-micro)",
432
502
  "border focus-within:ring-[3px]",
@@ -441,22 +511,22 @@ var inputWrapperStyles = cva(
441
511
  },
442
512
  tone: {
443
513
  default: "bg-panel border-border focus-within:border-accent focus-within:ring-accent-dim",
444
- error: "bg-panel border-err focus-within:border-err focus-within:ring-[oklch(0.55_0.18_30/0.18)]"
514
+ err: "bg-panel border-err focus-within:border-err focus-within:ring-err/30"
445
515
  }
446
516
  },
447
517
  defaultVariants: { size: "md", tone: "default" }
448
518
  }
449
519
  );
450
- var Input = forwardRef(function Input2({ size, tone, icon, trailing, error, width, className, style, disabled, ...props }, ref) {
451
- const computedTone = error ? "error" : tone;
452
- return /* @__PURE__ */ jsxs(
520
+ var Input = forwardRef7(function Input2({ size, tone, icon, trailing, error, width, className, style, disabled, ...props }, ref) {
521
+ const computedTone = error ? "err" : tone;
522
+ return /* @__PURE__ */ jsxs5(
453
523
  "div",
454
524
  {
455
525
  className: cn(inputWrapperStyles({ size, tone: computedTone }), className),
456
526
  style: { width, ...style },
457
527
  children: [
458
- icon && /* @__PURE__ */ jsx("span", { className: "text-text-dim leading-none", children: icon }),
459
- /* @__PURE__ */ jsx(
528
+ icon && /* @__PURE__ */ jsx8("span", { className: "text-text-dim leading-none", children: icon }),
529
+ /* @__PURE__ */ jsx8(
460
530
  "input",
461
531
  {
462
532
  ref,
@@ -470,14 +540,26 @@ var Input = forwardRef(function Input2({ size, tone, icon, trailing, error, widt
470
540
  ...props
471
541
  }
472
542
  ),
473
- trailing && /* @__PURE__ */ jsx("span", { className: "text-text-dim text-[11px]", children: trailing })
543
+ trailing && /* @__PURE__ */ jsx8("span", { className: "text-text-dim text-[11px]", children: trailing })
474
544
  ]
475
545
  }
476
546
  );
477
547
  });
478
548
  Input.displayName = "Input";
479
- var SearchInput = forwardRef(function SearchInput2({ shortcut = "\u2318K", width = 360, className, style, placeholder = "Search\u2026", ...props }, ref) {
480
- return /* @__PURE__ */ jsxs(
549
+
550
+ // src/components/Input/SearchInput.tsx
551
+ import { forwardRef as forwardRef8 } from "react";
552
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
553
+ var SearchInput = forwardRef8(function SearchInput2({
554
+ shortcut = "\u2318K",
555
+ width = 360,
556
+ className,
557
+ style,
558
+ placeholder = "Search\u2026",
559
+ "aria-label": ariaLabel,
560
+ ...props
561
+ }, ref) {
562
+ return /* @__PURE__ */ jsxs6(
481
563
  "div",
482
564
  {
483
565
  className: cn(
@@ -489,46 +571,63 @@ var SearchInput = forwardRef(function SearchInput2({ shortcut = "\u2318K", width
489
571
  ),
490
572
  style: { width, ...style },
491
573
  children: [
492
- /* @__PURE__ */ jsx("span", { className: "text-text-dim leading-none", children: "\u2315" }),
493
- /* @__PURE__ */ jsx(
574
+ /* @__PURE__ */ jsx9("span", { className: "text-text-dim leading-none", "aria-hidden": true, children: "\u2315" }),
575
+ /* @__PURE__ */ jsx9(
494
576
  "input",
495
577
  {
496
578
  ref,
497
579
  type: "search",
498
580
  placeholder,
581
+ "aria-label": ariaLabel ?? (typeof placeholder === "string" ? placeholder : "Search"),
499
582
  className: "text-text placeholder:text-text-dim min-w-0 flex-1 border-none bg-transparent text-[13px] outline-none",
500
583
  ...props
501
584
  }
502
585
  ),
503
- shortcut && /* @__PURE__ */ jsx("kbd", { className: "text-text-dim border-border rounded-xs border px-[6px] py-[2px] font-mono text-[10px]", children: shortcut })
586
+ shortcut && /* @__PURE__ */ jsx9("kbd", { className: "text-text-dim border-border rounded-xs border px-[6px] py-[2px] font-mono text-[10px]", children: shortcut })
504
587
  ]
505
588
  }
506
589
  );
507
590
  });
508
591
  SearchInput.displayName = "SearchInput";
509
- var OTP = forwardRef(function OTP2({ length = 6, onComplete, onChange, defaultValue = "", ariaLabel = "Code", className, disabled }, ref) {
510
- const baseId = useId();
511
- const refs = useRef([]);
512
- const [values, setValues] = useState(
592
+
593
+ // src/components/OTP/OTP.tsx
594
+ import {
595
+ forwardRef as forwardRef9,
596
+ useId as useId3,
597
+ useImperativeHandle,
598
+ useRef as useRef3,
599
+ useState as useState5
600
+ } from "react";
601
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
602
+ var OTP = forwardRef9(function OTP2({ length = 6, onComplete, onChange, defaultValue = "", ariaLabel = "Code", className, disabled }, ref) {
603
+ const baseId = useId3();
604
+ const refs = useRef3([]);
605
+ const [values, setValues] = useState5(
513
606
  () => Array.from({ length }, (_, i) => defaultValue[i] ?? "")
514
607
  );
608
+ const [completedAnnouncement, setCompletedAnnouncement] = useState5("");
515
609
  useImperativeHandle(ref, () => ({
516
610
  focus: () => refs.current[0]?.focus(),
517
611
  reset: () => {
518
612
  setValues(Array(length).fill(""));
613
+ setCompletedAnnouncement("");
519
614
  refs.current[0]?.focus();
520
615
  }
521
616
  }));
522
617
  const writeAt = (i, char) => {
523
618
  if (!/^\d?$/.test(char)) return;
524
- setValues((prev) => {
525
- const next = [...prev];
526
- next[i] = char;
527
- const joined = next.join("");
528
- onChange?.(joined);
529
- if (joined.length === length && next.every((c) => c)) onComplete?.(joined);
530
- return next;
531
- });
619
+ const next = [...values];
620
+ next[i] = char;
621
+ setValues(next);
622
+ const joined = next.join("");
623
+ onChange?.(joined);
624
+ const isComplete = joined.length === length && next.every((c) => c);
625
+ if (isComplete) {
626
+ onComplete?.(joined);
627
+ setCompletedAnnouncement("Code complete");
628
+ } else {
629
+ setCompletedAnnouncement("");
630
+ }
532
631
  if (char && i < length - 1) refs.current[i + 1]?.focus();
533
632
  };
534
633
  const onKey = (i, e) => {
@@ -548,45 +647,59 @@ var OTP = forwardRef(function OTP2({ length = 6, onComplete, onChange, defaultVa
548
647
  setValues(next);
549
648
  const joined = next.join("");
550
649
  onChange?.(joined);
551
- if (joined.length === length) onComplete?.(joined);
650
+ const isComplete = joined.length === length && next.every((c) => c);
651
+ if (isComplete) {
652
+ onComplete?.(joined);
653
+ setCompletedAnnouncement("Code complete");
654
+ } else {
655
+ setCompletedAnnouncement("");
656
+ }
552
657
  refs.current[Math.min(pasted.length, length - 1)]?.focus();
553
658
  };
554
- return /* @__PURE__ */ jsx("div", { className: cn("flex gap-2", className), children: values.map((c, i) => /* @__PURE__ */ jsx(
555
- "input",
556
- {
557
- id: `${baseId}-${i}`,
558
- ref: (el) => {
559
- refs.current[i] = el;
659
+ return /* @__PURE__ */ jsxs7("div", { className: cn("flex gap-2", className), children: [
660
+ values.map((c, i) => /* @__PURE__ */ jsx10(
661
+ "input",
662
+ {
663
+ id: `${baseId}-${i}`,
664
+ ref: (el) => {
665
+ refs.current[i] = el;
666
+ },
667
+ inputMode: "numeric",
668
+ autoComplete: "one-time-code",
669
+ maxLength: 1,
670
+ value: c,
671
+ disabled,
672
+ "aria-label": `${ariaLabel} ${i + 1} of ${length}`,
673
+ onChange: (e) => writeAt(i, e.target.value),
674
+ onKeyDown: (e) => onKey(i, e),
675
+ onFocus: (e) => e.target.select(),
676
+ onPaste: i === 0 ? onPaste : void 0,
677
+ className: cn(
678
+ "text-text bg-panel h-12 w-10 rounded-md text-center font-mono text-[20px] font-medium",
679
+ "border-border border transition-[border-color,box-shadow] duration-(--duration-micro) outline-none",
680
+ "focus:border-accent focus:ring-accent-dim focus:ring-[3px]",
681
+ "disabled:cursor-not-allowed disabled:opacity-50"
682
+ )
560
683
  },
561
- inputMode: "numeric",
562
- autoComplete: "one-time-code",
563
- maxLength: 1,
564
- value: c,
565
- disabled,
566
- "aria-label": `${ariaLabel} ${i + 1} of ${length}`,
567
- onChange: (e) => writeAt(i, e.target.value),
568
- onKeyDown: (e) => onKey(i, e),
569
- onFocus: (e) => e.target.select(),
570
- onPaste: i === 0 ? onPaste : void 0,
571
- className: cn(
572
- "text-text bg-panel h-12 w-10 rounded-md text-center font-mono text-[20px] font-medium",
573
- "border-border border transition-[border-color,box-shadow] duration-(--duration-micro) outline-none",
574
- "focus:border-accent focus:ring-accent-dim focus:ring-[3px]",
575
- "disabled:cursor-not-allowed disabled:opacity-50"
576
- )
577
- },
578
- i
579
- )) });
684
+ i
685
+ )),
686
+ /* @__PURE__ */ jsx10("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: completedAnnouncement })
687
+ ] });
580
688
  });
581
689
  OTP.displayName = "OTP";
582
- var RadioGroup = forwardRef(function RadioGroup2({ className, ...props }, ref) {
583
- return /* @__PURE__ */ jsx(RadixRadio.Root, { ref, className: cn("flex flex-col gap-2", className), ...props });
690
+
691
+ // src/components/Radio/Radio.tsx
692
+ import * as RadixRadio from "@radix-ui/react-radio-group";
693
+ import { forwardRef as forwardRef10, useId as useId4 } from "react";
694
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
695
+ var RadioGroup = forwardRef10(function RadioGroup2({ className, ...props }, ref) {
696
+ return /* @__PURE__ */ jsx11(RadixRadio.Root, { ref, className: cn("flex flex-col gap-2", className), ...props });
584
697
  });
585
698
  RadioGroup.displayName = "RadioGroup";
586
- var Radio = forwardRef(function Radio2({ label, className, id: idProp, ...props }, ref) {
587
- const reactId = useId();
699
+ var Radio = forwardRef10(function Radio2({ label, className, id: idProp, ...props }, ref) {
700
+ const reactId = useId4();
588
701
  const id = idProp ?? `radio-${reactId}`;
589
- return /* @__PURE__ */ jsxs(
702
+ return /* @__PURE__ */ jsxs8(
590
703
  "span",
591
704
  {
592
705
  className: cn(
@@ -595,7 +708,7 @@ var Radio = forwardRef(function Radio2({ label, className, id: idProp, ...props
595
708
  className
596
709
  ),
597
710
  children: [
598
- /* @__PURE__ */ jsx(
711
+ /* @__PURE__ */ jsx11(
599
712
  RadixRadio.Item,
600
713
  {
601
714
  ref,
@@ -608,15 +721,20 @@ var Radio = forwardRef(function Radio2({ label, className, id: idProp, ...props
608
721
  "focus-visible:ring-accent-dim outline-none focus-visible:ring-[3px]"
609
722
  ),
610
723
  ...props,
611
- children: /* @__PURE__ */ jsx(RadixRadio.Indicator, { className: "bg-accent block h-[7px] w-[7px] rounded-full" })
724
+ children: /* @__PURE__ */ jsx11(RadixRadio.Indicator, { className: "bg-accent block h-[7px] w-[7px] rounded-full" })
612
725
  }
613
726
  ),
614
- label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "cursor-pointer text-[13px]", children: label })
727
+ label && /* @__PURE__ */ jsx11("label", { htmlFor: id, className: "cursor-pointer text-[13px]", children: label })
615
728
  ]
616
729
  }
617
730
  );
618
731
  });
619
732
  Radio.displayName = "Radio";
733
+
734
+ // src/components/Select/Select.tsx
735
+ import * as RadixSelect from "@radix-ui/react-select";
736
+ import { forwardRef as forwardRef11 } from "react";
737
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
620
738
  var SelectRoot = RadixSelect.Root;
621
739
  var SelectValue = RadixSelect.Value;
622
740
  var SelectGroup = RadixSelect.Group;
@@ -626,8 +744,8 @@ var triggerClasses = {
626
744
  md: "h-[34px] px-[10px] text-[13px]",
627
745
  lg: "h-10 px-3 text-[14px]"
628
746
  };
629
- var SelectTrigger = forwardRef(function SelectTrigger2({ size = "md", className, children, ...props }, ref) {
630
- return /* @__PURE__ */ jsxs(
747
+ var SelectTrigger = forwardRef11(function SelectTrigger2({ size = "md", className, children, ...props }, ref) {
748
+ return /* @__PURE__ */ jsxs9(
631
749
  RadixSelect.Trigger,
632
750
  {
633
751
  ref,
@@ -643,35 +761,35 @@ var SelectTrigger = forwardRef(function SelectTrigger2({ size = "md", className,
643
761
  ...props,
644
762
  children: [
645
763
  children,
646
- /* @__PURE__ */ jsx(RadixSelect.Icon, { className: "text-text-dim text-[11px] leading-none", children: "\u25BE" })
764
+ /* @__PURE__ */ jsx12(RadixSelect.Icon, { className: "text-text-dim text-[11px] leading-none", children: "\u25BE" })
647
765
  ]
648
766
  }
649
767
  );
650
768
  });
651
769
  SelectTrigger.displayName = "SelectTrigger";
652
- var SelectContent = forwardRef(
770
+ var SelectContent = forwardRef11(
653
771
  function SelectContent2({ className, children, position = "popper", sideOffset = 6, ...props }, ref) {
654
- return /* @__PURE__ */ jsx(RadixSelect.Portal, { children: /* @__PURE__ */ jsx(
772
+ return /* @__PURE__ */ jsx12(RadixSelect.Portal, { children: /* @__PURE__ */ jsx12(
655
773
  RadixSelect.Content,
656
774
  {
657
775
  ref,
658
776
  position,
659
777
  sideOffset,
660
778
  className: cn(
661
- "bg-panel border-border z-50 min-w-[var(--radix-select-trigger-width)] rounded-md border p-1 shadow",
779
+ "bg-panel border-border z-popover min-w-[var(--radix-select-trigger-width)] rounded-md border p-1 shadow",
662
780
  "data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
663
781
  className
664
782
  ),
665
783
  ...props,
666
- children: /* @__PURE__ */ jsx(RadixSelect.Viewport, { children })
784
+ children: /* @__PURE__ */ jsx12(RadixSelect.Viewport, { children })
667
785
  }
668
786
  ) });
669
787
  }
670
788
  );
671
789
  SelectContent.displayName = "SelectContent";
672
- var SelectItem = forwardRef(
790
+ var SelectItem = forwardRef11(
673
791
  function SelectItem2({ className, children, ...props }, ref) {
674
- return /* @__PURE__ */ jsx(
792
+ return /* @__PURE__ */ jsx12(
675
793
  RadixSelect.Item,
676
794
  {
677
795
  ref,
@@ -683,7 +801,7 @@ var SelectItem = forwardRef(
683
801
  className
684
802
  ),
685
803
  ...props,
686
- children: /* @__PURE__ */ jsx(RadixSelect.ItemText, { children })
804
+ children: /* @__PURE__ */ jsx12(RadixSelect.ItemText, { children })
687
805
  }
688
806
  );
689
807
  }
@@ -698,64 +816,106 @@ function Select({
698
816
  "aria-labelledby": ariaLabelledBy,
699
817
  ...rootProps
700
818
  }) {
701
- return /* @__PURE__ */ jsxs(RadixSelect.Root, { ...rootProps, children: [
702
- /* @__PURE__ */ jsx(
819
+ return /* @__PURE__ */ jsxs9(RadixSelect.Root, { ...rootProps, children: [
820
+ /* @__PURE__ */ jsx12(
703
821
  SelectTrigger,
704
822
  {
705
823
  size,
706
824
  className,
707
825
  "aria-label": ariaLabel,
708
826
  "aria-labelledby": ariaLabelledBy,
709
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
827
+ children: /* @__PURE__ */ jsx12(SelectValue, { placeholder })
710
828
  }
711
829
  ),
712
- /* @__PURE__ */ jsx(SelectContent, { children: options.map((opt) => {
830
+ /* @__PURE__ */ jsx12(SelectContent, { children: options.map((opt) => {
713
831
  const value = typeof opt === "string" ? opt : opt.value;
714
832
  const label = typeof opt === "string" ? opt : opt.label;
715
- return /* @__PURE__ */ jsx(SelectItem, { value, children: label }, value);
833
+ return /* @__PURE__ */ jsx12(SelectItem, { value, children: label }, value);
716
834
  }) })
717
835
  ] });
718
836
  }
719
- var Slider = forwardRef(function Slider2({ showValue, width = 240, className, value, defaultValue, ...props }, ref) {
837
+
838
+ // src/components/Slider/Slider.tsx
839
+ import * as RadixSlider from "@radix-ui/react-slider";
840
+ import { forwardRef as forwardRef12, useCallback as useCallback5, useState as useState6 } from "react";
841
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
842
+ var Slider = forwardRef12(function Slider2({
843
+ showValue,
844
+ width = 240,
845
+ className,
846
+ value,
847
+ defaultValue,
848
+ onValueChange,
849
+ thumbLabels,
850
+ "aria-label": ariaLabel,
851
+ "aria-labelledby": ariaLabelledBy,
852
+ ...props
853
+ }, ref) {
720
854
  const arrValue = Array.isArray(value) ? value : value !== void 0 ? [value] : void 0;
721
855
  const arrDefault = Array.isArray(defaultValue) ? defaultValue : defaultValue !== void 0 ? [defaultValue] : void 0;
722
- const display = arrValue?.[0] ?? arrDefault?.[0] ?? props.min ?? 0;
723
- return /* @__PURE__ */ jsxs(
856
+ const isControlled = arrValue !== void 0;
857
+ const [uncontrolledValue, setUncontrolledValue] = useState6(arrDefault);
858
+ const currentValue = isControlled ? arrValue : uncontrolledValue;
859
+ const wasScalar = !Array.isArray(value ?? defaultValue) && (value ?? defaultValue) !== void 0;
860
+ const handleValueChange = useCallback5(
861
+ (next) => {
862
+ if (!isControlled) setUncontrolledValue(next);
863
+ if (onValueChange) {
864
+ onValueChange(wasScalar ? next[0] ?? 0 : next);
865
+ }
866
+ },
867
+ [isControlled, onValueChange, wasScalar]
868
+ );
869
+ const display = currentValue?.[0] ?? props.min ?? 0;
870
+ const thumbCount = (arrValue ?? arrDefault)?.length ?? 1;
871
+ return /* @__PURE__ */ jsxs10(
724
872
  "span",
725
873
  {
726
874
  ref,
727
875
  className: cn("inline-flex items-center gap-[10px]", className),
728
876
  style: { width },
729
877
  children: [
730
- /* @__PURE__ */ jsxs(
878
+ /* @__PURE__ */ jsxs10(
731
879
  RadixSlider.Root,
732
880
  {
733
881
  value: arrValue,
734
882
  defaultValue: arrDefault,
883
+ onValueChange: handleValueChange,
735
884
  className: "relative flex h-4 flex-1 touch-none items-center select-none",
736
885
  ...props,
737
886
  children: [
738
- /* @__PURE__ */ jsx(RadixSlider.Track, { className: "bg-panel-2 relative h-1 grow rounded-full", children: /* @__PURE__ */ jsx(RadixSlider.Range, { className: "bg-accent absolute h-full rounded-full" }) }),
739
- /* @__PURE__ */ jsx(
740
- RadixSlider.Thumb,
741
- {
742
- className: cn(
743
- "bg-text border-accent block h-[14px] w-[14px] rounded-full border-2 shadow",
744
- "focus-visible:ring-accent-dim outline-none focus-visible:ring-[3px]",
745
- "cursor-grab active:cursor-grabbing"
746
- ),
747
- "aria-label": "Value"
748
- }
749
- )
887
+ /* @__PURE__ */ jsx13(RadixSlider.Track, { className: "bg-panel-2 relative h-1 grow rounded-full", children: /* @__PURE__ */ jsx13(RadixSlider.Range, { className: "bg-accent absolute h-full rounded-full" }) }),
888
+ Array.from({ length: thumbCount }, (_, i) => {
889
+ const perThumb = thumbLabels?.[i];
890
+ const thumbAriaLabel = perThumb ?? (ariaLabelledBy ? void 0 : ariaLabel ?? "Value");
891
+ return /* @__PURE__ */ jsx13(
892
+ RadixSlider.Thumb,
893
+ {
894
+ className: cn(
895
+ "bg-text border-accent block h-[14px] w-[14px] rounded-full border-2 shadow",
896
+ "focus-visible:ring-accent-dim outline-none focus-visible:ring-[3px]",
897
+ "cursor-grab active:cursor-grabbing"
898
+ ),
899
+ "aria-label": thumbAriaLabel,
900
+ "aria-labelledby": perThumb ? void 0 : ariaLabelledBy
901
+ },
902
+ i
903
+ );
904
+ })
750
905
  ]
751
906
  }
752
907
  ),
753
- showValue && /* @__PURE__ */ jsx("span", { className: "text-text-muted min-w-[28px] text-right font-mono text-[11px]", children: display })
908
+ showValue && /* @__PURE__ */ jsx13("span", { className: "text-text-muted min-w-[28px] text-right font-mono text-[11px]", children: display })
754
909
  ]
755
910
  }
756
911
  );
757
912
  });
758
913
  Slider.displayName = "Slider";
914
+
915
+ // src/components/Switch/Switch.tsx
916
+ import * as RadixSwitch from "@radix-ui/react-switch";
917
+ import { forwardRef as forwardRef13, useId as useId5 } from "react";
918
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
759
919
  var trackClasses = {
760
920
  sm: "h-4 w-7",
761
921
  md: "h-5 w-9"
@@ -764,10 +924,10 @@ var thumbClasses = {
764
924
  sm: "h-3 w-3 data-[state=checked]:translate-x-3",
765
925
  md: "h-4 w-4 data-[state=checked]:translate-x-4"
766
926
  };
767
- var Switch = forwardRef(function Switch2({ label, size = "md", className, id: idProp, ...props }, ref) {
768
- const reactId = useId();
927
+ var Switch = forwardRef13(function Switch2({ label, size = "md", className, id: idProp, ...props }, ref) {
928
+ const reactId = useId5();
769
929
  const id = idProp ?? `sw-${reactId}`;
770
- return /* @__PURE__ */ jsxs(
930
+ return /* @__PURE__ */ jsxs11(
771
931
  "span",
772
932
  {
773
933
  className: cn(
@@ -776,7 +936,7 @@ var Switch = forwardRef(function Switch2({ label, size = "md", className, id: id
776
936
  className
777
937
  ),
778
938
  children: [
779
- /* @__PURE__ */ jsx(
939
+ /* @__PURE__ */ jsx14(
780
940
  RadixSwitch.Root,
781
941
  {
782
942
  ref,
@@ -789,7 +949,7 @@ var Switch = forwardRef(function Switch2({ label, size = "md", className, id: id
789
949
  trackClasses[size]
790
950
  ),
791
951
  ...props,
792
- children: /* @__PURE__ */ jsx(
952
+ children: /* @__PURE__ */ jsx14(
793
953
  RadixSwitch.Thumb,
794
954
  {
795
955
  className: cn(
@@ -801,13 +961,18 @@ var Switch = forwardRef(function Switch2({ label, size = "md", className, id: id
801
961
  )
802
962
  }
803
963
  ),
804
- label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "cursor-pointer text-[13px]", children: label })
964
+ label && /* @__PURE__ */ jsx14("label", { htmlFor: id, className: "cursor-pointer text-[13px]", children: label })
805
965
  ]
806
966
  }
807
967
  );
808
968
  });
809
969
  Switch.displayName = "Switch";
810
- var textareaStyles = cva(
970
+
971
+ // src/components/Textarea/Textarea.tsx
972
+ import { cva as cva4 } from "class-variance-authority";
973
+ import { forwardRef as forwardRef14 } from "react";
974
+ import { jsx as jsx15 } from "react/jsx-runtime";
975
+ var textareaStyles = cva4(
811
976
  [
812
977
  "w-full font-sans text-text bg-panel rounded-md p-[10px]",
813
978
  "border outline-none transition-[border-color,box-shadow] duration-(--duration-micro)",
@@ -819,26 +984,97 @@ var textareaStyles = cva(
819
984
  variants: {
820
985
  tone: {
821
986
  default: "border-border focus-visible:border-accent focus-visible:ring-accent-dim",
822
- error: "border-err focus-visible:border-err focus-visible:ring-[oklch(0.55_0.18_30/0.18)]"
987
+ err: "border-err focus-visible:border-err focus-visible:ring-err/30"
823
988
  }
824
989
  },
825
990
  defaultVariants: { tone: "default" }
826
991
  }
827
992
  );
828
- var Textarea = forwardRef(function Textarea2({ tone, error, rows = 4, className, ...props }, ref) {
829
- return /* @__PURE__ */ jsx(
993
+ var Textarea = forwardRef14(function Textarea2({ tone, error, rows = 4, className, ...props }, ref) {
994
+ return /* @__PURE__ */ jsx15(
830
995
  "textarea",
831
996
  {
832
997
  ref,
833
998
  rows,
834
999
  "aria-invalid": error || void 0,
835
- className: cn(textareaStyles({ tone: error ? "error" : tone }), className),
1000
+ className: cn(textareaStyles({ tone: error ? "err" : tone }), className),
836
1001
  ...props
837
1002
  }
838
1003
  );
839
1004
  });
840
1005
  Textarea.displayName = "Textarea";
841
- var sizePx = { xs: 20, sm: 24, md: 32, lg: 40, xl: 56 };
1006
+
1007
+ // src/components/Avatar/Avatar.tsx
1008
+ import * as RadixAvatar from "@radix-ui/react-avatar";
1009
+ import { forwardRef as forwardRef16 } from "react";
1010
+
1011
+ // src/components/StatusDot/StatusDot.tsx
1012
+ import { forwardRef as forwardRef15 } from "react";
1013
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1014
+ var stateColor = {
1015
+ ok: "bg-ok",
1016
+ warn: "bg-warn",
1017
+ err: "bg-err",
1018
+ off: "bg-text-dim",
1019
+ sync: "bg-accent",
1020
+ accent: "bg-accent"
1021
+ };
1022
+ var stateText = {
1023
+ ok: "text-ok",
1024
+ warn: "text-warn",
1025
+ err: "text-err",
1026
+ off: "text-text-dim",
1027
+ sync: "text-accent",
1028
+ accent: "text-accent"
1029
+ };
1030
+ var stateLabel = {
1031
+ ok: "Online",
1032
+ warn: "Warning",
1033
+ err: "Error",
1034
+ off: "Offline",
1035
+ sync: "Syncing",
1036
+ accent: "Active"
1037
+ };
1038
+ var StatusDot = forwardRef15(function StatusDot2({ state = "ok", label, pulse, size = 8, className, ...props }, ref) {
1039
+ return /* @__PURE__ */ jsxs12(
1040
+ "span",
1041
+ {
1042
+ ref,
1043
+ role: label ? "status" : "img",
1044
+ "aria-label": !label ? stateLabel[state] : void 0,
1045
+ className: cn("inline-flex items-center gap-[6px]", className),
1046
+ ...props,
1047
+ children: [
1048
+ /* @__PURE__ */ jsx16(
1049
+ "span",
1050
+ {
1051
+ className: cn(
1052
+ "inline-block rounded-full",
1053
+ stateColor[state],
1054
+ pulse && "animate-[ship-pulse-ring_1.6s_infinite]",
1055
+ stateText[state]
1056
+ ),
1057
+ style: { width: size, height: size }
1058
+ }
1059
+ ),
1060
+ label && /* @__PURE__ */ jsx16("span", { className: "text-text-muted text-[12px]", children: label })
1061
+ ]
1062
+ }
1063
+ );
1064
+ });
1065
+ StatusDot.displayName = "StatusDot";
1066
+
1067
+ // src/components/Avatar/sizes.ts
1068
+ var sizePx = {
1069
+ xs: 20,
1070
+ sm: 24,
1071
+ md: 32,
1072
+ lg: 40,
1073
+ xl: 56
1074
+ };
1075
+
1076
+ // src/components/Avatar/Avatar.tsx
1077
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
842
1078
  var statusBg = {
843
1079
  ok: "bg-ok",
844
1080
  warn: "bg-warn",
@@ -853,11 +1089,11 @@ function hashHue(str) {
853
1089
  for (let i = 0; i < str.length; i++) h = (h * 31 + str.charCodeAt(i)) % 360;
854
1090
  return h;
855
1091
  }
856
- var Avatar = forwardRef(function Avatar2({ name = "?", src, size = "md", status, initials, className, style, ...props }, ref) {
1092
+ var Avatar = forwardRef16(function Avatar2({ name = "?", src, size = "md", status, initials, className, style, ...props }, ref) {
857
1093
  const dim = sizePx[size];
858
1094
  const hue = hashHue(name);
859
1095
  const computedInitials = initials ?? initialsFor(name);
860
- return /* @__PURE__ */ jsxs(
1096
+ return /* @__PURE__ */ jsxs13(
861
1097
  "span",
862
1098
  {
863
1099
  ref,
@@ -865,14 +1101,16 @@ var Avatar = forwardRef(function Avatar2({ name = "?", src, size = "md", status,
865
1101
  style: { width: dim, height: dim, ...style },
866
1102
  ...props,
867
1103
  children: [
868
- /* @__PURE__ */ jsxs(
1104
+ /* @__PURE__ */ jsxs13(
869
1105
  RadixAvatar.Root,
870
1106
  {
871
1107
  className: "border-border relative inline-flex h-full w-full shrink-0 overflow-hidden rounded-full border",
872
- style: { background: src ? void 0 : `oklch(0.4 0.1 ${hue})` },
1108
+ style: {
1109
+ background: src ? void 0 : `oklch(var(--color-avatar-fallback-l) var(--color-avatar-fallback-c) ${hue})`
1110
+ },
873
1111
  children: [
874
- src && /* @__PURE__ */ jsx(RadixAvatar.Image, { src, alt: name, className: "h-full w-full object-cover" }),
875
- /* @__PURE__ */ jsx(
1112
+ src && /* @__PURE__ */ jsx17(RadixAvatar.Image, { src, alt: name, className: "h-full w-full object-cover" }),
1113
+ /* @__PURE__ */ jsx17(
876
1114
  RadixAvatar.Fallback,
877
1115
  {
878
1116
  className: "flex h-full w-full items-center justify-center font-sans font-semibold text-white",
@@ -883,11 +1121,11 @@ var Avatar = forwardRef(function Avatar2({ name = "?", src, size = "md", status,
883
1121
  ]
884
1122
  }
885
1123
  ),
886
- status && /* @__PURE__ */ jsx(
1124
+ status && /* @__PURE__ */ jsx17(
887
1125
  "span",
888
1126
  {
889
1127
  role: "img",
890
- "aria-label": `status: ${status}`,
1128
+ "aria-label": stateLabel[status],
891
1129
  className: cn(
892
1130
  "border-bg absolute right-0 bottom-0 rounded-full border-[2px]",
893
1131
  statusBg[status]
@@ -900,15 +1138,18 @@ var Avatar = forwardRef(function Avatar2({ name = "?", src, size = "md", status,
900
1138
  );
901
1139
  });
902
1140
  Avatar.displayName = "Avatar";
903
- var sizePx2 = { xs: 20, sm: 24, md: 32, lg: 40, xl: 56 };
904
- var AvatarGroup = forwardRef(function AvatarGroup2({ names, max = 3, size = "md", className, ...props }, ref) {
905
- const dim = sizePx2[size];
1141
+
1142
+ // src/components/Avatar/AvatarGroup.tsx
1143
+ import { forwardRef as forwardRef17 } from "react";
1144
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1145
+ var AvatarGroup = forwardRef17(function AvatarGroup2({ names, max = 3, size = "md", className, ...props }, ref) {
1146
+ const dim = sizePx[size];
906
1147
  const visible = names.slice(0, max);
907
1148
  const rest = names.length - visible.length;
908
1149
  const overlap = -dim * 0.35;
909
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("inline-flex", className), ...props, children: [
910
- visible.map((n, i) => /* @__PURE__ */ jsx("span", { style: { marginLeft: i === 0 ? 0 : overlap }, children: /* @__PURE__ */ jsx(Avatar, { name: n, size }) }, `${n}-${i}`)),
911
- rest > 0 && /* @__PURE__ */ jsxs(
1150
+ return /* @__PURE__ */ jsxs14("div", { ref, className: cn("inline-flex", className), ...props, children: [
1151
+ visible.map((n, i) => /* @__PURE__ */ jsx18("span", { style: { marginLeft: i === 0 ? 0 : overlap }, children: /* @__PURE__ */ jsx18(Avatar, { name: n, size }) }, `${n}-${i}`)),
1152
+ rest > 0 && /* @__PURE__ */ jsxs14(
912
1153
  "span",
913
1154
  {
914
1155
  "aria-label": `+${rest} more`,
@@ -928,7 +1169,12 @@ var AvatarGroup = forwardRef(function AvatarGroup2({ names, max = 3, size = "md"
928
1169
  ] });
929
1170
  });
930
1171
  AvatarGroup.displayName = "AvatarGroup";
931
- var badgeStyles = cva("inline-flex items-center font-sans leading-none whitespace-nowrap", {
1172
+
1173
+ // src/components/Badge/Badge.tsx
1174
+ import { cva as cva5 } from "class-variance-authority";
1175
+ import { forwardRef as forwardRef18 } from "react";
1176
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
1177
+ var badgeStyles = cva5("inline-flex items-center font-sans leading-none whitespace-nowrap", {
932
1178
  variants: {
933
1179
  variant: {
934
1180
  neutral: "bg-panel-2 text-text-muted border border-border",
@@ -961,21 +1207,28 @@ var dotColorClass = {
961
1207
  solid: "bg-bg"
962
1208
  };
963
1209
  var dotSize = { sm: "h-[5px] w-[5px]", md: "h-[6px] w-[6px]", lg: "h-[7px] w-[7px]" };
964
- var Badge = forwardRef(function Badge2({ variant = "neutral", size = "md", dot, icon, className, children, ...props }, ref) {
965
- return /* @__PURE__ */ jsxs("span", { ref, className: cn(badgeStyles({ variant, size }), className), ...props, children: [
966
- dot && /* @__PURE__ */ jsx(
1210
+ var Badge = forwardRef18(function Badge2({ variant = "neutral", size = "md", dot, icon, className, children, ...props }, ref) {
1211
+ const sz = size ?? "md";
1212
+ const v = variant ?? "neutral";
1213
+ return /* @__PURE__ */ jsxs15("span", { ref, className: cn(badgeStyles({ variant, size }), className), ...props, children: [
1214
+ dot && /* @__PURE__ */ jsx19(
967
1215
  "span",
968
1216
  {
969
1217
  "aria-hidden": true,
970
- className: cn("inline-block rounded-full", dotSize[size], dotColorClass[variant])
1218
+ className: cn("inline-block rounded-full", dotSize[sz], dotColorClass[v])
971
1219
  }
972
1220
  ),
973
- icon && /* @__PURE__ */ jsx("span", { className: "inline-flex leading-none", children: icon }),
1221
+ icon && /* @__PURE__ */ jsx19("span", { className: "inline-flex leading-none", children: icon }),
974
1222
  children
975
1223
  ] });
976
1224
  });
977
1225
  Badge.displayName = "Badge";
978
- var cardStyles = cva(
1226
+
1227
+ // src/components/Card/Card.tsx
1228
+ import { cva as cva6 } from "class-variance-authority";
1229
+ import { forwardRef as forwardRef19 } from "react";
1230
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
1231
+ var cardStyles = cva6(
979
1232
  "block bg-panel border border-border rounded-base transition-[border-color,transform,box-shadow] duration-(--duration-step)",
980
1233
  {
981
1234
  variants: {
@@ -992,7 +1245,7 @@ var cardStyles = cva(
992
1245
  defaultVariants: { variant: "default", interactive: false }
993
1246
  }
994
1247
  );
995
- var Card = forwardRef(function Card2({
1248
+ var Card = forwardRef19(function Card2({
996
1249
  variant,
997
1250
  interactive,
998
1251
  title,
@@ -1002,57 +1255,96 @@ var Card = forwardRef(function Card2({
1002
1255
  className,
1003
1256
  children,
1004
1257
  onClick,
1258
+ onActivate,
1005
1259
  ...props
1006
1260
  }, ref) {
1007
- const isInteractive = interactive ?? Boolean(onClick);
1008
- return /* @__PURE__ */ jsxs(
1261
+ const wantsInteractive = interactive ?? Boolean(onClick);
1262
+ const hasActions = actions != null;
1263
+ if (wantsInteractive && hasActions && process.env.NODE_ENV !== "production") {
1264
+ console.warn(
1265
+ "[Card] `interactive` was requested but `actions` is also set, which would create a nested-interactive a11y violation. The card will render as a plain <div>. Use <CardLink> for whole-card links, or move the actions outside the card."
1266
+ );
1267
+ }
1268
+ const isInteractive = wantsInteractive && !hasActions;
1269
+ const handleKeyDown = isInteractive ? (e) => {
1270
+ if (e.key !== "Enter" && e.key !== " ") return;
1271
+ if (onActivate) {
1272
+ e.preventDefault();
1273
+ onActivate();
1274
+ } else if (onClick) {
1275
+ e.preventDefault();
1276
+ onClick(e);
1277
+ }
1278
+ } : void 0;
1279
+ return /* @__PURE__ */ jsxs16(
1009
1280
  "div",
1010
1281
  {
1011
1282
  ref,
1012
1283
  onClick,
1013
- onKeyDown: isInteractive && onClick ? (e) => {
1014
- if (e.key === "Enter" || e.key === " ") {
1015
- e.preventDefault();
1016
- onClick(e);
1017
- }
1018
- } : void 0,
1284
+ onKeyDown: handleKeyDown,
1019
1285
  role: isInteractive ? "button" : void 0,
1020
1286
  tabIndex: isInteractive ? 0 : void 0,
1021
- className: cn(cardStyles({ variant, interactive: isInteractive }), "p-[18px]", className),
1287
+ className: cn(cardStyles({ variant, interactive: wantsInteractive }), "p-[18px]", className),
1022
1288
  ...props,
1023
1289
  children: [
1024
- (title || actions) && /* @__PURE__ */ jsxs("div", { className: cn("flex items-start gap-3", (description || children) && "mb-[10px]"), children: [
1025
- title && /* @__PURE__ */ jsx("div", { className: "flex-1 text-[14px] font-medium", children: title }),
1026
- actions && /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: actions })
1290
+ (title || actions) && /* @__PURE__ */ jsxs16("div", { className: cn("flex items-start gap-3", (description || children) && "mb-[10px]"), children: [
1291
+ title && /* @__PURE__ */ jsx20("div", { className: "flex-1 text-[14px] font-medium", children: title }),
1292
+ actions && /* @__PURE__ */ jsx20("div", { className: "flex gap-1", children: actions })
1027
1293
  ] }),
1028
- description && /* @__PURE__ */ jsx("div", { className: cn("text-text-muted text-[12px] leading-[1.55]", children && "mb-[14px]"), children: description }),
1294
+ description && /* @__PURE__ */ jsx20("div", { className: cn("text-text-muted text-[12px] leading-[1.55]", children && "mb-[14px]"), children: description }),
1029
1295
  children,
1030
- footer && /* @__PURE__ */ jsx("div", { className: "border-border text-text-dim mt-[14px] border-t pt-3 text-[11px]", children: footer })
1296
+ footer && /* @__PURE__ */ jsx20("div", { className: "border-border text-text-dim mt-[14px] border-t pt-3 text-[11px]", children: footer })
1031
1297
  ]
1032
1298
  }
1033
1299
  );
1034
1300
  });
1035
1301
  Card.displayName = "Card";
1302
+ var CardLink = forwardRef19(function CardLink2({ variant, title, description, footer, className, children, href, ...props }, ref) {
1303
+ return /* @__PURE__ */ jsxs16(
1304
+ "a",
1305
+ {
1306
+ ref,
1307
+ href,
1308
+ className: cn(
1309
+ cardStyles({ variant, interactive: true }),
1310
+ "focus-visible:ring-accent-dim p-[18px] no-underline outline-none focus-visible:ring-[3px]",
1311
+ className
1312
+ ),
1313
+ ...props,
1314
+ children: [
1315
+ title && /* @__PURE__ */ jsx20("div", { className: cn("flex items-start", (description || children) && "mb-[10px]"), children: /* @__PURE__ */ jsx20("div", { className: "flex-1 text-[14px] font-medium", children: title }) }),
1316
+ description && /* @__PURE__ */ jsx20("div", { className: cn("text-text-muted text-[12px] leading-[1.55]", children && "mb-[14px]"), children: description }),
1317
+ children,
1318
+ footer && /* @__PURE__ */ jsx20("div", { className: "border-border text-text-dim mt-[14px] border-t pt-3 text-[11px]", children: footer })
1319
+ ]
1320
+ }
1321
+ );
1322
+ });
1323
+ CardLink.displayName = "CardLink";
1324
+
1325
+ // src/components/Card/StatCard.tsx
1326
+ import { forwardRef as forwardRef20 } from "react";
1327
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
1036
1328
  var trendClasses = {
1037
1329
  up: "text-ok",
1038
1330
  down: "text-err",
1039
1331
  flat: "text-text-dim"
1040
1332
  };
1041
1333
  var trendArrows = { up: "\u2191", down: "\u2193", flat: "\u2192" };
1042
- var StatCard = forwardRef(function StatCard2({ label, value, delta, trend = "flat", icon, className, ...props }, ref) {
1043
- return /* @__PURE__ */ jsxs(
1334
+ var StatCard = forwardRef20(function StatCard2({ label, value, delta, trend = "flat", icon, className, ...props }, ref) {
1335
+ return /* @__PURE__ */ jsxs17(
1044
1336
  "div",
1045
1337
  {
1046
1338
  ref,
1047
1339
  className: cn("bg-panel border-border rounded-base block border p-[18px]", className),
1048
1340
  ...props,
1049
1341
  children: [
1050
- /* @__PURE__ */ jsxs("div", { className: "mb-[10px] flex items-center justify-between", children: [
1051
- /* @__PURE__ */ jsx("div", { className: "text-text-dim font-mono text-[10px] tracking-wide uppercase", children: label }),
1052
- icon && /* @__PURE__ */ jsx("div", { className: "text-text-dim text-[14px]", children: icon })
1342
+ /* @__PURE__ */ jsxs17("div", { className: "mb-[10px] flex items-center justify-between", children: [
1343
+ /* @__PURE__ */ jsx21("div", { className: "text-text-dim font-mono text-[10px] tracking-wide uppercase", children: label }),
1344
+ icon && /* @__PURE__ */ jsx21("div", { className: "text-text-dim text-[14px]", children: icon })
1053
1345
  ] }),
1054
- /* @__PURE__ */ jsx("div", { className: "text-text font-mono text-[26px] leading-none font-medium tracking-tight", children: value }),
1055
- delta !== void 0 && /* @__PURE__ */ jsxs("div", { className: cn("mt-[6px] font-mono text-[11px]", trendClasses[trend]), children: [
1346
+ /* @__PURE__ */ jsx21("div", { className: "text-text font-mono text-[26px] leading-none font-medium tracking-tight", children: value }),
1347
+ delta !== void 0 && /* @__PURE__ */ jsxs17("div", { className: cn("mt-[6px] font-mono text-[11px]", trendClasses[trend]), children: [
1056
1348
  trendArrows[trend],
1057
1349
  " ",
1058
1350
  delta
@@ -1062,8 +1354,12 @@ var StatCard = forwardRef(function StatCard2({ label, value, delta, trend = "fla
1062
1354
  );
1063
1355
  });
1064
1356
  StatCard.displayName = "StatCard";
1065
- var Chip = forwardRef(function Chip2({ icon, removable, onRemove, className, children, ...props }, ref) {
1066
- return /* @__PURE__ */ jsxs(
1357
+
1358
+ // src/components/Chip/Chip.tsx
1359
+ import { forwardRef as forwardRef21 } from "react";
1360
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1361
+ var Chip = forwardRef21(function Chip2({ icon, onRemove, className, children, ...props }, ref) {
1362
+ return /* @__PURE__ */ jsxs18(
1067
1363
  "span",
1068
1364
  {
1069
1365
  ref,
@@ -1074,9 +1370,9 @@ var Chip = forwardRef(function Chip2({ icon, removable, onRemove, className, chi
1074
1370
  ),
1075
1371
  ...props,
1076
1372
  children: [
1077
- icon && /* @__PURE__ */ jsx("span", { className: "text-text-dim inline-flex text-[10px]", children: icon }),
1373
+ icon && /* @__PURE__ */ jsx22("span", { className: "text-text-dim inline-flex text-[10px]", children: icon }),
1078
1374
  children,
1079
- removable && /* @__PURE__ */ jsx(
1375
+ onRemove && /* @__PURE__ */ jsx22(
1080
1376
  "button",
1081
1377
  {
1082
1378
  type: "button",
@@ -1091,8 +1387,12 @@ var Chip = forwardRef(function Chip2({ icon, removable, onRemove, className, chi
1091
1387
  );
1092
1388
  });
1093
1389
  Chip.displayName = "Chip";
1094
- var Kbd = forwardRef(function Kbd2({ className, children, ...props }, ref) {
1095
- return /* @__PURE__ */ jsx(
1390
+
1391
+ // src/components/Kbd/Kbd.tsx
1392
+ import { forwardRef as forwardRef22 } from "react";
1393
+ import { jsx as jsx23 } from "react/jsx-runtime";
1394
+ var Kbd = forwardRef22(function Kbd2({ className, children, ...props }, ref) {
1395
+ return /* @__PURE__ */ jsx23(
1096
1396
  "kbd",
1097
1397
  {
1098
1398
  ref,
@@ -1108,7 +1408,12 @@ var Kbd = forwardRef(function Kbd2({ className, children, ...props }, ref) {
1108
1408
  );
1109
1409
  });
1110
1410
  Kbd.displayName = "Kbd";
1111
- var skeletonStyles = cva("block bg-panel-2 animate-[ship-skeleton_1.4s_infinite]", {
1411
+
1412
+ // src/components/Skeleton/Skeleton.tsx
1413
+ import { cva as cva7 } from "class-variance-authority";
1414
+ import { forwardRef as forwardRef23 } from "react";
1415
+ import { jsx as jsx24 } from "react/jsx-runtime";
1416
+ var skeletonStyles = cva7("block bg-panel-2 animate-[ship-skeleton_1.4s_infinite]", {
1112
1417
  variants: {
1113
1418
  shape: {
1114
1419
  line: "rounded-xs",
@@ -1119,16 +1424,15 @@ var skeletonStyles = cva("block bg-panel-2 animate-[ship-skeleton_1.4s_infinite]
1119
1424
  defaultVariants: { shape: "line" }
1120
1425
  });
1121
1426
  var defaultHeight = { line: 14, block: 80, circle: 40 };
1122
- var Skeleton = forwardRef(function Skeleton2({ shape = "line", width = "100%", height, className, style, ...props }, ref) {
1427
+ var Skeleton = forwardRef23(function Skeleton2({ shape = "line", width = "100%", height, standalone = false, className, style, ...props }, ref) {
1123
1428
  const h = height ?? defaultHeight[shape];
1124
1429
  const w = shape === "circle" ? h : width;
1125
- return /* @__PURE__ */ jsx(
1430
+ const a11yProps = standalone ? { role: "status", "aria-busy": true, "aria-label": "Loading" } : { "aria-hidden": true };
1431
+ return /* @__PURE__ */ jsx24(
1126
1432
  "div",
1127
1433
  {
1128
1434
  ref,
1129
- role: "status",
1130
- "aria-busy": "true",
1131
- "aria-label": "Loading",
1435
+ ...a11yProps,
1132
1436
  className: cn(skeletonStyles({ shape }), className),
1133
1437
  style: { width: w, height: h, ...style },
1134
1438
  ...props
@@ -1136,52 +1440,30 @@ var Skeleton = forwardRef(function Skeleton2({ shape = "line", width = "100%", h
1136
1440
  );
1137
1441
  });
1138
1442
  Skeleton.displayName = "Skeleton";
1139
- var stateColor = {
1140
- ok: "bg-ok",
1141
- warn: "bg-warn",
1142
- err: "bg-err",
1143
- off: "bg-text-dim",
1144
- sync: "bg-accent",
1145
- accent: "bg-accent"
1146
- };
1147
- var stateText = {
1148
- ok: "text-ok",
1149
- warn: "text-warn",
1150
- err: "text-err",
1151
- off: "text-text-dim",
1152
- sync: "text-accent",
1153
- accent: "text-accent"
1154
- };
1155
- var StatusDot = forwardRef(function StatusDot2({ state = "ok", label, pulse, size = 8, className, ...props }, ref) {
1156
- return /* @__PURE__ */ jsxs(
1157
- "span",
1443
+ var SkeletonGroup = forwardRef23(function SkeletonGroup2({ label = "Loading", loading = true, className, children, ...props }, ref) {
1444
+ if (!loading) {
1445
+ return /* @__PURE__ */ jsx24("div", { ref, className, ...props, children });
1446
+ }
1447
+ return /* @__PURE__ */ jsx24(
1448
+ "div",
1158
1449
  {
1159
1450
  ref,
1160
- role: label ? "status" : "img",
1161
- "aria-label": !label && typeof state === "string" ? state : void 0,
1162
- className: cn("inline-flex items-center gap-[6px]", className),
1451
+ role: "status",
1452
+ "aria-busy": "true",
1453
+ "aria-label": label,
1454
+ className,
1163
1455
  ...props,
1164
- children: [
1165
- /* @__PURE__ */ jsx(
1166
- "span",
1167
- {
1168
- className: cn(
1169
- "inline-block rounded-full",
1170
- stateColor[state],
1171
- pulse && "animate-[ship-pulse-ring_1.6s_infinite]",
1172
- stateText[state]
1173
- ),
1174
- style: { width: size, height: size }
1175
- }
1176
- ),
1177
- label && /* @__PURE__ */ jsx("span", { className: "text-text-muted text-[12px]", children: label })
1178
- ]
1456
+ children
1179
1457
  }
1180
1458
  );
1181
1459
  });
1182
- StatusDot.displayName = "StatusDot";
1183
- var Tag = forwardRef(function Tag2({ onRemove, icon, size = 22, className, children, ...props }, ref) {
1184
- return /* @__PURE__ */ jsxs(
1460
+ SkeletonGroup.displayName = "SkeletonGroup";
1461
+
1462
+ // src/components/Tag/Tag.tsx
1463
+ import { forwardRef as forwardRef24 } from "react";
1464
+ import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
1465
+ var Tag = forwardRef24(function Tag2({ onRemove, icon, size = 22, className, children, ...props }, ref) {
1466
+ return /* @__PURE__ */ jsxs19(
1185
1467
  "span",
1186
1468
  {
1187
1469
  ref,
@@ -1193,9 +1475,9 @@ var Tag = forwardRef(function Tag2({ onRemove, icon, size = 22, className, child
1193
1475
  style: { height: size },
1194
1476
  ...props,
1195
1477
  children: [
1196
- icon && /* @__PURE__ */ jsx("span", { className: "text-text-dim inline-flex", children: icon }),
1478
+ icon && /* @__PURE__ */ jsx25("span", { className: "text-text-dim inline-flex", children: icon }),
1197
1479
  children,
1198
- onRemove && /* @__PURE__ */ jsx(
1480
+ onRemove && /* @__PURE__ */ jsx25(
1199
1481
  "button",
1200
1482
  {
1201
1483
  type: "button",
@@ -1210,17 +1492,22 @@ var Tag = forwardRef(function Tag2({ onRemove, icon, size = 22, className, child
1210
1492
  );
1211
1493
  });
1212
1494
  Tag.displayName = "Tag";
1495
+
1496
+ // src/components/ContextMenu/ContextMenu.tsx
1497
+ import * as RadixContext from "@radix-ui/react-context-menu";
1498
+ import { forwardRef as forwardRef25 } from "react";
1499
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
1213
1500
  var ContextMenuRoot = RadixContext.Root;
1214
1501
  var ContextMenuTrigger = RadixContext.Trigger;
1215
1502
  var ContextMenuPortal = RadixContext.Portal;
1216
- var ContextMenuContent = forwardRef(
1503
+ var ContextMenuContent = forwardRef25(
1217
1504
  function ContextMenuContent2({ className, ...props }, ref) {
1218
- return /* @__PURE__ */ jsx(RadixContext.Portal, { children: /* @__PURE__ */ jsx(
1505
+ return /* @__PURE__ */ jsx26(RadixContext.Portal, { children: /* @__PURE__ */ jsx26(
1219
1506
  RadixContext.Content,
1220
1507
  {
1221
1508
  ref,
1222
1509
  className: cn(
1223
- "bg-panel border-border-strong z-40 min-w-[180px] rounded-md border p-1 shadow-lg outline-none",
1510
+ "bg-panel border-border-strong z-popover min-w-[180px] rounded-md border p-1 shadow-lg outline-none",
1224
1511
  "data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
1225
1512
  className
1226
1513
  ),
@@ -1235,26 +1522,26 @@ var itemBase = cn(
1235
1522
  "data-[highlighted]:bg-panel-2",
1236
1523
  "data-[disabled]:opacity-40 data-[disabled]:cursor-not-allowed"
1237
1524
  );
1238
- var ContextMenuItem = forwardRef(
1525
+ var ContextMenuItem = forwardRef25(
1239
1526
  function ContextMenuItem2({ icon, trailing, destructive, className, children, ...props }, ref) {
1240
- return /* @__PURE__ */ jsxs(
1527
+ return /* @__PURE__ */ jsxs20(
1241
1528
  RadixContext.Item,
1242
1529
  {
1243
1530
  ref,
1244
1531
  className: cn(itemBase, destructive ? "text-err" : "text-text", className),
1245
1532
  ...props,
1246
1533
  children: [
1247
- icon && /* @__PURE__ */ jsx("span", { className: "w-[14px] text-[12px] opacity-70", children: icon }),
1248
- /* @__PURE__ */ jsx("span", { className: "flex-1", children }),
1249
- trailing && /* @__PURE__ */ jsx("span", { className: "text-text-dim font-mono text-[10px]", children: trailing })
1534
+ icon && /* @__PURE__ */ jsx26("span", { className: "w-[14px] text-[12px] opacity-70", children: icon }),
1535
+ /* @__PURE__ */ jsx26("span", { className: "flex-1", children }),
1536
+ trailing && /* @__PURE__ */ jsx26("span", { className: "text-text-dim font-mono text-[10px]", children: trailing })
1250
1537
  ]
1251
1538
  }
1252
1539
  );
1253
1540
  }
1254
1541
  );
1255
1542
  ContextMenuItem.displayName = "ContextMenuItem";
1256
- var ContextMenuSeparator = forwardRef(function ContextMenuSeparator2({ className, ...props }, ref) {
1257
- return /* @__PURE__ */ jsx(
1543
+ var ContextMenuSeparator = forwardRef25(function ContextMenuSeparator2({ className, ...props }, ref) {
1544
+ return /* @__PURE__ */ jsx26(
1258
1545
  RadixContext.Separator,
1259
1546
  {
1260
1547
  ref,
@@ -1265,18 +1552,23 @@ var ContextMenuSeparator = forwardRef(function ContextMenuSeparator2({ className
1265
1552
  });
1266
1553
  ContextMenuSeparator.displayName = "ContextMenuSeparator";
1267
1554
  var ContextMenu = RadixContext.Root;
1555
+
1556
+ // src/components/Dialog/Dialog.tsx
1557
+ import * as RadixDialog from "@radix-ui/react-dialog";
1558
+ import { forwardRef as forwardRef26 } from "react";
1559
+ import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
1268
1560
  var DialogRoot = RadixDialog.Root;
1269
1561
  var DialogTrigger = RadixDialog.Trigger;
1270
1562
  var DialogClose = RadixDialog.Close;
1271
1563
  var DialogPortal = RadixDialog.Portal;
1272
- var DialogOverlay = forwardRef(
1564
+ var DialogOverlay = forwardRef26(
1273
1565
  function DialogOverlay2({ className, ...props }, ref) {
1274
- return /* @__PURE__ */ jsx(
1566
+ return /* @__PURE__ */ jsx27(
1275
1567
  RadixDialog.Overlay,
1276
1568
  {
1277
1569
  ref,
1278
1570
  className: cn(
1279
- "fixed inset-0 z-50 bg-black/55 backdrop-blur-[4px]",
1571
+ "z-overlay fixed inset-0 bg-black/55 backdrop-blur-[4px]",
1280
1572
  "data-[state=open]:animate-[ship-fade-in_150ms_ease]",
1281
1573
  className
1282
1574
  ),
@@ -1286,15 +1578,15 @@ var DialogOverlay = forwardRef(
1286
1578
  }
1287
1579
  );
1288
1580
  DialogOverlay.displayName = "DialogOverlay";
1289
- var DialogContent = forwardRef(function DialogContent2({ className, width = 460, style, children, ...props }, ref) {
1290
- return /* @__PURE__ */ jsxs(DialogPortal, { children: [
1291
- /* @__PURE__ */ jsx(DialogOverlay, {}),
1292
- /* @__PURE__ */ jsx(
1581
+ var DialogContent = forwardRef26(function DialogContent2({ className, width = 460, style, children, ...props }, ref) {
1582
+ return /* @__PURE__ */ jsxs21(DialogPortal, { children: [
1583
+ /* @__PURE__ */ jsx27(DialogOverlay, {}),
1584
+ /* @__PURE__ */ jsx27(
1293
1585
  RadixDialog.Content,
1294
1586
  {
1295
1587
  ref,
1296
1588
  className: cn(
1297
- "fixed top-1/2 left-1/2 z-[51] w-[calc(100%-40px)] -translate-x-1/2 -translate-y-1/2 p-6",
1589
+ "z-modal fixed top-1/2 left-1/2 w-[calc(100%-40px)] -translate-x-1/2 -translate-y-1/2 p-6",
1298
1590
  "bg-panel border-border-strong rounded-lg border shadow-lg",
1299
1591
  "data-[state=open]:animate-[ship-dialog-in_180ms_var(--easing-out)]",
1300
1592
  "outline-none",
@@ -1309,27 +1601,32 @@ var DialogContent = forwardRef(function DialogContent2({ className, width = 460,
1309
1601
  });
1310
1602
  DialogContent.displayName = "DialogContent";
1311
1603
  function Dialog({ title, description, footer, width, children, ...rootProps }) {
1312
- return /* @__PURE__ */ jsx(DialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs(DialogContent, { width, children: [
1313
- title && /* @__PURE__ */ jsx(
1604
+ return /* @__PURE__ */ jsx27(DialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs21(DialogContent, { width, children: [
1605
+ title && /* @__PURE__ */ jsx27(
1314
1606
  RadixDialog.Title,
1315
1607
  {
1316
1608
  className: cn("text-[16px] font-medium", description ? "mb-[6px]" : "mb-4"),
1317
1609
  children: title
1318
1610
  }
1319
1611
  ),
1320
- description && /* @__PURE__ */ jsx(RadixDialog.Description, { className: "text-text-muted mb-[18px] text-[13px] leading-[1.55]", children: description }),
1612
+ description && /* @__PURE__ */ jsx27(RadixDialog.Description, { className: "text-text-muted mb-[18px] text-[13px] leading-[1.55]", children: description }),
1321
1613
  children,
1322
- footer && /* @__PURE__ */ jsx("div", { className: "mt-5 flex justify-end gap-2", children: footer })
1614
+ footer && /* @__PURE__ */ jsx27("div", { className: "mt-5 flex justify-end gap-2", children: footer })
1323
1615
  ] }) });
1324
1616
  }
1617
+
1618
+ // src/components/Dialog/Drawer.tsx
1619
+ import * as RadixDialog2 from "@radix-ui/react-dialog";
1620
+ import { forwardRef as forwardRef27 } from "react";
1621
+ import { jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
1325
1622
  var sideClasses = {
1326
1623
  left: "left-0 border-r border-border-strong data-[state=open]:animate-[ship-slide-in-left_220ms_var(--easing-out)]",
1327
1624
  right: "right-0 border-l border-border-strong data-[state=open]:animate-[ship-slide-in-right_220ms_var(--easing-out)]"
1328
1625
  };
1329
- var DrawerHeader = ({ title, onClose }) => /* @__PURE__ */ jsxs("div", { className: "border-border flex items-center justify-between border-b p-[16px] px-5", children: [
1330
- /* @__PURE__ */ jsx("span", { className: "text-[14px] font-medium", children: title }),
1331
- /* @__PURE__ */ jsx(
1332
- RadixDialog.Close,
1626
+ var DrawerHeader = ({ title, onClose }) => /* @__PURE__ */ jsxs22("div", { className: "border-border flex items-center justify-between border-b p-[16px] px-5", children: [
1627
+ /* @__PURE__ */ jsx28(RadixDialog2.Title, { className: "text-[14px] font-medium", children: title }),
1628
+ /* @__PURE__ */ jsx28(
1629
+ RadixDialog2.Close,
1333
1630
  {
1334
1631
  onClick: onClose,
1335
1632
  "aria-label": "Close",
@@ -1338,43 +1635,49 @@ var DrawerHeader = ({ title, onClose }) => /* @__PURE__ */ jsxs("div", { classNa
1338
1635
  }
1339
1636
  )
1340
1637
  ] });
1341
- var Drawer = forwardRef(function Drawer2({ side = "right", title, width = 420, children, ...rootProps }, ref) {
1342
- return /* @__PURE__ */ jsx(DialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs(DialogPortal, { children: [
1343
- /* @__PURE__ */ jsx(DialogOverlay, {}),
1344
- /* @__PURE__ */ jsxs(
1345
- RadixDialog.Content,
1638
+ var Drawer = forwardRef27(function Drawer2({ side = "right", title, width = 420, children, ...rootProps }, ref) {
1639
+ return /* @__PURE__ */ jsx28(DialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs22(DialogPortal, { children: [
1640
+ /* @__PURE__ */ jsx28(DialogOverlay, {}),
1641
+ /* @__PURE__ */ jsxs22(
1642
+ RadixDialog2.Content,
1346
1643
  {
1347
1644
  ref,
1645
+ "aria-describedby": void 0,
1348
1646
  className: cn(
1349
- "bg-panel fixed top-0 bottom-0 z-[51] flex flex-col shadow-lg outline-none",
1647
+ "bg-panel z-modal fixed top-0 bottom-0 flex flex-col shadow-lg outline-none",
1350
1648
  sideClasses[side]
1351
1649
  ),
1352
1650
  style: { width },
1353
1651
  children: [
1354
- title && /* @__PURE__ */ jsx(DrawerHeader, { title }),
1355
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto p-5", children })
1652
+ title ? /* @__PURE__ */ jsx28(DrawerHeader, { title }) : /* @__PURE__ */ jsx28(RadixDialog2.Title, { className: "sr-only", children: "Drawer" }),
1653
+ /* @__PURE__ */ jsx28("div", { className: "flex-1 overflow-auto p-5", children })
1356
1654
  ]
1357
1655
  }
1358
1656
  )
1359
1657
  ] }) });
1360
1658
  });
1361
1659
  Drawer.displayName = "Drawer";
1362
- var Sheet = forwardRef(function Sheet2({ title, width = "min(640px, 90vw)", children, ...rootProps }, ref) {
1363
- return /* @__PURE__ */ jsx(DialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs(DialogPortal, { children: [
1364
- /* @__PURE__ */ jsx(DialogOverlay, {}),
1365
- /* @__PURE__ */ jsxs(
1366
- RadixDialog.Content,
1660
+
1661
+ // src/components/Dialog/Sheet.tsx
1662
+ import * as RadixDialog3 from "@radix-ui/react-dialog";
1663
+ import { forwardRef as forwardRef28 } from "react";
1664
+ import { jsx as jsx29, jsxs as jsxs23 } from "react/jsx-runtime";
1665
+ var Sheet = forwardRef28(function Sheet2({ title, width = "min(640px, 90vw)", children, ...rootProps }, ref) {
1666
+ return /* @__PURE__ */ jsx29(DialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs23(DialogPortal, { children: [
1667
+ /* @__PURE__ */ jsx29(DialogOverlay, {}),
1668
+ /* @__PURE__ */ jsxs23(
1669
+ RadixDialog3.Content,
1367
1670
  {
1368
1671
  ref,
1672
+ "aria-describedby": void 0,
1369
1673
  className: cn(
1370
- "fixed bottom-0 left-1/2 z-[51] -translate-x-1/2 p-5",
1674
+ "z-modal fixed bottom-0 left-1/2 -translate-x-1/2 p-5",
1371
1675
  "bg-panel border-border-strong rounded-tl-lg rounded-tr-lg border-t shadow-lg outline-none",
1372
1676
  "data-[state=open]:animate-[ship-slide-in-bottom_220ms_var(--easing-out)]"
1373
1677
  ),
1374
1678
  style: { width },
1375
1679
  children: [
1376
- /* @__PURE__ */ jsx("div", { className: "bg-border mx-auto mb-[14px] h-1 w-9 rounded-full", "aria-hidden": true }),
1377
- title && /* @__PURE__ */ jsx(RadixDialog.Title, { className: "mb-1 text-[15px] font-medium", children: title }),
1680
+ title ? /* @__PURE__ */ jsx29(RadixDialog3.Title, { className: "mb-1 text-[15px] font-medium", children: title }) : /* @__PURE__ */ jsx29(RadixDialog3.Title, { className: "sr-only", children: "Sheet" }),
1378
1681
  children
1379
1682
  ]
1380
1683
  }
@@ -1382,64 +1685,74 @@ var Sheet = forwardRef(function Sheet2({ title, width = "min(640px, 90vw)", chil
1382
1685
  ] }) });
1383
1686
  });
1384
1687
  Sheet.displayName = "Sheet";
1688
+
1689
+ // src/components/Dialog/AlertDialog.tsx
1690
+ import * as RadixAlert from "@radix-ui/react-alert-dialog";
1691
+ import { forwardRef as forwardRef29 } from "react";
1692
+ import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
1385
1693
  var AlertDialogRoot = RadixAlert.Root;
1386
1694
  var AlertDialogTrigger = RadixAlert.Trigger;
1387
1695
  var AlertDialogAction = RadixAlert.Action;
1388
1696
  var AlertDialogCancel = RadixAlert.Cancel;
1389
- var AlertDialog = forwardRef(function AlertDialog2({ title, description, footer, width = 460, children, ...rootProps }, ref) {
1390
- return /* @__PURE__ */ jsx(AlertDialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs(RadixAlert.Portal, { children: [
1391
- /* @__PURE__ */ jsx(
1697
+ var AlertDialog = forwardRef29(function AlertDialog2({ title, description, footer, width = 460, children, ...rootProps }, ref) {
1698
+ return /* @__PURE__ */ jsx30(AlertDialogRoot, { ...rootProps, children: /* @__PURE__ */ jsxs24(RadixAlert.Portal, { children: [
1699
+ /* @__PURE__ */ jsx30(
1392
1700
  RadixAlert.Overlay,
1393
1701
  {
1394
1702
  className: cn(
1395
- "fixed inset-0 z-50 bg-black/55 backdrop-blur-[4px]",
1703
+ "z-overlay fixed inset-0 bg-black/55 backdrop-blur-[4px]",
1396
1704
  "data-[state=open]:animate-[ship-fade-in_150ms_ease]"
1397
1705
  )
1398
1706
  }
1399
1707
  ),
1400
- /* @__PURE__ */ jsxs(
1708
+ /* @__PURE__ */ jsxs24(
1401
1709
  RadixAlert.Content,
1402
1710
  {
1403
1711
  ref,
1404
1712
  style: { maxWidth: width },
1405
1713
  className: cn(
1406
- "fixed top-1/2 left-1/2 z-[51] w-[calc(100%-40px)] -translate-x-1/2 -translate-y-1/2 p-6",
1714
+ "z-modal fixed top-1/2 left-1/2 w-[calc(100%-40px)] -translate-x-1/2 -translate-y-1/2 p-6",
1407
1715
  "bg-panel border-border-strong rounded-lg border shadow-lg outline-none",
1408
1716
  "data-[state=open]:animate-[ship-dialog-in_180ms_var(--easing-out)]"
1409
1717
  ),
1410
1718
  children: [
1411
- /* @__PURE__ */ jsx(
1719
+ /* @__PURE__ */ jsx30(
1412
1720
  RadixAlert.Title,
1413
1721
  {
1414
1722
  className: cn("text-[16px] font-medium", description ? "mb-[6px]" : "mb-4"),
1415
1723
  children: title
1416
1724
  }
1417
1725
  ),
1418
- description && /* @__PURE__ */ jsx(RadixAlert.Description, { className: "text-text-muted mb-[18px] text-[13px] leading-[1.55]", children: description }),
1726
+ description && /* @__PURE__ */ jsx30(RadixAlert.Description, { className: "text-text-muted mb-[18px] text-[13px] leading-[1.55]", children: description }),
1419
1727
  children,
1420
- footer && /* @__PURE__ */ jsx("div", { className: "mt-5 flex justify-end gap-2", children: footer })
1728
+ footer && /* @__PURE__ */ jsx30("div", { className: "mt-5 flex justify-end gap-2", children: footer })
1421
1729
  ]
1422
1730
  }
1423
1731
  )
1424
1732
  ] }) });
1425
1733
  });
1426
1734
  AlertDialog.displayName = "AlertDialog";
1735
+
1736
+ // src/components/DropdownMenu/DropdownMenu.tsx
1737
+ import * as RadixMenu from "@radix-ui/react-dropdown-menu";
1738
+ import { forwardRef as forwardRef30 } from "react";
1739
+ import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
1427
1740
  var DropdownMenuRoot = RadixMenu.Root;
1428
1741
  var DropdownMenuTrigger = RadixMenu.Trigger;
1429
1742
  var DropdownMenuPortal = RadixMenu.Portal;
1430
1743
  var DropdownMenuGroup = RadixMenu.Group;
1431
1744
  var DropdownMenuLabel = RadixMenu.Label;
1432
1745
  var DropdownMenuRadioGroup = RadixMenu.RadioGroup;
1433
- var DropdownMenuContent = forwardRef(
1746
+ var DropdownMenuContent = forwardRef30(
1434
1747
  function DropdownMenuContent2({ className, sideOffset = 6, align = "start", ...props }, ref) {
1435
- return /* @__PURE__ */ jsx(RadixMenu.Portal, { children: /* @__PURE__ */ jsx(
1748
+ return /* @__PURE__ */ jsx31(RadixMenu.Portal, { children: /* @__PURE__ */ jsx31(
1436
1749
  RadixMenu.Content,
1437
1750
  {
1438
1751
  ref,
1439
1752
  sideOffset,
1440
1753
  align,
1441
1754
  className: cn(
1442
- "bg-panel border-border-strong z-40 min-w-[180px] rounded-md border p-1 shadow-lg outline-none",
1755
+ "bg-panel border-border-strong z-popover min-w-[180px] rounded-md border p-1 shadow-lg outline-none",
1443
1756
  "data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
1444
1757
  className
1445
1758
  ),
@@ -1454,32 +1767,32 @@ var itemBase2 = cn(
1454
1767
  "data-[highlighted]:bg-panel-2",
1455
1768
  "data-[disabled]:opacity-40 data-[disabled]:cursor-not-allowed"
1456
1769
  );
1457
- var MenuItem = forwardRef(function MenuItem2({ icon, trailing, destructive, className, children, ...props }, ref) {
1458
- return /* @__PURE__ */ jsxs(
1770
+ var MenuItem = forwardRef30(function MenuItem2({ icon, trailing, destructive, className, children, ...props }, ref) {
1771
+ return /* @__PURE__ */ jsxs25(
1459
1772
  RadixMenu.Item,
1460
1773
  {
1461
1774
  ref,
1462
1775
  className: cn(itemBase2, destructive ? "text-err" : "text-text", className),
1463
1776
  ...props,
1464
1777
  children: [
1465
- icon && /* @__PURE__ */ jsx("span", { className: "w-[14px] text-[12px] opacity-70", children: icon }),
1466
- /* @__PURE__ */ jsx("span", { className: "flex-1", children }),
1467
- trailing && /* @__PURE__ */ jsx("span", { className: "text-text-dim font-mono text-[10px]", children: trailing })
1778
+ icon && /* @__PURE__ */ jsx31("span", { className: "w-[14px] text-[12px] opacity-70", children: icon }),
1779
+ /* @__PURE__ */ jsx31("span", { className: "flex-1", children }),
1780
+ trailing && /* @__PURE__ */ jsx31("span", { className: "text-text-dim font-mono text-[10px]", children: trailing })
1468
1781
  ]
1469
1782
  }
1470
1783
  );
1471
1784
  });
1472
1785
  MenuItem.displayName = "MenuItem";
1473
- var MenuCheckboxItem = forwardRef(
1786
+ var MenuCheckboxItem = forwardRef30(
1474
1787
  function MenuCheckboxItem2({ className, children, ...props }, ref) {
1475
- return /* @__PURE__ */ jsxs(
1788
+ return /* @__PURE__ */ jsxs25(
1476
1789
  RadixMenu.CheckboxItem,
1477
1790
  {
1478
1791
  ref,
1479
1792
  className: cn(itemBase2, "text-text relative pl-[26px]", className),
1480
1793
  ...props,
1481
1794
  children: [
1482
- /* @__PURE__ */ jsx(RadixMenu.ItemIndicator, { className: "text-accent absolute top-1/2 left-2 -translate-y-1/2 text-[10px]", children: "\u2713" }),
1795
+ /* @__PURE__ */ jsx31(RadixMenu.ItemIndicator, { className: "text-accent absolute top-1/2 left-2 -translate-y-1/2 text-[10px]", children: "\u2713" }),
1483
1796
  children
1484
1797
  ]
1485
1798
  }
@@ -1487,9 +1800,9 @@ var MenuCheckboxItem = forwardRef(
1487
1800
  }
1488
1801
  );
1489
1802
  MenuCheckboxItem.displayName = "MenuCheckboxItem";
1490
- var MenuSeparator = forwardRef(
1803
+ var MenuSeparator = forwardRef30(
1491
1804
  function MenuSeparator2({ className, ...props }, ref) {
1492
- return /* @__PURE__ */ jsx(
1805
+ return /* @__PURE__ */ jsx31(
1493
1806
  RadixMenu.Separator,
1494
1807
  {
1495
1808
  ref,
@@ -1501,18 +1814,23 @@ var MenuSeparator = forwardRef(
1501
1814
  );
1502
1815
  MenuSeparator.displayName = "MenuSeparator";
1503
1816
  var DropdownMenu = RadixMenu.Root;
1817
+
1818
+ // src/components/HoverCard/HoverCard.tsx
1819
+ import * as RadixHoverCard from "@radix-ui/react-hover-card";
1820
+ import { forwardRef as forwardRef31 } from "react";
1821
+ import { jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
1504
1822
  var HoverCardRoot = RadixHoverCard.Root;
1505
1823
  var HoverCardTrigger = RadixHoverCard.Trigger;
1506
1824
  var HoverCardPortal = RadixHoverCard.Portal;
1507
- var HoverCardContent = forwardRef(
1825
+ var HoverCardContent = forwardRef31(
1508
1826
  function HoverCardContent2({ className, sideOffset = 4, ...props }, ref) {
1509
- return /* @__PURE__ */ jsx(RadixHoverCard.Portal, { children: /* @__PURE__ */ jsx(
1827
+ return /* @__PURE__ */ jsx32(RadixHoverCard.Portal, { children: /* @__PURE__ */ jsx32(
1510
1828
  RadixHoverCard.Content,
1511
1829
  {
1512
1830
  ref,
1513
1831
  sideOffset,
1514
1832
  className: cn(
1515
- "rounded-base bg-panel border-border-strong z-40 border p-[14px] shadow-lg outline-none",
1833
+ "rounded-base bg-panel border-border-strong z-popover border p-[14px] shadow-lg outline-none",
1516
1834
  "data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
1517
1835
  className
1518
1836
  ),
@@ -1523,27 +1841,32 @@ var HoverCardContent = forwardRef(
1523
1841
  );
1524
1842
  HoverCardContent.displayName = "HoverCardContent";
1525
1843
  function HoverCard({ trigger, content, ...rootProps }) {
1526
- return /* @__PURE__ */ jsxs(RadixHoverCard.Root, { openDelay: 200, closeDelay: 120, ...rootProps, children: [
1527
- /* @__PURE__ */ jsx(RadixHoverCard.Trigger, { asChild: true, children: trigger }),
1528
- /* @__PURE__ */ jsx(HoverCardContent, { children: content })
1844
+ return /* @__PURE__ */ jsxs26(RadixHoverCard.Root, { openDelay: 200, closeDelay: 120, ...rootProps, children: [
1845
+ /* @__PURE__ */ jsx32(RadixHoverCard.Trigger, { asChild: true, children: trigger }),
1846
+ /* @__PURE__ */ jsx32(HoverCardContent, { children: content })
1529
1847
  ] });
1530
1848
  }
1849
+
1850
+ // src/components/Popover/Popover.tsx
1851
+ import * as RadixPopover from "@radix-ui/react-popover";
1852
+ import { forwardRef as forwardRef32 } from "react";
1853
+ import { jsx as jsx33 } from "react/jsx-runtime";
1531
1854
  var PopoverRoot = RadixPopover.Root;
1532
1855
  var PopoverTrigger = RadixPopover.Trigger;
1533
1856
  var PopoverAnchor = RadixPopover.Anchor;
1534
1857
  var PopoverPortal = RadixPopover.Portal;
1535
1858
  var PopoverClose = RadixPopover.Close;
1536
1859
  var PopoverArrow = RadixPopover.Arrow;
1537
- var PopoverContent = forwardRef(
1860
+ var PopoverContent = forwardRef32(
1538
1861
  function PopoverContent2({ className, align = "start", sideOffset = 6, ...props }, ref) {
1539
- return /* @__PURE__ */ jsx(RadixPopover.Portal, { children: /* @__PURE__ */ jsx(
1862
+ return /* @__PURE__ */ jsx33(RadixPopover.Portal, { children: /* @__PURE__ */ jsx33(
1540
1863
  RadixPopover.Content,
1541
1864
  {
1542
1865
  ref,
1543
1866
  align,
1544
1867
  sideOffset,
1545
1868
  className: cn(
1546
- "bg-panel border-border-strong z-40 rounded-md border p-[6px] shadow-lg outline-none",
1869
+ "bg-panel border-border-strong z-popover rounded-md border p-[6px] shadow-lg outline-none",
1547
1870
  "data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
1548
1871
  className
1549
1872
  ),
@@ -1554,6 +1877,18 @@ var PopoverContent = forwardRef(
1554
1877
  );
1555
1878
  PopoverContent.displayName = "PopoverContent";
1556
1879
  var Popover = RadixPopover.Root;
1880
+
1881
+ // src/components/Toast/Toast.tsx
1882
+ import * as RadixToast from "@radix-ui/react-toast";
1883
+ import {
1884
+ createContext,
1885
+ forwardRef as forwardRef33,
1886
+ useCallback as useCallback6,
1887
+ useContext,
1888
+ useMemo,
1889
+ useState as useState7
1890
+ } from "react";
1891
+ import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
1557
1892
  var ToastContext = createContext(null);
1558
1893
  var variantIcon = {
1559
1894
  default: "\u25CF",
@@ -1576,21 +1911,30 @@ var variantBorderLeft = {
1576
1911
  warn: "border-l-warn",
1577
1912
  err: "border-l-err"
1578
1913
  };
1914
+ var toastIdCounter = 0;
1915
+ var nextToastId = () => `toast-${++toastIdCounter}`;
1579
1916
  function ToastProvider({ children }) {
1580
- const [toasts, setToasts] = useState([]);
1581
- const toast = useCallback((t) => {
1582
- const id = t.id ?? Math.random().toString(36).slice(2);
1583
- setToasts((prev) => [...prev, { ...t, id }]);
1917
+ const [toasts, setToasts] = useState7([]);
1918
+ const toast = useCallback6((t) => {
1919
+ const explicitId = t.id;
1920
+ const id = explicitId ?? nextToastId();
1921
+ const entry = { ...t, id };
1922
+ setToasts((prev) => {
1923
+ if (explicitId !== void 0 && prev.some((existing) => existing.id === explicitId)) {
1924
+ return prev.map((existing) => existing.id === explicitId ? entry : existing);
1925
+ }
1926
+ return [...prev, entry];
1927
+ });
1584
1928
  return id;
1585
1929
  }, []);
1586
- const dismiss = useCallback((id) => {
1930
+ const dismiss = useCallback6((id) => {
1587
1931
  setToasts((prev) => prev.filter((t) => t.id !== id));
1588
1932
  }, []);
1589
1933
  const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);
1590
- return /* @__PURE__ */ jsx(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs(RadixToast.Provider, { swipeDirection: "right", children: [
1934
+ return /* @__PURE__ */ jsx34(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs27(RadixToast.Provider, { swipeDirection: "right", children: [
1591
1935
  children,
1592
- toasts.map((t) => /* @__PURE__ */ jsx(ToastCard, { toast: t, onDismiss: () => dismiss(t.id) }, t.id)),
1593
- /* @__PURE__ */ jsx(RadixToast.Viewport, { className: "fixed right-5 bottom-5 z-[70] flex w-[380px] max-w-[calc(100vw-40px)] flex-col gap-2 outline-none" })
1936
+ toasts.map((t) => /* @__PURE__ */ jsx34(ToastCard, { toast: t, onDismiss: () => dismiss(t.id) }, t.id)),
1937
+ /* @__PURE__ */ jsx34(RadixToast.Viewport, { className: "z-toast fixed right-5 bottom-5 flex w-[380px] max-w-[calc(100vw-40px)] flex-col gap-2 outline-none" })
1594
1938
  ] }) });
1595
1939
  }
1596
1940
  function useToast() {
@@ -1598,9 +1942,9 @@ function useToast() {
1598
1942
  if (!ctx) throw new Error("useToast must be inside <ToastProvider>");
1599
1943
  return ctx;
1600
1944
  }
1601
- var ToastCard = forwardRef(function ToastCard2({ toast, onDismiss }, ref) {
1945
+ var ToastCard = forwardRef33(function ToastCard2({ toast, onDismiss }, ref) {
1602
1946
  const variant = toast.variant ?? "default";
1603
- return /* @__PURE__ */ jsxs(
1947
+ return /* @__PURE__ */ jsxs27(
1604
1948
  RadixToast.Root,
1605
1949
  {
1606
1950
  ref,
@@ -1615,13 +1959,13 @@ var ToastCard = forwardRef(function ToastCard2({ toast, onDismiss }, ref) {
1615
1959
  variantBorderLeft[variant]
1616
1960
  ),
1617
1961
  children: [
1618
- /* @__PURE__ */ jsx("span", { className: cn("mt-px text-[14px] leading-none", variantTextColor[variant]), children: variantIcon[variant] }),
1619
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1620
- /* @__PURE__ */ jsx(RadixToast.Title, { className: "text-text text-[13px] font-medium", children: toast.title }),
1621
- toast.description && /* @__PURE__ */ jsx(RadixToast.Description, { className: "text-text-muted mt-[2px] text-[12px] leading-[1.5]", children: toast.description }),
1622
- toast.action && /* @__PURE__ */ jsx("div", { className: "mt-2", children: toast.action })
1962
+ /* @__PURE__ */ jsx34("span", { className: cn("mt-px text-[14px] leading-none", variantTextColor[variant]), children: variantIcon[variant] }),
1963
+ /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
1964
+ /* @__PURE__ */ jsx34(RadixToast.Title, { className: "text-text text-[13px] font-medium", children: toast.title }),
1965
+ toast.description && /* @__PURE__ */ jsx34(RadixToast.Description, { className: "text-text-muted mt-[2px] text-[12px] leading-[1.5]", children: toast.description }),
1966
+ toast.action && /* @__PURE__ */ jsx34("div", { className: "mt-2", children: toast.action })
1623
1967
  ] }),
1624
- /* @__PURE__ */ jsx(
1968
+ /* @__PURE__ */ jsx34(
1625
1969
  RadixToast.Close,
1626
1970
  {
1627
1971
  "aria-label": "Dismiss",
@@ -1634,20 +1978,25 @@ var ToastCard = forwardRef(function ToastCard2({ toast, onDismiss }, ref) {
1634
1978
  );
1635
1979
  });
1636
1980
  ToastCard.displayName = "ToastCard";
1981
+
1982
+ // src/components/Tooltip/Tooltip.tsx
1983
+ import * as RadixTooltip from "@radix-ui/react-tooltip";
1984
+ import { forwardRef as forwardRef34 } from "react";
1985
+ import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
1637
1986
  var TooltipProvider = RadixTooltip.Provider;
1638
1987
  var TooltipRoot = RadixTooltip.Root;
1639
1988
  var TooltipTrigger = RadixTooltip.Trigger;
1640
1989
  var TooltipPortal = RadixTooltip.Portal;
1641
1990
  var TooltipArrow = RadixTooltip.Arrow;
1642
- var TooltipContent = forwardRef(
1991
+ var TooltipContent = forwardRef34(
1643
1992
  function TooltipContent2({ className, sideOffset = 6, ...props }, ref) {
1644
- return /* @__PURE__ */ jsx(RadixTooltip.Portal, { children: /* @__PURE__ */ jsx(
1993
+ return /* @__PURE__ */ jsx35(RadixTooltip.Portal, { children: /* @__PURE__ */ jsx35(
1645
1994
  RadixTooltip.Content,
1646
1995
  {
1647
1996
  ref,
1648
1997
  sideOffset,
1649
1998
  className: cn(
1650
- "pointer-events-none z-[60] rounded-sm px-2 py-[5px] text-[11px] whitespace-nowrap",
1999
+ "z-tooltip pointer-events-none rounded-sm px-2 py-[5px] text-[11px] whitespace-nowrap",
1651
2000
  "bg-text text-bg",
1652
2001
  "data-[state=delayed-open]:animate-[ship-pop-in_120ms_var(--easing-out)]",
1653
2002
  className
@@ -1659,124 +2008,152 @@ var TooltipContent = forwardRef(
1659
2008
  );
1660
2009
  TooltipContent.displayName = "TooltipContent";
1661
2010
  function Tooltip({ content, children, side = "top", delayDuration = 400 }) {
1662
- return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration, children: /* @__PURE__ */ jsxs(TooltipRoot, { children: [
1663
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children }),
1664
- /* @__PURE__ */ jsx(TooltipContent, { side, children: content })
2011
+ return /* @__PURE__ */ jsx35(TooltipProvider, { delayDuration, children: /* @__PURE__ */ jsxs28(TooltipRoot, { children: [
2012
+ /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children }),
2013
+ /* @__PURE__ */ jsx35(TooltipContent, { side, children: content })
1665
2014
  ] }) });
1666
2015
  }
1667
- var alertStyles = cva("flex items-start gap-3 rounded-base border bg-panel p-3 text-[13px]", {
2016
+
2017
+ // src/patterns/Alert/Alert.tsx
2018
+ import { cva as cva8 } from "class-variance-authority";
2019
+ import { forwardRef as forwardRef35 } from "react";
2020
+ import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
2021
+ var alertStyles = cva8("flex items-start gap-3 rounded-base border bg-panel p-3 text-[13px]", {
1668
2022
  variants: {
1669
- variant: {
1670
- info: "border-border border-l-2 border-l-accent",
2023
+ tone: {
2024
+ accent: "border-border border-l-2 border-l-accent",
1671
2025
  ok: "border-border border-l-2 border-l-ok",
1672
2026
  warn: "border-border border-l-2 border-l-warn",
1673
2027
  err: "border-border border-l-2 border-l-err"
1674
2028
  }
1675
2029
  },
1676
- defaultVariants: { variant: "info" }
2030
+ defaultVariants: { tone: "accent" }
1677
2031
  });
1678
2032
  var iconColorClass = {
1679
- info: "text-accent",
2033
+ accent: "text-accent",
1680
2034
  ok: "text-ok",
1681
2035
  warn: "text-warn",
1682
2036
  err: "text-err"
1683
2037
  };
1684
2038
  var defaultGlyph = {
1685
- info: "\u2139",
2039
+ accent: "\u2139",
1686
2040
  ok: "\u2713",
1687
2041
  warn: "!",
1688
2042
  err: "\xD7"
1689
2043
  };
1690
- var Alert = forwardRef(function Alert2({ variant = "info", title, description, icon, action, className, children, ...props }, ref) {
1691
- return /* @__PURE__ */ jsxs(
2044
+ var Alert = forwardRef35(function Alert2({
2045
+ tone = "accent",
2046
+ title,
2047
+ description,
2048
+ icon,
2049
+ action,
2050
+ live = "polite",
2051
+ className,
2052
+ children,
2053
+ ...props
2054
+ }, ref) {
2055
+ const t = tone ?? "accent";
2056
+ return /* @__PURE__ */ jsxs29(
1692
2057
  "div",
1693
2058
  {
1694
2059
  ref,
1695
- role: variant === "err" || variant === "warn" ? "alert" : "status",
1696
- className: cn(alertStyles({ variant }), className),
2060
+ role: live === "assertive" ? "alert" : "status",
2061
+ "aria-live": live === "off" ? void 0 : live,
2062
+ className: cn(alertStyles({ tone }), className),
1697
2063
  ...props,
1698
2064
  children: [
1699
- /* @__PURE__ */ jsx(
1700
- "span",
1701
- {
1702
- "aria-hidden": true,
1703
- className: cn("mt-[1px] text-[14px] leading-none", iconColorClass[variant]),
1704
- children: icon ?? defaultGlyph[variant]
1705
- }
1706
- ),
1707
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1708
- title && /* @__PURE__ */ jsx("div", { className: "font-medium", children: title }),
1709
- description && /* @__PURE__ */ jsx("div", { className: "text-text-muted mt-[2px] text-[12px]", children: description }),
2065
+ /* @__PURE__ */ jsx36("span", { "aria-hidden": true, className: cn("mt-[1px] text-[14px] leading-none", iconColorClass[t]), children: icon ?? defaultGlyph[t] }),
2066
+ /* @__PURE__ */ jsxs29("div", { className: "min-w-0 flex-1", children: [
2067
+ title && /* @__PURE__ */ jsx36("div", { className: "font-medium", children: title }),
2068
+ description && /* @__PURE__ */ jsx36("div", { className: "text-text-muted mt-[2px] text-[12px]", children: description }),
1710
2069
  children
1711
2070
  ] }),
1712
- action && /* @__PURE__ */ jsx("div", { className: "ml-1 shrink-0", children: action })
2071
+ action && /* @__PURE__ */ jsx36("div", { className: "ml-1 shrink-0", children: action })
1713
2072
  ]
1714
2073
  }
1715
2074
  );
1716
2075
  });
1717
2076
  Alert.displayName = "Alert";
1718
- var bannerStyles = cva(
1719
- "flex items-center gap-[10px] border-b border-border px-[14px] py-2 text-[12px]",
2077
+
2078
+ // src/patterns/Banner/Banner.tsx
2079
+ import { cva as cva9 } from "class-variance-authority";
2080
+ import { forwardRef as forwardRef36 } from "react";
2081
+ import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
2082
+ var bannerStyles = cva9(
2083
+ "flex items-center gap-3 border-b border-border px-[14px] py-2 text-[12px]",
1720
2084
  {
1721
2085
  variants: {
1722
- variant: {
1723
- info: "bg-[color-mix(in_oklab,var(--color-accent),transparent_82%)] text-accent",
2086
+ tone: {
2087
+ accent: "bg-[color-mix(in_oklab,var(--color-accent),transparent_82%)] text-accent",
1724
2088
  ok: "bg-[color-mix(in_oklab,var(--color-ok),transparent_82%)] text-ok",
1725
2089
  warn: "bg-[color-mix(in_oklab,var(--color-warn),transparent_82%)] text-warn",
1726
2090
  err: "bg-[color-mix(in_oklab,var(--color-err),transparent_82%)] text-err"
1727
2091
  },
1728
2092
  sticky: {
1729
- true: "sticky top-0 z-30",
2093
+ true: "sticky top-0 z-sticky",
1730
2094
  false: ""
1731
2095
  }
1732
2096
  },
1733
- defaultVariants: { variant: "info", sticky: false }
2097
+ defaultVariants: { tone: "accent", sticky: false }
1734
2098
  }
1735
2099
  );
1736
2100
  var defaultGlyph2 = {
1737
- info: "\u2726",
2101
+ accent: "\u2726",
1738
2102
  ok: "\u2713",
1739
2103
  warn: "!",
1740
2104
  err: "\xD7"
1741
2105
  };
1742
- var Banner = forwardRef(function Banner2({ variant = "info", sticky, icon, action, className, children, ...props }, ref) {
1743
- return /* @__PURE__ */ jsxs(
2106
+ var Banner = forwardRef36(function Banner2({ tone = "accent", sticky, icon, action, live = "polite", className, children, ...props }, ref) {
2107
+ const t = tone ?? "accent";
2108
+ return /* @__PURE__ */ jsxs30(
1744
2109
  "div",
1745
2110
  {
1746
2111
  ref,
1747
- role: variant === "err" || variant === "warn" ? "alert" : "status",
1748
- className: cn(bannerStyles({ variant, sticky }), className),
2112
+ role: live === "assertive" ? "alert" : "status",
2113
+ "aria-live": live === "off" ? void 0 : live,
2114
+ className: cn(bannerStyles({ tone, sticky }), className),
1749
2115
  ...props,
1750
2116
  children: [
1751
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "leading-none", children: icon ?? defaultGlyph2[variant] }),
1752
- /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children }),
1753
- action && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: action })
2117
+ /* @__PURE__ */ jsx37("span", { "aria-hidden": true, className: "leading-none", children: icon ?? defaultGlyph2[t] }),
2118
+ /* @__PURE__ */ jsx37("div", { className: "min-w-0 flex-1", children }),
2119
+ action && /* @__PURE__ */ jsx37("div", { className: "ml-auto", children: action })
1754
2120
  ]
1755
2121
  }
1756
2122
  );
1757
2123
  });
1758
2124
  Banner.displayName = "Banner";
1759
- var Breadcrumbs = forwardRef(function Breadcrumbs2({ separator = "/", className, children, ...props }, ref) {
1760
- const crumbs = Children.toArray(children).filter(isValidElement);
2125
+
2126
+ // src/patterns/Breadcrumbs/Breadcrumbs.tsx
2127
+ import {
2128
+ Children as Children2,
2129
+ forwardRef as forwardRef37,
2130
+ isValidElement as isValidElement2
2131
+ } from "react";
2132
+ import { jsx as jsx38, jsxs as jsxs31 } from "react/jsx-runtime";
2133
+ var Breadcrumbs = forwardRef37(function Breadcrumbs2({ separator = "/", className, children, ...props }, ref) {
2134
+ const crumbs = Children2.toArray(children).filter(isValidElement2);
1761
2135
  const last = crumbs.length - 1;
1762
- return /* @__PURE__ */ jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("text-[13px]", className), ...props, children: /* @__PURE__ */ jsx("ol", { className: "text-text-muted flex flex-wrap items-center gap-[6px]", children: crumbs.map((crumb, i) => {
2136
+ return /* @__PURE__ */ jsx38("nav", { ref, "aria-label": "Breadcrumb", className: cn("text-[13px]", className), ...props, children: /* @__PURE__ */ jsx38("ol", { className: "text-text-muted flex flex-wrap items-center gap-[6px]", children: crumbs.map((crumb, i) => {
1763
2137
  const isCurrent = i === last;
1764
- return /* @__PURE__ */ jsxs("li", { className: "inline-flex items-center gap-[6px]", children: [
1765
- isCurrent ? /* @__PURE__ */ jsx(Crumb, { ...crumb.props, current: true }) : crumb,
1766
- !isCurrent && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-text-dim", children: separator })
2138
+ return /* @__PURE__ */ jsxs31("li", { className: "inline-flex items-center gap-[6px]", children: [
2139
+ isCurrent ? /* @__PURE__ */ jsx38(Crumb, { ...crumb.props, current: true }) : crumb,
2140
+ !isCurrent && /* @__PURE__ */ jsx38("span", { "aria-hidden": true, className: "text-text-dim", children: separator })
1767
2141
  ] }, i);
1768
2142
  }) }) });
1769
2143
  });
1770
2144
  Breadcrumbs.displayName = "Breadcrumbs";
1771
- var Crumb = forwardRef(function Crumb2({ current, className, href, children, ...props }, ref) {
2145
+ var Crumb = forwardRef37(function Crumb2({ current, className, href, children, ...props }, ref) {
1772
2146
  if (current) {
1773
- return /* @__PURE__ */ jsx("span", { "aria-current": "page", className: cn("text-text", className), children });
2147
+ return /* @__PURE__ */ jsx38("span", { "aria-current": "page", className: cn("text-text", className), children });
1774
2148
  }
1775
- return /* @__PURE__ */ jsx(
2149
+ if (href === void 0) {
2150
+ return /* @__PURE__ */ jsx38("span", { className: cn("text-text-dim", className), children });
2151
+ }
2152
+ return /* @__PURE__ */ jsx38(
1776
2153
  "a",
1777
2154
  {
1778
2155
  ref,
1779
- href: href ?? "#",
2156
+ href,
1780
2157
  className: cn("hover:text-text transition-colors duration-(--duration-micro)", className),
1781
2158
  ...props,
1782
2159
  children
@@ -1784,6 +2161,17 @@ var Crumb = forwardRef(function Crumb2({ current, className, href, children, ...
1784
2161
  );
1785
2162
  });
1786
2163
  Crumb.displayName = "Crumb";
2164
+
2165
+ // src/patterns/Combobox/Combobox.tsx
2166
+ import {
2167
+ forwardRef as forwardRef38,
2168
+ useEffect as useEffect5,
2169
+ useId as useId6,
2170
+ useMemo as useMemo2,
2171
+ useRef as useRef4,
2172
+ useState as useState8
2173
+ } from "react";
2174
+ import { jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
1787
2175
  function normalize(option) {
1788
2176
  if (typeof option === "string") {
1789
2177
  return { value: option, label: option, searchText: option.toLowerCase() };
@@ -1799,7 +2187,7 @@ function normalize(option) {
1799
2187
  };
1800
2188
  }
1801
2189
  var defaultFilter = (option, query) => option.searchText.includes(query.toLowerCase());
1802
- var Combobox = forwardRef(function Combobox2({
2190
+ var Combobox = forwardRef38(function Combobox2({
1803
2191
  options,
1804
2192
  value: valueProp,
1805
2193
  defaultValue,
@@ -1816,16 +2204,16 @@ var Combobox = forwardRef(function Combobox2({
1816
2204
  id,
1817
2205
  "aria-label": ariaLabel
1818
2206
  }, ref) {
1819
- const reactId = useId();
2207
+ const reactId = useId6();
1820
2208
  const listboxId = `${id ?? reactId}-listbox`;
1821
2209
  const inputId = id ?? `${reactId}-input`;
1822
- const normalized = useMemo(() => options.map(normalize), [options]);
2210
+ const normalized = useMemo2(() => options.map(normalize), [options]);
1823
2211
  const [value, setValue] = useControllableState({
1824
2212
  value: valueProp,
1825
2213
  defaultValue,
1826
2214
  onChange: onValueChange
1827
2215
  });
1828
- const initialQuery = useMemo(() => {
2216
+ const initialQuery = useMemo2(() => {
1829
2217
  if (defaultQuery !== void 0) return defaultQuery;
1830
2218
  if (defaultValue !== void 0) {
1831
2219
  const opt = normalized.find((o) => o.value === defaultValue);
@@ -1838,10 +2226,10 @@ var Combobox = forwardRef(function Combobox2({
1838
2226
  defaultValue: initialQuery,
1839
2227
  onChange: onQueryChange
1840
2228
  });
1841
- const [open, setOpen] = useState(false);
1842
- const wrapperRef = useRef(null);
2229
+ const [open, setOpen] = useState8(false);
2230
+ const wrapperRef = useRef4(null);
1843
2231
  useOutsideClick(wrapperRef, () => setOpen(false));
1844
- const filtered = useMemo(
2232
+ const filtered = useMemo2(
1845
2233
  () => query ? normalized.filter((o) => filter(o, query)) : normalized,
1846
2234
  [normalized, query, filter]
1847
2235
  );
@@ -1853,7 +2241,7 @@ var Combobox = forwardRef(function Combobox2({
1853
2241
  if (item && !item.disabled) commit(item);
1854
2242
  }
1855
2243
  });
1856
- useEffect(() => {
2244
+ useEffect5(() => {
1857
2245
  setCursor(0);
1858
2246
  }, [query, setCursor]);
1859
2247
  function commit(option) {
@@ -1876,8 +2264,8 @@ var Combobox = forwardRef(function Combobox2({
1876
2264
  setOpen(false);
1877
2265
  }
1878
2266
  };
1879
- return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: "relative", style: { width }, children: [
1880
- /* @__PURE__ */ jsx(
2267
+ return /* @__PURE__ */ jsxs32("div", { ref: wrapperRef, className: "relative", style: { width }, children: [
2268
+ /* @__PURE__ */ jsx39(
1881
2269
  "input",
1882
2270
  {
1883
2271
  ref,
@@ -1911,19 +2299,19 @@ var Combobox = forwardRef(function Combobox2({
1911
2299
  )
1912
2300
  }
1913
2301
  ),
1914
- open && /* @__PURE__ */ jsx(
2302
+ open && /* @__PURE__ */ jsx39(
1915
2303
  "ul",
1916
2304
  {
1917
2305
  id: listboxId,
1918
2306
  role: "listbox",
1919
2307
  "aria-label": ariaLabel ?? "Suggestions",
1920
2308
  className: cn(
1921
- "absolute top-full right-0 left-0 z-30 mt-1 max-h-[220px] overflow-auto",
2309
+ "z-dropdown absolute top-full right-0 left-0 mt-1 max-h-[220px] overflow-auto",
1922
2310
  "border-border bg-panel rounded-md border p-1 shadow-lg"
1923
2311
  ),
1924
- children: filtered.length === 0 ? /* @__PURE__ */ jsx("li", { className: "text-text-dim px-2 py-3 text-center text-[12px]", role: "presentation", children: emptyState ?? "No matches" }) : filtered.map((option, i) => {
2312
+ children: filtered.length === 0 ? /* @__PURE__ */ jsx39("li", { className: "text-text-dim px-2 py-3 text-center text-[12px]", role: "presentation", children: emptyState ?? "No matches" }) : filtered.map((option, i) => {
1925
2313
  const isActive = i === cursor;
1926
- return /* @__PURE__ */ jsxs(
2314
+ return /* @__PURE__ */ jsxs32(
1927
2315
  "li",
1928
2316
  {
1929
2317
  id: `${listboxId}-option-${i}`,
@@ -1941,8 +2329,8 @@ var Combobox = forwardRef(function Combobox2({
1941
2329
  option.disabled && "pointer-events-none opacity-40"
1942
2330
  ),
1943
2331
  children: [
1944
- /* @__PURE__ */ jsx("div", { children: option.label }),
1945
- option.description && /* @__PURE__ */ jsx("div", { className: "text-text-dim text-[11px]", children: option.description })
2332
+ /* @__PURE__ */ jsx39("div", { children: option.label }),
2333
+ option.description && /* @__PURE__ */ jsx39("div", { className: "text-text-dim text-[11px]", children: option.description })
1946
2334
  ]
1947
2335
  },
1948
2336
  option.value
@@ -1950,14 +2338,19 @@ var Combobox = forwardRef(function Combobox2({
1950
2338
  })
1951
2339
  }
1952
2340
  ),
1953
- name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: value ?? "", readOnly: true })
2341
+ name && /* @__PURE__ */ jsx39("input", { type: "hidden", name, value: value ?? "", readOnly: true })
1954
2342
  ] });
1955
2343
  });
1956
2344
  Combobox.displayName = "Combobox";
2345
+
2346
+ // src/patterns/CommandPalette/CommandPalette.tsx
2347
+ import * as RadixDialog4 from "@radix-ui/react-dialog";
2348
+ import { forwardRef as forwardRef39, useEffect as useEffect6, useId as useId7, useMemo as useMemo3 } from "react";
2349
+ import { Fragment, jsx as jsx40, jsxs as jsxs33 } from "react/jsx-runtime";
1957
2350
  function flatItems(groups) {
1958
2351
  return groups.flatMap((g) => g.items);
1959
2352
  }
1960
- var CommandPalette = forwardRef(
2353
+ var CommandPalette = forwardRef39(
1961
2354
  function CommandPalette2({
1962
2355
  open,
1963
2356
  onOpenChange,
@@ -1970,7 +2363,7 @@ var CommandPalette = forwardRef(
1970
2363
  emptyState,
1971
2364
  width = 540
1972
2365
  }, ref) {
1973
- const flat = useMemo(() => flatItems(groups), [groups]);
2366
+ const flat = useMemo3(() => flatItems(groups), [groups]);
1974
2367
  const { cursor, setCursor, onKeyDown } = useKeyboardList({
1975
2368
  count: flat.length,
1976
2369
  defaultCursor: 0,
@@ -1979,37 +2372,41 @@ var CommandPalette = forwardRef(
1979
2372
  if (item) onSelect(item.id);
1980
2373
  }
1981
2374
  });
1982
- useEffect(() => {
2375
+ const reactId = useId7();
2376
+ const listboxId = `${reactId}-listbox`;
2377
+ const optionId = (i) => `${listboxId}-option-${i}`;
2378
+ const hasMatches = flat.length > 0;
2379
+ useEffect6(() => {
1983
2380
  setCursor(0);
1984
2381
  }, [query, groups, setCursor]);
1985
- return /* @__PURE__ */ jsx(RadixDialog.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs(RadixDialog.Portal, { children: [
1986
- /* @__PURE__ */ jsx(
1987
- RadixDialog.Overlay,
2382
+ return /* @__PURE__ */ jsx40(RadixDialog4.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs33(RadixDialog4.Portal, { children: [
2383
+ /* @__PURE__ */ jsx40(
2384
+ RadixDialog4.Overlay,
1988
2385
  {
1989
2386
  className: cn(
1990
- "fixed inset-0 z-50 bg-black/55 backdrop-blur-[4px]",
2387
+ "z-overlay fixed inset-0 bg-black/55 backdrop-blur-[4px]",
1991
2388
  "data-[state=open]:animate-[ship-fade-in_150ms_ease]"
1992
2389
  )
1993
2390
  }
1994
2391
  ),
1995
- /* @__PURE__ */ jsxs(
1996
- RadixDialog.Content,
2392
+ /* @__PURE__ */ jsxs33(
2393
+ RadixDialog4.Content,
1997
2394
  {
1998
2395
  ref,
1999
2396
  "aria-label": "Command palette",
2000
2397
  "aria-describedby": void 0,
2001
2398
  style: { width },
2002
2399
  className: cn(
2003
- "fixed top-[20%] left-1/2 z-[51] max-w-[calc(100%-40px)] -translate-x-1/2",
2400
+ "z-modal fixed top-[20%] left-1/2 max-w-[calc(100%-40px)] -translate-x-1/2",
2004
2401
  "border-border-strong bg-panel overflow-hidden rounded-xl border shadow-lg",
2005
2402
  "outline-none data-[state=open]:animate-[ship-dialog-in_180ms_var(--easing-out)]"
2006
2403
  ),
2007
2404
  onKeyDown,
2008
2405
  children: [
2009
- /* @__PURE__ */ jsx(RadixDialog.Title, { className: "sr-only", children: "Command palette" }),
2010
- /* @__PURE__ */ jsxs("div", { className: "border-border flex items-center gap-[10px] border-b px-4 py-[14px]", children: [
2011
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-text-dim", children: "\u2315" }),
2012
- /* @__PURE__ */ jsx(
2406
+ /* @__PURE__ */ jsx40(RadixDialog4.Title, { className: "sr-only", children: "Command palette" }),
2407
+ /* @__PURE__ */ jsxs33("div", { className: "border-border flex items-center gap-[10px] border-b px-4 py-[14px]", children: [
2408
+ /* @__PURE__ */ jsx40("span", { "aria-hidden": true, className: "text-text-dim", children: "\u2315" }),
2409
+ /* @__PURE__ */ jsx40(
2013
2410
  "input",
2014
2411
  {
2015
2412
  autoFocus: true,
@@ -2018,22 +2415,27 @@ var CommandPalette = forwardRef(
2018
2415
  onChange: (e) => onQueryChange(e.target.value),
2019
2416
  placeholder,
2020
2417
  "aria-label": "Search",
2418
+ role: "combobox",
2021
2419
  "aria-autocomplete": "list",
2420
+ "aria-expanded": true,
2421
+ "aria-controls": listboxId,
2422
+ "aria-activedescendant": hasMatches ? optionId(cursor) : void 0,
2022
2423
  className: "text-text placeholder:text-text-dim flex-1 border-0 bg-transparent text-[14px] outline-none"
2023
2424
  }
2024
2425
  ),
2025
- /* @__PURE__ */ jsx("span", { className: "border-border text-text-dim rounded-xs border px-[6px] py-[2px] font-mono text-[10px]", children: "ESC" })
2426
+ /* @__PURE__ */ jsx40("span", { className: "border-border text-text-dim rounded-xs border px-[6px] py-[2px] font-mono text-[10px]", children: "ESC" })
2026
2427
  ] }),
2027
- /* @__PURE__ */ jsx("div", { className: "min-h-[220px] p-2", role: "listbox", "aria-label": "Results", children: flat.length === 0 ? emptyState ?? /* @__PURE__ */ jsx("div", { className: "text-text-dim px-3 py-5 text-center text-[12px]", children: "No matches" }) : /* @__PURE__ */ jsx(
2428
+ /* @__PURE__ */ jsx40("div", { id: listboxId, className: "min-h-[220px] p-2", role: "listbox", "aria-label": "Results", children: flat.length === 0 ? emptyState ?? /* @__PURE__ */ jsx40("div", { className: "text-text-dim px-3 py-5 text-center text-[12px]", children: "No matches" }) : /* @__PURE__ */ jsx40(
2028
2429
  CommandGroups,
2029
2430
  {
2030
2431
  groups,
2031
2432
  cursor,
2032
2433
  setCursor,
2033
- onSelect
2434
+ onSelect,
2435
+ optionId
2034
2436
  }
2035
2437
  ) }),
2036
- footer && /* @__PURE__ */ jsx("div", { className: "border-border text-text-dim flex gap-4 border-t px-[14px] py-[10px] font-mono text-[10px]", children: footer })
2438
+ footer && /* @__PURE__ */ jsx40("div", { className: "border-border text-text-dim flex gap-4 border-t px-[14px] py-[10px] font-mono text-[10px]", children: footer })
2037
2439
  ]
2038
2440
  }
2039
2441
  )
@@ -2041,12 +2443,12 @@ var CommandPalette = forwardRef(
2041
2443
  }
2042
2444
  );
2043
2445
  CommandPalette.displayName = "CommandPalette";
2044
- function CommandGroups({ groups, cursor, setCursor, onSelect }) {
2446
+ function CommandGroups({ groups, cursor, setCursor, onSelect, optionId }) {
2045
2447
  let runningIndex = 0;
2046
- return /* @__PURE__ */ jsx(Fragment, { children: groups.map((group, gIdx) => {
2448
+ return /* @__PURE__ */ jsx40(Fragment, { children: groups.map((group, gIdx) => {
2047
2449
  if (group.items.length === 0) return null;
2048
- return /* @__PURE__ */ jsxs("div", { children: [
2049
- group.label && /* @__PURE__ */ jsxs("div", { className: "text-text-dim px-2 pt-2 pb-1 font-mono text-[9px] tracking-[1.4px] uppercase", children: [
2450
+ return /* @__PURE__ */ jsxs33("div", { children: [
2451
+ group.label && /* @__PURE__ */ jsxs33("div", { className: "text-text-dim px-2 pt-2 pb-1 font-mono text-[9px] tracking-[1.4px] uppercase", children: [
2050
2452
  group.label,
2051
2453
  " \xB7 ",
2052
2454
  group.items.length
@@ -2054,9 +2456,10 @@ function CommandGroups({ groups, cursor, setCursor, onSelect }) {
2054
2456
  group.items.map((item) => {
2055
2457
  const myIndex = runningIndex++;
2056
2458
  const isActive = cursor === myIndex;
2057
- return /* @__PURE__ */ jsxs(
2459
+ return /* @__PURE__ */ jsxs33(
2058
2460
  "button",
2059
2461
  {
2462
+ id: optionId(myIndex),
2060
2463
  type: "button",
2061
2464
  role: "option",
2062
2465
  "aria-selected": isActive,
@@ -2067,7 +2470,7 @@ function CommandGroups({ groups, cursor, setCursor, onSelect }) {
2067
2470
  isActive ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2"
2068
2471
  ),
2069
2472
  children: [
2070
- item.glyph != null && /* @__PURE__ */ jsx(
2473
+ item.glyph != null && /* @__PURE__ */ jsx40(
2071
2474
  "span",
2072
2475
  {
2073
2476
  "aria-hidden": true,
@@ -2078,11 +2481,11 @@ function CommandGroups({ groups, cursor, setCursor, onSelect }) {
2078
2481
  children: item.glyph
2079
2482
  }
2080
2483
  ),
2081
- /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
2082
- /* @__PURE__ */ jsx("span", { className: "block truncate text-[13px]", children: item.label }),
2083
- item.description && /* @__PURE__ */ jsx("span", { className: "text-text-dim block truncate text-[11px]", children: item.description })
2484
+ /* @__PURE__ */ jsxs33("span", { className: "min-w-0 flex-1", children: [
2485
+ /* @__PURE__ */ jsx40("span", { className: "block truncate text-[13px]", children: item.label }),
2486
+ item.description && /* @__PURE__ */ jsx40("span", { className: "text-text-dim block truncate text-[11px]", children: item.description })
2084
2487
  ] }),
2085
- item.trailing && /* @__PURE__ */ jsx("span", { className: "text-text-dim font-mono text-[10px]", children: item.trailing })
2488
+ item.trailing && /* @__PURE__ */ jsx40("span", { className: "text-text-dim font-mono text-[10px]", children: item.trailing })
2086
2489
  ]
2087
2490
  },
2088
2491
  item.id
@@ -2102,11 +2505,16 @@ function filterCommandItems(query, groups) {
2102
2505
  })
2103
2506
  })).filter((g) => g.items.length > 0);
2104
2507
  }
2508
+
2509
+ // src/patterns/DataTable/DataTable.tsx
2510
+ import { useEffect as useEffect7, useMemo as useMemo4, useRef as useRef5 } from "react";
2511
+ import { jsx as jsx41, jsxs as jsxs34 } from "react/jsx-runtime";
2105
2512
  var alignClass = {
2106
2513
  left: "text-left",
2107
2514
  right: "text-right",
2108
2515
  center: "text-center"
2109
2516
  };
2517
+ var EMPTY_SET = /* @__PURE__ */ new Set();
2110
2518
  function DataTable(props) {
2111
2519
  const {
2112
2520
  data,
@@ -2131,16 +2539,16 @@ function DataTable(props) {
2131
2539
  onChange: onSortChange
2132
2540
  });
2133
2541
  const [selected, setSelected] = useControllableState({
2134
- value: selectedProp instanceof Set ? selectedProp : selectedProp,
2542
+ value: selectedProp,
2135
2543
  defaultValue: new Set(defaultSelected ?? []),
2136
2544
  onChange: onSelectionChange
2137
2545
  });
2138
- const sortableMap = useMemo(() => {
2546
+ const sortableMap = useMemo4(() => {
2139
2547
  const m = /* @__PURE__ */ new Map();
2140
2548
  for (const c of columns) if (c.accessor) m.set(c.key, c);
2141
2549
  return m;
2142
2550
  }, [columns]);
2143
- const sortedData = useMemo(() => {
2551
+ const sortedData = useMemo4(() => {
2144
2552
  if (!sort) return [...data];
2145
2553
  const col = sortableMap.get(sort.key);
2146
2554
  if (!col || !col.accessor) return [...data];
@@ -2152,11 +2560,12 @@ function DataTable(props) {
2152
2560
  return String(av).localeCompare(String(bv)) * factor;
2153
2561
  });
2154
2562
  }, [data, sort, sortableMap]);
2155
- const allIds = useMemo(() => sortedData.map(rowKey), [sortedData, rowKey]);
2156
- const allSelected = allIds.length > 0 && allIds.every((id) => selected.has(id));
2157
- const someSelected = !allSelected && allIds.some((id) => selected.has(id));
2158
- const headerCheckRef = useRef(null);
2159
- useEffect(() => {
2563
+ const allIds = useMemo4(() => sortedData.map(rowKey), [sortedData, rowKey]);
2564
+ const selectedSet = selected ?? EMPTY_SET;
2565
+ const allSelected = allIds.length > 0 && allIds.every((id) => selectedSet.has(id));
2566
+ const someSelected = !allSelected && allIds.some((id) => selectedSet.has(id));
2567
+ const headerCheckRef = useRef5(null);
2568
+ useEffect7(() => {
2160
2569
  if (headerCheckRef.current) headerCheckRef.current.indeterminate = someSelected;
2161
2570
  }, [someSelected]);
2162
2571
  const toggleSort = (key) => {
@@ -2187,10 +2596,10 @@ function DataTable(props) {
2187
2596
  return next;
2188
2597
  });
2189
2598
  };
2190
- return /* @__PURE__ */ jsxs("table", { ref, className: cn("w-full border-collapse text-[12px]", className), children: [
2191
- caption && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
2192
- /* @__PURE__ */ jsx("thead", { className: cn("bg-panel-2", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs("tr", { children: [
2193
- selectable && /* @__PURE__ */ jsx("th", { scope: "col", className: "border-border w-8 border-b px-3 py-2 text-left", children: /* @__PURE__ */ jsx(
2599
+ return /* @__PURE__ */ jsxs34("table", { ref, className: cn("w-full border-collapse text-[12px]", className), children: [
2600
+ caption && /* @__PURE__ */ jsx41("caption", { className: "sr-only", children: caption }),
2601
+ /* @__PURE__ */ jsx41("thead", { className: cn("bg-panel-2", stickyHeader && "z-raised sticky top-0"), children: /* @__PURE__ */ jsxs34("tr", { children: [
2602
+ selectable && /* @__PURE__ */ jsx41("th", { scope: "col", className: "border-border w-8 border-b px-3 py-2 text-left", children: /* @__PURE__ */ jsx41(
2194
2603
  "input",
2195
2604
  {
2196
2605
  ref: headerCheckRef,
@@ -2206,12 +2615,12 @@ function DataTable(props) {
2206
2615
  const isSorted = sort?.key === col.key;
2207
2616
  const ariaSort = !sortable ? void 0 : isSorted ? sort?.direction === "asc" ? "ascending" : "descending" : "none";
2208
2617
  const align = col.align ?? "left";
2209
- return /* @__PURE__ */ jsxs(
2618
+ const indicator = sortable && isSorted && /* @__PURE__ */ jsx41("span", { "aria-hidden": true, className: "ml-1", children: sort?.direction === "asc" ? "\u2191" : "\u2193" });
2619
+ return /* @__PURE__ */ jsx41(
2210
2620
  "th",
2211
2621
  {
2212
2622
  scope: "col",
2213
2623
  "aria-sort": ariaSort,
2214
- onClick: sortable ? () => toggleSort(col.key) : void 0,
2215
2624
  style: col.width != null ? { width: col.width } : void 0,
2216
2625
  className: cn(
2217
2626
  "border-border border-b px-3 py-2 font-mono text-[10px] font-medium tracking-[1.4px] uppercase select-none",
@@ -2219,17 +2628,25 @@ function DataTable(props) {
2219
2628
  sortable && "cursor-pointer",
2220
2629
  isSorted ? "text-accent" : "text-text-dim"
2221
2630
  ),
2222
- children: [
2223
- col.header,
2224
- sortable && isSorted && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "ml-1", children: sort?.direction === "asc" ? "\u2191" : "\u2193" })
2225
- ]
2631
+ children: sortable ? /* @__PURE__ */ jsxs34(
2632
+ "button",
2633
+ {
2634
+ type: "button",
2635
+ onClick: () => toggleSort(col.key),
2636
+ className: "focus-visible:ring-accent-dim inline-flex cursor-pointer items-center gap-1 font-mono text-[10px] font-medium tracking-[1.4px] uppercase outline-none focus-visible:ring-[3px]",
2637
+ children: [
2638
+ col.header,
2639
+ indicator
2640
+ ]
2641
+ }
2642
+ ) : col.header
2226
2643
  },
2227
2644
  col.key
2228
2645
  );
2229
2646
  })
2230
2647
  ] }) }),
2231
- /* @__PURE__ */ jsxs("tbody", { children: [
2232
- sortedData.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
2648
+ /* @__PURE__ */ jsxs34("tbody", { children: [
2649
+ sortedData.length === 0 && /* @__PURE__ */ jsx41("tr", { children: /* @__PURE__ */ jsx41(
2233
2650
  "td",
2234
2651
  {
2235
2652
  colSpan: columns.length + (selectable ? 1 : 0),
@@ -2239,8 +2656,8 @@ function DataTable(props) {
2239
2656
  ) }),
2240
2657
  sortedData.map((row) => {
2241
2658
  const id = rowKey(row);
2242
- const isSelected = selected.has(id);
2243
- return /* @__PURE__ */ jsxs(
2659
+ const isSelected = selectedSet.has(id);
2660
+ return /* @__PURE__ */ jsxs34(
2244
2661
  "tr",
2245
2662
  {
2246
2663
  "data-state": isSelected ? "selected" : void 0,
@@ -2249,7 +2666,7 @@ function DataTable(props) {
2249
2666
  isSelected ? "bg-accent-dim/50" : "hover:bg-panel-2"
2250
2667
  ),
2251
2668
  children: [
2252
- selectable && /* @__PURE__ */ jsx("td", { className: "px-3 py-[10px]", children: /* @__PURE__ */ jsx(
2669
+ selectable && /* @__PURE__ */ jsx41("td", { className: "px-3 py-[10px]", children: /* @__PURE__ */ jsx41(
2253
2670
  "input",
2254
2671
  {
2255
2672
  type: "checkbox",
@@ -2259,7 +2676,7 @@ function DataTable(props) {
2259
2676
  className: "cursor-pointer accent-[var(--color-accent)]"
2260
2677
  }
2261
2678
  ) }),
2262
- columns.map((col) => /* @__PURE__ */ jsx("td", { className: cn("px-3 py-[10px]", alignClass[col.align ?? "left"]), children: col.cell ? col.cell(row) : col.accessor ? String(col.accessor(row)) : null }, col.key))
2679
+ columns.map((col) => /* @__PURE__ */ jsx41("td", { className: cn("px-3 py-[10px]", alignClass[col.align ?? "left"]), children: col.cell ? col.cell(row) : col.accessor ? String(col.accessor(row)) : null }, col.key))
2263
2680
  ]
2264
2681
  },
2265
2682
  id
@@ -2268,29 +2685,30 @@ function DataTable(props) {
2268
2685
  ] })
2269
2686
  ] });
2270
2687
  }
2271
- var MONTHS = [
2272
- "Jan",
2273
- "Feb",
2274
- "Mar",
2275
- "April",
2276
- "May",
2277
- "June",
2278
- "July",
2279
- "Aug",
2280
- "Sep",
2281
- "Oct",
2282
- "Nov",
2283
- "Dec"
2284
- ];
2688
+
2689
+ // src/patterns/DatePicker/Calendar.tsx
2690
+ import {
2691
+ forwardRef as forwardRef40,
2692
+ useCallback as useCallback7,
2693
+ useEffect as useEffect8,
2694
+ useRef as useRef6,
2695
+ useState as useState9
2696
+ } from "react";
2697
+ import { jsx as jsx42, jsxs as jsxs35 } from "react/jsx-runtime";
2698
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
2285
2699
  var DAYS = ["S", "M", "T", "W", "T", "F", "S"];
2286
2700
  function isSameDay(a, b) {
2287
2701
  if (!a) return false;
2288
2702
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2289
2703
  }
2290
- var Calendar = forwardRef(function Calendar2({
2291
- selected,
2292
- defaultSelected,
2293
- onSelect,
2704
+ function clampDay(year, month, day) {
2705
+ const max = new Date(year, month + 1, 0).getDate();
2706
+ return Math.min(Math.max(1, day), max);
2707
+ }
2708
+ var Calendar = forwardRef40(function Calendar2({
2709
+ value,
2710
+ defaultValue,
2711
+ onValueChange,
2294
2712
  month: monthProp,
2295
2713
  year: yearProp,
2296
2714
  defaultMonth,
@@ -2300,39 +2718,125 @@ var Calendar = forwardRef(function Calendar2({
2300
2718
  className,
2301
2719
  ...props
2302
2720
  }, ref) {
2303
- const today = /* @__PURE__ */ new Date();
2721
+ const [today] = useState9(() => /* @__PURE__ */ new Date());
2722
+ const [hydrated, setHydrated] = useState9(false);
2723
+ useEffect8(() => setHydrated(true), []);
2304
2724
  const [selectedDate, setSelectedDate] = useControllableState({
2305
- value: selected,
2306
- defaultValue: defaultSelected,
2307
- onChange: onSelect
2725
+ value,
2726
+ defaultValue,
2727
+ onChange: onValueChange
2308
2728
  });
2309
- const initialMonth = defaultMonth ?? defaultSelected?.getMonth() ?? today.getMonth();
2310
- const initialYear = defaultYear ?? defaultSelected?.getFullYear() ?? today.getFullYear();
2311
- const [internalMonth, setInternalMonth] = useState(initialMonth);
2312
- const [internalYear, setInternalYear] = useState(initialYear);
2729
+ const initialMonth = defaultMonth ?? defaultValue?.getMonth() ?? today.getMonth();
2730
+ const initialYear = defaultYear ?? defaultValue?.getFullYear() ?? today.getFullYear();
2731
+ const [internalMonth, setInternalMonth] = useState9(initialMonth);
2732
+ const [internalYear, setInternalYear] = useState9(initialYear);
2313
2733
  const month = monthProp ?? internalMonth;
2314
2734
  const year = yearProp ?? internalYear;
2315
2735
  const isControlled = monthProp !== void 0 && yearProp !== void 0;
2316
- const setVisible = (m, y) => {
2317
- if (!isControlled) {
2318
- setInternalMonth(m);
2319
- setInternalYear(y);
2320
- }
2321
- onVisibleMonthChange?.({ month: m, year: y });
2322
- };
2323
- const goPrev = () => {
2736
+ const setVisible = useCallback7(
2737
+ (m, y) => {
2738
+ if (!isControlled) {
2739
+ setInternalMonth(m);
2740
+ setInternalYear(y);
2741
+ }
2742
+ onVisibleMonthChange?.({ month: m, year: y });
2743
+ },
2744
+ [isControlled, onVisibleMonthChange]
2745
+ );
2746
+ const goPrev = useCallback7(() => {
2324
2747
  const m = month === 0 ? 11 : month - 1;
2325
2748
  const y = month === 0 ? year - 1 : year;
2326
2749
  setVisible(m, y);
2327
- };
2328
- const goNext = () => {
2750
+ }, [month, year, setVisible]);
2751
+ const goNext = useCallback7(() => {
2329
2752
  const m = month === 11 ? 0 : month + 1;
2330
2753
  const y = month === 11 ? year + 1 : year;
2331
2754
  setVisible(m, y);
2332
- };
2755
+ }, [month, year, setVisible]);
2333
2756
  const daysInMonth = new Date(year, month + 1, 0).getDate();
2334
2757
  const firstDayOfMonth = new Date(year, month, 1).getDay();
2335
- return /* @__PURE__ */ jsxs(
2758
+ const [focusedDate, setFocusedDate] = useState9(() => {
2759
+ if (selectedDate) return selectedDate;
2760
+ return new Date(initialYear, initialMonth, 1);
2761
+ });
2762
+ useEffect8(() => {
2763
+ if (selectedDate) setFocusedDate(selectedDate);
2764
+ }, [selectedDate]);
2765
+ const focusedInVisibleMonth = focusedDate.getMonth() === month && focusedDate.getFullYear() === year;
2766
+ const effectiveFocusDay = focusedInVisibleMonth ? focusedDate.getDate() : clampDay(year, month, focusedDate.getDate());
2767
+ const dayRefs = useRef6(/* @__PURE__ */ new Map());
2768
+ const shouldFocusRef = useRef6(false);
2769
+ useEffect8(() => {
2770
+ if (!shouldFocusRef.current) return;
2771
+ shouldFocusRef.current = false;
2772
+ const node = dayRefs.current.get(effectiveFocusDay);
2773
+ node?.focus();
2774
+ }, [effectiveFocusDay, month, year]);
2775
+ const moveFocus = useCallback7(
2776
+ (next) => {
2777
+ setFocusedDate(next);
2778
+ shouldFocusRef.current = true;
2779
+ const nextMonth = next.getMonth();
2780
+ const nextYear = next.getFullYear();
2781
+ if (nextMonth !== month || nextYear !== year) {
2782
+ setVisible(nextMonth, nextYear);
2783
+ }
2784
+ },
2785
+ [month, year, setVisible]
2786
+ );
2787
+ const onCellKeyDown = useCallback7(
2788
+ (e, day) => {
2789
+ const current = new Date(year, month, day);
2790
+ let next = null;
2791
+ let handled = true;
2792
+ switch (e.key) {
2793
+ case "ArrowLeft":
2794
+ next = new Date(year, month, day - 1);
2795
+ break;
2796
+ case "ArrowRight":
2797
+ next = new Date(year, month, day + 1);
2798
+ break;
2799
+ case "ArrowUp":
2800
+ next = new Date(year, month, day - 7);
2801
+ break;
2802
+ case "ArrowDown":
2803
+ next = new Date(year, month, day + 7);
2804
+ break;
2805
+ case "Home": {
2806
+ const dow = current.getDay();
2807
+ next = new Date(year, month, day - dow);
2808
+ break;
2809
+ }
2810
+ case "End": {
2811
+ const dow = current.getDay();
2812
+ next = new Date(year, month, day + (6 - dow));
2813
+ break;
2814
+ }
2815
+ case "PageUp": {
2816
+ const targetMonth = month === 0 ? 11 : month - 1;
2817
+ const targetYear = month === 0 ? year - 1 : year;
2818
+ const targetDay = clampDay(targetYear, targetMonth, day);
2819
+ next = new Date(targetYear, targetMonth, targetDay);
2820
+ break;
2821
+ }
2822
+ case "PageDown": {
2823
+ const targetMonth = month === 11 ? 0 : month + 1;
2824
+ const targetYear = month === 11 ? year + 1 : year;
2825
+ const targetDay = clampDay(targetYear, targetMonth, day);
2826
+ next = new Date(targetYear, targetMonth, targetDay);
2827
+ break;
2828
+ }
2829
+ default:
2830
+ handled = false;
2831
+ }
2832
+ if (handled && next) {
2833
+ e.preventDefault();
2834
+ moveFocus(next);
2835
+ }
2836
+ },
2837
+ [month, year, moveFocus]
2838
+ );
2839
+ return /* @__PURE__ */ jsxs35(
2336
2840
  "div",
2337
2841
  {
2338
2842
  ref,
@@ -2344,14 +2848,14 @@ var Calendar = forwardRef(function Calendar2({
2344
2848
  ),
2345
2849
  ...props,
2346
2850
  children: [
2347
- /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between", children: [
2348
- /* @__PURE__ */ jsxs("span", { className: "text-[13px] font-medium", "aria-live": "polite", children: [
2851
+ /* @__PURE__ */ jsxs35("div", { className: "mb-3 flex items-center justify-between", children: [
2852
+ /* @__PURE__ */ jsxs35("span", { className: "text-[13px] font-medium", "aria-live": "polite", children: [
2349
2853
  MONTHS[month],
2350
2854
  " ",
2351
2855
  year
2352
2856
  ] }),
2353
- /* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
2354
- /* @__PURE__ */ jsx(
2857
+ /* @__PURE__ */ jsxs35("div", { className: "flex gap-1", children: [
2858
+ /* @__PURE__ */ jsx42(
2355
2859
  IconButton,
2356
2860
  {
2357
2861
  size: "sm",
@@ -2361,48 +2865,89 @@ var Calendar = forwardRef(function Calendar2({
2361
2865
  onClick: goPrev
2362
2866
  }
2363
2867
  ),
2364
- /* @__PURE__ */ jsx(IconButton, { size: "sm", variant: "ghost", icon: "\u203A", "aria-label": "Next month", onClick: goNext })
2868
+ /* @__PURE__ */ jsx42(IconButton, { size: "sm", variant: "ghost", icon: "\u203A", "aria-label": "Next month", onClick: goNext })
2365
2869
  ] })
2366
2870
  ] }),
2367
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-7 gap-[2px]", children: [
2368
- DAYS.map((d, i) => /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "text-text-dim p-1 text-center font-mono text-[10px]", children: d }, i)),
2369
- Array.from({ length: firstDayOfMonth }).map((_, i) => /* @__PURE__ */ jsx("div", { "aria-hidden": true }, `pad-${i}`)),
2370
- Array.from({ length: daysInMonth }).map((_, i) => {
2371
- const d = i + 1;
2372
- const date = new Date(year, month, d);
2373
- const isSelected = isSameDay(selectedDate, date);
2374
- const isToday = isSameDay(today, date);
2375
- const disabled = isDateDisabled?.(date) ?? false;
2376
- return /* @__PURE__ */ jsx(
2377
- "button",
2378
- {
2379
- type: "button",
2380
- disabled,
2381
- "aria-pressed": isSelected,
2382
- "aria-current": isToday ? "date" : void 0,
2383
- "aria-label": date.toDateString(),
2384
- onClick: () => setSelectedDate(date),
2385
- className: cn(
2386
- "cursor-pointer rounded-xs border-0 bg-transparent py-[6px] text-center text-[12px] outline-none",
2387
- "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
2388
- "disabled:cursor-not-allowed disabled:opacity-30",
2389
- !isSelected && !disabled && "text-text hover:bg-panel-2",
2390
- isSelected && "bg-accent text-on-accent font-semibold",
2391
- !isSelected && isToday && "border-border-strong border"
2392
- ),
2393
- children: d
2394
- },
2395
- d
2396
- );
2397
- })
2871
+ /* @__PURE__ */ jsxs35("div", { role: "grid", "aria-label": `${MONTHS[month]} ${year}`, className: "flex flex-col gap-[2px]", children: [
2872
+ /* @__PURE__ */ jsx42("div", { role: "row", className: "grid grid-cols-7 gap-[2px]", children: DAYS.map((d, i) => /* @__PURE__ */ jsx42(
2873
+ "div",
2874
+ {
2875
+ role: "columnheader",
2876
+ "aria-label": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][i],
2877
+ className: "text-text-dim p-1 text-center font-mono text-[10px]",
2878
+ children: d
2879
+ },
2880
+ i
2881
+ )) }),
2882
+ (() => {
2883
+ const totalCells = firstDayOfMonth + daysInMonth;
2884
+ const rowCount = Math.ceil(totalCells / 7);
2885
+ const rows = [];
2886
+ for (let r = 0; r < rowCount; r++) {
2887
+ const cells = [];
2888
+ for (let c = 0; c < 7; c++) {
2889
+ const cellIndex = r * 7 + c;
2890
+ const dayNum = cellIndex - firstDayOfMonth + 1;
2891
+ if (dayNum < 1 || dayNum > daysInMonth) {
2892
+ cells.push(/* @__PURE__ */ jsx42("div", { role: "gridcell", "aria-hidden": true }, `pad-${r}-${c}`));
2893
+ continue;
2894
+ }
2895
+ const date = new Date(year, month, dayNum);
2896
+ const isSelected = isSameDay(selectedDate, date);
2897
+ const isToday = hydrated && isSameDay(today, date);
2898
+ const disabled = isDateDisabled?.(date) ?? false;
2899
+ const isFocused = dayNum === effectiveFocusDay;
2900
+ const day = dayNum;
2901
+ cells.push(
2902
+ /* @__PURE__ */ jsx42("div", { role: "gridcell", "aria-selected": isSelected, children: /* @__PURE__ */ jsx42(
2903
+ "button",
2904
+ {
2905
+ ref: (node) => {
2906
+ if (node) dayRefs.current.set(day, node);
2907
+ else dayRefs.current.delete(day);
2908
+ },
2909
+ type: "button",
2910
+ disabled,
2911
+ "aria-current": isToday ? "date" : void 0,
2912
+ "aria-label": date.toDateString(),
2913
+ tabIndex: isFocused ? 0 : -1,
2914
+ onClick: () => {
2915
+ setSelectedDate(date);
2916
+ setFocusedDate(date);
2917
+ },
2918
+ onKeyDown: (e) => onCellKeyDown(e, day),
2919
+ className: cn(
2920
+ "w-full cursor-pointer rounded-xs border-0 bg-transparent py-[6px] text-center text-[12px] outline-none",
2921
+ "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
2922
+ "disabled:cursor-not-allowed disabled:opacity-30",
2923
+ !isSelected && !disabled && "text-text hover:bg-panel-2",
2924
+ isSelected && "bg-accent text-on-accent font-semibold",
2925
+ !isSelected && isToday && "border-border-strong border"
2926
+ ),
2927
+ children: day
2928
+ }
2929
+ ) }, day)
2930
+ );
2931
+ }
2932
+ rows.push(
2933
+ /* @__PURE__ */ jsx42("div", { role: "row", className: "grid grid-cols-7 gap-[2px]", children: cells }, `row-${r}`)
2934
+ );
2935
+ }
2936
+ return rows;
2937
+ })()
2398
2938
  ] })
2399
2939
  ]
2400
2940
  }
2401
2941
  );
2402
2942
  });
2403
2943
  Calendar.displayName = "Calendar";
2944
+
2945
+ // src/patterns/DatePicker/DatePicker.tsx
2946
+ import * as RadixPopover2 from "@radix-ui/react-popover";
2947
+ import { forwardRef as forwardRef41, useState as useState10 } from "react";
2948
+ import { jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
2404
2949
  var defaultFormat = (d) => d.toLocaleDateString();
2405
- var DatePicker = forwardRef(function DatePicker2({
2950
+ var DatePicker = forwardRef41(function DatePicker2({
2406
2951
  value: valueProp,
2407
2952
  defaultValue,
2408
2953
  onValueChange,
@@ -2416,14 +2961,14 @@ var DatePicker = forwardRef(function DatePicker2({
2416
2961
  id,
2417
2962
  name
2418
2963
  }, ref) {
2419
- const [open, setOpen] = useState(false);
2964
+ const [open, setOpen] = useState10(false);
2420
2965
  const [value, setValue] = useControllableState({
2421
2966
  value: valueProp,
2422
2967
  defaultValue,
2423
2968
  onChange: onValueChange
2424
2969
  });
2425
- return /* @__PURE__ */ jsxs(RadixPopover.Root, { open, onOpenChange: setOpen, children: [
2426
- /* @__PURE__ */ jsx(RadixPopover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2970
+ return /* @__PURE__ */ jsxs36(RadixPopover2.Root, { open, onOpenChange: setOpen, children: [
2971
+ /* @__PURE__ */ jsx43(RadixPopover2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs36(
2427
2972
  "button",
2428
2973
  {
2429
2974
  ref,
@@ -2440,24 +2985,24 @@ var DatePicker = forwardRef(function DatePicker2({
2440
2985
  ),
2441
2986
  style: { width },
2442
2987
  children: [
2443
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-text-dim", children: "\u25A2" }),
2444
- /* @__PURE__ */ jsx("span", { className: cn("flex-1 truncate", !value && "text-text-dim"), children: value ? format(value) : emptyLabel ?? placeholder })
2988
+ /* @__PURE__ */ jsx43("span", { "aria-hidden": true, className: "text-text-dim", children: "\u25A2" }),
2989
+ /* @__PURE__ */ jsx43("span", { className: cn("flex-1 truncate", !value && "text-text-dim"), children: value ? format(value) : emptyLabel ?? placeholder })
2445
2990
  ]
2446
2991
  }
2447
2992
  ) }),
2448
- /* @__PURE__ */ jsx(RadixPopover.Portal, { children: /* @__PURE__ */ jsx(
2449
- RadixPopover.Content,
2993
+ /* @__PURE__ */ jsx43(RadixPopover2.Portal, { children: /* @__PURE__ */ jsx43(
2994
+ RadixPopover2.Content,
2450
2995
  {
2451
2996
  align: "start",
2452
2997
  sideOffset: 6,
2453
- className: "z-40 outline-none data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
2454
- children: /* @__PURE__ */ jsx(
2998
+ className: "z-popover outline-none data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
2999
+ children: /* @__PURE__ */ jsx43(
2455
3000
  Calendar,
2456
3001
  {
2457
- selected: value,
3002
+ value,
2458
3003
  defaultMonth: value?.getMonth(),
2459
3004
  defaultYear: value?.getFullYear(),
2460
- onSelect: (date) => {
3005
+ onValueChange: (date) => {
2461
3006
  setValue(date);
2462
3007
  setOpen(false);
2463
3008
  },
@@ -2466,13 +3011,17 @@ var DatePicker = forwardRef(function DatePicker2({
2466
3011
  )
2467
3012
  }
2468
3013
  ) }),
2469
- name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: value ? value.toISOString() : "", readOnly: true })
3014
+ name && /* @__PURE__ */ jsx43("input", { type: "hidden", name, value: value ? value.toISOString() : "", readOnly: true })
2470
3015
  ] });
2471
3016
  });
2472
3017
  DatePicker.displayName = "DatePicker";
2473
- var Dots = forwardRef(function Dots2({ total, current, onChange, className, "aria-label": ariaLabel = "Progress", ...props }, ref) {
3018
+
3019
+ // src/patterns/Dots/Dots.tsx
3020
+ import { forwardRef as forwardRef42 } from "react";
3021
+ import { jsx as jsx44 } from "react/jsx-runtime";
3022
+ var Dots = forwardRef42(function Dots2({ total, current, onChange, className, "aria-label": ariaLabel = "Progress", ...props }, ref) {
2474
3023
  const interactive = typeof onChange === "function";
2475
- return /* @__PURE__ */ jsx(
3024
+ return /* @__PURE__ */ jsx44(
2476
3025
  "nav",
2477
3026
  {
2478
3027
  ref,
@@ -2486,7 +3035,7 @@ var Dots = forwardRef(function Dots2({ total, current, onChange, className, "ari
2486
3035
  isActive ? "w-[18px] bg-accent" : "w-[6px] bg-panel-2"
2487
3036
  );
2488
3037
  if (interactive) {
2489
- return /* @__PURE__ */ jsx(
3038
+ return /* @__PURE__ */ jsx44(
2490
3039
  "button",
2491
3040
  {
2492
3041
  type: "button",
@@ -2503,24 +3052,115 @@ var Dots = forwardRef(function Dots2({ total, current, onChange, className, "ari
2503
3052
  i
2504
3053
  );
2505
3054
  }
2506
- return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: sharedClass }, i);
3055
+ return /* @__PURE__ */ jsx44("span", { "aria-hidden": true, className: sharedClass }, i);
2507
3056
  })
2508
3057
  }
2509
3058
  );
2510
3059
  });
2511
3060
  Dots.displayName = "Dots";
2512
- var plateStyles = cva("grid h-12 w-12 place-items-center rounded-base text-[22px]", {
3061
+
3062
+ // src/patterns/Dropzone/Dropzone.tsx
3063
+ import {
3064
+ forwardRef as forwardRef43,
3065
+ useState as useState11
3066
+ } from "react";
3067
+ import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
3068
+ function listToArray(list) {
3069
+ if (!list) return [];
3070
+ return Array.from(list);
3071
+ }
3072
+ var Dropzone = forwardRef43(function Dropzone2({
3073
+ onFiles,
3074
+ accept,
3075
+ multiple = true,
3076
+ title = "Drop files to ingest",
3077
+ description,
3078
+ icon = "\u21A5",
3079
+ disabled,
3080
+ className,
3081
+ ...props
3082
+ }, ref) {
3083
+ const [isDragging, setIsDragging] = useState11(false);
3084
+ const onDragOver = (e) => {
3085
+ if (disabled) return;
3086
+ e.preventDefault();
3087
+ setIsDragging(true);
3088
+ };
3089
+ const onDragLeave = () => setIsDragging(false);
3090
+ const onDrop = (e) => {
3091
+ if (disabled) return;
3092
+ e.preventDefault();
3093
+ setIsDragging(false);
3094
+ const files = listToArray(e.dataTransfer.files);
3095
+ if (files.length) onFiles?.(files);
3096
+ };
3097
+ return /* @__PURE__ */ jsxs37(
3098
+ "label",
3099
+ {
3100
+ ref,
3101
+ onDragOver,
3102
+ onDragLeave,
3103
+ onDrop,
3104
+ className: cn(
3105
+ "rounded-base flex max-w-[420px] cursor-pointer flex-col items-center border-[1.5px] border-dashed p-8 text-center",
3106
+ "transition-[background,border] duration-(--duration-micro)",
3107
+ "focus-within:ring-accent-dim focus-within:ring-[3px]",
3108
+ isDragging ? "border-accent bg-accent-dim" : "border-border-strong bg-panel hover:bg-panel-2",
3109
+ disabled && "pointer-events-none cursor-not-allowed opacity-50",
3110
+ className
3111
+ ),
3112
+ ...props,
3113
+ children: [
3114
+ /* @__PURE__ */ jsx45(
3115
+ "input",
3116
+ {
3117
+ type: "file",
3118
+ accept,
3119
+ multiple,
3120
+ disabled,
3121
+ "aria-label": typeof title === "string" ? title : "Upload files",
3122
+ className: "sr-only",
3123
+ onChange: (e) => {
3124
+ const files = listToArray(e.target.files);
3125
+ if (files.length) onFiles?.(files);
3126
+ e.target.value = "";
3127
+ }
3128
+ }
3129
+ ),
3130
+ /* @__PURE__ */ jsx45(
3131
+ "div",
3132
+ {
3133
+ "aria-hidden": true,
3134
+ className: cn("mb-2 text-[28px]", isDragging ? "text-accent" : "text-text-dim"),
3135
+ children: icon
3136
+ }
3137
+ ),
3138
+ /* @__PURE__ */ jsx45("div", { className: "mb-1 text-[13px] font-medium", children: title }),
3139
+ description && /* @__PURE__ */ jsx45("div", { className: "text-text-dim text-[11px]", children: description })
3140
+ ]
3141
+ }
3142
+ );
3143
+ });
3144
+ Dropzone.displayName = "Dropzone";
3145
+
3146
+ // src/patterns/EmptyState/EmptyState.tsx
3147
+ import { cva as cva10 } from "class-variance-authority";
3148
+ import { forwardRef as forwardRef44 } from "react";
3149
+ import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
3150
+ var plateStyles = cva10("grid h-12 w-12 place-items-center rounded-base text-[22px]", {
2513
3151
  variants: {
2514
3152
  tone: {
3153
+ neutral: "bg-panel-2 text-text-muted",
2515
3154
  accent: "bg-accent-dim text-accent",
2516
- danger: "bg-[color-mix(in_oklab,var(--color-err),transparent_85%)] text-err",
2517
- muted: "bg-panel-2 text-text-muted"
3155
+ ok: "bg-[color-mix(in_oklab,var(--color-ok),transparent_85%)] text-ok",
3156
+ warn: "bg-[color-mix(in_oklab,var(--color-warn),transparent_85%)] text-warn",
3157
+ err: "bg-[color-mix(in_oklab,var(--color-err),transparent_85%)] text-err"
2518
3158
  }
2519
3159
  },
2520
- defaultVariants: { tone: "accent" }
3160
+ defaultVariants: { tone: "neutral" }
2521
3161
  });
2522
- var EmptyState = forwardRef(function EmptyState2({ icon, title, description, action, chips, tone, className, ...props }, ref) {
2523
- return /* @__PURE__ */ jsxs(
3162
+ var EmptyState = forwardRef44(function EmptyState2({ icon, title, description, action, chips, tone, className, ...props }, ref) {
3163
+ return /* @__PURE__ */ jsxs38(
2524
3164
  "div",
2525
3165
  {
2526
3166
  ref,
@@ -2530,10 +3170,10 @@ var EmptyState = forwardRef(function EmptyState2({ icon, title, description, act
2530
3170
  ),
2531
3171
  ...props,
2532
3172
  children: [
2533
- icon != null && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: plateStyles({ tone }), children: icon }),
2534
- /* @__PURE__ */ jsx("div", { className: "text-[14px] font-medium", children: title }),
2535
- description && /* @__PURE__ */ jsx("div", { className: "text-text-muted max-w-[260px] text-[12px] leading-[1.5]", children: description }),
2536
- chips && chips.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-1", children: chips.map((c, i) => /* @__PURE__ */ jsx(
3173
+ icon != null && /* @__PURE__ */ jsx46("span", { "aria-hidden": true, className: plateStyles({ tone: tone ?? "neutral" }), children: icon }),
3174
+ /* @__PURE__ */ jsx46("div", { className: "text-[14px] font-medium", children: title }),
3175
+ description && /* @__PURE__ */ jsx46("div", { className: "text-text-muted max-w-[260px] text-[12px] leading-[1.5]", children: description }),
3176
+ chips && chips.length > 0 && /* @__PURE__ */ jsx46("div", { className: "flex w-full flex-col gap-1", children: chips.map((c, i) => /* @__PURE__ */ jsx46(
2537
3177
  "button",
2538
3178
  {
2539
3179
  type: "button",
@@ -2553,16 +3193,20 @@ var EmptyState = forwardRef(function EmptyState2({ icon, title, description, act
2553
3193
  );
2554
3194
  });
2555
3195
  EmptyState.displayName = "EmptyState";
3196
+
3197
+ // src/patterns/FileChip/FileChip.tsx
3198
+ import { forwardRef as forwardRef45 } from "react";
3199
+ import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
2556
3200
  function deriveExt(name) {
2557
3201
  const dot = name.lastIndexOf(".");
2558
3202
  if (dot < 0) return "FILE";
2559
3203
  return name.slice(dot + 1).slice(0, 4).toUpperCase();
2560
3204
  }
2561
- var FileChip = forwardRef(function FileChip2({ name, size, progress, icon, onRemove, failed, className, ...props }, ref) {
3205
+ var FileChip = forwardRef45(function FileChip2({ name, size, progress, icon, onRemove, failed, className, ...props }, ref) {
2562
3206
  const ext = deriveExt(name);
2563
3207
  const showProgress = typeof progress === "number";
2564
3208
  const isComplete = showProgress && progress >= 100;
2565
- return /* @__PURE__ */ jsxs(
3209
+ return /* @__PURE__ */ jsxs39(
2566
3210
  "div",
2567
3211
  {
2568
3212
  ref,
@@ -2572,7 +3216,7 @@ var FileChip = forwardRef(function FileChip2({ name, size, progress, icon, onRem
2572
3216
  ),
2573
3217
  ...props,
2574
3218
  children: [
2575
- /* @__PURE__ */ jsx(
3219
+ /* @__PURE__ */ jsx47(
2576
3220
  "span",
2577
3221
  {
2578
3222
  "aria-hidden": true,
@@ -2580,17 +3224,17 @@ var FileChip = forwardRef(function FileChip2({ name, size, progress, icon, onRem
2580
3224
  children: icon ?? ext
2581
3225
  }
2582
3226
  ),
2583
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2584
- /* @__PURE__ */ jsx("div", { className: "truncate text-[12px] font-medium", children: name }),
2585
- /* @__PURE__ */ jsxs("div", { className: cn("font-mono text-[10px]", failed ? "text-err" : "text-text-dim"), children: [
3227
+ /* @__PURE__ */ jsxs39("div", { className: "min-w-0 flex-1", children: [
3228
+ /* @__PURE__ */ jsx47("div", { className: "truncate text-[12px] font-medium", children: name }),
3229
+ /* @__PURE__ */ jsxs39("div", { className: cn("font-mono text-[10px]", failed ? "text-err" : "text-text-dim"), children: [
2586
3230
  size,
2587
- showProgress && !isComplete && /* @__PURE__ */ jsxs("span", { children: [
3231
+ showProgress && !isComplete && /* @__PURE__ */ jsxs39("span", { children: [
2588
3232
  " \xB7 ",
2589
3233
  Math.round(progress),
2590
3234
  "%"
2591
3235
  ] })
2592
3236
  ] }),
2593
- showProgress && !isComplete && /* @__PURE__ */ jsx("div", { className: "bg-panel mt-1 h-[2px] overflow-hidden rounded-full", children: /* @__PURE__ */ jsx(
3237
+ showProgress && !isComplete && /* @__PURE__ */ jsx47("div", { className: "bg-panel mt-1 h-[2px] overflow-hidden rounded-full", children: /* @__PURE__ */ jsx47(
2594
3238
  "div",
2595
3239
  {
2596
3240
  className: cn(
@@ -2601,7 +3245,7 @@ var FileChip = forwardRef(function FileChip2({ name, size, progress, icon, onRem
2601
3245
  }
2602
3246
  ) })
2603
3247
  ] }),
2604
- onRemove && /* @__PURE__ */ jsx(
3248
+ onRemove && /* @__PURE__ */ jsx47(
2605
3249
  "button",
2606
3250
  {
2607
3251
  type: "button",
@@ -2619,8 +3263,13 @@ var FileChip = forwardRef(function FileChip2({ name, size, progress, icon, onRem
2619
3263
  );
2620
3264
  });
2621
3265
  FileChip.displayName = "FileChip";
2622
- var Menubar = forwardRef(function Menubar2({ className, ...props }, ref) {
2623
- return /* @__PURE__ */ jsx(
3266
+
3267
+ // src/patterns/Menubar/Menubar.tsx
3268
+ import * as RadixMenubar from "@radix-ui/react-menubar";
3269
+ import { forwardRef as forwardRef46 } from "react";
3270
+ import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
3271
+ var Menubar = forwardRef46(function Menubar2({ className, ...props }, ref) {
3272
+ return /* @__PURE__ */ jsx48(
2624
3273
  RadixMenubar.Root,
2625
3274
  {
2626
3275
  ref,
@@ -2634,9 +3283,9 @@ var Menubar = forwardRef(function Menubar2({ className, ...props }, ref) {
2634
3283
  });
2635
3284
  Menubar.displayName = "Menubar";
2636
3285
  var MenubarMenu = RadixMenubar.Menu;
2637
- var MenubarTrigger = forwardRef(
3286
+ var MenubarTrigger = forwardRef46(
2638
3287
  function MenubarTrigger2({ className, ...props }, ref) {
2639
- return /* @__PURE__ */ jsx(
3288
+ return /* @__PURE__ */ jsx48(
2640
3289
  RadixMenubar.Trigger,
2641
3290
  {
2642
3291
  ref,
@@ -2653,16 +3302,16 @@ var MenubarTrigger = forwardRef(
2653
3302
  }
2654
3303
  );
2655
3304
  MenubarTrigger.displayName = "MenubarTrigger";
2656
- var MenubarContent = forwardRef(
3305
+ var MenubarContent = forwardRef46(
2657
3306
  function MenubarContent2({ className, sideOffset = 6, align = "start", ...props }, ref) {
2658
- return /* @__PURE__ */ jsx(RadixMenubar.Portal, { children: /* @__PURE__ */ jsx(
3307
+ return /* @__PURE__ */ jsx48(RadixMenubar.Portal, { children: /* @__PURE__ */ jsx48(
2659
3308
  RadixMenubar.Content,
2660
3309
  {
2661
3310
  ref,
2662
3311
  sideOffset,
2663
3312
  align,
2664
3313
  className: cn(
2665
- "border-border-strong bg-panel z-40 min-w-[180px] rounded-md border p-1 shadow-lg outline-none",
3314
+ "border-border-strong bg-panel z-popover min-w-[180px] rounded-md border p-1 shadow-lg outline-none",
2666
3315
  "data-[state=open]:animate-[ship-pop-in_140ms_var(--easing-out)]",
2667
3316
  className
2668
3317
  ),
@@ -2677,24 +3326,24 @@ var itemBase3 = cn(
2677
3326
  "data-[highlighted]:bg-panel-2",
2678
3327
  "data-[disabled]:opacity-40 data-[disabled]:cursor-not-allowed"
2679
3328
  );
2680
- var MenubarItem = forwardRef(function MenubarItem2({ trailing, destructive, className, children, ...props }, ref) {
2681
- return /* @__PURE__ */ jsxs(
3329
+ var MenubarItem = forwardRef46(function MenubarItem2({ trailing, destructive, className, children, ...props }, ref) {
3330
+ return /* @__PURE__ */ jsxs40(
2682
3331
  RadixMenubar.Item,
2683
3332
  {
2684
3333
  ref,
2685
3334
  className: cn(itemBase3, destructive ? "text-err" : "text-text", className),
2686
3335
  ...props,
2687
3336
  children: [
2688
- /* @__PURE__ */ jsx("span", { className: "flex-1", children }),
2689
- trailing && /* @__PURE__ */ jsx("span", { className: "text-text-dim font-mono text-[10px]", children: trailing })
3337
+ /* @__PURE__ */ jsx48("span", { className: "flex-1", children }),
3338
+ trailing && /* @__PURE__ */ jsx48("span", { className: "text-text-dim font-mono text-[10px]", children: trailing })
2690
3339
  ]
2691
3340
  }
2692
3341
  );
2693
3342
  });
2694
3343
  MenubarItem.displayName = "MenubarItem";
2695
- var MenubarSeparator = forwardRef(
3344
+ var MenubarSeparator = forwardRef46(
2696
3345
  function MenubarSeparator2({ className, ...props }, ref) {
2697
- return /* @__PURE__ */ jsx(
3346
+ return /* @__PURE__ */ jsx48(
2698
3347
  RadixMenubar.Separator,
2699
3348
  {
2700
3349
  ref,
@@ -2705,6 +3354,516 @@ var MenubarSeparator = forwardRef(
2705
3354
  }
2706
3355
  );
2707
3356
  MenubarSeparator.displayName = "MenubarSeparator";
3357
+
3358
+ // src/patterns/NavBar/NavBar.tsx
3359
+ import * as RadixNav from "@radix-ui/react-navigation-menu";
3360
+ import {
3361
+ forwardRef as forwardRef48,
3362
+ useCallback as useCallback9,
3363
+ useEffect as useEffect9,
3364
+ useRef as useRef7,
3365
+ useState as useState13
3366
+ } from "react";
3367
+
3368
+ // src/patterns/Sidebar/Sidebar.tsx
3369
+ import {
3370
+ forwardRef as forwardRef47,
3371
+ useCallback as useCallback8,
3372
+ useState as useState12
3373
+ } from "react";
3374
+ import { Fragment as Fragment2, jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
3375
+ var Sidebar = forwardRef47(function Sidebar2({ width = 240, className, style, ...props }, ref) {
3376
+ return /* @__PURE__ */ jsx49(
3377
+ "aside",
3378
+ {
3379
+ ref,
3380
+ style: { width, ...style },
3381
+ className: cn(
3382
+ "border-border bg-panel flex h-full flex-col gap-2 border-r p-[14px]",
3383
+ className
3384
+ ),
3385
+ ...props
3386
+ }
3387
+ );
3388
+ });
3389
+ Sidebar.displayName = "Sidebar";
3390
+ var NavItem = forwardRef47(
3391
+ function NavItem2({ icon, label, active, badge, href, disabled, className, ...props }, ref) {
3392
+ const inner = /* @__PURE__ */ jsxs41(Fragment2, { children: [
3393
+ icon && /* @__PURE__ */ jsx49("span", { "aria-hidden": true, className: "w-[14px] text-center opacity-80", children: icon }),
3394
+ /* @__PURE__ */ jsx49("span", { className: "flex-1 truncate", children: label }),
3395
+ badge != null && /* @__PURE__ */ jsx49(
3396
+ "span",
3397
+ {
3398
+ className: cn(
3399
+ "rounded-xs px-[6px] py-px font-mono text-[10px]",
3400
+ active ? "bg-accent text-on-accent" : "bg-panel-2 text-text-muted"
3401
+ ),
3402
+ children: badge
3403
+ }
3404
+ )
3405
+ ] });
3406
+ const baseClass = cn(
3407
+ "flex cursor-pointer items-center gap-[10px] rounded-xs px-2 py-[6px] text-[13px] outline-none",
3408
+ "transition-colors duration-(--duration-micro)",
3409
+ "focus-visible:ring-[3px] focus-visible:ring-accent-dim",
3410
+ active ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2",
3411
+ disabled && "opacity-50 pointer-events-none",
3412
+ className
3413
+ );
3414
+ if (href) {
3415
+ const anchorProps = props;
3416
+ return /* @__PURE__ */ jsx49(
3417
+ "a",
3418
+ {
3419
+ ref,
3420
+ href,
3421
+ "aria-current": active ? "page" : void 0,
3422
+ "aria-disabled": disabled || void 0,
3423
+ className: baseClass,
3424
+ ...anchorProps,
3425
+ children: inner
3426
+ }
3427
+ );
3428
+ }
3429
+ const buttonProps = props;
3430
+ return /* @__PURE__ */ jsx49(
3431
+ "button",
3432
+ {
3433
+ ref,
3434
+ type: "button",
3435
+ "aria-current": active ? "page" : void 0,
3436
+ disabled,
3437
+ className: cn(baseClass, "w-full text-left"),
3438
+ ...buttonProps,
3439
+ children: inner
3440
+ }
3441
+ );
3442
+ }
3443
+ );
3444
+ NavItem.displayName = "NavItem";
3445
+ var NavSection = forwardRef47(function NavSection2({
3446
+ label,
3447
+ icon,
3448
+ action,
3449
+ collapsible = false,
3450
+ defaultOpen = true,
3451
+ open,
3452
+ onOpenChange,
3453
+ indent = 0,
3454
+ className,
3455
+ children,
3456
+ ...props
3457
+ }, ref) {
3458
+ const isControlled = open !== void 0;
3459
+ const [internalOpen, setInternalOpen] = useState12(defaultOpen);
3460
+ const isOpen = !collapsible || (isControlled ? open : internalOpen);
3461
+ const toggle = useCallback8(() => {
3462
+ const next = !isOpen;
3463
+ if (!isControlled) setInternalOpen(next);
3464
+ onOpenChange?.(next);
3465
+ }, [isOpen, isControlled, onOpenChange]);
3466
+ const eyebrowClass = "text-text-dim flex items-center gap-[6px] px-2 pt-2 font-mono text-[9px] tracking-[1.4px] uppercase";
3467
+ return /* @__PURE__ */ jsxs41("div", { ref, className: cn("flex flex-col gap-1", className), ...props, children: [
3468
+ collapsible ? /* @__PURE__ */ jsxs41(
3469
+ "button",
3470
+ {
3471
+ type: "button",
3472
+ "aria-expanded": isOpen,
3473
+ onClick: toggle,
3474
+ className: cn(
3475
+ eyebrowClass,
3476
+ "cursor-pointer rounded-xs outline-none",
3477
+ "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
3478
+ "hover:text-text-muted"
3479
+ ),
3480
+ children: [
3481
+ icon != null && /* @__PURE__ */ jsx49("span", { "aria-hidden": true, className: "opacity-80", children: icon }),
3482
+ /* @__PURE__ */ jsx49("span", { className: "flex-1 text-left", children: label }),
3483
+ action,
3484
+ /* @__PURE__ */ jsx49("span", { "aria-hidden": true, className: "text-[10px] opacity-70", children: isOpen ? "\u25BE" : "\u25B8" })
3485
+ ]
3486
+ }
3487
+ ) : /* @__PURE__ */ jsxs41("div", { className: eyebrowClass, children: [
3488
+ icon != null && /* @__PURE__ */ jsx49("span", { "aria-hidden": true, className: "opacity-80", children: icon }),
3489
+ /* @__PURE__ */ jsx49("span", { className: "flex-1", children: label }),
3490
+ action
3491
+ ] }),
3492
+ isOpen && /* @__PURE__ */ jsx49(
3493
+ "div",
3494
+ {
3495
+ className: cn("flex flex-col gap-[2px]", indent > 0 && "border-border ml-2 border-l"),
3496
+ style: indent > 0 ? { paddingLeft: indent } : void 0,
3497
+ children
3498
+ }
3499
+ )
3500
+ ] });
3501
+ });
3502
+ NavSection.displayName = "NavSection";
3503
+
3504
+ // src/patterns/NavBar/NavBar.tsx
3505
+ import { Fragment as Fragment3, jsx as jsx50, jsxs as jsxs42 } from "react/jsx-runtime";
3506
+ function isActiveTree(item, activeId) {
3507
+ if (item.id === activeId) return true;
3508
+ return item.children?.some((c) => isActiveTree(c, activeId)) ?? false;
3509
+ }
3510
+ var NavBar = forwardRef48(function NavBar2({
3511
+ orientation = "horizontal",
3512
+ items,
3513
+ brand,
3514
+ actions,
3515
+ value,
3516
+ defaultValue,
3517
+ onValueChange,
3518
+ width = 240,
3519
+ responsive = true,
3520
+ className,
3521
+ ...props
3522
+ }, ref) {
3523
+ const isControlled = value !== void 0;
3524
+ const [internalValue, setInternalValue] = useState13(defaultValue);
3525
+ const activeId = isControlled ? value : internalValue;
3526
+ const [drawerOpen, setDrawerOpen] = useState13(false);
3527
+ const select = useCallback9(
3528
+ (id) => {
3529
+ if (!isControlled) setInternalValue(id);
3530
+ onValueChange?.(id);
3531
+ },
3532
+ [isControlled, onValueChange]
3533
+ );
3534
+ const handleItemActivate = useCallback9(
3535
+ (id) => {
3536
+ select(id);
3537
+ setDrawerOpen(false);
3538
+ },
3539
+ [select]
3540
+ );
3541
+ const drawerBody = (
3542
+ // Distinct aria-label from the desktop <aside>'s <nav> below — when the
3543
+ // drawer is open on a viewport that's resizing past `md`, both navs can
3544
+ // sit in the DOM together. Identical accessible names would trip axe's
3545
+ // `landmark-unique` rule.
3546
+ /* @__PURE__ */ jsx50("nav", { "aria-label": "Mobile navigation", className: "flex flex-col gap-1", children: items.map((item) => /* @__PURE__ */ jsx50(
3547
+ VerticalItem,
3548
+ {
3549
+ item,
3550
+ activeId,
3551
+ onActivate: handleItemActivate
3552
+ },
3553
+ item.id
3554
+ )) })
3555
+ );
3556
+ const mobileBar = responsive ? /* @__PURE__ */ jsxs42(
3557
+ "div",
3558
+ {
3559
+ className: cn(
3560
+ "border-border bg-panel z-overlay sticky top-0 flex h-[52px] items-center gap-4 border-b px-5 md:hidden"
3561
+ ),
3562
+ children: [
3563
+ /* @__PURE__ */ jsx50(
3564
+ "button",
3565
+ {
3566
+ type: "button",
3567
+ onClick: () => setDrawerOpen(true),
3568
+ "aria-label": "Open navigation",
3569
+ className: "text-text-muted hover:text-text focus-visible:ring-accent-dim rounded-xs px-2 py-1 text-[18px] outline-none focus-visible:ring-[3px]",
3570
+ children: "\u2630"
3571
+ }
3572
+ ),
3573
+ brand && /* @__PURE__ */ jsx50("div", { className: "flex flex-1 items-center text-[13px] font-medium whitespace-nowrap", children: brand }),
3574
+ actions && /* @__PURE__ */ jsx50("div", { className: "flex items-center gap-3", children: actions })
3575
+ ]
3576
+ }
3577
+ ) : null;
3578
+ if (orientation === "horizontal") {
3579
+ return /* @__PURE__ */ jsxs42(Fragment3, { children: [
3580
+ mobileBar,
3581
+ /* @__PURE__ */ jsxs42(
3582
+ "header",
3583
+ {
3584
+ ref,
3585
+ className: cn(
3586
+ "border-border bg-panel flex h-[52px] items-center gap-4 border-b px-5",
3587
+ responsive && "hidden md:flex",
3588
+ className
3589
+ ),
3590
+ ...props,
3591
+ children: [
3592
+ brand && /* @__PURE__ */ jsx50("div", { className: "shrink-0 text-[13px] font-medium whitespace-nowrap", children: brand }),
3593
+ /* @__PURE__ */ jsxs42(RadixNav.Root, { className: "relative flex-1", delayDuration: 120, children: [
3594
+ /* @__PURE__ */ jsx50(RadixNav.List, { className: "m-0! flex list-none! items-center gap-1 p-0! [&_li]:m-0!", children: items.map(
3595
+ (item) => item.children?.length ? /* @__PURE__ */ jsx50(
3596
+ HorizontalDropdown,
3597
+ {
3598
+ item,
3599
+ active: isActiveTree(item, activeId),
3600
+ activeId,
3601
+ onActivate: handleItemActivate
3602
+ },
3603
+ item.id
3604
+ ) : /* @__PURE__ */ jsx50(RadixNav.Item, { children: /* @__PURE__ */ jsx50(
3605
+ HorizontalLink,
3606
+ {
3607
+ item,
3608
+ active: item.id === activeId,
3609
+ onActivate: handleItemActivate
3610
+ }
3611
+ ) }, item.id)
3612
+ ) }),
3613
+ /* @__PURE__ */ jsx50("div", { className: "z-popover absolute top-full left-0 flex justify-start", children: /* @__PURE__ */ jsx50(RadixNav.Viewport, { className: "origin-top-left data-[state=open]:animate-[ship-fade-in_120ms_var(--easing-out)]" }) })
3614
+ ] }),
3615
+ actions && /* @__PURE__ */ jsx50("div", { className: "flex items-center gap-3", children: actions })
3616
+ ]
3617
+ }
3618
+ ),
3619
+ responsive && /* @__PURE__ */ jsx50(
3620
+ Drawer,
3621
+ {
3622
+ open: drawerOpen,
3623
+ onOpenChange: setDrawerOpen,
3624
+ side: "left",
3625
+ title: brand ?? "Navigation",
3626
+ width: 300,
3627
+ children: drawerBody
3628
+ }
3629
+ )
3630
+ ] });
3631
+ }
3632
+ return /* @__PURE__ */ jsxs42(Fragment3, { children: [
3633
+ mobileBar,
3634
+ /* @__PURE__ */ jsxs42(
3635
+ "aside",
3636
+ {
3637
+ ref,
3638
+ "aria-label": "Primary navigation",
3639
+ style: { width },
3640
+ className: cn(
3641
+ "border-border bg-panel flex h-full flex-col gap-2 border-r p-[14px]",
3642
+ responsive && "hidden md:flex",
3643
+ className
3644
+ ),
3645
+ ...props,
3646
+ children: [
3647
+ brand && /* @__PURE__ */ jsx50("div", { className: "px-2 py-1 text-[13px] font-medium", children: brand }),
3648
+ /* @__PURE__ */ jsx50("nav", { "aria-label": "Sidebar navigation", className: "flex flex-1 flex-col gap-1 overflow-y-auto", children: items.map((item) => /* @__PURE__ */ jsx50(
3649
+ VerticalItem,
3650
+ {
3651
+ item,
3652
+ activeId,
3653
+ onActivate: handleItemActivate
3654
+ },
3655
+ item.id
3656
+ )) }),
3657
+ actions && /* @__PURE__ */ jsx50("div", { className: "border-border mt-auto flex flex-col gap-2 border-t pt-3", children: actions })
3658
+ ]
3659
+ }
3660
+ ),
3661
+ responsive && /* @__PURE__ */ jsx50(
3662
+ Drawer,
3663
+ {
3664
+ open: drawerOpen,
3665
+ onOpenChange: setDrawerOpen,
3666
+ side: "left",
3667
+ title: brand ?? "Navigation",
3668
+ width: 300,
3669
+ children: drawerBody
3670
+ }
3671
+ )
3672
+ ] });
3673
+ });
3674
+ NavBar.displayName = "NavBar";
3675
+ function HorizontalLink({ item, active, onActivate }) {
3676
+ const baseClass = cn(
3677
+ "flex items-center gap-[6px] rounded-xs px-3 py-[6px] text-[13px] outline-none",
3678
+ "transition-colors duration-(--duration-micro)",
3679
+ "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
3680
+ active ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2",
3681
+ item.disabled && "pointer-events-none opacity-50"
3682
+ );
3683
+ const handleClick = (e) => {
3684
+ if (item.disabled) {
3685
+ e.preventDefault();
3686
+ return;
3687
+ }
3688
+ onActivate(item.id);
3689
+ };
3690
+ const inner = /* @__PURE__ */ jsxs42(Fragment3, { children: [
3691
+ item.icon != null && /* @__PURE__ */ jsx50("span", { "aria-hidden": true, className: "opacity-80", children: item.icon }),
3692
+ /* @__PURE__ */ jsx50("span", { children: item.label }),
3693
+ item.badge != null && /* @__PURE__ */ jsx50(ItemBadge, { active, children: item.badge })
3694
+ ] });
3695
+ if (item.href) {
3696
+ return /* @__PURE__ */ jsx50(RadixNav.Link, { asChild: true, active, children: /* @__PURE__ */ jsx50(
3697
+ "a",
3698
+ {
3699
+ href: item.href,
3700
+ "aria-current": active ? "page" : void 0,
3701
+ "aria-disabled": item.disabled || void 0,
3702
+ className: baseClass,
3703
+ onClick: handleClick,
3704
+ children: inner
3705
+ }
3706
+ ) });
3707
+ }
3708
+ return /* @__PURE__ */ jsx50(RadixNav.Link, { asChild: true, active, children: /* @__PURE__ */ jsx50(
3709
+ "button",
3710
+ {
3711
+ type: "button",
3712
+ "aria-current": active ? "page" : void 0,
3713
+ disabled: item.disabled,
3714
+ className: baseClass,
3715
+ onClick: handleClick,
3716
+ children: inner
3717
+ }
3718
+ ) });
3719
+ }
3720
+ function HorizontalDropdown({ item, active, activeId, onActivate }) {
3721
+ return /* @__PURE__ */ jsxs42(RadixNav.Item, { children: [
3722
+ /* @__PURE__ */ jsxs42(
3723
+ RadixNav.Trigger,
3724
+ {
3725
+ className: cn(
3726
+ "group flex items-center gap-1 rounded-xs px-3 py-[6px] text-[13px] outline-none",
3727
+ "transition-colors duration-(--duration-micro)",
3728
+ "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
3729
+ active ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2",
3730
+ "data-[state=open]:bg-panel-2"
3731
+ ),
3732
+ disabled: item.disabled,
3733
+ children: [
3734
+ item.icon != null && /* @__PURE__ */ jsx50("span", { "aria-hidden": true, className: "opacity-80", children: item.icon }),
3735
+ /* @__PURE__ */ jsx50("span", { children: item.label }),
3736
+ /* @__PURE__ */ jsx50(
3737
+ "span",
3738
+ {
3739
+ "aria-hidden": true,
3740
+ className: "ml-1 text-[10px] opacity-70 transition-transform group-data-[state=open]:rotate-180",
3741
+ children: "\u25BE"
3742
+ }
3743
+ )
3744
+ ]
3745
+ }
3746
+ ),
3747
+ /* @__PURE__ */ jsx50(RadixNav.Content, { className: "border-border bg-panel min-w-[220px] rounded-xs border p-2 shadow-lg", children: /* @__PURE__ */ jsx50("ul", { className: "m-0! flex list-none! flex-col gap-[2px] p-0! [&_li]:m-0!", children: item.children.map((child) => /* @__PURE__ */ jsx50("li", { children: /* @__PURE__ */ jsx50(DropdownLink, { item: child, active: child.id === activeId, onActivate }) }, child.id)) }) })
3748
+ ] });
3749
+ }
3750
+ function DropdownLink({ item, active, onActivate }) {
3751
+ const baseClass = cn(
3752
+ "flex w-full items-center gap-2 rounded-xs px-2 py-[6px] text-left text-[13px] outline-none",
3753
+ "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
3754
+ active ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2",
3755
+ item.disabled && "pointer-events-none opacity-50"
3756
+ );
3757
+ const handleClick = (e) => {
3758
+ if (item.disabled) {
3759
+ e.preventDefault();
3760
+ return;
3761
+ }
3762
+ onActivate(item.id);
3763
+ };
3764
+ const inner = /* @__PURE__ */ jsxs42(Fragment3, { children: [
3765
+ item.icon != null && /* @__PURE__ */ jsx50("span", { "aria-hidden": true, className: "opacity-80", children: item.icon }),
3766
+ /* @__PURE__ */ jsx50("span", { className: "flex-1", children: item.label }),
3767
+ item.badge != null && /* @__PURE__ */ jsx50(ItemBadge, { active, children: item.badge })
3768
+ ] });
3769
+ if (item.href) {
3770
+ return /* @__PURE__ */ jsx50(RadixNav.Link, { asChild: true, active, children: /* @__PURE__ */ jsx50(
3771
+ "a",
3772
+ {
3773
+ href: item.href,
3774
+ "aria-current": active ? "page" : void 0,
3775
+ "aria-disabled": item.disabled || void 0,
3776
+ className: baseClass,
3777
+ onClick: handleClick,
3778
+ children: inner
3779
+ }
3780
+ ) });
3781
+ }
3782
+ return /* @__PURE__ */ jsx50(RadixNav.Link, { asChild: true, active, children: /* @__PURE__ */ jsx50(
3783
+ "button",
3784
+ {
3785
+ type: "button",
3786
+ "aria-current": active ? "page" : void 0,
3787
+ disabled: item.disabled,
3788
+ className: baseClass,
3789
+ onClick: handleClick,
3790
+ children: inner
3791
+ }
3792
+ ) });
3793
+ }
3794
+ function VerticalItem({ item, activeId, onActivate }) {
3795
+ const hasChildren = (item.children?.length ?? 0) > 0;
3796
+ const treeActive = isActiveTree(item, activeId);
3797
+ const [open, setOpen] = useState13(treeActive);
3798
+ const prevTreeActive = useRef7(treeActive);
3799
+ useEffect9(() => {
3800
+ if (treeActive && !prevTreeActive.current) setOpen(true);
3801
+ prevTreeActive.current = treeActive;
3802
+ }, [treeActive]);
3803
+ if (!hasChildren) {
3804
+ const handleClick = (e) => {
3805
+ if (item.disabled) {
3806
+ e.preventDefault();
3807
+ return;
3808
+ }
3809
+ onActivate(item.id);
3810
+ };
3811
+ return /* @__PURE__ */ jsx50(
3812
+ NavItem,
3813
+ {
3814
+ icon: item.icon,
3815
+ label: item.label,
3816
+ active: item.id === activeId,
3817
+ badge: item.badge,
3818
+ disabled: item.disabled,
3819
+ href: item.href,
3820
+ onClick: handleClick
3821
+ }
3822
+ );
3823
+ }
3824
+ return /* @__PURE__ */ jsxs42("div", { className: "flex flex-col", children: [
3825
+ /* @__PURE__ */ jsxs42(
3826
+ "button",
3827
+ {
3828
+ type: "button",
3829
+ "aria-expanded": open,
3830
+ onClick: () => setOpen((o) => !o),
3831
+ disabled: item.disabled,
3832
+ className: cn(
3833
+ "flex w-full items-center gap-[10px] rounded-xs px-2 py-[6px] text-left text-[13px] outline-none",
3834
+ "transition-colors duration-(--duration-micro)",
3835
+ "focus-visible:ring-accent-dim focus-visible:ring-[3px]",
3836
+ treeActive ? "text-text" : "text-text-muted",
3837
+ "hover:bg-panel-2",
3838
+ item.disabled && "pointer-events-none opacity-50"
3839
+ ),
3840
+ children: [
3841
+ item.icon != null && /* @__PURE__ */ jsx50("span", { "aria-hidden": true, className: "w-[14px] text-center opacity-80", children: item.icon }),
3842
+ /* @__PURE__ */ jsx50("span", { className: "flex-1 truncate", children: item.label }),
3843
+ item.badge != null && /* @__PURE__ */ jsx50(ItemBadge, { active: treeActive, children: item.badge }),
3844
+ /* @__PURE__ */ jsx50("span", { "aria-hidden": true, className: "text-[10px] opacity-60", children: open ? "\u25BE" : "\u25B8" })
3845
+ ]
3846
+ }
3847
+ ),
3848
+ open && /* @__PURE__ */ jsx50("div", { className: "border-border mt-1 ml-[18px] flex flex-col gap-[2px] border-l pl-3", children: item.children.map((child) => /* @__PURE__ */ jsx50(VerticalItem, { item: child, activeId, onActivate }, child.id)) })
3849
+ ] });
3850
+ }
3851
+ function ItemBadge({ active, children }) {
3852
+ return /* @__PURE__ */ jsx50(
3853
+ "span",
3854
+ {
3855
+ className: cn(
3856
+ "rounded-xs px-[6px] py-px font-mono text-[10px]",
3857
+ active ? "bg-accent text-on-accent" : "bg-panel-2 text-text-muted"
3858
+ ),
3859
+ children
3860
+ }
3861
+ );
3862
+ }
3863
+
3864
+ // src/patterns/Pagination/Pagination.tsx
3865
+ import { forwardRef as forwardRef49 } from "react";
3866
+ import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
2708
3867
  function buildRange(page, total, siblings) {
2709
3868
  if (total <= 0) return [];
2710
3869
  const items = [];
@@ -2717,9 +3876,9 @@ function buildRange(page, total, siblings) {
2717
3876
  if (total > 1) items.push(total);
2718
3877
  return items;
2719
3878
  }
2720
- var Pagination = forwardRef(function Pagination2({ page, total, onPageChange, siblings = 1, className, ...props }, ref) {
3879
+ var Pagination = forwardRef49(function Pagination2({ page, total, onPageChange, siblings = 1, className, ...props }, ref) {
2721
3880
  const items = buildRange(page, total, siblings);
2722
- return /* @__PURE__ */ jsxs(
3881
+ return /* @__PURE__ */ jsxs43(
2723
3882
  "nav",
2724
3883
  {
2725
3884
  ref,
@@ -2727,7 +3886,7 @@ var Pagination = forwardRef(function Pagination2({ page, total, onPageChange, si
2727
3886
  className: cn("inline-flex items-center gap-1", className),
2728
3887
  ...props,
2729
3888
  children: [
2730
- /* @__PURE__ */ jsx(
3889
+ /* @__PURE__ */ jsx51(
2731
3890
  IconButton,
2732
3891
  {
2733
3892
  size: "sm",
@@ -2740,7 +3899,7 @@ var Pagination = forwardRef(function Pagination2({ page, total, onPageChange, si
2740
3899
  ),
2741
3900
  items.map((item, i) => {
2742
3901
  if (item === "start-ellipsis" || item === "end-ellipsis") {
2743
- return /* @__PURE__ */ jsx(
3902
+ return /* @__PURE__ */ jsx51(
2744
3903
  "span",
2745
3904
  {
2746
3905
  "aria-hidden": true,
@@ -2751,7 +3910,7 @@ var Pagination = forwardRef(function Pagination2({ page, total, onPageChange, si
2751
3910
  );
2752
3911
  }
2753
3912
  const isActive = item === page;
2754
- return /* @__PURE__ */ jsx(
3913
+ return /* @__PURE__ */ jsx51(
2755
3914
  "button",
2756
3915
  {
2757
3916
  type: "button",
@@ -2769,7 +3928,7 @@ var Pagination = forwardRef(function Pagination2({ page, total, onPageChange, si
2769
3928
  item
2770
3929
  );
2771
3930
  }),
2772
- /* @__PURE__ */ jsx(
3931
+ /* @__PURE__ */ jsx51(
2773
3932
  IconButton,
2774
3933
  {
2775
3934
  size: "sm",
@@ -2785,7 +3944,12 @@ var Pagination = forwardRef(function Pagination2({ page, total, onPageChange, si
2785
3944
  );
2786
3945
  });
2787
3946
  Pagination.displayName = "Pagination";
2788
- var trackStyles = cva("w-full rounded-full bg-panel-2 overflow-hidden", {
3947
+
3948
+ // src/patterns/Progress/Progress.tsx
3949
+ import { cva as cva11 } from "class-variance-authority";
3950
+ import { forwardRef as forwardRef50 } from "react";
3951
+ import { jsx as jsx52, jsxs as jsxs44 } from "react/jsx-runtime";
3952
+ var trackStyles = cva11("w-full rounded-full bg-panel-2 overflow-hidden", {
2789
3953
  variants: {
2790
3954
  size: {
2791
3955
  sm: "h-[3px]",
@@ -2795,7 +3959,7 @@ var trackStyles = cva("w-full rounded-full bg-panel-2 overflow-hidden", {
2795
3959
  },
2796
3960
  defaultVariants: { size: "md" }
2797
3961
  });
2798
- var fillStyles = cva("h-full rounded-full transition-[width] duration-(--duration-step)", {
3962
+ var fillStyles = cva11("h-full rounded-full transition-[width] duration-(--duration-step)", {
2799
3963
  variants: {
2800
3964
  tone: {
2801
3965
  accent: "bg-accent",
@@ -2806,7 +3970,7 @@ var fillStyles = cva("h-full rounded-full transition-[width] duration-(--duratio
2806
3970
  },
2807
3971
  defaultVariants: { tone: "accent" }
2808
3972
  });
2809
- var Progress = forwardRef(function Progress2({
3973
+ var Progress = forwardRef50(function Progress2({
2810
3974
  value = 0,
2811
3975
  max = 100,
2812
3976
  indeterminate = false,
@@ -2820,15 +3984,15 @@ var Progress = forwardRef(function Progress2({
2820
3984
  const clamped = Math.min(max, Math.max(0, value));
2821
3985
  const pct = max > 0 ? clamped / max * 100 : 0;
2822
3986
  const display = Math.round(pct);
2823
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex w-full flex-col gap-2", className), ...props, children: [
2824
- label != null && /* @__PURE__ */ jsxs("div", { className: "flex text-[12px]", children: [
2825
- /* @__PURE__ */ jsx("span", { className: "text-text-muted", children: label }),
2826
- showValue && !indeterminate && /* @__PURE__ */ jsxs("span", { className: "text-text ml-auto font-mono tabular-nums", children: [
3987
+ return /* @__PURE__ */ jsxs44("div", { ref, className: cn("flex w-full flex-col gap-2", className), ...props, children: [
3988
+ label != null && /* @__PURE__ */ jsxs44("div", { className: "flex text-[12px]", children: [
3989
+ /* @__PURE__ */ jsx52("span", { className: "text-text-muted", children: label }),
3990
+ showValue && !indeterminate && /* @__PURE__ */ jsxs44("span", { className: "text-text ml-auto font-mono tabular-nums", children: [
2827
3991
  display,
2828
3992
  "%"
2829
3993
  ] })
2830
3994
  ] }),
2831
- /* @__PURE__ */ jsx(
3995
+ /* @__PURE__ */ jsx52(
2832
3996
  "div",
2833
3997
  {
2834
3998
  role: "progressbar",
@@ -2837,7 +4001,7 @@ var Progress = forwardRef(function Progress2({
2837
4001
  "aria-valuenow": indeterminate ? void 0 : display,
2838
4002
  "aria-label": typeof label === "string" ? label : void 0,
2839
4003
  className: trackStyles({ size }),
2840
- children: indeterminate ? /* @__PURE__ */ jsx(
4004
+ children: indeterminate ? /* @__PURE__ */ jsx52(
2841
4005
  "span",
2842
4006
  {
2843
4007
  "aria-hidden": true,
@@ -2847,19 +4011,23 @@ var Progress = forwardRef(function Progress2({
2847
4011
  "animate-[ship-indeterminate_1.4s_linear_infinite]"
2848
4012
  )
2849
4013
  }
2850
- ) : /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: fillStyles({ tone }), style: { width: `${pct}%` } })
4014
+ ) : /* @__PURE__ */ jsx52("span", { "aria-hidden": true, className: fillStyles({ tone }), style: { width: `${pct}%` } })
2851
4015
  }
2852
4016
  )
2853
4017
  ] });
2854
4018
  });
2855
4019
  Progress.displayName = "Progress";
4020
+
4021
+ // src/patterns/RadialProgress/RadialProgress.tsx
4022
+ import { forwardRef as forwardRef51 } from "react";
4023
+ import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
2856
4024
  var toneStrokeClass = {
2857
4025
  accent: "stroke-accent",
2858
4026
  ok: "stroke-ok",
2859
4027
  warn: "stroke-warn",
2860
4028
  err: "stroke-err"
2861
4029
  };
2862
- var RadialProgress = forwardRef(
4030
+ var RadialProgress = forwardRef51(
2863
4031
  function RadialProgress2({
2864
4032
  value,
2865
4033
  max = 100,
@@ -2877,7 +4045,7 @@ var RadialProgress = forwardRef(
2877
4045
  const c = 2 * Math.PI * r;
2878
4046
  const dash = pct / 100 * c;
2879
4047
  const resolvedTone = tone ?? (clamped >= max ? "ok" : "accent");
2880
- return /* @__PURE__ */ jsxs(
4048
+ return /* @__PURE__ */ jsxs45(
2881
4049
  "div",
2882
4050
  {
2883
4051
  ref,
@@ -2890,8 +4058,8 @@ var RadialProgress = forwardRef(
2890
4058
  style: { width: size, height: size },
2891
4059
  ...props,
2892
4060
  children: [
2893
- /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, children: [
2894
- /* @__PURE__ */ jsx(
4061
+ /* @__PURE__ */ jsxs45("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, children: [
4062
+ /* @__PURE__ */ jsx53(
2895
4063
  "circle",
2896
4064
  {
2897
4065
  cx: size / 2,
@@ -2902,7 +4070,7 @@ var RadialProgress = forwardRef(
2902
4070
  className: "stroke-panel-2"
2903
4071
  }
2904
4072
  ),
2905
- /* @__PURE__ */ jsx(
4073
+ /* @__PURE__ */ jsx53(
2906
4074
  "circle",
2907
4075
  {
2908
4076
  cx: size / 2,
@@ -2920,98 +4088,17 @@ var RadialProgress = forwardRef(
2920
4088
  }
2921
4089
  )
2922
4090
  ] }),
2923
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 grid place-items-center font-mono text-[11px] font-medium tabular-nums", children: children ?? `${Math.round(pct)}%` })
4091
+ /* @__PURE__ */ jsx53("div", { className: "absolute inset-0 grid place-items-center font-mono text-[11px] font-medium tabular-nums", children: children ?? `${Math.round(pct)}%` })
2924
4092
  ]
2925
4093
  }
2926
4094
  );
2927
4095
  }
2928
4096
  );
2929
4097
  RadialProgress.displayName = "RadialProgress";
2930
- var Sidebar = forwardRef(function Sidebar2({ width = 240, className, style, ...props }, ref) {
2931
- return /* @__PURE__ */ jsx(
2932
- "aside",
2933
- {
2934
- ref,
2935
- style: { width, ...style },
2936
- className: cn(
2937
- "border-border bg-panel flex h-full flex-col gap-2 border-r p-[14px]",
2938
- className
2939
- ),
2940
- ...props
2941
- }
2942
- );
2943
- });
2944
- Sidebar.displayName = "Sidebar";
2945
- var NavItem = forwardRef(function NavItem2({ icon, label, active, badge, href, disabled, className, onClick, ...props }, ref) {
2946
- const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
2947
- icon && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "w-[14px] text-center opacity-80", children: icon }),
2948
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: label }),
2949
- badge != null && /* @__PURE__ */ jsx(
2950
- "span",
2951
- {
2952
- className: cn(
2953
- "rounded-xs px-[6px] py-px font-mono text-[10px]",
2954
- active ? "bg-accent text-on-accent" : "bg-panel-2 text-text-muted"
2955
- ),
2956
- children: badge
2957
- }
2958
- )
2959
- ] });
2960
- const baseClass = cn(
2961
- "flex cursor-pointer items-center gap-[10px] rounded-xs px-2 py-[6px] text-[13px] outline-none",
2962
- "transition-colors duration-(--duration-micro)",
2963
- "focus-visible:ring-[3px] focus-visible:ring-accent-dim",
2964
- active ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2",
2965
- disabled && "opacity-50 pointer-events-none",
2966
- className
2967
- );
2968
- if (href) {
2969
- return /* @__PURE__ */ jsx(
2970
- "a",
2971
- {
2972
- ref,
2973
- href,
2974
- "aria-current": active ? "page" : void 0,
2975
- "aria-disabled": disabled || void 0,
2976
- className: baseClass,
2977
- onClick,
2978
- ...props,
2979
- children: inner
2980
- }
2981
- );
2982
- }
2983
- return /* @__PURE__ */ jsx(
2984
- "a",
2985
- {
2986
- ref,
2987
- role: "button",
2988
- tabIndex: disabled ? -1 : 0,
2989
- "aria-current": active ? "page" : void 0,
2990
- "aria-disabled": disabled || void 0,
2991
- className: baseClass,
2992
- onClick,
2993
- onKeyDown: (e) => {
2994
- if (e.key === "Enter" || e.key === " ") {
2995
- e.preventDefault();
2996
- e.currentTarget.click();
2997
- }
2998
- },
2999
- ...props,
3000
- children: inner
3001
- }
3002
- );
3003
- });
3004
- NavItem.displayName = "NavItem";
3005
- var NavSection = forwardRef(function NavSection2({ label, action, className, children, ...props }, ref) {
3006
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-1", className), ...props, children: [
3007
- /* @__PURE__ */ jsxs("div", { className: "text-text-dim flex items-center px-2 pt-2 font-mono text-[9px] tracking-[1.4px] uppercase", children: [
3008
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: label }),
3009
- action
3010
- ] }),
3011
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[2px]", children })
3012
- ] });
3013
- });
3014
- NavSection.displayName = "NavSection";
4098
+
4099
+ // src/patterns/Sparkline/Sparkline.tsx
4100
+ import { forwardRef as forwardRef52, useMemo as useMemo5 } from "react";
4101
+ import { jsx as jsx54, jsxs as jsxs46 } from "react/jsx-runtime";
3015
4102
  function buildPath(values, w, h) {
3016
4103
  if (values.length === 0) return { line: "", area: "" };
3017
4104
  const pad = 2;
@@ -3030,7 +4117,7 @@ function buildPath(values, w, h) {
3030
4117
  )} L${pad.toFixed(2)},${(h - pad).toFixed(2)} Z`;
3031
4118
  return { line, area };
3032
4119
  }
3033
- var Sparkline = forwardRef(function Sparkline2({
4120
+ var Sparkline = forwardRef52(function Sparkline2({
3034
4121
  values,
3035
4122
  width = 160,
3036
4123
  height = 32,
@@ -3041,8 +4128,8 @@ var Sparkline = forwardRef(function Sparkline2({
3041
4128
  "aria-label": ariaLabel = "Trend",
3042
4129
  ...props
3043
4130
  }, ref) {
3044
- const { line, area } = useMemo(() => buildPath(values, width, height), [values, width, height]);
3045
- return /* @__PURE__ */ jsxs(
4131
+ const { line, area } = useMemo5(() => buildPath(values, width, height), [values, width, height]);
4132
+ return /* @__PURE__ */ jsxs46(
3046
4133
  "svg",
3047
4134
  {
3048
4135
  ref,
@@ -3054,8 +4141,8 @@ var Sparkline = forwardRef(function Sparkline2({
3054
4141
  className: cn("inline-block", className),
3055
4142
  ...props,
3056
4143
  children: [
3057
- fill && /* @__PURE__ */ jsx("path", { d: area, fill: stroke, fillOpacity: 0.16, stroke: "none" }),
3058
- /* @__PURE__ */ jsx(
4144
+ fill && /* @__PURE__ */ jsx54("path", { d: area, fill: stroke, fillOpacity: 0.16, stroke: "none" }),
4145
+ /* @__PURE__ */ jsx54(
3059
4146
  "path",
3060
4147
  {
3061
4148
  d: line,
@@ -3071,14 +4158,18 @@ var Sparkline = forwardRef(function Sparkline2({
3071
4158
  );
3072
4159
  });
3073
4160
  Sparkline.displayName = "Sparkline";
4161
+
4162
+ // src/patterns/Spinner/Spinner.tsx
4163
+ import { forwardRef as forwardRef53 } from "react";
4164
+ import { jsx as jsx55 } from "react/jsx-runtime";
3074
4165
  var sizes = {
3075
4166
  sm: { box: "h-3 w-3", border: "border-[2px]" },
3076
4167
  md: { box: "h-4 w-4", border: "border-[2px]" },
3077
4168
  lg: { box: "h-5 w-5", border: "border-[2px]" }
3078
4169
  };
3079
- var Spinner2 = forwardRef(function Spinner3({ size = "md", label = "Loading", className, ...props }, ref) {
4170
+ var Spinner2 = forwardRef53(function Spinner3({ size = "md", label = "Loading", className, ...props }, ref) {
3080
4171
  const s = sizes[size];
3081
- return /* @__PURE__ */ jsx(
4172
+ return /* @__PURE__ */ jsx55(
3082
4173
  "span",
3083
4174
  {
3084
4175
  ref,
@@ -3086,7 +4177,7 @@ var Spinner2 = forwardRef(function Spinner3({ size = "md", label = "Loading", cl
3086
4177
  "aria-label": label,
3087
4178
  className: cn("inline-block", className),
3088
4179
  ...props,
3089
- children: /* @__PURE__ */ jsx(
4180
+ children: /* @__PURE__ */ jsx55(
3090
4181
  "span",
3091
4182
  {
3092
4183
  "aria-hidden": true,
@@ -3101,6 +4192,10 @@ var Spinner2 = forwardRef(function Spinner3({ size = "md", label = "Loading", cl
3101
4192
  );
3102
4193
  });
3103
4194
  Spinner2.displayName = "Spinner";
4195
+
4196
+ // src/patterns/Stepper/Stepper.tsx
4197
+ import { forwardRef as forwardRef54, Fragment as Fragment4 } from "react";
4198
+ import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
3104
4199
  var dotBase = "h-6 w-6 rounded-full grid place-items-center text-[11px] font-mono font-semibold border";
3105
4200
  var dotStateClass = {
3106
4201
  done: "bg-accent text-on-accent border-accent",
@@ -3117,46 +4212,52 @@ function stateFor(index, current) {
3117
4212
  if (index === current) return "current";
3118
4213
  return "upcoming";
3119
4214
  }
3120
- var Stepper = forwardRef(function Stepper2({ steps, current, className, ...props }, ref) {
3121
- return /* @__PURE__ */ jsx(
3122
- "div",
4215
+ var Stepper = forwardRef54(function Stepper2({ steps, current, className, ...props }, ref) {
4216
+ return /* @__PURE__ */ jsx56(
4217
+ "ol",
3123
4218
  {
3124
4219
  ref,
3125
- role: "list",
3126
4220
  "aria-label": "Progress",
3127
- className: cn("flex w-full items-center", className),
4221
+ className: cn("m-0 flex w-full list-none items-center p-0", className),
3128
4222
  ...props,
3129
- children: steps.map((label, i) => {
4223
+ children: steps.map((step, i) => {
4224
+ const label = typeof step === "string" ? step : step.label;
4225
+ const id = typeof step === "string" ? void 0 : step.id;
3130
4226
  const state = stateFor(i, current);
3131
4227
  const connectorActive = i < current;
3132
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
3133
- /* @__PURE__ */ jsxs(
3134
- "div",
4228
+ return /* @__PURE__ */ jsxs47(Fragment4, { children: [
4229
+ /* @__PURE__ */ jsxs47(
4230
+ "li",
3135
4231
  {
3136
- role: "listitem",
3137
4232
  "aria-current": state === "current" ? "step" : void 0,
3138
4233
  className: "flex items-center gap-2",
3139
4234
  children: [
3140
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(dotBase, dotStateClass[state]), children: state === "done" ? "\u2713" : i + 1 }),
3141
- /* @__PURE__ */ jsx("span", { className: cn("text-[12px]", labelStateClass[state]), children: label })
4235
+ /* @__PURE__ */ jsx56("span", { "aria-hidden": true, className: cn(dotBase, dotStateClass[state]), children: state === "done" ? "\u2713" : i + 1 }),
4236
+ /* @__PURE__ */ jsx56("span", { className: cn("text-[12px]", labelStateClass[state]), children: label })
3142
4237
  ]
3143
4238
  }
3144
4239
  ),
3145
- i < steps.length - 1 && /* @__PURE__ */ jsx(
4240
+ i < steps.length - 1 && /* @__PURE__ */ jsx56(
3146
4241
  "span",
3147
4242
  {
3148
4243
  "aria-hidden": true,
3149
4244
  className: cn("mx-3 h-px flex-1", connectorActive ? "bg-accent" : "bg-border")
3150
4245
  }
3151
4246
  )
3152
- ] }, label);
4247
+ ] }, id ?? i);
3153
4248
  })
3154
4249
  }
3155
4250
  );
3156
4251
  });
3157
4252
  Stepper.displayName = "Stepper";
3158
- var TabsVariantContext = createContext("underline");
3159
- var tabsListStyles = cva("", {
4253
+
4254
+ // src/patterns/Tabs/Tabs.tsx
4255
+ import * as RadixTabs from "@radix-ui/react-tabs";
4256
+ import { cva as cva12 } from "class-variance-authority";
4257
+ import { createContext as createContext2, forwardRef as forwardRef55, useContext as useContext2 } from "react";
4258
+ import { jsx as jsx57 } from "react/jsx-runtime";
4259
+ var TabsVariantContext = createContext2("underline");
4260
+ var tabsListStyles = cva12("", {
3160
4261
  variants: {
3161
4262
  variant: {
3162
4263
  underline: "flex gap-6 border-b border-border",
@@ -3164,7 +4265,7 @@ var tabsListStyles = cva("", {
3164
4265
  }
3165
4266
  }
3166
4267
  });
3167
- var tabsTriggerStyles = cva(
4268
+ var tabsTriggerStyles = cva12(
3168
4269
  "cursor-pointer outline-none transition-colors duration-(--duration-micro) focus-visible:ring-[3px] focus-visible:ring-accent-dim",
3169
4270
  {
3170
4271
  variants: {
@@ -3185,8 +4286,8 @@ var tabsTriggerStyles = cva(
3185
4286
  }
3186
4287
  }
3187
4288
  );
3188
- var Tabs = forwardRef(function Tabs2({ variant = "underline", className, ...props }, ref) {
3189
- return /* @__PURE__ */ jsx(TabsVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx(
4289
+ var Tabs = forwardRef55(function Tabs2({ variant = "underline", className, ...props }, ref) {
4290
+ return /* @__PURE__ */ jsx57(TabsVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx57(
3190
4291
  RadixTabs.Root,
3191
4292
  {
3192
4293
  ref,
@@ -3196,14 +4297,14 @@ var Tabs = forwardRef(function Tabs2({ variant = "underline", className, ...prop
3196
4297
  ) });
3197
4298
  });
3198
4299
  Tabs.displayName = "Tabs";
3199
- var TabsList = forwardRef(function TabsList2({ className, ...props }, ref) {
3200
- const variant = useContext(TabsVariantContext);
3201
- return /* @__PURE__ */ jsx(RadixTabs.List, { ref, className: cn(tabsListStyles({ variant }), className), ...props });
4300
+ var TabsList = forwardRef55(function TabsList2({ className, ...props }, ref) {
4301
+ const variant = useContext2(TabsVariantContext);
4302
+ return /* @__PURE__ */ jsx57(RadixTabs.List, { ref, className: cn(tabsListStyles({ variant }), className), ...props });
3202
4303
  });
3203
4304
  TabsList.displayName = "TabsList";
3204
- var Tab = forwardRef(function Tab2({ className, ...props }, ref) {
3205
- const variant = useContext(TabsVariantContext);
3206
- return /* @__PURE__ */ jsx(
4305
+ var Tab = forwardRef55(function Tab2({ className, ...props }, ref) {
4306
+ const variant = useContext2(TabsVariantContext);
4307
+ return /* @__PURE__ */ jsx57(
3207
4308
  RadixTabs.Trigger,
3208
4309
  {
3209
4310
  ref,
@@ -3213,9 +4314,9 @@ var Tab = forwardRef(function Tab2({ className, ...props }, ref) {
3213
4314
  );
3214
4315
  });
3215
4316
  Tab.displayName = "Tab";
3216
- var TabsContent = forwardRef(
4317
+ var TabsContent = forwardRef55(
3217
4318
  function TabsContent2({ className, ...props }, ref) {
3218
- return /* @__PURE__ */ jsx(
4319
+ return /* @__PURE__ */ jsx57(
3219
4320
  RadixTabs.Content,
3220
4321
  {
3221
4322
  ref,
@@ -3229,6 +4330,10 @@ var TabsContent = forwardRef(
3229
4330
  }
3230
4331
  );
3231
4332
  TabsContent.displayName = "TabsContent";
4333
+
4334
+ // src/patterns/Timeline/Timeline.tsx
4335
+ import { forwardRef as forwardRef56 } from "react";
4336
+ import { jsx as jsx58, jsxs as jsxs48 } from "react/jsx-runtime";
3232
4337
  var ringClass = {
3233
4338
  accent: "border-accent",
3234
4339
  ok: "border-ok",
@@ -3236,8 +4341,8 @@ var ringClass = {
3236
4341
  err: "border-err",
3237
4342
  muted: "border-text-dim"
3238
4343
  };
3239
- var Timeline = forwardRef(function Timeline2({ events, className, children, ...props }, ref) {
3240
- return /* @__PURE__ */ jsx(
4344
+ var Timeline = forwardRef56(function Timeline2({ events, className, children, ...props }, ref) {
4345
+ return /* @__PURE__ */ jsx58(
3241
4346
  "ol",
3242
4347
  {
3243
4348
  ref,
@@ -3247,14 +4352,14 @@ var Timeline = forwardRef(function Timeline2({ events, className, children, ...p
3247
4352
  className
3248
4353
  ),
3249
4354
  ...props,
3250
- children: events ? events.map((e, i) => /* @__PURE__ */ jsx(TimelineItem, { tone: e.tone, time: e.time, description: e.description, children: e.title }, i)) : children
4355
+ children: events ? events.map((e, i) => /* @__PURE__ */ jsx58(TimelineItem, { tone: e.tone, time: e.time, description: e.description, children: e.title }, i)) : children
3251
4356
  }
3252
4357
  );
3253
4358
  });
3254
4359
  Timeline.displayName = "Timeline";
3255
- var TimelineItem = forwardRef(function TimelineItem2({ tone = "accent", description, time, className, children, ...props }, ref) {
3256
- return /* @__PURE__ */ jsxs("li", { ref, className: cn("relative mb-[18px] last:mb-0", className), ...props, children: [
3257
- /* @__PURE__ */ jsx(
4360
+ var TimelineItem = forwardRef56(function TimelineItem2({ tone = "accent", description, time, className, children, ...props }, ref) {
4361
+ return /* @__PURE__ */ jsxs48("li", { ref, className: cn("relative mb-[18px] last:mb-0", className), ...props, children: [
4362
+ /* @__PURE__ */ jsx58(
3258
4363
  "span",
3259
4364
  {
3260
4365
  "aria-hidden": true,
@@ -3264,14 +4369,18 @@ var TimelineItem = forwardRef(function TimelineItem2({ tone = "accent", descript
3264
4369
  )
3265
4370
  }
3266
4371
  ),
3267
- /* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium", children }),
3268
- description && /* @__PURE__ */ jsx("div", { className: "text-text-muted text-[12px]", children: description }),
3269
- time && /* @__PURE__ */ jsx("div", { className: "text-text-dim mt-[2px] font-mono text-[10px]", children: time })
4372
+ /* @__PURE__ */ jsx58("div", { className: "text-[13px] font-medium", children }),
4373
+ description && /* @__PURE__ */ jsx58("div", { className: "text-text-muted text-[12px]", children: description }),
4374
+ time && /* @__PURE__ */ jsx58("div", { className: "text-text-dim mt-[2px] font-mono text-[10px]", children: time })
3270
4375
  ] });
3271
4376
  });
3272
4377
  TimelineItem.displayName = "TimelineItem";
3273
- var Topbar = forwardRef(function Topbar2({ title, leading, actions, className, children, ...props }, ref) {
3274
- return /* @__PURE__ */ jsxs(
4378
+
4379
+ // src/patterns/Topbar/Topbar.tsx
4380
+ import { forwardRef as forwardRef57 } from "react";
4381
+ import { jsx as jsx59, jsxs as jsxs49 } from "react/jsx-runtime";
4382
+ var Topbar = forwardRef57(function Topbar2({ title, leading, actions, className, children, ...props }, ref) {
4383
+ return /* @__PURE__ */ jsxs49(
3275
4384
  "header",
3276
4385
  {
3277
4386
  ref,
@@ -3282,40 +4391,101 @@ var Topbar = forwardRef(function Topbar2({ title, leading, actions, className, c
3282
4391
  ...props,
3283
4392
  children: [
3284
4393
  leading,
3285
- title && /* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium", children: title }),
3286
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center" }),
3287
- actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: actions }),
4394
+ title && /* @__PURE__ */ jsx59("div", { className: "text-[13px] font-medium", children: title }),
4395
+ /* @__PURE__ */ jsx59("div", { className: "flex flex-1 items-center" }),
4396
+ actions && /* @__PURE__ */ jsx59("div", { className: "flex items-center gap-3", children: actions }),
3288
4397
  children
3289
4398
  ]
3290
4399
  }
3291
4400
  );
3292
4401
  });
3293
4402
  Topbar.displayName = "Topbar";
3294
- var Tree = forwardRef(function Tree2({
4403
+
4404
+ // src/patterns/Tree/Tree.tsx
4405
+ import {
4406
+ forwardRef as forwardRef58,
4407
+ useCallback as useCallback10,
4408
+ useEffect as useEffect10,
4409
+ useMemo as useMemo6,
4410
+ useRef as useRef8,
4411
+ useState as useState14
4412
+ } from "react";
4413
+ import { jsx as jsx60, jsxs as jsxs50 } from "react/jsx-runtime";
4414
+ var EMPTY_SET2 = /* @__PURE__ */ new Set();
4415
+ function flattenVisible(items, expanded, level, parentId, out) {
4416
+ for (const item of items) {
4417
+ const hasChildren = !!item.children && item.children.length > 0;
4418
+ out.push({ id: item.id, level, hasChildren, parentId });
4419
+ if (hasChildren && expanded.has(item.id)) {
4420
+ flattenVisible(item.children ?? [], expanded, level + 1, item.id, out);
4421
+ }
4422
+ }
4423
+ }
4424
+ var Tree = forwardRef58(function Tree2({
3295
4425
  items,
3296
4426
  expanded: expandedProp,
3297
4427
  defaultExpanded,
3298
4428
  onExpandedChange,
3299
- selected: selectedProp,
3300
- defaultSelected,
3301
- onSelect,
4429
+ value: valueProp,
4430
+ defaultValue,
4431
+ onValueChange,
3302
4432
  className,
4433
+ onKeyDown,
3303
4434
  ...props
3304
4435
  }, ref) {
3305
4436
  const [expanded, setExpanded] = useControllableState({
3306
- value: expandedProp instanceof Set ? expandedProp : expandedProp,
3307
- defaultValue: defaultExpanded ? new Set(defaultExpanded) : /* @__PURE__ */ new Set(),
4437
+ value: expandedProp,
4438
+ defaultValue: defaultExpanded ? new Set(defaultExpanded) : void 0,
3308
4439
  onChange: onExpandedChange
3309
4440
  });
3310
- const [selected, setSelected] = useControllableState({
3311
- value: selectedProp,
3312
- defaultValue: defaultSelected,
3313
- onChange: onSelect
4441
+ const [value, setValue] = useControllableState({
4442
+ value: valueProp,
4443
+ defaultValue,
4444
+ onChange: onValueChange
3314
4445
  });
3315
- const toggle = useCallback(
4446
+ const expandedSet = expanded ?? EMPTY_SET2;
4447
+ const flatVisible = useMemo6(() => {
4448
+ const out = [];
4449
+ flattenVisible(items, expandedSet, 1, null, out);
4450
+ return out;
4451
+ }, [items, expandedSet]);
4452
+ const [activeId, setActiveId] = useState14(null);
4453
+ useEffect10(() => {
4454
+ if (activeId && !flatVisible.some((f) => f.id === activeId)) {
4455
+ setActiveId(null);
4456
+ }
4457
+ }, [activeId, flatVisible]);
4458
+ const tabStopId = useMemo6(() => {
4459
+ if (activeId && flatVisible.some((f) => f.id === activeId)) return activeId;
4460
+ if (value && flatVisible.some((f) => f.id === value)) return value;
4461
+ return flatVisible[0]?.id ?? null;
4462
+ }, [activeId, flatVisible, value]);
4463
+ const listRef = useRef8(null);
4464
+ const setRefs = useCallback10(
4465
+ (node) => {
4466
+ listRef.current = node;
4467
+ if (typeof ref === "function") ref(node);
4468
+ else if (ref) ref.current = node;
4469
+ },
4470
+ [ref]
4471
+ );
4472
+ const focusItem = useCallback10((id) => {
4473
+ const root = listRef.current;
4474
+ if (!root) return;
4475
+ const el = root.querySelector(`[data-treeitem-id="${CSS.escape(id)}"]`);
4476
+ el?.focus();
4477
+ }, []);
4478
+ const moveActive = useCallback10(
4479
+ (id) => {
4480
+ setActiveId(id);
4481
+ queueMicrotask(() => focusItem(id));
4482
+ },
4483
+ [focusItem]
4484
+ );
4485
+ const toggle = useCallback10(
3316
4486
  (id) => {
3317
4487
  setExpanded((prev) => {
3318
- const next = new Set(prev ?? []);
4488
+ const next = new Set(prev ?? EMPTY_SET2);
3319
4489
  if (next.has(id)) next.delete(id);
3320
4490
  else next.add(id);
3321
4491
  return next;
@@ -3323,22 +4493,138 @@ var Tree = forwardRef(function Tree2({
3323
4493
  },
3324
4494
  [setExpanded]
3325
4495
  );
3326
- return /* @__PURE__ */ jsx(
4496
+ const expand = useCallback10(
4497
+ (id) => {
4498
+ setExpanded((prev) => {
4499
+ const base = prev ?? EMPTY_SET2;
4500
+ if (base.has(id)) return base;
4501
+ const next = new Set(base);
4502
+ next.add(id);
4503
+ return next;
4504
+ });
4505
+ },
4506
+ [setExpanded]
4507
+ );
4508
+ const collapse = useCallback10(
4509
+ (id) => {
4510
+ setExpanded((prev) => {
4511
+ const base = prev ?? EMPTY_SET2;
4512
+ if (!base.has(id)) return base;
4513
+ const next = new Set(base);
4514
+ next.delete(id);
4515
+ return next;
4516
+ });
4517
+ },
4518
+ [setExpanded]
4519
+ );
4520
+ const selectItem = useCallback10(
4521
+ (id) => {
4522
+ setValue(id);
4523
+ },
4524
+ [setValue]
4525
+ );
4526
+ const handleKeyDown = useCallback10(
4527
+ (e) => {
4528
+ onKeyDown?.(e);
4529
+ if (e.defaultPrevented) return;
4530
+ if (flatVisible.length === 0) return;
4531
+ const currentId = tabStopId;
4532
+ const currentIndex = currentId ? flatVisible.findIndex((f) => f.id === currentId) : -1;
4533
+ const current = currentIndex >= 0 ? flatVisible[currentIndex] : void 0;
4534
+ switch (e.key) {
4535
+ case "ArrowDown": {
4536
+ e.preventDefault();
4537
+ const next = flatVisible[Math.min(flatVisible.length - 1, currentIndex + 1)];
4538
+ if (next) moveActive(next.id);
4539
+ break;
4540
+ }
4541
+ case "ArrowUp": {
4542
+ e.preventDefault();
4543
+ const prev = flatVisible[Math.max(0, currentIndex - 1)];
4544
+ if (prev) moveActive(prev.id);
4545
+ break;
4546
+ }
4547
+ case "ArrowRight": {
4548
+ if (!current) return;
4549
+ e.preventDefault();
4550
+ if (current.hasChildren) {
4551
+ if (!expandedSet.has(current.id)) {
4552
+ expand(current.id);
4553
+ } else {
4554
+ const child = flatVisible[currentIndex + 1];
4555
+ if (child && child.parentId === current.id) moveActive(child.id);
4556
+ }
4557
+ }
4558
+ break;
4559
+ }
4560
+ case "ArrowLeft": {
4561
+ if (!current) return;
4562
+ e.preventDefault();
4563
+ if (current.hasChildren && expandedSet.has(current.id)) {
4564
+ collapse(current.id);
4565
+ } else if (current.parentId) {
4566
+ moveActive(current.parentId);
4567
+ }
4568
+ break;
4569
+ }
4570
+ case "Home": {
4571
+ e.preventDefault();
4572
+ const first = flatVisible[0];
4573
+ if (first) moveActive(first.id);
4574
+ break;
4575
+ }
4576
+ case "End": {
4577
+ e.preventDefault();
4578
+ const last = flatVisible[flatVisible.length - 1];
4579
+ if (last) moveActive(last.id);
4580
+ break;
4581
+ }
4582
+ case "Enter":
4583
+ case " ": {
4584
+ if (!current) return;
4585
+ e.preventDefault();
4586
+ selectItem(current.id);
4587
+ if (current.hasChildren) toggle(current.id);
4588
+ break;
4589
+ }
4590
+ default:
4591
+ break;
4592
+ }
4593
+ },
4594
+ [
4595
+ collapse,
4596
+ expand,
4597
+ expandedSet,
4598
+ flatVisible,
4599
+ moveActive,
4600
+ onKeyDown,
4601
+ selectItem,
4602
+ tabStopId,
4603
+ toggle
4604
+ ]
4605
+ );
4606
+ return /* @__PURE__ */ jsx60(
3327
4607
  "ul",
3328
4608
  {
3329
- ref,
4609
+ ref: setRefs,
3330
4610
  role: "tree",
3331
4611
  className: cn("flex flex-col gap-px text-[12px]", className),
4612
+ onKeyDown: handleKeyDown,
3332
4613
  ...props,
3333
- children: items.map((item) => /* @__PURE__ */ jsx(
4614
+ children: items.map((item) => /* @__PURE__ */ jsx60(
3334
4615
  TreeItemRow,
3335
4616
  {
3336
4617
  item,
3337
4618
  level: 1,
3338
- expanded: expanded ?? /* @__PURE__ */ new Set(),
3339
- selected,
3340
- onToggle: toggle,
3341
- onSelect: (id) => setSelected(id)
4619
+ expanded: expandedSet,
4620
+ selected: value,
4621
+ tabStopId,
4622
+ onFocusItem: setActiveId,
4623
+ onActivate: (id) => {
4624
+ setActiveId(id);
4625
+ selectItem(id);
4626
+ },
4627
+ onToggle: toggle
3342
4628
  },
3343
4629
  item.id
3344
4630
  ))
@@ -3346,36 +4632,37 @@ var Tree = forwardRef(function Tree2({
3346
4632
  );
3347
4633
  });
3348
4634
  Tree.displayName = "Tree";
3349
- function TreeItemRow({ item, level, expanded, selected, onToggle, onSelect }) {
4635
+ function TreeItemRow({
4636
+ item,
4637
+ level,
4638
+ expanded,
4639
+ selected,
4640
+ tabStopId,
4641
+ onFocusItem,
4642
+ onActivate,
4643
+ onToggle
4644
+ }) {
3350
4645
  const hasChildren = !!item.children && item.children.length > 0;
3351
4646
  const isExpanded = hasChildren && expanded.has(item.id);
3352
4647
  const isSelected = selected === item.id;
3353
- return /* @__PURE__ */ jsxs("li", { role: "none", children: [
3354
- /* @__PURE__ */ jsxs(
4648
+ const isTabStop = tabStopId === item.id;
4649
+ return /* @__PURE__ */ jsxs50("li", { role: "none", children: [
4650
+ /* @__PURE__ */ jsxs50(
3355
4651
  "div",
3356
4652
  {
3357
4653
  role: "treeitem",
4654
+ "data-treeitem-id": item.id,
3358
4655
  "aria-level": level,
3359
4656
  "aria-expanded": hasChildren ? isExpanded : void 0,
3360
4657
  "aria-selected": isSelected,
3361
- tabIndex: isSelected ? 0 : -1,
4658
+ tabIndex: isTabStop ? 0 : -1,
4659
+ onFocus: (e) => {
4660
+ if (e.target === e.currentTarget) onFocusItem(item.id);
4661
+ },
3362
4662
  onClick: () => {
3363
- onSelect(item.id);
4663
+ onActivate(item.id);
3364
4664
  if (hasChildren) onToggle(item.id);
3365
4665
  },
3366
- onKeyDown: (e) => {
3367
- if (e.key === "Enter" || e.key === " ") {
3368
- e.preventDefault();
3369
- onSelect(item.id);
3370
- if (hasChildren) onToggle(item.id);
3371
- } else if (e.key === "ArrowRight" && hasChildren && !isExpanded) {
3372
- e.preventDefault();
3373
- onToggle(item.id);
3374
- } else if (e.key === "ArrowLeft" && hasChildren && isExpanded) {
3375
- e.preventDefault();
3376
- onToggle(item.id);
3377
- }
3378
- },
3379
4666
  style: { paddingLeft: 4 + (level - 1) * 16 },
3380
4667
  className: cn(
3381
4668
  "flex cursor-pointer items-center gap-[6px] rounded-xs py-[5px] pr-2 outline-none",
@@ -3383,28 +4670,169 @@ function TreeItemRow({ item, level, expanded, selected, onToggle, onSelect }) {
3383
4670
  isSelected ? "bg-accent-dim text-accent" : "text-text hover:bg-panel-2"
3384
4671
  ),
3385
4672
  children: [
3386
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-text-dim grid w-3 place-items-center text-[10px]", children: hasChildren ? isExpanded ? "\u25BE" : "\u25B8" : "" }),
3387
- item.icon && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-[12px] opacity-80", children: item.icon }),
3388
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: item.label }),
4673
+ /* @__PURE__ */ jsx60("span", { "aria-hidden": true, className: "text-text-dim grid w-3 place-items-center text-[10px]", children: hasChildren ? isExpanded ? "\u25BE" : "\u25B8" : "" }),
4674
+ item.icon && /* @__PURE__ */ jsx60("span", { "aria-hidden": true, className: "text-[12px] opacity-80", children: item.icon }),
4675
+ /* @__PURE__ */ jsx60("span", { className: "flex-1 truncate", children: item.label }),
3389
4676
  item.trailing
3390
4677
  ]
3391
4678
  }
3392
4679
  ),
3393
- hasChildren && isExpanded && /* @__PURE__ */ jsx("ul", { role: "group", className: "flex flex-col gap-px", children: item.children.map((child) => /* @__PURE__ */ jsx(
4680
+ hasChildren && isExpanded && /* @__PURE__ */ jsx60("ul", { role: "group", className: "flex flex-col gap-px", children: (item.children ?? []).map((child) => /* @__PURE__ */ jsx60(
3394
4681
  TreeItemRow,
3395
4682
  {
3396
4683
  item: child,
3397
4684
  level: level + 1,
3398
4685
  expanded,
3399
4686
  selected,
3400
- onToggle,
3401
- onSelect
4687
+ tabStopId,
4688
+ onFocusItem,
4689
+ onActivate,
4690
+ onToggle
3402
4691
  },
3403
4692
  child.id
3404
4693
  )) })
3405
4694
  ] });
3406
4695
  }
3407
-
3408
- export { Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogRoot, AlertDialogTrigger, Avatar, AvatarGroup, Badge, Banner, Breadcrumbs, Button, ButtonGroup, Calendar, Card, Checkbox, Chip, Combobox, CommandPalette, ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuSeparator, ContextMenuTrigger, Crumb, DataTable, DatePicker, Dialog, DialogClose, DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTrigger, Dots, Drawer, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRoot, DropdownMenuTrigger, EmptyState, FAB, Field, FileChip, HoverCard, HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger, IconButton, Input, Kbd, MenuCheckboxItem, MenuItem, MenuSeparator, Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger, NavItem, NavSection, OTP, Pagination, Popover, PopoverAnchor, PopoverArrow, PopoverClose, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger, Progress, RadialProgress, Radio, RadioGroup, SearchInput, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectTrigger, SelectValue, Sheet, Sidebar, Skeleton, Slider, Sparkline, Spinner2 as Spinner, SplitButton, StatCard, StatusDot, Stepper, Switch, Tab, Tabs, TabsContent, TabsList, Tag, Textarea, Timeline, TimelineItem, ToastCard, ToastProvider, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger, Topbar, Tree, badgeStyles, buttonStyles, cardStyles, cn, filterCommandItems, iconButtonStyles, useControllableState, useDisclosure, useEscape, useKeyboardList, useOutsideClick, useTheme, useToast };
3409
- //# sourceMappingURL=index.js.map
4696
+ export {
4697
+ Alert,
4698
+ AlertDialog,
4699
+ AlertDialogAction,
4700
+ AlertDialogCancel,
4701
+ AlertDialogRoot,
4702
+ AlertDialogTrigger,
4703
+ Avatar,
4704
+ AvatarGroup,
4705
+ Badge,
4706
+ Banner,
4707
+ Breadcrumbs,
4708
+ Button,
4709
+ ButtonGroup,
4710
+ Calendar,
4711
+ Card,
4712
+ CardLink,
4713
+ Checkbox,
4714
+ Chip,
4715
+ Combobox,
4716
+ CommandPalette,
4717
+ ContextMenu,
4718
+ ContextMenuContent,
4719
+ ContextMenuItem,
4720
+ ContextMenuPortal,
4721
+ ContextMenuRoot,
4722
+ ContextMenuSeparator,
4723
+ ContextMenuTrigger,
4724
+ Crumb,
4725
+ DataTable,
4726
+ DatePicker,
4727
+ Dialog,
4728
+ DialogClose,
4729
+ DialogContent,
4730
+ DialogOverlay,
4731
+ DialogPortal,
4732
+ DialogRoot,
4733
+ DialogTrigger,
4734
+ Dots,
4735
+ Drawer,
4736
+ DropdownMenu,
4737
+ DropdownMenuContent,
4738
+ DropdownMenuGroup,
4739
+ DropdownMenuLabel,
4740
+ DropdownMenuPortal,
4741
+ DropdownMenuRadioGroup,
4742
+ DropdownMenuRoot,
4743
+ DropdownMenuTrigger,
4744
+ Dropzone,
4745
+ EmptyState,
4746
+ FAB,
4747
+ Field,
4748
+ FileChip,
4749
+ HoverCard,
4750
+ HoverCardContent,
4751
+ HoverCardPortal,
4752
+ HoverCardRoot,
4753
+ HoverCardTrigger,
4754
+ IconButton,
4755
+ Input,
4756
+ Kbd,
4757
+ MenuCheckboxItem,
4758
+ MenuItem,
4759
+ MenuSeparator,
4760
+ Menubar,
4761
+ MenubarContent,
4762
+ MenubarItem,
4763
+ MenubarMenu,
4764
+ MenubarSeparator,
4765
+ MenubarTrigger,
4766
+ NavBar,
4767
+ NavItem,
4768
+ NavSection,
4769
+ OTP,
4770
+ Pagination,
4771
+ Popover,
4772
+ PopoverAnchor,
4773
+ PopoverArrow,
4774
+ PopoverClose,
4775
+ PopoverContent,
4776
+ PopoverPortal,
4777
+ PopoverRoot,
4778
+ PopoverTrigger,
4779
+ Progress,
4780
+ RadialProgress,
4781
+ Radio,
4782
+ RadioGroup,
4783
+ SearchInput,
4784
+ Select,
4785
+ SelectContent,
4786
+ SelectGroup,
4787
+ SelectItem,
4788
+ SelectLabel,
4789
+ SelectRoot,
4790
+ SelectTrigger,
4791
+ SelectValue,
4792
+ Sheet,
4793
+ Sidebar,
4794
+ Skeleton,
4795
+ SkeletonGroup,
4796
+ Slider,
4797
+ Sparkline,
4798
+ Spinner2 as Spinner,
4799
+ SplitButton,
4800
+ StatCard,
4801
+ StatusDot,
4802
+ Stepper,
4803
+ Switch,
4804
+ Tab,
4805
+ Tabs,
4806
+ TabsContent,
4807
+ TabsList,
4808
+ Tag,
4809
+ Textarea,
4810
+ Timeline,
4811
+ TimelineItem,
4812
+ ToastCard,
4813
+ ToastProvider,
4814
+ Tooltip,
4815
+ TooltipArrow,
4816
+ TooltipContent,
4817
+ TooltipPortal,
4818
+ TooltipProvider,
4819
+ TooltipRoot,
4820
+ TooltipTrigger,
4821
+ Topbar,
4822
+ Tree,
4823
+ badgeStyles,
4824
+ buttonStyles,
4825
+ cardStyles,
4826
+ cn,
4827
+ filterCommandItems,
4828
+ iconButtonStyles,
4829
+ useControllableState,
4830
+ useDisclosure,
4831
+ useEscape,
4832
+ useIsomorphicLayoutEffect,
4833
+ useKeyboardList,
4834
+ useOutsideClick,
4835
+ useTheme,
4836
+ useToast
4837
+ };
3410
4838
  //# sourceMappingURL=index.js.map