@salemcobalt/ui 0.2.0-rc.0 → 0.2.0-rc.10

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
@@ -737,40 +760,2198 @@ var Menu = {
737
760
  Separator
738
761
  };
739
762
 
763
+ // src/components/Input/Input.tsx
764
+ import { Field as Field2 } from "@base-ui/react/field";
765
+
766
+ // src/components/Field/FieldShell.tsx
767
+ import { Field } from "@base-ui/react/field";
768
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
769
+ function FieldShell({
770
+ label,
771
+ hideLabel = false,
772
+ description,
773
+ error,
774
+ invalid = false,
775
+ required = false,
776
+ disabled = false,
777
+ name,
778
+ size = "md",
779
+ className,
780
+ children
781
+ }) {
782
+ return /* @__PURE__ */ jsxs9(
783
+ Field.Root,
784
+ {
785
+ className: cx("sc-field", className),
786
+ name,
787
+ disabled,
788
+ invalid: invalid || error != null,
789
+ "data-size": size,
790
+ children: [
791
+ /* @__PURE__ */ jsxs9(Field.Label, { className: cx("sc-field__label", hideLabel && "sc-visually-hidden"), children: [
792
+ label,
793
+ required ? /* @__PURE__ */ jsx10("span", { className: "sc-field__required", "aria-hidden": "true", children: "*" }) : null
794
+ ] }),
795
+ children,
796
+ description != null ? /* @__PURE__ */ jsx10(Field.Description, { className: "sc-field__description", children: description }) : null,
797
+ error != null ? /* @__PURE__ */ jsx10(Field.Error, { className: "sc-field__error", match: true, children: error }) : null
798
+ ]
799
+ }
800
+ );
801
+ }
802
+
803
+ // src/components/Input/Input.tsx
804
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
805
+ function Input({
806
+ label,
807
+ hideLabel,
808
+ description,
809
+ error,
810
+ invalid,
811
+ required,
812
+ disabled,
813
+ name,
814
+ size,
815
+ className,
816
+ iconStart,
817
+ iconEnd,
818
+ onValueChange,
819
+ ...rest
820
+ }) {
821
+ return /* @__PURE__ */ jsx11(
822
+ FieldShell,
823
+ {
824
+ label,
825
+ hideLabel,
826
+ description,
827
+ error,
828
+ invalid,
829
+ required,
830
+ disabled,
831
+ name,
832
+ size,
833
+ className,
834
+ children: /* @__PURE__ */ jsxs10(
835
+ "span",
836
+ {
837
+ className: "sc-input-wrap",
838
+ "data-icon-start": iconStart ? "" : void 0,
839
+ "data-icon-end": iconEnd ? "" : void 0,
840
+ children: [
841
+ iconStart ? /* @__PURE__ */ jsx11("span", { className: "sc-input__icon", "data-side": "start", "aria-hidden": "true", children: iconStart }) : null,
842
+ /* @__PURE__ */ jsx11(
843
+ Field2.Control,
844
+ {
845
+ className: "sc-input",
846
+ required,
847
+ onValueChange: onValueChange ? (value) => onValueChange(value) : void 0,
848
+ ...rest
849
+ }
850
+ ),
851
+ iconEnd ? /* @__PURE__ */ jsx11("span", { className: "sc-input__icon", "data-side": "end", "aria-hidden": "true", children: iconEnd }) : null
852
+ ]
853
+ }
854
+ )
855
+ }
856
+ );
857
+ }
858
+
859
+ // src/components/Textarea/Textarea.tsx
860
+ import { Field as Field3 } from "@base-ui/react/field";
861
+ import { jsx as jsx12 } from "react/jsx-runtime";
862
+ function Textarea({
863
+ label,
864
+ hideLabel,
865
+ description,
866
+ error,
867
+ invalid,
868
+ required,
869
+ disabled,
870
+ name,
871
+ className,
872
+ rows = 3,
873
+ resize = "vertical",
874
+ variant = "default",
875
+ onValueChange,
876
+ spellCheck,
877
+ autoCorrect,
878
+ autoCapitalize,
879
+ ...rest
880
+ }) {
881
+ const code = variant === "code";
882
+ return /* @__PURE__ */ jsx12(
883
+ FieldShell,
884
+ {
885
+ label,
886
+ hideLabel,
887
+ description,
888
+ error,
889
+ invalid,
890
+ required,
891
+ disabled,
892
+ name,
893
+ className,
894
+ children: /* @__PURE__ */ jsx12(
895
+ Field3.Control,
896
+ {
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
+ ),
907
+ className: "sc-input sc-textarea",
908
+ "data-resize": resize,
909
+ "data-variant": code ? "code" : void 0,
910
+ required,
911
+ onValueChange: onValueChange ? (value) => onValueChange(value) : void 0
912
+ }
913
+ )
914
+ }
915
+ );
916
+ }
917
+
918
+ // src/components/Select/Select.tsx
919
+ import { Select as BaseSelect } from "@base-ui/react/select";
920
+ import { useState } from "react";
921
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
922
+ function isGroup(entry) {
923
+ return "options" in entry;
924
+ }
925
+ function Option({ option }) {
926
+ return /* @__PURE__ */ jsxs11(BaseSelect.Item, { value: option.value, disabled: option.disabled, className: "sc-select__item", children: [
927
+ /* @__PURE__ */ jsx13(BaseSelect.ItemIndicator, { className: "sc-select__indicator", children: /* @__PURE__ */ jsx13(CheckIcon, { size: "sm" }) }),
928
+ /* @__PURE__ */ jsx13(BaseSelect.ItemText, { className: "sc-select__item-text", children: option.label })
929
+ ] });
930
+ }
931
+ function Select({
932
+ label,
933
+ hideLabel,
934
+ description,
935
+ error,
936
+ invalid,
937
+ required,
938
+ disabled,
939
+ name,
940
+ size = "md",
941
+ className,
942
+ options,
943
+ value,
944
+ defaultValue,
945
+ onValueChange,
946
+ placeholder = "Choose\u2026",
947
+ clearable = false,
948
+ clearLabel = "Clear",
949
+ readOnly,
950
+ fullWidth = false,
951
+ id
952
+ }) {
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
+ };
968
+ return /* @__PURE__ */ jsx13(
969
+ FieldShell,
970
+ {
971
+ label,
972
+ hideLabel,
973
+ description,
974
+ error,
975
+ invalid,
976
+ required,
977
+ disabled,
978
+ name,
979
+ size,
980
+ className,
981
+ children: /* @__PURE__ */ jsxs11(
982
+ BaseSelect.Root,
983
+ {
984
+ items,
985
+ value: current,
986
+ onValueChange: (next) => setValue(next),
987
+ disabled,
988
+ required,
989
+ readOnly,
990
+ children: [
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
+ ] }),
1018
+ /* @__PURE__ */ jsx13(BaseSelect.Portal, { children: /* @__PURE__ */ jsx13(
1019
+ BaseSelect.Positioner,
1020
+ {
1021
+ className: "sc-select__positioner",
1022
+ sideOffset: 4,
1023
+ alignItemWithTrigger: false,
1024
+ children: /* @__PURE__ */ jsx13(BaseSelect.Popup, { className: "sc-select__popup", children: /* @__PURE__ */ jsx13(BaseSelect.List, { children: options.map(
1025
+ (entry, i) => isGroup(entry) ? /* @__PURE__ */ jsxs11(BaseSelect.Group, { className: "sc-select__group", children: [
1026
+ /* @__PURE__ */ jsx13(BaseSelect.GroupLabel, { className: "sc-select__group-label", children: entry.label }),
1027
+ entry.options.map((option) => /* @__PURE__ */ jsx13(Option, { option }, option.value))
1028
+ ] }, i) : /* @__PURE__ */ jsx13(Option, { option: entry }, entry.value)
1029
+ ) }) })
1030
+ }
1031
+ ) })
1032
+ ]
1033
+ }
1034
+ )
1035
+ }
1036
+ );
1037
+ }
1038
+
1039
+ // src/components/Checkbox/Checkbox.tsx
1040
+ import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
1041
+ import { useId } from "react";
1042
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1043
+ function Checkbox({
1044
+ label,
1045
+ description,
1046
+ onCheckedChange,
1047
+ className,
1048
+ disabled,
1049
+ ...rest
1050
+ }) {
1051
+ const descriptionId = useId();
1052
+ return /* @__PURE__ */ jsxs12("div", { className: cx("sc-choice", className), "data-disabled": disabled || void 0, children: [
1053
+ /* @__PURE__ */ jsxs12("label", { className: "sc-choice__control", children: [
1054
+ /* @__PURE__ */ jsx14(
1055
+ BaseCheckbox.Root,
1056
+ {
1057
+ className: "sc-checkbox",
1058
+ disabled,
1059
+ "aria-describedby": description != null ? descriptionId : void 0,
1060
+ onCheckedChange: onCheckedChange ? (checked) => onCheckedChange(checked) : void 0,
1061
+ ...rest,
1062
+ children: /* @__PURE__ */ jsxs12(BaseCheckbox.Indicator, { className: "sc-checkbox__indicator", children: [
1063
+ /* @__PURE__ */ jsx14(CheckIcon, { size: "sm", className: "sc-checkbox__check" }),
1064
+ /* @__PURE__ */ jsx14(MinusIcon, { size: "sm", className: "sc-checkbox__dash" })
1065
+ ] })
1066
+ }
1067
+ ),
1068
+ /* @__PURE__ */ jsx14("span", { className: "sc-choice__label", children: label })
1069
+ ] }),
1070
+ description != null ? /* @__PURE__ */ jsx14("span", { className: "sc-choice__description", id: descriptionId, children: description }) : null
1071
+ ] });
1072
+ }
1073
+
1074
+ // src/components/Switch/Switch.tsx
1075
+ import { Switch as BaseSwitch } from "@base-ui/react/switch";
1076
+ import { useId as useId2 } from "react";
1077
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1078
+ function Switch({
1079
+ label,
1080
+ description,
1081
+ onCheckedChange,
1082
+ labelPosition = "end",
1083
+ className,
1084
+ disabled,
1085
+ ...rest
1086
+ }) {
1087
+ const descriptionId = useId2();
1088
+ return /* @__PURE__ */ jsxs13(
1089
+ "div",
1090
+ {
1091
+ className: cx("sc-choice", className),
1092
+ "data-disabled": disabled || void 0,
1093
+ "data-label-position": labelPosition,
1094
+ children: [
1095
+ /* @__PURE__ */ jsxs13("label", { className: "sc-choice__control", children: [
1096
+ /* @__PURE__ */ jsx15(
1097
+ BaseSwitch.Root,
1098
+ {
1099
+ className: "sc-switch",
1100
+ disabled,
1101
+ "aria-describedby": description != null ? descriptionId : void 0,
1102
+ onCheckedChange: onCheckedChange ? (checked) => onCheckedChange(checked) : void 0,
1103
+ ...rest,
1104
+ children: /* @__PURE__ */ jsx15(BaseSwitch.Thumb, { className: "sc-switch__thumb" })
1105
+ }
1106
+ ),
1107
+ /* @__PURE__ */ jsx15("span", { className: "sc-choice__label", children: label })
1108
+ ] }),
1109
+ description != null ? /* @__PURE__ */ jsx15("span", { className: "sc-choice__description", id: descriptionId, children: description }) : null
1110
+ ]
1111
+ }
1112
+ );
1113
+ }
1114
+
1115
+ // src/components/Tabs/Tabs.tsx
1116
+ import { Tabs as BaseTabs } from "@base-ui/react/tabs";
1117
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1118
+ function Root3({ className, onValueChange, ...rest }) {
1119
+ return /* @__PURE__ */ jsx16(
1120
+ BaseTabs.Root,
1121
+ {
1122
+ className: cx("sc-tabs", className),
1123
+ onValueChange: onValueChange ? (value) => onValueChange(String(value)) : void 0,
1124
+ ...rest
1125
+ }
1126
+ );
1127
+ }
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
+ );
1142
+ }
1143
+ function Tab({ icon, count, className, children, ...rest }) {
1144
+ return /* @__PURE__ */ jsxs14(BaseTabs.Tab, { className: cx("sc-tabs__tab", className), ...rest, children: [
1145
+ icon ? /* @__PURE__ */ jsx16("span", { className: "sc-tabs__icon", "aria-hidden": "true", children: icon }) : null,
1146
+ /* @__PURE__ */ jsx16("span", { className: "sc-tabs__label", children }),
1147
+ count != null ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
1148
+ " ",
1149
+ /* @__PURE__ */ jsx16("span", { className: "sc-tabs__count", children: count })
1150
+ ] }) : null
1151
+ ] });
1152
+ }
1153
+ function Panel({ className, ...rest }) {
1154
+ return /* @__PURE__ */ jsx16(BaseTabs.Panel, { className: cx("sc-tabs__panel", className), ...rest });
1155
+ }
1156
+ var Tabs = { Root: Root3, List, Tab, Panel };
1157
+
1158
+ // src/components/Toolbar/Toolbar.tsx
1159
+ import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
1160
+ import { jsx as jsx17 } from "react/jsx-runtime";
1161
+ function Root4({ wrap = true, gap = "xs", className, ...rest }) {
1162
+ return /* @__PURE__ */ jsx17(
1163
+ BaseToolbar.Root,
1164
+ {
1165
+ className: cx("sc-toolbar", className),
1166
+ "data-wrap": wrap || void 0,
1167
+ "data-gap": gap,
1168
+ ...rest
1169
+ }
1170
+ );
1171
+ }
1172
+ function Group2({ gap = "2xs", className, ...rest }) {
1173
+ return /* @__PURE__ */ jsx17(BaseToolbar.Group, { className: cx("sc-toolbar__group", className), "data-gap": gap, ...rest });
1174
+ }
1175
+ function Separator2({ className, ...rest }) {
1176
+ return /* @__PURE__ */ jsx17(BaseToolbar.Separator, { className: cx("sc-toolbar__separator", className), ...rest });
1177
+ }
1178
+ var Button2 = BaseToolbar.Button;
1179
+ var Link = BaseToolbar.Link;
1180
+ function Spacer({ className }) {
1181
+ return /* @__PURE__ */ jsx17("div", { className: cx("sc-toolbar__spacer", className), "aria-hidden": "true" });
1182
+ }
1183
+ var Toolbar = { Root: Root4, Group: Group2, Separator: Separator2, Button: Button2, Link, Spacer };
1184
+
1185
+ // src/components/Banner/Banner.tsx
1186
+ import { useState as useState2 } from "react";
1187
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1188
+ var toneIcons = {
1189
+ info: /* @__PURE__ */ jsx18(InfoIcon, {}),
1190
+ success: /* @__PURE__ */ jsx18(CircleCheckIcon, {}),
1191
+ warning: /* @__PURE__ */ jsx18(WarningIcon, {}),
1192
+ danger: /* @__PURE__ */ jsx18(CircleXIcon, {}),
1193
+ neutral: null
1194
+ };
1195
+ function Banner({
1196
+ tone = "info",
1197
+ icon,
1198
+ action,
1199
+ dismissible = false,
1200
+ onDismiss,
1201
+ open,
1202
+ dismissLabel = "Dismiss",
1203
+ role,
1204
+ className,
1205
+ children,
1206
+ ...rest
1207
+ }) {
1208
+ const [dismissed, setDismissed] = useState2(false);
1209
+ const visible = open ?? !dismissed;
1210
+ if (!visible) return null;
1211
+ const glyph = icon === false ? null : icon ?? toneIcons[tone];
1212
+ return /* @__PURE__ */ jsxs15(
1213
+ "div",
1214
+ {
1215
+ role: role ?? (tone === "warning" || tone === "danger" ? "alert" : "status"),
1216
+ className: cx("sc-banner", className),
1217
+ "data-tone": tone,
1218
+ ...rest,
1219
+ children: [
1220
+ glyph ? /* @__PURE__ */ jsx18("span", { className: "sc-banner__icon", "aria-hidden": "true", children: glyph }) : null,
1221
+ /* @__PURE__ */ jsx18("div", { className: "sc-banner__body", children }),
1222
+ action ? /* @__PURE__ */ jsx18("div", { className: "sc-banner__action", children: action }) : null,
1223
+ dismissible ? /* @__PURE__ */ jsx18(
1224
+ IconButton,
1225
+ {
1226
+ label: dismissLabel,
1227
+ size: "sm",
1228
+ className: "sc-banner__dismiss",
1229
+ onClick: () => {
1230
+ setDismissed(true);
1231
+ onDismiss?.();
1232
+ },
1233
+ children: /* @__PURE__ */ jsx18(XIcon, {})
1234
+ }
1235
+ ) : null
1236
+ ]
1237
+ }
1238
+ );
1239
+ }
1240
+
1241
+ // src/components/Spinner/Spinner.tsx
1242
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1243
+ function Spinner({
1244
+ size = "md",
1245
+ label = "Loading",
1246
+ decorative = false,
1247
+ className,
1248
+ ...rest
1249
+ }) {
1250
+ return /* @__PURE__ */ jsx19(
1251
+ "span",
1252
+ {
1253
+ className: cx("sc-spinner", className),
1254
+ "data-size": size,
1255
+ role: decorative ? void 0 : "status",
1256
+ "aria-label": decorative ? void 0 : label,
1257
+ "aria-hidden": decorative || void 0,
1258
+ ...rest,
1259
+ children: /* @__PURE__ */ jsxs16(
1260
+ "svg",
1261
+ {
1262
+ viewBox: "0 0 16 16",
1263
+ fill: "none",
1264
+ stroke: "currentColor",
1265
+ strokeWidth: "1.75",
1266
+ "aria-hidden": "true",
1267
+ focusable: "false",
1268
+ children: [
1269
+ /* @__PURE__ */ jsx19("circle", { className: "sc-spinner__track", cx: "8", cy: "8", r: "6.25" }),
1270
+ /* @__PURE__ */ jsx19("circle", { className: "sc-spinner__arc", cx: "8", cy: "8", r: "6.25", strokeLinecap: "round" })
1271
+ ]
1272
+ }
1273
+ )
1274
+ }
1275
+ );
1276
+ }
1277
+
1278
+ // src/components/Progress/Progress.tsx
1279
+ import { Progress as BaseProgress } from "@base-ui/react/progress";
1280
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1281
+ function Progress({
1282
+ value,
1283
+ max = 100,
1284
+ min = 0,
1285
+ label,
1286
+ valueText,
1287
+ showValue = false,
1288
+ tone = "accent",
1289
+ size = "md",
1290
+ variant = "bar",
1291
+ className,
1292
+ ...rest
1293
+ }) {
1294
+ const current = value ?? null;
1295
+ const hasValueText = valueText != null || showValue && current !== null;
1296
+ return /* @__PURE__ */ jsxs17(
1297
+ BaseProgress.Root,
1298
+ {
1299
+ value: current,
1300
+ max,
1301
+ min,
1302
+ getAriaValueText: (formatted) => typeof valueText === "string" ? valueText : formatted ?? "",
1303
+ className: cx("sc-progress", className),
1304
+ "data-variant": variant,
1305
+ "data-tone": tone,
1306
+ "data-size": size,
1307
+ ...rest,
1308
+ children: [
1309
+ variant === "inline" ? /* @__PURE__ */ jsx20(Spinner, { size: "sm", decorative: true, className: "sc-progress__spinner" }) : null,
1310
+ label != null ? /* @__PURE__ */ jsx20(BaseProgress.Label, { className: "sc-progress__label", children: label }) : null,
1311
+ hasValueText ? /* @__PURE__ */ jsx20(BaseProgress.Value, { className: "sc-progress__value", children: (formatted) => valueText != null ? valueText : formatted }) : null,
1312
+ variant === "bar" ? /* @__PURE__ */ jsx20(BaseProgress.Track, { className: "sc-progress__track", children: /* @__PURE__ */ jsx20(BaseProgress.Indicator, { className: "sc-progress__indicator" }) }) : null
1313
+ ]
1314
+ }
1315
+ );
1316
+ }
1317
+
1318
+ // src/components/Heading/Heading.tsx
1319
+ import { createElement as createElement3 } from "react";
1320
+ var sizeByLevel = {
1321
+ 1: "3xl",
1322
+ 2: "2xl",
1323
+ 3: "xl",
1324
+ 4: "lg",
1325
+ 5: "md",
1326
+ 6: "sm"
1327
+ };
1328
+ function Heading({
1329
+ level = 2,
1330
+ size,
1331
+ as,
1332
+ tone = "default",
1333
+ truncate = false,
1334
+ className,
1335
+ ...rest
1336
+ }) {
1337
+ return createElement3(as ?? `h${level}`, {
1338
+ className: cx("sc-heading", className),
1339
+ "data-size": size ?? sizeByLevel[level],
1340
+ "data-tone": tone,
1341
+ "data-truncate": truncate || void 0,
1342
+ ...rest
1343
+ });
1344
+ }
1345
+
1346
+ // src/components/Text/Text.tsx
1347
+ import { createElement as createElement4 } from "react";
1348
+ function Text({
1349
+ as = "p",
1350
+ size = "sm",
1351
+ tone = "default",
1352
+ weight = "regular",
1353
+ align,
1354
+ truncate = false,
1355
+ numeric = false,
1356
+ className,
1357
+ style,
1358
+ ...rest
1359
+ }) {
1360
+ const clamp2 = typeof truncate === "number" ? truncate : void 0;
1361
+ return createElement4(as, {
1362
+ className: cx("sc-text", className),
1363
+ "data-size": size,
1364
+ "data-tone": tone,
1365
+ "data-weight": weight,
1366
+ "data-align": align,
1367
+ "data-truncate": truncate === true ? "" : clamp2 !== void 0 ? "clamp" : void 0,
1368
+ "data-numeric": numeric || void 0,
1369
+ style: clamp2 !== void 0 ? { ...style, "--sc-text-lines": clamp2 } : style,
1370
+ ...rest
1371
+ });
1372
+ }
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 useEffect3, useId as useId3, useRef as useRef3, useState as useState5 } from "react";
2128
+
2129
+ // src/components/FileInput/accept.ts
2130
+ function parseAccept(accept) {
2131
+ if (accept == null) return [];
2132
+ const list = typeof accept === "string" ? accept.split(",") : accept;
2133
+ return list.map((entry) => entry.trim().toLowerCase()).filter(Boolean);
2134
+ }
2135
+ function matchesAccept(file, accept) {
2136
+ if (accept.length === 0) return true;
2137
+ const name = file.name.toLowerCase();
2138
+ const type = file.type.toLowerCase();
2139
+ return accept.some((entry) => {
2140
+ if (entry.startsWith(".")) return name.endsWith(entry);
2141
+ if (entry.endsWith("/*")) return type.startsWith(entry.slice(0, -1));
2142
+ return type === entry;
2143
+ });
2144
+ }
2145
+ var UNITS = { b: 1, kb: 1e3, mb: 1e6, gb: 1e9 };
2146
+ function parseSize(size) {
2147
+ if (size == null) return void 0;
2148
+ if (typeof size === "number") return size;
2149
+ const match = /^\s*(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)\s*$/i.exec(size);
2150
+ if (!match) throw new Error(`FileInput: maxFileSize "${size}" is not a size like "10MB".`);
2151
+ return Math.round(Number(match[1]) * UNITS[match[2].toLowerCase()]);
2152
+ }
2153
+ function formatSize(bytes) {
2154
+ const [unit, base] = bytes >= 1e9 ? ["GB", 1e9] : bytes >= 1e6 ? ["MB", 1e6] : bytes >= 1e3 ? ["KB", 1e3] : ["bytes", 1];
2155
+ const value = bytes / base;
2156
+ return `${Number.isInteger(value) ? value : Number(value.toFixed(1))} ${unit}`;
2157
+ }
2158
+ var MIME_NAMES = {
2159
+ "application/pdf": "PDF",
2160
+ "application/msword": "DOC",
2161
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX",
2162
+ "application/json": "JSON",
2163
+ "text/plain": "plain text",
2164
+ "text/markdown": "Markdown",
2165
+ "text/csv": "CSV",
2166
+ "image/png": "PNG",
2167
+ "image/jpeg": "JPEG"
2168
+ };
2169
+ function describeAccept(accept) {
2170
+ const names = accept.map((entry) => {
2171
+ if (entry.startsWith(".")) return entry.slice(1).toUpperCase();
2172
+ if (entry.endsWith("/*")) return `any ${entry.slice(0, -2)}`;
2173
+ return MIME_NAMES[entry] ?? entry.split("/").pop().toUpperCase();
2174
+ });
2175
+ const unique = [...new Set(names)];
2176
+ if (unique.length <= 1) return unique[0] ?? "";
2177
+ return `${unique.slice(0, -1).join(", ")} or ${unique.at(-1)}`;
2178
+ }
2179
+ function rejectionMessage(reason, detail) {
2180
+ switch (reason) {
2181
+ case "type":
2182
+ return `${detail.name} is not an accepted file type. Use ${detail.acceptLabel}.`;
2183
+ case "size":
2184
+ return `${detail.name} is ${formatSize(detail.size ?? 0)}, over the ${formatSize(detail.maxFileSize ?? 0)} limit.`;
2185
+ case "count":
2186
+ return detail.maxFiles === 1 ? "Choose one file." : `Up to ${detail.maxFiles} files. Remove one to add another.`;
2187
+ }
2188
+ }
2189
+ function escapeHtml(text) {
2190
+ return text.replace(
2191
+ /[&<>"']/g,
2192
+ (ch) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[ch]
2193
+ );
2194
+ }
2195
+
2196
+ // src/components/FileInput/FileInput.tsx
2197
+ import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2198
+ 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>';
2199
+ var sameFiles = (a, b) => a.length === b.length && a.every((file, i) => file === b[i]);
2200
+ function FileInput({
2201
+ label,
2202
+ hideLabel = false,
2203
+ description,
2204
+ error,
2205
+ invalid = false,
2206
+ required = false,
2207
+ disabled = false,
2208
+ name,
2209
+ size = "md",
2210
+ className,
2211
+ accept,
2212
+ acceptLabel,
2213
+ maxFileSize,
2214
+ multiple = false,
2215
+ maxFiles,
2216
+ files,
2217
+ defaultFiles,
2218
+ onFilesChange,
2219
+ idleLabel,
2220
+ browseLabel = "browse"
2221
+ }) {
2222
+ const id = useId3();
2223
+ const labelId = `${id}label`;
2224
+ const descriptionId = `${id}description`;
2225
+ const messagesId = `${id}messages`;
2226
+ const controlled = files !== void 0;
2227
+ const [uncontrolledFiles, setUncontrolledFiles] = useState5(defaultFiles ?? []);
2228
+ const current = controlled ? files : uncontrolledFiles;
2229
+ const [rejections, setRejections] = useState5([]);
2230
+ const [inputId, setInputId] = useState5();
2231
+ const [pondVersion, setPondVersion] = useState5(0);
2232
+ const hostRef = useRef3(null);
2233
+ const pondRef = useRef3(null);
2234
+ const moduleRef = useRef3(null);
2235
+ const patchRef = useRef3(() => {
2236
+ });
2237
+ const settledRef = useRef3(current);
2238
+ const targetRef = useRef3(null);
2239
+ const acceptList = parseAccept(accept);
2240
+ const acceptAttr = acceptList.join(",");
2241
+ const maxBytes = parseSize(maxFileSize);
2242
+ const messages = [...rejections, ...error != null ? [error] : []];
2243
+ const isInvalid = invalid || messages.length > 0;
2244
+ const idleText = idleLabel ?? (multiple ? "Drop files here or" : current.length > 0 ? "Drop another file to replace it, or" : "Drop a file here or");
2245
+ const live = {
2246
+ acceptList,
2247
+ acceptLabel: acceptLabel ?? describeAccept(acceptList),
2248
+ maxBytes,
2249
+ maxFiles: multiple ? maxFiles : 1,
2250
+ multiple,
2251
+ current,
2252
+ controlled,
2253
+ onFilesChange,
2254
+ labelId,
2255
+ describedBy: [description != null ? descriptionId : null, messages.length > 0 ? messagesId : null],
2256
+ isInvalid,
2257
+ acceptAttr
2258
+ };
2259
+ const liveRef = useRef3(live);
2260
+ useEffect3(() => {
2261
+ liveRef.current = live;
2262
+ });
2263
+ useEffect3(() => {
2264
+ let cancelled = false;
2265
+ let pond = null;
2266
+ let observer = null;
2267
+ const host = hostRef.current;
2268
+ if (!host) return void 0;
2269
+ const reject = (reason, file) => {
2270
+ const l = liveRef.current;
2271
+ const message = rejectionMessage(reason, {
2272
+ name: file?.name,
2273
+ size: file?.size,
2274
+ acceptLabel: l.acceptLabel,
2275
+ maxFileSize: l.maxBytes,
2276
+ maxFiles: l.maxFiles
2277
+ });
2278
+ setRejections((list) => list.includes(message) ? list : [...list, message]);
2279
+ if (file && targetRef.current) {
2280
+ targetRef.current = targetRef.current.filter((f) => f !== file);
2281
+ queueMicrotask(emit);
2282
+ }
2283
+ };
2284
+ const startAttempt = () => setRejections((list) => list.length ? [] : list);
2285
+ let removeIntent = false;
2286
+ const acceptedIds = /* @__PURE__ */ new Set();
2287
+ const noteRemove = (event) => {
2288
+ if (event.target?.closest?.(".filepond--action-remove-item")) removeIntent = true;
2289
+ };
2290
+ const emit = () => {
2291
+ const mod = moduleRef.current;
2292
+ if (!pond || !mod) return;
2293
+ const idle = pond.getFiles().filter((item) => item.status === mod.FileStatus.IDLE).map((item) => item.file);
2294
+ const accepted = liveRef.current.multiple ? idle : idle.slice(-1);
2295
+ const target = targetRef.current;
2296
+ if (target) {
2297
+ if (!sameFiles(accepted, target)) return;
2298
+ targetRef.current = null;
2299
+ settledRef.current = accepted;
2300
+ if (!sameFiles(accepted, liveRef.current.current)) {
2301
+ if (!liveRef.current.controlled) setUncontrolledFiles(accepted);
2302
+ liveRef.current.onFilesChange?.(accepted);
2303
+ }
2304
+ return;
2305
+ }
2306
+ if (sameFiles(accepted, settledRef.current)) return;
2307
+ settledRef.current = accepted;
2308
+ if (!liveRef.current.controlled) setUncontrolledFiles(accepted);
2309
+ liveRef.current.onFilesChange?.(accepted);
2310
+ };
2311
+ const patch = () => {
2312
+ if (!pond) return;
2313
+ const l = liveRef.current;
2314
+ const root = pond.element;
2315
+ if (!root) return;
2316
+ const set = (el, attr, value) => {
2317
+ if (!el || el.getAttribute(attr) === value) return;
2318
+ if (value == null) el.removeAttribute(attr);
2319
+ else el.setAttribute(attr, value);
2320
+ };
2321
+ const input = root.querySelector("input.filepond--browser");
2322
+ const dropLabel = root.querySelector(".filepond--drop-label label");
2323
+ set(input, "aria-labelledby", l.labelId);
2324
+ set(input, "aria-describedby", [dropLabel?.id, ...l.describedBy].filter(Boolean).join(" ") || null);
2325
+ set(input, "aria-invalid", l.isInvalid ? "true" : null);
2326
+ set(input, "accept", l.acceptAttr || null);
2327
+ set(input, "multiple", l.multiple ? "" : null);
2328
+ set(root.querySelector(".filepond--label-action"), "tabindex", null);
2329
+ for (const item of root.querySelectorAll(".filepond--item")) {
2330
+ const fileName = item.querySelector(".filepond--file-info-main")?.textContent?.trim();
2331
+ if (fileName)
2332
+ set(item.querySelector(".filepond--action-remove-item"), "aria-label", `Remove ${fileName}`);
2333
+ }
2334
+ setInputId(input?.id || void 0);
2335
+ };
2336
+ void import("filepond").then((mod) => {
2337
+ if (cancelled || !mod.supported()) return;
2338
+ moduleRef.current = mod;
2339
+ const options = {
2340
+ credits: false,
2341
+ allowPaste: false,
2342
+ allowReorder: false,
2343
+ allowProcess: false,
2344
+ allowRevert: false,
2345
+ instantUpload: false,
2346
+ dropOnPage: false,
2347
+ // Always multi: FilePond's own single mode replaces the current file *before* validating the new
2348
+ // one, so a rejected file would discard a good one. Replacement happens in `addfile` instead.
2349
+ allowMultiple: true,
2350
+ allowReplace: false,
2351
+ itemInsertLocation: "after",
2352
+ fileSizeBase: 1e3,
2353
+ iconRemove: REMOVE_ICON,
2354
+ labelButtonRemoveItem: "Remove",
2355
+ styleButtonRemoveItemPosition: "right",
2356
+ beforeAddFile: (item) => {
2357
+ const l = liveRef.current;
2358
+ const file = item.file;
2359
+ if (!matchesAccept(file, l.acceptList)) return reject("type", file), false;
2360
+ if (l.maxBytes != null && file.size > l.maxBytes) return reject("size", file), false;
2361
+ return true;
2362
+ }
2363
+ };
2364
+ pond = mod.create(options);
2365
+ const root = pond.element;
2366
+ if (!root) return;
2367
+ host.appendChild(root);
2368
+ pondRef.current = pond;
2369
+ patchRef.current = patch;
2370
+ pond.on("addfile", (error2, added) => {
2371
+ if (!error2) acceptedIds.add(added.id);
2372
+ if (!error2 && !liveRef.current.multiple) {
2373
+ for (const other of pond?.getFiles() ?? []) if (other.id !== added.id) pond?.removeFile(other.id);
2374
+ }
2375
+ emit();
2376
+ });
2377
+ pond.on("removefile", (_error, removed) => {
2378
+ const active = document.activeElement;
2379
+ const inRemovedRow = active?.closest(".filepond--item")?.id === `filepond--item-${removed.id}`;
2380
+ if (inRemovedRow || removeIntent && (active == null || active === document.body))
2381
+ root.querySelector("input.filepond--browser")?.focus();
2382
+ removeIntent = false;
2383
+ if (acceptedIds.delete(removed.id)) startAttempt();
2384
+ emit();
2385
+ });
2386
+ pond.on("updatefiles", emit);
2387
+ pond.on("warning", (warning) => {
2388
+ if (warning?.body === "Max files") reject("count");
2389
+ });
2390
+ observer = new MutationObserver(patch);
2391
+ observer.observe(root, {
2392
+ subtree: true,
2393
+ childList: true,
2394
+ attributes: true,
2395
+ attributeFilter: ["tabindex", "aria-labelledby", "aria-describedby", "accept", "id", "multiple"]
2396
+ });
2397
+ host.addEventListener("drop", startAttempt, true);
2398
+ host.addEventListener("change", startAttempt, true);
2399
+ host.addEventListener("click", noteRemove, true);
2400
+ settledRef.current = [];
2401
+ setPondVersion((v) => v + 1);
2402
+ });
2403
+ return () => {
2404
+ cancelled = true;
2405
+ host.removeEventListener("drop", startAttempt, true);
2406
+ host.removeEventListener("change", startAttempt, true);
2407
+ host.removeEventListener("click", noteRemove, true);
2408
+ observer?.disconnect();
2409
+ if (pond) {
2410
+ pond.element?.remove();
2411
+ pond.destroy();
2412
+ }
2413
+ pondRef.current = null;
2414
+ patchRef.current = () => {
2415
+ };
2416
+ };
2417
+ }, []);
2418
+ useEffect3(() => {
2419
+ const pond = pondRef.current;
2420
+ if (!pond) return;
2421
+ pond.setOptions({
2422
+ name: name ?? "",
2423
+ storeAsFile: name != null,
2424
+ disabled,
2425
+ required,
2426
+ maxFiles: multiple ? maxFiles ?? null : null,
2427
+ allowRemove: !disabled,
2428
+ labelIdle: `${escapeHtml(idleText)} <span class="filepond--label-action">${escapeHtml(browseLabel)}</span>`
2429
+ });
2430
+ patchRef.current();
2431
+ }, [
2432
+ pondVersion,
2433
+ name,
2434
+ disabled,
2435
+ required,
2436
+ multiple,
2437
+ maxFiles,
2438
+ idleText,
2439
+ browseLabel,
2440
+ labelId,
2441
+ acceptAttr,
2442
+ isInvalid,
2443
+ description,
2444
+ messages.length
2445
+ ]);
2446
+ useEffect3(() => {
2447
+ const pond = pondRef.current;
2448
+ const mod = moduleRef.current;
2449
+ if (!pond || !mod) return;
2450
+ const items = pond.getFiles();
2451
+ const idle = items.filter((item) => item.status === mod.FileStatus.IDLE);
2452
+ const inPond = idle.map((item) => item.file);
2453
+ if (sameFiles(inPond, current)) {
2454
+ settledRef.current = current;
2455
+ return;
2456
+ }
2457
+ targetRef.current = current;
2458
+ for (const item of idle) if (!current.includes(item.file)) pond.removeFile(item.id);
2459
+ const toAdd = current.filter((file) => !inPond.includes(file));
2460
+ if (toAdd.length > 0) void pond.addFiles(toAdd);
2461
+ }, [current, pondVersion]);
2462
+ const ready = pondVersion > 0;
2463
+ return /* @__PURE__ */ jsxs24(
2464
+ "div",
2465
+ {
2466
+ className: cx("sc-field", "sc-file-input-field", className),
2467
+ "data-size": size,
2468
+ "data-disabled": disabled ? "" : void 0,
2469
+ "data-invalid": isInvalid ? "" : void 0,
2470
+ children: [
2471
+ /* @__PURE__ */ jsxs24(
2472
+ "label",
2473
+ {
2474
+ id: labelId,
2475
+ htmlFor: inputId,
2476
+ className: cx("sc-field__label", hideLabel && "sc-visually-hidden"),
2477
+ children: [
2478
+ label,
2479
+ required ? /* @__PURE__ */ jsx29("span", { className: "sc-field__required", "aria-hidden": "true", children: "*" }) : null
2480
+ ]
2481
+ }
2482
+ ),
2483
+ /* @__PURE__ */ jsxs24(
2484
+ "div",
2485
+ {
2486
+ className: "sc-file-input",
2487
+ "data-ready": ready ? "" : void 0,
2488
+ "data-disabled": disabled ? "" : void 0,
2489
+ "data-invalid": isInvalid ? "" : void 0,
2490
+ "data-multiple": multiple ? "" : void 0,
2491
+ children: [
2492
+ ready ? null : (
2493
+ // Server render and first paint: the same drop zone, inert until FilePond takes over.
2494
+ /* @__PURE__ */ jsxs24("div", { className: "sc-file-input__placeholder", "aria-hidden": "true", children: [
2495
+ idleText,
2496
+ " ",
2497
+ /* @__PURE__ */ jsx29("span", { className: "sc-file-input__browse", children: browseLabel })
2498
+ ] })
2499
+ ),
2500
+ /* @__PURE__ */ jsx29("div", { ref: hostRef, className: "sc-file-input__pond" })
2501
+ ]
2502
+ }
2503
+ ),
2504
+ description != null ? /* @__PURE__ */ jsx29("p", { id: descriptionId, className: "sc-field__description", children: description }) : null,
2505
+ /* @__PURE__ */ jsx29("div", { id: messagesId, className: "sc-file-input__messages", "aria-live": "polite", children: messages.map((message, i) => /* @__PURE__ */ jsx29("p", { className: "sc-field__error", children: message }, i)) })
2506
+ ]
2507
+ }
2508
+ );
2509
+ }
2510
+
2511
+ // src/components/PriorityNav/PriorityNav.tsx
2512
+ import {
2513
+ useEffect as useEffect4,
2514
+ useId as useId4,
2515
+ useLayoutEffect as useLayoutEffect2,
2516
+ useRef as useRef4,
2517
+ useState as useState6
2518
+ } from "react";
2519
+
2520
+ // src/components/PriorityNav/fit.ts
2521
+ var EPSILON = 0.5;
2522
+ function rowWidth(widths, gap) {
2523
+ let total = 0;
2524
+ for (const w of widths) total += w;
2525
+ return widths.length > 1 ? total + gap * (widths.length - 1) : total;
2526
+ }
2527
+ function fitCount({ widths, current, available, more, gap }) {
2528
+ const n = widths.length;
2529
+ const hasCurrent = current >= 0 && current < n;
2530
+ const others = hasCurrent ? n - 1 : n;
2531
+ if (rowWidth(widths, gap) <= available + EPSILON) return others;
2532
+ let used = more + (hasCurrent ? widths[current] + gap : 0);
2533
+ let count = 0;
2534
+ for (let i = 0; i < n; i++) {
2535
+ if (i === current) continue;
2536
+ const next = used + widths[i] + gap;
2537
+ if (next > available + EPSILON) break;
2538
+ used = next;
2539
+ count++;
2540
+ }
2541
+ return count;
2542
+ }
2543
+ function inlineFlags(length, current, count) {
2544
+ const flags = [];
2545
+ let seen = 0;
2546
+ for (let i = 0; i < length; i++) {
2547
+ if (i === current) flags.push(true);
2548
+ else flags.push(seen++ < count);
2549
+ }
2550
+ return flags;
2551
+ }
2552
+ function isOverflowing({ widths, gap, available, was, hysteresis }) {
2553
+ const total = rowWidth(widths, gap);
2554
+ return was ? total + Math.max(0, hysteresis) > available + EPSILON : total > available + EPSILON;
2555
+ }
2556
+
2557
+ // src/components/PriorityNav/place.ts
2558
+ var clamp = (value, min, max) => Math.max(min, Math.min(value, max));
2559
+ function placePanel({ anchor, panel, viewport, gutter, offset, rtl = false }) {
2560
+ const endAligned = rtl ? anchor.left : anchor.right - panel.width;
2561
+ const startAligned = rtl ? anchor.right - panel.width : anchor.left;
2562
+ const fitsX = (x2) => x2 >= gutter && x2 + panel.width <= viewport.width - gutter;
2563
+ const x = fitsX(endAligned) ? endAligned : fitsX(startAligned) ? startAligned : endAligned;
2564
+ const left = clamp(x, gutter, Math.max(gutter, viewport.width - gutter - panel.width));
2565
+ const below = anchor.bottom + offset;
2566
+ const above = anchor.top - offset - panel.height;
2567
+ const fitsBelow = below + panel.height <= viewport.height - gutter;
2568
+ const top = fitsBelow || above < gutter ? below : above;
2569
+ return { left, top };
2570
+ }
2571
+
2572
+ // src/components/PriorityNav/PriorityNav.tsx
2573
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
2574
+ var defaultCountLabel2 = (n) => n === 1 ? "1 link" : `${n} links`;
2575
+ var defaultLink = ({ children, ...props }) => /* @__PURE__ */ jsx30("a", { ...props, children });
2576
+ var keyOf = (item) => item.id ?? item.href;
2577
+ var supportsAnchor = () => typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("anchor-name: --a");
2578
+ var supportsPopover = (el) => typeof el.showPopover === "function";
2579
+ function signatureOf(items) {
2580
+ return items.map((item) => {
2581
+ const text = typeof item.label === "string" || typeof item.label === "number" ? item.label : "";
2582
+ return `${keyOf(item)}${text}`;
2583
+ }).join("");
2584
+ }
2585
+ function PriorityNav({
2586
+ items,
2587
+ moreLabel = "More",
2588
+ moreCountLabel = defaultCountLabel2,
2589
+ renderLink = defaultLink,
2590
+ onOverflowChange,
2591
+ overflowHysteresis = 0,
2592
+ className,
2593
+ style,
2594
+ ...rest
2595
+ }) {
2596
+ const signature = signatureOf(items);
2597
+ const current = items.findIndex((item) => item.current);
2598
+ const [fit, setFit] = useState6({ signature: null, current: -1, count: 0, overflowing: false });
2599
+ const [open, setOpen] = useState6(false);
2600
+ const panelId = useId4();
2601
+ const listRef = useRef4(null);
2602
+ const moreRef = useRef4(null);
2603
+ const toggleRef = useRef4(null);
2604
+ const panelRef = useRef4(null);
2605
+ const measured = useRef4(null);
2606
+ const currentRef = useRef4(current);
2607
+ const fitRef = useRef4(fit);
2608
+ const hysteresisRef = useRef4(overflowHysteresis);
2609
+ const onOverflowRef = useRef4(onOverflowChange);
2610
+ const solve = (m, cur, was) => ({
2611
+ count: fitCount({ ...m, current: cur }),
2612
+ overflowing: isOverflowing({ ...m, was, hysteresis: hysteresisRef.current })
2613
+ });
2614
+ const measuring = fit.signature !== signature;
2615
+ useLayoutEffect2(() => {
2616
+ currentRef.current = current;
2617
+ fitRef.current = fit;
2618
+ hysteresisRef.current = overflowHysteresis;
2619
+ onOverflowRef.current = onOverflowChange;
2620
+ });
2621
+ useLayoutEffect2(() => {
2622
+ const list = listRef.current;
2623
+ const more = moreRef.current;
2624
+ if (!list || !more) return;
2625
+ if (measuring) {
2626
+ const widths = Array.from(
2627
+ list.querySelectorAll(":scope > .sc-priority-nav__item"),
2628
+ (el) => el.getBoundingClientRect().width
2629
+ );
2630
+ measured.current = {
2631
+ widths,
2632
+ more: more.getBoundingClientRect().width,
2633
+ gap: parseFloat(getComputedStyle(list).columnGap) || 0,
2634
+ available: list.clientWidth
2635
+ };
2636
+ } else if (fit.current === current) return;
2637
+ const m = measured.current;
2638
+ if (!m) return;
2639
+ setFit({ signature, current, ...solve(m, current, fit.overflowing) });
2640
+ }, [measuring, signature, current, fit]);
2641
+ useEffect4(() => {
2642
+ const list = listRef.current;
2643
+ const more = moreRef.current;
2644
+ if (!list || !more || typeof ResizeObserver === "undefined") return;
2645
+ const observer = new ResizeObserver((entries) => {
2646
+ const m = measured.current;
2647
+ if (!m) return;
2648
+ for (const entry of entries) {
2649
+ if (entry.target === list)
2650
+ m.available = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
2651
+ else {
2652
+ const width = entry.borderBoxSize?.[0]?.inlineSize ?? 0;
2653
+ if (width > 0) m.more = width;
2654
+ }
2655
+ }
2656
+ const prev = fitRef.current;
2657
+ if (prev.signature === null) return;
2658
+ const next = solve(m, currentRef.current, prev.overflowing);
2659
+ if (prev.count !== next.count || prev.overflowing !== next.overflowing) setFit({ ...prev, ...next });
2660
+ });
2661
+ observer.observe(list);
2662
+ observer.observe(more);
2663
+ return () => observer.disconnect();
2664
+ }, []);
2665
+ const reported = useRef4(false);
2666
+ useEffect4(() => {
2667
+ if (reported.current === fit.overflowing) return;
2668
+ reported.current = fit.overflowing;
2669
+ onOverflowRef.current?.(fit.overflowing);
2670
+ }, [fit.overflowing]);
2671
+ useEffect4(() => {
2672
+ const fonts = typeof document === "undefined" ? void 0 : document.fonts;
2673
+ if (!fonts || fonts.status === "loaded") return;
2674
+ let live = true;
2675
+ void fonts.ready.then(() => {
2676
+ if (live) setFit((prev) => ({ ...prev, signature: null }));
2677
+ });
2678
+ return () => {
2679
+ live = false;
2680
+ };
2681
+ }, []);
2682
+ const flags = measuring ? null : inlineFlags(items.length, current, fit.count);
2683
+ const overflow = flags ? items.filter((_, i) => !flags[i]) : [];
2684
+ const expanded = open && overflow.length > 0;
2685
+ useLayoutEffect2(() => {
2686
+ const panel = panelRef.current;
2687
+ if (!panel || !supportsPopover(panel)) return;
2688
+ if (!panel.hasAttribute("popover")) panel.setAttribute("popover", "manual");
2689
+ const shown = panel.matches(":popover-open");
2690
+ if (expanded && !shown) panel.showPopover();
2691
+ else if (!expanded && shown) panel.hidePopover();
2692
+ }, [expanded]);
2693
+ useLayoutEffect2(() => {
2694
+ const panel = panelRef.current;
2695
+ const toggle2 = toggleRef.current;
2696
+ if (!expanded || !panel || !toggle2 || supportsAnchor()) return;
2697
+ const place = () => {
2698
+ const anchor = toggle2.getBoundingClientRect();
2699
+ const box = panel.getBoundingClientRect();
2700
+ const css = getComputedStyle(panel);
2701
+ const { left, top } = placePanel({
2702
+ anchor,
2703
+ panel: { width: box.width, height: box.height },
2704
+ viewport: { width: document.documentElement.clientWidth, height: window.innerHeight },
2705
+ gutter: parseFloat(css.getPropertyValue("--sc-spacing-md")) || 16,
2706
+ offset: parseFloat(css.getPropertyValue("--sc-spacing-2xs")) || 4,
2707
+ rtl: css.direction === "rtl"
2708
+ });
2709
+ panel.style.left = `${left}px`;
2710
+ panel.style.top = `${top}px`;
2711
+ };
2712
+ place();
2713
+ window.addEventListener("resize", place, { passive: true });
2714
+ window.addEventListener("scroll", place, { passive: true, capture: true });
2715
+ return () => {
2716
+ window.removeEventListener("resize", place);
2717
+ window.removeEventListener("scroll", place, { capture: true });
2718
+ panel.style.left = "";
2719
+ panel.style.top = "";
2720
+ };
2721
+ }, [expanded]);
2722
+ useEffect4(() => {
2723
+ if (!expanded) return;
2724
+ const onPointerDown = (event) => {
2725
+ if (!moreRef.current?.contains(event.target)) setOpen(false);
2726
+ };
2727
+ const onKeyDown = (event) => {
2728
+ if (event.key !== "Escape") return;
2729
+ const active = document.activeElement;
2730
+ setOpen(false);
2731
+ if (!active || active === document.body || moreRef.current?.contains(active))
2732
+ toggleRef.current?.focus();
2733
+ };
2734
+ document.addEventListener("pointerdown", onPointerDown);
2735
+ document.addEventListener("keydown", onKeyDown);
2736
+ return () => {
2737
+ document.removeEventListener("pointerdown", onPointerDown);
2738
+ document.removeEventListener("keydown", onKeyDown);
2739
+ };
2740
+ }, [expanded]);
2741
+ const onBlur = (event) => {
2742
+ if (!event.currentTarget.contains(event.relatedTarget)) setOpen(false);
2743
+ };
2744
+ const link = (item, inPanel) => renderLink(
2745
+ {
2746
+ href: item.href,
2747
+ className: "sc-priority-nav__link",
2748
+ "aria-current": item.current ? "page" : void 0,
2749
+ onClick: inPanel ? () => setOpen(false) : void 0,
2750
+ children: /* @__PURE__ */ jsx30("span", { className: "sc-priority-nav__label", children: item.label })
2751
+ },
2752
+ item
2753
+ );
2754
+ return /* @__PURE__ */ jsx30(
2755
+ "nav",
2756
+ {
2757
+ className: cx("sc-priority-nav", className),
2758
+ "data-measuring": measuring || void 0,
2759
+ "data-overflowing": fit.overflowing || void 0,
2760
+ style: { ...style, "--_anchor": `--sc-priority-nav${panelId.replace(/[^\w-]/g, "")}` },
2761
+ ...rest,
2762
+ children: /* @__PURE__ */ jsxs25("ul", { ref: listRef, className: "sc-priority-nav__list", children: [
2763
+ items.map(
2764
+ (item, i) => flags && !flags[i] ? null : /* @__PURE__ */ jsx30("li", { className: "sc-priority-nav__item", "data-current": item.current || void 0, children: link(item, false) }, keyOf(item))
2765
+ ),
2766
+ /* @__PURE__ */ jsxs25(
2767
+ "li",
2768
+ {
2769
+ ref: moreRef,
2770
+ className: "sc-priority-nav__more",
2771
+ hidden: measuring || overflow.length === 0,
2772
+ onBlur,
2773
+ children: [
2774
+ /* @__PURE__ */ jsxs25(
2775
+ "button",
2776
+ {
2777
+ ref: toggleRef,
2778
+ type: "button",
2779
+ className: "sc-priority-nav__toggle",
2780
+ "aria-expanded": expanded,
2781
+ "aria-controls": panelId,
2782
+ onClick: () => setOpen((o) => !o),
2783
+ children: [
2784
+ /* @__PURE__ */ jsx30(MoreHorizontalIcon, { className: "sc-priority-nav__ellipsis" }),
2785
+ /* @__PURE__ */ jsx30("span", { className: "sc-priority-nav__toggle-label", children: moreLabel }),
2786
+ /* @__PURE__ */ jsxs25("span", { className: "sc-visually-hidden", children: [
2787
+ ", ",
2788
+ moreCountLabel(overflow.length)
2789
+ ] }),
2790
+ /* @__PURE__ */ jsx30(ChevronDownIcon, { size: "sm", className: "sc-priority-nav__chevron" })
2791
+ ]
2792
+ }
2793
+ ),
2794
+ /* @__PURE__ */ jsx30("ul", { ref: panelRef, id: panelId, className: "sc-priority-nav__panel", hidden: !expanded, children: overflow.map((item) => /* @__PURE__ */ jsx30("li", { children: link(item, true) }, keyOf(item))) })
2795
+ ]
2796
+ }
2797
+ )
2798
+ ] })
2799
+ }
2800
+ );
2801
+ }
2802
+
2803
+ // src/components/Popover/Popover.tsx
2804
+ import { Popover as BasePopover } from "@base-ui/react/popover";
2805
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
2806
+ function Root6({ open, defaultOpen, onOpenChange, modal = false, children }) {
2807
+ return /* @__PURE__ */ jsx31(
2808
+ BasePopover.Root,
2809
+ {
2810
+ open,
2811
+ defaultOpen,
2812
+ onOpenChange: onOpenChange ? (next) => onOpenChange(next) : void 0,
2813
+ modal,
2814
+ children
2815
+ }
2816
+ );
2817
+ }
2818
+ function Trigger3({ render, className, children, ...rest }) {
2819
+ return /* @__PURE__ */ jsx31(
2820
+ BasePopover.Trigger,
2821
+ {
2822
+ render: render ?? /* @__PURE__ */ jsx31(Button, { variant: "secondary", className }),
2823
+ className: render ? className : void 0,
2824
+ ...rest,
2825
+ children
2826
+ }
2827
+ );
2828
+ }
2829
+ function Content3({
2830
+ side = "bottom",
2831
+ align = "center",
2832
+ sideOffset,
2833
+ arrow = false,
2834
+ className,
2835
+ children,
2836
+ ...rest
2837
+ }) {
2838
+ return /* @__PURE__ */ jsx31(BasePopover.Portal, { children: /* @__PURE__ */ jsx31(
2839
+ BasePopover.Positioner,
2840
+ {
2841
+ side,
2842
+ align,
2843
+ sideOffset: sideOffset ?? (arrow ? 8 : 4),
2844
+ className: "sc-popover__positioner",
2845
+ children: /* @__PURE__ */ jsxs26(BasePopover.Popup, { className: cx("sc-popover", className), ...rest, children: [
2846
+ arrow ? /* @__PURE__ */ jsx31(BasePopover.Arrow, { className: "sc-popover__arrow" }) : null,
2847
+ children
2848
+ ] })
2849
+ }
2850
+ ) });
2851
+ }
2852
+ function Title2({ className, ...rest }) {
2853
+ return /* @__PURE__ */ jsx31(BasePopover.Title, { className: cx("sc-popover__title", className), ...rest });
2854
+ }
2855
+ function Description2({ className, ...rest }) {
2856
+ return /* @__PURE__ */ jsx31(BasePopover.Description, { className: cx("sc-popover__description", className), ...rest });
2857
+ }
2858
+ function Close2({ className, children, render, ...rest }) {
2859
+ if (children === void 0 && render === void 0) {
2860
+ return /* @__PURE__ */ jsx31(BasePopover.Close, { className: cx("sc-popover__close", className), "aria-label": "Close", ...rest, children: /* @__PURE__ */ jsx31(XIcon, {}) });
2861
+ }
2862
+ return /* @__PURE__ */ jsx31(BasePopover.Close, { className, render, ...rest, children });
2863
+ }
2864
+ var Popover = { Root: Root6, Trigger: Trigger3, Content: Content3, Title: Title2, Description: Description2, Close: Close2 };
2865
+
2866
+ // src/components/BroomIcon/BroomIcon.tsx
2867
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
2868
+ function BroomIcon({ sweeping = false, size = "lg", title, className, ...rest }) {
2869
+ return /* @__PURE__ */ jsxs27(
2870
+ "svg",
2871
+ {
2872
+ className: cx("sc-icon", "sc-broom", className),
2873
+ "data-size": size,
2874
+ "data-sweeping": sweeping || void 0,
2875
+ viewBox: "0 0 24 24",
2876
+ fill: "none",
2877
+ focusable: "false",
2878
+ "aria-hidden": title ? void 0 : true,
2879
+ role: title ? "img" : void 0,
2880
+ "aria-label": title,
2881
+ ...rest,
2882
+ children: [
2883
+ /* @__PURE__ */ jsxs27(
2884
+ "g",
2885
+ {
2886
+ className: "sc-broom__body",
2887
+ fill: "none",
2888
+ stroke: "currentColor",
2889
+ strokeLinecap: "round",
2890
+ strokeLinejoin: "round",
2891
+ children: [
2892
+ /* @__PURE__ */ jsx32("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" }),
2893
+ /* @__PURE__ */ jsx32("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" }),
2894
+ /* @__PURE__ */ jsx32("path", { className: "sc-broom__band", d: "M13.47 12.13 L18.4 13.5 L18.33 14.1 L13.27 12.77 Z" }),
2895
+ /* @__PURE__ */ jsx32("path", { d: "M12.87 13.73 L14.4 14.47 M16.2 15.27 L18.47 15.87" }),
2896
+ /* @__PURE__ */ jsx32("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" })
2897
+ ]
2898
+ }
2899
+ ),
2900
+ /* @__PURE__ */ jsxs27("g", { className: "sc-broom__dust", fill: "none", stroke: "currentColor", children: [
2901
+ /* @__PURE__ */ jsx32("circle", { cx: "4.77", cy: "13.53", r: "0.5" }),
2902
+ /* @__PURE__ */ jsx32("circle", { cx: "2.7", cy: "15.53", r: "0.87" }),
2903
+ /* @__PURE__ */ jsx32("circle", { cx: "4.1", cy: "18.27", r: "0.5" })
2904
+ ] })
2905
+ ]
2906
+ }
2907
+ );
2908
+ }
2909
+
740
2910
  // src/index.ts
