@salemcobalt/ui 0.2.0-rc.2 → 0.2.0-rc.21

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
@@ -14,6 +14,8 @@ function Button({
14
14
  iconEnd,
15
15
  loading = false,
16
16
  fullWidth = false,
17
+ shortcut,
18
+ iconOnly = false,
17
19
  type = "button",
18
20
  className,
19
21
  children,
@@ -36,6 +38,7 @@ function Button({
36
38
  "data-size": size,
37
39
  "data-loading": loading || void 0,
38
40
  "data-full-width": fullWidth || void 0,
41
+ "data-icon-only": iconOnly || void 0,
39
42
  "aria-busy": loading || void 0,
40
43
  onClick: handleClick,
41
44
  ...rest,
@@ -43,6 +46,7 @@ function Button({
43
46
  iconStart ? /* @__PURE__ */ jsx("span", { className: "sc-button__icon", "aria-hidden": "true", children: iconStart }) : null,
44
47
  /* @__PURE__ */ jsx("span", { className: "sc-button__label", children }),
45
48
  iconEnd ? /* @__PURE__ */ jsx("span", { className: "sc-button__icon", "aria-hidden": "true", children: iconEnd }) : null,
49
+ shortcut ? /* @__PURE__ */ jsx("span", { className: "sc-button__shortcut", "aria-hidden": "true", children: shortcut }) : null,
46
50
  loading ? /* @__PURE__ */ jsx("span", { className: "sc-button__spinner", "aria-hidden": "true" }) : null
47
51
  ]
48
52
  }
@@ -438,7 +442,19 @@ function XIcon(props) {
438
442
 
439
443
  // src/components/Dialog/Dialog.tsx
440
444
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
441
- function Root({ dismissible = true, onOpenChange, open, defaultOpen, children }) {
445
+ var REQUESTABLE = /* @__PURE__ */ new Set([
446
+ "escape-key",
447
+ "outside-press",
448
+ "close-press"
449
+ ]);
450
+ function Root({
451
+ dismissible = true,
452
+ onOpenChange,
453
+ onRequestClose,
454
+ open,
455
+ defaultOpen,
456
+ children
457
+ }) {
442
458
  return /* @__PURE__ */ jsx6(
443
459
  BaseDialog.Root,
444
460
  {
@@ -450,6 +466,11 @@ function Root({ dismissible = true, onOpenChange, open, defaultOpen, children })
450
466
  details.cancel();
451
467
  return;
452
468
  }
469
+ if (!next && onRequestClose && REQUESTABLE.has(details.reason)) {
470
+ details.cancel();
471
+ onRequestClose(details.reason);
472
+ return;
473
+ }
453
474
  onOpenChange?.(next);
454
475
  },
455
476
  children
@@ -457,7 +478,7 @@ function Root({ dismissible = true, onOpenChange, open, defaultOpen, children })
457
478
  );
458
479
  }
459
480
  var Trigger = BaseDialog.Trigger;
460
- function Content({ size = "md", className, children, ...rest }) {
481
+ function Content({ size = "md", variant = "dialog", className, children, ...rest }) {
461
482
  return /* @__PURE__ */ jsxs5(BaseDialog.Portal, { children: [
462
483
  /* @__PURE__ */ jsx6(BaseDialog.Backdrop, { className: "sc-dialog__backdrop" }),
463
484
  /* @__PURE__ */ jsx6(
@@ -465,6 +486,7 @@ function Content({ size = "md", className, children, ...rest }) {
465
486
  {
466
487
  className: cx("sc-dialog__popup", className),
467
488
  "data-size": size,
489
+ "data-variant": variant,
468
490
  "aria-modal": "true",
469
491
  ...rest,
470
492
  children
@@ -545,6 +567,9 @@ var iconNames = [
545
567
  "x"
546
568
  ];
547
569
 
570
+ // src/components/IconButton/IconButton.tsx
571
+ import { useRender as useRender2 } from "@base-ui/react/use-render";
572
+
548
573
  // src/components/Tooltip/Tooltip.tsx
549
574
  import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
550
575
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -582,7 +607,7 @@ var Provider = BaseTooltip.Provider;
582
607
  var Tooltip = Object.assign(TooltipBase, { Provider });
583
608
 
584
609
  // src/components/IconButton/IconButton.tsx
585
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
610
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
586
611
  function IconButton({
587
612
  label,
588
613
  children,
@@ -592,9 +617,12 @@ function IconButton({
592
617
  tooltipSide = "top",
593
618
  round = false,
594
619
  loading = false,
595
- type = "button",
620
+ dot,
621
+ type,
596
622
  className,
597
623
  onClick,
624
+ render,
625
+ ref,
598
626
  ...rest
599
627
  }) {
600
628
  const handleClick = (event) => {
@@ -604,10 +632,13 @@ function IconButton({
604
632
  }
605
633
  onClick?.(event);
606
634
  };
607
- const button = /* @__PURE__ */ jsxs7(
608
- "button",
609
- {
610
- type,
635
+ const button = useRender2({
636
+ render,
637
+ ref,
638
+ defaultTagName: "button",
639
+ props: {
640
+ // `type` only means something on a real button; a rendered link keeps its own attributes.
641
+ type: render ? type : type ?? "button",
611
642
  className: cx("sc-button", "sc-icon-button", className),
612
643
  "data-variant": variant,
613
644
  "data-size": size,
@@ -617,19 +648,20 @@ function IconButton({
617
648
  "aria-label": label,
618
649
  onClick: handleClick,
619
650
  ...rest,
620
- children: [
651
+ children: /* @__PURE__ */ jsxs7(Fragment2, { children: [
621
652
  /* @__PURE__ */ jsx8("span", { className: "sc-button__icon", "aria-hidden": "true", children }),
622
- loading ? /* @__PURE__ */ jsx8("span", { className: "sc-button__spinner", "aria-hidden": "true" }) : null
623
- ]
653
+ loading ? /* @__PURE__ */ jsx8("span", { className: "sc-button__spinner", "aria-hidden": "true" }) : null,
654
+ dot ? /* @__PURE__ */ jsx8("span", { className: "sc-icon-button__dot", "data-tone": dot, "aria-hidden": "true" }) : null
655
+ ] })
624
656
  }
625
- );
657
+ });
626
658
  if (!tooltip) return button;
627
659
  return /* @__PURE__ */ jsx8(Tooltip, { content: tooltip === true ? label : tooltip, side: tooltipSide, children: button });
628
660
  }
629
661
 
630
662
  // src/components/Menu/Menu.tsx
631
663
  import { Menu as BaseMenu } from "@base-ui/react/menu";
632
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
664
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
633
665
  function Root2({ open, defaultOpen, onOpenChange, disabled, modal = true, children }) {
634
666
  return /* @__PURE__ */ jsx9(
635
667
  BaseMenu.Root,
@@ -669,7 +701,7 @@ function ItemBody({
669
701
  trailing,
670
702
  children
671
703
  }) {
672
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
704
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
673
705
  /* @__PURE__ */ jsx9("span", { className: "sc-menu__icon", "aria-hidden": "true", children: icon }),
674
706
  /* @__PURE__ */ jsx9("span", { className: "sc-menu__label", children }),
675
707
  trailing !== void 0 ? /* @__PURE__ */ jsx9("span", { className: "sc-menu__trailing", children: trailing }) : null
@@ -678,8 +710,25 @@ function ItemBody({
678
710
  function Item({ icon, trailing, tone = "default", className, children, ...rest }) {
679
711
  return /* @__PURE__ */ jsx9(BaseMenu.Item, { className: cx("sc-menu__item", className), "data-tone": tone, ...rest, children: /* @__PURE__ */ jsx9(ItemBody, { icon, trailing, children }) });
680
712
  }
681
- function LinkItem({ icon, trailing, tone = "default", className, children, ...rest }) {
682
- return /* @__PURE__ */ jsx9(BaseMenu.LinkItem, { className: cx("sc-menu__item", className), "data-tone": tone, ...rest, children: /* @__PURE__ */ jsx9(ItemBody, { icon, trailing, children }) });
713
+ function LinkItem({
714
+ icon,
715
+ trailing,
716
+ tone = "default",
717
+ className,
718
+ closeOnClick = true,
719
+ children,
720
+ ...rest
721
+ }) {
722
+ return /* @__PURE__ */ jsx9(
723
+ BaseMenu.LinkItem,
724
+ {
725
+ className: cx("sc-menu__item", className),
726
+ "data-tone": tone,
727
+ closeOnClick,
728
+ ...rest,
729
+ children: /* @__PURE__ */ jsx9(ItemBody, { icon, trailing, children })
730
+ }
731
+ );
683
732
  }
684
733
  function CheckboxItem({ trailing, onCheckedChange, className, children, ...rest }) {
685
734
  return /* @__PURE__ */ jsxs8(
@@ -856,9 +905,14 @@ function Textarea({
856
905
  className,
857
906
  rows = 3,
858
907
  resize = "vertical",
908
+ variant = "default",
859
909
  onValueChange,
910
+ spellCheck,
911
+ autoCorrect,
912
+ autoCapitalize,
860
913
  ...rest
861
914
  }) {
915
+ const code = variant === "code";
862
916
  return /* @__PURE__ */ jsx12(
863
917
  FieldShell,
864
918
  {
@@ -874,9 +928,19 @@ function Textarea({
874
928
  children: /* @__PURE__ */ jsx12(
875
929
  Field3.Control,
876
930
  {
877
- render: /* @__PURE__ */ jsx12("textarea", { rows, ...rest }),
931
+ render: /* @__PURE__ */ jsx12(
932
+ "textarea",
933
+ {
934
+ rows,
935
+ spellCheck: spellCheck ?? (code ? false : void 0),
936
+ autoCorrect: autoCorrect ?? (code ? "off" : void 0),
937
+ autoCapitalize: autoCapitalize ?? (code ? "off" : void 0),
938
+ ...rest
939
+ }
940
+ ),
878
941
  className: "sc-input sc-textarea",
879
942
  "data-resize": resize,
943
+ "data-variant": code ? "code" : void 0,
880
944
  required,
881
945
  onValueChange: onValueChange ? (value) => onValueChange(value) : void 0
882
946
  }
@@ -887,6 +951,7 @@ function Textarea({
887
951
 
888
952
  // src/components/Select/Select.tsx
889
953
  import { Select as BaseSelect } from "@base-ui/react/select";
954
+ import { useState } from "react";
890
955
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
891
956
  function isGroup(entry) {
892
957
  return "options" in entry;
@@ -913,11 +978,27 @@ function Select({
913
978
  defaultValue,
914
979
  onValueChange,
915
980
  placeholder = "Choose\u2026",
981
+ clearable = false,
982
+ clearLabel = "Clear",
916
983
  readOnly,
917
984
  fullWidth = false,
918
985
  id
919
986
  }) {
920
987
  const items = options.flatMap((entry) => isGroup(entry) ? entry.options : [entry]);
988
+ const [internal, setInternal] = useState(defaultValue ?? null);
989
+ const controlled = value !== void 0;
990
+ const current = controlled ? value : internal;
991
+ const setValue = (next) => {
992
+ if (!controlled) setInternal(next);
993
+ onValueChange?.(next);
994
+ };
995
+ const canClear = clearable && current != null && !disabled && !readOnly;
996
+ const onTriggerKeyDown = (event) => {
997
+ if (canClear && (event.key === "Backspace" || event.key === "Delete")) {
998
+ event.preventDefault();
999
+ setValue(null);
1000
+ }
1001
+ };
921
1002
  return /* @__PURE__ */ jsx13(
922
1003
  FieldShell,
923
1004
  {
@@ -935,26 +1016,39 @@ function Select({
935
1016
  BaseSelect.Root,
936
1017
  {
937
1018
  items,
938
- value,
939
- defaultValue,
940
- onValueChange: onValueChange ? (next) => onValueChange(next) : void 0,
1019
+ value: current,
1020
+ onValueChange: (next) => setValue(next),
941
1021
  disabled,
942
1022
  required,
943
1023
  readOnly,
944
1024
  children: [
945
- /* @__PURE__ */ jsxs11(
946
- BaseSelect.Trigger,
947
- {
948
- id,
949
- className: "sc-select",
950
- "data-size": size,
951
- "data-full-width": fullWidth || void 0,
952
- children: [
953
- /* @__PURE__ */ jsx13(BaseSelect.Value, { className: "sc-select__value", placeholder }),
954
- /* @__PURE__ */ jsx13(BaseSelect.Icon, { className: "sc-select__icon", children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) })
955
- ]
956
- }
957
- ),
1025
+ /* @__PURE__ */ jsxs11("span", { className: "sc-select__wrap", "data-full-width": fullWidth || void 0, children: [
1026
+ /* @__PURE__ */ jsxs11(
1027
+ BaseSelect.Trigger,
1028
+ {
1029
+ id,
1030
+ className: "sc-select",
1031
+ "data-size": size,
1032
+ "data-full-width": fullWidth || void 0,
1033
+ "data-clearable": canClear || void 0,
1034
+ onKeyDown: onTriggerKeyDown,
1035
+ children: [
1036
+ /* @__PURE__ */ jsx13(BaseSelect.Value, { className: "sc-select__value", placeholder }),
1037
+ /* @__PURE__ */ jsx13(BaseSelect.Icon, { className: "sc-select__icon", children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) })
1038
+ ]
1039
+ }
1040
+ ),
1041
+ canClear ? /* @__PURE__ */ jsx13(
1042
+ "button",
1043
+ {
1044
+ type: "button",
1045
+ className: "sc-select__clear",
1046
+ "aria-label": clearLabel,
1047
+ onClick: () => setValue(null),
1048
+ children: /* @__PURE__ */ jsx13(XIcon, { size: "sm" })
1049
+ }
1050
+ ) : null
1051
+ ] }),
958
1052
  /* @__PURE__ */ jsx13(BaseSelect.Portal, { children: /* @__PURE__ */ jsx13(
959
1053
  BaseSelect.Positioner,
960
1054
  {
@@ -1054,7 +1148,7 @@ function Switch({
1054
1148
 
1055
1149
  // src/components/Tabs/Tabs.tsx
1056
1150
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
1057
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1151
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1058
1152
  function Root3({ className, onValueChange, ...rest }) {
1059
1153
  return /* @__PURE__ */ jsx16(
1060
1154
  BaseTabs.Root,
@@ -1065,17 +1159,26 @@ function Root3({ className, onValueChange, ...rest }) {
1065
1159
  }
1066
1160
  );
1067
1161
  }
1068
- function List({ fill = false, className, children, ...rest }) {
1069
- return /* @__PURE__ */ jsxs14(BaseTabs.List, { className: cx("sc-tabs__list", className), "data-fill": fill || void 0, ...rest, children: [
1070
- children,
1071
- /* @__PURE__ */ jsx16(BaseTabs.Indicator, { className: "sc-tabs__indicator" })
1072
- ] });
1162
+ function List({ fill = false, variant = "line", className, children, ...rest }) {
1163
+ return /* @__PURE__ */ jsxs14(
1164
+ BaseTabs.List,
1165
+ {
1166
+ className: cx("sc-tabs__list", className),
1167
+ "data-fill": fill || void 0,
1168
+ "data-variant": variant,
1169
+ ...rest,
1170
+ children: [
1171
+ children,
1172
+ /* @__PURE__ */ jsx16(BaseTabs.Indicator, { className: "sc-tabs__indicator" })
1173
+ ]
1174
+ }
1175
+ );
1073
1176
  }
1074
1177
  function Tab({ icon, count, className, children, ...rest }) {
1075
1178
  return /* @__PURE__ */ jsxs14(BaseTabs.Tab, { className: cx("sc-tabs__tab", className), ...rest, children: [
1076
1179
  icon ? /* @__PURE__ */ jsx16("span", { className: "sc-tabs__icon", "aria-hidden": "true", children: icon }) : null,
1077
1180
  /* @__PURE__ */ jsx16("span", { className: "sc-tabs__label", children }),
1078
- count != null ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
1181
+ count != null ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
1079
1182
  " ",
1080
1183
  /* @__PURE__ */ jsx16("span", { className: "sc-tabs__count", children: count })
1081
1184
  ] }) : null
@@ -1107,13 +1210,14 @@ function Separator2({ className, ...rest }) {
1107
1210
  return /* @__PURE__ */ jsx17(BaseToolbar.Separator, { className: cx("sc-toolbar__separator", className), ...rest });
1108
1211
  }
1109
1212
  var Button2 = BaseToolbar.Button;
1213
+ var Link = BaseToolbar.Link;
1110
1214
  function Spacer({ className }) {
1111
1215
  return /* @__PURE__ */ jsx17("div", { className: cx("sc-toolbar__spacer", className), "aria-hidden": "true" });
1112
1216
  }
1113
- var Toolbar = { Root: Root4, Group: Group2, Separator: Separator2, Button: Button2, Spacer };
1217
+ var Toolbar = { Root: Root4, Group: Group2, Separator: Separator2, Button: Button2, Link, Spacer };
1114
1218
 
1115
1219
  // src/components/Banner/Banner.tsx
1116
- import { useState } from "react";
1220
+ import { useState as useState2 } from "react";
1117
1221
  import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1118
1222
  var toneIcons = {
1119
1223
  info: /* @__PURE__ */ jsx18(InfoIcon, {}),
@@ -1135,7 +1239,7 @@ function Banner({
1135
1239
  children,
1136
1240
  ...rest
1137
1241
  }) {
1138
- const [dismissed, setDismissed] = useState(false);
1242
+ const [dismissed, setDismissed] = useState2(false);
1139
1243
  const visible = open ?? !dismissed;
1140
1244
  if (!visible) return null;
1141
1245
  const glyph = icon === false ? null : icon ?? toneIcons[tone];
@@ -1255,19 +1359,11 @@ var sizeByLevel = {
1255
1359
  5: "md",
1256
1360
  6: "sm"
1257
1361
  };
1258
- function Heading({
1259
- level = 2,
1260
- size,
1261
- as,
1262
- tone = "default",
1263
- truncate = false,
1264
- className,
1265
- ...rest
1266
- }) {
1362
+ function Heading({ level = 2, size, as, tone, truncate = false, className, ...rest }) {
1267
1363
  return createElement3(as ?? `h${level}`, {
1268
1364
  className: cx("sc-heading", className),
1269
1365
  "data-size": size ?? sizeByLevel[level],
1270
- "data-tone": tone,
1366
+ "data-tone": tone ?? (size === "overline" ? "muted" : "default"),
1271
1367
  "data-truncate": truncate || void 0,
1272
1368
  ...rest
1273
1369
  });
@@ -1283,26 +1379,53 @@ function Text({
1283
1379
  align,
1284
1380
  truncate = false,
1285
1381
  numeric = false,
1382
+ family = "sans",
1286
1383
  className,
1287
1384
  style,
1288
1385
  ...rest
1289
1386
  }) {
1290
- const clamp = typeof truncate === "number" ? truncate : void 0;
1387
+ const clamp2 = typeof truncate === "number" ? truncate : void 0;
1291
1388
  return createElement4(as, {
1292
1389
  className: cx("sc-text", className),
1293
1390
  "data-size": size,
1294
1391
  "data-tone": tone,
1295
1392
  "data-weight": weight,
1296
1393
  "data-align": align,
1297
- "data-truncate": truncate === true ? "" : clamp !== void 0 ? "clamp" : void 0,
1394
+ "data-truncate": truncate === true ? "" : clamp2 !== void 0 ? "clamp" : void 0,
1298
1395
  "data-numeric": numeric || void 0,
1299
- style: clamp !== void 0 ? { ...style, "--sc-text-lines": clamp } : style,
1396
+ "data-family": family === "mono" ? "mono" : void 0,
1397
+ style: clamp2 !== void 0 ? { ...style, "--sc-text-lines": clamp2 } : style,
1300
1398
  ...rest
1301
1399
  });
1302
1400
  }
1303
1401
 
1304
1402
  // src/components/Table/Table.tsx
1305
- import { jsx as jsx21 } from "react/jsx-runtime";
1403
+ import { Checkbox as BaseCheckbox2 } from "@base-ui/react/checkbox";
1404
+ import {
1405
+ createContext,
1406
+ useContext
1407
+ } from "react";
1408
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1409
+ var SelectionContext = createContext(null);
1410
+ var RowIdContext = createContext(void 0);
1411
+ function useSelection(part) {
1412
+ const selection = useContext(SelectionContext);
1413
+ if (!selection) throw new Error(`${part} needs Table.Root selection={useRowSelection(ids)}`);
1414
+ return selection;
1415
+ }
1416
+ function isTextEntry(target) {
1417
+ if (!(target instanceof HTMLElement)) return false;
1418
+ if (target.isContentEditable || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement)
1419
+ return true;
1420
+ return target instanceof HTMLInputElement && !["checkbox", "radio", "button", "submit", "reset", "image", "file", "color", "range"].includes(
1421
+ target.type
1422
+ );
1423
+ }
1424
+ var CONTROLS = 'a[href], button, input, select, textarea, label, summary, [role="checkbox"], [role="button"], [role="link"], [contenteditable="true"]';
1425
+ function fromControl(event) {
1426
+ const control = event.target instanceof Element ? event.target.closest(CONTROLS) : null;
1427
+ return control !== null && event.currentTarget.contains(control);
1428
+ }
1306
1429
  function Root5({
1307
1430
  stickyHeader = false,
1308
1431
  maxHeight,
@@ -1314,8 +1437,23 @@ function Root5({
1314
1437
  className,
1315
1438
  style,
1316
1439
  children,
1440
+ selection,
1441
+ onKeyDown,
1317
1442
  ...rest
1318
1443
  }) {
1444
+ const handleKeyDown = (event) => {
1445
+ onKeyDown?.(event);
1446
+ if (!selection || event.defaultPrevented) return;
1447
+ if (!(event.target instanceof Node) || !event.currentTarget.contains(event.target)) return;
1448
+ if (isTextEntry(event.target)) return;
1449
+ if ((event.metaKey || event.ctrlKey) && !event.altKey && event.key.toLowerCase() === "a") {
1450
+ event.preventDefault();
1451
+ selection.selectAll();
1452
+ } else if (event.key === "Escape" && selection.count > 0) {
1453
+ event.preventDefault();
1454
+ selection.clear();
1455
+ }
1456
+ };
1319
1457
  return /* @__PURE__ */ jsx21(
1320
1458
  "div",
1321
1459
  {
@@ -1331,8 +1469,9 @@ function Root5({
1331
1469
  "data-divided": divided || void 0,
1332
1470
  "data-layout": layout,
1333
1471
  style,
1472
+ onKeyDown: selection ? handleKeyDown : onKeyDown,
1334
1473
  ...rest,
1335
- children
1474
+ children: /* @__PURE__ */ jsx21(SelectionContext.Provider, { value: selection ?? null, children })
1336
1475
  }
1337
1476
  )
1338
1477
  }
@@ -1350,17 +1489,117 @@ function Body2({ className, ...rest }) {
1350
1489
  function Foot({ className, ...rest }) {
1351
1490
  return /* @__PURE__ */ jsx21("tfoot", { className: cx("sc-table__foot", className), ...rest });
1352
1491
  }
1353
- function Row({ selected = false, interactive = false, className, ...rest }) {
1354
- return /* @__PURE__ */ jsx21(
1492
+ function Row({
1493
+ selected,
1494
+ interactive = false,
1495
+ selectionId,
1496
+ className,
1497
+ onClick,
1498
+ onMouseDown,
1499
+ ...rest
1500
+ }) {
1501
+ const selection = useContext(SelectionContext);
1502
+ const selectable = selection !== null && selectionId !== void 0;
1503
+ const isSelected = selected ?? (selectable && selection.isSelected(selectionId));
1504
+ const row = /* @__PURE__ */ jsx21(
1355
1505
  "tr",
1356
1506
  {
1357
1507
  className: cx("sc-table__row", className),
1358
- "data-selected": selected || void 0,
1508
+ "data-selected": isSelected || void 0,
1359
1509
  "data-interactive": interactive || void 0,
1360
- "aria-selected": selected || void 0,
1510
+ "aria-selected": selectable ? isSelected : isSelected || void 0,
1511
+ onClick: selectable ? (event) => {
1512
+ if ((event.shiftKey || event.metaKey || event.ctrlKey) && !fromControl(event)) {
1513
+ event.preventDefault();
1514
+ if (event.shiftKey) selection.toggleRange(selectionId);
1515
+ else selection.toggle(selectionId);
1516
+ return;
1517
+ }
1518
+ onClick?.(event);
1519
+ } : onClick,
1520
+ onMouseDown: selectable ? (event) => {
1521
+ if (event.shiftKey && !fromControl(event)) event.preventDefault();
1522
+ onMouseDown?.(event);
1523
+ } : onMouseDown,
1361
1524
  ...rest
1362
1525
  }
1363
1526
  );
1527
+ return selectionId === void 0 ? row : /* @__PURE__ */ jsx21(RowIdContext.Provider, { value: selectionId, children: row });
1528
+ }
1529
+ function SelectionBox({
1530
+ label,
1531
+ ...rest
1532
+ }) {
1533
+ return /* @__PURE__ */ jsx21(BaseCheckbox2.Root, { className: "sc-checkbox", "aria-label": label, ...rest, children: /* @__PURE__ */ jsxs18(BaseCheckbox2.Indicator, { className: "sc-checkbox__indicator", children: [
1534
+ /* @__PURE__ */ jsx21(CheckIcon, { size: "sm", className: "sc-checkbox__check" }),
1535
+ /* @__PURE__ */ jsx21(MinusIcon, { size: "sm", className: "sc-checkbox__dash" })
1536
+ ] }) });
1537
+ }
1538
+ var onCheckbox = (event) => event.target instanceof Element && event.target.closest('[role="checkbox"]') !== null;
1539
+ function SelectionHeader({
1540
+ label = "Select all rows",
1541
+ className,
1542
+ onClick,
1543
+ ...rest
1544
+ }) {
1545
+ const selection = useSelection("Table.SelectionHeader");
1546
+ const disabled = selection.ids.length === 0;
1547
+ const toggleAll = () => selection.headerState === "all" ? selection.clear() : selection.selectAll();
1548
+ return /* @__PURE__ */ jsx21(
1549
+ "th",
1550
+ {
1551
+ scope: "col",
1552
+ className: cx("sc-table__header", "sc-table__select", className),
1553
+ "data-disabled": disabled || void 0,
1554
+ onClick: (event) => {
1555
+ onClick?.(event);
1556
+ if (!disabled && !onCheckbox(event)) toggleAll();
1557
+ },
1558
+ ...rest,
1559
+ children: /* @__PURE__ */ jsx21(
1560
+ SelectionBox,
1561
+ {
1562
+ label,
1563
+ checked: selection.headerState === "all",
1564
+ indeterminate: selection.headerState === "some",
1565
+ disabled,
1566
+ onCheckedChange: toggleAll
1567
+ }
1568
+ )
1569
+ }
1570
+ );
1571
+ }
1572
+ function SelectionCell({ label, className, onClick, onClickCapture, ...rest }) {
1573
+ const selection = useSelection("Table.SelectionCell");
1574
+ const id = useContext(RowIdContext);
1575
+ if (id === void 0) throw new Error("Table.SelectionCell goes inside a Table.Row with selectionId");
1576
+ return /* @__PURE__ */ jsx21(
1577
+ "td",
1578
+ {
1579
+ className: cx("sc-table__cell", "sc-table__select", className),
1580
+ onClickCapture: (event) => {
1581
+ onClickCapture?.(event);
1582
+ if (!event.shiftKey) return;
1583
+ event.preventDefault();
1584
+ event.stopPropagation();
1585
+ selection.toggleRange(id);
1586
+ },
1587
+ onClick: (event) => {
1588
+ onClick?.(event);
1589
+ event.stopPropagation();
1590
+ if (!onCheckbox(event)) selection.toggle(id);
1591
+ },
1592
+ ...rest,
1593
+ children: /* @__PURE__ */ jsx21(
1594
+ SelectionBox,
1595
+ {
1596
+ label,
1597
+ checked: selection.isSelected(id),
1598
+ onCheckedChange: () => selection.toggle(id)
1599
+ }
1600
+ )
1601
+ }
1602
+ );
1364
1603
  }
1365
1604
  function Header({
1366
1605
  align,
@@ -1368,11 +1607,16 @@ function Header({
1368
1607
  nowrap = false,
1369
1608
  truncate = false,
1370
1609
  width,
1610
+ sortable = false,
1611
+ sortDirection = "none",
1612
+ onSort,
1371
1613
  scope = "col",
1372
1614
  className,
1373
1615
  style,
1616
+ children,
1374
1617
  ...rest
1375
1618
  }) {
1619
+ const sorted = sortable && sortDirection !== "none";
1376
1620
  return /* @__PURE__ */ jsx21(
1377
1621
  "th",
1378
1622
  {
@@ -1382,8 +1626,23 @@ function Header({
1382
1626
  "data-numeric": numeric || void 0,
1383
1627
  "data-nowrap": nowrap || void 0,
1384
1628
  "data-truncate": truncate || void 0,
1629
+ "data-sortable": sortable || void 0,
1630
+ "data-sorted": sorted ? sortDirection : void 0,
1631
+ "aria-sort": sorted ? sortDirection : void 0,
1385
1632
  style: width ? { ...style, inlineSize: width } : style,
1386
- ...rest
1633
+ ...rest,
1634
+ children: sortable ? /* @__PURE__ */ jsxs18(
1635
+ "button",
1636
+ {
1637
+ type: "button",
1638
+ className: "sc-table__sort",
1639
+ onClick: () => onSort?.(sortDirection === "ascending" ? "descending" : "ascending"),
1640
+ children: [
1641
+ /* @__PURE__ */ jsx21("span", { className: "sc-table__sort-label", children }),
1642
+ /* @__PURE__ */ jsx21("span", { className: "sc-table__sort-icon", "aria-hidden": "true", children: sortDirection === "descending" ? /* @__PURE__ */ jsx21(ArrowDownIcon, { size: "xs" }) : /* @__PURE__ */ jsx21(ArrowUpIcon, { size: "xs" }) })
1643
+ ]
1644
+ }
1645
+ ) : children
1387
1646
  }
1388
1647
  );
1389
1648
  }
@@ -1410,15 +1669,248 @@ function Cell({
1410
1669
  }
1411
1670
  );
1412
1671
  }
1413
- var Table = { Root: Root5, Caption, Head, Body: Body2, Foot, Row, Header, Cell };
1672
+ var Table = { Root: Root5, Caption, Head, Body: Body2, Foot, Row, Header, Cell, SelectionHeader, SelectionCell };
1673
+
1674
+ // src/components/Table/useRowSelection.ts
1675
+ import { useMemo, useReducer } from "react";
1676
+
1677
+ // src/components/Table/rowSelection.ts
1678
+ function initRowSelection(ids) {
1679
+ return { ids, selected: /* @__PURE__ */ new Set(), anchor: null };
1680
+ }
1681
+ function sameIds(a, b) {
1682
+ if (a === b) return true;
1683
+ if (a.length !== b.length) return false;
1684
+ for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
1685
+ return true;
1686
+ }
1687
+ function toggle(state, id) {
1688
+ if (!state.ids.includes(id)) return state;
1689
+ const selected = new Set(state.selected);
1690
+ if (selected.has(id)) selected.delete(id);
1691
+ else selected.add(id);
1692
+ return { ...state, selected, anchor: id };
1693
+ }
1694
+ function toggleRange(state, id) {
1695
+ const to = state.ids.indexOf(id);
1696
+ if (to < 0) return state;
1697
+ const from = state.anchor === null ? -1 : state.ids.indexOf(state.anchor);
1698
+ if (from < 0 || from === to) return toggle(state, id);
1699
+ const on = !state.selected.has(id);
1700
+ const selected = new Set(state.selected);
1701
+ const [start, end] = from < to ? [from, to] : [to, from];
1702
+ for (let i = start; i <= end; i += 1) {
1703
+ const rowId = state.ids[i];
1704
+ if (on) selected.add(rowId);
1705
+ else selected.delete(rowId);
1706
+ }
1707
+ return { ...state, selected, anchor: id };
1708
+ }
1709
+ function sync(state, ids) {
1710
+ if (sameIds(state.ids, ids)) return state;
1711
+ const present = new Set(ids);
1712
+ let selected = state.selected;
1713
+ for (const id of state.selected) {
1714
+ if (present.has(id)) continue;
1715
+ selected = new Set([...state.selected].filter((x) => present.has(x)));
1716
+ break;
1717
+ }
1718
+ const anchor = state.anchor !== null && present.has(state.anchor) ? state.anchor : null;
1719
+ return { ids, selected, anchor };
1720
+ }
1721
+ function rowSelectionReducer(state, event) {
1722
+ switch (event.type) {
1723
+ case "selection.sync":
1724
+ return sync(state, event.ids);
1725
+ case "selection.toggle":
1726
+ return toggle(state, event.id);
1727
+ case "selection.toggleRange":
1728
+ return toggleRange(state, event.id);
1729
+ case "selection.selectAll":
1730
+ return state.selected.size === state.ids.length ? state : { ...state, selected: new Set(state.ids) };
1731
+ case "selection.clear":
1732
+ return state.selected.size === 0 && state.anchor === null ? state : { ...state, selected: /* @__PURE__ */ new Set(), anchor: null };
1733
+ }
1734
+ }
1735
+ function headerState(state) {
1736
+ if (state.selected.size === 0) return "none";
1737
+ return state.selected.size === state.ids.length ? "all" : "some";
1738
+ }
1739
+ function selectedIds(state) {
1740
+ return state.ids.filter((id) => state.selected.has(id));
1741
+ }
1742
+
1743
+ // src/components/Table/useRowSelection.ts
1744
+ function useRowSelection(ids) {
1745
+ const [stored, dispatch] = useReducer(rowSelectionReducer, ids, initRowSelection);
1746
+ const state = sameIds(stored.ids, ids) ? stored : rowSelectionReducer(stored, { type: "selection.sync", ids });
1747
+ if (state !== stored) dispatch({ type: "selection.sync", ids });
1748
+ const actions = useMemo(
1749
+ () => ({
1750
+ toggle: (id) => dispatch({ type: "selection.toggle", id }),
1751
+ toggleRange: (id) => dispatch({ type: "selection.toggleRange", id }),
1752
+ selectAll: () => dispatch({ type: "selection.selectAll" }),
1753
+ clear: () => dispatch({ type: "selection.clear" })
1754
+ }),
1755
+ []
1756
+ );
1757
+ return useMemo(
1758
+ () => ({
1759
+ ids: state.ids,
1760
+ selected: state.selected,
1761
+ selectedIds: selectedIds(state),
1762
+ count: state.selected.size,
1763
+ anchor: state.anchor,
1764
+ headerState: headerState(state),
1765
+ isSelected: (id) => state.selected.has(id),
1766
+ ...actions
1767
+ }),
1768
+ [state, actions]
1769
+ );
1770
+ }
1771
+
1772
+ // src/components/SelectionBar/SelectionBar.tsx
1773
+ import { useEffect, useLayoutEffect, useRef, useState as useState3 } from "react";
1774
+ import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
1775
+ var defaultCountLabel = (count) => `${count} selected`;
1776
+ var LEAVE_MS = 200;
1777
+ function SelectionBar({
1778
+ count,
1779
+ onClear,
1780
+ children,
1781
+ "aria-label": ariaLabel = "Bulk actions",
1782
+ countLabel = defaultCountLabel,
1783
+ clearLabel = "Clear",
1784
+ clearedMessage = "Selection cleared",
1785
+ className
1786
+ }) {
1787
+ const open = count > 0;
1788
+ const [hadSelection, setHadSelection] = useState3(open);
1789
+ if (open && !hadSelection) setHadSelection(true);
1790
+ const message = open ? countLabel(count) : hadSelection ? clearedMessage : "";
1791
+ const [rendered, setRendered] = useState3(open);
1792
+ const [shownCount, setShownCount] = useState3(count);
1793
+ if (open && !rendered) setRendered(true);
1794
+ if (open && shownCount !== count) setShownCount(count);
1795
+ useEffect(() => {
1796
+ if (open || !rendered) return;
1797
+ const timer = setTimeout(() => setRendered(false), LEAVE_MS);
1798
+ return () => clearTimeout(timer);
1799
+ }, [open, rendered]);
1800
+ const barRef = useRef(null);
1801
+ const returnTo = useRef(null);
1802
+ useLayoutEffect(() => {
1803
+ const bar = barRef.current;
1804
+ if (open || !bar?.contains(bar.ownerDocument.activeElement)) return;
1805
+ if (returnTo.current?.isConnected) returnTo.current.focus();
1806
+ }, [open]);
1807
+ const [height, setHeight] = useState3(0);
1808
+ useEffect(() => {
1809
+ const bar = barRef.current;
1810
+ if (!rendered || !bar || typeof ResizeObserver === "undefined") return;
1811
+ const observer = new ResizeObserver(([entry]) => setHeight(entry.borderBoxSize[0]?.blockSize ?? 0));
1812
+ observer.observe(bar);
1813
+ return () => observer.disconnect();
1814
+ }, [rendered]);
1815
+ return /* @__PURE__ */ jsxs19(Fragment5, { children: [
1816
+ /* @__PURE__ */ jsx22("span", { role: "status", className: "sc-visually-hidden", children: message }),
1817
+ rendered ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
1818
+ open ? /* @__PURE__ */ jsx22(
1819
+ "div",
1820
+ {
1821
+ className: "sc-selection-bar__spacer",
1822
+ style: { "--sc-selection-bar-height": `${height}px` },
1823
+ "aria-hidden": "true"
1824
+ }
1825
+ ) : null,
1826
+ /* @__PURE__ */ jsx22(
1827
+ "div",
1828
+ {
1829
+ ref: barRef,
1830
+ className: cx("sc-selection-bar", className),
1831
+ "data-open": open || void 0,
1832
+ onFocus: (event) => {
1833
+ const from = event.relatedTarget;
1834
+ if (from instanceof HTMLElement && !event.currentTarget.contains(from)) returnTo.current = from;
1835
+ },
1836
+ children: /* @__PURE__ */ jsxs19(Toolbar.Root, { "aria-label": ariaLabel, className: "sc-selection-bar__toolbar", children: [
1837
+ /* @__PURE__ */ jsx22("span", { className: "sc-selection-bar__count", children: countLabel(shownCount) }),
1838
+ /* @__PURE__ */ jsx22(Toolbar.Separator, {}),
1839
+ children,
1840
+ /* @__PURE__ */ jsx22(Toolbar.Spacer, {}),
1841
+ /* @__PURE__ */ jsx22(Toolbar.Button, { render: /* @__PURE__ */ jsx22(Button, { variant: "ghost", size: "sm" }), onClick: onClear, children: clearLabel })
1842
+ ] })
1843
+ }
1844
+ )
1845
+ ] }) : null
1846
+ ] });
1847
+ }
1848
+
1849
+ // src/components/Toast/Toast.tsx
1850
+ import { Toast as BaseToast } from "@base-ui/react/toast";
1851
+ import { useMemo as useMemo2 } from "react";
1852
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
1853
+ function Provider2({ children, timeout = 6e3, limit = 3 }) {
1854
+ return /* @__PURE__ */ jsxs20(BaseToast.Provider, { timeout, limit, children: [
1855
+ children,
1856
+ /* @__PURE__ */ jsx23(BaseToast.Portal, { children: /* @__PURE__ */ jsx23(Viewport, {}) })
1857
+ ] });
1858
+ }
1859
+ function Viewport() {
1860
+ const { toasts, close } = BaseToast.useToastManager();
1861
+ return /* @__PURE__ */ jsx23(BaseToast.Viewport, { className: "sc-toast-viewport", children: toasts.map((toast) => /* @__PURE__ */ jsxs20(BaseToast.Root, { toast, className: "sc-toast", "data-tone": toast.type ?? "neutral", children: [
1862
+ /* @__PURE__ */ jsxs20(BaseToast.Content, { className: "sc-toast__content", children: [
1863
+ /* @__PURE__ */ jsx23(BaseToast.Title, { className: "sc-toast__title" }),
1864
+ toast.description != null ? /* @__PURE__ */ jsx23(BaseToast.Description, { className: "sc-toast__description" }) : null
1865
+ ] }),
1866
+ toast.actionProps ? /* @__PURE__ */ jsx23(
1867
+ BaseToast.Action,
1868
+ {
1869
+ className: "sc-toast__action",
1870
+ render: /* @__PURE__ */ jsx23(Button, { variant: "secondary", size: "sm" })
1871
+ }
1872
+ ) : null,
1873
+ /* @__PURE__ */ jsx23(IconButton, { label: "Dismiss", size: "sm", className: "sc-toast__close", onClick: () => close(toast.id), children: /* @__PURE__ */ jsx23(XIcon, {}) })
1874
+ ] }, toast.id)) });
1875
+ }
1876
+ function useToast() {
1877
+ const manager = BaseToast.useToastManager();
1878
+ return useMemo2(
1879
+ () => ({
1880
+ add: ({ title, description, tone = "neutral", action, timeout, priority }) => {
1881
+ let id = "";
1882
+ id = manager.add({
1883
+ title,
1884
+ description,
1885
+ type: tone,
1886
+ ...timeout !== void 0 ? { timeout } : {},
1887
+ ...priority ? { priority } : {},
1888
+ ...action ? {
1889
+ actionProps: {
1890
+ children: action.label,
1891
+ onClick: () => {
1892
+ action.onClick();
1893
+ manager.close(id);
1894
+ }
1895
+ }
1896
+ } : {}
1897
+ });
1898
+ return id;
1899
+ },
1900
+ close: manager.close
1901
+ }),
1902
+ [manager]
1903
+ );
1904
+ }
1905
+ var Toast = { Provider: Provider2 };
1414
1906
 
1415
1907
  // src/components/Stat/Stat.tsx
1416
1908
  import { createElement as createElement5 } from "react";
1417
- import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1909
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
1418
1910
  var trendIcons = {
1419
- up: /* @__PURE__ */ jsx22(ArrowUpIcon, { size: "xs" }),
1420
- down: /* @__PURE__ */ jsx22(ArrowDownIcon, { size: "xs" }),
1421
- flat: /* @__PURE__ */ jsx22(ArrowRightIcon, { size: "xs" })
1911
+ up: /* @__PURE__ */ jsx24(ArrowUpIcon, { size: "xs" }),
1912
+ down: /* @__PURE__ */ jsx24(ArrowDownIcon, { size: "xs" }),
1913
+ flat: /* @__PURE__ */ jsx24(ArrowRightIcon, { size: "xs" })
1422
1914
  };
1423
1915
  function Stat({
1424
1916
  label,
@@ -1442,23 +1934,1712 @@ function Stat({
1442
1934
  "data-size": size,
1443
1935
  ...rest
1444
1936
  },
1445
- /* @__PURE__ */ jsxs18(Fragment4, { children: [
1446
- /* @__PURE__ */ jsx22("div", { className: "sc-stat__label", children: label }),
1447
- icon ? /* @__PURE__ */ jsx22("span", { className: "sc-stat__icon", "aria-hidden": "true", children: icon }) : null,
1448
- /* @__PURE__ */ jsx22("div", { className: "sc-stat__value", children: value }),
1449
- delta != null ? /* @__PURE__ */ jsxs18("div", { className: "sc-stat__delta", "data-tone": deltaTone, children: [
1450
- trend ? /* @__PURE__ */ jsx22("span", { className: "sc-stat__trend", "aria-hidden": "true", children: trendIcons[trend] }) : null,
1451
- trend ? /* @__PURE__ */ jsxs18("span", { className: "sc-visually-hidden", children: [
1937
+ /* @__PURE__ */ jsxs21(Fragment6, { children: [
1938
+ /* @__PURE__ */ jsx24("div", { className: "sc-stat__label", children: label }),
1939
+ icon ? /* @__PURE__ */ jsx24("span", { className: "sc-stat__icon", "aria-hidden": "true", children: icon }) : null,
1940
+ /* @__PURE__ */ jsx24("div", { className: "sc-stat__value", children: value }),
1941
+ delta != null ? /* @__PURE__ */ jsxs21("div", { className: "sc-stat__delta", "data-tone": deltaTone, children: [
1942
+ trend ? /* @__PURE__ */ jsx24("span", { className: "sc-stat__trend", "aria-hidden": "true", children: trendIcons[trend] }) : null,
1943
+ trend ? /* @__PURE__ */ jsxs21("span", { className: "sc-visually-hidden", children: [
1452
1944
  trend === "flat" ? "unchanged" : trend,
1453
1945
  " "
1454
1946
  ] }) : null,
1455
1947
  delta
1456
1948
  ] }) : null,
1457
- hint != null ? /* @__PURE__ */ jsx22("div", { className: "sc-stat__hint", children: hint }) : null
1949
+ hint != null ? /* @__PURE__ */ jsx24("div", { className: "sc-stat__hint", children: hint }) : null
1458
1950
  ] })
1459
1951
  );
1460
1952
  }
1461
1953
 
1954
+ // src/components/Chip/Chip.tsx
1955
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
1956
+ function Chip({
1957
+ children,
1958
+ icon,
1959
+ tone = "neutral",
1960
+ size = "md",
1961
+ selected = false,
1962
+ onClick,
1963
+ onRemove,
1964
+ removeLabel,
1965
+ disabled = false,
1966
+ className,
1967
+ ...rest
1968
+ }) {
1969
+ const interactive = onClick !== void 0;
1970
+ const removeName = removeLabel ?? (typeof children === "string" ? `Remove ${children}` : "Remove");
1971
+ const handleRemoveKey = (event) => {
1972
+ if (onRemove && !disabled && (event.key === "Backspace" || event.key === "Delete")) {
1973
+ event.preventDefault();
1974
+ onRemove();
1975
+ }
1976
+ };
1977
+ const shared = {
1978
+ className: cx("sc-chip", className),
1979
+ "data-tone": tone,
1980
+ "data-size": size,
1981
+ "data-selected": selected || void 0,
1982
+ "data-removable": onRemove ? "" : void 0,
1983
+ "data-disabled": disabled || void 0
1984
+ };
1985
+ const body = /* @__PURE__ */ jsxs22(Fragment7, { children: [
1986
+ icon ? /* @__PURE__ */ jsx25("span", { className: "sc-chip__icon", "aria-hidden": "true", children: icon }) : null,
1987
+ /* @__PURE__ */ jsx25("span", { className: "sc-chip__label", children })
1988
+ ] });
1989
+ const remove = onRemove ? /* @__PURE__ */ jsx25(
1990
+ "button",
1991
+ {
1992
+ type: "button",
1993
+ className: "sc-chip__remove",
1994
+ "aria-label": removeName,
1995
+ disabled,
1996
+ onClick: (event) => {
1997
+ event.stopPropagation();
1998
+ onRemove();
1999
+ },
2000
+ onKeyDown: handleRemoveKey,
2001
+ children: /* @__PURE__ */ jsx25(XIcon, { size: "xs" })
2002
+ }
2003
+ ) : null;
2004
+ if (interactive) {
2005
+ return /* @__PURE__ */ jsxs22("span", { ...shared, ...rest, children: [
2006
+ /* @__PURE__ */ jsx25(
2007
+ "button",
2008
+ {
2009
+ type: "button",
2010
+ className: "sc-chip__action",
2011
+ "aria-pressed": selected,
2012
+ disabled,
2013
+ onClick,
2014
+ onKeyDown: handleRemoveKey,
2015
+ children: body
2016
+ }
2017
+ ),
2018
+ remove
2019
+ ] });
2020
+ }
2021
+ return /* @__PURE__ */ jsxs22("span", { ...shared, ...rest, children: [
2022
+ body,
2023
+ remove
2024
+ ] });
2025
+ }
2026
+
2027
+ // src/components/Disclosure/Disclosure.tsx
2028
+ import {
2029
+ useEffect as useEffect2,
2030
+ useRef as useRef2,
2031
+ useState as useState4
2032
+ } from "react";
2033
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
2034
+ function Disclosure({
2035
+ summary,
2036
+ summaryOpen,
2037
+ open,
2038
+ defaultOpen = false,
2039
+ onOpenChange,
2040
+ previewLines,
2041
+ summaryPosition,
2042
+ className,
2043
+ style,
2044
+ children,
2045
+ ref,
2046
+ ...rest
2047
+ }) {
2048
+ const controlled = open !== void 0;
2049
+ const [internal, setInternal] = useState4(defaultOpen);
2050
+ const isOpen = controlled ? open : internal;
2051
+ const inner = useRef2(null);
2052
+ useEffect2(() => {
2053
+ if (controlled && inner.current && inner.current.open !== open) inner.current.open = open;
2054
+ });
2055
+ const onToggle = (event) => {
2056
+ const next = event.currentTarget.open;
2057
+ if (next === isOpen) return;
2058
+ if (!controlled) setInternal(next);
2059
+ onOpenChange?.(next);
2060
+ };
2061
+ const position = summaryPosition ?? (previewLines ? "end" : "start");
2062
+ return /* @__PURE__ */ jsxs23(
2063
+ "details",
2064
+ {
2065
+ ref: (node) => {
2066
+ inner.current = node;
2067
+ if (typeof ref === "function") ref(node);
2068
+ else if (ref) ref.current = node;
2069
+ },
2070
+ className: cx("sc-disclosure", className),
2071
+ open: isOpen,
2072
+ onToggle,
2073
+ "data-summary-position": position,
2074
+ "data-preview": previewLines ? "" : void 0,
2075
+ style: previewLines ? { ...style, "--_lines": previewLines } : style,
2076
+ ...rest,
2077
+ children: [
2078
+ /* @__PURE__ */ jsxs23("summary", { className: "sc-disclosure__summary", children: [
2079
+ /* @__PURE__ */ jsx26(ChevronDownIcon, { className: "sc-disclosure__chevron" }),
2080
+ /* @__PURE__ */ jsx26("span", { className: "sc-disclosure__summary-text", children: isOpen && summaryOpen != null ? summaryOpen : summary })
2081
+ ] }),
2082
+ /* @__PURE__ */ jsx26("div", { className: "sc-disclosure__content", children })
2083
+ ]
2084
+ }
2085
+ );
2086
+ }
2087
+
2088
+ // src/components/EmptyState/EmptyState.tsx
2089
+ import { createElement as createElement6 } from "react";
2090
+ import { jsx as jsx27 } from "react/jsx-runtime";
2091
+ function EmptyState({
2092
+ title,
2093
+ description,
2094
+ icon,
2095
+ children,
2096
+ size = "md",
2097
+ as = "div",
2098
+ className,
2099
+ ...rest
2100
+ }) {
2101
+ return createElement6(
2102
+ as,
2103
+ { className: cx("sc-empty-state", className), "data-size": size, ...rest },
2104
+ icon ? /* @__PURE__ */ jsx27("span", { className: "sc-empty-state__icon", "aria-hidden": "true", children: icon }) : null,
2105
+ /* @__PURE__ */ jsx27("p", { className: "sc-empty-state__title", children: title }),
2106
+ description != null ? /* @__PURE__ */ jsx27("p", { className: "sc-empty-state__description", children: description }) : null,
2107
+ children != null ? /* @__PURE__ */ jsx27("div", { className: "sc-empty-state__actions", children }) : null
2108
+ );
2109
+ }
2110
+
2111
+ // src/components/Skeleton/Skeleton.tsx
2112
+ import { jsx as jsx28 } from "react/jsx-runtime";
2113
+ function Skeleton({
2114
+ variant = "text",
2115
+ width,
2116
+ height,
2117
+ lines = 1,
2118
+ still = false,
2119
+ className,
2120
+ style,
2121
+ ...rest
2122
+ }) {
2123
+ const size = {
2124
+ ...style,
2125
+ ...width !== void 0 ? { inlineSize: width } : {},
2126
+ ...height !== void 0 ? { blockSize: height } : {}
2127
+ };
2128
+ if (variant === "text" && lines > 1) {
2129
+ return /* @__PURE__ */ jsx28("span", { className: cx("sc-skeleton-lines", className), "aria-hidden": "true", style, ...rest, children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx28(
2130
+ "span",
2131
+ {
2132
+ className: "sc-skeleton",
2133
+ "data-variant": "text",
2134
+ "data-still": still || void 0,
2135
+ "data-last": i === lines - 1 || void 0,
2136
+ style: width !== void 0 ? { inlineSize: width } : void 0
2137
+ },
2138
+ i
2139
+ )) });
2140
+ }
2141
+ return /* @__PURE__ */ jsx28(
2142
+ "span",
2143
+ {
2144
+ className: cx("sc-skeleton", className),
2145
+ "data-variant": variant,
2146
+ "data-still": still || void 0,
2147
+ "aria-hidden": "true",
2148
+ style: size,
2149
+ ...rest
2150
+ }
2151
+ );
2152
+ }
2153
+
2154
+ // src/components/FileInput/FileInput.tsx
2155
+ import { useEffect as useEffect4, useId as useId3, useRef as useRef4, useState as useState6 } from "react";
2156
+
2157
+ // src/components/FilePreviewDialog/FilePreviewDialog.tsx
2158
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState5 } from "react";
2159
+
2160
+ // src/components/FileInput/accept.ts
2161
+ function parseAccept(accept) {
2162
+ if (accept == null) return [];
2163
+ const list = typeof accept === "string" ? accept.split(",") : accept;
2164
+ return list.map((entry) => entry.trim().toLowerCase()).filter(Boolean);
2165
+ }
2166
+ function matchesAccept(file, accept) {
2167
+ if (accept.length === 0) return true;
2168
+ const name = file.name.toLowerCase();
2169
+ const type = file.type.toLowerCase();
2170
+ return accept.some((entry) => {
2171
+ if (entry.startsWith(".")) return name.endsWith(entry);
2172
+ if (entry.endsWith("/*")) return type.startsWith(entry.slice(0, -1));
2173
+ return type === entry;
2174
+ });
2175
+ }
2176
+ var UNITS = { b: 1, kb: 1e3, mb: 1e6, gb: 1e9 };
2177
+ function parseSize(size) {
2178
+ if (size == null) return void 0;
2179
+ if (typeof size === "number") return size;
2180
+ const match = /^\s*(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)\s*$/i.exec(size);
2181
+ if (!match) throw new Error(`FileInput: maxFileSize "${size}" is not a size like "10MB".`);
2182
+ return Math.round(Number(match[1]) * UNITS[match[2].toLowerCase()]);
2183
+ }
2184
+ function formatSize(bytes) {
2185
+ const [unit, base] = bytes >= 1e9 ? ["GB", 1e9] : bytes >= 1e6 ? ["MB", 1e6] : bytes >= 1e3 ? ["KB", 1e3] : ["bytes", 1];
2186
+ const value = bytes / base;
2187
+ return `${Number.isInteger(value) ? value : Number(value.toFixed(1))} ${unit}`;
2188
+ }
2189
+ function formatListSize(bytes) {
2190
+ const n = Math.round(Math.abs(bytes));
2191
+ const trim = (value, decimals) => value.toFixed(decimals).replace(/\.0+$/, "");
2192
+ if (n < 1e3) return `${n} bytes`;
2193
+ if (n < 1e6) return `${Math.floor(n / 1e3)} KB`;
2194
+ if (n < 1e9) return `${trim(n / 1e6, 1)} MB`;
2195
+ return `${trim(n / 1e9, 2)} GB`;
2196
+ }
2197
+ var MIME_NAMES = {
2198
+ "application/pdf": "PDF",
2199
+ "application/msword": "DOC",
2200
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX",
2201
+ "application/json": "JSON",
2202
+ "text/plain": "plain text",
2203
+ "text/markdown": "Markdown",
2204
+ "text/csv": "CSV",
2205
+ "image/png": "PNG",
2206
+ "image/jpeg": "JPEG"
2207
+ };
2208
+ function describeAccept(accept) {
2209
+ const names = accept.map((entry) => {
2210
+ if (entry.startsWith(".")) return entry.slice(1).toUpperCase();
2211
+ if (entry.endsWith("/*")) return `any ${entry.slice(0, -2)}`;
2212
+ return MIME_NAMES[entry] ?? entry.split("/").pop().toUpperCase();
2213
+ });
2214
+ const unique = [...new Set(names)];
2215
+ if (unique.length <= 1) return unique[0] ?? "";
2216
+ return `${unique.slice(0, -1).join(", ")} or ${unique.at(-1)}`;
2217
+ }
2218
+ function rejectionMessage(reason, detail) {
2219
+ switch (reason) {
2220
+ case "type":
2221
+ return `${detail.name} is not an accepted file type. Use ${detail.acceptLabel}.`;
2222
+ case "size":
2223
+ return `${detail.name} is ${formatSize(detail.size ?? 0)}, over the ${formatSize(detail.maxFileSize ?? 0)} limit.`;
2224
+ case "count":
2225
+ return detail.maxFiles === 1 ? "Choose one file." : `Up to ${detail.maxFiles} files. Remove one to add another.`;
2226
+ }
2227
+ }
2228
+ function escapeHtml(text) {
2229
+ return text.replace(
2230
+ /[&<>"']/g,
2231
+ (ch) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[ch]
2232
+ );
2233
+ }
2234
+ var extensionOf = (name) => {
2235
+ const dot = name.lastIndexOf(".");
2236
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
2237
+ };
2238
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set(["txt", "text", "md", "markdown"]);
2239
+ var TEXT_TYPES = /* @__PURE__ */ new Set(["text/plain", "text/markdown", "text/x-markdown"]);
2240
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "webp", "avif", "svg", "bmp"]);
2241
+ var UNDRAWABLE_IMAGE_TYPES = /* @__PURE__ */ new Set(["image/heic", "image/heif", "image/tiff"]);
2242
+ function previewKind(file) {
2243
+ const ext = extensionOf(file.name);
2244
+ const type = file.type.toLowerCase();
2245
+ if (ext === "pdf" || type === "application/pdf") return "pdf";
2246
+ if (TEXT_EXTENSIONS.has(ext) || TEXT_TYPES.has(type)) return "text";
2247
+ if (UNDRAWABLE_IMAGE_TYPES.has(type)) return null;
2248
+ if (IMAGE_EXTENSIONS.has(ext) || type.startsWith("image/")) return "image";
2249
+ return null;
2250
+ }
2251
+ function fileTypeLabel(file) {
2252
+ const ext = extensionOf(file.name);
2253
+ if (ext) return ext.toUpperCase();
2254
+ return MIME_NAMES[file.type.toLowerCase()] ?? (file.type.split("/").pop()?.toUpperCase() || "File");
2255
+ }
2256
+
2257
+ // src/utils/useMediaQuery.ts
2258
+ import { useCallback, useSyncExternalStore } from "react";
2259
+ function useMediaQuery(query) {
2260
+ const subscribe = useCallback(
2261
+ (onChange) => {
2262
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
2263
+ };
2264
+ const list = window.matchMedia(query);
2265
+ list.addEventListener?.("change", onChange);
2266
+ return () => list.removeEventListener?.("change", onChange);
2267
+ },
2268
+ [query]
2269
+ );
2270
+ return useSyncExternalStore(
2271
+ subscribe,
2272
+ () => typeof window.matchMedia === "function" && window.matchMedia(query).matches,
2273
+ () => false
2274
+ );
2275
+ }
2276
+
2277
+ // src/components/FilePreviewDialog/FilePreviewDialog.tsx
2278
+ import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2279
+ var TEXT_LIMIT = 1e6;
2280
+ var NARROW = "(max-width: 48rem)";
2281
+ function FilePreviewDialog({ file, open, onOpenChange, finalFocus }) {
2282
+ const kind = file ? previewKind(file) : null;
2283
+ const narrow = useMediaQuery(NARROW);
2284
+ const pdfInTab = kind === "pdf" && narrow;
2285
+ return /* @__PURE__ */ jsx29(Dialog.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs24(
2286
+ Dialog.Content,
2287
+ {
2288
+ size: "lg",
2289
+ className: "sc-file-preview",
2290
+ "data-kind": kind ?? "none",
2291
+ finalFocus,
2292
+ children: [
2293
+ /* @__PURE__ */ jsx29(Dialog.Close, {}),
2294
+ file ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
2295
+ /* @__PURE__ */ jsx29(Dialog.Title, { children: file.name }),
2296
+ /* @__PURE__ */ jsxs24(Dialog.Description, { children: [
2297
+ fileTypeLabel(file),
2298
+ ", ",
2299
+ formatListSize(file.size)
2300
+ ] }),
2301
+ /* @__PURE__ */ jsx29(Dialog.Body, { children: /* @__PURE__ */ jsx29(PreviewBody, { file, kind, open, pdfInTab }) })
2302
+ ] }) : /* @__PURE__ */ jsx29(Dialog.Title, { children: "Preview" })
2303
+ ]
2304
+ }
2305
+ ) });
2306
+ }
2307
+ function PreviewBody({
2308
+ file,
2309
+ kind,
2310
+ open,
2311
+ pdfInTab
2312
+ }) {
2313
+ const frameRef = useRef3(null);
2314
+ const imageRef = useRef3(null);
2315
+ const linkRef = useRef3(null);
2316
+ const [text, setText] = useState5(null);
2317
+ useEffect3(() => {
2318
+ if (!open || kind !== "pdf" && kind !== "image") return void 0;
2319
+ const url = URL.createObjectURL(kind === "pdf" ? new Blob([file], { type: "application/pdf" }) : file);
2320
+ if (frameRef.current) frameRef.current.src = url;
2321
+ if (imageRef.current) imageRef.current.src = url;
2322
+ if (linkRef.current) linkRef.current.href = url;
2323
+ return () => URL.revokeObjectURL(url);
2324
+ }, [open, file, kind, pdfInTab]);
2325
+ useEffect3(() => {
2326
+ if (!open || kind !== "text") return void 0;
2327
+ let cancelled = false;
2328
+ void file.slice(0, TEXT_LIMIT).text().then((value) => {
2329
+ if (!cancelled) setText({ file, value });
2330
+ });
2331
+ return () => {
2332
+ cancelled = true;
2333
+ };
2334
+ }, [open, file, kind]);
2335
+ if (kind === "pdf") {
2336
+ const link = (
2337
+ // eslint-disable-next-line jsx-a11y/anchor-is-valid -- the effect above sets href to the object URL on mount
2338
+ /* @__PURE__ */ jsxs24(
2339
+ "a",
2340
+ {
2341
+ ref: linkRef,
2342
+ className: "sc-button",
2343
+ "data-variant": pdfInTab ? "primary" : "secondary",
2344
+ "data-size": "md",
2345
+ target: "_blank",
2346
+ rel: "noopener",
2347
+ children: [
2348
+ "Open in a new tab",
2349
+ /* @__PURE__ */ jsx29(ExternalLinkIcon, {})
2350
+ ]
2351
+ }
2352
+ )
2353
+ );
2354
+ return pdfInTab ? /* @__PURE__ */ jsxs24("div", { className: "sc-file-preview__tab", children: [
2355
+ /* @__PURE__ */ jsx29("p", { className: "sc-file-preview__note", children: "On a small screen the PDF reads best in its own tab." }),
2356
+ link
2357
+ ] }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
2358
+ /* @__PURE__ */ jsx29("iframe", { ref: frameRef, className: "sc-file-preview__frame", title: `Preview of ${file.name}` }),
2359
+ /* @__PURE__ */ jsx29("div", { className: "sc-file-preview__actions", children: link })
2360
+ ] });
2361
+ }
2362
+ if (kind === "text") {
2363
+ const value = text?.file === file ? text.value : null;
2364
+ return /* @__PURE__ */ jsxs24(Fragment8, { children: [
2365
+ /* @__PURE__ */ jsx29(
2366
+ "pre",
2367
+ {
2368
+ className: "sc-file-preview__text",
2369
+ role: "region",
2370
+ tabIndex: 0,
2371
+ "aria-label": `Contents of ${file.name}`,
2372
+ "aria-busy": value == null || void 0,
2373
+ children: value
2374
+ }
2375
+ ),
2376
+ file.size > TEXT_LIMIT ? /* @__PURE__ */ jsxs24("p", { className: "sc-file-preview__note", children: [
2377
+ "Showing the first ",
2378
+ formatSize(TEXT_LIMIT),
2379
+ "."
2380
+ ] }) : null
2381
+ ] });
2382
+ }
2383
+ if (kind === "image") {
2384
+ return /* @__PURE__ */ jsx29("img", { ref: imageRef, className: "sc-file-preview__image", alt: file.name });
2385
+ }
2386
+ return /* @__PURE__ */ jsxs24("p", { className: "sc-file-preview__note", children: [
2387
+ "There is no preview for ",
2388
+ fileTypeLabel(file),
2389
+ " files."
2390
+ ] });
2391
+ }
2392
+
2393
+ // src/components/FileInput/FileInput.tsx
2394
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
2395
+ var REMOVE_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>';
2396
+ var sameFiles = (a, b) => a.length === b.length && a.every((file, i) => file === b[i]);
2397
+ function FileInput({
2398
+ label,
2399
+ hideLabel = false,
2400
+ description,
2401
+ error,
2402
+ invalid = false,
2403
+ required = false,
2404
+ disabled = false,
2405
+ name,
2406
+ size = "md",
2407
+ className,
2408
+ accept,
2409
+ acceptLabel,
2410
+ maxFileSize,
2411
+ multiple = false,
2412
+ maxFiles,
2413
+ files,
2414
+ defaultFiles,
2415
+ onFilesChange,
2416
+ idleLabel,
2417
+ browseLabel = "browse",
2418
+ preview = true
2419
+ }) {
2420
+ const id = useId3();
2421
+ const labelId = `${id}label`;
2422
+ const descriptionId = `${id}description`;
2423
+ const messagesId = `${id}messages`;
2424
+ const controlled = files !== void 0;
2425
+ const [uncontrolledFiles, setUncontrolledFiles] = useState6(defaultFiles ?? []);
2426
+ const current = controlled ? files : uncontrolledFiles;
2427
+ const [rejections, setRejections] = useState6([]);
2428
+ const [inputId, setInputId] = useState6();
2429
+ const [previewFile, setPreviewFile] = useState6(null);
2430
+ const [previewOpen, setPreviewOpen] = useState6(false);
2431
+ const previewTriggerRef = useRef4(null);
2432
+ const [pondVersion, setPondVersion] = useState6(0);
2433
+ const hostRef = useRef4(null);
2434
+ const pondRef = useRef4(null);
2435
+ const moduleRef = useRef4(null);
2436
+ const patchRef = useRef4(() => {
2437
+ });
2438
+ const settledRef = useRef4(current);
2439
+ const targetRef = useRef4(null);
2440
+ const acceptList = parseAccept(accept);
2441
+ const acceptAttr = acceptList.join(",");
2442
+ const maxBytes = parseSize(maxFileSize);
2443
+ const messages = [...rejections, ...error != null ? [error] : []];
2444
+ const isInvalid = invalid || messages.length > 0;
2445
+ const idleText = idleLabel ?? (multiple ? "Drop files here or" : current.length > 0 ? "Drop another file to replace it, or" : "Drop a file here or");
2446
+ const live = {
2447
+ acceptList,
2448
+ acceptLabel: acceptLabel ?? describeAccept(acceptList),
2449
+ maxBytes,
2450
+ maxFiles: multiple ? maxFiles : 1,
2451
+ multiple,
2452
+ current,
2453
+ controlled,
2454
+ onFilesChange,
2455
+ labelId,
2456
+ describedBy: [description != null ? descriptionId : null, messages.length > 0 ? messagesId : null],
2457
+ isInvalid,
2458
+ acceptAttr,
2459
+ preview: preview && !disabled,
2460
+ openPreview: (file, trigger) => {
2461
+ previewTriggerRef.current = trigger;
2462
+ setPreviewFile(file);
2463
+ setPreviewOpen(true);
2464
+ }
2465
+ };
2466
+ const liveRef = useRef4(live);
2467
+ useEffect4(() => {
2468
+ liveRef.current = live;
2469
+ });
2470
+ useEffect4(() => {
2471
+ let cancelled = false;
2472
+ let pond = null;
2473
+ let observer = null;
2474
+ const host = hostRef.current;
2475
+ if (!host) return void 0;
2476
+ const reject = (reason, file) => {
2477
+ const l = liveRef.current;
2478
+ const message = rejectionMessage(reason, {
2479
+ name: file?.name,
2480
+ size: file?.size,
2481
+ acceptLabel: l.acceptLabel,
2482
+ maxFileSize: l.maxBytes,
2483
+ maxFiles: l.maxFiles
2484
+ });
2485
+ setRejections((list) => list.includes(message) ? list : [...list, message]);
2486
+ if (file && targetRef.current) {
2487
+ targetRef.current = targetRef.current.filter((f) => f !== file);
2488
+ queueMicrotask(emit);
2489
+ }
2490
+ };
2491
+ const startAttempt = () => setRejections((list) => list.length ? [] : list);
2492
+ let removeIntent = false;
2493
+ const acceptedIds = /* @__PURE__ */ new Set();
2494
+ const noteRemove = (event) => {
2495
+ if (event.target?.closest?.(".filepond--action-remove-item")) removeIntent = true;
2496
+ };
2497
+ const onPreviewClick = (event) => {
2498
+ const button = event.target?.closest?.(
2499
+ ".sc-file-input__preview"
2500
+ );
2501
+ const file = button?.dataset.fileId ? pond?.getFile(button.dataset.fileId)?.file : null;
2502
+ if (!button || !(file instanceof File)) return;
2503
+ event.stopPropagation();
2504
+ liveRef.current.openPreview(file, button);
2505
+ };
2506
+ const emit = () => {
2507
+ const mod = moduleRef.current;
2508
+ if (!pond || !mod) return;
2509
+ const idle = pond.getFiles().filter((item) => item.status === mod.FileStatus.IDLE).map((item) => item.file);
2510
+ const accepted = liveRef.current.multiple ? idle : idle.slice(-1);
2511
+ const target = targetRef.current;
2512
+ if (target) {
2513
+ if (!sameFiles(accepted, target)) return;
2514
+ targetRef.current = null;
2515
+ settledRef.current = accepted;
2516
+ if (!sameFiles(accepted, liveRef.current.current)) {
2517
+ if (!liveRef.current.controlled) setUncontrolledFiles(accepted);
2518
+ liveRef.current.onFilesChange?.(accepted);
2519
+ }
2520
+ return;
2521
+ }
2522
+ if (sameFiles(accepted, settledRef.current)) return;
2523
+ settledRef.current = accepted;
2524
+ if (!liveRef.current.controlled) setUncontrolledFiles(accepted);
2525
+ liveRef.current.onFilesChange?.(accepted);
2526
+ };
2527
+ const patch = () => {
2528
+ if (!pond) return;
2529
+ const l = liveRef.current;
2530
+ const root = pond.element;
2531
+ if (!root) return;
2532
+ const set = (el, attr, value) => {
2533
+ if (!el || el.getAttribute(attr) === value) return;
2534
+ if (value == null) el.removeAttribute(attr);
2535
+ else el.setAttribute(attr, value);
2536
+ };
2537
+ const input = root.querySelector("input.filepond--browser");
2538
+ const dropLabel = root.querySelector(".filepond--drop-label label");
2539
+ set(input, "aria-labelledby", l.labelId);
2540
+ set(input, "aria-describedby", [dropLabel?.id, ...l.describedBy].filter(Boolean).join(" ") || null);
2541
+ set(input, "aria-invalid", l.isInvalid ? "true" : null);
2542
+ set(input, "accept", l.acceptAttr || null);
2543
+ set(input, "multiple", l.multiple ? "" : null);
2544
+ set(root.querySelector(".filepond--label-action"), "tabindex", null);
2545
+ for (const item of root.querySelectorAll(".filepond--item")) {
2546
+ const fileName = item.querySelector(".filepond--file-info-main")?.textContent?.trim();
2547
+ const remove = item.querySelector(".filepond--action-remove-item");
2548
+ if (fileName) set(remove, "aria-label", `Remove ${fileName}`);
2549
+ patchPreview(item, remove);
2550
+ }
2551
+ setInputId(input?.id || void 0);
2552
+ };
2553
+ const patchPreview = (item, remove) => {
2554
+ const row = item.querySelector(".filepond--file");
2555
+ if (!row) return;
2556
+ let button = row.querySelector(":scope > .sc-file-input__preview");
2557
+ const id2 = item.id.replace(/^filepond--item-/, "");
2558
+ const file = pond?.getFile(id2)?.file;
2559
+ if (!liveRef.current.preview || !(file instanceof File) || previewKind(file) == null) {
2560
+ button?.remove();
2561
+ return;
2562
+ }
2563
+ if (!button) {
2564
+ button = document.createElement("button");
2565
+ button.type = "button";
2566
+ button.className = "sc-file-input__preview";
2567
+ row.insertBefore(button, remove ?? row.firstChild);
2568
+ }
2569
+ if (button.dataset.fileId !== id2) button.dataset.fileId = id2;
2570
+ if (button.textContent !== file.name) button.textContent = file.name;
2571
+ const name2 = `Preview ${file.name}`;
2572
+ if (button.getAttribute("aria-label") !== name2) button.setAttribute("aria-label", name2);
2573
+ };
2574
+ void import("filepond").then((mod) => {
2575
+ if (cancelled || !mod.supported()) return;
2576
+ moduleRef.current = mod;
2577
+ const options = {
2578
+ credits: false,
2579
+ allowPaste: false,
2580
+ allowReorder: false,
2581
+ allowProcess: false,
2582
+ allowRevert: false,
2583
+ instantUpload: false,
2584
+ dropOnPage: false,
2585
+ // Always multi: FilePond's own single mode replaces the current file *before* validating the new
2586
+ // one, so a rejected file would discard a good one. Replacement happens in `addfile` instead.
2587
+ allowMultiple: true,
2588
+ allowReplace: false,
2589
+ itemInsertLocation: "after",
2590
+ fileSizeBase: 1e3,
2591
+ iconRemove: REMOVE_ICON,
2592
+ labelButtonRemoveItem: "Remove",
2593
+ styleButtonRemoveItemPosition: "right",
2594
+ beforeAddFile: (item) => {
2595
+ const l = liveRef.current;
2596
+ const file = item.file;
2597
+ if (!matchesAccept(file, l.acceptList)) return reject("type", file), false;
2598
+ if (l.maxBytes != null && file.size > l.maxBytes) return reject("size", file), false;
2599
+ return true;
2600
+ }
2601
+ };
2602
+ pond = mod.create(options);
2603
+ const root = pond.element;
2604
+ if (!root) return;
2605
+ host.appendChild(root);
2606
+ pondRef.current = pond;
2607
+ patchRef.current = patch;
2608
+ pond.on("addfile", (error2, added) => {
2609
+ if (!error2) acceptedIds.add(added.id);
2610
+ if (!error2 && !liveRef.current.multiple) {
2611
+ for (const other of pond?.getFiles() ?? []) if (other.id !== added.id) pond?.removeFile(other.id);
2612
+ }
2613
+ emit();
2614
+ });
2615
+ pond.on("removefile", (_error, removed) => {
2616
+ const active = document.activeElement;
2617
+ const inRemovedRow = active?.closest(".filepond--item")?.id === `filepond--item-${removed.id}`;
2618
+ if (inRemovedRow || removeIntent && (active == null || active === document.body))
2619
+ root.querySelector("input.filepond--browser")?.focus();
2620
+ removeIntent = false;
2621
+ if (acceptedIds.delete(removed.id)) startAttempt();
2622
+ emit();
2623
+ });
2624
+ pond.on("updatefiles", emit);
2625
+ pond.on("warning", (warning) => {
2626
+ if (warning?.body === "Max files") reject("count");
2627
+ });
2628
+ observer = new MutationObserver(patch);
2629
+ observer.observe(root, {
2630
+ subtree: true,
2631
+ childList: true,
2632
+ attributes: true,
2633
+ attributeFilter: ["tabindex", "aria-labelledby", "aria-describedby", "accept", "id", "multiple"]
2634
+ });
2635
+ host.addEventListener("drop", startAttempt, true);
2636
+ host.addEventListener("change", startAttempt, true);
2637
+ host.addEventListener("click", noteRemove, true);
2638
+ host.addEventListener("click", onPreviewClick);
2639
+ settledRef.current = [];
2640
+ setPondVersion((v) => v + 1);
2641
+ });
2642
+ return () => {
2643
+ cancelled = true;
2644
+ host.removeEventListener("drop", startAttempt, true);
2645
+ host.removeEventListener("change", startAttempt, true);
2646
+ host.removeEventListener("click", noteRemove, true);
2647
+ host.removeEventListener("click", onPreviewClick);
2648
+ observer?.disconnect();
2649
+ if (pond) {
2650
+ pond.element?.remove();
2651
+ pond.destroy();
2652
+ }
2653
+ pondRef.current = null;
2654
+ patchRef.current = () => {
2655
+ };
2656
+ };
2657
+ }, []);
2658
+ useEffect4(() => {
2659
+ const pond = pondRef.current;
2660
+ if (!pond) return;
2661
+ pond.setOptions({
2662
+ name: name ?? "",
2663
+ storeAsFile: name != null,
2664
+ disabled,
2665
+ required,
2666
+ maxFiles: multiple ? maxFiles ?? null : null,
2667
+ allowRemove: !disabled,
2668
+ labelIdle: `${escapeHtml(idleText)} <span class="filepond--label-action">${escapeHtml(browseLabel)}</span>`
2669
+ });
2670
+ patchRef.current();
2671
+ }, [
2672
+ pondVersion,
2673
+ name,
2674
+ disabled,
2675
+ required,
2676
+ multiple,
2677
+ maxFiles,
2678
+ idleText,
2679
+ browseLabel,
2680
+ labelId,
2681
+ acceptAttr,
2682
+ isInvalid,
2683
+ description,
2684
+ messages.length,
2685
+ preview
2686
+ ]);
2687
+ useEffect4(() => {
2688
+ const pond = pondRef.current;
2689
+ const mod = moduleRef.current;
2690
+ if (!pond || !mod) return;
2691
+ const items = pond.getFiles();
2692
+ const idle = items.filter((item) => item.status === mod.FileStatus.IDLE);
2693
+ const inPond = idle.map((item) => item.file);
2694
+ if (sameFiles(inPond, current)) {
2695
+ settledRef.current = current;
2696
+ return;
2697
+ }
2698
+ targetRef.current = current;
2699
+ for (const item of idle) if (!current.includes(item.file)) pond.removeFile(item.id);
2700
+ const toAdd = current.filter((file) => !inPond.includes(file));
2701
+ if (toAdd.length > 0) void pond.addFiles(toAdd);
2702
+ }, [current, pondVersion]);
2703
+ const ready = pondVersion > 0;
2704
+ return /* @__PURE__ */ jsxs25(
2705
+ "div",
2706
+ {
2707
+ className: cx("sc-field", "sc-file-input-field", className),
2708
+ "data-size": size,
2709
+ "data-disabled": disabled ? "" : void 0,
2710
+ "data-invalid": isInvalid ? "" : void 0,
2711
+ children: [
2712
+ /* @__PURE__ */ jsxs25(
2713
+ "label",
2714
+ {
2715
+ id: labelId,
2716
+ htmlFor: inputId,
2717
+ className: cx("sc-field__label", hideLabel && "sc-visually-hidden"),
2718
+ children: [
2719
+ label,
2720
+ required ? /* @__PURE__ */ jsx30("span", { className: "sc-field__required", "aria-hidden": "true", children: "*" }) : null
2721
+ ]
2722
+ }
2723
+ ),
2724
+ /* @__PURE__ */ jsxs25(
2725
+ "div",
2726
+ {
2727
+ className: "sc-file-input",
2728
+ "data-ready": ready ? "" : void 0,
2729
+ "data-disabled": disabled ? "" : void 0,
2730
+ "data-invalid": isInvalid ? "" : void 0,
2731
+ "data-multiple": multiple ? "" : void 0,
2732
+ children: [
2733
+ ready ? null : (
2734
+ // Server render and first paint: the same drop zone, inert until FilePond takes over.
2735
+ /* @__PURE__ */ jsxs25("div", { className: "sc-file-input__placeholder", "aria-hidden": "true", children: [
2736
+ idleText,
2737
+ " ",
2738
+ /* @__PURE__ */ jsx30("span", { className: "sc-file-input__browse", children: browseLabel })
2739
+ ] })
2740
+ ),
2741
+ /* @__PURE__ */ jsx30("div", { ref: hostRef, className: "sc-file-input__pond" })
2742
+ ]
2743
+ }
2744
+ ),
2745
+ description != null ? /* @__PURE__ */ jsx30("p", { id: descriptionId, className: "sc-field__description", children: description }) : null,
2746
+ /* @__PURE__ */ jsx30("div", { id: messagesId, className: "sc-file-input__messages", "aria-live": "polite", children: messages.map((message, i) => /* @__PURE__ */ jsx30("p", { className: "sc-field__error", children: message }, i)) }),
2747
+ previewFile ? /* @__PURE__ */ jsx30(
2748
+ FilePreviewDialog,
2749
+ {
2750
+ file: previewFile,
2751
+ open: previewOpen,
2752
+ onOpenChange: setPreviewOpen,
2753
+ finalFocus: () => {
2754
+ const trigger = previewTriggerRef.current;
2755
+ if (trigger?.isConnected) return trigger;
2756
+ return hostRef.current?.querySelector("input.filepond--browser") ?? true;
2757
+ }
2758
+ }
2759
+ ) : null
2760
+ ]
2761
+ }
2762
+ );
2763
+ }
2764
+
2765
+ // src/components/PriorityNav/PriorityNav.tsx
2766
+ import {
2767
+ useEffect as useEffect5,
2768
+ useId as useId4,
2769
+ useLayoutEffect as useLayoutEffect2,
2770
+ useRef as useRef5,
2771
+ useState as useState7
2772
+ } from "react";
2773
+
2774
+ // src/components/PriorityNav/fit.ts
2775
+ var EPSILON = 0.5;
2776
+ function rowWidth(widths, gap) {
2777
+ let total = 0;
2778
+ for (const w of widths) total += w;
2779
+ return widths.length > 1 ? total + gap * (widths.length - 1) : total;
2780
+ }
2781
+ function fitCount({ widths, current, available, more, gap }) {
2782
+ const n = widths.length;
2783
+ const hasCurrent = current >= 0 && current < n;
2784
+ const others = hasCurrent ? n - 1 : n;
2785
+ if (rowWidth(widths, gap) <= available + EPSILON) return others;
2786
+ let used = more + (hasCurrent ? widths[current] + gap : 0);
2787
+ let count = 0;
2788
+ for (let i = 0; i < n; i++) {
2789
+ if (i === current) continue;
2790
+ const next = used + widths[i] + gap;
2791
+ if (next > available + EPSILON) break;
2792
+ used = next;
2793
+ count++;
2794
+ }
2795
+ return count;
2796
+ }
2797
+ function inlineFlags(length, current, count) {
2798
+ const flags = [];
2799
+ let seen = 0;
2800
+ for (let i = 0; i < length; i++) {
2801
+ if (i === current) flags.push(true);
2802
+ else flags.push(seen++ < count);
2803
+ }
2804
+ return flags;
2805
+ }
2806
+ function isOverflowing({ widths, gap, available, was, hysteresis }) {
2807
+ const total = rowWidth(widths, gap);
2808
+ return was ? total + Math.max(0, hysteresis) > available + EPSILON : total > available + EPSILON;
2809
+ }
2810
+
2811
+ // src/components/PriorityNav/place.ts
2812
+ var clamp = (value, min, max) => Math.max(min, Math.min(value, max));
2813
+ function placePanel({ anchor, panel, viewport, gutter, offset, rtl = false }) {
2814
+ const endAligned = rtl ? anchor.left : anchor.right - panel.width;
2815
+ const startAligned = rtl ? anchor.right - panel.width : anchor.left;
2816
+ const fitsX = (x2) => x2 >= gutter && x2 + panel.width <= viewport.width - gutter;
2817
+ const x = fitsX(endAligned) ? endAligned : fitsX(startAligned) ? startAligned : endAligned;
2818
+ const left = clamp(x, gutter, Math.max(gutter, viewport.width - gutter - panel.width));
2819
+ const below = anchor.bottom + offset;
2820
+ const above = anchor.top - offset - panel.height;
2821
+ const fitsBelow = below + panel.height <= viewport.height - gutter;
2822
+ const top = fitsBelow || above < gutter ? below : above;
2823
+ return { left, top };
2824
+ }
2825
+
2826
+ // src/components/PriorityNav/PriorityNav.tsx
2827
+ import { Fragment as Fragment9, jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
2828
+ var defaultCountLabel2 = (n) => n === 1 ? "1 link" : `${n} links`;
2829
+ var defaultLink = ({ children, ...props }) => /* @__PURE__ */ jsx31("a", { ...props, children });
2830
+ var keyOf = (item) => item.id ?? item.href;
2831
+ var badgeOf = (item) => item.badge === "dot" ? "dot" : typeof item.badge === "number" && item.badge > 0 && Number.isFinite(item.badge) ? item.badge : null;
2832
+ var badgeTextOf = (item) => {
2833
+ const badge = badgeOf(item);
2834
+ if (badge === null) return null;
2835
+ return item.badgeLabel ?? (badge === "dot" ? null : String(badge));
2836
+ };
2837
+ function Badge2({ value }) {
2838
+ return /* @__PURE__ */ jsx31("span", { className: "sc-priority-nav__badge", "data-kind": value === "dot" ? "dot" : "count", "aria-hidden": "true", children: value === "dot" ? null : value });
2839
+ }
2840
+ var supportsAnchor = () => typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("anchor-name: --a");
2841
+ var supportsPopover = (el) => typeof el.showPopover === "function";
2842
+ function signatureOf(items) {
2843
+ return items.map((item) => {
2844
+ const text = typeof item.label === "string" || typeof item.label === "number" ? item.label : "";
2845
+ return `${keyOf(item)}${text}${badgeOf(item) ?? ""}`;
2846
+ }).join("");
2847
+ }
2848
+ function PriorityNav({
2849
+ items,
2850
+ moreLabel = "More",
2851
+ moreCountLabel = defaultCountLabel2,
2852
+ renderLink = defaultLink,
2853
+ onOverflowChange,
2854
+ overflowHysteresis = 0,
2855
+ className,
2856
+ style,
2857
+ ...rest
2858
+ }) {
2859
+ const signature = signatureOf(items);
2860
+ const current = items.findIndex((item) => item.current);
2861
+ const [fit, setFit] = useState7({ signature: null, current: -1, count: 0, overflowing: false });
2862
+ const [open, setOpen] = useState7(false);
2863
+ const panelId = useId4();
2864
+ const listRef = useRef5(null);
2865
+ const moreRef = useRef5(null);
2866
+ const toggleRef = useRef5(null);
2867
+ const panelRef = useRef5(null);
2868
+ const measured = useRef5(null);
2869
+ const currentRef = useRef5(current);
2870
+ const fitRef = useRef5(fit);
2871
+ const hysteresisRef = useRef5(overflowHysteresis);
2872
+ const onOverflowRef = useRef5(onOverflowChange);
2873
+ const solve = (m, cur, was) => ({
2874
+ count: fitCount({ ...m, current: cur }),
2875
+ overflowing: isOverflowing({ ...m, was, hysteresis: hysteresisRef.current })
2876
+ });
2877
+ const measuring = fit.signature !== signature;
2878
+ useLayoutEffect2(() => {
2879
+ currentRef.current = current;
2880
+ fitRef.current = fit;
2881
+ hysteresisRef.current = overflowHysteresis;
2882
+ onOverflowRef.current = onOverflowChange;
2883
+ });
2884
+ useLayoutEffect2(() => {
2885
+ const list = listRef.current;
2886
+ const more = moreRef.current;
2887
+ if (!list || !more) return;
2888
+ if (measuring) {
2889
+ const widths = Array.from(
2890
+ list.querySelectorAll(":scope > .sc-priority-nav__item"),
2891
+ (el) => el.getBoundingClientRect().width
2892
+ );
2893
+ measured.current = {
2894
+ widths,
2895
+ more: more.getBoundingClientRect().width,
2896
+ gap: parseFloat(getComputedStyle(list).columnGap) || 0,
2897
+ available: list.clientWidth
2898
+ };
2899
+ } else if (fit.current === current) return;
2900
+ const m = measured.current;
2901
+ if (!m) return;
2902
+ setFit({ signature, current, ...solve(m, current, fit.overflowing) });
2903
+ }, [measuring, signature, current, fit]);
2904
+ useEffect5(() => {
2905
+ const list = listRef.current;
2906
+ const more = moreRef.current;
2907
+ if (!list || !more || typeof ResizeObserver === "undefined") return;
2908
+ const observer = new ResizeObserver((entries) => {
2909
+ const m = measured.current;
2910
+ if (!m) return;
2911
+ for (const entry of entries) {
2912
+ if (entry.target === list)
2913
+ m.available = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
2914
+ else {
2915
+ const width = entry.borderBoxSize?.[0]?.inlineSize ?? 0;
2916
+ if (width > 0) m.more = width;
2917
+ }
2918
+ }
2919
+ const prev = fitRef.current;
2920
+ if (prev.signature === null) return;
2921
+ const next = solve(m, currentRef.current, prev.overflowing);
2922
+ if (prev.count !== next.count || prev.overflowing !== next.overflowing) setFit({ ...prev, ...next });
2923
+ });
2924
+ observer.observe(list);
2925
+ observer.observe(more);
2926
+ return () => observer.disconnect();
2927
+ }, []);
2928
+ const reported = useRef5(false);
2929
+ useEffect5(() => {
2930
+ if (reported.current === fit.overflowing) return;
2931
+ reported.current = fit.overflowing;
2932
+ onOverflowRef.current?.(fit.overflowing);
2933
+ }, [fit.overflowing]);
2934
+ useEffect5(() => {
2935
+ const fonts = typeof document === "undefined" ? void 0 : document.fonts;
2936
+ if (!fonts || fonts.status === "loaded") return;
2937
+ let live = true;
2938
+ void fonts.ready.then(() => {
2939
+ if (live) setFit((prev) => ({ ...prev, signature: null }));
2940
+ });
2941
+ return () => {
2942
+ live = false;
2943
+ };
2944
+ }, []);
2945
+ const flags = measuring ? null : inlineFlags(items.length, current, fit.count);
2946
+ const overflow = flags ? items.filter((_, i) => !flags[i]) : [];
2947
+ const expanded = open && overflow.length > 0;
2948
+ const overflowBadges = overflow.map(badgeOf).filter((b) => b !== null);
2949
+ const overflowCount = overflowBadges.reduce((sum, b) => sum + (b === "dot" ? 0 : b), 0);
2950
+ const moreBadge = overflowCount > 0 ? overflowCount : overflowBadges.length > 0 ? "dot" : null;
2951
+ const moreBadgeText = overflow.map(badgeTextOf).filter((text) => text !== null).map((text) => `, ${text}`).join("");
2952
+ useLayoutEffect2(() => {
2953
+ const panel = panelRef.current;
2954
+ if (!panel || !supportsPopover(panel)) return;
2955
+ if (!panel.hasAttribute("popover")) panel.setAttribute("popover", "manual");
2956
+ const shown = panel.matches(":popover-open");
2957
+ if (expanded && !shown) panel.showPopover();
2958
+ else if (!expanded && shown) panel.hidePopover();
2959
+ }, [expanded]);
2960
+ useLayoutEffect2(() => {
2961
+ const panel = panelRef.current;
2962
+ const toggle2 = toggleRef.current;
2963
+ if (!expanded || !panel || !toggle2 || supportsAnchor()) return;
2964
+ const place = () => {
2965
+ const anchor = toggle2.getBoundingClientRect();
2966
+ const box = panel.getBoundingClientRect();
2967
+ const css = getComputedStyle(panel);
2968
+ const { left, top } = placePanel({
2969
+ anchor,
2970
+ panel: { width: box.width, height: box.height },
2971
+ viewport: { width: document.documentElement.clientWidth, height: window.innerHeight },
2972
+ gutter: parseFloat(css.getPropertyValue("--sc-spacing-md")) || 16,
2973
+ offset: parseFloat(css.getPropertyValue("--sc-spacing-2xs")) || 4,
2974
+ rtl: css.direction === "rtl"
2975
+ });
2976
+ panel.style.left = `${left}px`;
2977
+ panel.style.top = `${top}px`;
2978
+ };
2979
+ place();
2980
+ window.addEventListener("resize", place, { passive: true });
2981
+ window.addEventListener("scroll", place, { passive: true, capture: true });
2982
+ return () => {
2983
+ window.removeEventListener("resize", place);
2984
+ window.removeEventListener("scroll", place, { capture: true });
2985
+ panel.style.left = "";
2986
+ panel.style.top = "";
2987
+ };
2988
+ }, [expanded]);
2989
+ useEffect5(() => {
2990
+ if (!expanded) return;
2991
+ const onPointerDown = (event) => {
2992
+ if (!moreRef.current?.contains(event.target)) setOpen(false);
2993
+ };
2994
+ const onKeyDown = (event) => {
2995
+ if (event.key !== "Escape") return;
2996
+ const active = document.activeElement;
2997
+ setOpen(false);
2998
+ if (!active || active === document.body || moreRef.current?.contains(active))
2999
+ toggleRef.current?.focus();
3000
+ };
3001
+ document.addEventListener("pointerdown", onPointerDown);
3002
+ document.addEventListener("keydown", onKeyDown);
3003
+ return () => {
3004
+ document.removeEventListener("pointerdown", onPointerDown);
3005
+ document.removeEventListener("keydown", onKeyDown);
3006
+ };
3007
+ }, [expanded]);
3008
+ const onBlur = (event) => {
3009
+ if (!event.currentTarget.contains(event.relatedTarget)) setOpen(false);
3010
+ };
3011
+ const link = (item, inPanel) => {
3012
+ const badge = badgeOf(item);
3013
+ const badgeText = badgeTextOf(item);
3014
+ return renderLink(
3015
+ {
3016
+ href: item.href,
3017
+ className: "sc-priority-nav__link",
3018
+ "aria-current": item.current ? "page" : void 0,
3019
+ onClick: inPanel ? () => setOpen(false) : void 0,
3020
+ children: /* @__PURE__ */ jsxs26(Fragment9, { children: [
3021
+ /* @__PURE__ */ jsx31("span", { className: "sc-priority-nav__label", children: item.label }),
3022
+ badge !== null ? /* @__PURE__ */ jsx31(Badge2, { value: badge }) : null,
3023
+ badgeText !== null ? /* @__PURE__ */ jsxs26("span", { className: "sc-visually-hidden", children: [
3024
+ ", ",
3025
+ badgeText
3026
+ ] }) : null
3027
+ ] })
3028
+ },
3029
+ item
3030
+ );
3031
+ };
3032
+ return /* @__PURE__ */ jsx31(
3033
+ "nav",
3034
+ {
3035
+ className: cx("sc-priority-nav", className),
3036
+ "data-measuring": measuring || void 0,
3037
+ "data-overflowing": fit.overflowing || void 0,
3038
+ style: { ...style, "--_anchor": `--sc-priority-nav${panelId.replace(/[^\w-]/g, "")}` },
3039
+ ...rest,
3040
+ children: /* @__PURE__ */ jsxs26("ul", { ref: listRef, className: "sc-priority-nav__list", children: [
3041
+ items.map(
3042
+ (item, i) => flags && !flags[i] ? null : /* @__PURE__ */ jsx31("li", { className: "sc-priority-nav__item", "data-current": item.current || void 0, children: link(item, false) }, keyOf(item))
3043
+ ),
3044
+ /* @__PURE__ */ jsxs26(
3045
+ "li",
3046
+ {
3047
+ ref: moreRef,
3048
+ className: "sc-priority-nav__more",
3049
+ hidden: measuring || overflow.length === 0,
3050
+ onBlur,
3051
+ children: [
3052
+ /* @__PURE__ */ jsxs26(
3053
+ "button",
3054
+ {
3055
+ ref: toggleRef,
3056
+ type: "button",
3057
+ className: "sc-priority-nav__toggle",
3058
+ "aria-expanded": expanded,
3059
+ "aria-controls": panelId,
3060
+ onClick: () => setOpen((o) => !o),
3061
+ children: [
3062
+ /* @__PURE__ */ jsx31(MoreHorizontalIcon, { className: "sc-priority-nav__ellipsis" }),
3063
+ /* @__PURE__ */ jsx31("span", { className: "sc-priority-nav__toggle-label", children: moreLabel }),
3064
+ /* @__PURE__ */ jsxs26("span", { className: "sc-visually-hidden", children: [
3065
+ ", ",
3066
+ moreCountLabel(overflow.length),
3067
+ moreBadgeText
3068
+ ] }),
3069
+ moreBadge !== null ? /* @__PURE__ */ jsx31(Badge2, { value: moreBadge }) : null,
3070
+ /* @__PURE__ */ jsx31(ChevronDownIcon, { size: "sm", className: "sc-priority-nav__chevron" })
3071
+ ]
3072
+ }
3073
+ ),
3074
+ /* @__PURE__ */ jsx31("ul", { ref: panelRef, id: panelId, className: "sc-priority-nav__panel", hidden: !expanded, children: overflow.map((item) => /* @__PURE__ */ jsx31("li", { children: link(item, true) }, keyOf(item))) })
3075
+ ]
3076
+ }
3077
+ )
3078
+ ] })
3079
+ }
3080
+ );
3081
+ }
3082
+
3083
+ // src/components/Popover/Popover.tsx
3084
+ import { Popover as BasePopover } from "@base-ui/react/popover";
3085
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
3086
+ function Root6({ open, defaultOpen, onOpenChange, modal = false, children }) {
3087
+ return /* @__PURE__ */ jsx32(
3088
+ BasePopover.Root,
3089
+ {
3090
+ open,
3091
+ defaultOpen,
3092
+ onOpenChange: onOpenChange ? (next) => onOpenChange(next) : void 0,
3093
+ modal,
3094
+ children
3095
+ }
3096
+ );
3097
+ }
3098
+ function Trigger3({ render, className, children, ...rest }) {
3099
+ return /* @__PURE__ */ jsx32(
3100
+ BasePopover.Trigger,
3101
+ {
3102
+ render: render ?? /* @__PURE__ */ jsx32(Button, { variant: "secondary", className }),
3103
+ className: render ? className : void 0,
3104
+ ...rest,
3105
+ children
3106
+ }
3107
+ );
3108
+ }
3109
+ function Content3({
3110
+ side = "bottom",
3111
+ align = "center",
3112
+ sideOffset,
3113
+ arrow = false,
3114
+ className,
3115
+ children,
3116
+ ...rest
3117
+ }) {
3118
+ return /* @__PURE__ */ jsx32(BasePopover.Portal, { children: /* @__PURE__ */ jsx32(
3119
+ BasePopover.Positioner,
3120
+ {
3121
+ side,
3122
+ align,
3123
+ sideOffset: sideOffset ?? (arrow ? 8 : 4),
3124
+ className: "sc-popover__positioner",
3125
+ children: /* @__PURE__ */ jsxs27(BasePopover.Popup, { className: cx("sc-popover", className), ...rest, children: [
3126
+ arrow ? /* @__PURE__ */ jsx32(BasePopover.Arrow, { className: "sc-popover__arrow" }) : null,
3127
+ children
3128
+ ] })
3129
+ }
3130
+ ) });
3131
+ }
3132
+ function Title2({ className, ...rest }) {
3133
+ return /* @__PURE__ */ jsx32(BasePopover.Title, { className: cx("sc-popover__title", className), ...rest });
3134
+ }
3135
+ function Description2({ className, ...rest }) {
3136
+ return /* @__PURE__ */ jsx32(BasePopover.Description, { className: cx("sc-popover__description", className), ...rest });
3137
+ }
3138
+ function Close2({ className, children, render, ...rest }) {
3139
+ if (children === void 0 && render === void 0) {
3140
+ return /* @__PURE__ */ jsx32(BasePopover.Close, { className: cx("sc-popover__close", className), "aria-label": "Close", ...rest, children: /* @__PURE__ */ jsx32(XIcon, {}) });
3141
+ }
3142
+ return /* @__PURE__ */ jsx32(BasePopover.Close, { className, render, ...rest, children });
3143
+ }
3144
+ var Popover = { Root: Root6, Trigger: Trigger3, Content: Content3, Title: Title2, Description: Description2, Close: Close2 };
3145
+
3146
+ // src/components/BroomIcon/BroomIcon.tsx
3147
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
3148
+ function BroomIcon({ sweeping = false, size = "lg", title, className, ...rest }) {
3149
+ return /* @__PURE__ */ jsxs28(
3150
+ "svg",
3151
+ {
3152
+ className: cx("sc-icon", "sc-broom", className),
3153
+ "data-size": size,
3154
+ "data-sweeping": sweeping || void 0,
3155
+ viewBox: "0 0 24 24",
3156
+ fill: "none",
3157
+ focusable: "false",
3158
+ "aria-hidden": title ? void 0 : true,
3159
+ role: title ? "img" : void 0,
3160
+ "aria-label": title,
3161
+ ...rest,
3162
+ children: [
3163
+ /* @__PURE__ */ jsxs28(
3164
+ "g",
3165
+ {
3166
+ className: "sc-broom__body",
3167
+ fill: "none",
3168
+ stroke: "currentColor",
3169
+ strokeLinecap: "round",
3170
+ strokeLinejoin: "round",
3171
+ children: [
3172
+ /* @__PURE__ */ jsx33("path", { d: "M16.1 10.48 L19.36 1.86 A0.87 0.87 0 0 1 20.98 2.47 L17.84 10.78" }),
3173
+ /* @__PURE__ */ jsx33("path", { d: "M13.33 12 C14.23 10.67 16.73 9.87 18.17 11 C19.07 12.67 18.93 18.33 18.4 21.4 C16.07 22.4 11.07 22.07 6.4 18.07 C9.07 16.67 11.8 15 13.33 12 Z" }),
3174
+ /* @__PURE__ */ jsx33("path", { className: "sc-broom__band", d: "M13.47 12.13 L18.4 13.5 L18.33 14.1 L13.27 12.77 Z" }),
3175
+ /* @__PURE__ */ jsx33("path", { d: "M12.87 13.73 L14.4 14.47 M16.2 15.27 L18.47 15.87" }),
3176
+ /* @__PURE__ */ jsx33("path", { d: "M12.8 16.87 C11.86 18.24 10.75 19.38 9.57 20.23 M15.6 17.4 C15.22 18.96 14.6 20.44 13.77 21.71" })
3177
+ ]
3178
+ }
3179
+ ),
3180
+ /* @__PURE__ */ jsxs28("g", { className: "sc-broom__dust", fill: "none", stroke: "currentColor", children: [
3181
+ /* @__PURE__ */ jsx33("circle", { cx: "4.77", cy: "13.53", r: "0.5" }),
3182
+ /* @__PURE__ */ jsx33("circle", { cx: "2.7", cy: "15.53", r: "0.87" }),
3183
+ /* @__PURE__ */ jsx33("circle", { cx: "4.1", cy: "18.27", r: "0.5" })
3184
+ ] })
3185
+ ]
3186
+ }
3187
+ );
3188
+ }
3189
+
3190
+ // src/components/FullScreenFlow/FullScreenFlow.tsx
3191
+ import {
3192
+ Children as Children2,
3193
+ createContext as createContext2,
3194
+ useCallback as useCallback2,
3195
+ useContext as useContext2,
3196
+ useEffect as useEffect6,
3197
+ useId as useId5,
3198
+ useMemo as useMemo3,
3199
+ useRef as useRef6,
3200
+ useState as useState8
3201
+ } from "react";
3202
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
3203
+ var FlowContext = createContext2({ announce: () => {
3204
+ } });
3205
+ var FrameContext = createContext2(void 0);
3206
+ var ENTER_IGNORES = 'textarea, button, a[href], summary, select, [contenteditable], [role="combobox"], [data-flow-keys="local"]';
3207
+ var ARROW_IGNORES = 'input, textarea, select, button, a[href], summary, [contenteditable], [role="radiogroup"], [role="slider"], [role="listbox"], [role="tablist"], [role="menu"], [role="grid"], [role="combobox"], [data-flow-keys="local"]';
3208
+ function Root7({
3209
+ open = true,
3210
+ onRequestClose,
3211
+ onNext,
3212
+ onBack,
3213
+ decoration,
3214
+ className,
3215
+ children
3216
+ }) {
3217
+ const popupRef = useRef6(null);
3218
+ const [message, setMessage] = useState8("");
3219
+ const timer = useRef6(void 0);
3220
+ const announce = useCallback2((next) => {
3221
+ setMessage("");
3222
+ clearTimeout(timer.current);
3223
+ timer.current = setTimeout(() => setMessage(next), 30);
3224
+ }, []);
3225
+ useEffect6(() => () => clearTimeout(timer.current), []);
3226
+ const context = useMemo3(() => ({ announce }), [announce]);
3227
+ const handleKeyDown = (event) => {
3228
+ if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;
3229
+ if (event.nativeEvent.isComposing) return;
3230
+ const target = event.target;
3231
+ if (!event.currentTarget.contains(target)) return;
3232
+ if (event.key === "Enter") {
3233
+ if (!onNext || target.closest(ENTER_IGNORES)) return;
3234
+ event.preventDefault();
3235
+ onNext();
3236
+ return;
3237
+ }
3238
+ if (event.key !== "ArrowRight" && event.key !== "ArrowLeft") return;
3239
+ if (target.closest(ARROW_IGNORES)) return;
3240
+ const rtl = getComputedStyle(event.currentTarget).direction === "rtl";
3241
+ const forward = event.key === "ArrowRight" !== rtl;
3242
+ const handler = forward ? onNext : onBack;
3243
+ if (!handler) return;
3244
+ event.preventDefault();
3245
+ handler();
3246
+ };
3247
+ return /* @__PURE__ */ jsx34(
3248
+ Dialog.Root,
3249
+ {
3250
+ open,
3251
+ onRequestClose: (reason) => {
3252
+ if (reason !== "outside-press") onRequestClose(reason);
3253
+ },
3254
+ children: /* @__PURE__ */ jsx34(
3255
+ Dialog.Content,
3256
+ {
3257
+ ref: popupRef,
3258
+ variant: "fullscreen",
3259
+ className: cx("sc-flow", className),
3260
+ initialFocus: () => popupRef.current?.querySelector(".sc-flow__step-title") ?? true,
3261
+ onKeyDown: handleKeyDown,
3262
+ children: /* @__PURE__ */ jsxs29(FlowContext.Provider, { value: context, children: [
3263
+ decoration ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__decoration", "aria-hidden": "true", children: decoration }) : null,
3264
+ children,
3265
+ /* @__PURE__ */ jsx34("div", { className: "sc-visually-hidden", "aria-live": "polite", "aria-atomic": "true", children: message })
3266
+ ] })
3267
+ }
3268
+ )
3269
+ }
3270
+ );
3271
+ }
3272
+ function Header2({
3273
+ title,
3274
+ logo,
3275
+ compactTitle,
3276
+ status,
3277
+ closeLabel = "Close",
3278
+ className,
3279
+ children,
3280
+ ...rest
3281
+ }) {
3282
+ return /* @__PURE__ */ jsxs29("div", { className: cx("sc-flow__header", className), ...rest, children: [
3283
+ /* @__PURE__ */ jsxs29("div", { className: "sc-flow__heading", "data-compact": compactTitle ? "" : void 0, children: [
3284
+ logo ? /* @__PURE__ */ jsx34("span", { className: "sc-flow__logo", "aria-hidden": "true", children: logo }) : null,
3285
+ /* @__PURE__ */ jsx34(Dialog.Title, { className: "sc-flow__title", children: title }),
3286
+ compactTitle ? /* @__PURE__ */ jsx34("span", { className: "sc-flow__compact-title", children: compactTitle }) : null
3287
+ ] }),
3288
+ children,
3289
+ status ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__status", children: status }) : null,
3290
+ /* @__PURE__ */ jsx34(
3291
+ Dialog.Close,
3292
+ {
3293
+ className: "sc-flow__close",
3294
+ render: /* @__PURE__ */ jsx34(IconButton, { label: closeLabel, "aria-keyshortcuts": "Escape" }),
3295
+ children: /* @__PURE__ */ jsx34(XIcon, { size: "lg" })
3296
+ }
3297
+ )
3298
+ ] });
3299
+ }
3300
+ function Progress2({
3301
+ chapters,
3302
+ step,
3303
+ label,
3304
+ listLabel = "Progress",
3305
+ className,
3306
+ ...rest
3307
+ }) {
3308
+ const starts = chapters.reduce(
3309
+ (acc, chapter, i) => [...acc, i === 0 ? 0 : acc[i - 1] + chapters[i - 1].steps],
3310
+ []
3311
+ );
3312
+ return /* @__PURE__ */ jsxs29("div", { className: cx("sc-flow__progress", className), ...rest, children: [
3313
+ label ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__progress-label", children: label }) : null,
3314
+ /* @__PURE__ */ jsx34("ol", { className: "sc-flow__segments", "aria-label": listLabel, children: chapters.map((chapter, i) => {
3315
+ const from = starts[i];
3316
+ const current = step > from && step <= from + chapter.steps;
3317
+ const done = Math.min(chapter.steps, Math.max(0, step - 1 - from)) + (current ? 0.5 : 0);
3318
+ const percent = chapter.steps > 0 ? Math.min(100, done / chapter.steps * 100) : 0;
3319
+ return /* @__PURE__ */ jsxs29(
3320
+ "li",
3321
+ {
3322
+ className: "sc-flow__segment",
3323
+ style: { flexGrow: chapter.steps },
3324
+ "aria-current": current ? "step" : void 0,
3325
+ children: [
3326
+ /* @__PURE__ */ jsx34("span", { className: "sc-flow__segment-fill", style: { inlineSize: `${percent}%` } }),
3327
+ /* @__PURE__ */ jsx34("span", { className: "sc-visually-hidden", children: chapter.label })
3328
+ ]
3329
+ },
3330
+ chapter.label
3331
+ );
3332
+ }) })
3333
+ ] });
3334
+ }
3335
+ function Body3({ className, ...rest }) {
3336
+ return /* @__PURE__ */ jsx34("div", { className: cx("sc-flow__body", className), ...rest });
3337
+ }
3338
+ function Rail({
3339
+ "aria-label": ariaLabel = "Steps",
3340
+ footer,
3341
+ className,
3342
+ children,
3343
+ ...rest
3344
+ }) {
3345
+ return /* @__PURE__ */ jsxs29("nav", { className: cx("sc-flow__rail", className), "aria-label": ariaLabel, ...rest, children: [
3346
+ children,
3347
+ footer ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__rail-note", children: footer }) : null
3348
+ ] });
3349
+ }
3350
+ function RailGroup({ label, className, children, ...rest }) {
3351
+ const id = useId5();
3352
+ return /* @__PURE__ */ jsxs29("div", { className: cx("sc-flow__rail-group", className), ...rest, children: [
3353
+ /* @__PURE__ */ jsx34("span", { className: "sc-flow__rail-label", id, children: label }),
3354
+ /* @__PURE__ */ jsx34("ol", { className: "sc-flow__rail-list", "aria-labelledby": id, children })
3355
+ ] });
3356
+ }
3357
+ function RailItem({
3358
+ current = false,
3359
+ done = false,
3360
+ doneLabel = "done",
3361
+ adornment,
3362
+ type = "button",
3363
+ className,
3364
+ children,
3365
+ ...rest
3366
+ }) {
3367
+ return /* @__PURE__ */ jsx34("li", { className: "sc-flow__rail-entry", children: /* @__PURE__ */ jsxs29(
3368
+ "button",
3369
+ {
3370
+ type,
3371
+ className: cx("sc-flow__rail-item", className),
3372
+ "aria-current": current ? "step" : void 0,
3373
+ "data-done": done || void 0,
3374
+ ...rest,
3375
+ children: [
3376
+ /* @__PURE__ */ jsx34("span", { className: "sc-flow__rail-mark", "aria-hidden": "true", children: done ? /* @__PURE__ */ jsx34(CheckIcon, { size: "sm" }) : null }),
3377
+ /* @__PURE__ */ jsxs29("span", { className: "sc-flow__rail-text", children: [
3378
+ children,
3379
+ done ? /* @__PURE__ */ jsxs29("span", { className: "sc-visually-hidden", children: [
3380
+ ", ",
3381
+ doneLabel
3382
+ ] }) : null
3383
+ ] }),
3384
+ adornment ? /* @__PURE__ */ jsx34("span", { className: "sc-flow__rail-adornment", children: adornment }) : null
3385
+ ]
3386
+ }
3387
+ ) });
3388
+ }
3389
+ function Viewport2({ direction = "forward", className, children, ...rest }) {
3390
+ const element = Children2.only(children);
3391
+ const key = String(element.key ?? "");
3392
+ const [state, setState] = useState8({
3393
+ current: { key, element, direction },
3394
+ leaving: null,
3395
+ moved: false
3396
+ });
3397
+ if (state.current.key !== key) {
3398
+ setState({
3399
+ current: { key, element, direction },
3400
+ leaving: { ...state.current, direction },
3401
+ moved: true
3402
+ });
3403
+ } else if (state.current.element !== element) {
3404
+ setState((s) => ({ ...s, current: { ...s.current, element } }));
3405
+ }
3406
+ const finishExit = useCallback2((leftKey) => {
3407
+ setState((s) => s.leaving?.key === leftKey ? { ...s, leaving: null } : s);
3408
+ }, []);
3409
+ const ref = useRef6(null);
3410
+ useEffect6(() => {
3411
+ if (state.moved && ref.current) ref.current.scrollTop = 0;
3412
+ }, [key, state.moved]);
3413
+ const frames = [];
3414
+ if (state.leaving && state.leaving.key !== key) frames.push({ frame: state.leaving, phase: "exit" });
3415
+ frames.push({
3416
+ frame: { key, element, direction: state.current.direction },
3417
+ phase: state.moved ? "enter" : void 0
3418
+ });
3419
+ return /* @__PURE__ */ jsx34("div", { ref, className: cx("sc-flow__viewport", className), ...rest, children: frames.map(({ frame, phase }) => /* @__PURE__ */ jsx34(
3420
+ FrameView,
3421
+ {
3422
+ frameKey: frame.key,
3423
+ phase,
3424
+ direction: frame.direction,
3425
+ onExited: finishExit,
3426
+ children: frame.element
3427
+ },
3428
+ frame.key
3429
+ )) });
3430
+ }
3431
+ function FrameView({
3432
+ frameKey,
3433
+ phase,
3434
+ direction,
3435
+ onExited,
3436
+ children
3437
+ }) {
3438
+ const ref = useRef6(null);
3439
+ useEffect6(() => {
3440
+ if (phase !== "exit") return;
3441
+ let cancelled = false;
3442
+ const el = ref.current;
3443
+ const animations = el && typeof el.getAnimations === "function" ? el.getAnimations() : [];
3444
+ const done = () => {
3445
+ if (!cancelled) onExited(frameKey);
3446
+ };
3447
+ Promise.all(animations.map((a) => a.finished)).then(done, done);
3448
+ return () => {
3449
+ cancelled = true;
3450
+ };
3451
+ }, [phase, frameKey, onExited]);
3452
+ return /* @__PURE__ */ jsx34(
3453
+ "div",
3454
+ {
3455
+ ref,
3456
+ className: "sc-flow__frame",
3457
+ "data-phase": phase,
3458
+ "data-direction": direction,
3459
+ inert: phase === "exit",
3460
+ children: /* @__PURE__ */ jsx34(FrameContext.Provider, { value: phase, children })
3461
+ }
3462
+ );
3463
+ }
3464
+ function Step({
3465
+ title,
3466
+ eyebrow,
3467
+ description,
3468
+ announcement,
3469
+ className,
3470
+ children,
3471
+ ...rest
3472
+ }) {
3473
+ const id = useId5();
3474
+ const titleRef = useRef6(null);
3475
+ const phase = useContext2(FrameContext);
3476
+ const { announce } = useContext2(FlowContext);
3477
+ const message = announcement ?? (typeof title === "string" ? title : void 0);
3478
+ const latest = useRef6({ message, announce });
3479
+ useEffect6(() => {
3480
+ latest.current = { message, announce };
3481
+ });
3482
+ useEffect6(() => {
3483
+ if (phase !== "enter") return;
3484
+ titleRef.current?.focus({ preventScroll: true });
3485
+ if (latest.current.message) latest.current.announce(latest.current.message);
3486
+ }, [phase]);
3487
+ return /* @__PURE__ */ jsxs29("section", { className: cx("sc-flow__step", className), "aria-labelledby": id, ...rest, children: [
3488
+ /* @__PURE__ */ jsxs29("div", { className: "sc-flow__step-head", children: [
3489
+ eyebrow ? /* @__PURE__ */ jsx34("p", { className: "sc-flow__eyebrow", children: eyebrow }) : null,
3490
+ /* @__PURE__ */ jsx34("h2", { className: "sc-flow__step-title", id, ref: titleRef, tabIndex: -1, children: title }),
3491
+ description ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__step-description", children: description }) : null
3492
+ ] }),
3493
+ children
3494
+ ] });
3495
+ }
3496
+ function Footer({ back, hint, className, children, ...rest }) {
3497
+ return /* @__PURE__ */ jsxs29("div", { className: cx("sc-flow__footer", className), ...rest, children: [
3498
+ back ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__footer-back", children: back }) : null,
3499
+ hint ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__footer-hint", children: hint }) : null,
3500
+ /* @__PURE__ */ jsx34("div", { className: "sc-flow__footer-actions", children })
3501
+ ] });
3502
+ }
3503
+ var FullScreenFlow = {
3504
+ Root: Root7,
3505
+ Header: Header2,
3506
+ Progress: Progress2,
3507
+ Body: Body3,
3508
+ Rail,
3509
+ RailGroup,
3510
+ RailItem,
3511
+ Viewport: Viewport2,
3512
+ Step,
3513
+ Footer
3514
+ };
3515
+
3516
+ // src/components/Score/Score.tsx
3517
+ import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
3518
+ function Score({
3519
+ value,
3520
+ max = 100,
3521
+ tone = "accent",
3522
+ variant = "tile",
3523
+ size = "sm",
3524
+ caption,
3525
+ label = "Score",
3526
+ valueText,
3527
+ selected = false,
3528
+ className,
3529
+ style,
3530
+ ...rest
3531
+ }) {
3532
+ const scored = value !== null;
3533
+ const fraction = scored && max > 0 ? Math.min(1, Math.max(0, value / max)) : 0;
3534
+ return /* @__PURE__ */ jsxs30(
3535
+ "span",
3536
+ {
3537
+ className: cx("sc-score", className),
3538
+ "data-variant": variant,
3539
+ "data-size": variant === "tile" ? size : void 0,
3540
+ "data-tone": scored ? tone : void 0,
3541
+ "data-unscored": scored ? void 0 : true,
3542
+ "data-selected": selected || void 0,
3543
+ style: variant === "ring" ? { ...style, "--sc-score-fill": (fraction * 100).toFixed(2) } : style,
3544
+ ...rest,
3545
+ children: [
3546
+ /* @__PURE__ */ jsx35("span", { className: "sc-visually-hidden", children: valueText ?? (scored ? `${label} ${value} out of ${max}` : `${label}: not scored`) }),
3547
+ variant === "ring" ? /* @__PURE__ */ jsxs30("svg", { className: "sc-score__ring", viewBox: "0 0 64 64", "aria-hidden": "true", focusable: "false", children: [
3548
+ /* @__PURE__ */ jsx35("circle", { className: "sc-score__track", cx: "32", cy: "32", r: "29", pathLength: 100 }),
3549
+ fraction > 0 ? /* @__PURE__ */ jsx35("circle", { className: "sc-score__arc", cx: "32", cy: "32", r: "29", pathLength: 100 }) : null
3550
+ ] }) : null,
3551
+ /* @__PURE__ */ jsxs30("span", { className: "sc-score__body", "aria-hidden": "true", children: [
3552
+ /* @__PURE__ */ jsx35("span", { className: "sc-score__value", children: scored ? value : "\u2013" }),
3553
+ caption != null ? /* @__PURE__ */ jsx35("span", { className: "sc-score__caption", children: caption }) : null
3554
+ ] })
3555
+ ]
3556
+ }
3557
+ );
3558
+ }
3559
+
3560
+ // src/components/ReasonList/ReasonList.tsx
3561
+ import { jsx as jsx36 } from "react/jsx-runtime";
3562
+ function ReasonListRoot({ tone, size = "md", divider = false, className, ...rest }) {
3563
+ return /* @__PURE__ */ jsx36(
3564
+ "ul",
3565
+ {
3566
+ className: cx("sc-reason-list", className),
3567
+ "data-tone": tone,
3568
+ "data-size": size,
3569
+ "data-divider": divider || void 0,
3570
+ ...rest
3571
+ }
3572
+ );
3573
+ }
3574
+ function ReasonListItem({ className, ...rest }) {
3575
+ return /* @__PURE__ */ jsx36("li", { className: cx("sc-reason-list__item", className), ...rest });
3576
+ }
3577
+ var ReasonList = Object.assign(ReasonListRoot, { Item: ReasonListItem });
3578
+
3579
+ // src/components/WordDiff/WordDiff.tsx
3580
+ import { createElement as createElement7, Fragment as Fragment10 } from "react";
3581
+ import { Fragment as Fragment11, jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
3582
+ var edges = /^(\s*)([\s\S]*?)(\s*)$/;
3583
+ function Change({ kind, text, label }) {
3584
+ const [, lead = "", core = "", trail = ""] = edges.exec(text) ?? [];
3585
+ if (!core) return /* @__PURE__ */ jsx37(Fragment11, { children: text });
3586
+ const Tag = kind === "added" ? "ins" : "del";
3587
+ return /* @__PURE__ */ jsxs31(Fragment11, { children: [
3588
+ lead,
3589
+ /* @__PURE__ */ jsxs31(Tag, { className: `sc-word-diff__${kind}`, children: [
3590
+ /* @__PURE__ */ jsxs31("span", { className: "sc-visually-hidden", children: [
3591
+ "[",
3592
+ label,
3593
+ ": "
3594
+ ] }),
3595
+ core,
3596
+ /* @__PURE__ */ jsx37("span", { className: "sc-visually-hidden", children: "]" })
3597
+ ] }),
3598
+ trail
3599
+ ] });
3600
+ }
3601
+ function WordDiff({
3602
+ parts,
3603
+ as = "p",
3604
+ size = "sm",
3605
+ family = "sans",
3606
+ addedLabel = "added",
3607
+ removedLabel = "removed",
3608
+ className,
3609
+ ...rest
3610
+ }) {
3611
+ const children = parts.map(
3612
+ (part, i) => part.kind === "same" ? /* @__PURE__ */ jsx37(Fragment10, { children: part.text }, i) : /* @__PURE__ */ jsx37(
3613
+ Change,
3614
+ {
3615
+ kind: part.kind,
3616
+ text: part.text,
3617
+ label: part.kind === "added" ? addedLabel : removedLabel
3618
+ },
3619
+ i
3620
+ )
3621
+ );
3622
+ return createElement7(
3623
+ as,
3624
+ {
3625
+ className: cx("sc-word-diff", className),
3626
+ "data-size": size,
3627
+ ...family === "mono" ? { "data-family": "mono" } : {},
3628
+ ...rest
3629
+ },
3630
+ children
3631
+ );
3632
+ }
3633
+
3634
+ // src/components/Quote/Quote.tsx
3635
+ import { jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
3636
+ function Quote({ label, className, children, ...rest }) {
3637
+ return /* @__PURE__ */ jsxs32("figure", { className: cx("sc-quote", className), ...rest, children: [
3638
+ /* @__PURE__ */ jsx38("figcaption", { className: "sc-quote__label", children: label }),
3639
+ /* @__PURE__ */ jsx38("blockquote", { className: "sc-quote__text", children })
3640
+ ] });
3641
+ }
3642
+
1462
3643
  // src/index.ts
1463
3644
  var version = "0.1.1";
1464
3645
  export {
@@ -1471,6 +3652,7 @@ export {
1471
3652
  Banner,
1472
3653
  BellIcon,
1473
3654
  BriefcaseIcon,
3655
+ BroomIcon,
1474
3656
  Button,
1475
3657
  CalendarIcon,
1476
3658
  Card,
@@ -1480,18 +3662,24 @@ export {
1480
3662
  ChevronLeftIcon,
1481
3663
  ChevronRightIcon,
1482
3664
  ChevronUpIcon,
3665
+ Chip,
1483
3666
  CircleCheckIcon,
1484
3667
  CircleXIcon,
1485
3668
  ClockIcon,
1486
3669
  CopyIcon,
1487
3670
  Dialog,
3671
+ Disclosure,
1488
3672
  DocumentIcon,
1489
3673
  DownloadIcon,
1490
3674
  EditIcon,
3675
+ EmptyState,
1491
3676
  ExternalLinkIcon,
1492
3677
  EyeIcon,
3678
+ FileInput,
3679
+ FilePreviewDialog,
1493
3680
  FilterIcon,
1494
3681
  FlagIcon,
3682
+ FullScreenFlow,
1495
3683
  Heading,
1496
3684
  Icon,
1497
3685
  IconButton,
@@ -1512,11 +3700,18 @@ export {
1512
3700
  PauseIcon,
1513
3701
  PlayIcon,
1514
3702
  PlusIcon,
3703
+ Popover,
3704
+ PriorityNav,
1515
3705
  Progress,
3706
+ Quote,
3707
+ ReasonList,
1516
3708
  RefreshIcon,
3709
+ Score,
1517
3710
  SearchIcon,
1518
3711
  Select,
3712
+ SelectionBar,
1519
3713
  SettingsIcon,
3714
+ Skeleton,
1520
3715
  Spinner,
1521
3716
  Stack,
1522
3717
  StarIcon,
@@ -1529,14 +3724,18 @@ export {
1529
3724
  Textarea,
1530
3725
  ThumbsDownIcon,
1531
3726
  ThumbsUpIcon,
3727
+ Toast,
1532
3728
  Toolbar,
1533
3729
  Tooltip,
1534
3730
  TrashIcon,
1535
3731
  UndoIcon,
1536
3732
  UserIcon,
1537
3733
  WarningIcon,
3734
+ WordDiff,
1538
3735
  XIcon,
1539
3736
  iconNames,
3737
+ useRowSelection,
3738
+ useToast,
1540
3739
  version
1541
3740
  };
1542
3741
  //# sourceMappingURL=index.js.map