@bmsuisse/ui 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -167,8 +167,8 @@ var Badge = ({ className, variant, ...props }) => /* @__PURE__ */ jsx6("div", {
167
167
 
168
168
  // src/primitives/dialog.tsx
169
169
  import * as DialogPrimitive from "@radix-ui/react-dialog";
170
- import { X } from "lucide-react";
171
- import { forwardRef as forwardRef5 } from "react";
170
+ import { XMarkIcon } from "@heroicons/react/24/outline";
171
+ import { forwardRef as forwardRef5, useCallback, useLayoutEffect, useRef } from "react";
172
172
  import { jsx as jsx7, jsxs } from "react/jsx-runtime";
173
173
  var Dialog = DialogPrimitive.Root;
174
174
  var DialogTrigger = DialogPrimitive.Trigger;
@@ -188,7 +188,7 @@ var DialogContent = forwardRef5(({ className, children, showCloseButton = true,
188
188
  {
189
189
  ref,
190
190
  className: cn(
191
- "fixed left-1/2 top-1/2 z-50 flex max-h-[85vh] w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border bg-background shadow-lg",
191
+ "fixed left-1/2 top-1/2 z-50 flex max-h-[85vh] [--dialog-divider:color-mix(in_oklab,var(--color-foreground)_12%,transparent)] dark:[--dialog-divider:var(--color-border)] w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border bg-background shadow-lg",
192
192
  className
193
193
  ),
194
194
  ...props,
@@ -200,7 +200,7 @@ var DialogContent = forwardRef5(({ className, children, showCloseButton = true,
200
200
  "data-testid": closeButtonTestId,
201
201
  className: "absolute right-4 top-4 z-20 rounded-sm opacity-70 hover:opacity-100",
202
202
  children: [
203
- /* @__PURE__ */ jsx7(X, { className: "h-4 w-4" }),
203
+ /* @__PURE__ */ jsx7(XMarkIcon, { className: "h-4 w-4" }),
204
204
  /* @__PURE__ */ jsx7("span", { className: "sr-only", children: "Close" })
205
205
  ]
206
206
  }
@@ -213,7 +213,17 @@ DialogContent.displayName = "DialogContent";
213
213
  var DialogHeader = ({
214
214
  className,
215
215
  ...props
216
- }) => /* @__PURE__ */ jsx7("div", { className: cn("flex shrink-0 flex-col gap-1.5 px-6 pt-6", className), ...props });
216
+ }) => /* @__PURE__ */ jsx7(
217
+ "div",
218
+ {
219
+ "data-slot": "dialog-header",
220
+ className: cn(
221
+ "flex shrink-0 flex-col gap-1.5 bg-background px-6 pb-3 pt-6 transition-shadow [&:has(+[data-overflow-top])]:shadow-[inset_0_-1px_0_var(--dialog-divider)]",
222
+ className
223
+ ),
224
+ ...props
225
+ }
226
+ );
217
227
  var DialogTitle = forwardRef5(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
218
228
  DialogTitle.displayName = "DialogTitle";
219
229
  var DialogDescription = forwardRef5(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
@@ -225,17 +235,77 @@ var DialogDescription = forwardRef5(({ className, ...props }, ref) => /* @__PURE
225
235
  }
226
236
  ));
227
237
  DialogDescription.displayName = "DialogDescription";
228
- var DialogBody = ({
229
- className,
230
- ...props
231
- }) => /* @__PURE__ */ jsx7("div", { className: cn("min-h-0 flex-1 overflow-y-auto px-6 pb-6", className), ...props });
238
+ function useScrollEdges(ref) {
239
+ useLayoutEffect(() => {
240
+ const el = ref.current;
241
+ if (!el) return void 0;
242
+ const update = () => {
243
+ el.toggleAttribute("data-overflow-top", el.scrollTop > 0.5);
244
+ el.toggleAttribute(
245
+ "data-overflow-bottom",
246
+ el.scrollTop + el.clientHeight < el.scrollHeight - 0.5
247
+ );
248
+ };
249
+ update();
250
+ el.addEventListener("scroll", update, { passive: true });
251
+ const resizeObserver = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(update);
252
+ const observeChildren = () => {
253
+ if (!resizeObserver) return;
254
+ resizeObserver.disconnect();
255
+ resizeObserver.observe(el);
256
+ for (const child of Array.from(el.children)) resizeObserver.observe(child);
257
+ };
258
+ observeChildren();
259
+ const mutationObserver = typeof MutationObserver === "undefined" ? void 0 : new MutationObserver(() => {
260
+ observeChildren();
261
+ update();
262
+ });
263
+ mutationObserver?.observe(el, { childList: true });
264
+ return () => {
265
+ el.removeEventListener("scroll", update);
266
+ resizeObserver?.disconnect();
267
+ mutationObserver?.disconnect();
268
+ };
269
+ }, [ref]);
270
+ }
271
+ var DialogBody = forwardRef5(
272
+ ({ className, ...props }, forwardedRef) => {
273
+ const ref = useRef(null);
274
+ useScrollEdges(ref);
275
+ const setRefs = useCallback(
276
+ (node) => {
277
+ ref.current = node;
278
+ if (typeof forwardedRef === "function") forwardedRef(node);
279
+ else if (forwardedRef) forwardedRef.current = node;
280
+ },
281
+ [forwardedRef]
282
+ );
283
+ return /* @__PURE__ */ jsx7(
284
+ "div",
285
+ {
286
+ ref: setRefs,
287
+ "data-slot": "dialog-body",
288
+ className: cn(
289
+ "min-h-0 flex-1 overflow-y-auto px-6 pb-6 pt-1 empty:pb-3 empty:pt-0 [&:empty:has(+[data-slot=dialog-footer])]:hidden [&:has(+[data-slot=dialog-footer])]:pb-1",
290
+ className
291
+ ),
292
+ ...props
293
+ }
294
+ );
295
+ }
296
+ );
297
+ DialogBody.displayName = "DialogBody";
232
298
  var DialogFooter = ({
233
299
  className,
234
300
  ...props
235
301
  }) => /* @__PURE__ */ jsx7(
236
302
  "div",
237
303
  {
238
- className: cn("-mt-6 flex shrink-0 justify-end gap-2 px-6 pb-6 pt-4", className),
304
+ "data-slot": "dialog-footer",
305
+ className: cn(
306
+ "flex shrink-0 justify-end gap-2 bg-background px-6 pb-6 pt-3 transition-shadow [[data-overflow-bottom]+&]:shadow-[inset_0_1px_0_var(--dialog-divider)] [[data-slot=dialog-body]:empty+&]:pt-1 [[data-slot=dialog-header]+&]:pt-1",
307
+ className
308
+ ),
239
309
  ...props
240
310
  }
241
311
  );
@@ -264,7 +334,7 @@ PopoverContent.displayName = "PopoverContent";
264
334
 
265
335
  // src/primitives/select.tsx
266
336
  import * as SelectPrimitive from "@radix-ui/react-select";
267
- import { Check, ChevronDown } from "lucide-react";
337
+ import { CheckIcon, ChevronDownIcon } from "@heroicons/react/24/outline";
268
338
  import { forwardRef as forwardRef7 } from "react";
269
339
  import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
270
340
  var Select = SelectPrimitive.Root;
@@ -283,7 +353,7 @@ var SelectTrigger = forwardRef7(
283
353
  ...props,
284
354
  children: [
285
355
  children,
286
- /* @__PURE__ */ jsx9(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx9(ChevronDown, { className: "h-4 w-4 opacity-50" }) })
356
+ /* @__PURE__ */ jsx9(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx9(ChevronDownIcon, { className: "h-4 w-4 opacity-50" }) })
287
357
  ]
288
358
  }
289
359
  )
@@ -314,7 +384,7 @@ var SelectItem = forwardRef7(({ className, children, ...props }, ref) => /* @__P
314
384
  ),
315
385
  ...props,
316
386
  children: [
317
- /* @__PURE__ */ jsx9("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx9(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx9(Check, { className: "h-4 w-4" }) }) }),
387
+ /* @__PURE__ */ jsx9("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx9(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx9(CheckIcon, { className: "h-4 w-4" }) }) }),
318
388
  /* @__PURE__ */ jsx9(SelectPrimitive.ItemText, { children })
319
389
  ]
320
390
  }
@@ -327,7 +397,7 @@ var Skeleton = ({ className, ...props }) => /* @__PURE__ */ jsx10("div", { class
327
397
 
328
398
  // src/primitives/checkbox.tsx
329
399
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
330
- import { Check as Check2 } from "lucide-react";
400
+ import { CheckIcon as CheckIcon2 } from "@heroicons/react/24/outline";
331
401
  import { forwardRef as forwardRef8 } from "react";
332
402
  import { jsx as jsx11 } from "react/jsx-runtime";
333
403
  var Checkbox = forwardRef8(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
@@ -339,7 +409,7 @@ var Checkbox = forwardRef8(({ className, ...props }, ref) => /* @__PURE__ */ jsx
339
409
  className
340
410
  ),
341
411
  ...props,
342
- children: /* @__PURE__ */ jsx11(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: /* @__PURE__ */ jsx11(Check2, { className: "h-3.5 w-3.5" }) })
412
+ children: /* @__PURE__ */ jsx11(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: /* @__PURE__ */ jsx11(CheckIcon2, { className: "h-3.5 w-3.5" }) })
343
413
  }
344
414
  ));
345
415
  Checkbox.displayName = "Checkbox";
@@ -521,7 +591,7 @@ TableCaption.displayName = "TableCaption";
521
591
 
522
592
  // src/primitives/dropdown-menu.tsx
523
593
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
524
- import { Check as Check3, ChevronRight, Circle } from "lucide-react";
594
+ import { CheckIcon as CheckIcon3, ChevronRightIcon } from "@heroicons/react/24/outline";
525
595
  import { forwardRef as forwardRef14 } from "react";
526
596
  import { jsx as jsx17, jsxs as jsxs4 } from "react/jsx-runtime";
527
597
  var DropdownMenu = DropdownMenuPrimitive.Root;
@@ -567,7 +637,7 @@ var DropdownMenuCheckboxItem = forwardRef14(({ className, children, checked, ...
567
637
  ),
568
638
  ...props,
569
639
  children: [
570
- /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx17(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx17(Check3, { className: "h-4 w-4" }) }) }),
640
+ /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx17(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx17(CheckIcon3, { className: "h-4 w-4" }) }) }),
571
641
  children
572
642
  ]
573
643
  }
@@ -583,7 +653,7 @@ var DropdownMenuRadioItem = forwardRef14(({ className, children, ...props }, ref
583
653
  ),
584
654
  ...props,
585
655
  children: [
586
- /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx17(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx17(Circle, { className: "h-2 w-2 fill-current" }) }) }),
656
+ /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx17(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx17("span", { className: "h-2 w-2 rounded-full bg-current" }) }) }),
587
657
  children
588
658
  ]
589
659
  }
@@ -622,7 +692,7 @@ var DropdownMenuSubTrigger = forwardRef14(({ className, children, ...props }, re
622
692
  ...props,
623
693
  children: [
624
694
  children,
625
- /* @__PURE__ */ jsx17(ChevronRight, { className: "ml-auto h-4 w-4" })
695
+ /* @__PURE__ */ jsx17(ChevronRightIcon, { className: "ml-auto h-4 w-4" })
626
696
  ]
627
697
  }
628
698
  ));
@@ -643,8 +713,8 @@ DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
643
713
  // src/primitives/sheet.tsx
644
714
  import { cva as cva3 } from "class-variance-authority";
645
715
  import * as DialogPrimitive2 from "@radix-ui/react-dialog";
646
- import { X as X2 } from "lucide-react";
647
- import { forwardRef as forwardRef15, useEffect, useRef, useState } from "react";
716
+ import { XMarkIcon as XMarkIcon2 } from "@heroicons/react/24/outline";
717
+ import { forwardRef as forwardRef15, useEffect, useRef as useRef2, useState } from "react";
648
718
  import { jsx as jsx18, jsxs as jsxs5 } from "react/jsx-runtime";
649
719
  var Sheet = DialogPrimitive2.Root;
650
720
  var SheetTrigger = DialogPrimitive2.Trigger;
@@ -695,7 +765,7 @@ var SheetContent = forwardRef15(
695
765
  }, []);
696
766
  const [dragHeight, setDragHeight] = useState(null);
697
767
  const [isDragging, setIsDragging] = useState(false);
698
- const dragStart = useRef(null);
768
+ const dragStart = useRef2(null);
699
769
  const canResize = resizable && side === "bottom";
700
770
  const onHandlePointerDown = (e) => {
701
771
  const popup = e.currentTarget.closest('[data-slot="sheet-content"]');
@@ -750,7 +820,7 @@ var SheetContent = forwardRef15(
750
820
  ),
751
821
  children,
752
822
  /* @__PURE__ */ jsxs5(DialogPrimitive2.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100", children: [
753
- /* @__PURE__ */ jsx18(X2, { className: "h-4 w-4" }),
823
+ /* @__PURE__ */ jsx18(XMarkIcon2, { className: "h-4 w-4" }),
754
824
  /* @__PURE__ */ jsx18("span", { className: "sr-only", children: "Close" })
755
825
  ] })
756
826
  ]