741
2911
  var version = "0.1.1";
742
2912
  export {
743
2913
  ArchiveIcon,
2914
+ ArrowDownIcon,
744
2915
  ArrowLeftIcon,
745
2916
  ArrowRightIcon,
2917
+ ArrowUpIcon,
746
2918
  Badge,
2919
+ Banner,
747
2920
  BellIcon,
748
2921
  BriefcaseIcon,
2922
+ BroomIcon,
749
2923
  Button,
750
2924
  CalendarIcon,
751
2925
  Card,
752
2926
  CheckIcon,
2927
+ Checkbox,
753
2928
  ChevronDownIcon,
754
2929
  ChevronLeftIcon,
755
2930
  ChevronRightIcon,
756
2931
  ChevronUpIcon,
2932
+ Chip,
757
2933
  CircleCheckIcon,
758
2934
  CircleXIcon,
759
2935
  ClockIcon,
760
2936
  CopyIcon,
761
2937
  Dialog,
2938
+ Disclosure,
762
2939
  DocumentIcon,
763
2940
  DownloadIcon,
764
2941
  EditIcon,
2942
+ EmptyState,
765
2943
  ExternalLinkIcon,
766
2944
  EyeIcon,
2945
+ FileInput,
767
2946
  FilterIcon,
768
2947
  FlagIcon,
2948
+ Heading,
769
2949
  Icon,
770
2950
  IconButton,
771
2951
  InboxIcon,
772
2952
  InfoIcon,
773
2953
  Inline,
2954
+ Input,
774
2955
  Kbd,
775
2956
  LinkIcon,
776
2957
  MailIcon,
@@ -784,14 +2965,29 @@ export {
784
2965
  PauseIcon,
785
2966
  PlayIcon,
786
2967
  PlusIcon,
2968
+ Popover,
2969
+ PriorityNav,
2970
+ Progress,
787
2971
  RefreshIcon,
788
2972
  SearchIcon,
2973
+ Select,
2974
+ SelectionBar,
789
2975
  SettingsIcon,
2976
+ Skeleton,
2977
+ Spinner,
790
2978
  Stack,
791
2979
  StarIcon,
2980
+ Stat,
792
2981
  SunIcon,
2982
+ Switch,
2983
+ Table,
2984
+ Tabs,
2985
+ Text,
2986
+ Textarea,
793
2987
  ThumbsDownIcon,
794
2988
  ThumbsUpIcon,
2989
+ Toast,
2990
+ Toolbar,
795
2991
  Tooltip,
796
2992
  TrashIcon,
797
2993
  UndoIcon,
@@ -799,6 +2995,8 @@ export {
799
2995
  WarningIcon,
800
2996
  XIcon,
801
2997
  iconNames,
2998
+ useRowSelection,
2999
+ useToast,
802
3000
  version
803
3001
  };
804
3002
  //# sourceMappingURL=index.js.map