@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/README.md +31 -19
- package/dist/index.d.ts +1177 -42
- package/dist/index.js +1900 -43
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3000 -69
- package/package.json +6 -5
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
|
-
|
|
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 =
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
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
|
|
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(
|
|
1062
|
-
|
|
1063
|
-
|
|
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(
|
|
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] =
|
|
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
|
|
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 ? "" :
|
|
1367
|
+
"data-truncate": truncate === true ? "" : clamp2 !== void 0 ? "clamp" : void 0,
|
|
1290
1368
|
"data-numeric": numeric || void 0,
|
|
1291
|
-
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) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[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
|