@@ -966,7 +1036,7 @@ var FormModal = ({
966
1036
  };
967
1037
 
968
1038
  // src/patterns/modal/ResponsivePanel.tsx
969
- import { useRef as useRef2, useState as useState6 } from "react";
1039
+ import { useRef as useRef3, useState as useState6 } from "react";
970
1040
 
971
1041
  // src/lib/useMediaQuery.ts
972
1042
  import { useEffect as useEffect2, useState as useState5 } from "react";
@@ -1022,8 +1092,8 @@ var cornerGripPosition = {
1022
1092
  function useDesktopPanelGeometry() {
1023
1093
  const [style, setStyle] = useState6(void 0);
1024
1094
  const [isDragging, setIsDragging] = useState6(false);
1025
- const drag = useRef2(null);
1026
- const lastRect = useRef2(null);
1095
+ const drag = useRef3(null);
1096
+ const lastRect = useRef3(null);
1027
1097
  const beginDrag = (mode, corner) => (e) => {
1028
1098
  const content = e.currentTarget.closest('[data-slot="dialog-content"]');
1029
1099
  if (!(content instanceof HTMLElement)) return;
@@ -1286,8 +1356,103 @@ function FormField({
1286
1356
  }
1287
1357
 
1288
1358
  // src/patterns/combobox/Combobox.tsx
1289
- import { Check as Check4, ChevronsUpDown, X as X3 } from "lucide-react";
1290
- import { useEffect as useEffect3, useMemo, useRef as useRef3, useState as useState8 } from "react";
1359
+ import { CheckIcon as CheckIcon4, ChevronUpDownIcon, XMarkIcon as XMarkIcon3 } from "@heroicons/react/24/outline";
1360
+ import { useEffect as useEffect3, useMemo, useRef as useRef4, useState as useState8 } from "react";
1361
+
1362
+ // src/lib/errorState.ts
1363
+ function toErrorInfo(error) {
1364
+ if (error == null || error === false || error === "") return void 0;
1365
+ if (typeof error === "string") return { message: error };
1366
+ if (error instanceof Error) {
1367
+ return { message: error.message || void 0, details: error.stack };
1368
+ }
1369
+ if (typeof error === "object") {
1370
+ const { title, message, details } = error;
1371
+ if (title !== void 0 || message !== void 0 || details !== void 0) return { title, message, details };
1372
+ }
1373
+ try {
1374
+ return { message: typeof error === "object" ? "Unknown error" : String(error) };
1375
+ } catch {
1376
+ return { message: "Unknown error" };
1377
+ }
1378
+ }
1379
+
1380
+ // src/patterns/error-state/ErrorState.tsx
1381
+ import { ArrowPathIcon, ExclamationTriangleIcon } from "@heroicons/react/24/outline";
1382
+ import { jsx as jsx27, jsxs as jsxs11 } from "react/jsx-runtime";
1383
+ var defaultErrorStateLabels = {
1384
+ title: "Couldn't load data",
1385
+ retry: "Retry",
1386
+ showDetails: "Show details"
1387
+ };
1388
+ var ErrorState = ({
1389
+ error,
1390
+ onRetry,
1391
+ variant = "block",
1392
+ labels,
1393
+ className,
1394
+ ...props
1395
+ }) => {
1396
+ const info = toErrorInfo(error);
1397
+ if (!info) return null;
1398
+ const l = { ...defaultErrorStateLabels, ...labels };
1399
+ const compact = variant === "compact";
1400
+ return /* @__PURE__ */ jsxs11(
1401
+ "div",
1402
+ {
1403
+ role: "alert",
1404
+ "data-testid": "error-state",
1405
+ className: cn(
1406
+ "flex gap-3 text-sm",
1407
+ compact ? "items-start rounded-md border border-destructive bg-destructive/10 p-3 text-red-800 dark:text-red-300" : "min-h-32 w-full flex-col items-center justify-center p-6 text-center",
1408
+ className
1409
+ ),
1410
+ ...props,
1411
+ children: [
1412
+ /* @__PURE__ */ jsx27(
1413
+ ExclamationTriangleIcon,
1414
+ {
1415
+ className: cn("shrink-0", compact ? "mt-0.5 h-4 w-4" : "h-8 w-8 text-destructive"),
1416
+ "aria-hidden": "true"
1417
+ }
1418
+ ),
1419
+ /* @__PURE__ */ jsxs11("div", { className: cn("flex min-w-0 flex-col gap-1", compact ? "items-start" : "items-center"), children: [
1420
+ /* @__PURE__ */ jsx27("p", { className: "font-semibold", children: info.title ?? l.title }),
1421
+ info.message ? /* @__PURE__ */ jsx27("p", { className: cn(!compact && "text-muted-foreground"), children: info.message }) : null,
1422
+ info.details ? /* @__PURE__ */ jsxs11("details", { className: "mt-1 w-full max-w-full text-left text-xs", children: [
1423
+ /* @__PURE__ */ jsx27("summary", { className: "cursor-pointer select-none underline underline-offset-2", children: l.showDetails }),
1424
+ /* @__PURE__ */ jsx27("pre", { className: "mt-1 max-h-40 overflow-auto whitespace-pre-wrap break-words rounded bg-muted p-2 text-muted-foreground", children: info.details })
1425
+ ] }) : null,
1426
+ onRetry ? /* @__PURE__ */ jsxs11(Button, { type: "button", variant: "outline", size: "sm", className: "mt-2", onClick: onRetry, children: [
1427
+ /* @__PURE__ */ jsx27(ArrowPathIcon, { className: "h-4 w-4", "aria-hidden": "true" }),
1428
+ l.retry
1429
+ ] }) : null
1430
+ ] })
1431
+ ]
1432
+ }
1433
+ );
1434
+ };
1435
+ var InlineError = ({ error, onRetry, labels, className, ...props }) => {
1436
+ const info = toErrorInfo(error);
1437
+ if (!info) return null;
1438
+ const l = { ...defaultErrorStateLabels, ...labels };
1439
+ const text = info.message ?? info.title ?? l.title;
1440
+ return /* @__PURE__ */ jsxs11(
1441
+ "span",
1442
+ {
1443
+ role: "alert",
1444
+ "data-testid": "inline-error",
1445
+ title: info.details,
1446
+ className: cn("inline-flex min-w-0 items-center gap-1.5 text-xs text-red-700 dark:text-red-300", className),
1447
+ ...props,
1448
+ children: [
1449
+ /* @__PURE__ */ jsx27(ExclamationTriangleIcon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }),
1450
+ /* @__PURE__ */ jsx27("span", { className: "truncate", children: text }),
1451
+ onRetry ? /* @__PURE__ */ jsx27("button", { type: "button", className: "shrink-0 underline underline-offset-2", onClick: onRetry, children: l.retry }) : null
1452
+ ]
1453
+ }
1454
+ );
1455
+ };
1291
1456
 
1292
1457
  // src/lib/optionGrouping.ts
1293
1458
  function groupMembers(options, group) {
@@ -1316,7 +1481,7 @@ function buildRenderChunks(visibleOptions) {
1316
1481
  }
1317
1482
 
1318
1483
  // src/lib/optionGrid.tsx
1319
- import { jsx as jsx27, jsxs as jsxs11 } from "react/jsx-runtime";
1484
+ import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
1320
1485
  function renderGridOptions({
1321
1486
  columns,
1322
1487
  options,
@@ -1327,10 +1492,10 @@ function renderGridOptions({
1327
1492
  onHover,
1328
1493
  testId
1329
1494
  }) {
1330
- return /* @__PURE__ */ jsxs11(Table, { className: "text-sm", children: [
1331
- /* @__PURE__ */ jsx27(TableHeader, { children: /* @__PURE__ */ jsxs11(TableRow, { className: "hover:bg-transparent", children: [
1332
- multiple && /* @__PURE__ */ jsx27(TableHead, { className: "sticky top-0 z-10 w-6 bg-muted" }),
1333
- columns.map((column) => /* @__PURE__ */ jsx27(
1495
+ return /* @__PURE__ */ jsxs12(Table, { className: "text-sm", children: [
1496
+ /* @__PURE__ */ jsx28(TableHeader, { children: /* @__PURE__ */ jsxs12(TableRow, { className: "hover:bg-transparent", children: [
1497
+ multiple && /* @__PURE__ */ jsx28(TableHead, { className: "sticky top-0 z-10 w-6 bg-muted" }),
1498
+ columns.map((column) => /* @__PURE__ */ jsx28(
1334
1499
  TableHead,
1335
1500
  {
1336
1501
  className: cn("sticky top-0 z-10 whitespace-nowrap bg-muted text-xs", column.className),
@@ -1339,10 +1504,10 @@ function renderGridOptions({
1339
1504
  column.key
1340
1505
  ))
1341
1506
  ] }) }),
1342
- /* @__PURE__ */ jsx27(TableBody, { children: options.map((option, index) => {
1507
+ /* @__PURE__ */ jsx28(TableBody, { children: options.map((option, index) => {
1343
1508
  const selected = isSelected(option);
1344
1509
  const active = index === activeIndex;
1345
- return /* @__PURE__ */ jsxs11(
1510
+ return /* @__PURE__ */ jsxs12(
1346
1511
  TableRow,
1347
1512
  {
1348
1513
  role: "option",
@@ -1366,7 +1531,7 @@ function renderGridOptions({
1366
1531
  option.disabled && "pointer-events-none opacity-50"
1367
1532
  ),
1368
1533
  children: [
1369
- multiple && /* @__PURE__ */ jsx27(TableCell, { className: "w-6", children: /* @__PURE__ */ jsx27(
1534
+ multiple && /* @__PURE__ */ jsx28(TableCell, { className: "w-6", children: /* @__PURE__ */ jsx28(
1370
1535
  "input",
1371
1536
  {
1372
1537
  type: "checkbox",
@@ -1376,7 +1541,7 @@ function renderGridOptions({
1376
1541
  className: "pointer-events-none h-3.5 w-3.5 shrink-0 accent-primary"
1377
1542
  }
1378
1543
  ) }),
1379
- columns.map((column) => /* @__PURE__ */ jsx27(TableCell, { className: cn("truncate", column.className), children: column.key === "label" ? option.label : option.data?.[column.key] }, column.key))
1544
+ columns.map((column) => /* @__PURE__ */ jsx28(TableCell, { className: cn("truncate", column.className), children: column.key === "label" ? option.label : option.data?.[column.key] }, column.key))
1380
1545
  ]
1381
1546
  },
1382
1547
  option.value
@@ -1386,7 +1551,7 @@ function renderGridOptions({
1386
1551
  }
1387
1552
 
1388
1553
  // src/patterns/combobox/Combobox.tsx
1389
- import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
1554
+ import { jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
1390
1555
  function resolveGroupTriggerLabel(options, selectedValues, groupLabel) {
1391
1556
  const selectedSet = new Set(selectedValues);
1392
1557
  const groupsPresent = Array.from(
@@ -1415,6 +1580,8 @@ function Combobox(props) {
1415
1580
  disabled,
1416
1581
  loading = false,
1417
1582
  loadingMessage = "Loading\u2026",
1583
+ error,
1584
+ onRetry,
1418
1585
  clearable = true,
1419
1586
  className,
1420
1587
  id,
@@ -1425,10 +1592,11 @@ function Combobox(props) {
1425
1592
  columns
1426
1593
  } = props;
1427
1594
  const testId = props["data-testid"];
1595
+ const hasError = toErrorInfo(error) !== void 0;
1428
1596
  const [open, setOpen] = useState8(false);
1429
1597
  const [search, setSearch] = useState8("");
1430
1598
  const [activeIndex, setActiveIndex] = useState8(0);
1431
- const inputRef = useRef3(null);
1599
+ const inputRef = useRef4(null);
1432
1600
  const selectedValues = useMemo(
1433
1601
  () => props.multiple ? props.value : props.value ? [props.value] : [],
1434
1602
  [props.multiple, props.value]
@@ -1466,6 +1634,7 @@ function Combobox(props) {
1466
1634
  setOpen(false);
1467
1635
  }
1468
1636
  function handleKeyDown(event) {
1637
+ if (hasError) return;
1469
1638
  if (event.key === "ArrowDown") {
1470
1639
  event.preventDefault();
1471
1640
  setActiveIndex((i) => Math.min(i + 1, visibleOptions.length - 1));
@@ -1490,7 +1659,7 @@ function Combobox(props) {
1490
1659
  function renderOption({ option, index }) {
1491
1660
  const isSelected = selectedValues.includes(option.value);
1492
1661
  const isActive = index === activeIndex;
1493
- return /* @__PURE__ */ jsxs12(
1662
+ return /* @__PURE__ */ jsxs13(
1494
1663
  "button",
1495
1664
  {
1496
1665
  type: "button",
@@ -1506,7 +1675,7 @@ function Combobox(props) {
1506
1675
  isActive && "bg-accent text-accent-foreground"
1507
1676
  ),
1508
1677
  children: [
1509
- props.multiple ? /* @__PURE__ */ jsx28(
1678
+ props.multiple ? /* @__PURE__ */ jsx29(
1510
1679
  "input",
1511
1680
  {
1512
1681
  type: "checkbox",
@@ -1515,15 +1684,15 @@ function Combobox(props) {
1515
1684
  tabIndex: -1,
1516
1685
  className: "pointer-events-none h-3.5 w-3.5 shrink-0 accent-primary"
1517
1686
  }
1518
- ) : /* @__PURE__ */ jsx28(Check4, { className: cn("h-4 w-4 shrink-0", isSelected ? "opacity-100" : "opacity-0") }),
1519
- /* @__PURE__ */ jsx28("span", { className: "truncate", children: option.label })
1687
+ ) : /* @__PURE__ */ jsx29(CheckIcon4, { className: cn("h-4 w-4 shrink-0", isSelected ? "opacity-100" : "opacity-0") }),
1688
+ /* @__PURE__ */ jsx29("span", { className: "truncate", children: option.label })
1520
1689
  ]
1521
1690
  },
1522
1691
  option.value
1523
1692
  );
1524
1693
  }
1525
- return /* @__PURE__ */ jsxs12(Popover, { open, onOpenChange: setOpen, children: [
1526
- /* @__PURE__ */ jsx28(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(
1694
+ return /* @__PURE__ */ jsxs13(Popover, { open, onOpenChange: setOpen, children: [
1695
+ /* @__PURE__ */ jsx29(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs13(
1527
1696
  Button,
1528
1697
  {
1529
1698
  id,
@@ -1532,16 +1701,18 @@ function Combobox(props) {
1532
1701
  variant: "outline",
1533
1702
  role: "combobox",
1534
1703
  "aria-expanded": open,
1704
+ "aria-invalid": hasError || void 0,
1535
1705
  disabled: disabled || loading,
1536
1706
  className: cn(
1537
1707
  "w-full justify-between font-normal",
1708
+ hasError && "border-destructive",
1538
1709
  (selectedOptions.length === 0 || loading) && "text-muted-foreground",
1539
1710
  className
1540
1711
  ),
1541
1712
  children: [
1542
- /* @__PURE__ */ jsx28("span", { className: "truncate", children: triggerLabel }),
1543
- /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1", children: [
1544
- clearable && !loading && selectedValues.length > 0 ? /* @__PURE__ */ jsx28(
1713
+ /* @__PURE__ */ jsx29("span", { className: "truncate", children: triggerLabel }),
1714
+ /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-1", children: [
1715
+ clearable && !loading && selectedValues.length > 0 ? /* @__PURE__ */ jsx29(
1545
1716
  "span",
1546
1717
  {
1547
1718
  role: "button",
@@ -1556,15 +1727,15 @@ function Combobox(props) {
1556
1727
  props.onChange(null);
1557
1728
  }
1558
1729
  },
1559
- children: /* @__PURE__ */ jsx28(X3, { className: "h-3.5 w-3.5" })
1730
+ children: /* @__PURE__ */ jsx29(XMarkIcon3, { className: "h-3.5 w-3.5" })
1560
1731
  }
1561
1732
  ) : null,
1562
- /* @__PURE__ */ jsx28(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50", "aria-hidden": "true" })
1733
+ /* @__PURE__ */ jsx29(ChevronUpDownIcon, { className: "h-4 w-4 shrink-0 opacity-50", "aria-hidden": "true" })
1563
1734
  ] })
1564
1735
  ]
1565
1736
  }
1566
1737
  ) }),
1567
- /* @__PURE__ */ jsx28(
1738
+ /* @__PURE__ */ jsx29(
1568
1739
  PopoverContent,
1569
1740
  {
1570
1741
  align: "start",
@@ -1574,8 +1745,8 @@ function Combobox(props) {
1574
1745
  columns && "w-max min-w-[var(--radix-popover-trigger-width)] max-w-[min(40rem,90vw)]"
1575
1746
  ),
1576
1747
  onOpenAutoFocus: (event) => event.preventDefault(),
1577
- children: /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2", children: [
1578
- /* @__PURE__ */ jsx28(
1748
+ children: /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
1749
+ /* @__PURE__ */ jsx29(
1579
1750
  Input,
1580
1751
  {
1581
1752
  ref: inputRef,
@@ -1589,7 +1760,7 @@ function Combobox(props) {
1589
1760
  "aria-label": searchPlaceholder
1590
1761
  }
1591
1762
  ),
1592
- /* @__PURE__ */ jsx28("div", { role: "listbox", className: cn("max-h-60 overflow-y-auto", !columns && "flex flex-col gap-0.5"), children: visibleOptions.length === 0 ? /* @__PURE__ */ jsx28("p", { className: "py-2 text-center text-sm text-muted-foreground", children: emptyMessage }) : columns ? renderGridOptions({
1763
+ /* @__PURE__ */ jsx29("div", { role: hasError ? void 0 : "listbox", className: cn("max-h-60 overflow-y-auto", !columns && "flex flex-col gap-0.5"), children: hasError ? /* @__PURE__ */ jsx29("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx29(InlineError, { error, onRetry }) }) : visibleOptions.length === 0 ? /* @__PURE__ */ jsx29("p", { className: "py-2 text-center text-sm text-muted-foreground", children: emptyMessage }) : columns ? renderGridOptions({
1593
1764
  columns,
1594
1765
  options: visibleOptions,
1595
1766
  activeIndex,
@@ -1609,14 +1780,14 @@ function Combobox(props) {
1609
1780
  // lives on this wrapper's `pt-1`, not on the header itself -- a margin on
1610
1781
  // the sticky element would travel with it once stuck, leaving a gap at the
1611
1782
  // scrollport's top that the row behind it shows through.
1612
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-0.5 pt-1 first:pt-0", children: [
1613
- /* @__PURE__ */ jsxs12(
1783
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-0.5 pt-1 first:pt-0", children: [
1784
+ /* @__PURE__ */ jsxs13(
1614
1785
  "div",
1615
1786
  {
1616
1787
  "data-group-header": true,
1617
1788
  className: "sticky top-0 z-10 flex items-center gap-2 rounded-sm bg-muted px-2 py-1.5 text-sm font-semibold text-foreground",
1618
1789
  children: [
1619
- props.multiple ? /* @__PURE__ */ jsx28(
1790
+ props.multiple ? /* @__PURE__ */ jsx29(
1620
1791
  "input",
1621
1792
  {
1622
1793
  type: "checkbox",
@@ -1630,7 +1801,7 @@ function Combobox(props) {
1630
1801
  "aria-label": `Select all of ${groupLabel(chunk.group)}`
1631
1802
  }
1632
1803
  ) : null,
1633
- /* @__PURE__ */ jsx28("span", { className: "truncate", children: groupLabel(chunk.group) })
1804
+ /* @__PURE__ */ jsx29("span", { className: "truncate", children: groupLabel(chunk.group) })
1634
1805
  ]
1635
1806
  }
1636
1807
  ),
@@ -1645,9 +1816,9 @@ function Combobox(props) {
1645
1816
  }
1646
1817
 
1647
1818
  // src/patterns/tag-combobox/TagCombobox.tsx
1648
- import { X as X4 } from "lucide-react";
1649
- import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState9 } from "react";
1650
- import { jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
1819
+ import { XMarkIcon as XMarkIcon4 } from "@heroicons/react/24/outline";
1820
+ import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState9 } from "react";
1821
+ import { jsx as jsx30, jsxs as jsxs14 } from "react/jsx-runtime";
1651
1822
  function TagCombobox({
1652
1823
  options,
1653
1824
  value,
@@ -1657,6 +1828,8 @@ function TagCombobox({
1657
1828
  disabled,
1658
1829
  loading = false,
1659
1830
  loadingMessage = "Loading\u2026",
1831
+ error,
1832
+ onRetry,
1660
1833
  className,
1661
1834
  id,
1662
1835
  onSearchChange,
@@ -1669,8 +1842,8 @@ function TagCombobox({
1669
1842
  const [open, setOpen] = useState9(false);
1670
1843
  const [search, setSearch] = useState9("");
1671
1844
  const [activeIndex, setActiveIndex] = useState9(0);
1672
- const inputRef = useRef4(null);
1673
- const fieldRef = useRef4(null);
1845
+ const inputRef = useRef5(null);
1846
+ const fieldRef = useRef5(null);
1674
1847
  const selectedOptions = useMemo2(
1675
1848
  () => value.map((v) => options.find((o) => o.value === v) ?? { value: v, label: v }),
1676
1849
  [options, value]
@@ -1716,6 +1889,7 @@ function TagCombobox({
1716
1889
  onChange(next);
1717
1890
  inputRef.current?.focus();
1718
1891
  }
1892
+ const hasError = toErrorInfo(error) !== void 0;
1719
1893
  function handleKeyDown(event) {
1720
1894
  if (event.key === "ArrowDown") {
1721
1895
  event.preventDefault();
@@ -1727,7 +1901,7 @@ function TagCombobox({
1727
1901
  } else if (event.key === "Enter") {
1728
1902
  event.preventDefault();
1729
1903
  const option = visibleOptions[activeIndex];
1730
- if (option) toggleOption(option);
1904
+ if (option && !hasError) toggleOption(option);
1731
1905
  } else if (event.key === "Escape") {
1732
1906
  setOpen(false);
1733
1907
  } else if (event.key === "Backspace" && search === "") {
@@ -1738,7 +1912,7 @@ function TagCombobox({
1738
1912
  function renderOption({ option, index }) {
1739
1913
  const isSelected = value.includes(option.value);
1740
1914
  const isActive = index === activeIndex;
1741
- return /* @__PURE__ */ jsxs13(
1915
+ return /* @__PURE__ */ jsxs14(
1742
1916
  "button",
1743
1917
  {
1744
1918
  type: "button",
@@ -1754,7 +1928,7 @@ function TagCombobox({
1754
1928
  isActive && "bg-accent text-accent-foreground"
1755
1929
  ),
1756
1930
  children: [
1757
- /* @__PURE__ */ jsx29(
1931
+ /* @__PURE__ */ jsx30(
1758
1932
  "input",
1759
1933
  {
1760
1934
  type: "checkbox",
@@ -1764,14 +1938,14 @@ function TagCombobox({
1764
1938
  className: "pointer-events-none h-3.5 w-3.5 shrink-0 accent-primary"
1765
1939
  }
1766
1940
  ),
1767
- /* @__PURE__ */ jsx29("span", { className: "truncate", children: option.label })
1941
+ /* @__PURE__ */ jsx30("span", { className: "truncate", children: option.label })
1768
1942
  ]
1769
1943
  },
1770
1944
  option.value
1771
1945
  );
1772
1946
  }
1773
- return /* @__PURE__ */ jsxs13(Popover, { open, onOpenChange: setOpen, children: [
1774
- /* @__PURE__ */ jsx29(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs13(
1947
+ return /* @__PURE__ */ jsxs14(Popover, { open, onOpenChange: setOpen, children: [
1948
+ /* @__PURE__ */ jsx30(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs14(
1775
1949
  "div",
1776
1950
  {
1777
1951
  ref: fieldRef,
@@ -1789,13 +1963,13 @@ function TagCombobox({
1789
1963
  if (!disabled) inputRef.current?.focus();
1790
1964
  },
1791
1965
  children: [
1792
- selectedOptions.map((option) => /* @__PURE__ */ jsxs13(
1966
+ selectedOptions.map((option) => /* @__PURE__ */ jsxs14(
1793
1967
  "span",
1794
1968
  {
1795
1969
  className: "inline-flex items-center gap-1 rounded-full bg-muted py-0.5 pr-1 pl-2.5 text-xs font-medium text-muted-foreground",
1796
1970
  children: [
1797
- /* @__PURE__ */ jsx29("span", { className: "max-w-48 truncate", children: option.label }),
1798
- !disabled && /* @__PURE__ */ jsx29(
1971
+ /* @__PURE__ */ jsx30("span", { className: "max-w-48 truncate", children: option.label }),
1972
+ !disabled && /* @__PURE__ */ jsx30(
1799
1973
  "button",
1800
1974
  {
1801
1975
  type: "button",
@@ -1805,14 +1979,14 @@ function TagCombobox({
1805
1979
  event.stopPropagation();
1806
1980
  removeValue(option.value);
1807
1981
  },
1808
- children: /* @__PURE__ */ jsx29(X4, { className: "h-3 w-3" })
1982
+ children: /* @__PURE__ */ jsx30(XMarkIcon4, { className: "h-3 w-3" })
1809
1983
  }
1810
1984
  )
1811
1985
  ]
1812
1986
  },
1813
1987
  option.value
1814
1988
  )),
1815
- /* @__PURE__ */ jsx29(
1989
+ /* @__PURE__ */ jsx30(
1816
1990
  "input",
1817
1991
  {
1818
1992
  ref: inputRef,
@@ -1830,7 +2004,7 @@ function TagCombobox({
1830
2004
  ]
1831
2005
  }
1832
2006
  ) }),
1833
- /* @__PURE__ */ jsx29(
2007
+ /* @__PURE__ */ jsx30(
1834
2008
  PopoverContent,
1835
2009
  {
1836
2010
  align: "start",
@@ -1844,7 +2018,7 @@ function TagCombobox({
1844
2018
  onInteractOutside: (event) => {
1845
2019
  if (fieldRef.current?.contains(event.target)) event.preventDefault();
1846
2020
  },
1847
- children: /* @__PURE__ */ jsx29("div", { role: "listbox", className: cn("max-h-60 overflow-y-auto", !columns && "flex flex-col gap-0.5"), children: loading ? /* @__PURE__ */ jsx29("p", { className: "py-2 text-center text-sm text-muted-foreground", children: loadingMessage }) : visibleOptions.length === 0 ? /* @__PURE__ */ jsx29("p", { className: "py-2 text-center text-sm text-muted-foreground", children: emptyMessage }) : columns ? renderGridOptions({
2021
+ children: /* @__PURE__ */ jsx30("div", { role: hasError ? void 0 : "listbox", className: cn("max-h-60 overflow-y-auto", !columns && "flex flex-col gap-0.5"), children: loading ? /* @__PURE__ */ jsx30("p", { className: "py-2 text-center text-sm text-muted-foreground", children: loadingMessage }) : hasError ? /* @__PURE__ */ jsx30("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx30(InlineError, { error, onRetry }) }) : visibleOptions.length === 0 ? /* @__PURE__ */ jsx30("p", { className: "py-2 text-center text-sm text-muted-foreground", children: emptyMessage }) : columns ? renderGridOptions({
1848
2022
  columns,
1849
2023
  options: visibleOptions,
1850
2024
  activeIndex,
@@ -1863,14 +2037,14 @@ function TagCombobox({
1863
2037
  // past its first row. Spacing above a group lives on this wrapper's
1864
2038
  // `pt-1`/`first:pt-0`, not on the header itself -- see `Combobox`'s own
1865
2039
  // identical structure for why both of these matter.
1866
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-0.5 pt-1 first:pt-0", children: [
1867
- /* @__PURE__ */ jsxs13(
2040
+ /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-0.5 pt-1 first:pt-0", children: [
2041
+ /* @__PURE__ */ jsxs14(
1868
2042
  "div",
1869
2043
  {
1870
2044
  "data-group-header": true,
1871
2045
  className: "sticky top-0 z-10 flex items-center gap-2 rounded-sm bg-muted px-2 py-1.5 text-sm font-semibold text-foreground",
1872
2046
  children: [
1873
- /* @__PURE__ */ jsx29(
2047
+ /* @__PURE__ */ jsx30(
1874
2048
  "input",
1875
2049
  {
1876
2050
  type: "checkbox",
@@ -1884,7 +2058,7 @@ function TagCombobox({
1884
2058
  "aria-label": `Select all of ${groupLabel(chunk.group)}`
1885
2059
  }
1886
2060
  ),
1887
- /* @__PURE__ */ jsx29("span", { className: "truncate", children: groupLabel(chunk.group) })
2061
+ /* @__PURE__ */ jsx30("span", { className: "truncate", children: groupLabel(chunk.group) })
1888
2062
  ]
1889
2063
  }
1890
2064
  ),
@@ -1898,8 +2072,13 @@ function TagCombobox({
1898
2072
  }
1899
2073
 
1900
2074
  // src/patterns/alert-box/AlertBox.tsx
1901
- import { AlertCircle, AlertTriangle, CheckCircle2, Info } from "lucide-react";
1902
- import { jsx as jsx30, jsxs as jsxs14 } from "react/jsx-runtime";
2075
+ import {
2076
+ CheckCircleIcon,
2077
+ ExclamationCircleIcon,
2078
+ ExclamationTriangleIcon as ExclamationTriangleIcon2,
2079
+ InformationCircleIcon
2080
+ } from "@heroicons/react/24/outline";
2081
+ import { jsx as jsx31, jsxs as jsxs15 } from "react/jsx-runtime";
1903
2082
  var variantStyles = {
1904
2083
  error: "border-destructive bg-destructive/10 text-red-800 dark:text-red-300",
1905
2084
  warning: "border-amber-500 bg-amber-500/10 text-amber-900 dark:text-amber-200",
@@ -1907,24 +2086,24 @@ var variantStyles = {
1907
2086
  success: "border-emerald-500 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"
1908
2087
  };
1909
2088
  var defaultIcons = {
1910
- error: /* @__PURE__ */ jsx30(AlertCircle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
1911
- warning: /* @__PURE__ */ jsx30(AlertTriangle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
1912
- info: /* @__PURE__ */ jsx30(Info, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
1913
- success: /* @__PURE__ */ jsx30(CheckCircle2, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" })
2089
+ error: /* @__PURE__ */ jsx31(ExclamationCircleIcon, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
2090
+ warning: /* @__PURE__ */ jsx31(ExclamationTriangleIcon2, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
2091
+ info: /* @__PURE__ */ jsx31(InformationCircleIcon, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
2092
+ success: /* @__PURE__ */ jsx31(CheckCircleIcon, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" })
1914
2093
  };
1915
2094
  var AlertBox = ({ variant, title, children, className, icon }) => {
1916
2095
  const resolvedIcon = icon === void 0 ? defaultIcons[variant] : icon;
1917
- return /* @__PURE__ */ jsx30("div", { className: cn("rounded-md border p-3 text-sm", variantStyles[variant], className), children: /* @__PURE__ */ jsxs14("div", { className: "flex flex-row items-start gap-2", children: [
1918
- resolvedIcon != null && /* @__PURE__ */ jsx30("span", { className: "mt-0.5 shrink-0", children: resolvedIcon }),
1919
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
1920
- title && /* @__PURE__ */ jsx30("p", { className: "font-bold", children: title }),
1921
- /* @__PURE__ */ jsx30("div", { children })
2096
+ return /* @__PURE__ */ jsx31("div", { className: cn("rounded-md border p-3 text-sm", variantStyles[variant], className), children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-row items-start gap-2", children: [
2097
+ resolvedIcon != null && /* @__PURE__ */ jsx31("span", { className: "mt-0.5 shrink-0", children: resolvedIcon }),
2098
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-1", children: [
2099
+ title && /* @__PURE__ */ jsx31("p", { className: "font-bold", children: title }),
2100
+ /* @__PURE__ */ jsx31("div", { children })
1922
2101
  ] })
1923
2102
  ] }) });
1924
2103
  };
1925
2104
 
1926
2105
  // src/patterns/status-badge/StatusBadge.tsx
1927
- import { jsx as jsx31 } from "react/jsx-runtime";
2106
+ import { jsx as jsx32 } from "react/jsx-runtime";
1928
2107
  var TONE_CLASSES = {
1929
2108
  success: "border-transparent bg-emerald-500/15 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300",
1930
2109
  warning: "border-transparent bg-amber-500/15 text-amber-800 dark:bg-amber-500/20 dark:text-amber-300",
@@ -1971,11 +2150,11 @@ function resolveTone(status, tone, toneMap) {
1971
2150
  var StatusBadge = ({ status, label, tone, toneMap, className, ...props }) => {
1972
2151
  const resolvedTone = resolveTone(status, tone, toneMap);
1973
2152
  const displayLabel = label ?? deriveLabel(status);
1974
- return /* @__PURE__ */ jsx31(Badge, { variant: "outline", className: cn(TONE_CLASSES[resolvedTone], className), ...props, children: displayLabel });
2153
+ return /* @__PURE__ */ jsx32(Badge, { variant: "outline", className: cn(TONE_CLASSES[resolvedTone], className), ...props, children: displayLabel });
1975
2154
  };
1976
2155
 
1977
2156
  // src/patterns/button-group/ButtonGroup.tsx
1978
- import { jsx as jsx32, jsxs as jsxs15 } from "react/jsx-runtime";
2157
+ import { jsx as jsx33, jsxs as jsxs16 } from "react/jsx-runtime";
1979
2158
  function ButtonGroup({
1980
2159
  options,
1981
2160
  value,
@@ -1985,10 +2164,10 @@ function ButtonGroup({
1985
2164
  className,
1986
2165
  ...props
1987
2166
  }) {
1988
- return /* @__PURE__ */ jsx32("div", { role: "group", "aria-label": props["aria-label"], className: cn("inline-flex", className), "data-testid": props["data-testid"], children: options.map((option, index) => {
2167
+ return /* @__PURE__ */ jsx33("div", { role: "group", "aria-label": props["aria-label"], className: cn("inline-flex", className), "data-testid": props["data-testid"], children: options.map((option, index) => {
1989
2168
  const selected = option.value === value;
1990
2169
  const Icon2 = option.icon;
1991
- return /* @__PURE__ */ jsxs15(
2170
+ return /* @__PURE__ */ jsxs16(
1992
2171
  Button,
1993
2172
  {
1994
2173
  type: "button",
@@ -2006,7 +2185,7 @@ function ButtonGroup({
2006
2185
  index > 0 && "-ml-px"
2007
2186
  ),
2008
2187
  children: [
2009
- Icon2 && /* @__PURE__ */ jsx32(Icon2, { className: "h-4 w-4" }),
2188
+ Icon2 && /* @__PURE__ */ jsx33(Icon2, { className: "h-4 w-4" }),
2010
2189
  option.label
2011
2190
  ]
2012
2191
  },
@@ -2017,8 +2196,8 @@ function ButtonGroup({
2017
2196
 
2018
2197
  // src/patterns/loading-spinner/LoadingSpinner.tsx
2019
2198
  import { cva as cva4 } from "class-variance-authority";
2020
- import { Loader2 } from "lucide-react";
2021
- import { jsx as jsx33, jsxs as jsxs16 } from "react/jsx-runtime";
2199
+ import { ArrowPathIcon as ArrowPathIcon2 } from "@heroicons/react/24/outline";
2200
+ import { jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
2022
2201
  var loadingSpinnerIconVariants = cva4("animate-spin text-muted-foreground", {
2023
2202
  variants: {
2024
2203
  size: {
@@ -2036,75 +2215,167 @@ var LoadingSpinner = ({
2036
2215
  label,
2037
2216
  className,
2038
2217
  ...props
2039
- }) => /* @__PURE__ */ jsxs16("span", { role: "status", className: cn("inline-flex items-center gap-2", className), ...props, children: [
2040
- /* @__PURE__ */ jsx33(Loader2, { className: cn(loadingSpinnerIconVariants({ size })), "aria-hidden": "true" }),
2041
- label ? /* @__PURE__ */ jsx33("span", { children: label }) : null
2218
+ }) => /* @__PURE__ */ jsxs17("span", { role: "status", className: cn("inline-flex items-center gap-2", className), ...props, children: [
2219
+ /* @__PURE__ */ jsx34(ArrowPathIcon2, { className: cn(loadingSpinnerIconVariants({ size })), "aria-hidden": "true" }),
2220
+ label ? /* @__PURE__ */ jsx34("span", { children: label }) : null
2042
2221
  ] });
2043
2222
  var LoadingOverlay = ({
2044
2223
  size = "lg",
2045
2224
  label,
2046
2225
  className,
2047
2226
  ...props
2048
- }) => /* @__PURE__ */ jsx33(
2227
+ }) => /* @__PURE__ */ jsx34(
2049
2228
  "div",
2050
2229
  {
2051
2230
  className: cn("flex h-full min-h-32 w-full items-center justify-center", className),
2052
2231
  ...props,
2053
- children: /* @__PURE__ */ jsx33(LoadingSpinner, { size, label })
2232
+ children: /* @__PURE__ */ jsx34(LoadingSpinner, { size, label })
2054
2233
  }
2055
2234
  );
2056
2235
 
2236
+ // src/patterns/loading-spinner/LoadingState.tsx
2237
+ import { useEffect as useEffect5, useState as useState10 } from "react";
2238
+ import { jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
2239
+ function useDelayedFlag(active, delayMs = 150) {
2240
+ const [shown, setShown] = useState10(false);
2241
+ useEffect5(() => {
2242
+ if (!active) {
2243
+ setShown(false);
2244
+ return;
2245
+ }
2246
+ if (delayMs <= 0) {
2247
+ setShown(true);
2248
+ return;
2249
+ }
2250
+ const timer = setTimeout(() => setShown(true), delayMs);
2251
+ return () => clearTimeout(timer);
2252
+ }, [active, delayMs]);
2253
+ return active && (delayMs <= 0 || shown);
2254
+ }
2255
+ var LoadingState = ({
2256
+ variant = "skeleton",
2257
+ lines = 3,
2258
+ label = "Loading\u2026",
2259
+ delayMs = 150,
2260
+ className,
2261
+ ...props
2262
+ }) => {
2263
+ const visible = useDelayedFlag(true, delayMs);
2264
+ if (variant === "spinner") {
2265
+ return /* @__PURE__ */ jsx35("div", { "data-testid": "loading-state", "aria-busy": "true", className: cn(!visible && "invisible", className), ...props, children: /* @__PURE__ */ jsx35(LoadingOverlay, { label }) });
2266
+ }
2267
+ return /* @__PURE__ */ jsxs18(
2268
+ "div",
2269
+ {
2270
+ role: "status",
2271
+ "aria-busy": "true",
2272
+ "data-testid": "loading-state",
2273
+ className: cn("flex w-full flex-col gap-2 p-1", !visible && "invisible", className),
2274
+ ...props,
2275
+ children: [
2276
+ /* @__PURE__ */ jsx35("span", { className: "sr-only", children: label }),
2277
+ Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx35(Skeleton, { "aria-hidden": "true", className: cn("h-4", i === lines - 1 && lines > 1 ? "w-2/3" : "w-full") }, i))
2278
+ ]
2279
+ }
2280
+ );
2281
+ };
2282
+ var RefreshBar = ({ active, className }) => active ? /* @__PURE__ */ jsx35(
2283
+ "div",
2284
+ {
2285
+ role: "progressbar",
2286
+ "aria-label": "Refreshing",
2287
+ "data-testid": "refresh-bar",
2288
+ className: cn("absolute inset-x-0 top-0 z-30 h-0.5 overflow-hidden bg-muted", className),
2289
+ children: /* @__PURE__ */ jsx35("div", { className: "h-full w-1/3 animate-pulse bg-primary motion-reduce:animate-none" })
2290
+ }
2291
+ ) : null;
2292
+
2293
+ // src/patterns/async-boundary/AsyncBoundary.tsx
2294
+ import { Fragment as Fragment3, jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
2295
+ var AsyncBoundary = ({
2296
+ loading = false,
2297
+ error,
2298
+ onRetry,
2299
+ empty = false,
2300
+ emptyContent,
2301
+ loadingContent,
2302
+ hasData,
2303
+ children
2304
+ }) => {
2305
+ const failed = toErrorInfo(error) !== void 0;
2306
+ const showData = hasData ?? false;
2307
+ if (loading && !showData) return /* @__PURE__ */ jsx36(Fragment3, { children: loadingContent ?? /* @__PURE__ */ jsx36(LoadingState, {}) });
2308
+ if (failed && !showData) return /* @__PURE__ */ jsx36(ErrorState, { error, onRetry });
2309
+ if (empty && !showData) return /* @__PURE__ */ jsx36(Fragment3, { children: emptyContent ?? null });
2310
+ return /* @__PURE__ */ jsxs19("div", { className: "relative", children: [
2311
+ /* @__PURE__ */ jsx36(RefreshBar, { active: loading }),
2312
+ failed ? /* @__PURE__ */ jsx36(InlineError, { error, onRetry, className: "mb-2" }) : null,
2313
+ children
2314
+ ] });
2315
+ };
2316
+
2057
2317
  // src/patterns/search-bar/SearchBar.tsx
2058
- import { Search, X as X5 } from "lucide-react";
2059
- import { jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
2318
+ import { ExclamationTriangleIcon as ExclamationTriangleIcon3, MagnifyingGlassIcon, XMarkIcon as XMarkIcon5 } from "@heroicons/react/24/outline";
2319
+ import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
2060
2320
  function SearchBar({
2061
2321
  value,
2062
2322
  onChange,
2323
+ loading,
2063
2324
  isLoading,
2325
+ error,
2326
+ onRetry,
2064
2327
  onClear,
2065
2328
  clearLabel = "Clear search",
2066
2329
  inputRef,
2067
2330
  className,
2068
2331
  ...props
2069
2332
  }) {
2333
+ const busy = loading ?? isLoading;
2334
+ const hasError = toErrorInfo(error) !== void 0;
2070
2335
  const showClear = onClear !== false && value.length > 0;
2071
- return /* @__PURE__ */ jsxs17("div", { className: cn("relative", className), children: [
2072
- /* @__PURE__ */ jsx34("span", { className: "pointer-events-none absolute top-1/2 left-4 -translate-y-1/2 text-muted-foreground", children: isLoading ? /* @__PURE__ */ jsx34(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx34(Search, { className: "h-4 w-4", "aria-hidden": "true" }) }),
2073
- /* @__PURE__ */ jsx34(
2074
- "input",
2075
- {
2076
- ref: inputRef,
2077
- type: "search",
2078
- value,
2079
- onChange: (event) => onChange(event.target.value),
2080
- className: cn(
2081
- "h-11 w-full rounded-full border border-input bg-background text-[15px] text-foreground placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
2082
- // Chromium/Safari render their own native clear (×) control on
2083
- // type="search" inputs -- left alone, it stacks on top of our own
2084
- // custom clear button below instead of replacing it.
2085
- "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none",
2086
- showClear ? "pr-11" : "pr-4",
2087
- "pl-11"
2088
- ),
2089
- ...props
2090
- }
2091
- ),
2092
- showClear && /* @__PURE__ */ jsx34(
2093
- "button",
2094
- {
2095
- type: "button",
2096
- onClick: () => onClear ? onClear() : onChange(""),
2097
- "aria-label": clearLabel,
2098
- className: "absolute top-1/2 right-2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-full text-muted-foreground hover:bg-accent hover:text-foreground",
2099
- children: /* @__PURE__ */ jsx34(X5, { className: "h-4 w-4", "aria-hidden": "true" })
2100
- }
2101
- )
2336
+ return /* @__PURE__ */ jsxs20("div", { className, children: [
2337
+ /* @__PURE__ */ jsxs20("div", { className: "relative", children: [
2338
+ /* @__PURE__ */ jsx37("span", { className: "pointer-events-none absolute top-1/2 left-4 -translate-y-1/2 text-muted-foreground", children: busy ? /* @__PURE__ */ jsx37(LoadingSpinner, { size: "sm" }) : hasError ? /* @__PURE__ */ jsx37(ExclamationTriangleIcon3, { className: "h-4 w-4 text-destructive", "aria-hidden": "true" }) : /* @__PURE__ */ jsx37(MagnifyingGlassIcon, { className: "h-4 w-4", "aria-hidden": "true" }) }),
2339
+ /* @__PURE__ */ jsx37(
2340
+ "input",
2341
+ {
2342
+ ref: inputRef,
2343
+ type: "search",
2344
+ "aria-invalid": hasError || void 0,
2345
+ value,
2346
+ onChange: (event) => onChange(event.target.value),
2347
+ className: cn(
2348
+ "h-11 w-full rounded-full border bg-background text-[15px] text-foreground placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
2349
+ // Chromium/Safari render their own native clear (×) control on
2350
+ // type="search" inputs -- left alone, it stacks on top of our own
2351
+ // custom clear button below instead of replacing it.
2352
+ "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none",
2353
+ hasError ? "border-destructive" : "border-input",
2354
+ showClear ? "pr-11" : "pr-4",
2355
+ "pl-11"
2356
+ ),
2357
+ ...props
2358
+ }
2359
+ ),
2360
+ showClear && /* @__PURE__ */ jsx37(
2361
+ "button",
2362
+ {
2363
+ type: "button",
2364
+ onClick: () => onClear ? onClear() : onChange(""),
2365
+ "aria-label": clearLabel,
2366
+ className: "absolute top-1/2 right-2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-full text-muted-foreground hover:bg-accent hover:text-foreground",
2367
+ children: /* @__PURE__ */ jsx37(XMarkIcon5, { className: "h-4 w-4", "aria-hidden": "true" })
2368
+ }
2369
+ )
2370
+ ] }),
2371
+ hasError && /* @__PURE__ */ jsx37(InlineError, { error, onRetry, className: "mt-1 ml-4" })
2102
2372
  ] });
2103
2373
  }
2104
2374
 
2105
2375
  // src/patterns/kpi-card/KpiCard.tsx
2106
2376
  import { memo } from "react";
2107
- import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
2377
+ import { ExclamationTriangleIcon as ExclamationTriangleIcon4 } from "@heroicons/react/24/outline";
2378
+ import { Fragment as Fragment4, jsx as jsx38, jsxs as jsxs21 } from "react/jsx-runtime";
2108
2379
  var DONUT_COLORS = [
2109
2380
  "var(--chart-1, #3b82f6)",
2110
2381
  "var(--chart-2, #22c55e)",
@@ -2125,13 +2396,13 @@ function DonutChart({
2125
2396
  const radius = (size - thickness) / 2;
2126
2397
  const circumference = 2 * Math.PI * radius;
2127
2398
  let offset = 0;
2128
- return /* @__PURE__ */ jsxs18("div", { className: "relative inline-flex shrink-0 items-center justify-center", style: { width: size, height: size }, children: [
2129
- /* @__PURE__ */ jsxs18("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, className: "-rotate-90", children: [
2130
- /* @__PURE__ */ jsx35("circle", { cx: size / 2, cy: size / 2, r: radius, fill: "none", stroke: "currentColor", className: "text-muted/40", strokeWidth: thickness }),
2399
+ return /* @__PURE__ */ jsxs21("div", { className: "relative inline-flex shrink-0 items-center justify-center", style: { width: size, height: size }, children: [
2400
+ /* @__PURE__ */ jsxs21("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, className: "-rotate-90", children: [
2401
+ /* @__PURE__ */ jsx38("circle", { cx: size / 2, cy: size / 2, r: radius, fill: "none", stroke: "currentColor", className: "text-muted/40", strokeWidth: thickness }),
2131
2402
  data.map((segment, i) => {
2132
2403
  const fraction = segment.value / total;
2133
2404
  const dash = fraction * circumference;
2134
- const el = /* @__PURE__ */ jsx35(
2405
+ const el = /* @__PURE__ */ jsx38(
2135
2406
  "circle",
2136
2407
  {
2137
2408
  cx: size / 2,
@@ -2150,9 +2421,9 @@ function DonutChart({
2150
2421
  return el;
2151
2422
  })
2152
2423
  ] }),
2153
- (centerValue || centerLabel) && /* @__PURE__ */ jsxs18("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: [
2154
- centerValue && /* @__PURE__ */ jsx35("span", { className: "text-base font-black tracking-tight text-foreground tabular-nums", children: centerValue }),
2155
- centerLabel && /* @__PURE__ */ jsx35("span", { className: "text-[9px] font-medium text-muted-foreground uppercase", children: centerLabel })
2424
+ (centerValue || centerLabel) && /* @__PURE__ */ jsxs21("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: [
2425
+ centerValue && /* @__PURE__ */ jsx38("span", { className: "text-base font-black tracking-tight text-foreground tabular-nums", children: centerValue }),
2426
+ centerLabel && /* @__PURE__ */ jsx38("span", { className: "text-[9px] font-medium text-muted-foreground uppercase", children: centerLabel })
2156
2427
  ] })
2157
2428
  ] });
2158
2429
  }
@@ -2164,7 +2435,7 @@ function Sparkline({ data, color }) {
2164
2435
  const W = 72;
2165
2436
  const H = 28;
2166
2437
  const pts = data.map((v, i) => `${i / (data.length - 1) * W},${H - (v - min) / range * (H - 2) - 1}`).join(" ");
2167
- return /* @__PURE__ */ jsx35("svg", { width: W, height: H, viewBox: `0 0 ${W} ${H}`, className: "overflow-visible opacity-70", children: /* @__PURE__ */ jsx35("polyline", { points: pts, fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
2438
+ return /* @__PURE__ */ jsx38("svg", { width: W, height: H, viewBox: `0 0 ${W} ${H}`, className: "overflow-visible opacity-70", children: /* @__PURE__ */ jsx38("polyline", { points: pts, fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
2168
2439
  }
2169
2440
  function AreaSparkline({ data, color }) {
2170
2441
  if (data.length < 2) return null;
@@ -2178,14 +2449,14 @@ function AreaSparkline({ data, color }) {
2178
2449
  const ys = data.map((v) => H - (v - min) / range * (H - 2 * P) - P);
2179
2450
  const linePts = xs.map((x, i) => `${x},${ys[i]}`).join(" ");
2180
2451
  const areaPath = `M${xs[0]},${H} ` + xs.map((x, i) => `L${x},${ys[i]}`).join(" ") + ` L${xs[xs.length - 1]},${H} Z`;
2181
- return /* @__PURE__ */ jsxs18("svg", { width: W, height: H, viewBox: `0 0 ${W} ${H}`, className: "overflow-visible", preserveAspectRatio: "none", children: [
2182
- /* @__PURE__ */ jsx35("defs", { children: /* @__PURE__ */ jsxs18("linearGradient", { id: "kpi-card-spark-fill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
2183
- /* @__PURE__ */ jsx35("stop", { offset: "0%", stopColor: color, stopOpacity: "0.22" }),
2184
- /* @__PURE__ */ jsx35("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
2452
+ return /* @__PURE__ */ jsxs21("svg", { width: W, height: H, viewBox: `0 0 ${W} ${H}`, className: "overflow-visible", preserveAspectRatio: "none", children: [
2453
+ /* @__PURE__ */ jsx38("defs", { children: /* @__PURE__ */ jsxs21("linearGradient", { id: "kpi-card-spark-fill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
2454
+ /* @__PURE__ */ jsx38("stop", { offset: "0%", stopColor: color, stopOpacity: "0.22" }),
2455
+ /* @__PURE__ */ jsx38("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
2185
2456
  ] }) }),
2186
- /* @__PURE__ */ jsx35("path", { d: areaPath, fill: "url(#kpi-card-spark-fill)" }),
2187
- /* @__PURE__ */ jsx35("polyline", { points: linePts, fill: "none", stroke: color, strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }),
2188
- /* @__PURE__ */ jsx35("circle", { cx: xs[xs.length - 1], cy: ys[ys.length - 1], r: "2.5", fill: color })
2457
+ /* @__PURE__ */ jsx38("path", { d: areaPath, fill: "url(#kpi-card-spark-fill)" }),
2458
+ /* @__PURE__ */ jsx38("polyline", { points: linePts, fill: "none", stroke: color, strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }),
2459
+ /* @__PURE__ */ jsx38("circle", { cx: xs[xs.length - 1], cy: ys[ys.length - 1], r: "2.5", fill: color })
2189
2460
  ] });
2190
2461
  }
2191
2462
  var rowBetween = "flex items-center justify-between";
@@ -2197,6 +2468,8 @@ var KpiCard = memo(function KpiCard2({
2197
2468
  badgeLabel,
2198
2469
  variant = "default",
2199
2470
  loading = false,
2471
+ error,
2472
+ onRetry,
2200
2473
  sub,
2201
2474
  subTone = "default",
2202
2475
  href,
@@ -2209,9 +2482,33 @@ var KpiCard = memo(function KpiCard2({
2209
2482
  background,
2210
2483
  testId
2211
2484
  }) {
2485
+ const errorInfo = loading ? void 0 : toErrorInfo(error);
2486
+ if (errorInfo) {
2487
+ const hero = variant === "hero";
2488
+ return /* @__PURE__ */ jsxs21(
2489
+ "div",
2490
+ {
2491
+ "data-testid": testId,
2492
+ role: "status",
2493
+ className: cn(
2494
+ "flex min-w-0 flex-col gap-1 rounded-2xl border border-destructive/40 bg-card p-3",
2495
+ hero && "col-span-2 flex-1 lg:col-span-1 lg:max-w-[340px] lg:min-w-[260px]"
2496
+ ),
2497
+ children: [
2498
+ /* @__PURE__ */ jsx38("p", { className: "text-[11px] font-bold tracking-[0.14em] text-muted-foreground uppercase", children: label }),
2499
+ /* @__PURE__ */ jsxs21("p", { className: "flex items-center gap-1.5 text-xl font-bold text-muted-foreground", children: [
2500
+ "\u2014",
2501
+ /* @__PURE__ */ jsx38(ExclamationTriangleIcon4, { className: "h-4 w-4 text-destructive", "aria-hidden": "true" })
2502
+ ] }),
2503
+ /* @__PURE__ */ jsx38("p", { className: "truncate text-xs text-red-700 dark:text-red-300", children: errorInfo.message ?? errorInfo.title ?? "Failed to load" }),
2504
+ onRetry ? /* @__PURE__ */ jsx38("button", { type: "button", onClick: onRetry, className: "self-start text-xs text-red-700 underline underline-offset-2 dark:text-red-300", children: "Retry" }) : null
2505
+ ]
2506
+ }
2507
+ );
2508
+ }
2212
2509
  const bgStyle = background ? { background } : void 0;
2213
2510
  if (variant === "hero") {
2214
- return /* @__PURE__ */ jsxs18(
2511
+ return /* @__PURE__ */ jsxs21(
2215
2512
  "div",
2216
2513
  {
2217
2514
  "data-testid": testId,
@@ -2221,13 +2518,13 @@ var KpiCard = memo(function KpiCard2({
2221
2518
  boxShadow: `0 2px 10px color-mix(in oklch, ${background ?? "var(--color-primary)"} 18%, transparent)`
2222
2519
  },
2223
2520
  children: [
2224
- /* @__PURE__ */ jsxs18("div", { className: "relative flex items-start justify-between", children: [
2225
- /* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.14em] text-white/70 uppercase", children: label }),
2226
- Icon2 && /* @__PURE__ */ jsx35("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-white/15 ring-1 ring-white/20", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-3 w-3 text-white/90", "aria-hidden": "true" }) })
2521
+ /* @__PURE__ */ jsxs21("div", { className: "relative flex items-start justify-between", children: [
2522
+ /* @__PURE__ */ jsx38("p", { className: "text-[11px] font-bold tracking-[0.14em] text-white/70 uppercase", children: label }),
2523
+ Icon2 && /* @__PURE__ */ jsx38("div", { className: "flex h-6 w-6 items-center justify-center rounded-lg bg-white/15 ring-1 ring-white/20", children: /* @__PURE__ */ jsx38(Icon2, { className: "h-3 w-3 text-white/90", "aria-hidden": "true" }) })
2227
2524
  ] }),
2228
- /* @__PURE__ */ jsx35("div", { className: "relative", children: loading ? /* @__PURE__ */ jsx35("div", { className: "h-6 w-28 animate-pulse rounded-lg bg-white/15" }) : /* @__PURE__ */ jsx35("p", { className: "text-2xl leading-none font-black tracking-tight text-white tabular-nums md:text-[22px]", children: value ?? "\u2014" }) }),
2229
- (badge || badgeLabel) && !loading && /* @__PURE__ */ jsxs18("div", { className: "relative flex items-center gap-2", children: [
2230
- badge && /* @__PURE__ */ jsx35(
2525
+ /* @__PURE__ */ jsx38("div", { className: "relative", children: loading ? /* @__PURE__ */ jsx38("div", { className: "h-6 w-28 animate-pulse rounded-lg bg-white/15" }) : /* @__PURE__ */ jsx38("p", { className: "text-2xl leading-none font-black tracking-tight text-white tabular-nums md:text-[22px]", children: value ?? "\u2014" }) }),
2526
+ (badge || badgeLabel) && !loading && /* @__PURE__ */ jsxs21("div", { className: "relative flex items-center gap-2", children: [
2527
+ badge && /* @__PURE__ */ jsx38(
2231
2528
  "span",
2232
2529
  {
2233
2530
  className: cn(
@@ -2237,28 +2534,28 @@ var KpiCard = memo(function KpiCard2({
2237
2534
  children: badge.text
2238
2535
  }
2239
2536
  ),
2240
- badgeLabel && /* @__PURE__ */ jsx35("span", { className: "text-[11px] text-white/70", children: badgeLabel })
2537
+ badgeLabel && /* @__PURE__ */ jsx38("span", { className: "text-[11px] text-white/70", children: badgeLabel })
2241
2538
  ] }),
2242
- sub && !loading && /* @__PURE__ */ jsx35("p", { className: "relative -mt-1 text-[11px] font-medium text-white/75 tabular-nums", children: sub }),
2243
- progress != null && !loading && /* @__PURE__ */ jsxs18("div", { className: "relative flex items-center gap-1.5", children: [
2244
- /* @__PURE__ */ jsx35("div", { className: "h-1 flex-1 overflow-hidden rounded-full bg-white/20", children: /* @__PURE__ */ jsx35("div", { className: "h-1 rounded-full bg-white/85", style: { width: `${Math.min(100, Math.max(0, progress))}%` } }) }),
2245
- progressLabel && /* @__PURE__ */ jsx35("span", { className: "shrink-0 text-[11px] font-semibold text-white/80 tabular-nums", children: progressLabel })
2539
+ sub && !loading && /* @__PURE__ */ jsx38("p", { className: "relative -mt-1 text-[11px] font-medium text-white/75 tabular-nums", children: sub }),
2540
+ progress != null && !loading && /* @__PURE__ */ jsxs21("div", { className: "relative flex items-center gap-1.5", children: [
2541
+ /* @__PURE__ */ jsx38("div", { className: "h-1 flex-1 overflow-hidden rounded-full bg-white/20", children: /* @__PURE__ */ jsx38("div", { className: "h-1 rounded-full bg-white/85", style: { width: `${Math.min(100, Math.max(0, progress))}%` } }) }),
2542
+ progressLabel && /* @__PURE__ */ jsx38("span", { className: "shrink-0 text-[11px] font-semibold text-white/80 tabular-nums", children: progressLabel })
2246
2543
  ] }),
2247
- sparkline && sparkline.length > 1 && !loading && /* @__PURE__ */ jsx35("div", { className: "relative -mx-4 mt-auto -mb-4 md:-mx-3 md:-mb-3", children: /* @__PURE__ */ jsx35(AreaSparkline, { data: sparkline, color: "#ffffff" }) })
2544
+ sparkline && sparkline.length > 1 && !loading && /* @__PURE__ */ jsx38("div", { className: "relative -mx-4 mt-auto -mb-4 md:-mx-3 md:-mb-3", children: /* @__PURE__ */ jsx38(AreaSparkline, { data: sparkline, color: "#ffffff" }) })
2248
2545
  ]
2249
2546
  }
2250
2547
  );
2251
2548
  }
2252
2549
  if (variant === "mini") {
2253
- const iconSlot = Icon2 ? href ? /* @__PURE__ */ jsx35(
2550
+ const iconSlot = Icon2 ? href ? /* @__PURE__ */ jsx38(
2254
2551
  "a",
2255
2552
  {
2256
2553
  href,
2257
2554
  className: "tap-target flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary transition-[background-color,scale] hover:bg-primary/20 active:scale-90 motion-reduce:transition-none md:h-6 md:w-6",
2258
- children: /* @__PURE__ */ jsx35(Icon2, { className: "h-4 w-4 md:h-3.5 md:w-3.5", "aria-hidden": "true" })
2555
+ children: /* @__PURE__ */ jsx38(Icon2, { className: "h-4 w-4 md:h-3.5 md:w-3.5", "aria-hidden": "true" })
2259
2556
  }
2260
- ) : /* @__PURE__ */ jsx35("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary md:h-6 md:w-6", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-4 w-4 md:h-3.5 md:w-3.5", "aria-hidden": "true" }) }) : null;
2261
- return /* @__PURE__ */ jsxs18(
2557
+ ) : /* @__PURE__ */ jsx38("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary md:h-6 md:w-6", children: /* @__PURE__ */ jsx38(Icon2, { className: "h-4 w-4 md:h-3.5 md:w-3.5", "aria-hidden": "true" }) }) : null;
2558
+ return /* @__PURE__ */ jsxs21(
2262
2559
  "div",
2263
2560
  {
2264
2561
  "data-testid": testId,
@@ -2268,13 +2565,13 @@ var KpiCard = memo(function KpiCard2({
2268
2565
  href && "hover:border-primary/20 hover:shadow-md"
2269
2566
  ),
2270
2567
  children: [
2271
- /* @__PURE__ */ jsxs18("div", { className: rowBetween, children: [
2272
- /* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
2568
+ /* @__PURE__ */ jsxs21("div", { className: rowBetween, children: [
2569
+ /* @__PURE__ */ jsx38("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
2273
2570
  iconSlot
2274
2571
  ] }),
2275
- /* @__PURE__ */ jsx35("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: loading ? /* @__PURE__ */ jsx35(Skeleton, { className: "h-6 w-16" }) : /* @__PURE__ */ jsxs18(Fragment3, { children: [
2276
- /* @__PURE__ */ jsx35("p", { className: "min-w-0 animate-in truncate text-[20px] leading-none font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none md:text-[16px]", children: value ?? "\u2014" }),
2277
- badge && /* @__PURE__ */ jsx35(
2572
+ /* @__PURE__ */ jsx38("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: loading ? /* @__PURE__ */ jsx38(Skeleton, { className: "h-6 w-16" }) : /* @__PURE__ */ jsxs21(Fragment4, { children: [
2573
+ /* @__PURE__ */ jsx38("p", { className: "min-w-0 animate-in truncate text-[20px] leading-none font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none md:text-[16px]", children: value ?? "\u2014" }),
2574
+ badge && /* @__PURE__ */ jsx38(
2278
2575
  "span",
2279
2576
  {
2280
2577
  className: cn(
@@ -2285,8 +2582,8 @@ var KpiCard = memo(function KpiCard2({
2285
2582
  }
2286
2583
  )
2287
2584
  ] }) }),
2288
- (sub || sparkline) && !loading && /* @__PURE__ */ jsxs18("div", { className: "flex items-end justify-between gap-2", children: [
2289
- sub && /* @__PURE__ */ jsx35(
2585
+ (sub || sparkline) && !loading && /* @__PURE__ */ jsxs21("div", { className: "flex items-end justify-between gap-2", children: [
2586
+ sub && /* @__PURE__ */ jsx38(
2290
2587
  "p",
2291
2588
  {
2292
2589
  className: cn(
@@ -2296,7 +2593,7 @@ var KpiCard = memo(function KpiCard2({
2296
2593
  children: sub
2297
2594
  }
2298
2595
  ),
2299
- sparkline && /* @__PURE__ */ jsx35(Sparkline, { data: sparkline, color: sparklineColor })
2596
+ sparkline && /* @__PURE__ */ jsx38(Sparkline, { data: sparkline, color: sparklineColor })
2300
2597
  ] })
2301
2598
  ]
2302
2599
  }
@@ -2304,22 +2601,22 @@ var KpiCard = memo(function KpiCard2({
2304
2601
  }
2305
2602
  if (variant === "donut") {
2306
2603
  const total = segments?.reduce((sum, s) => sum + s.value, 0) ?? 0;
2307
- return /* @__PURE__ */ jsxs18("div", { "data-testid": testId, style: bgStyle, className: "rounded-xl border border-border bg-card p-5", children: [
2308
- /* @__PURE__ */ jsxs18("div", { className: rowBetween, children: [
2309
- /* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
2310
- Icon2 && /* @__PURE__ */ jsx35("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/8 text-primary", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) })
2604
+ return /* @__PURE__ */ jsxs21("div", { "data-testid": testId, style: bgStyle, className: "rounded-xl border border-border bg-card p-5", children: [
2605
+ /* @__PURE__ */ jsxs21("div", { className: rowBetween, children: [
2606
+ /* @__PURE__ */ jsx38("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
2607
+ Icon2 && /* @__PURE__ */ jsx38("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/8 text-primary", children: /* @__PURE__ */ jsx38(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) })
2311
2608
  ] }),
2312
- loading ? /* @__PURE__ */ jsxs18("div", { className: "mt-3 flex items-center gap-4", children: [
2313
- /* @__PURE__ */ jsx35(Skeleton, { className: "h-24 w-24 shrink-0 rounded-full" }),
2314
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-1 flex-col gap-2", children: [
2315
- /* @__PURE__ */ jsx35(Skeleton, { className: "h-3 w-full" }),
2316
- /* @__PURE__ */ jsx35(Skeleton, { className: "h-3 w-3/4" }),
2317
- /* @__PURE__ */ jsx35(Skeleton, { className: "h-3 w-1/2" })
2609
+ loading ? /* @__PURE__ */ jsxs21("div", { className: "mt-3 flex items-center gap-4", children: [
2610
+ /* @__PURE__ */ jsx38(Skeleton, { className: "h-24 w-24 shrink-0 rounded-full" }),
2611
+ /* @__PURE__ */ jsxs21("div", { className: "flex flex-1 flex-col gap-2", children: [
2612
+ /* @__PURE__ */ jsx38(Skeleton, { className: "h-3 w-full" }),
2613
+ /* @__PURE__ */ jsx38(Skeleton, { className: "h-3 w-3/4" }),
2614
+ /* @__PURE__ */ jsx38(Skeleton, { className: "h-3 w-1/2" })
2318
2615
  ] })
2319
- ] }) : segments && segments.length > 0 ? /* @__PURE__ */ jsxs18("div", { className: "mt-3 flex items-center gap-4", children: [
2320
- /* @__PURE__ */ jsx35(DonutChart, { data: segments, centerValue: centerValue ?? String(total) }),
2321
- /* @__PURE__ */ jsx35("ul", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: segments.map((segment, i) => /* @__PURE__ */ jsxs18("li", { className: "flex items-center gap-2 text-[12px]", children: [
2322
- /* @__PURE__ */ jsx35(
2616
+ ] }) : segments && segments.length > 0 ? /* @__PURE__ */ jsxs21("div", { className: "mt-3 flex items-center gap-4", children: [
2617
+ /* @__PURE__ */ jsx38(DonutChart, { data: segments, centerValue: centerValue ?? String(total) }),
2618
+ /* @__PURE__ */ jsx38("ul", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: segments.map((segment, i) => /* @__PURE__ */ jsxs21("li", { className: "flex items-center gap-2 text-[12px]", children: [
2619
+ /* @__PURE__ */ jsx38(
2323
2620
  "span",
2324
2621
  {
2325
2622
  className: "h-2 w-2 shrink-0 rounded-full",
@@ -2327,11 +2624,11 @@ var KpiCard = memo(function KpiCard2({
2327
2624
  "aria-hidden": "true"
2328
2625
  }
2329
2626
  ),
2330
- /* @__PURE__ */ jsx35("span", { className: "min-w-0 flex-1 truncate text-muted-foreground", children: segment.label }),
2331
- /* @__PURE__ */ jsx35("span", { className: "shrink-0 font-semibold text-foreground tabular-nums", children: total > 0 ? `${Math.round(segment.value / total * 100)}%` : segment.value })
2627
+ /* @__PURE__ */ jsx38("span", { className: "min-w-0 flex-1 truncate text-muted-foreground", children: segment.label }),
2628
+ /* @__PURE__ */ jsx38("span", { className: "shrink-0 font-semibold text-foreground tabular-nums", children: total > 0 ? `${Math.round(segment.value / total * 100)}%` : segment.value })
2332
2629
  ] }, segment.label)) })
2333
- ] }) : /* @__PURE__ */ jsx35("span", { className: "mt-3 block text-2xl font-black text-muted-foreground/40", children: "\u2014" }),
2334
- sub && !loading && /* @__PURE__ */ jsx35("p", { className: "mt-2.5 text-[11px] text-muted-foreground tabular-nums", children: sub })
2630
+ ] }) : /* @__PURE__ */ jsx38("span", { className: "mt-3 block text-2xl font-black text-muted-foreground/40", children: "\u2014" }),
2631
+ sub && !loading && /* @__PURE__ */ jsx38("p", { className: "mt-2.5 text-[11px] text-muted-foreground tabular-nums", children: sub })
2335
2632
  ] });
2336
2633
  }
2337
2634
  const strValue = value != null ? String(value) : null;
@@ -2341,28 +2638,28 @@ var KpiCard = memo(function KpiCard2({
2341
2638
  const prefix = isSuffix ? null : parts?.[0];
2342
2639
  const number = isSuffix ? parts[0] : parts?.[1] ?? parts?.[0];
2343
2640
  const suffix = isSuffix ? parts[1] : null;
2344
- return /* @__PURE__ */ jsxs18("div", { "data-testid": testId, style: bgStyle, className: "rounded-xl border border-border bg-card p-5", children: [
2345
- /* @__PURE__ */ jsxs18("div", { className: rowBetween, children: [
2346
- /* @__PURE__ */ jsx35("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
2347
- Icon2 && /* @__PURE__ */ jsx35("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/8 text-primary", children: /* @__PURE__ */ jsx35(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) })
2641
+ return /* @__PURE__ */ jsxs21("div", { "data-testid": testId, style: bgStyle, className: "rounded-xl border border-border bg-card p-5", children: [
2642
+ /* @__PURE__ */ jsxs21("div", { className: rowBetween, children: [
2643
+ /* @__PURE__ */ jsx38("p", { className: "text-[11px] font-bold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
2644
+ Icon2 && /* @__PURE__ */ jsx38("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-xl bg-primary/8 text-primary", children: /* @__PURE__ */ jsx38(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) })
2348
2645
  ] }),
2349
- /* @__PURE__ */ jsxs18("div", { className: "mt-3", children: [
2350
- loading ? /* @__PURE__ */ jsx35(Skeleton, { className: "h-7 w-20" }) : value == null ? /* @__PURE__ */ jsx35("span", { className: "text-2xl font-black text-muted-foreground/40", children: "\u2014" }) : plain ? /* @__PURE__ */ jsx35("span", { className: "animate-in text-2xl font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none", children: strValue }) : /* @__PURE__ */ jsxs18("span", { className: "animate-in font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none", children: [
2351
- prefix && /* @__PURE__ */ jsxs18("span", { className: "text-sm text-muted-foreground", children: [
2646
+ /* @__PURE__ */ jsxs21("div", { className: "mt-3", children: [
2647
+ loading ? /* @__PURE__ */ jsx38(Skeleton, { className: "h-7 w-20" }) : value == null ? /* @__PURE__ */ jsx38("span", { className: "text-2xl font-black text-muted-foreground/40", children: "\u2014" }) : plain ? /* @__PURE__ */ jsx38("span", { className: "animate-in text-2xl font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none", children: strValue }) : /* @__PURE__ */ jsxs21("span", { className: "animate-in font-black tracking-tight text-foreground duration-200 fade-in-0 tabular-nums motion-reduce:animate-none", children: [
2648
+ prefix && /* @__PURE__ */ jsxs21("span", { className: "text-sm text-muted-foreground", children: [
2352
2649
  prefix,
2353
2650
  " "
2354
2651
  ] }),
2355
- /* @__PURE__ */ jsx35("span", { className: "text-2xl", children: number }),
2356
- suffix && /* @__PURE__ */ jsxs18("span", { className: "text-sm text-muted-foreground", children: [
2652
+ /* @__PURE__ */ jsx38("span", { className: "text-2xl", children: number }),
2653
+ suffix && /* @__PURE__ */ jsxs21("span", { className: "text-sm text-muted-foreground", children: [
2357
2654
  " ",
2358
2655
  suffix
2359
2656
  ] })
2360
2657
  ] }),
2361
- sub && !loading && /* @__PURE__ */ jsx35("p", { className: "mt-0.5 text-[11px] text-muted-foreground tabular-nums", children: sub })
2658
+ sub && !loading && /* @__PURE__ */ jsx38("p", { className: "mt-0.5 text-[11px] text-muted-foreground tabular-nums", children: sub })
2362
2659
  ] }),
2363
- (badge || badgeLabel || sparkline) && !loading && /* @__PURE__ */ jsxs18("div", { className: "mt-2.5 flex items-end justify-between gap-2", children: [
2364
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap items-center gap-2", children: [
2365
- badge && /* @__PURE__ */ jsx35(
2660
+ (badge || badgeLabel || sparkline) && !loading && /* @__PURE__ */ jsxs21("div", { className: "mt-2.5 flex items-end justify-between gap-2", children: [
2661
+ /* @__PURE__ */ jsxs21("div", { className: "flex flex-wrap items-center gap-2", children: [
2662
+ badge && /* @__PURE__ */ jsx38(
2366
2663
  "span",
2367
2664
  {
2368
2665
  className: cn(
@@ -2372,20 +2669,23 @@ var KpiCard = memo(function KpiCard2({
2372
2669
  children: badge.text
2373
2670
  }
2374
2671
  ),
2375
- badgeLabel && /* @__PURE__ */ jsx35("span", { className: "text-[11px] text-muted-foreground", children: badgeLabel })
2672
+ badgeLabel && /* @__PURE__ */ jsx38("span", { className: "text-[11px] text-muted-foreground", children: badgeLabel })
2376
2673
  ] }),
2377
- sparkline && /* @__PURE__ */ jsx35(Sparkline, { data: sparkline, color: sparklineColor })
2674
+ sparkline && /* @__PURE__ */ jsx38(Sparkline, { data: sparkline, color: sparklineColor })
2378
2675
  ] })
2379
2676
  ] });
2380
2677
  });
2381
2678
 
2382
2679
  // src/patterns/search-panel/SearchPanel.tsx
2383
- import { Search as Search2 } from "lucide-react";
2384
- import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
2680
+ import { ExclamationTriangleIcon as ExclamationTriangleIcon5, MagnifyingGlassIcon as MagnifyingGlassIcon2 } from "@heroicons/react/24/outline";
2681
+ import { jsx as jsx39, jsxs as jsxs22 } from "react/jsx-runtime";
2385
2682
  function SearchPanel({
2386
2683
  value,
2387
2684
  onChange,
2685
+ loading,
2388
2686
  isLoading,
2687
+ error,
2688
+ onRetry,
2389
2689
  trailingSlot,
2390
2690
  shortcutHint,
2391
2691
  modes,
@@ -2396,7 +2696,9 @@ function SearchPanel({
2396
2696
  className,
2397
2697
  ...props
2398
2698
  }) {
2399
- return /* @__PURE__ */ jsxs19(
2699
+ const busy = loading ?? isLoading;
2700
+ const hasError = toErrorInfo(error) !== void 0;
2701
+ return /* @__PURE__ */ jsxs22(
2400
2702
  "div",
2401
2703
  {
2402
2704
  className: cn(
@@ -2405,9 +2707,9 @@ function SearchPanel({
2405
2707
  className
2406
2708
  ),
2407
2709
  children: [
2408
- /* @__PURE__ */ jsxs19("div", { className: "flex h-14 items-center gap-3 px-4", children: [
2409
- isLoading ? /* @__PURE__ */ jsx36(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx36(Search2, { className: "h-5 w-5 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
2410
- /* @__PURE__ */ jsx36(
2710
+ /* @__PURE__ */ jsxs22("div", { className: "flex h-14 items-center gap-3 px-4", children: [
2711
+ busy ? /* @__PURE__ */ jsx39(LoadingSpinner, { size: "sm" }) : hasError ? /* @__PURE__ */ jsx39(ExclamationTriangleIcon5, { className: "h-5 w-5 shrink-0 text-destructive", "aria-hidden": "true" }) : /* @__PURE__ */ jsx39(MagnifyingGlassIcon2, { className: "h-5 w-5 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
2712
+ /* @__PURE__ */ jsx39(
2411
2713
  "input",
2412
2714
  {
2413
2715
  ref: inputRef,
@@ -2419,7 +2721,7 @@ function SearchPanel({
2419
2721
  }
2420
2722
  ),
2421
2723
  trailingSlot,
2422
- shortcutHint && /* @__PURE__ */ jsx36(
2724
+ shortcutHint && /* @__PURE__ */ jsx39(
2423
2725
  "kbd",
2424
2726
  {
2425
2727
  "aria-hidden": "true",
@@ -2428,7 +2730,8 @@ function SearchPanel({
2428
2730
  }
2429
2731
  )
2430
2732
  ] }),
2431
- modes && modes.length > 0 && /* @__PURE__ */ jsx36("div", { className: "flex items-center gap-2 px-4 pb-3", children: modes.map(({ key, label, icon: Icon2 }) => /* @__PURE__ */ jsxs19(
2733
+ hasError && /* @__PURE__ */ jsx39("div", { className: "px-4 pb-3", children: /* @__PURE__ */ jsx39(InlineError, { error, onRetry }) }),
2734
+ modes && modes.length > 0 && /* @__PURE__ */ jsx39("div", { className: "flex items-center gap-2 px-4 pb-3", children: modes.map(({ key, label, icon: Icon2 }) => /* @__PURE__ */ jsxs22(
2432
2735
  "button",
2433
2736
  {
2434
2737
  type: "button",
@@ -2438,7 +2741,7 @@ function SearchPanel({
2438
2741
  activeMode === key ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
2439
2742
  ),
2440
2743
  children: [
2441
- Icon2 && /* @__PURE__ */ jsx36(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2744
+ Icon2 && /* @__PURE__ */ jsx39(Icon2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2442
2745
  label
2443
2746
  ]
2444
2747
  },
@@ -2450,10 +2753,10 @@ function SearchPanel({
2450
2753
  }
2451
2754
 
2452
2755
  // src/patterns/search-panel/SearchTrigger.tsx
2453
- import { Search as Search3 } from "lucide-react";
2454
- import { jsx as jsx37 } from "react/jsx-runtime";
2756
+ import { MagnifyingGlassIcon as MagnifyingGlassIcon3 } from "@heroicons/react/24/outline";
2757
+ import { jsx as jsx40 } from "react/jsx-runtime";
2455
2758
  function SearchTrigger({ label = "Search", ...props }) {
2456
- return /* @__PURE__ */ jsx37(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": label, ...props, children: /* @__PURE__ */ jsx37(Search3, { className: "h-[18px] w-[18px]", "aria-hidden": "true" }) });
2759
+ return /* @__PURE__ */ jsx40(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": label, ...props, children: /* @__PURE__ */ jsx40(MagnifyingGlassIcon3, { className: "h-[18px] w-[18px]", "aria-hidden": "true" }) });
2457
2760
  }
2458
2761
 
2459
2762
  // src/patterns/sidebar/context.ts
@@ -2465,7 +2768,7 @@ function useSidebarCollapsed() {
2465
2768
  }
2466
2769
 
2467
2770
  // src/patterns/sidebar/NavItem.tsx
2468
- import { jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
2771
+ import { jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
2469
2772
  function NavItem({
2470
2773
  as,
2471
2774
  icon: Icon2,
@@ -2477,7 +2780,7 @@ function NavItem({
2477
2780
  }) {
2478
2781
  const collapsed = useSidebarCollapsed();
2479
2782
  const Comp = as ?? "a";
2480
- const row = /* @__PURE__ */ jsxs20(
2783
+ const row = /* @__PURE__ */ jsxs23(
2481
2784
  Comp,
2482
2785
  {
2483
2786
  className: cn(
@@ -2489,7 +2792,7 @@ function NavItem({
2489
2792
  ),
2490
2793
  ...rest,
2491
2794
  children: [
2492
- Icon2 && /* @__PURE__ */ jsx38(
2795
+ Icon2 && /* @__PURE__ */ jsx41(
2493
2796
  Icon2,
2494
2797
  {
2495
2798
  className: cn("h-[18px] w-[18px] shrink-0", active ? "text-nav-primary" : "text-muted-foreground"),
@@ -2497,7 +2800,7 @@ function NavItem({
2497
2800
  "aria-hidden": true
2498
2801
  }
2499
2802
  ),
2500
- /* @__PURE__ */ jsx38(
2803
+ /* @__PURE__ */ jsx41(
2501
2804
  "span",
2502
2805
  {
2503
2806
  className: cn(
@@ -2512,9 +2815,9 @@ function NavItem({
2512
2815
  }
2513
2816
  );
2514
2817
  if (!collapsed) return row;
2515
- return /* @__PURE__ */ jsxs20(Tooltip, { children: [
2516
- /* @__PURE__ */ jsx38(TooltipTrigger, { asChild: true, children: row }),
2517
- /* @__PURE__ */ jsxs20(TooltipContent, { side: "right", className: "flex items-center gap-1.5", children: [
2818
+ return /* @__PURE__ */ jsxs23(Tooltip, { children: [
2819
+ /* @__PURE__ */ jsx41(TooltipTrigger, { asChild: true, children: row }),
2820
+ /* @__PURE__ */ jsxs23(TooltipContent, { side: "right", className: "flex items-center gap-1.5", children: [
2518
2821
  label,
2519
2822
  badge
2520
2823
  ] })
@@ -2522,9 +2825,9 @@ function NavItem({
2522
2825
  }
2523
2826
 
2524
2827
  // src/patterns/sidebar/NavGroup.tsx
2525
- import { ChevronDown as ChevronDown2 } from "lucide-react";
2526
- import { useState as useState10 } from "react";
2527
- import { jsx as jsx39, jsxs as jsxs21 } from "react/jsx-runtime";
2828
+ import { ChevronDownIcon as ChevronDownIcon2 } from "@heroicons/react/24/outline";
2829
+ import { useState as useState11 } from "react";
2830
+ import { jsx as jsx42, jsxs as jsxs24 } from "react/jsx-runtime";
2528
2831
  function NavGroup({
2529
2832
  label,
2530
2833
  defaultCollapsed = false,
@@ -2533,15 +2836,15 @@ function NavGroup({
2533
2836
  children,
2534
2837
  className
2535
2838
  }) {
2536
- const [internalCollapsed, setInternalCollapsed] = useState10(defaultCollapsed);
2839
+ const [internalCollapsed, setInternalCollapsed] = useState11(defaultCollapsed);
2537
2840
  const groupCollapsed = collapsed ?? internalCollapsed;
2538
2841
  const railCollapsed = useSidebarCollapsed();
2539
2842
  const setGroupCollapsed = (next) => {
2540
2843
  onCollapsedChange?.(next);
2541
2844
  if (collapsed === void 0) setInternalCollapsed(next);
2542
2845
  };
2543
- return /* @__PURE__ */ jsxs21("div", { className: cn("flex flex-col gap-0.5", className), children: [
2544
- label && (railCollapsed ? /* @__PURE__ */ jsx39("div", { className: "mx-2 my-1 h-px bg-border/50", "aria-hidden": true }) : /* @__PURE__ */ jsxs21(
2846
+ return /* @__PURE__ */ jsxs24("div", { className: cn("flex flex-col gap-0.5", className), children: [
2847
+ label && (railCollapsed ? /* @__PURE__ */ jsx42("div", { className: "mx-2 my-1 h-px bg-border/50", "aria-hidden": true }) : /* @__PURE__ */ jsxs24(
2545
2848
  "button",
2546
2849
  {
2547
2850
  type: "button",
@@ -2549,9 +2852,9 @@ function NavGroup({
2549
2852
  "aria-expanded": !groupCollapsed,
2550
2853
  className: "group flex w-full items-center justify-between px-2.5 py-0.5 text-[11px] font-medium text-muted-foreground/80 hover:text-foreground",
2551
2854
  children: [
2552
- /* @__PURE__ */ jsx39("span", { children: label }),
2553
- /* @__PURE__ */ jsx39(
2554
- ChevronDown2,
2855
+ /* @__PURE__ */ jsx42("span", { children: label }),
2856
+ /* @__PURE__ */ jsx42(
2857
+ ChevronDownIcon2,
2555
2858
  {
2556
2859
  className: cn(
2557
2860
  "h-4 w-4 opacity-40 transition-transform group-hover:opacity-100",
@@ -2563,19 +2866,19 @@ function NavGroup({
2563
2866
  ]
2564
2867
  }
2565
2868
  )),
2566
- !groupCollapsed && /* @__PURE__ */ jsx39("div", { className: "flex flex-col gap-0.5", children })
2869
+ !groupCollapsed && /* @__PURE__ */ jsx42("div", { className: "flex flex-col gap-0.5", children })
2567
2870
  ] });
2568
2871
  }
2569
2872
 
2570
2873
  // src/patterns/sidebar/Sidebar.tsx
2571
- import { PanelLeftClose, PanelLeftOpen } from "lucide-react";
2874
+ import { ChevronDoubleLeftIcon, ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
2572
2875
  import {
2573
- useCallback,
2574
- useEffect as useEffect5,
2575
- useRef as useRef5,
2576
- useState as useState11
2876
+ useCallback as useCallback2,
2877
+ useEffect as useEffect6,
2878
+ useRef as useRef6,
2879
+ useState as useState12
2577
2880
  } from "react";
2578
- import { Fragment as Fragment4, jsx as jsx40, jsxs as jsxs22 } from "react/jsx-runtime";
2881
+ import { Fragment as Fragment5, jsx as jsx43, jsxs as jsxs25 } from "react/jsx-runtime";
2579
2882
  function resolve(value, collapsed) {
2580
2883
  return typeof value === "function" ? value(collapsed) : value;
2581
2884
  }
@@ -2594,10 +2897,10 @@ function Sidebar({
2594
2897
  children,
2595
2898
  className
2596
2899
  }) {
2597
- const [internalWidth, setInternalWidth] = useState11(defaultWidth);
2900
+ const [internalWidth, setInternalWidth] = useState12(defaultWidth);
2598
2901
  const currentWidth = width ?? internalWidth;
2599
- const [isDragging, setIsDragging] = useState11(false);
2600
- const setWidth = useCallback(
2902
+ const [isDragging, setIsDragging] = useState12(false);
2903
+ const setWidth = useCallback2(
2601
2904
  (next) => {
2602
2905
  const clamped = Math.min(maxWidth, Math.max(minWidth, next));
2603
2906
  onWidthChange?.(clamped);
@@ -2605,7 +2908,7 @@ function Sidebar({
2605
2908
  },
2606
2909
  [maxWidth, minWidth, onWidthChange, width]
2607
2910
  );
2608
- const dragStartRef = useRef5(null);
2911
+ const dragStartRef = useRef6(null);
2609
2912
  const handlePointerDown = (event) => {
2610
2913
  event.currentTarget.setPointerCapture(event.pointerId);
2611
2914
  dragStartRef.current = { x: event.clientX, width: currentWidth };
@@ -2622,7 +2925,7 @@ function Sidebar({
2622
2925
  dragStartRef.current = null;
2623
2926
  setIsDragging(false);
2624
2927
  };
2625
- return /* @__PURE__ */ jsx40(SidebarContextProvider, { value: { collapsed }, children: /* @__PURE__ */ jsx40(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs22(
2928
+ return /* @__PURE__ */ jsx43(SidebarContextProvider, { value: { collapsed }, children: /* @__PURE__ */ jsx43(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs25(
2626
2929
  "aside",
2627
2930
  {
2628
2931
  style: { width: collapsed ? railWidth : currentWidth },
@@ -2632,13 +2935,13 @@ function Sidebar({
2632
2935
  className
2633
2936
  ),
2634
2937
  children: [
2635
- (header || onCollapsedChange) && /* @__PURE__ */ jsx40("div", { className: "flex h-16 items-center gap-2 border-b border-border px-3", children: collapsed && onCollapsedChange ? (
2938
+ (header || onCollapsedChange) && /* @__PURE__ */ jsx43("div", { className: "flex h-16 items-center gap-2 border-b border-border px-3", children: collapsed && onCollapsedChange ? (
2636
2939
  // Collapsed rail: the header slot (e.g. a compact logo mark) and the
2637
2940
  // expand toggle would otherwise compete for the narrow rail's width
2638
2941
  // and clip each other, so they're stacked instead — the header shows
2639
2942
  // by default and cross-fades to the toggle icon on hover, matching
2640
2943
  // the same affordance OneSales' own sidebar rail uses.
2641
- /* @__PURE__ */ jsxs22(
2944
+ /* @__PURE__ */ jsxs25(
2642
2945
  "button",
2643
2946
  {
2644
2947
  type: "button",
@@ -2646,9 +2949,9 @@ function Sidebar({
2646
2949
  "aria-label": "Expand sidebar",
2647
2950
  className: "group relative flex h-9 w-9 shrink-0 items-center justify-center",
2648
2951
  children: [
2649
- header && /* @__PURE__ */ jsx40("span", { className: "transition-opacity group-hover:opacity-0", children: resolve(header, collapsed) }),
2650
- /* @__PURE__ */ jsx40(
2651
- PanelLeftOpen,
2952
+ header && /* @__PURE__ */ jsx43("span", { className: "transition-opacity group-hover:opacity-0", children: resolve(header, collapsed) }),
2953
+ /* @__PURE__ */ jsx43(
2954
+ ChevronDoubleRightIcon,
2652
2955
  {
2653
2956
  className: "absolute h-4 w-4 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100",
2654
2957
  "aria-hidden": true
@@ -2657,22 +2960,22 @@ function Sidebar({
2657
2960
  ]
2658
2961
  }
2659
2962
  )
2660
- ) : /* @__PURE__ */ jsxs22(Fragment4, { children: [
2661
- header && /* @__PURE__ */ jsx40("div", { className: "min-w-0 flex-1", children: resolve(header, collapsed) }),
2662
- onCollapsedChange && /* @__PURE__ */ jsx40(
2963
+ ) : /* @__PURE__ */ jsxs25(Fragment5, { children: [
2964
+ header && /* @__PURE__ */ jsx43("div", { className: "min-w-0 flex-1", children: resolve(header, collapsed) }),
2965
+ onCollapsedChange && /* @__PURE__ */ jsx43(
2663
2966
  "button",
2664
2967
  {
2665
2968
  type: "button",
2666
2969
  onClick: () => onCollapsedChange(!collapsed),
2667
2970
  "aria-label": "Collapse sidebar",
2668
2971
  className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground",
2669
- children: /* @__PURE__ */ jsx40(PanelLeftClose, { className: "h-4 w-4", "aria-hidden": true })
2972
+ children: /* @__PURE__ */ jsx43(ChevronDoubleLeftIcon, { className: "h-4 w-4", "aria-hidden": true })
2670
2973
  }
2671
2974
  )
2672
2975
  ] }) }),
2673
- /* @__PURE__ */ jsx40(SidebarNav, { children }),
2674
- footer && /* @__PURE__ */ jsx40("div", { className: "border-t border-border/50 px-2 py-2", children: resolve(footer, collapsed) }),
2675
- resizable && !collapsed && /* @__PURE__ */ jsx40(
2976
+ /* @__PURE__ */ jsx43(SidebarNav, { children }),
2977
+ footer && /* @__PURE__ */ jsx43("div", { className: "border-t border-border/50 px-2 py-2", children: resolve(footer, collapsed) }),
2978
+ resizable && !collapsed && /* @__PURE__ */ jsx43(
2676
2979
  "div",
2677
2980
  {
2678
2981
  onPointerDown: handlePointerDown,
@@ -2687,9 +2990,9 @@ function Sidebar({
2687
2990
  ) }) });
2688
2991
  }
2689
2992
  function SidebarNav({ children, className, ...rest }) {
2690
- const ref = useRef5(null);
2691
- const [showFade, setShowFade] = useState11(false);
2692
- useEffect5(() => {
2993
+ const ref = useRef6(null);
2994
+ const [showFade, setShowFade] = useState12(false);
2995
+ useEffect6(() => {
2693
2996
  const el = ref.current;
2694
2997
  if (!el) return;
2695
2998
  const update = () => setShowFade(el.scrollHeight - el.scrollTop - el.clientHeight > 1);
@@ -2702,8 +3005,8 @@ function SidebarNav({ children, className, ...rest }) {
2702
3005
  observer.disconnect();
2703
3006
  };
2704
3007
  }, []);
2705
- return /* @__PURE__ */ jsxs22("div", { className: "relative flex min-h-0 flex-1 flex-col", children: [
2706
- /* @__PURE__ */ jsx40(
3008
+ return /* @__PURE__ */ jsxs25("div", { className: "relative flex min-h-0 flex-1 flex-col", children: [
3009
+ /* @__PURE__ */ jsx43(
2707
3010
  "div",
2708
3011
  {
2709
3012
  ref,
@@ -2712,7 +3015,7 @@ function SidebarNav({ children, className, ...rest }) {
2712
3015
  children
2713
3016
  }
2714
3017
  ),
2715
- showFade && /* @__PURE__ */ jsx40(
3018
+ showFade && /* @__PURE__ */ jsx43(
2716
3019
  "div",
2717
3020
  {
2718
3021
  className: "pointer-events-none absolute right-0 bottom-0 left-0 h-6 bg-gradient-to-t from-sidebar to-transparent",
@@ -2723,11 +3026,11 @@ function SidebarNav({ children, className, ...rest }) {
2723
3026
  }
2724
3027
 
2725
3028
  // src/patterns/ai/AiButton.tsx
2726
- import { Sparkles } from "lucide-react";
3029
+ import { SparklesIcon } from "@heroicons/react/24/outline";
2727
3030
  import { forwardRef as forwardRef17 } from "react";
2728
- import { jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
3031
+ import { jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
2729
3032
  var AiButton = forwardRef17(
2730
- ({ variant = "ai-subtle", loading = false, icon: Icon2 = Sparkles, disabled, children, ...props }, ref) => /* @__PURE__ */ jsxs23(
3033
+ ({ variant = "ai-subtle", loading = false, icon: Icon2 = SparklesIcon, disabled, children, ...props }, ref) => /* @__PURE__ */ jsxs26(
2731
3034
  Button,
2732
3035
  {
2733
3036
  ref,
@@ -2736,7 +3039,7 @@ var AiButton = forwardRef17(
2736
3039
  "aria-busy": loading || void 0,
2737
3040
  ...props,
2738
3041
  children: [
2739
- loading ? /* @__PURE__ */ jsx41(LoadingSpinner, { size: "sm", className: "[&_svg]:text-current" }) : /* @__PURE__ */ jsx41(Icon2, { className: "h-4 w-4", "aria-hidden": "true" }),
3042
+ loading ? /* @__PURE__ */ jsx44(LoadingSpinner, { size: "sm", className: "[&_svg]:text-current" }) : /* @__PURE__ */ jsx44(Icon2, { className: "h-4 w-4", "aria-hidden": "true" }),
2740
3043
  children
2741
3044
  ]
2742
3045
  }
@@ -2745,9 +3048,9 @@ var AiButton = forwardRef17(
2745
3048
  AiButton.displayName = "AiButton";
2746
3049
 
2747
3050
  // src/patterns/ai/AiExplainButton.tsx
2748
- import { RefreshCw, Sparkles as Sparkles2 } from "lucide-react";
2749
- import { useState as useState12 } from "react";
2750
- import { jsx as jsx42, jsxs as jsxs24 } from "react/jsx-runtime";
3051
+ import { SparklesIcon as SparklesIcon2 } from "@heroicons/react/24/outline";
3052
+ import { useState as useState13 } from "react";
3053
+ import { jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
2751
3054
  function AiExplainButton({
2752
3055
  onExplain,
2753
3056
  label = "Explain",
@@ -2757,10 +3060,10 @@ function AiExplainButton({
2757
3060
  size = "sm",
2758
3061
  ...props
2759
3062
  }) {
2760
- const [open, setOpen] = useState12(false);
2761
- const [loading, setLoading] = useState12(false);
2762
- const [content, setContent] = useState12(null);
2763
- const [error, setError] = useState12(null);
3063
+ const [open, setOpen] = useState13(false);
3064
+ const [loading, setLoading] = useState13(false);
3065
+ const [content, setContent] = useState13(null);
3066
+ const [error, setError] = useState13(null);
2764
3067
  const load = async () => {
2765
3068
  setLoading(true);
2766
3069
  setError(null);
@@ -2776,30 +3079,32 @@ function AiExplainButton({
2776
3079
  setOpen(next);
2777
3080
  if (next && content === null && error === null && !loading) void load();
2778
3081
  };
2779
- return /* @__PURE__ */ jsxs24(Popover, { open, onOpenChange: handleOpenChange, children: [
2780
- /* @__PURE__ */ jsx42(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx42(AiButton, { size, ...props, children: label }) }),
2781
- /* @__PURE__ */ jsxs24(PopoverContent, { align, className: contentClassName, children: [
2782
- /* @__PURE__ */ jsxs24("p", { className: "mb-2 flex items-center gap-1.5 text-sm font-semibold", children: [
2783
- /* @__PURE__ */ jsx42(Sparkles2, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
3082
+ return /* @__PURE__ */ jsxs27(Popover, { open, onOpenChange: handleOpenChange, children: [
3083
+ /* @__PURE__ */ jsx45(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx45(AiButton, { size, ...props, children: label }) }),
3084
+ /* @__PURE__ */ jsxs27(PopoverContent, { align, className: contentClassName, children: [
3085
+ /* @__PURE__ */ jsxs27("p", { className: "mb-2 flex items-center gap-1.5 text-sm font-semibold", children: [
3086
+ /* @__PURE__ */ jsx45(SparklesIcon2, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
2784
3087
  title ?? label
2785
3088
  ] }),
2786
- loading ? /* @__PURE__ */ jsx42(LoadingSpinner, { size: "sm", label: "Thinking\u2026", className: "text-sm text-muted-foreground" }) : error ? /* @__PURE__ */ jsxs24("div", { className: "flex flex-col items-start gap-2", children: [
2787
- /* @__PURE__ */ jsx42("div", { role: "alert", className: "w-full", children: /* @__PURE__ */ jsx42(AlertBox, { variant: "error", children: error }) }),
2788
- /* @__PURE__ */ jsxs24(Button, { type: "button", variant: "outline", size: "sm", onClick: () => void load(), children: [
2789
- /* @__PURE__ */ jsx42(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
2790
- "Try again"
2791
- ] })
2792
- ] }) : /* @__PURE__ */ jsx42("div", { className: "max-h-80 overflow-y-auto text-sm leading-relaxed", children: content })
3089
+ loading ? /* @__PURE__ */ jsx45(LoadingSpinner, { size: "sm", label: "Thinking\u2026", className: "text-sm text-muted-foreground" }) : error ? /* @__PURE__ */ jsx45(
3090
+ ErrorState,
3091
+ {
3092
+ variant: "compact",
3093
+ error,
3094
+ onRetry: () => void load(),
3095
+ labels: { title: "Something went wrong", retry: "Try again" }
3096
+ }
3097
+ ) : /* @__PURE__ */ jsx45("div", { className: "max-h-80 overflow-y-auto text-sm leading-relaxed", children: content })
2793
3098
  ] })
2794
3099
  ] });
2795
3100
  }
2796
3101
 
2797
3102
  // src/patterns/ai/VoiceInputButton.tsx
2798
- import { Mic, MicOff } from "lucide-react";
3103
+ import { MicrophoneIcon, SlashIcon } from "@heroicons/react/24/outline";
2799
3104
  import { forwardRef as forwardRef18 } from "react";
2800
3105
 
2801
3106
  // src/patterns/ai/useSpeechRecognition.ts
2802
- import { useCallback as useCallback2, useEffect as useEffect6, useRef as useRef6, useState as useState13 } from "react";
3107
+ import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef7, useState as useState14 } from "react";
2803
3108
  function getCtor() {
2804
3109
  if (typeof window === "undefined") return void 0;
2805
3110
  const w = window;
@@ -2832,21 +3137,21 @@ function useSpeechRecognition({
2832
3137
  onError,
2833
3138
  engine
2834
3139
  } = {}) {
2835
- const [listening, setListening] = useState13(false);
2836
- const [interim, setInterim] = useState13("");
2837
- const [error, setError] = useState13(null);
2838
- const recognitionRef = useRef6(null);
2839
- const onResultRef = useRef6(onResult);
2840
- const onErrorRef = useRef6(onError);
2841
- const engineRef = useRef6(engine);
3140
+ const [listening, setListening] = useState14(false);
3141
+ const [interim, setInterim] = useState14("");
3142
+ const [error, setError] = useState14(null);
3143
+ const recognitionRef = useRef7(null);
3144
+ const onResultRef = useRef7(onResult);
3145
+ const onErrorRef = useRef7(onError);
3146
+ const engineRef = useRef7(engine);
2842
3147
  onResultRef.current = onResult;
2843
3148
  onErrorRef.current = onError;
2844
3149
  engineRef.current = engine;
2845
3150
  const supported = engine !== void 0 || getCtor() !== void 0;
2846
- const stop = useCallback2(() => {
3151
+ const stop = useCallback3(() => {
2847
3152
  recognitionRef.current?.stop();
2848
3153
  }, []);
2849
- const start = useCallback2(() => {
3154
+ const start = useCallback3(() => {
2850
3155
  if (recognitionRef.current) return;
2851
3156
  const recognition = engineRef.current ? engineRef.current() : browserEngine();
2852
3157
  if (!recognition) return;
@@ -2879,16 +3184,16 @@ function useSpeechRecognition({
2879
3184
  setListening(true);
2880
3185
  recognition.start();
2881
3186
  }, [lang]);
2882
- const toggle = useCallback2(() => {
3187
+ const toggle = useCallback3(() => {
2883
3188
  if (recognitionRef.current) stop();
2884
3189
  else start();
2885
3190
  }, [start, stop]);
2886
- useEffect6(() => () => recognitionRef.current?.abort(), []);
3191
+ useEffect7(() => () => recognitionRef.current?.abort(), []);
2887
3192
  return { supported, listening, interim, error, start, stop, toggle };
2888
3193
  }
2889
3194
 
2890
3195
  // src/patterns/ai/VoiceInputButton.tsx
2891
- import { jsx as jsx43, jsxs as jsxs25 } from "react/jsx-runtime";
3196
+ import { jsx as jsx46, jsxs as jsxs28 } from "react/jsx-runtime";
2892
3197
  var VoiceInputButton = forwardRef18(
2893
3198
  ({
2894
3199
  onTranscript,
@@ -2914,8 +3219,8 @@ var VoiceInputButton = forwardRef18(
2914
3219
  return (
2915
3220
  // `title` lives on the wrapper, not the button: buttonVariants sets
2916
3221
  // `disabled:pointer-events-none`, so a disabled button never shows its own.
2917
- /* @__PURE__ */ jsxs25("span", { className: "inline-flex min-w-0 items-center gap-2", title: supported ? void 0 : unsupportedTitle, children: [
2918
- /* @__PURE__ */ jsxs25(
3222
+ /* @__PURE__ */ jsxs28("span", { className: "inline-flex min-w-0 items-center gap-2", title: supported ? void 0 : unsupportedTitle, children: [
3223
+ /* @__PURE__ */ jsxs28(
2919
3224
  Button,
2920
3225
  {
2921
3226
  ref,
@@ -2932,12 +3237,25 @@ var VoiceInputButton = forwardRef18(
2932
3237
  ),
2933
3238
  ...props,
2934
3239
  children: [
2935
- supported ? /* @__PURE__ */ jsx43(Mic, { className: cn("h-4 w-4", listening && "animate-pulse motion-reduce:animate-none"), "aria-hidden": "true" }) : /* @__PURE__ */ jsx43(MicOff, { className: "h-4 w-4", "aria-hidden": "true" }),
3240
+ supported ? /* @__PURE__ */ jsx46(
3241
+ MicrophoneIcon,
3242
+ {
3243
+ className: cn("h-4 w-4", listening && "animate-pulse motion-reduce:animate-none"),
3244
+ "aria-hidden": "true"
3245
+ }
3246
+ ) : (
3247
+ // heroicons has no muted-mic glyph -- MicrophoneIcon plus SlashIcon
3248
+ // (same 24x24 viewBox/stroke) layered on top approximates one.
3249
+ /* @__PURE__ */ jsxs28("span", { className: "relative inline-flex h-4 w-4", "aria-hidden": "true", children: [
3250
+ /* @__PURE__ */ jsx46(MicrophoneIcon, { className: "h-4 w-4" }),
3251
+ /* @__PURE__ */ jsx46(SlashIcon, { className: "absolute inset-0 h-4 w-4" })
3252
+ ] })
3253
+ ),
2936
3254
  label
2937
3255
  ]
2938
3256
  }
2939
3257
  ),
2940
- showInterim && interim ? /* @__PURE__ */ jsx43("span", { "aria-live": "polite", className: "truncate text-sm text-muted-foreground italic", children: interim }) : null
3258
+ showInterim && interim ? /* @__PURE__ */ jsx46("span", { "aria-live": "polite", className: "truncate text-sm text-muted-foreground italic", children: interim }) : null
2941
3259
  ] })
2942
3260
  );
2943
3261
  }
@@ -2945,9 +3263,9 @@ var VoiceInputButton = forwardRef18(
2945
3263
  VoiceInputButton.displayName = "VoiceInputButton";
2946
3264
 
2947
3265
  // src/patterns/ai/VoiceTranscript.tsx
2948
- import { Undo2, Wand2 } from "lucide-react";
2949
- import { useState as useState14 } from "react";
2950
- import { jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
3266
+ import { ArrowUturnLeftIcon, SparklesIcon as SparklesIcon3 } from "@heroicons/react/24/outline";
3267
+ import { useState as useState15 } from "react";
3268
+ import { jsx as jsx47, jsxs as jsxs29 } from "react/jsx-runtime";
2951
3269
  function VoiceTranscript({
2952
3270
  value,
2953
3271
  onChange,
@@ -2961,9 +3279,9 @@ function VoiceTranscript({
2961
3279
  className,
2962
3280
  ...props
2963
3281
  }) {
2964
- const [loading, setLoading] = useState14(false);
2965
- const [error, setError] = useState14(null);
2966
- const [previous, setPrevious] = useState14(null);
3282
+ const [loading, setLoading] = useState15(false);
3283
+ const [error, setError] = useState15(null);
3284
+ const [previous, setPrevious] = useState15(null);
2967
3285
  const append = (chunk) => {
2968
3286
  onChange(value ? `${value.trimEnd()} ${chunk}` : chunk);
2969
3287
  };
@@ -2987,8 +3305,8 @@ function VoiceTranscript({
2987
3305
  onChange(previous);
2988
3306
  setPrevious(null);
2989
3307
  };
2990
- return /* @__PURE__ */ jsxs26("div", { className: cn("flex flex-col gap-2", className), ...props, children: [
2991
- /* @__PURE__ */ jsx44(
3308
+ return /* @__PURE__ */ jsxs29("div", { className: cn("flex flex-col gap-2", className), ...props, children: [
3309
+ /* @__PURE__ */ jsx47(
2992
3310
  Textarea,
2993
3311
  {
2994
3312
  value,
@@ -2999,8 +3317,8 @@ function VoiceTranscript({
2999
3317
  "aria-busy": loading || void 0
3000
3318
  }
3001
3319
  ),
3002
- /* @__PURE__ */ jsxs26("div", { className: "flex flex-wrap items-center gap-2", children: [
3003
- /* @__PURE__ */ jsx44(
3320
+ /* @__PURE__ */ jsxs29("div", { className: "flex flex-wrap items-center gap-2", children: [
3321
+ /* @__PURE__ */ jsx47(
3004
3322
  VoiceInputButton,
3005
3323
  {
3006
3324
  onTranscript: append,
@@ -3013,35 +3331,35 @@ function VoiceTranscript({
3013
3331
  disabled: disabled || loading
3014
3332
  }
3015
3333
  ),
3016
- onTransform ? /* @__PURE__ */ jsx44(
3334
+ onTransform ? /* @__PURE__ */ jsx47(
3017
3335
  AiButton,
3018
3336
  {
3019
3337
  variant: "ai",
3020
3338
  size: "sm",
3021
- icon: Wand2,
3339
+ icon: SparklesIcon3,
3022
3340
  loading,
3023
3341
  disabled: disabled || value.trim().length === 0,
3024
3342
  onClick: () => void transform(),
3025
3343
  children: transformLabel
3026
3344
  }
3027
3345
  ) : null,
3028
- previous !== null && !loading ? /* @__PURE__ */ jsxs26(Button, { type: "button", variant: "ghost", size: "sm", onClick: undo, children: [
3029
- /* @__PURE__ */ jsx44(Undo2, { className: "h-4 w-4", "aria-hidden": "true" }),
3346
+ previous !== null && !loading ? /* @__PURE__ */ jsxs29(Button, { type: "button", variant: "ghost", size: "sm", onClick: undo, children: [
3347
+ /* @__PURE__ */ jsx47(ArrowUturnLeftIcon, { className: "h-4 w-4", "aria-hidden": "true" }),
3030
3348
  "Undo"
3031
3349
  ] }) : null
3032
3350
  ] }),
3033
3351
  error ? (
3034
3352
  // AlertBox has no `role` prop, so the live region wraps it; same shape
3035
3353
  // a consuming app's own form errors take.
3036
- /* @__PURE__ */ jsx44("div", { role: "alert", children: /* @__PURE__ */ jsx44(AlertBox, { variant: "error", children: error }) })
3354
+ /* @__PURE__ */ jsx47("div", { role: "alert", children: /* @__PURE__ */ jsx47(AlertBox, { variant: "error", children: error }) })
3037
3355
  ) : null
3038
3356
  ] });
3039
3357
  }
3040
3358
 
3041
3359
  // src/patterns/stepper/Stepper.tsx
3042
- import { useEffect as useEffect7, useRef as useRef7 } from "react";
3043
- import { Check as Check5, Plus } from "lucide-react";
3044
- import { jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
3360
+ import { useEffect as useEffect8, useRef as useRef8 } from "react";
3361
+ import { CheckIcon as CheckIcon5, PlusIcon } from "@heroicons/react/24/outline";
3362
+ import { jsx as jsx48, jsxs as jsxs30 } from "react/jsx-runtime";
3045
3363
  function Stepper({
3046
3364
  step,
3047
3365
  maxStep,
@@ -3053,8 +3371,8 @@ function Stepper({
3053
3371
  scrollTestId = "stepper-scroll",
3054
3372
  newTestId
3055
3373
  }) {
3056
- const stepRefs = useRef7(/* @__PURE__ */ new Map());
3057
- useEffect7(() => {
3374
+ const stepRefs = useRef8(/* @__PURE__ */ new Map());
3375
+ useEffect8(() => {
3058
3376
  const activeStep = stepRefs.current.get(step);
3059
3377
  activeStep?.scrollIntoView({ block: "nearest", inline: "center" });
3060
3378
  }, [step]);
@@ -3062,19 +3380,19 @@ function Stepper({
3062
3380
  // onNew is pinned outside the horizontally-scrolling region below (a sibling of
3063
3381
  // it, not a child) so its own edge never scrolls off-screen along with the
3064
3382
  // later steps once the scroller's min-width doesn't fit the viewport.
3065
- /* @__PURE__ */ jsxs27("div", { className: "flex w-full shrink-0 items-center gap-2", children: [
3066
- /* @__PURE__ */ jsx45("nav", { "aria-label": navLabel, className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx45(
3383
+ /* @__PURE__ */ jsxs30("div", { className: "flex w-full shrink-0 items-center gap-2", children: [
3384
+ /* @__PURE__ */ jsx48("nav", { "aria-label": navLabel, className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx48(
3067
3385
  "div",
3068
3386
  {
3069
3387
  "data-testid": scrollTestId,
3070
3388
  className: "flex w-full items-center gap-0 overflow-x-auto px-2 py-1",
3071
- children: /* @__PURE__ */ jsx45("ol", { className: "flex min-w-[700px] flex-1 items-start", children: steps.map(({ n, label, phase }, i) => {
3389
+ children: /* @__PURE__ */ jsx48("ol", { className: "flex min-w-[700px] flex-1 items-start", children: steps.map(({ n, label, phase }, i) => {
3072
3390
  const done = step > n;
3073
3391
  const active = step === n;
3074
3392
  const navigable = n <= maxStep && n !== step;
3075
3393
  const last = i === steps.length - 1;
3076
- return /* @__PURE__ */ jsxs27("li", { className: cn("flex items-start", !last && "flex-1"), children: [
3077
- /* @__PURE__ */ jsxs27(
3394
+ return /* @__PURE__ */ jsxs30("li", { className: cn("flex items-start", !last && "flex-1"), children: [
3395
+ /* @__PURE__ */ jsxs30(
3078
3396
  "button",
3079
3397
  {
3080
3398
  ref: (element) => {
@@ -3090,17 +3408,17 @@ function Stepper({
3090
3408
  navigable ? "cursor-pointer hover:opacity-80" : "cursor-default"
3091
3409
  ),
3092
3410
  children: [
3093
- /* @__PURE__ */ jsx45(
3411
+ /* @__PURE__ */ jsx48(
3094
3412
  "div",
3095
3413
  {
3096
3414
  className: cn(
3097
3415
  "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-[11px] font-bold transition-colors",
3098
3416
  done ? "bg-primary/15 text-primary" : active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
3099
3417
  ),
3100
- children: done ? /* @__PURE__ */ jsx45(Check5, { className: "h-3 w-3" }) : n
3418
+ children: done ? /* @__PURE__ */ jsx48(CheckIcon5, { className: "h-3 w-3" }) : n
3101
3419
  }
3102
3420
  ),
3103
- /* @__PURE__ */ jsx45(
3421
+ /* @__PURE__ */ jsx48(
3104
3422
  "span",
3105
3423
  {
3106
3424
  className: cn(
@@ -3110,11 +3428,11 @@ function Stepper({
3110
3428
  children: label
3111
3429
  }
3112
3430
  ),
3113
- /* @__PURE__ */ jsx45("span", { className: "text-[9px] tracking-[0.5px] text-muted-foreground/50 uppercase", children: phase })
3431
+ /* @__PURE__ */ jsx48("span", { className: "text-[9px] tracking-[0.5px] text-muted-foreground/50 uppercase", children: phase })
3114
3432
  ]
3115
3433
  }
3116
3434
  ),
3117
- !last && /* @__PURE__ */ jsx45(
3435
+ !last && /* @__PURE__ */ jsx48(
3118
3436
  "div",
3119
3437
  {
3120
3438
  className: cn(
@@ -3127,7 +3445,7 @@ function Stepper({
3127
3445
  }) })
3128
3446
  }
3129
3447
  ) }),
3130
- onNew && /* @__PURE__ */ jsxs27(
3448
+ onNew && /* @__PURE__ */ jsxs30(
3131
3449
  "button",
3132
3450
  {
3133
3451
  "data-testid": newTestId,
@@ -3135,7 +3453,7 @@ function Stepper({
3135
3453
  title: newLabel,
3136
3454
  className: "flex shrink-0 items-center gap-1.5 rounded-lg border border-border px-3 py-1.5 text-[12px] font-semibold text-foreground transition-colors hover:bg-muted/50",
3137
3455
  children: [
3138
- /* @__PURE__ */ jsx45(Plus, { className: "h-3.5 w-3.5" }),
3456
+ /* @__PURE__ */ jsx48(PlusIcon, { className: "h-3.5 w-3.5" }),
3139
3457
  newLabel
3140
3458
  ]
3141
3459
  }
@@ -3147,6 +3465,7 @@ export {
3147
3465
  AiButton,
3148
3466
  AiExplainButton,
3149
3467
  AlertBox,
3468
+ AsyncBoundary,
3150
3469
  Badge,
3151
3470
  Button,
3152
3471
  ButtonGroup,
@@ -3184,13 +3503,16 @@ export {
3184
3503
  DropdownMenuSubContent,
3185
3504
  DropdownMenuSubTrigger,
3186
3505
  DropdownMenuTrigger,
3506
+ ErrorState,
3187
3507
  FormField,
3188
3508
  FormModal,
3509
+ InlineError,
3189
3510
  Input,
3190
3511
  KpiCard,
3191
3512
  Label,
3192
3513
  LoadingOverlay,
3193
3514
  LoadingSpinner,
3515
+ LoadingState,
3194
3516
  Modal,
3195
3517
  NavGroup,
3196
3518
  NavItem,
@@ -3199,6 +3521,7 @@ export {
3199
3521
  PopoverContent,
3200
3522
  PopoverTrigger,
3201
3523
  QuestionDialog,
3524
+ RefreshBar,
3202
3525
  ResponsivePanel,
3203
3526
  ScrollArea,
3204
3527
  ScrollBar,
@@ -3252,11 +3575,14 @@ export {
3252
3575
  badgeVariants,
3253
3576
  buttonVariants,
3254
3577
  cn,
3578
+ defaultErrorStateLabels,
3255
3579
  describeSpeechError,
3256
3580
  getConfirmButtonPlacement,
3257
3581
  isWindowsPlatform,
3258
3582
  loadingSpinnerIconVariants,
3259
3583
  sheetVariants,
3584
+ toErrorInfo,
3585
+ useDelayedFlag,
3260
3586
  useMediaQuery,
3261
3587
  useSidebarCollapsed,
3262
3588
  useSpeechRecognition