@salemcobalt/ui 0.2.0-rc.1 → 0.2.0-rc.11

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
  }
@@ -196,12 +200,18 @@ function ArchiveIcon(props) {
196
200
  /* @__PURE__ */ jsx5("path", { d: "M3.25 5.75v6.5a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1v-6.5M6.5 8.75h3" })
197
201
  ] });
198
202
  }
203
+ function ArrowDownIcon(props) {
204
+ return /* @__PURE__ */ jsx5(Icon, { ...props, children: /* @__PURE__ */ jsx5("path", { d: "M8 3v10M4 9l4 4 4-4" }) });
205
+ }
199
206
  function ArrowLeftIcon(props) {
200
207
  return /* @__PURE__ */ jsx5(Icon, { ...props, children: /* @__PURE__ */ jsx5("path", { d: "M13 8H3M7 4 3 8l4 4" }) });
201
208
  }
202
209
  function ArrowRightIcon(props) {
203
210
  return /* @__PURE__ */ jsx5(Icon, { ...props, children: /* @__PURE__ */ jsx5("path", { d: "M3 8h10M9 4l4 4-4 4" }) });
204
211
  }
212
+ function ArrowUpIcon(props) {
213
+ return /* @__PURE__ */ jsx5(Icon, { ...props, children: /* @__PURE__ */ jsx5("path", { d: "M8 13V3M4 7l4-4 4 4" }) });
214
+ }
205
215
  function BellIcon(props) {
206
216
  return /* @__PURE__ */ jsxs4(Icon, { ...props, children: [
207
217
  /* @__PURE__ */ jsx5("path", { d: "M4 6.5a4 4 0 0 1 8 0v3l1.25 2H2.75L4 9.5z" }),
@@ -451,7 +461,7 @@ function Root({ dismissible = true, onOpenChange, open, defaultOpen, children })
451
461
  );
452
462
  }
453
463
  var Trigger = BaseDialog.Trigger;
454
- function Content({ size = "md", className, children, ...rest }) {
464
+ function Content({ size = "md", variant = "dialog", className, children, ...rest }) {
455
465
  return /* @__PURE__ */ jsxs5(BaseDialog.Portal, { children: [
456
466
  /* @__PURE__ */ jsx6(BaseDialog.Backdrop, { className: "sc-dialog__backdrop" }),
457
467
  /* @__PURE__ */ jsx6(
@@ -459,6 +469,7 @@ function Content({ size = "md", className, children, ...rest }) {
459
469
  {
460
470
  className: cx("sc-dialog__popup", className),
461
471
  "data-size": size,
472
+ "data-variant": variant,
462
473
  "aria-modal": "true",
463
474
  ...rest,
464
475
  children
@@ -489,8 +500,10 @@ var Dialog = { Root, Trigger, Content, Title, Description, Body, Actions, Close
489
500
  // src/icons/icon-names.gen.ts
490
501
  var iconNames = [
491
502
  "archive",
503
+ "arrow-down",
492
504
  "arrow-left",
493
505
  "arrow-right",
506
+ "arrow-up",
494
507
  "bell",
495
508
  "briefcase",
496
509
  "calendar",
@@ -537,6 +550,9 @@ var iconNames = [
537
550
  "x"
538
551
  ];
539
552
 
553
+ // src/components/IconButton/IconButton.tsx
554
+ import { useRender as useRender2 } from "@base-ui/react/use-render";
555
+
540
556
  // src/components/Tooltip/Tooltip.tsx
541
557
  import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
542
558
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -574,7 +590,7 @@ var Provider = BaseTooltip.Provider;
574
590
  var Tooltip = Object.assign(TooltipBase, { Provider });
575
591
 
576
592
  // src/components/IconButton/IconButton.tsx
577
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
593
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
578
594
  function IconButton({
579
595
  label,
580
596
  children,
@@ -584,9 +600,12 @@ function IconButton({
584
600
  tooltipSide = "top",
585
601
  round = false,
586
602
  loading = false,
587
- type = "button",
603
+ dot,
604
+ type,
588
605
  className,
589
606
  onClick,
607
+ render,
608
+ ref,
590
609
  ...rest
591
610
  }) {
592
611
  const handleClick = (event) => {
@@ -596,10 +615,13 @@ function IconButton({
596
615
  }
597
616
  onClick?.(event);
598
617
  };
599
- const button = /* @__PURE__ */ jsxs7(
600
- "button",
601
- {
602
- type,
618
+ const button = useRender2({
619
+ render,
620
+ ref,
621
+ defaultTagName: "button",
622
+ props: {
623
+ // `type` only means something on a real button; a rendered link keeps its own attributes.
624
+ type: render ? type : type ?? "button",
603
625
  className: cx("sc-button", "sc-icon-button", className),
604
626
  "data-variant": variant,
605
627
  "data-size": size,
@@ -609,19 +631,20 @@ function IconButton({
609
631
  "aria-label": label,
610
632
  onClick: handleClick,
611
633
  ...rest,
612
- children: [
634
+ children: /* @__PURE__ */ jsxs7(Fragment2, { children: [
613
635
  /* @__PURE__ */ jsx8("span", { className: "sc-button__icon", "aria-hidden": "true", children }),
614
- loading ? /* @__PURE__ */ jsx8("span", { className: "sc-button__spinner", "aria-hidden": "true" }) : null
615
- ]
636
+ loading ? /* @__PURE__ */ jsx8("span", { className: "sc-button__spinner", "aria-hidden": "true" }) : null,
637
+ dot ? /* @__PURE__ */ jsx8("span", { className: "sc-icon-button__dot", "data-tone": dot, "aria-hidden": "true" }) : null
638
+ ] })
616
639
  }
617
- );
640
+ });
618
641
  if (!tooltip) return button;
619
642
  return /* @__PURE__ */ jsx8(Tooltip, { content: tooltip === true ? label : tooltip, side: tooltipSide, children: button });
620
643
  }
621
644
 
622
645
  // src/components/Menu/Menu.tsx
623
646
  import { Menu as BaseMenu } from "@base-ui/react/menu";
624
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
647
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
625
648
  function Root2({ open, defaultOpen, onOpenChange, disabled, modal = true, children }) {
626
649
  return /* @__PURE__ */ jsx9(
627
650
  BaseMenu.Root,
@@ -661,7 +684,7 @@ function ItemBody({
661
684
  trailing,
662
685
  children
663
686
  }) {
664
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
687
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
665
688
  /* @__PURE__ */ jsx9("span", { className: "sc-menu__icon", "aria-hidden": "true", children: icon }),
666
689
  /* @__PURE__ */ jsx9("span", { className: "sc-menu__label", children }),
667
690
  trailing !== void 0 ? /* @__PURE__ */ jsx9("span", { className: "sc-menu__trailing", children: trailing }) : null
@@ -848,9 +871,14 @@ function Textarea({
848
871
  className,
849
872
  rows = 3,
850
873
  resize = "vertical",
874
+ variant = "default",
851
875
  onValueChange,
876
+ spellCheck,
877
+ autoCorrect,
878
+ autoCapitalize,
852
879
  ...rest
853
880
  }) {
881
+ const code = variant === "code";
854
882
  return /* @__PURE__ */ jsx12(
855
883
  FieldShell,
856
884
  {
@@ -866,9 +894,19 @@ function Textarea({
866
894
  children: /* @__PURE__ */ jsx12(
867
895
  Field3.Control,
868
896
  {
869
- render: /* @__PURE__ */ jsx12("textarea", { rows, ...rest }),
897
+ render: /* @__PURE__ */ jsx12(
898
+ "textarea",
899
+ {
900
+ rows,
901
+ spellCheck: spellCheck ?? (code ? false : void 0),
902
+ autoCorrect: autoCorrect ?? (code ? "off" : void 0),
903
+ autoCapitalize: autoCapitalize ?? (code ? "off" : void 0),
904
+ ...rest
905
+ }
906
+ ),
870
907
  className: "sc-input sc-textarea",
871
908
  "data-resize": resize,
909
+ "data-variant": code ? "code" : void 0,
872
910
  required,
873
911
  onValueChange: onValueChange ? (value) => onValueChange(value) : void 0
874
912
  }
@@ -879,6 +917,7 @@ function Textarea({
879
917
 
880
918
  // src/components/Select/Select.tsx
881
919
  import { Select as BaseSelect } from "@base-ui/react/select";
920
+ import { useState } from "react";
882
921
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
883
922
  function isGroup(entry) {
884
923
  return "options" in entry;
@@ -905,11 +944,27 @@ function Select({
905
944
  defaultValue,
906
945
  onValueChange,
907
946
  placeholder = "Choose\u2026",
947
+ clearable = false,
948
+ clearLabel = "Clear",
908
949
  readOnly,
909
950
  fullWidth = false,
910
951
  id
911
952
  }) {
912
953
  const items = options.flatMap((entry) => isGroup(entry) ? entry.options : [entry]);
954
+ const [internal, setInternal] = useState(defaultValue ?? null);
955
+ const controlled = value !== void 0;
956
+ const current = controlled ? value : internal;
957
+ const setValue = (next) => {
958
+ if (!controlled) setInternal(next);
959
+ onValueChange?.(next);
960
+ };
961
+ const canClear = clearable && current != null && !disabled && !readOnly;
962
+ const onTriggerKeyDown = (event) => {
963
+ if (canClear && (event.key === "Backspace" || event.key === "Delete")) {
964
+ event.preventDefault();
965
+ setValue(null);
966
+ }
967
+ };
913
968
  return /* @__PURE__ */ jsx13(
914
969
  FieldShell,
915
970
  {
@@ -927,26 +982,39 @@ function Select({
927
982
  BaseSelect.Root,
928
983
  {
929
984
  items,
930
- value,
931
- defaultValue,
932
- onValueChange: onValueChange ? (next) => onValueChange(next) : void 0,
985
+ value: current,
986
+ onValueChange: (next) => setValue(next),
933
987
  disabled,
934
988
  required,
935
989
  readOnly,
936
990
  children: [
937
- /* @__PURE__ */ jsxs11(
938
- BaseSelect.Trigger,
939
- {
940
- id,
941
- className: "sc-select",
942
- "data-size": size,
943
- "data-full-width": fullWidth || void 0,
944
- children: [
945
- /* @__PURE__ */ jsx13(BaseSelect.Value, { className: "sc-select__value", placeholder }),
946
- /* @__PURE__ */ jsx13(BaseSelect.Icon, { className: "sc-select__icon", children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) })
947
- ]
948
- }
949
- ),
991
+ /* @__PURE__ */ jsxs11("span", { className: "sc-select__wrap", "data-full-width": fullWidth || void 0, children: [
992
+ /* @__PURE__ */ jsxs11(
993
+ BaseSelect.Trigger,
994
+ {
995
+ id,
996
+ className: "sc-select",
997
+ "data-size": size,
998
+ "data-full-width": fullWidth || void 0,
999
+ "data-clearable": canClear || void 0,
1000
+ onKeyDown: onTriggerKeyDown,
1001
+ children: [
1002
+ /* @__PURE__ */ jsx13(BaseSelect.Value, { className: "sc-select__value", placeholder }),
1003
+ /* @__PURE__ */ jsx13(BaseSelect.Icon, { className: "sc-select__icon", children: /* @__PURE__ */ jsx13(ChevronDownIcon, {}) })
1004
+ ]
1005
+ }
1006
+ ),
1007
+ canClear ? /* @__PURE__ */ jsx13(
1008
+ "button",
1009
+ {
1010
+ type: "button",
1011
+ className: "sc-select__clear",
1012
+ "aria-label": clearLabel,
1013
+ onClick: () => setValue(null),
1014
+ children: /* @__PURE__ */ jsx13(XIcon, { size: "sm" })
1015
+ }
1016
+ ) : null
1017
+ ] }),
950
1018
  /* @__PURE__ */ jsx13(BaseSelect.Portal, { children: /* @__PURE__ */ jsx13(
951
1019
  BaseSelect.Positioner,
952
1020
  {
@@ -1046,7 +1114,7 @@ function Switch({
1046
1114
 
1047
1115
  // src/components/Tabs/Tabs.tsx
1048
1116
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
1049
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1117
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1050
1118
  function Root3({ className, onValueChange, ...rest }) {
1051
1119
  return /* @__PURE__ */ jsx16(
1052
1120
  BaseTabs.Root,
@@ -1057,17 +1125,26 @@ function Root3({ className, onValueChange, ...rest }) {
1057
1125
  }
1058
1126
  );
1059
1127
  }
1060
- function List({ fill = false, className, children, ...rest }) {
1061
- return /* @__PURE__ */ jsxs14(BaseTabs.List, { className: cx("sc-tabs__list", className), "data-fill": fill || void 0, ...rest, children: [
1062
- children,
1063
- /* @__PURE__ */ jsx16(BaseTabs.Indicator, { className: "sc-tabs__indicator" })
1064
- ] });
1128
+ function List({ fill = false, variant = "line", className, children, ...rest }) {
1129
+ return /* @__PURE__ */ jsxs14(
1130
+ BaseTabs.List,
1131
+ {
1132
+ className: cx("sc-tabs__list", className),
1133
+ "data-fill": fill || void 0,
1134
+ "data-variant": variant,
1135
+ ...rest,
1136
+ children: [
1137
+ children,
1138
+ /* @__PURE__ */ jsx16(BaseTabs.Indicator, { className: "sc-tabs__indicator" })
1139
+ ]
1140
+ }
1141
+ );
1065
1142
  }
1066
1143
  function Tab({ icon, count, className, children, ...rest }) {
1067
1144
  return /* @__PURE__ */ jsxs14(BaseTabs.Tab, { className: cx("sc-tabs__tab", className), ...rest, children: [
1068
1145
  icon ? /* @__PURE__ */ jsx16("span", { className: "sc-tabs__icon", "aria-hidden": "true", children: icon }) : null,
1069
1146
  /* @__PURE__ */ jsx16("span", { className: "sc-tabs__label", children }),
1070
- count != null ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
1147
+ count != null ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
1071
1148
  " ",
1072
1149
  /* @__PURE__ */ jsx16("span", { className: "sc-tabs__count", children: count })
1073
1150
  ] }) : null
@@ -1099,13 +1176,14 @@ function Separator2({ className, ...rest }) {
1099
1176
  return /* @__PURE__ */ jsx17(BaseToolbar.Separator, { className: cx("sc-toolbar__separator", className), ...rest });
1100
1177
  }
1101
1178
  var Button2 = BaseToolbar.Button;
1179
+ var Link = BaseToolbar.Link;
1102
1180
  function Spacer({ className }) {
1103
1181
  return /* @__PURE__ */ jsx17("div", { className: cx("sc-toolbar__spacer", className), "aria-hidden": "true" });
1104
1182
  }
1105
- var Toolbar = { Root: Root4, Group: Group2, Separator: Separator2, Button: Button2, Spacer };
1183
+ var Toolbar = { Root: Root4, Group: Group2, Separator: Separator2, Button: Button2, Link, Spacer };
1106
1184
 
1107
1185
  // src/components/Banner/Banner.tsx
1108
- import { useState } from "react";
1186
+ import { useState as useState2 } from "react";
1109
1187
  import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1110
1188
  var toneIcons = {
1111
1189
  info: /* @__PURE__ */ jsx18(InfoIcon, {}),
@@ -1127,7 +1205,7 @@ function Banner({
1127
1205
  children,
1128
1206
  ...rest
1129
1207
  }) {
1130
- const [dismissed, setDismissed] = useState(false);
1208
+ const [dismissed, setDismissed] = useState2(false);
1131
1209
  const visible = open ?? !dismissed;
1132
1210
  if (!visible) return null;
1133
1211
  const glyph = icon === false ? null : icon ?? toneIcons[tone];
@@ -1279,30 +1357,1795 @@ function Text({
1279
1357
  style,
1280
1358
  ...rest
1281
1359
  }) {
1282
- const clamp = typeof truncate === "number" ? truncate : void 0;
1360
+ const clamp2 = typeof truncate === "number" ? truncate : void 0;
1283
1361
  return createElement4(as, {
1284
1362
  className: cx("sc-text", className),
1285
1363
  "data-size": size,
1286
1364
  "data-tone": tone,
1287
1365
  "data-weight": weight,
1288
1366
  "data-align": align,
1289
- "data-truncate": truncate === true ? "" : clamp !== void 0 ? "clamp" : void 0,
1367
+ "data-truncate": truncate === true ? "" : clamp2 !== void 0 ? "clamp" : void 0,
1290
1368
  "data-numeric": numeric || void 0,
1291
- style: clamp !== void 0 ? { ...style, "--sc-text-lines": clamp } : style,
1369
+ style: clamp2 !== void 0 ? { ...style, "--sc-text-lines": clamp2 } : style,
1292
1370
  ...rest
1293
1371
  });
1294
1372
  }
1295
1373
 
1374
+ // src/components/Table/Table.tsx
1375
+ import { Checkbox as BaseCheckbox2 } from "@base-ui/react/checkbox";
1376
+ import {
1377
+ createContext,
1378
+ useContext
1379
+ } from "react";
1380
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1381
+ var SelectionContext = createContext(null);
1382
+ var RowIdContext = createContext(void 0);
1383
+ function useSelection(part) {
1384
+ const selection = useContext(SelectionContext);
1385
+ if (!selection) throw new Error(`${part} needs Table.Root selection={useRowSelection(ids)}`);
1386
+ return selection;
1387
+ }
1388
+ function isTextEntry(target) {
1389
+ if (!(target instanceof HTMLElement)) return false;
1390
+ if (target.isContentEditable || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement)
1391
+ return true;
1392
+ return target instanceof HTMLInputElement && !["checkbox", "radio", "button", "submit", "reset", "image", "file", "color", "range"].includes(
1393
+ target.type
1394
+ );
1395
+ }
1396
+ var CONTROLS = 'a[href], button, input, select, textarea, label, summary, [role="checkbox"], [role="button"], [role="link"], [contenteditable="true"]';
1397
+ function fromControl(event) {
1398
+ const control = event.target instanceof Element ? event.target.closest(CONTROLS) : null;
1399
+ return control !== null && event.currentTarget.contains(control);
1400
+ }
1401
+ function Root5({
1402
+ stickyHeader = false,
1403
+ maxHeight,
1404
+ density,
1405
+ divided = true,
1406
+ layout = "auto",
1407
+ wrapperClassName,
1408
+ wrapperStyle,
1409
+ className,
1410
+ style,
1411
+ children,
1412
+ selection,
1413
+ onKeyDown,
1414
+ ...rest
1415
+ }) {
1416
+ const handleKeyDown = (event) => {
1417
+ onKeyDown?.(event);
1418
+ if (!selection || event.defaultPrevented) return;
1419
+ if (!(event.target instanceof Node) || !event.currentTarget.contains(event.target)) return;
1420
+ if (isTextEntry(event.target)) return;
1421
+ if ((event.metaKey || event.ctrlKey) && !event.altKey && event.key.toLowerCase() === "a") {
1422
+ event.preventDefault();
1423
+ selection.selectAll();
1424
+ } else if (event.key === "Escape" && selection.count > 0) {
1425
+ event.preventDefault();
1426
+ selection.clear();
1427
+ }
1428
+ };
1429
+ return /* @__PURE__ */ jsx21(
1430
+ "div",
1431
+ {
1432
+ className: cx("sc-table-wrap", wrapperClassName),
1433
+ "data-sticky-header": stickyHeader || void 0,
1434
+ "data-scroll": maxHeight ? "" : void 0,
1435
+ style: maxHeight ? { ...wrapperStyle, maxBlockSize: maxHeight } : wrapperStyle,
1436
+ children: /* @__PURE__ */ jsx21(
1437
+ "table",
1438
+ {
1439
+ className: cx("sc-table", className),
1440
+ "data-density": density,
1441
+ "data-divided": divided || void 0,
1442
+ "data-layout": layout,
1443
+ style,
1444
+ onKeyDown: selection ? handleKeyDown : onKeyDown,
1445
+ ...rest,
1446
+ children: /* @__PURE__ */ jsx21(SelectionContext.Provider, { value: selection ?? null, children })
1447
+ }
1448
+ )
1449
+ }
1450
+ );
1451
+ }
1452
+ function Caption({ className, ...rest }) {
1453
+ return /* @__PURE__ */ jsx21("caption", { className: cx("sc-table__caption", className), ...rest });
1454
+ }
1455
+ function Head({ className, ...rest }) {
1456
+ return /* @__PURE__ */ jsx21("thead", { className: cx("sc-table__head", className), ...rest });
1457
+ }
1458
+ function Body2({ className, ...rest }) {
1459
+ return /* @__PURE__ */ jsx21("tbody", { className: cx("sc-table__body", className), ...rest });
1460
+ }
1461
+ function Foot({ className, ...rest }) {
1462
+ return /* @__PURE__ */ jsx21("tfoot", { className: cx("sc-table__foot", className), ...rest });
1463
+ }
1464
+ function Row({
1465
+ selected,
1466
+ interactive = false,
1467
+ selectionId,
1468
+ className,
1469
+ onClick,
1470
+ onMouseDown,
1471
+ ...rest
1472
+ }) {
1473
+ const selection = useContext(SelectionContext);
1474
+ const selectable = selection !== null && selectionId !== void 0;
1475
+ const isSelected = selected ?? (selectable && selection.isSelected(selectionId));
1476
+ const row = /* @__PURE__ */ jsx21(
1477
+ "tr",
1478
+ {
1479
+ className: cx("sc-table__row", className),
1480
+ "data-selected": isSelected || void 0,
1481
+ "data-interactive": interactive || void 0,
1482
+ "aria-selected": selectable ? isSelected : isSelected || void 0,
1483
+ onClick: selectable ? (event) => {
1484
+ if ((event.shiftKey || event.metaKey || event.ctrlKey) && !fromControl(event)) {
1485
+ event.preventDefault();
1486
+ if (event.shiftKey) selection.toggleRange(selectionId);
1487
+ else selection.toggle(selectionId);
1488
+ return;
1489
+ }
1490
+ onClick?.(event);
1491
+ } : onClick,
1492
+ onMouseDown: selectable ? (event) => {
1493
+ if (event.shiftKey && !fromControl(event)) event.preventDefault();
1494
+ onMouseDown?.(event);
1495
+ } : onMouseDown,
1496
+ ...rest
1497
+ }
1498
+ );
1499
+ return selectionId === void 0 ? row : /* @__PURE__ */ jsx21(RowIdContext.Provider, { value: selectionId, children: row });
1500
+ }
1501
+ function SelectionBox({
1502
+ label,
1503
+ ...rest
1504
+ }) {
1505
+ return /* @__PURE__ */ jsx21(BaseCheckbox2.Root, { className: "sc-checkbox", "aria-label": label, ...rest, children: /* @__PURE__ */ jsxs18(BaseCheckbox2.Indicator, { className: "sc-checkbox__indicator", children: [
1506
+ /* @__PURE__ */ jsx21(CheckIcon, { size: "sm", className: "sc-checkbox__check" }),
1507
+ /* @__PURE__ */ jsx21(MinusIcon, { size: "sm", className: "sc-checkbox__dash" })
1508
+ ] }) });
1509
+ }
1510
+ var onCheckbox = (event) => event.target instanceof Element && event.target.closest('[role="checkbox"]') !== null;
1511
+ function SelectionHeader({
1512
+ label = "Select all rows",
1513
+ className,
1514
+ onClick,
1515
+ ...rest
1516
+ }) {
1517
+ const selection = useSelection("Table.SelectionHeader");
1518
+ const disabled = selection.ids.length === 0;
1519
+ const toggleAll = () => selection.headerState === "all" ? selection.clear() : selection.selectAll();
1520
+ return /* @__PURE__ */ jsx21(
1521
+ "th",
1522
+ {
1523
+ scope: "col",
1524
+ className: cx("sc-table__header", "sc-table__select", className),
1525
+ "data-disabled": disabled || void 0,
1526
+ onClick: (event) => {
1527
+ onClick?.(event);
1528
+ if (!disabled && !onCheckbox(event)) toggleAll();
1529
+ },
1530
+ ...rest,
1531
+ children: /* @__PURE__ */ jsx21(
1532
+ SelectionBox,
1533
+ {
1534
+ label,
1535
+ checked: selection.headerState === "all",
1536
+ indeterminate: selection.headerState === "some",
1537
+ disabled,
1538
+ onCheckedChange: toggleAll
1539
+ }
1540
+ )
1541
+ }
1542
+ );
1543
+ }
1544
+ function SelectionCell({ label, className, onClick, onClickCapture, ...rest }) {
1545
+ const selection = useSelection("Table.SelectionCell");
1546
+ const id = useContext(RowIdContext);
1547
+ if (id === void 0) throw new Error("Table.SelectionCell goes inside a Table.Row with selectionId");
1548
+ return /* @__PURE__ */ jsx21(
1549
+ "td",
1550
+ {
1551
+ className: cx("sc-table__cell", "sc-table__select", className),
1552
+ onClickCapture: (event) => {
1553
+ onClickCapture?.(event);
1554
+ if (!event.shiftKey) return;
1555
+ event.preventDefault();
1556
+ event.stopPropagation();
1557
+ selection.toggleRange(id);
1558
+ },
1559
+ onClick: (event) => {
1560
+ onClick?.(event);
1561
+ event.stopPropagation();
1562
+ if (!onCheckbox(event)) selection.toggle(id);
1563
+ },
1564
+ ...rest,
1565
+ children: /* @__PURE__ */ jsx21(
1566
+ SelectionBox,
1567
+ {
1568
+ label,
1569
+ checked: selection.isSelected(id),
1570
+ onCheckedChange: () => selection.toggle(id)
1571
+ }
1572
+ )
1573
+ }
1574
+ );
1575
+ }
1576
+ function Header({
1577
+ align,
1578
+ numeric = false,
1579
+ nowrap = false,
1580
+ truncate = false,
1581
+ width,
1582
+ sortable = false,
1583
+ sortDirection = "none",
1584
+ onSort,
1585
+ scope = "col",
1586
+ className,
1587
+ style,
1588
+ children,
1589
+ ...rest
1590
+ }) {
1591
+ const sorted = sortable && sortDirection !== "none";
1592
+ return /* @__PURE__ */ jsx21(
1593
+ "th",
1594
+ {
1595
+ scope,
1596
+ className: cx("sc-table__header", className),
1597
+ "data-align": align ?? (numeric ? "end" : void 0),
1598
+ "data-numeric": numeric || void 0,
1599
+ "data-nowrap": nowrap || void 0,
1600
+ "data-truncate": truncate || void 0,
1601
+ "data-sortable": sortable || void 0,
1602
+ "data-sorted": sorted ? sortDirection : void 0,
1603
+ "aria-sort": sorted ? sortDirection : void 0,
1604
+ style: width ? { ...style, inlineSize: width } : style,
1605
+ ...rest,
1606
+ children: sortable ? /* @__PURE__ */ jsxs18(
1607
+ "button",
1608
+ {
1609
+ type: "button",
1610
+ className: "sc-table__sort",
1611
+ onClick: () => onSort?.(sortDirection === "ascending" ? "descending" : "ascending"),
1612
+ children: [
1613
+ /* @__PURE__ */ jsx21("span", { className: "sc-table__sort-label", children }),
1614
+ /* @__PURE__ */ jsx21("span", { className: "sc-table__sort-icon", "aria-hidden": "true", children: sortDirection === "descending" ? /* @__PURE__ */ jsx21(ArrowDownIcon, { size: "xs" }) : /* @__PURE__ */ jsx21(ArrowUpIcon, { size: "xs" }) })
1615
+ ]
1616
+ }
1617
+ ) : children
1618
+ }
1619
+ );
1620
+ }
1621
+ function Cell({
1622
+ align,
1623
+ numeric = false,
1624
+ nowrap = false,
1625
+ truncate = false,
1626
+ width,
1627
+ className,
1628
+ style,
1629
+ ...rest
1630
+ }) {
1631
+ return /* @__PURE__ */ jsx21(
1632
+ "td",
1633
+ {
1634
+ className: cx("sc-table__cell", className),
1635
+ "data-align": align ?? (numeric ? "end" : void 0),
1636
+ "data-numeric": numeric || void 0,
1637
+ "data-nowrap": nowrap || void 0,
1638
+ "data-truncate": truncate || void 0,
1639
+ style: width ? { ...style, inlineSize: width } : style,
1640
+ ...rest
1641
+ }
1642
+ );
1643
+ }
1644
+ var Table = { Root: Root5, Caption, Head, Body: Body2, Foot, Row, Header, Cell, SelectionHeader, SelectionCell };
1645
+
1646
+ // src/components/Table/useRowSelection.ts
1647
+ import { useMemo, useReducer } from "react";
1648
+
1649
+ // src/components/Table/rowSelection.ts
1650
+ function initRowSelection(ids) {
1651
+ return { ids, selected: /* @__PURE__ */ new Set(), anchor: null };
1652
+ }
1653
+ function sameIds(a, b) {
1654
+ if (a === b) return true;
1655
+ if (a.length !== b.length) return false;
1656
+ for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
1657
+ return true;
1658
+ }
1659
+ function toggle(state, id) {
1660
+ if (!state.ids.includes(id)) return state;
1661
+ const selected = new Set(state.selected);
1662
+ if (selected.has(id)) selected.delete(id);
1663
+ else selected.add(id);
1664
+ return { ...state, selected, anchor: id };
1665
+ }
1666
+ function toggleRange(state, id) {
1667
+ const to = state.ids.indexOf(id);
1668
+ if (to < 0) return state;
1669
+ const from = state.anchor === null ? -1 : state.ids.indexOf(state.anchor);
1670
+ if (from < 0 || from === to) return toggle(state, id);
1671
+ const on = !state.selected.has(id);
1672
+ const selected = new Set(state.selected);
1673
+ const [start, end] = from < to ? [from, to] : [to, from];
1674
+ for (let i = start; i <= end; i += 1) {
1675
+ const rowId = state.ids[i];
1676
+ if (on) selected.add(rowId);
1677
+ else selected.delete(rowId);
1678
+ }
1679
+ return { ...state, selected, anchor: id };
1680
+ }
1681
+ function sync(state, ids) {
1682
+ if (sameIds(state.ids, ids)) return state;
1683
+ const present = new Set(ids);
1684
+ let selected = state.selected;
1685
+ for (const id of state.selected) {
1686
+ if (present.has(id)) continue;
1687
+ selected = new Set([...state.selected].filter((x) => present.has(x)));
1688
+ break;
1689
+ }
1690
+ const anchor = state.anchor !== null && present.has(state.anchor) ? state.anchor : null;
1691
+ return { ids, selected, anchor };
1692
+ }
1693
+ function rowSelectionReducer(state, event) {
1694
+ switch (event.type) {
1695
+ case "selection.sync":
1696
+ return sync(state, event.ids);
1697
+ case "selection.toggle":
1698
+ return toggle(state, event.id);
1699
+ case "selection.toggleRange":
1700
+ return toggleRange(state, event.id);
1701
+ case "selection.selectAll":
1702
+ return state.selected.size === state.ids.length ? state : { ...state, selected: new Set(state.ids) };
1703
+ case "selection.clear":
1704
+ return state.selected.size === 0 && state.anchor === null ? state : { ...state, selected: /* @__PURE__ */ new Set(), anchor: null };
1705
+ }
1706
+ }
1707
+ function headerState(state) {
1708
+ if (state.selected.size === 0) return "none";
1709
+ return state.selected.size === state.ids.length ? "all" : "some";
1710
+ }
1711
+ function selectedIds(state) {
1712
+ return state.ids.filter((id) => state.selected.has(id));
1713
+ }
1714
+
1715
+ // src/components/Table/useRowSelection.ts
1716
+ function useRowSelection(ids) {
1717
+ const [stored, dispatch] = useReducer(rowSelectionReducer, ids, initRowSelection);
1718
+ const state = sameIds(stored.ids, ids) ? stored : rowSelectionReducer(stored, { type: "selection.sync", ids });
1719
+ if (state !== stored) dispatch({ type: "selection.sync", ids });
1720
+ const actions = useMemo(
1721
+ () => ({
1722
+ toggle: (id) => dispatch({ type: "selection.toggle", id }),
1723
+ toggleRange: (id) => dispatch({ type: "selection.toggleRange", id }),
1724
+ selectAll: () => dispatch({ type: "selection.selectAll" }),
1725
+ clear: () => dispatch({ type: "selection.clear" })
1726
+ }),
1727
+ []
1728
+ );
1729
+ return useMemo(
1730
+ () => ({
1731
+ ids: state.ids,
1732
+ selected: state.selected,
1733
+ selectedIds: selectedIds(state),
1734
+ count: state.selected.size,
1735
+ anchor: state.anchor,
1736
+ headerState: headerState(state),
1737
+ isSelected: (id) => state.selected.has(id),
1738
+ ...actions
1739
+ }),
1740
+ [state, actions]
1741
+ );
1742
+ }
1743
+
1744
+ // src/components/SelectionBar/SelectionBar.tsx
1745
+ import { useEffect, useLayoutEffect, useRef, useState as useState3 } from "react";
1746
+ import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
1747
+ var defaultCountLabel = (count) => `${count} selected`;
1748
+ var LEAVE_MS = 200;
1749
+ function SelectionBar({
1750
+ count,
1751
+ onClear,
1752
+ children,
1753
+ "aria-label": ariaLabel = "Bulk actions",
1754
+ countLabel = defaultCountLabel,
1755
+ clearLabel = "Clear",
1756
+ clearedMessage = "Selection cleared",
1757
+ className
1758
+ }) {
1759
+ const open = count > 0;
1760
+ const [hadSelection, setHadSelection] = useState3(open);
1761
+ if (open && !hadSelection) setHadSelection(true);
1762
+ const message = open ? countLabel(count) : hadSelection ? clearedMessage : "";
1763
+ const [rendered, setRendered] = useState3(open);
1764
+ const [shownCount, setShownCount] = useState3(count);
1765
+ if (open && !rendered) setRendered(true);
1766
+ if (open && shownCount !== count) setShownCount(count);
1767
+ useEffect(() => {
1768
+ if (open || !rendered) return;
1769
+ const timer = setTimeout(() => setRendered(false), LEAVE_MS);
1770
+ return () => clearTimeout(timer);
1771
+ }, [open, rendered]);
1772
+ const barRef = useRef(null);
1773
+ const returnTo = useRef(null);
1774
+ useLayoutEffect(() => {
1775
+ const bar = barRef.current;
1776
+ if (open || !bar?.contains(bar.ownerDocument.activeElement)) return;
1777
+ if (returnTo.current?.isConnected) returnTo.current.focus();
1778
+ }, [open]);
1779
+ const [height, setHeight] = useState3(0);
1780
+ useEffect(() => {
1781
+ const bar = barRef.current;
1782
+ if (!rendered || !bar || typeof ResizeObserver === "undefined") return;
1783
+ const observer = new ResizeObserver(([entry]) => setHeight(entry.borderBoxSize[0]?.blockSize ?? 0));
1784
+ observer.observe(bar);
1785
+ return () => observer.disconnect();
1786
+ }, [rendered]);
1787
+ return /* @__PURE__ */ jsxs19(Fragment5, { children: [
1788
+ /* @__PURE__ */ jsx22("span", { role: "status", className: "sc-visually-hidden", children: message }),
1789
+ rendered ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
1790
+ open ? /* @__PURE__ */ jsx22(
1791
+ "div",
1792
+ {
1793
+ className: "sc-selection-bar__spacer",
1794
+ style: { "--sc-selection-bar-height": `${height}px` },
1795
+ "aria-hidden": "true"
1796
+ }
1797
+ ) : null,
1798
+ /* @__PURE__ */ jsx22(
1799
+ "div",
1800
+ {
1801
+ ref: barRef,
1802
+ className: cx("sc-selection-bar", className),
1803
+ "data-open": open || void 0,
1804
+ onFocus: (event) => {
1805
+ const from = event.relatedTarget;
1806
+ if (from instanceof HTMLElement && !event.currentTarget.contains(from)) returnTo.current = from;
1807
+ },
1808
+ children: /* @__PURE__ */ jsxs19(Toolbar.Root, { "aria-label": ariaLabel, className: "sc-selection-bar__toolbar", children: [
1809
+ /* @__PURE__ */ jsx22("span", { className: "sc-selection-bar__count", children: countLabel(shownCount) }),
1810
+ /* @__PURE__ */ jsx22(Toolbar.Separator, {}),
1811
+ children,
1812
+ /* @__PURE__ */ jsx22(Toolbar.Spacer, {}),
1813
+ /* @__PURE__ */ jsx22(Toolbar.Button, { render: /* @__PURE__ */ jsx22(Button, { variant: "ghost", size: "sm" }), onClick: onClear, children: clearLabel })
1814
+ ] })
1815
+ }
1816
+ )
1817
+ ] }) : null
1818
+ ] });
1819
+ }
1820
+
1821
+ // src/components/Toast/Toast.tsx
1822
+ import { Toast as BaseToast } from "@base-ui/react/toast";
1823
+ import { useMemo as useMemo2 } from "react";
1824
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
1825
+ function Provider2({ children, timeout = 6e3, limit = 3 }) {
1826
+ return /* @__PURE__ */ jsxs20(BaseToast.Provider, { timeout, limit, children: [
1827
+ children,
1828
+ /* @__PURE__ */ jsx23(BaseToast.Portal, { children: /* @__PURE__ */ jsx23(Viewport, {}) })
1829
+ ] });
1830
+ }
1831
+ function Viewport() {
1832
+ const { toasts, close } = BaseToast.useToastManager();
1833
+ 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: [
1834
+ /* @__PURE__ */ jsxs20(BaseToast.Content, { className: "sc-toast__content", children: [
1835
+ /* @__PURE__ */ jsx23(BaseToast.Title, { className: "sc-toast__title" }),
1836
+ toast.description != null ? /* @__PURE__ */ jsx23(BaseToast.Description, { className: "sc-toast__description" }) : null
1837
+ ] }),
1838
+ toast.actionProps ? /* @__PURE__ */ jsx23(
1839
+ BaseToast.Action,
1840
+ {
1841
+ className: "sc-toast__action",
1842
+ render: /* @__PURE__ */ jsx23(Button, { variant: "secondary", size: "sm" })
1843
+ }
1844
+ ) : null,
1845
+ /* @__PURE__ */ jsx23(IconButton, { label: "Dismiss", size: "sm", className: "sc-toast__close", onClick: () => close(toast.id), children: /* @__PURE__ */ jsx23(XIcon, {}) })
1846
+ ] }, toast.id)) });
1847
+ }
1848
+ function useToast() {
1849
+ const manager = BaseToast.useToastManager();
1850
+ return useMemo2(
1851
+ () => ({
1852
+ add: ({ title, description, tone = "neutral", action, timeout, priority }) => {
1853
+ let id = "";
1854
+ id = manager.add({
1855
+ title,
1856
+ description,
1857
+ type: tone,
1858
+ ...timeout !== void 0 ? { timeout } : {},
1859
+ ...priority ? { priority } : {},
1860
+ ...action ? {
1861
+ actionProps: {
1862
+ children: action.label,
1863
+ onClick: () => {
1864
+ action.onClick();
1865
+ manager.close(id);
1866
+ }
1867
+ }
1868
+ } : {}
1869
+ });
1870
+ return id;
1871
+ },
1872
+ close: manager.close
1873
+ }),
1874
+ [manager]
1875
+ );
1876
+ }
1877
+ var Toast = { Provider: Provider2 };
1878
+
1879
+ // src/components/Stat/Stat.tsx
1880
+ import { createElement as createElement5 } from "react";
1881
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
1882
+ var trendIcons = {
1883
+ up: /* @__PURE__ */ jsx24(ArrowUpIcon, { size: "xs" }),
1884
+ down: /* @__PURE__ */ jsx24(ArrowDownIcon, { size: "xs" }),
1885
+ flat: /* @__PURE__ */ jsx24(ArrowRightIcon, { size: "xs" })
1886
+ };
1887
+ function Stat({
1888
+ label,
1889
+ value,
1890
+ delta,
1891
+ deltaTone = "neutral",
1892
+ trend,
1893
+ hint,
1894
+ icon,
1895
+ variant = "outlined",
1896
+ size = "md",
1897
+ as = "div",
1898
+ className,
1899
+ ...rest
1900
+ }) {
1901
+ return createElement5(
1902
+ as,
1903
+ {
1904
+ className: cx("sc-stat", className),
1905
+ "data-variant": variant,
1906
+ "data-size": size,
1907
+ ...rest
1908
+ },
1909
+ /* @__PURE__ */ jsxs21(Fragment6, { children: [
1910
+ /* @__PURE__ */ jsx24("div", { className: "sc-stat__label", children: label }),
1911
+ icon ? /* @__PURE__ */ jsx24("span", { className: "sc-stat__icon", "aria-hidden": "true", children: icon }) : null,
1912
+ /* @__PURE__ */ jsx24("div", { className: "sc-stat__value", children: value }),
1913
+ delta != null ? /* @__PURE__ */ jsxs21("div", { className: "sc-stat__delta", "data-tone": deltaTone, children: [
1914
+ trend ? /* @__PURE__ */ jsx24("span", { className: "sc-stat__trend", "aria-hidden": "true", children: trendIcons[trend] }) : null,
1915
+ trend ? /* @__PURE__ */ jsxs21("span", { className: "sc-visually-hidden", children: [
1916
+ trend === "flat" ? "unchanged" : trend,
1917
+ " "
1918
+ ] }) : null,
1919
+ delta
1920
+ ] }) : null,
1921
+ hint != null ? /* @__PURE__ */ jsx24("div", { className: "sc-stat__hint", children: hint }) : null
1922
+ ] })
1923
+ );
1924
+ }
1925
+
1926
+ // src/components/Chip/Chip.tsx
1927
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
1928
+ function Chip({
1929
+ children,
1930
+ icon,
1931
+ tone = "neutral",
1932
+ size = "md",
1933
+ selected = false,
1934
+ onClick,
1935
+ onRemove,
1936
+ removeLabel,
1937
+ disabled = false,
1938
+ className,
1939
+ ...rest
1940
+ }) {
1941
+ const interactive = onClick !== void 0;
1942
+ const removeName = removeLabel ?? (typeof children === "string" ? `Remove ${children}` : "Remove");
1943
+ const handleRemoveKey = (event) => {
1944
+ if (onRemove && !disabled && (event.key === "Backspace" || event.key === "Delete")) {
1945
+ event.preventDefault();
1946
+ onRemove();
1947
+ }
1948
+ };
1949
+ const shared = {
1950
+ className: cx("sc-chip", className),
1951
+ "data-tone": tone,
1952
+ "data-size": size,
1953
+ "data-selected": selected || void 0,
1954
+ "data-removable": onRemove ? "" : void 0,
1955
+ "data-disabled": disabled || void 0
1956
+ };
1957
+ const body = /* @__PURE__ */ jsxs22(Fragment7, { children: [
1958
+ icon ? /* @__PURE__ */ jsx25("span", { className: "sc-chip__icon", "aria-hidden": "true", children: icon }) : null,
1959
+ /* @__PURE__ */ jsx25("span", { className: "sc-chip__label", children })
1960
+ ] });
1961
+ const remove = onRemove ? /* @__PURE__ */ jsx25(
1962
+ "button",
1963
+ {
1964
+ type: "button",
1965
+ className: "sc-chip__remove",
1966
+ "aria-label": removeName,
1967
+ disabled,
1968
+ onClick: (event) => {
1969
+ event.stopPropagation();
1970
+ onRemove();
1971
+ },
1972
+ onKeyDown: handleRemoveKey,
1973
+ children: /* @__PURE__ */ jsx25(XIcon, { size: "xs" })
1974
+ }
1975
+ ) : null;
1976
+ if (interactive) {
1977
+ return /* @__PURE__ */ jsxs22("span", { ...shared, ...rest, children: [
1978
+ /* @__PURE__ */ jsx25(
1979
+ "button",
1980
+ {
1981
+ type: "button",
1982
+ className: "sc-chip__action",
1983
+ "aria-pressed": selected,
1984
+ disabled,
1985
+ onClick,
1986
+ onKeyDown: handleRemoveKey,
1987
+ children: body
1988
+ }
1989
+ ),
1990
+ remove
1991
+ ] });
1992
+ }
1993
+ return /* @__PURE__ */ jsxs22("span", { ...shared, ...rest, children: [
1994
+ body,
1995
+ remove
1996
+ ] });
1997
+ }
1998
+
1999
+ // src/components/Disclosure/Disclosure.tsx
2000
+ import {
2001
+ useEffect as useEffect2,
2002
+ useRef as useRef2,
2003
+ useState as useState4
2004
+ } from "react";
2005
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
2006
+ function Disclosure({
2007
+ summary,
2008
+ summaryOpen,
2009
+ open,
2010
+ defaultOpen = false,
2011
+ onOpenChange,
2012
+ previewLines,
2013
+ summaryPosition,
2014
+ className,
2015
+ style,
2016
+ children,
2017
+ ref,
2018
+ ...rest
2019
+ }) {
2020
+ const controlled = open !== void 0;
2021
+ const [internal, setInternal] = useState4(defaultOpen);
2022
+ const isOpen = controlled ? open : internal;
2023
+ const inner = useRef2(null);
2024
+ useEffect2(() => {
2025
+ if (controlled && inner.current && inner.current.open !== open) inner.current.open = open;
2026
+ });
2027
+ const onToggle = (event) => {
2028
+ const next = event.currentTarget.open;
2029
+ if (next === isOpen) return;
2030
+ if (!controlled) setInternal(next);
2031
+ onOpenChange?.(next);
2032
+ };
2033
+ const position = summaryPosition ?? (previewLines ? "end" : "start");
2034
+ return /* @__PURE__ */ jsxs23(
2035
+ "details",
2036
+ {
2037
+ ref: (node) => {
2038
+ inner.current = node;
2039
+ if (typeof ref === "function") ref(node);
2040
+ else if (ref) ref.current = node;
2041
+ },
2042
+ className: cx("sc-disclosure", className),
2043
+ open: isOpen,
2044
+ onToggle,
2045
+ "data-summary-position": position,
2046
+ "data-preview": previewLines ? "" : void 0,
2047
+ style: previewLines ? { ...style, "--_lines": previewLines } : style,
2048
+ ...rest,
2049
+ children: [
2050
+ /* @__PURE__ */ jsxs23("summary", { className: "sc-disclosure__summary", children: [
2051
+ /* @__PURE__ */ jsx26(ChevronDownIcon, { className: "sc-disclosure__chevron" }),
2052
+ /* @__PURE__ */ jsx26("span", { className: "sc-disclosure__summary-text", children: isOpen && summaryOpen != null ? summaryOpen : summary })
2053
+ ] }),
2054
+ /* @__PURE__ */ jsx26("div", { className: "sc-disclosure__content", children })
2055
+ ]
2056
+ }
2057
+ );
2058
+ }
2059
+
2060
+ // src/components/EmptyState/EmptyState.tsx
2061
+ import { createElement as createElement6 } from "react";
2062
+ import { jsx as jsx27 } from "react/jsx-runtime";
2063
+ function EmptyState({
2064
+ title,
2065
+ description,
2066
+ icon,
2067
+ children,
2068
+ size = "md",
2069
+ as = "div",
2070
+ className,
2071
+ ...rest
2072
+ }) {
2073
+ return createElement6(
2074
+ as,
2075
+ { className: cx("sc-empty-state", className), "data-size": size, ...rest },
2076
+ icon ? /* @__PURE__ */ jsx27("span", { className: "sc-empty-state__icon", "aria-hidden": "true", children: icon }) : null,
2077
+ /* @__PURE__ */ jsx27("p", { className: "sc-empty-state__title", children: title }),
2078
+ description != null ? /* @__PURE__ */ jsx27("p", { className: "sc-empty-state__description", children: description }) : null,
2079
+ children != null ? /* @__PURE__ */ jsx27("div", { className: "sc-empty-state__actions", children }) : null
2080
+ );
2081
+ }
2082
+
2083
+ // src/components/Skeleton/Skeleton.tsx
2084
+ import { jsx as jsx28 } from "react/jsx-runtime";
2085
+ function Skeleton({
2086
+ variant = "text",
2087
+ width,
2088
+ height,
2089
+ lines = 1,
2090
+ still = false,
2091
+ className,
2092
+ style,
2093
+ ...rest
2094
+ }) {
2095
+ const size = {
2096
+ ...style,
2097
+ ...width !== void 0 ? { inlineSize: width } : {},
2098
+ ...height !== void 0 ? { blockSize: height } : {}
2099
+ };
2100
+ if (variant === "text" && lines > 1) {
2101
+ return /* @__PURE__ */ jsx28("span", { className: cx("sc-skeleton-lines", className), "aria-hidden": "true", style, ...rest, children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx28(
2102
+ "span",
2103
+ {
2104
+ className: "sc-skeleton",
2105
+ "data-variant": "text",
2106
+ "data-still": still || void 0,
2107
+ "data-last": i === lines - 1 || void 0,
2108
+ style: width !== void 0 ? { inlineSize: width } : void 0
2109
+ },
2110
+ i
2111
+ )) });
2112
+ }
2113
+ return /* @__PURE__ */ jsx28(
2114
+ "span",
2115
+ {
2116
+ className: cx("sc-skeleton", className),
2117
+ "data-variant": variant,
2118
+ "data-still": still || void 0,
2119
+ "aria-hidden": "true",
2120
+ style: size,
2121
+ ...rest
2122
+ }
2123
+ );
2124
+ }
2125
+
2126
+ // src/components/FileInput/FileInput.tsx
2127
+ import { useEffect as useEffect4, useId as useId3, useRef as useRef4, useState as useState6 } from "react";
2128
+
2129
+ // src/components/FilePreviewDialog/FilePreviewDialog.tsx
2130
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState5 } from "react";
2131
+
2132
+ // src/components/FileInput/accept.ts
2133
+ function parseAccept(accept) {
2134
+ if (accept == null) return [];
2135
+ const list = typeof accept === "string" ? accept.split(",") : accept;
2136
+ return list.map((entry) => entry.trim().toLowerCase()).filter(Boolean);
2137
+ }
2138
+ function matchesAccept(file, accept) {
2139
+ if (accept.length === 0) return true;
2140
+ const name = file.name.toLowerCase();
2141
+ const type = file.type.toLowerCase();
2142
+ return accept.some((entry) => {
2143
+ if (entry.startsWith(".")) return name.endsWith(entry);
2144
+ if (entry.endsWith("/*")) return type.startsWith(entry.slice(0, -1));
2145
+ return type === entry;
2146
+ });
2147
+ }
2148
+ var UNITS = { b: 1, kb: 1e3, mb: 1e6, gb: 1e9 };
2149
+ function parseSize(size) {
2150
+ if (size == null) return void 0;
2151
+ if (typeof size === "number") return size;
2152
+ const match = /^\s*(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)\s*$/i.exec(size);
2153
+ if (!match) throw new Error(`FileInput: maxFileSize "${size}" is not a size like "10MB".`);
2154
+ return Math.round(Number(match[1]) * UNITS[match[2].toLowerCase()]);
2155
+ }
2156
+ function formatSize(bytes) {
2157
+ const [unit, base] = bytes >= 1e9 ? ["GB", 1e9] : bytes >= 1e6 ? ["MB", 1e6] : bytes >= 1e3 ? ["KB", 1e3] : ["bytes", 1];
2158
+ const value = bytes / base;
2159
+ return `${Number.isInteger(value) ? value : Number(value.toFixed(1))} ${unit}`;
2160
+ }
2161
+ function formatListSize(bytes) {
2162
+ const n = Math.round(Math.abs(bytes));
2163
+ const trim = (value, decimals) => value.toFixed(decimals).replace(/\.0+$/, "");
2164
+ if (n < 1e3) return `${n} bytes`;
2165
+ if (n < 1e6) return `${Math.floor(n / 1e3)} KB`;
2166
+ if (n < 1e9) return `${trim(n / 1e6, 1)} MB`;
2167
+ return `${trim(n / 1e9, 2)} GB`;
2168
+ }
2169
+ var MIME_NAMES = {
2170
+ "application/pdf": "PDF",
2171
+ "application/msword": "DOC",
2172
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX",
2173
+ "application/json": "JSON",
2174
+ "text/plain": "plain text",
2175
+ "text/markdown": "Markdown",
2176
+ "text/csv": "CSV",
2177
+ "image/png": "PNG",
2178
+ "image/jpeg": "JPEG"
2179
+ };
2180
+ function describeAccept(accept) {
2181
+ const names = accept.map((entry) => {
2182
+ if (entry.startsWith(".")) return entry.slice(1).toUpperCase();
2183
+ if (entry.endsWith("/*")) return `any ${entry.slice(0, -2)}`;
2184
+ return MIME_NAMES[entry] ?? entry.split("/").pop().toUpperCase();
2185
+ });
2186
+ const unique = [...new Set(names)];
2187
+ if (unique.length <= 1) return unique[0] ?? "";
2188
+ return `${unique.slice(0, -1).join(", ")} or ${unique.at(-1)}`;
2189
+ }
2190
+ function rejectionMessage(reason, detail) {
2191
+ switch (reason) {
2192
+ case "type":
2193
+ return `${detail.name} is not an accepted file type. Use ${detail.acceptLabel}.`;
2194
+ case "size":
2195
+ return `${detail.name} is ${formatSize(detail.size ?? 0)}, over the ${formatSize(detail.maxFileSize ?? 0)} limit.`;
2196
+ case "count":
2197
+ return detail.maxFiles === 1 ? "Choose one file." : `Up to ${detail.maxFiles} files. Remove one to add another.`;
2198
+ }
2199
+ }
2200
+ function escapeHtml(text) {
2201
+ return text.replace(
2202
+ /[&<>"']/g,
2203
+ (ch) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[ch]
2204
+ );
2205
+ }
2206
+ var extensionOf = (name) => {
2207
+ const dot = name.lastIndexOf(".");
2208
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
2209
+ };
2210
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set(["txt", "text", "md", "markdown"]);
2211
+ var TEXT_TYPES = /* @__PURE__ */ new Set(["text/plain", "text/markdown", "text/x-markdown"]);
2212
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "webp", "avif", "svg", "bmp"]);
2213
+ var UNDRAWABLE_IMAGE_TYPES = /* @__PURE__ */ new Set(["image/heic", "image/heif", "image/tiff"]);
2214
+ function previewKind(file) {
2215
+ const ext = extensionOf(file.name);
2216
+ const type = file.type.toLowerCase();
2217
+ if (ext === "pdf" || type === "application/pdf") return "pdf";
2218
+ if (TEXT_EXTENSIONS.has(ext) || TEXT_TYPES.has(type)) return "text";
2219
+ if (UNDRAWABLE_IMAGE_TYPES.has(type)) return null;
2220
+ if (IMAGE_EXTENSIONS.has(ext) || type.startsWith("image/")) return "image";
2221
+ return null;
2222
+ }
2223
+ function fileTypeLabel(file) {
2224
+ const ext = extensionOf(file.name);
2225
+ if (ext) return ext.toUpperCase();
2226
+ return MIME_NAMES[file.type.toLowerCase()] ?? (file.type.split("/").pop()?.toUpperCase() || "File");
2227
+ }
2228
+
2229
+ // src/utils/useMediaQuery.ts
2230
+ import { useCallback, useSyncExternalStore } from "react";
2231
+ function useMediaQuery(query) {
2232
+ const subscribe = useCallback(
2233
+ (onChange) => {
2234
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
2235
+ };
2236
+ const list = window.matchMedia(query);
2237
+ list.addEventListener?.("change", onChange);
2238
+ return () => list.removeEventListener?.("change", onChange);
2239
+ },
2240
+ [query]
2241
+ );
2242
+ return useSyncExternalStore(
2243
+ subscribe,
2244
+ () => typeof window.matchMedia === "function" && window.matchMedia(query).matches,
2245
+ () => false
2246
+ );
2247
+ }
2248
+
2249
+ // src/components/FilePreviewDialog/FilePreviewDialog.tsx
2250
+ import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2251
+ var TEXT_LIMIT = 1e6;
2252
+ var NARROW = "(max-width: 48rem)";
2253
+ function FilePreviewDialog({ file, open, onOpenChange, finalFocus }) {
2254
+ const kind = file ? previewKind(file) : null;
2255
+ const narrow = useMediaQuery(NARROW);
2256
+ const pdfInTab = kind === "pdf" && narrow;
2257
+ return /* @__PURE__ */ jsx29(Dialog.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs24(
2258
+ Dialog.Content,
2259
+ {
2260
+ size: "lg",
2261
+ className: "sc-file-preview",
2262
+ "data-kind": kind ?? "none",
2263
+ finalFocus,
2264
+ children: [
2265
+ /* @__PURE__ */ jsx29(Dialog.Close, {}),
2266
+ file ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
2267
+ /* @__PURE__ */ jsx29(Dialog.Title, { children: file.name }),
2268
+ /* @__PURE__ */ jsxs24(Dialog.Description, { children: [
2269
+ fileTypeLabel(file),
2270
+ ", ",
2271
+ formatListSize(file.size)
2272
+ ] }),
2273
+ /* @__PURE__ */ jsx29(Dialog.Body, { children: /* @__PURE__ */ jsx29(PreviewBody, { file, kind, open, pdfInTab }) })
2274
+ ] }) : /* @__PURE__ */ jsx29(Dialog.Title, { children: "Preview" })
2275
+ ]
2276
+ }
2277
+ ) });
2278
+ }
2279
+ function PreviewBody({
2280
+ file,
2281
+ kind,
2282
+ open,
2283
+ pdfInTab
2284
+ }) {
2285
+ const frameRef = useRef3(null);
2286
+ const imageRef = useRef3(null);
2287
+ const linkRef = useRef3(null);
2288
+ const [text, setText] = useState5(null);
2289
+ useEffect3(() => {
2290
+ if (!open || kind !== "pdf" && kind !== "image") return void 0;
2291
+ const url = URL.createObjectURL(kind === "pdf" ? new Blob([file], { type: "application/pdf" }) : file);
2292
+ if (frameRef.current) frameRef.current.src = url;
2293
+ if (imageRef.current) imageRef.current.src = url;
2294
+ if (linkRef.current) linkRef.current.href = url;
2295
+ return () => URL.revokeObjectURL(url);
2296
+ }, [open, file, kind, pdfInTab]);
2297
+ useEffect3(() => {
2298
+ if (!open || kind !== "text") return void 0;
2299
+ let cancelled = false;
2300
+ void file.slice(0, TEXT_LIMIT).text().then((value) => {
2301
+ if (!cancelled) setText({ file, value });
2302
+ });
2303
+ return () => {
2304
+ cancelled = true;
2305
+ };
2306
+ }, [open, file, kind]);
2307
+ if (kind === "pdf") {
2308
+ const link = (
2309
+ // eslint-disable-next-line jsx-a11y/anchor-is-valid -- the effect above sets href to the object URL on mount
2310
+ /* @__PURE__ */ jsxs24(
2311
+ "a",
2312
+ {
2313
+ ref: linkRef,
2314
+ className: "sc-button",
2315
+ "data-variant": pdfInTab ? "primary" : "secondary",
2316
+ "data-size": "md",
2317
+ target: "_blank",
2318
+ rel: "noopener",
2319
+ children: [
2320
+ "Open in a new tab",
2321
+ /* @__PURE__ */ jsx29(ExternalLinkIcon, {})
2322
+ ]
2323
+ }
2324
+ )
2325
+ );
2326
+ return pdfInTab ? /* @__PURE__ */ jsxs24("div", { className: "sc-file-preview__tab", children: [
2327
+ /* @__PURE__ */ jsx29("p", { className: "sc-file-preview__note", children: "On a small screen the PDF reads best in its own tab." }),
2328
+ link
2329
+ ] }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
2330
+ /* @__PURE__ */ jsx29("iframe", { ref: frameRef, className: "sc-file-preview__frame", title: `Preview of ${file.name}` }),
2331
+ /* @__PURE__ */ jsx29("div", { className: "sc-file-preview__actions", children: link })
2332
+ ] });
2333
+ }
2334
+ if (kind === "text") {
2335
+ const value = text?.file === file ? text.value : null;
2336
+ return /* @__PURE__ */ jsxs24(Fragment8, { children: [
2337
+ /* @__PURE__ */ jsx29(
2338
+ "pre",
2339
+ {
2340
+ className: "sc-file-preview__text",
2341
+ role: "region",
2342
+ tabIndex: 0,
2343
+ "aria-label": `Contents of ${file.name}`,
2344
+ "aria-busy": value == null || void 0,
2345
+ children: value
2346
+ }
2347
+ ),
2348
+ file.size > TEXT_LIMIT ? /* @__PURE__ */ jsxs24("p", { className: "sc-file-preview__note", children: [
2349
+ "Showing the first ",
2350
+ formatSize(TEXT_LIMIT),
2351
+ "."
2352
+ ] }) : null
2353
+ ] });
2354
+ }
2355
+ if (kind === "image") {
2356
+ return /* @__PURE__ */ jsx29("img", { ref: imageRef, className: "sc-file-preview__image", alt: file.name });
2357
+ }
2358
+ return /* @__PURE__ */ jsxs24("p", { className: "sc-file-preview__note", children: [
2359
+ "There is no preview for ",
2360
+ fileTypeLabel(file),
2361
+ " files."
2362
+ ] });
2363
+ }
2364
+
2365
+ // src/components/FileInput/FileInput.tsx
2366
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
2367
+ 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>';
2368
+ var sameFiles = (a, b) => a.length === b.length && a.every((file, i) => file === b[i]);
2369
+ function FileInput({
2370
+ label,
2371
+ hideLabel = false,
2372
+ description,
2373
+ error,
2374
+ invalid = false,
2375
+ required = false,
2376
+ disabled = false,
2377
+ name,
2378
+ size = "md",
2379
+ className,
2380
+ accept,
2381
+ acceptLabel,
2382
+ maxFileSize,
2383
+ multiple = false,
2384
+ maxFiles,
2385
+ files,
2386
+ defaultFiles,
2387
+ onFilesChange,
2388
+ idleLabel,
2389
+ browseLabel = "browse",
2390
+ preview = true
2391
+ }) {
2392
+ const id = useId3();
2393
+ const labelId = `${id}label`;
2394
+ const descriptionId = `${id}description`;
2395
+ const messagesId = `${id}messages`;
2396
+ const controlled = files !== void 0;
2397
+ const [uncontrolledFiles, setUncontrolledFiles] = useState6(defaultFiles ?? []);
2398
+ const current = controlled ? files : uncontrolledFiles;
2399
+ const [rejections, setRejections] = useState6([]);
2400
+ const [inputId, setInputId] = useState6();
2401
+ const [previewFile, setPreviewFile] = useState6(null);
2402
+ const [previewOpen, setPreviewOpen] = useState6(false);
2403
+ const previewTriggerRef = useRef4(null);
2404
+ const [pondVersion, setPondVersion] = useState6(0);
2405
+ const hostRef = useRef4(null);
2406
+ const pondRef = useRef4(null);
2407
+ const moduleRef = useRef4(null);
2408
+ const patchRef = useRef4(() => {
2409
+ });
2410
+ const settledRef = useRef4(current);
2411
+ const targetRef = useRef4(null);
2412
+ const acceptList = parseAccept(accept);
2413
+ const acceptAttr = acceptList.join(",");
2414
+ const maxBytes = parseSize(maxFileSize);
2415
+ const messages = [...rejections, ...error != null ? [error] : []];
2416
+ const isInvalid = invalid || messages.length > 0;
2417
+ const idleText = idleLabel ?? (multiple ? "Drop files here or" : current.length > 0 ? "Drop another file to replace it, or" : "Drop a file here or");
2418
+ const live = {
2419
+ acceptList,
2420
+ acceptLabel: acceptLabel ?? describeAccept(acceptList),
2421
+ maxBytes,
2422
+ maxFiles: multiple ? maxFiles : 1,
2423
+ multiple,
2424
+ current,
2425
+ controlled,
2426
+ onFilesChange,
2427
+ labelId,
2428
+ describedBy: [description != null ? descriptionId : null, messages.length > 0 ? messagesId : null],
2429
+ isInvalid,
2430
+ acceptAttr,
2431
+ preview: preview && !disabled,
2432
+ openPreview: (file, trigger) => {
2433
+ previewTriggerRef.current = trigger;
2434
+ setPreviewFile(file);
2435
+ setPreviewOpen(true);
2436
+ }
2437
+ };
2438
+ const liveRef = useRef4(live);
2439
+ useEffect4(() => {
2440
+ liveRef.current = live;
2441
+ });
2442
+ useEffect4(() => {
2443
+ let cancelled = false;
2444
+ let pond = null;
2445
+ let observer = null;
2446
+ const host = hostRef.current;
2447
+ if (!host) return void 0;
2448
+ const reject = (reason, file) => {
2449
+ const l = liveRef.current;
2450
+ const message = rejectionMessage(reason, {
2451
+ name: file?.name,
2452
+ size: file?.size,
2453
+ acceptLabel: l.acceptLabel,
2454
+ maxFileSize: l.maxBytes,
2455
+ maxFiles: l.maxFiles
2456
+ });
2457
+ setRejections((list) => list.includes(message) ? list : [...list, message]);
2458
+ if (file && targetRef.current) {
2459
+ targetRef.current = targetRef.current.filter((f) => f !== file);
2460
+ queueMicrotask(emit);
2461
+ }
2462
+ };
2463
+ const startAttempt = () => setRejections((list) => list.length ? [] : list);
2464
+ let removeIntent = false;
2465
+ const acceptedIds = /* @__PURE__ */ new Set();
2466
+ const noteRemove = (event) => {
2467
+ if (event.target?.closest?.(".filepond--action-remove-item")) removeIntent = true;
2468
+ };
2469
+ const onPreviewClick = (event) => {
2470
+ const button = event.target?.closest?.(
2471
+ ".sc-file-input__preview"
2472
+ );
2473
+ const file = button?.dataset.fileId ? pond?.getFile(button.dataset.fileId)?.file : null;
2474
+ if (!button || !(file instanceof File)) return;
2475
+ event.stopPropagation();
2476
+ liveRef.current.openPreview(file, button);
2477
+ };
2478
+ const emit = () => {
2479
+ const mod = moduleRef.current;
2480
+ if (!pond || !mod) return;
2481
+ const idle = pond.getFiles().filter((item) => item.status === mod.FileStatus.IDLE).map((item) => item.file);
2482
+ const accepted = liveRef.current.multiple ? idle : idle.slice(-1);
2483
+ const target = targetRef.current;
2484
+ if (target) {
2485
+ if (!sameFiles(accepted, target)) return;
2486
+ targetRef.current = null;
2487
+ settledRef.current = accepted;
2488
+ if (!sameFiles(accepted, liveRef.current.current)) {
2489
+ if (!liveRef.current.controlled) setUncontrolledFiles(accepted);
2490
+ liveRef.current.onFilesChange?.(accepted);
2491
+ }
2492
+ return;
2493
+ }
2494
+ if (sameFiles(accepted, settledRef.current)) return;
2495
+ settledRef.current = accepted;
2496
+ if (!liveRef.current.controlled) setUncontrolledFiles(accepted);
2497
+ liveRef.current.onFilesChange?.(accepted);
2498
+ };
2499
+ const patch = () => {
2500
+ if (!pond) return;
2501
+ const l = liveRef.current;
2502
+ const root = pond.element;
2503
+ if (!root) return;
2504
+ const set = (el, attr, value) => {
2505
+ if (!el || el.getAttribute(attr) === value) return;
2506
+ if (value == null) el.removeAttribute(attr);
2507
+ else el.setAttribute(attr, value);
2508
+ };
2509
+ const input = root.querySelector("input.filepond--browser");
2510
+ const dropLabel = root.querySelector(".filepond--drop-label label");
2511
+ set(input, "aria-labelledby", l.labelId);
2512
+ set(input, "aria-describedby", [dropLabel?.id, ...l.describedBy].filter(Boolean).join(" ") || null);
2513
+ set(input, "aria-invalid", l.isInvalid ? "true" : null);
2514
+ set(input, "accept", l.acceptAttr || null);
2515
+ set(input, "multiple", l.multiple ? "" : null);
2516
+ set(root.querySelector(".filepond--label-action"), "tabindex", null);
2517
+ for (const item of root.querySelectorAll(".filepond--item")) {
2518
+ const fileName = item.querySelector(".filepond--file-info-main")?.textContent?.trim();
2519
+ const remove = item.querySelector(".filepond--action-remove-item");
2520
+ if (fileName) set(remove, "aria-label", `Remove ${fileName}`);
2521
+ patchPreview(item, remove);
2522
+ }
2523
+ setInputId(input?.id || void 0);
2524
+ };
2525
+ const patchPreview = (item, remove) => {
2526
+ const row = item.querySelector(".filepond--file");
2527
+ if (!row) return;
2528
+ let button = row.querySelector(":scope > .sc-file-input__preview");
2529
+ const id2 = item.id.replace(/^filepond--item-/, "");
2530
+ const file = pond?.getFile(id2)?.file;
2531
+ if (!liveRef.current.preview || !(file instanceof File) || previewKind(file) == null) {
2532
+ button?.remove();
2533
+ return;
2534
+ }
2535
+ if (!button) {
2536
+ button = document.createElement("button");
2537
+ button.type = "button";
2538
+ button.className = "sc-file-input__preview";
2539
+ row.insertBefore(button, remove ?? row.firstChild);
2540
+ }
2541
+ if (button.dataset.fileId !== id2) button.dataset.fileId = id2;
2542
+ if (button.textContent !== file.name) button.textContent = file.name;
2543
+ const name2 = `Preview ${file.name}`;
2544
+ if (button.getAttribute("aria-label") !== name2) button.setAttribute("aria-label", name2);
2545
+ };
2546
+ void import("filepond").then((mod) => {
2547
+ if (cancelled || !mod.supported()) return;
2548
+ moduleRef.current = mod;
2549
+ const options = {
2550
+ credits: false,
2551
+ allowPaste: false,
2552
+ allowReorder: false,
2553
+ allowProcess: false,
2554
+ allowRevert: false,
2555
+ instantUpload: false,
2556
+ dropOnPage: false,
2557
+ // Always multi: FilePond's own single mode replaces the current file *before* validating the new
2558
+ // one, so a rejected file would discard a good one. Replacement happens in `addfile` instead.
2559
+ allowMultiple: true,
2560
+ allowReplace: false,
2561
+ itemInsertLocation: "after",
2562
+ fileSizeBase: 1e3,
2563
+ iconRemove: REMOVE_ICON,
2564
+ labelButtonRemoveItem: "Remove",
2565
+ styleButtonRemoveItemPosition: "right",
2566
+ beforeAddFile: (item) => {
2567
+ const l = liveRef.current;
2568
+ const file = item.file;
2569
+ if (!matchesAccept(file, l.acceptList)) return reject("type", file), false;
2570
+ if (l.maxBytes != null && file.size > l.maxBytes) return reject("size", file), false;
2571
+ return true;
2572
+ }
2573
+ };
2574
+ pond = mod.create(options);
2575
+ const root = pond.element;
2576
+ if (!root) return;
2577
+ host.appendChild(root);
2578
+ pondRef.current = pond;
2579
+ patchRef.current = patch;
2580
+ pond.on("addfile", (error2, added) => {
2581
+ if (!error2) acceptedIds.add(added.id);
2582
+ if (!error2 && !liveRef.current.multiple) {
2583
+ for (const other of pond?.getFiles() ?? []) if (other.id !== added.id) pond?.removeFile(other.id);
2584
+ }
2585
+ emit();
2586
+ });
2587
+ pond.on("removefile", (_error, removed) => {
2588
+ const active = document.activeElement;
2589
+ const inRemovedRow = active?.closest(".filepond--item")?.id === `filepond--item-${removed.id}`;
2590
+ if (inRemovedRow || removeIntent && (active == null || active === document.body))
2591
+ root.querySelector("input.filepond--browser")?.focus();
2592
+ removeIntent = false;
2593
+ if (acceptedIds.delete(removed.id)) startAttempt();
2594
+ emit();
2595
+ });
2596
+ pond.on("updatefiles", emit);
2597
+ pond.on("warning", (warning) => {
2598
+ if (warning?.body === "Max files") reject("count");
2599
+ });
2600
+ observer = new MutationObserver(patch);
2601
+ observer.observe(root, {
2602
+ subtree: true,
2603
+ childList: true,
2604
+ attributes: true,
2605
+ attributeFilter: ["tabindex", "aria-labelledby", "aria-describedby", "accept", "id", "multiple"]
2606
+ });
2607
+ host.addEventListener("drop", startAttempt, true);
2608
+ host.addEventListener("change", startAttempt, true);
2609
+ host.addEventListener("click", noteRemove, true);
2610
+ host.addEventListener("click", onPreviewClick);
2611
+ settledRef.current = [];
2612
+ setPondVersion((v) => v + 1);
2613
+ });
2614
+ return () => {
2615
+ cancelled = true;
2616
+ host.removeEventListener("drop", startAttempt, true);
2617
+ host.removeEventListener("change", startAttempt, true);
2618
+ host.removeEventListener("click", noteRemove, true);
2619
+ host.removeEventListener("click", onPreviewClick);
2620
+ observer?.disconnect();
2621
+ if (pond) {
2622
+ pond.element?.remove();
2623
+ pond.destroy();
2624
+ }
2625
+ pondRef.current = null;
2626
+ patchRef.current = () => {
2627
+ };
2628
+ };
2629
+ }, []);
2630
+ useEffect4(() => {
2631
+ const pond = pondRef.current;
2632
+ if (!pond) return;
2633
+ pond.setOptions({
2634
+ name: name ?? "",
2635
+ storeAsFile: name != null,
2636
+ disabled,
2637
+ required,
2638
+ maxFiles: multiple ? maxFiles ?? null : null,
2639
+ allowRemove: !disabled,
2640
+ labelIdle: `${escapeHtml(idleText)} <span class="filepond--label-action">${escapeHtml(browseLabel)}</span>`
2641
+ });
2642
+ patchRef.current();
2643
+ }, [
2644
+ pondVersion,
2645
+ name,
2646
+ disabled,
2647
+ required,
2648
+ multiple,
2649
+ maxFiles,
2650
+ idleText,
2651
+ browseLabel,
2652
+ labelId,
2653
+ acceptAttr,
2654
+ isInvalid,
2655
+ description,
2656
+ messages.length,
2657
+ preview
2658
+ ]);
2659
+ useEffect4(() => {
2660
+ const pond = pondRef.current;
2661
+ const mod = moduleRef.current;
2662
+ if (!pond || !mod) return;
2663
+ const items = pond.getFiles();
2664
+ const idle = items.filter((item) => item.status === mod.FileStatus.IDLE);
2665
+ const inPond = idle.map((item) => item.file);
2666
+ if (sameFiles(inPond, current)) {
2667
+ settledRef.current = current;
2668
+ return;
2669
+ }
2670
+ targetRef.current = current;
2671
+ for (const item of idle) if (!current.includes(item.file)) pond.removeFile(item.id);
2672
+ const toAdd = current.filter((file) => !inPond.includes(file));
2673
+ if (toAdd.length > 0) void pond.addFiles(toAdd);
2674
+ }, [current, pondVersion]);
2675
+ const ready = pondVersion > 0;
2676
+ return /* @__PURE__ */ jsxs25(
2677
+ "div",
2678
+ {
2679
+ className: cx("sc-field", "sc-file-input-field", className),
2680
+ "data-size": size,
2681
+ "data-disabled": disabled ? "" : void 0,
2682
+ "data-invalid": isInvalid ? "" : void 0,
2683
+ children: [
2684
+ /* @__PURE__ */ jsxs25(
2685
+ "label",
2686
+ {
2687
+ id: labelId,
2688
+ htmlFor: inputId,
2689
+ className: cx("sc-field__label", hideLabel && "sc-visually-hidden"),
2690
+ children: [
2691
+ label,
2692
+ required ? /* @__PURE__ */ jsx30("span", { className: "sc-field__required", "aria-hidden": "true", children: "*" }) : null
2693
+ ]
2694
+ }
2695
+ ),
2696
+ /* @__PURE__ */ jsxs25(
2697
+ "div",
2698
+ {
2699
+ className: "sc-file-input",
2700
+ "data-ready": ready ? "" : void 0,
2701
+ "data-disabled": disabled ? "" : void 0,
2702
+ "data-invalid": isInvalid ? "" : void 0,
2703
+ "data-multiple": multiple ? "" : void 0,
2704
+ children: [
2705
+ ready ? null : (
2706
+ // Server render and first paint: the same drop zone, inert until FilePond takes over.
2707
+ /* @__PURE__ */ jsxs25("div", { className: "sc-file-input__placeholder", "aria-hidden": "true", children: [
2708
+ idleText,
2709
+ " ",
2710
+ /* @__PURE__ */ jsx30("span", { className: "sc-file-input__browse", children: browseLabel })
2711
+ ] })
2712
+ ),
2713
+ /* @__PURE__ */ jsx30("div", { ref: hostRef, className: "sc-file-input__pond" })
2714
+ ]
2715
+ }
2716
+ ),
2717
+ description != null ? /* @__PURE__ */ jsx30("p", { id: descriptionId, className: "sc-field__description", children: description }) : null,
2718
+ /* @__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)) }),
2719
+ previewFile ? /* @__PURE__ */ jsx30(
2720
+ FilePreviewDialog,
2721
+ {
2722
+ file: previewFile,
2723
+ open: previewOpen,
2724
+ onOpenChange: setPreviewOpen,
2725
+ finalFocus: () => {
2726
+ const trigger = previewTriggerRef.current;
2727
+ if (trigger?.isConnected) return trigger;
2728
+ return hostRef.current?.querySelector("input.filepond--browser") ?? true;
2729
+ }
2730
+ }
2731
+ ) : null
2732
+ ]
2733
+ }
2734
+ );
2735
+ }
2736
+
2737
+ // src/components/PriorityNav/PriorityNav.tsx
2738
+ import {
2739
+ useEffect as useEffect5,
2740
+ useId as useId4,
2741
+ useLayoutEffect as useLayoutEffect2,
2742
+ useRef as useRef5,
2743
+ useState as useState7
2744
+ } from "react";
2745
+
2746
+ // src/components/PriorityNav/fit.ts
2747
+ var EPSILON = 0.5;
2748
+ function rowWidth(widths, gap) {
2749
+ let total = 0;
2750
+ for (const w of widths) total += w;
2751
+ return widths.length > 1 ? total + gap * (widths.length - 1) : total;
2752
+ }
2753
+ function fitCount({ widths, current, available, more, gap }) {
2754
+ const n = widths.length;
2755
+ const hasCurrent = current >= 0 && current < n;
2756
+ const others = hasCurrent ? n - 1 : n;
2757
+ if (rowWidth(widths, gap) <= available + EPSILON) return others;
2758
+ let used = more + (hasCurrent ? widths[current] + gap : 0);
2759
+ let count = 0;
2760
+ for (let i = 0; i < n; i++) {
2761
+ if (i === current) continue;
2762
+ const next = used + widths[i] + gap;
2763
+ if (next > available + EPSILON) break;
2764
+ used = next;
2765
+ count++;
2766
+ }
2767
+ return count;
2768
+ }
2769
+ function inlineFlags(length, current, count) {
2770
+ const flags = [];
2771
+ let seen = 0;
2772
+ for (let i = 0; i < length; i++) {
2773
+ if (i === current) flags.push(true);
2774
+ else flags.push(seen++ < count);
2775
+ }
2776
+ return flags;
2777
+ }
2778
+ function isOverflowing({ widths, gap, available, was, hysteresis }) {
2779
+ const total = rowWidth(widths, gap);
2780
+ return was ? total + Math.max(0, hysteresis) > available + EPSILON : total > available + EPSILON;
2781
+ }
2782
+
2783
+ // src/components/PriorityNav/place.ts
2784
+ var clamp = (value, min, max) => Math.max(min, Math.min(value, max));
2785
+ function placePanel({ anchor, panel, viewport, gutter, offset, rtl = false }) {
2786
+ const endAligned = rtl ? anchor.left : anchor.right - panel.width;
2787
+ const startAligned = rtl ? anchor.right - panel.width : anchor.left;
2788
+ const fitsX = (x2) => x2 >= gutter && x2 + panel.width <= viewport.width - gutter;
2789
+ const x = fitsX(endAligned) ? endAligned : fitsX(startAligned) ? startAligned : endAligned;
2790
+ const left = clamp(x, gutter, Math.max(gutter, viewport.width - gutter - panel.width));
2791
+ const below = anchor.bottom + offset;
2792
+ const above = anchor.top - offset - panel.height;
2793
+ const fitsBelow = below + panel.height <= viewport.height - gutter;
2794
+ const top = fitsBelow || above < gutter ? below : above;
2795
+ return { left, top };
2796
+ }
2797
+
2798
+ // src/components/PriorityNav/PriorityNav.tsx
2799
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
2800
+ var defaultCountLabel2 = (n) => n === 1 ? "1 link" : `${n} links`;
2801
+ var defaultLink = ({ children, ...props }) => /* @__PURE__ */ jsx31("a", { ...props, children });
2802
+ var keyOf = (item) => item.id ?? item.href;
2803
+ var supportsAnchor = () => typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("anchor-name: --a");
2804
+ var supportsPopover = (el) => typeof el.showPopover === "function";
2805
+ function signatureOf(items) {
2806
+ return items.map((item) => {
2807
+ const text = typeof item.label === "string" || typeof item.label === "number" ? item.label : "";
2808
+ return `${keyOf(item)}${text}`;
2809
+ }).join("");
2810
+ }
2811
+ function PriorityNav({
2812
+ items,
2813
+ moreLabel = "More",
2814
+ moreCountLabel = defaultCountLabel2,
2815
+ renderLink = defaultLink,
2816
+ onOverflowChange,
2817
+ overflowHysteresis = 0,
2818
+ className,
2819
+ style,
2820
+ ...rest
2821
+ }) {
2822
+ const signature = signatureOf(items);
2823
+ const current = items.findIndex((item) => item.current);
2824
+ const [fit, setFit] = useState7({ signature: null, current: -1, count: 0, overflowing: false });
2825
+ const [open, setOpen] = useState7(false);
2826
+ const panelId = useId4();
2827
+ const listRef = useRef5(null);
2828
+ const moreRef = useRef5(null);
2829
+ const toggleRef = useRef5(null);
2830
+ const panelRef = useRef5(null);
2831
+ const measured = useRef5(null);
2832
+ const currentRef = useRef5(current);
2833
+ const fitRef = useRef5(fit);
2834
+ const hysteresisRef = useRef5(overflowHysteresis);
2835
+ const onOverflowRef = useRef5(onOverflowChange);
2836
+ const solve = (m, cur, was) => ({
2837
+ count: fitCount({ ...m, current: cur }),
2838
+ overflowing: isOverflowing({ ...m, was, hysteresis: hysteresisRef.current })
2839
+ });
2840
+ const measuring = fit.signature !== signature;
2841
+ useLayoutEffect2(() => {
2842
+ currentRef.current = current;
2843
+ fitRef.current = fit;
2844
+ hysteresisRef.current = overflowHysteresis;
2845
+ onOverflowRef.current = onOverflowChange;
2846
+ });
2847
+ useLayoutEffect2(() => {
2848
+ const list = listRef.current;
2849
+ const more = moreRef.current;
2850
+ if (!list || !more) return;
2851
+ if (measuring) {
2852
+ const widths = Array.from(
2853
+ list.querySelectorAll(":scope > .sc-priority-nav__item"),
2854
+ (el) => el.getBoundingClientRect().width
2855
+ );
2856
+ measured.current = {
2857
+ widths,
2858
+ more: more.getBoundingClientRect().width,
2859
+ gap: parseFloat(getComputedStyle(list).columnGap) || 0,
2860
+ available: list.clientWidth
2861
+ };
2862
+ } else if (fit.current === current) return;
2863
+ const m = measured.current;
2864
+ if (!m) return;
2865
+ setFit({ signature, current, ...solve(m, current, fit.overflowing) });
2866
+ }, [measuring, signature, current, fit]);
2867
+ useEffect5(() => {
2868
+ const list = listRef.current;
2869
+ const more = moreRef.current;
2870
+ if (!list || !more || typeof ResizeObserver === "undefined") return;
2871
+ const observer = new ResizeObserver((entries) => {
2872
+ const m = measured.current;
2873
+ if (!m) return;
2874
+ for (const entry of entries) {
2875
+ if (entry.target === list)
2876
+ m.available = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
2877
+ else {
2878
+ const width = entry.borderBoxSize?.[0]?.inlineSize ?? 0;
2879
+ if (width > 0) m.more = width;
2880
+ }
2881
+ }
2882
+ const prev = fitRef.current;
2883
+ if (prev.signature === null) return;
2884
+ const next = solve(m, currentRef.current, prev.overflowing);
2885
+ if (prev.count !== next.count || prev.overflowing !== next.overflowing) setFit({ ...prev, ...next });
2886
+ });
2887
+ observer.observe(list);
2888
+ observer.observe(more);
2889
+ return () => observer.disconnect();
2890
+ }, []);
2891
+ const reported = useRef5(false);
2892
+ useEffect5(() => {
2893
+ if (reported.current === fit.overflowing) return;
2894
+ reported.current = fit.overflowing;
2895
+ onOverflowRef.current?.(fit.overflowing);
2896
+ }, [fit.overflowing]);
2897
+ useEffect5(() => {
2898
+ const fonts = typeof document === "undefined" ? void 0 : document.fonts;
2899
+ if (!fonts || fonts.status === "loaded") return;
2900
+ let live = true;
2901
+ void fonts.ready.then(() => {
2902
+ if (live) setFit((prev) => ({ ...prev, signature: null }));
2903
+ });
2904
+ return () => {
2905
+ live = false;
2906
+ };
2907
+ }, []);
2908
+ const flags = measuring ? null : inlineFlags(items.length, current, fit.count);
2909
+ const overflow = flags ? items.filter((_, i) => !flags[i]) : [];
2910
+ const expanded = open && overflow.length > 0;
2911
+ useLayoutEffect2(() => {
2912
+ const panel = panelRef.current;
2913
+ if (!panel || !supportsPopover(panel)) return;
2914
+ if (!panel.hasAttribute("popover")) panel.setAttribute("popover", "manual");
2915
+ const shown = panel.matches(":popover-open");
2916
+ if (expanded && !shown) panel.showPopover();
2917
+ else if (!expanded && shown) panel.hidePopover();
2918
+ }, [expanded]);
2919
+ useLayoutEffect2(() => {
2920
+ const panel = panelRef.current;
2921
+ const toggle2 = toggleRef.current;
2922
+ if (!expanded || !panel || !toggle2 || supportsAnchor()) return;
2923
+ const place = () => {
2924
+ const anchor = toggle2.getBoundingClientRect();
2925
+ const box = panel.getBoundingClientRect();
2926
+ const css = getComputedStyle(panel);
2927
+ const { left, top } = placePanel({
2928
+ anchor,
2929
+ panel: { width: box.width, height: box.height },
2930
+ viewport: { width: document.documentElement.clientWidth, height: window.innerHeight },
2931
+ gutter: parseFloat(css.getPropertyValue("--sc-spacing-md")) || 16,
2932
+ offset: parseFloat(css.getPropertyValue("--sc-spacing-2xs")) || 4,
2933
+ rtl: css.direction === "rtl"
2934
+ });
2935
+ panel.style.left = `${left}px`;
2936
+ panel.style.top = `${top}px`;
2937
+ };
2938
+ place();
2939
+ window.addEventListener("resize", place, { passive: true });
2940
+ window.addEventListener("scroll", place, { passive: true, capture: true });
2941
+ return () => {
2942
+ window.removeEventListener("resize", place);
2943
+ window.removeEventListener("scroll", place, { capture: true });
2944
+ panel.style.left = "";
2945
+ panel.style.top = "";
2946
+ };
2947
+ }, [expanded]);
2948
+ useEffect5(() => {
2949
+ if (!expanded) return;
2950
+ const onPointerDown = (event) => {
2951
+ if (!moreRef.current?.contains(event.target)) setOpen(false);
2952
+ };
2953
+ const onKeyDown = (event) => {
2954
+ if (event.key !== "Escape") return;
2955
+ const active = document.activeElement;
2956
+ setOpen(false);
2957
+ if (!active || active === document.body || moreRef.current?.contains(active))
2958
+ toggleRef.current?.focus();
2959
+ };
2960
+ document.addEventListener("pointerdown", onPointerDown);
2961
+ document.addEventListener("keydown", onKeyDown);
2962
+ return () => {
2963
+ document.removeEventListener("pointerdown", onPointerDown);
2964
+ document.removeEventListener("keydown", onKeyDown);
2965
+ };
2966
+ }, [expanded]);
2967
+ const onBlur = (event) => {
2968
+ if (!event.currentTarget.contains(event.relatedTarget)) setOpen(false);
2969
+ };
2970
+ const link = (item, inPanel) => renderLink(
2971
+ {
2972
+ href: item.href,
2973
+ className: "sc-priority-nav__link",
2974
+ "aria-current": item.current ? "page" : void 0,
2975
+ onClick: inPanel ? () => setOpen(false) : void 0,
2976
+ children: /* @__PURE__ */ jsx31("span", { className: "sc-priority-nav__label", children: item.label })
2977
+ },
2978
+ item
2979
+ );
2980
+ return /* @__PURE__ */ jsx31(
2981
+ "nav",
2982
+ {
2983
+ className: cx("sc-priority-nav", className),
2984
+ "data-measuring": measuring || void 0,
2985
+ "data-overflowing": fit.overflowing || void 0,
2986
+ style: { ...style, "--_anchor": `--sc-priority-nav${panelId.replace(/[^\w-]/g, "")}` },
2987
+ ...rest,
2988
+ children: /* @__PURE__ */ jsxs26("ul", { ref: listRef, className: "sc-priority-nav__list", children: [
2989
+ items.map(
2990
+ (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))
2991
+ ),
2992
+ /* @__PURE__ */ jsxs26(
2993
+ "li",
2994
+ {
2995
+ ref: moreRef,
2996
+ className: "sc-priority-nav__more",
2997
+ hidden: measuring || overflow.length === 0,
2998
+ onBlur,
2999
+ children: [
3000
+ /* @__PURE__ */ jsxs26(
3001
+ "button",
3002
+ {
3003
+ ref: toggleRef,
3004
+ type: "button",
3005
+ className: "sc-priority-nav__toggle",
3006
+ "aria-expanded": expanded,
3007
+ "aria-controls": panelId,
3008
+ onClick: () => setOpen((o) => !o),
3009
+ children: [
3010
+ /* @__PURE__ */ jsx31(MoreHorizontalIcon, { className: "sc-priority-nav__ellipsis" }),
3011
+ /* @__PURE__ */ jsx31("span", { className: "sc-priority-nav__toggle-label", children: moreLabel }),
3012
+ /* @__PURE__ */ jsxs26("span", { className: "sc-visually-hidden", children: [
3013
+ ", ",
3014
+ moreCountLabel(overflow.length)
3015
+ ] }),
3016
+ /* @__PURE__ */ jsx31(ChevronDownIcon, { size: "sm", className: "sc-priority-nav__chevron" })
3017
+ ]
3018
+ }
3019
+ ),
3020
+ /* @__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))) })
3021
+ ]
3022
+ }
3023
+ )
3024
+ ] })
3025
+ }
3026
+ );
3027
+ }
3028
+
3029
+ // src/components/Popover/Popover.tsx
3030
+ import { Popover as BasePopover } from "@base-ui/react/popover";
3031
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
3032
+ function Root6({ open, defaultOpen, onOpenChange, modal = false, children }) {
3033
+ return /* @__PURE__ */ jsx32(
3034
+ BasePopover.Root,
3035
+ {
3036
+ open,
3037
+ defaultOpen,
3038
+ onOpenChange: onOpenChange ? (next) => onOpenChange(next) : void 0,
3039
+ modal,
3040
+ children
3041
+ }
3042
+ );
3043
+ }
3044
+ function Trigger3({ render, className, children, ...rest }) {
3045
+ return /* @__PURE__ */ jsx32(
3046
+ BasePopover.Trigger,
3047
+ {
3048
+ render: render ?? /* @__PURE__ */ jsx32(Button, { variant: "secondary", className }),
3049
+ className: render ? className : void 0,
3050
+ ...rest,
3051
+ children
3052
+ }
3053
+ );
3054
+ }
3055
+ function Content3({
3056
+ side = "bottom",
3057
+ align = "center",
3058
+ sideOffset,
3059
+ arrow = false,
3060
+ className,
3061
+ children,
3062
+ ...rest
3063
+ }) {
3064
+ return /* @__PURE__ */ jsx32(BasePopover.Portal, { children: /* @__PURE__ */ jsx32(
3065
+ BasePopover.Positioner,
3066
+ {
3067
+ side,
3068
+ align,
3069
+ sideOffset: sideOffset ?? (arrow ? 8 : 4),
3070
+ className: "sc-popover__positioner",
3071
+ children: /* @__PURE__ */ jsxs27(BasePopover.Popup, { className: cx("sc-popover", className), ...rest, children: [
3072
+ arrow ? /* @__PURE__ */ jsx32(BasePopover.Arrow, { className: "sc-popover__arrow" }) : null,
3073
+ children
3074
+ ] })
3075
+ }
3076
+ ) });
3077
+ }
3078
+ function Title2({ className, ...rest }) {
3079
+ return /* @__PURE__ */ jsx32(BasePopover.Title, { className: cx("sc-popover__title", className), ...rest });
3080
+ }
3081
+ function Description2({ className, ...rest }) {
3082
+ return /* @__PURE__ */ jsx32(BasePopover.Description, { className: cx("sc-popover__description", className), ...rest });
3083
+ }
3084
+ function Close2({ className, children, render, ...rest }) {
3085
+ if (children === void 0 && render === void 0) {
3086
+ return /* @__PURE__ */ jsx32(BasePopover.Close, { className: cx("sc-popover__close", className), "aria-label": "Close", ...rest, children: /* @__PURE__ */ jsx32(XIcon, {}) });
3087
+ }
3088
+ return /* @__PURE__ */ jsx32(BasePopover.Close, { className, render, ...rest, children });
3089
+ }
3090
+ var Popover = { Root: Root6, Trigger: Trigger3, Content: Content3, Title: Title2, Description: Description2, Close: Close2 };
3091
+
3092
+ // src/components/BroomIcon/BroomIcon.tsx
3093
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
3094
+ function BroomIcon({ sweeping = false, size = "lg", title, className, ...rest }) {
3095
+ return /* @__PURE__ */ jsxs28(
3096
+ "svg",
3097
+ {
3098
+ className: cx("sc-icon", "sc-broom", className),
3099
+ "data-size": size,
3100
+ "data-sweeping": sweeping || void 0,
3101
+ viewBox: "0 0 24 24",
3102
+ fill: "none",
3103
+ focusable: "false",
3104
+ "aria-hidden": title ? void 0 : true,
3105
+ role: title ? "img" : void 0,
3106
+ "aria-label": title,
3107
+ ...rest,
3108
+ children: [
3109
+ /* @__PURE__ */ jsxs28(
3110
+ "g",
3111
+ {
3112
+ className: "sc-broom__body",
3113
+ fill: "none",
3114
+ stroke: "currentColor",
3115
+ strokeLinecap: "round",
3116
+ strokeLinejoin: "round",
3117
+ children: [
3118
+ /* @__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" }),
3119
+ /* @__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" }),
3120
+ /* @__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" }),
3121
+ /* @__PURE__ */ jsx33("path", { d: "M12.87 13.73 L14.4 14.47 M16.2 15.27 L18.47 15.87" }),
3122
+ /* @__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" })
3123
+ ]
3124
+ }
3125
+ ),
3126
+ /* @__PURE__ */ jsxs28("g", { className: "sc-broom__dust", fill: "none", stroke: "currentColor", children: [
3127
+ /* @__PURE__ */ jsx33("circle", { cx: "4.77", cy: "13.53", r: "0.5" }),
3128
+ /* @__PURE__ */ jsx33("circle", { cx: "2.7", cy: "15.53", r: "0.87" }),
3129
+ /* @__PURE__ */ jsx33("circle", { cx: "4.1", cy: "18.27", r: "0.5" })
3130
+ ] })
3131
+ ]
3132
+ }
3133
+ );
3134
+ }
3135
+
1296
3136
  // src/index.ts
1297
3137
  var version = "0.1.1";
1298
3138
  export {
1299
3139
  ArchiveIcon,
3140
+ ArrowDownIcon,
1300
3141
  ArrowLeftIcon,
1301
3142
  ArrowRightIcon,
3143
+ ArrowUpIcon,
1302
3144
  Badge,
1303
3145
  Banner,
1304
3146
  BellIcon,
1305
3147
  BriefcaseIcon,
3148
+ BroomIcon,
1306
3149
  Button,
1307
3150
  CalendarIcon,
1308
3151
  Card,
@@ -1312,16 +3155,21 @@ export {
1312
3155
  ChevronLeftIcon,
1313
3156
  ChevronRightIcon,
1314
3157
  ChevronUpIcon,
3158
+ Chip,
1315
3159
  CircleCheckIcon,
1316
3160
  CircleXIcon,
1317
3161
  ClockIcon,
1318
3162
  CopyIcon,
1319
3163
  Dialog,
3164
+ Disclosure,
1320
3165
  DocumentIcon,
1321
3166
  DownloadIcon,
1322
3167
  EditIcon,
3168
+ EmptyState,
1323
3169
  ExternalLinkIcon,
1324
3170
  EyeIcon,
3171
+ FileInput,
3172
+ FilePreviewDialog,
1325
3173
  FilterIcon,
1326
3174
  FlagIcon,
1327
3175
  Heading,
@@ -1344,21 +3192,28 @@ export {
1344
3192
  PauseIcon,
1345
3193
  PlayIcon,
1346
3194
  PlusIcon,
3195
+ Popover,
3196
+ PriorityNav,
1347
3197
  Progress,
1348
3198
  RefreshIcon,
1349
3199
  SearchIcon,
1350
3200
  Select,
3201
+ SelectionBar,
1351
3202
  SettingsIcon,
3203
+ Skeleton,
1352
3204
  Spinner,
1353
3205
  Stack,
1354
3206
  StarIcon,
3207
+ Stat,
1355
3208
  SunIcon,
1356
3209
  Switch,
3210
+ Table,
1357
3211
  Tabs,
1358
3212
  Text,
1359
3213
  Textarea,
1360
3214
  ThumbsDownIcon,
1361
3215
  ThumbsUpIcon,
3216
+ Toast,
1362
3217
  Toolbar,
1363
3218
  Tooltip,
1364
3219
  TrashIcon,
@@ -1367,6 +3222,8 @@ export {
1367
3222
  WarningIcon,
1368
3223
  XIcon,
1369
3224
  iconNames,
3225
+ useRowSelection,
3226
+ useToast,
1370
3227
  version
1371
3228
  };
1372
3229
  //# sourceMappingURL=index.js.map