@geomak/ui 7.8.0 → 7.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +767 -515
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -6
- package/dist/index.d.ts +48 -6
- package/dist/index.js +424 -172
- package/dist/index.js.map +1 -1
- package/dist/styles.css +16 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var chunk4V4U2W7K_cjs = require('./chunk-4V4U2W7K.cjs');
|
|
4
4
|
var chunkCNUDNGJM_cjs = require('./chunk-CNUDNGJM.cjs');
|
|
5
|
-
var
|
|
5
|
+
var React36 = require('react');
|
|
6
6
|
var reactDom = require('react-dom');
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
var AvatarPrimitive = require('@radix-ui/react-avatar');
|
|
@@ -41,7 +41,7 @@ function _interopNamespace(e) {
|
|
|
41
41
|
return Object.freeze(n);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
var
|
|
44
|
+
var React36__default = /*#__PURE__*/_interopDefault(React36);
|
|
45
45
|
var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
|
|
46
46
|
var DropdownMenu2__namespace = /*#__PURE__*/_interopNamespace(DropdownMenu2);
|
|
47
47
|
var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
|
|
@@ -67,8 +67,8 @@ function cx(...values) {
|
|
|
67
67
|
return out;
|
|
68
68
|
}
|
|
69
69
|
function Portal({ children, target }) {
|
|
70
|
-
const [resolved, setResolved] =
|
|
71
|
-
|
|
70
|
+
const [resolved, setResolved] = React36.useState(null);
|
|
71
|
+
React36.useEffect(() => {
|
|
72
72
|
if (target === null) {
|
|
73
73
|
setResolved(null);
|
|
74
74
|
return;
|
|
@@ -489,7 +489,7 @@ function Typography({
|
|
|
489
489
|
}
|
|
490
490
|
);
|
|
491
491
|
}
|
|
492
|
-
var IconButton =
|
|
492
|
+
var IconButton = React36__default.default.forwardRef(function IconButton2({
|
|
493
493
|
icon,
|
|
494
494
|
onClick,
|
|
495
495
|
type = "primary",
|
|
@@ -502,7 +502,7 @@ var IconButton = React34__default.default.forwardRef(function IconButton2({
|
|
|
502
502
|
className = "",
|
|
503
503
|
style
|
|
504
504
|
}, ref) {
|
|
505
|
-
const colorScheme =
|
|
505
|
+
const colorScheme = React36.useMemo(() => {
|
|
506
506
|
if (type === "primary") {
|
|
507
507
|
return "bg-accent text-accent-fg hover:bg-accent-hover";
|
|
508
508
|
}
|
|
@@ -598,7 +598,7 @@ var SIZE_CLASSES = {
|
|
|
598
598
|
md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
|
|
599
599
|
lg: "h-11 px-5 text-sm gap-2 rounded-xl"
|
|
600
600
|
};
|
|
601
|
-
var Button =
|
|
601
|
+
var Button = React36__default.default.forwardRef(function Button2({
|
|
602
602
|
content,
|
|
603
603
|
variant = "primary",
|
|
604
604
|
size = "md",
|
|
@@ -706,7 +706,7 @@ function MenuButton({
|
|
|
706
706
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
707
707
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
|
|
708
708
|
].join(" "),
|
|
709
|
-
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
709
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
|
|
710
710
|
item.separatorBefore && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu2__namespace.Separator, { className: "my-1 h-px bg-border" }),
|
|
711
711
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
712
712
|
DropdownMenu2__namespace.Item,
|
|
@@ -729,6 +729,10 @@ function MenuButton({
|
|
|
729
729
|
) })
|
|
730
730
|
] });
|
|
731
731
|
}
|
|
732
|
+
var DialogContainerContext = React36.createContext(null);
|
|
733
|
+
function useDialogContainer() {
|
|
734
|
+
return React36.useContext(DialogContainerContext);
|
|
735
|
+
}
|
|
732
736
|
var SIZE_MAP = {
|
|
733
737
|
sm: 400,
|
|
734
738
|
md: 600,
|
|
@@ -753,6 +757,7 @@ function Modal({
|
|
|
753
757
|
className = ""
|
|
754
758
|
}) {
|
|
755
759
|
const reduced = framerMotion.useReducedMotion();
|
|
760
|
+
const [panelEl, setPanelEl] = React36.useState(null);
|
|
756
761
|
const maxWidth = width ?? SIZE_MAP[size];
|
|
757
762
|
return /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Root, { open, onOpenChange: (next) => {
|
|
758
763
|
if (!next) onClose?.();
|
|
@@ -770,6 +775,7 @@ function Modal({
|
|
|
770
775
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Content, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
771
776
|
framerMotion.motion.div,
|
|
772
777
|
{
|
|
778
|
+
ref: setPanelEl,
|
|
773
779
|
className: `fixed left-1/2 top-1/2 z-modal flex flex-col w-[calc(100%-2rem)] max-h-[90dvh] bg-surface rounded-2xl shadow-xl overflow-hidden focus:outline-none ${className}`.trim(),
|
|
774
780
|
style: {
|
|
775
781
|
maxWidth,
|
|
@@ -797,7 +803,7 @@ function Modal({
|
|
|
797
803
|
}
|
|
798
804
|
) })
|
|
799
805
|
] }),
|
|
800
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children }),
|
|
806
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: /* @__PURE__ */ jsxRuntime.jsx(DialogContainerContext.Provider, { value: panelEl, children }) }),
|
|
801
807
|
hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-border px-5 py-3", children: [
|
|
802
808
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
803
809
|
Button_default,
|
|
@@ -848,6 +854,7 @@ function Drawer({
|
|
|
848
854
|
className = ""
|
|
849
855
|
}) {
|
|
850
856
|
const reduced = framerMotion.useReducedMotion();
|
|
857
|
+
const [panelEl, setPanelEl] = React36.useState(null);
|
|
851
858
|
const isRight = placement === "right";
|
|
852
859
|
const hiddenX = isRight ? "100%" : "-100%";
|
|
853
860
|
const resolvedWidth = width ?? SIZE_MAP2[size];
|
|
@@ -868,6 +875,7 @@ function Drawer({
|
|
|
868
875
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Content, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
869
876
|
framerMotion.motion.div,
|
|
870
877
|
{
|
|
878
|
+
ref: setPanelEl,
|
|
871
879
|
className: `fixed top-0 bottom-0 ${isRight ? "right-0" : "left-0"} z-modal flex flex-col bg-surface shadow-xl focus:outline-none ${className}`.trim(),
|
|
872
880
|
style: { width: `min(calc(100vw - 1rem), ${widthCss})` },
|
|
873
881
|
initial: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
|
|
@@ -894,7 +902,7 @@ function Drawer({
|
|
|
894
902
|
}
|
|
895
903
|
) })
|
|
896
904
|
] }),
|
|
897
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5", children }),
|
|
905
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5", children: /* @__PURE__ */ jsxRuntime.jsx(DialogContainerContext.Provider, { value: panelEl, children }) }),
|
|
898
906
|
hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-shrink-0 items-center gap-3 border-t border-border px-5 py-3 ${isRight ? "justify-start" : "justify-end"}`, children: [
|
|
899
907
|
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { style: { width: 90 }, variant: cancelVariant, content: cancelText, onClick: onCancel }),
|
|
900
908
|
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { style: { width: 90 }, variant: okVariant, content: okText, onClick: onOk })
|
|
@@ -955,9 +963,9 @@ function Tooltip({
|
|
|
955
963
|
] }) });
|
|
956
964
|
}
|
|
957
965
|
var TooltipProvider = TooltipPrimitive__namespace.Provider;
|
|
958
|
-
var TabsContext =
|
|
966
|
+
var TabsContext = React36.createContext(null);
|
|
959
967
|
function useTabsContext() {
|
|
960
|
-
const ctx =
|
|
968
|
+
const ctx = React36.useContext(TabsContext);
|
|
961
969
|
if (!ctx) throw new Error("Tabs.List / Tabs.Trigger / Tabs.Panel must be rendered inside <Tabs>.");
|
|
962
970
|
return ctx;
|
|
963
971
|
}
|
|
@@ -979,26 +987,26 @@ function Tabs({
|
|
|
979
987
|
children
|
|
980
988
|
}) {
|
|
981
989
|
const isControlled = value !== void 0;
|
|
982
|
-
const [internal, setInternal] =
|
|
990
|
+
const [internal, setInternal] = React36.useState(defaultValue);
|
|
983
991
|
const current = isControlled ? value : internal;
|
|
984
992
|
const reduced = !!framerMotion.useReducedMotion();
|
|
985
|
-
const indicatorId =
|
|
986
|
-
const select =
|
|
993
|
+
const indicatorId = React36.useId();
|
|
994
|
+
const select = React36.useCallback((next) => {
|
|
987
995
|
if (!isControlled) setInternal(next);
|
|
988
996
|
onChange?.(next);
|
|
989
997
|
}, [isControlled, onChange]);
|
|
990
|
-
const registry =
|
|
991
|
-
const orderRef =
|
|
992
|
-
const [, bump] =
|
|
993
|
-
const registerTab =
|
|
998
|
+
const registry = React36.useRef(/* @__PURE__ */ new Map());
|
|
999
|
+
const orderRef = React36.useRef(0);
|
|
1000
|
+
const [, bump] = React36.useState(0);
|
|
1001
|
+
const registerTab = React36.useCallback((val, meta) => {
|
|
994
1002
|
const existing = registry.current.get(val);
|
|
995
1003
|
registry.current.set(val, { ...meta, order: existing?.order ?? orderRef.current++ });
|
|
996
1004
|
if (!existing) bump((v) => v + 1);
|
|
997
1005
|
}, []);
|
|
998
|
-
const unregisterTab =
|
|
1006
|
+
const unregisterTab = React36.useCallback((val) => {
|
|
999
1007
|
if (registry.current.delete(val)) bump((v) => v + 1);
|
|
1000
1008
|
}, []);
|
|
1001
|
-
const getTabs =
|
|
1009
|
+
const getTabs = React36.useCallback(() => [...registry.current.entries()].sort((a, b) => a[1].order - b[1].order).map(([val, m]) => ({ value: val, label: m.label, icon: m.icon, disabled: m.disabled })), []);
|
|
1002
1010
|
return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, variant, size, orientation, indicatorId, reduced, select, registerTab, unregisterTab, getTabs }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1003
1011
|
TabsPrimitive__namespace.Root,
|
|
1004
1012
|
{
|
|
@@ -1018,10 +1026,10 @@ function Tabs({
|
|
|
1018
1026
|
function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
|
|
1019
1027
|
const { variant, orientation, reduced, value } = useTabsContext();
|
|
1020
1028
|
const horizontal = orientation === "horizontal";
|
|
1021
|
-
const scrollRef =
|
|
1022
|
-
const [edges, setEdges] =
|
|
1029
|
+
const scrollRef = React36.useRef(null);
|
|
1030
|
+
const [edges, setEdges] = React36.useState({ start: false, end: false });
|
|
1023
1031
|
const scrollable = variant !== "segmented";
|
|
1024
|
-
|
|
1032
|
+
React36.useLayoutEffect(() => {
|
|
1025
1033
|
const el = scrollRef.current;
|
|
1026
1034
|
if (!el || !scrollable) return;
|
|
1027
1035
|
const update = () => {
|
|
@@ -1046,13 +1054,13 @@ function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
|
|
|
1046
1054
|
ro.disconnect();
|
|
1047
1055
|
};
|
|
1048
1056
|
}, [horizontal, scrollable, children]);
|
|
1049
|
-
const nudge =
|
|
1057
|
+
const nudge = React36.useCallback((dir) => {
|
|
1050
1058
|
const el = scrollRef.current;
|
|
1051
1059
|
if (!el) return;
|
|
1052
1060
|
const amount = (horizontal ? el.clientWidth : el.clientHeight) * 0.7 * dir;
|
|
1053
1061
|
el.scrollBy({ [horizontal ? "left" : "top"]: amount, behavior: reduced ? "auto" : "smooth" });
|
|
1054
1062
|
}, [horizontal, reduced]);
|
|
1055
|
-
|
|
1063
|
+
React36.useLayoutEffect(() => {
|
|
1056
1064
|
const el = scrollRef.current;
|
|
1057
1065
|
if (!el || !scrollable) return;
|
|
1058
1066
|
const active = el.querySelector("[role=tab][data-state=active]");
|
|
@@ -1110,9 +1118,9 @@ function Chevron2({ side, orientation, onClick }) {
|
|
|
1110
1118
|
function OverflowMenu() {
|
|
1111
1119
|
const { getTabs, value, select, orientation } = useTabsContext();
|
|
1112
1120
|
const horizontal = orientation === "horizontal";
|
|
1113
|
-
const [open, setOpen] =
|
|
1114
|
-
const wrapRef =
|
|
1115
|
-
const timer =
|
|
1121
|
+
const [open, setOpen] = React36.useState(false);
|
|
1122
|
+
const wrapRef = React36.useRef(null);
|
|
1123
|
+
const timer = React36.useRef(null);
|
|
1116
1124
|
const openNow = () => {
|
|
1117
1125
|
if (timer.current) clearTimeout(timer.current);
|
|
1118
1126
|
setOpen(true);
|
|
@@ -1120,7 +1128,7 @@ function OverflowMenu() {
|
|
|
1120
1128
|
const closeSoon = () => {
|
|
1121
1129
|
timer.current = setTimeout(() => setOpen(false), 160);
|
|
1122
1130
|
};
|
|
1123
|
-
|
|
1131
|
+
React36.useLayoutEffect(() => {
|
|
1124
1132
|
if (!open) return;
|
|
1125
1133
|
const onDoc = (e) => {
|
|
1126
1134
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -1201,7 +1209,7 @@ function TabsTrigger({ value, icon, badge, closeable, onClose, disabled, classNa
|
|
|
1201
1209
|
const isActive = active === value;
|
|
1202
1210
|
const horizontal = orientation === "horizontal";
|
|
1203
1211
|
const sz = SIZE[size];
|
|
1204
|
-
|
|
1212
|
+
React36.useLayoutEffect(() => {
|
|
1205
1213
|
registerTab(value, { label: children, icon, disabled });
|
|
1206
1214
|
return () => unregisterTab(value);
|
|
1207
1215
|
}, [value, children, icon, disabled, registerTab, unregisterTab]);
|
|
@@ -1400,7 +1408,7 @@ function Tree({
|
|
|
1400
1408
|
item.key
|
|
1401
1409
|
)) });
|
|
1402
1410
|
}
|
|
1403
|
-
var AccordionCtx =
|
|
1411
|
+
var AccordionCtx = React36.createContext({ variant: "separated" });
|
|
1404
1412
|
function Accordion2({
|
|
1405
1413
|
children,
|
|
1406
1414
|
type = "single",
|
|
@@ -1459,7 +1467,7 @@ var Chevron3 = /* @__PURE__ */ jsxRuntime.jsx(
|
|
|
1459
1467
|
}
|
|
1460
1468
|
);
|
|
1461
1469
|
function AccordionItem({ value, title, icon, children, disabled, className = "" }) {
|
|
1462
|
-
const { variant } =
|
|
1470
|
+
const { variant } = React36.useContext(AccordionCtx);
|
|
1463
1471
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1464
1472
|
AccordionPrimitive__namespace.Item,
|
|
1465
1473
|
{
|
|
@@ -1518,7 +1526,7 @@ function Breadcrumbs({
|
|
|
1518
1526
|
className = "",
|
|
1519
1527
|
style
|
|
1520
1528
|
}) {
|
|
1521
|
-
const [expanded, setExpanded] =
|
|
1529
|
+
const [expanded, setExpanded] = React36.useState(false);
|
|
1522
1530
|
const shouldCollapse = maxItems > 0 && items.length > maxItems && !expanded;
|
|
1523
1531
|
const visible = [];
|
|
1524
1532
|
if (shouldCollapse) {
|
|
@@ -1743,8 +1751,8 @@ function Stepper({
|
|
|
1743
1751
|
className = ""
|
|
1744
1752
|
}) {
|
|
1745
1753
|
const reduced = framerMotion.useReducedMotion();
|
|
1746
|
-
const [forcedVertical, setForcedVertical] =
|
|
1747
|
-
|
|
1754
|
+
const [forcedVertical, setForcedVertical] = React36.useState(false);
|
|
1755
|
+
React36.useEffect(() => {
|
|
1748
1756
|
if (!responsive || orientation === "vertical") return;
|
|
1749
1757
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1750
1758
|
const mq = window.matchMedia("(max-width: 767px)");
|
|
@@ -1853,7 +1861,7 @@ function Kbd({
|
|
|
1853
1861
|
style
|
|
1854
1862
|
}) {
|
|
1855
1863
|
if (keys && keys.length > 0) {
|
|
1856
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx("inline-flex items-center gap-1", className), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1864
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx("inline-flex items-center gap-1", className), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
|
|
1857
1865
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
|
|
1858
1866
|
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
|
|
1859
1867
|
] }, `${k}-${i}`)) });
|
|
@@ -1944,13 +1952,13 @@ function FlatCarousel({
|
|
|
1944
1952
|
className = "",
|
|
1945
1953
|
style
|
|
1946
1954
|
}) {
|
|
1947
|
-
const scrollerRef =
|
|
1948
|
-
const slides =
|
|
1949
|
-
const [active, setActive] =
|
|
1950
|
-
const [atStart, setAtStart] =
|
|
1951
|
-
const [atEnd, setAtEnd] =
|
|
1955
|
+
const scrollerRef = React36.useRef(null);
|
|
1956
|
+
const slides = React36__default.default.Children.toArray(children);
|
|
1957
|
+
const [active, setActive] = React36.useState(0);
|
|
1958
|
+
const [atStart, setAtStart] = React36.useState(true);
|
|
1959
|
+
const [atEnd, setAtEnd] = React36.useState(false);
|
|
1952
1960
|
const width = typeof itemWidth === "number" ? `${itemWidth}px` : itemWidth;
|
|
1953
|
-
const update =
|
|
1961
|
+
const update = React36.useCallback(() => {
|
|
1954
1962
|
const el = scrollerRef.current;
|
|
1955
1963
|
if (!el) return;
|
|
1956
1964
|
setAtStart(el.scrollLeft <= 1);
|
|
@@ -1959,7 +1967,7 @@ function FlatCarousel({
|
|
|
1959
1967
|
const slideW = first ? first.getBoundingClientRect().width + gap : el.clientWidth;
|
|
1960
1968
|
setActive(Math.round(el.scrollLeft / slideW));
|
|
1961
1969
|
}, [gap]);
|
|
1962
|
-
|
|
1970
|
+
React36.useEffect(() => {
|
|
1963
1971
|
update();
|
|
1964
1972
|
const el = scrollerRef.current;
|
|
1965
1973
|
if (!el) return;
|
|
@@ -2000,9 +2008,9 @@ function RotatingCarousel({
|
|
|
2000
2008
|
className = "",
|
|
2001
2009
|
style
|
|
2002
2010
|
}) {
|
|
2003
|
-
const slides =
|
|
2011
|
+
const slides = React36__default.default.Children.toArray(children);
|
|
2004
2012
|
const count = slides.length;
|
|
2005
|
-
const [active, setActive] =
|
|
2013
|
+
const [active, setActive] = React36.useState(0);
|
|
2006
2014
|
const reduced = framerMotion.useReducedMotion();
|
|
2007
2015
|
const wrap = (n) => count > 0 ? (n % count + count) % count : 0;
|
|
2008
2016
|
const idx = wrap(active);
|
|
@@ -2240,13 +2248,13 @@ function Chat({
|
|
|
2240
2248
|
className = "",
|
|
2241
2249
|
style
|
|
2242
2250
|
}) {
|
|
2243
|
-
const listRef =
|
|
2244
|
-
const atBottomRef =
|
|
2245
|
-
const [showJump, setShowJump] =
|
|
2246
|
-
const [draft, setDraft] =
|
|
2251
|
+
const listRef = React36.useRef(null);
|
|
2252
|
+
const atBottomRef = React36.useRef(true);
|
|
2253
|
+
const [showJump, setShowJump] = React36.useState(false);
|
|
2254
|
+
const [draft, setDraft] = React36.useState("");
|
|
2247
2255
|
const hasHeader = title != null || subtitle != null || avatar != null || headerActions != null;
|
|
2248
2256
|
const isTyping = typingNames.length > 0;
|
|
2249
|
-
const scrollToBottom =
|
|
2257
|
+
const scrollToBottom = React36.useCallback((smooth = true) => {
|
|
2250
2258
|
const el = listRef.current;
|
|
2251
2259
|
if (!el) return;
|
|
2252
2260
|
if (typeof el.scrollTo === "function") el.scrollTo({ top: el.scrollHeight, behavior: smooth ? "smooth" : "auto" });
|
|
@@ -2259,10 +2267,10 @@ function Chat({
|
|
|
2259
2267
|
atBottomRef.current = near;
|
|
2260
2268
|
setShowJump(!near);
|
|
2261
2269
|
};
|
|
2262
|
-
|
|
2270
|
+
React36.useEffect(() => {
|
|
2263
2271
|
if (atBottomRef.current) scrollToBottom(messages.length > 0);
|
|
2264
2272
|
}, [messages.length, isTyping]);
|
|
2265
|
-
|
|
2273
|
+
React36.useEffect(() => {
|
|
2266
2274
|
scrollToBottom(false);
|
|
2267
2275
|
}, [scrollToBottom]);
|
|
2268
2276
|
const send = () => {
|
|
@@ -2452,7 +2460,7 @@ function FAB({
|
|
|
2452
2460
|
className = "",
|
|
2453
2461
|
style
|
|
2454
2462
|
}) {
|
|
2455
|
-
const [open, setOpen] =
|
|
2463
|
+
const [open, setOpen] = React36.useState(false);
|
|
2456
2464
|
const reduced = framerMotion.useReducedMotion();
|
|
2457
2465
|
const hasDial = !!actions && actions.length > 0;
|
|
2458
2466
|
const bottom = position.startsWith("bottom");
|
|
@@ -2554,8 +2562,8 @@ function PopConfirm({
|
|
|
2554
2562
|
onOpenChange,
|
|
2555
2563
|
className = ""
|
|
2556
2564
|
}) {
|
|
2557
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
2558
|
-
const [loading, setLoading] =
|
|
2565
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React36.useState(false);
|
|
2566
|
+
const [loading, setLoading] = React36.useState(false);
|
|
2559
2567
|
const isOpen = open ?? uncontrolledOpen;
|
|
2560
2568
|
const setOpen = (next) => {
|
|
2561
2569
|
onOpenChange?.(next);
|
|
@@ -2658,16 +2666,16 @@ function LogoutTimer({
|
|
|
2658
2666
|
logoutLabel = "Sign out now"
|
|
2659
2667
|
}) {
|
|
2660
2668
|
const reduced = framerMotion.useReducedMotion();
|
|
2661
|
-
const [warning, setWarning] =
|
|
2662
|
-
const [remaining, setRemaining] =
|
|
2663
|
-
const idleTimer =
|
|
2664
|
-
const tick =
|
|
2665
|
-
const deadline =
|
|
2666
|
-
const warningRef =
|
|
2667
|
-
const lastReset =
|
|
2668
|
-
const cbs =
|
|
2669
|
+
const [warning, setWarning] = React36.useState(false);
|
|
2670
|
+
const [remaining, setRemaining] = React36.useState(countdown);
|
|
2671
|
+
const idleTimer = React36.useRef(null);
|
|
2672
|
+
const tick = React36.useRef(null);
|
|
2673
|
+
const deadline = React36.useRef(0);
|
|
2674
|
+
const warningRef = React36.useRef(false);
|
|
2675
|
+
const lastReset = React36.useRef(0);
|
|
2676
|
+
const cbs = React36.useRef({ onLogout, onContinue, onWarning });
|
|
2669
2677
|
cbs.current = { onLogout, onContinue, onWarning };
|
|
2670
|
-
const clearTimers =
|
|
2678
|
+
const clearTimers = React36.useCallback(() => {
|
|
2671
2679
|
if (idleTimer.current) {
|
|
2672
2680
|
clearTimeout(idleTimer.current);
|
|
2673
2681
|
idleTimer.current = null;
|
|
@@ -2677,13 +2685,13 @@ function LogoutTimer({
|
|
|
2677
2685
|
tick.current = null;
|
|
2678
2686
|
}
|
|
2679
2687
|
}, []);
|
|
2680
|
-
const logout =
|
|
2688
|
+
const logout = React36.useCallback(() => {
|
|
2681
2689
|
clearTimers();
|
|
2682
2690
|
warningRef.current = false;
|
|
2683
2691
|
setWarning(false);
|
|
2684
2692
|
cbs.current.onLogout();
|
|
2685
2693
|
}, [clearTimers]);
|
|
2686
|
-
const startIdle =
|
|
2694
|
+
const startIdle = React36.useCallback(() => {
|
|
2687
2695
|
if (idleTimer.current) clearTimeout(idleTimer.current);
|
|
2688
2696
|
idleTimer.current = setTimeout(() => {
|
|
2689
2697
|
warningRef.current = true;
|
|
@@ -2698,7 +2706,7 @@ function LogoutTimer({
|
|
|
2698
2706
|
}, 250);
|
|
2699
2707
|
}, timeout);
|
|
2700
2708
|
}, [timeout, countdown, logout]);
|
|
2701
|
-
const stay =
|
|
2709
|
+
const stay = React36.useCallback(() => {
|
|
2702
2710
|
if (tick.current) {
|
|
2703
2711
|
clearInterval(tick.current);
|
|
2704
2712
|
tick.current = null;
|
|
@@ -2708,7 +2716,7 @@ function LogoutTimer({
|
|
|
2708
2716
|
cbs.current.onContinue?.();
|
|
2709
2717
|
startIdle();
|
|
2710
2718
|
}, [startIdle]);
|
|
2711
|
-
|
|
2719
|
+
React36.useEffect(() => {
|
|
2712
2720
|
if (!enabled) {
|
|
2713
2721
|
clearTimers();
|
|
2714
2722
|
warningRef.current = false;
|
|
@@ -2773,11 +2781,11 @@ function SegmentedControl({
|
|
|
2773
2781
|
"aria-label": ariaLabel
|
|
2774
2782
|
}) {
|
|
2775
2783
|
const sz = SIZE5[size];
|
|
2776
|
-
const groupId =
|
|
2777
|
-
const errorId =
|
|
2784
|
+
const groupId = React36.useId();
|
|
2785
|
+
const errorId = React36.useId();
|
|
2778
2786
|
const hasError = errorMessage != null;
|
|
2779
2787
|
const isControlled = value !== void 0;
|
|
2780
|
-
const [internal, setInternal] =
|
|
2788
|
+
const [internal, setInternal] = React36.useState(defaultValue);
|
|
2781
2789
|
const current = isControlled ? value : internal;
|
|
2782
2790
|
const handle = (v) => {
|
|
2783
2791
|
if (!v) return;
|
|
@@ -2938,22 +2946,22 @@ function Scheduler({
|
|
|
2938
2946
|
style
|
|
2939
2947
|
}) {
|
|
2940
2948
|
const reduced = framerMotion.useReducedMotion();
|
|
2941
|
-
const [view, setView] =
|
|
2942
|
-
const [cursor, setCursor] =
|
|
2943
|
-
const [loaded, setLoaded] =
|
|
2944
|
-
const [loading, setLoading] =
|
|
2945
|
-
const [error, setError] =
|
|
2946
|
-
const [reloadKey, setReloadKey] =
|
|
2947
|
-
const [dir, setDir] =
|
|
2948
|
-
const cbRef =
|
|
2949
|
+
const [view, setView] = React36.useState(defaultView);
|
|
2950
|
+
const [cursor, setCursor] = React36.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
|
|
2951
|
+
const [loaded, setLoaded] = React36.useState([]);
|
|
2952
|
+
const [loading, setLoading] = React36.useState(false);
|
|
2953
|
+
const [error, setError] = React36.useState(null);
|
|
2954
|
+
const [reloadKey, setReloadKey] = React36.useState(0);
|
|
2955
|
+
const [dir, setDir] = React36.useState(0);
|
|
2956
|
+
const cbRef = React36.useRef({ loadEvents, onError });
|
|
2949
2957
|
cbRef.current = { loadEvents, onError };
|
|
2950
|
-
const range =
|
|
2958
|
+
const range = React36.useMemo(
|
|
2951
2959
|
() => view === "month" ? monthRange(cursor) : weekRange(cursor, weekStartsOn),
|
|
2952
2960
|
[view, cursor, weekStartsOn]
|
|
2953
2961
|
);
|
|
2954
2962
|
const fromKey = range.from.getTime();
|
|
2955
2963
|
const toKey = range.to.getTime();
|
|
2956
|
-
|
|
2964
|
+
React36.useEffect(() => {
|
|
2957
2965
|
const { loadEvents: loader, onError: onErr } = cbRef.current;
|
|
2958
2966
|
if (!loader) return;
|
|
2959
2967
|
let cancelled = false;
|
|
@@ -2973,16 +2981,16 @@ function Scheduler({
|
|
|
2973
2981
|
cancelled = true;
|
|
2974
2982
|
};
|
|
2975
2983
|
}, [fromKey, toKey, view, reloadKey]);
|
|
2976
|
-
const retry =
|
|
2977
|
-
const events =
|
|
2984
|
+
const retry = React36.useCallback(() => setReloadKey((k) => k + 1), []);
|
|
2985
|
+
const events = React36.useMemo(
|
|
2978
2986
|
() => (controlledEvents ?? loaded).map(normalize),
|
|
2979
2987
|
[controlledEvents, loaded]
|
|
2980
2988
|
);
|
|
2981
|
-
const go =
|
|
2989
|
+
const go = React36.useCallback((delta) => {
|
|
2982
2990
|
setDir(delta);
|
|
2983
2991
|
setCursor((c) => view === "month" ? addMonths(c, delta) : addDays(c, delta * 7));
|
|
2984
2992
|
}, [view]);
|
|
2985
|
-
const goToday =
|
|
2993
|
+
const goToday = React36.useCallback(() => {
|
|
2986
2994
|
setDir(0);
|
|
2987
2995
|
setCursor(/* @__PURE__ */ new Date());
|
|
2988
2996
|
}, []);
|
|
@@ -3092,9 +3100,9 @@ function SchedulerError({ onRetry }) {
|
|
|
3092
3100
|
] });
|
|
3093
3101
|
}
|
|
3094
3102
|
function MonthYearPicker({ label, cursor, onPick }) {
|
|
3095
|
-
const [open, setOpen] =
|
|
3096
|
-
const [viewYear, setViewYear] =
|
|
3097
|
-
|
|
3103
|
+
const [open, setOpen] = React36.useState(false);
|
|
3104
|
+
const [viewYear, setViewYear] = React36.useState(cursor.getFullYear());
|
|
3105
|
+
React36.useEffect(() => {
|
|
3098
3106
|
if (open) setViewYear(cursor.getFullYear());
|
|
3099
3107
|
}, [open, cursor]);
|
|
3100
3108
|
return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
@@ -3168,8 +3176,8 @@ function MonthView({
|
|
|
3168
3176
|
onSelectSlot,
|
|
3169
3177
|
onSelectEvent
|
|
3170
3178
|
}) {
|
|
3171
|
-
const grid =
|
|
3172
|
-
const eventsByDay =
|
|
3179
|
+
const grid = React36.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
|
|
3180
|
+
const eventsByDay = React36.useMemo(() => bucketByDay(events), [events]);
|
|
3173
3181
|
const labels = weekdayLabels(weekStartsOn);
|
|
3174
3182
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
|
|
3175
3183
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 border-b border-border", children: labels.map((l) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-center text-[11px] font-medium uppercase tracking-wide text-foreground-muted", children: l }, l)) }),
|
|
@@ -3243,12 +3251,12 @@ function WeekView({
|
|
|
3243
3251
|
onSelectSlot,
|
|
3244
3252
|
onSelectEvent
|
|
3245
3253
|
}) {
|
|
3246
|
-
const days =
|
|
3247
|
-
const eventsByDay =
|
|
3248
|
-
const labels =
|
|
3254
|
+
const days = React36.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
|
|
3255
|
+
const eventsByDay = React36.useMemo(() => bucketByDay(events), [events]);
|
|
3256
|
+
const labels = React36.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
|
|
3249
3257
|
const dow = (d) => labels[(d.getDay() - weekStartsOn + 7) % 7];
|
|
3250
3258
|
const [startHour, endHour] = dayHours;
|
|
3251
|
-
const hours =
|
|
3259
|
+
const hours = React36.useMemo(
|
|
3252
3260
|
() => Array.from({ length: endHour - startHour }, (_, i) => startHour + i),
|
|
3253
3261
|
[startHour, endHour]
|
|
3254
3262
|
);
|
|
@@ -3439,17 +3447,17 @@ function Cart({
|
|
|
3439
3447
|
] })
|
|
3440
3448
|
] });
|
|
3441
3449
|
}
|
|
3442
|
-
var CartContext =
|
|
3450
|
+
var CartContext = React36.createContext(null);
|
|
3443
3451
|
var clampQty = (qty, max) => {
|
|
3444
3452
|
const lower = Math.max(1, Math.round(qty));
|
|
3445
3453
|
return max != null ? Math.min(lower, max) : lower;
|
|
3446
3454
|
};
|
|
3447
3455
|
function CartProvider({ children, initialItems = [], onChange }) {
|
|
3448
|
-
const [items, setItems] =
|
|
3449
|
-
|
|
3456
|
+
const [items, setItems] = React36.useState(initialItems);
|
|
3457
|
+
React36.useEffect(() => {
|
|
3450
3458
|
onChange?.(items);
|
|
3451
3459
|
}, [items]);
|
|
3452
|
-
const addToCart =
|
|
3460
|
+
const addToCart = React36.useCallback((item, quantity) => {
|
|
3453
3461
|
const addQty = quantity ?? item.quantity ?? 1;
|
|
3454
3462
|
setItems((prev) => {
|
|
3455
3463
|
const existing = prev.find((it) => it.id === item.id);
|
|
@@ -3462,29 +3470,29 @@ function CartProvider({ children, initialItems = [], onChange }) {
|
|
|
3462
3470
|
return [...prev, { ...rest, quantity: clampQty(addQty, item.max) }];
|
|
3463
3471
|
});
|
|
3464
3472
|
}, []);
|
|
3465
|
-
const removeFromCart =
|
|
3473
|
+
const removeFromCart = React36.useCallback((id) => {
|
|
3466
3474
|
setItems((prev) => prev.filter((it) => it.id !== id));
|
|
3467
3475
|
}, []);
|
|
3468
|
-
const updateQuantity =
|
|
3476
|
+
const updateQuantity = React36.useCallback((id, quantity) => {
|
|
3469
3477
|
setItems(
|
|
3470
3478
|
(prev) => prev.map((it) => it.id === id ? { ...it, quantity: clampQty(quantity, it.max) } : it)
|
|
3471
3479
|
);
|
|
3472
3480
|
}, []);
|
|
3473
|
-
const clearCart =
|
|
3474
|
-
const isInCart =
|
|
3475
|
-
const getItemCount =
|
|
3476
|
-
const getCartTotal =
|
|
3481
|
+
const clearCart = React36.useCallback(() => setItems([]), []);
|
|
3482
|
+
const isInCart = React36.useCallback((id) => items.some((it) => it.id === id), [items]);
|
|
3483
|
+
const getItemCount = React36.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
|
|
3484
|
+
const getCartTotal = React36.useCallback(
|
|
3477
3485
|
() => items.reduce((sum, it) => sum + it.price * it.quantity, 0),
|
|
3478
3486
|
[items]
|
|
3479
3487
|
);
|
|
3480
|
-
const value =
|
|
3488
|
+
const value = React36.useMemo(
|
|
3481
3489
|
() => ({ items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal }),
|
|
3482
3490
|
[items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal]
|
|
3483
3491
|
);
|
|
3484
3492
|
return /* @__PURE__ */ jsxRuntime.jsx(CartContext.Provider, { value, children });
|
|
3485
3493
|
}
|
|
3486
3494
|
function useCart() {
|
|
3487
|
-
const ctx =
|
|
3495
|
+
const ctx = React36.useContext(CartContext);
|
|
3488
3496
|
if (!ctx) {
|
|
3489
3497
|
throw new Error("useCart must be used within a <CartProvider>.");
|
|
3490
3498
|
}
|
|
@@ -3826,11 +3834,11 @@ function buildBindings(store, name, kind, snap) {
|
|
|
3826
3834
|
|
|
3827
3835
|
// src/form/useForm.ts
|
|
3828
3836
|
function useForm(options = {}) {
|
|
3829
|
-
const ref =
|
|
3837
|
+
const ref = React36.useRef(null);
|
|
3830
3838
|
if (ref.current === null) ref.current = new FormStore(options);
|
|
3831
3839
|
const store = ref.current;
|
|
3832
|
-
|
|
3833
|
-
const make =
|
|
3840
|
+
React36.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
3841
|
+
const make = React36.useCallback(
|
|
3834
3842
|
(kind) => (name, rules) => {
|
|
3835
3843
|
if (rules !== void 0) store.setRule(name, rules);
|
|
3836
3844
|
return buildBindings(store, name, kind, store.getFieldSnapshot(name));
|
|
@@ -3860,9 +3868,9 @@ function useForm(options = {}) {
|
|
|
3860
3868
|
fieldTarget: make("target")
|
|
3861
3869
|
};
|
|
3862
3870
|
}
|
|
3863
|
-
var FormContext =
|
|
3871
|
+
var FormContext = React36.createContext(null);
|
|
3864
3872
|
function useFormStore() {
|
|
3865
|
-
const store =
|
|
3873
|
+
const store = React36.useContext(FormContext);
|
|
3866
3874
|
if (!store) {
|
|
3867
3875
|
throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
|
|
3868
3876
|
}
|
|
@@ -3876,8 +3884,8 @@ function Form({
|
|
|
3876
3884
|
children,
|
|
3877
3885
|
...rest
|
|
3878
3886
|
}) {
|
|
3879
|
-
const ref =
|
|
3880
|
-
const bypass =
|
|
3887
|
+
const ref = React36.useRef(null);
|
|
3888
|
+
const bypass = React36.useRef(false);
|
|
3881
3889
|
const handleSubmit = async (e) => {
|
|
3882
3890
|
if (bypass.current) {
|
|
3883
3891
|
bypass.current = false;
|
|
@@ -3934,12 +3942,12 @@ function useFormField(name, options = {}) {
|
|
|
3934
3942
|
const store = useFormStore();
|
|
3935
3943
|
const { kind = "value", rules } = options;
|
|
3936
3944
|
if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
|
|
3937
|
-
|
|
3945
|
+
React36.useEffect(() => {
|
|
3938
3946
|
return () => {
|
|
3939
3947
|
if (rules !== void 0) store.removeRule(name);
|
|
3940
3948
|
};
|
|
3941
3949
|
}, [store, name]);
|
|
3942
|
-
const snap =
|
|
3950
|
+
const snap = React36.useSyncExternalStore(
|
|
3943
3951
|
store.subscribe,
|
|
3944
3952
|
() => store.getFieldSnapshot(name)
|
|
3945
3953
|
);
|
|
@@ -3951,7 +3959,7 @@ function FormField({ name, kind, rules, children }) {
|
|
|
3951
3959
|
}
|
|
3952
3960
|
function useFieldArray(name) {
|
|
3953
3961
|
const store = useFormStore();
|
|
3954
|
-
|
|
3962
|
+
React36.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
3955
3963
|
const arr = store.getValue(name) ?? [];
|
|
3956
3964
|
const keys = store.getKeys(name);
|
|
3957
3965
|
return {
|
|
@@ -3984,7 +3992,7 @@ function TextInput({
|
|
|
3984
3992
|
suffix,
|
|
3985
3993
|
id
|
|
3986
3994
|
}) {
|
|
3987
|
-
const errorId =
|
|
3995
|
+
const errorId = React36.useId();
|
|
3988
3996
|
const hasError = errorMessage != null;
|
|
3989
3997
|
const hasAdornment = prefix != null || suffix != null;
|
|
3990
3998
|
const inputId = htmlFor ?? id;
|
|
@@ -4145,7 +4153,7 @@ function CreditCardForm({
|
|
|
4145
4153
|
className = "",
|
|
4146
4154
|
style
|
|
4147
4155
|
}) {
|
|
4148
|
-
const initial =
|
|
4156
|
+
const initial = React36.useRef({
|
|
4149
4157
|
number: formatCardNumber(defaultValue?.number ?? ""),
|
|
4150
4158
|
name: defaultValue?.name ?? "",
|
|
4151
4159
|
expiry: formatExpiry(defaultValue?.expiry ?? ""),
|
|
@@ -4154,7 +4162,7 @@ function CreditCardForm({
|
|
|
4154
4162
|
const form = useForm({ initialValues: initial });
|
|
4155
4163
|
const numberStr = String(form.values.number ?? "");
|
|
4156
4164
|
const brand = detectBrand(numberStr);
|
|
4157
|
-
|
|
4165
|
+
React36.useEffect(() => {
|
|
4158
4166
|
onChange?.(toCard(form.values));
|
|
4159
4167
|
}, [form.values.number, form.values.name, form.values.expiry, form.values.cvv]);
|
|
4160
4168
|
const numberBind = form.fieldNative("number", {
|
|
@@ -4277,7 +4285,7 @@ function Checkout({
|
|
|
4277
4285
|
] })
|
|
4278
4286
|
] });
|
|
4279
4287
|
}
|
|
4280
|
-
var NotificationContext =
|
|
4288
|
+
var NotificationContext = React36.createContext({
|
|
4281
4289
|
open: () => void 0,
|
|
4282
4290
|
close: () => void 0
|
|
4283
4291
|
});
|
|
@@ -4335,26 +4343,26 @@ function NotificationItem({
|
|
|
4335
4343
|
onClose,
|
|
4336
4344
|
reduced
|
|
4337
4345
|
}) {
|
|
4338
|
-
const [paused, setPaused] =
|
|
4346
|
+
const [paused, setPaused] = React36.useState(false);
|
|
4339
4347
|
const duration = n.duration ?? 4e3;
|
|
4340
4348
|
const isAutoDismissing = isFinite(duration) && duration > 0;
|
|
4341
4349
|
const showProgress = !reduced && isAutoDismissing;
|
|
4342
|
-
const timerRef =
|
|
4343
|
-
const startTimeRef =
|
|
4344
|
-
const remainingRef =
|
|
4345
|
-
const clearTimer =
|
|
4350
|
+
const timerRef = React36.useRef(null);
|
|
4351
|
+
const startTimeRef = React36.useRef(0);
|
|
4352
|
+
const remainingRef = React36.useRef(duration);
|
|
4353
|
+
const clearTimer = React36.useCallback(() => {
|
|
4346
4354
|
if (timerRef.current !== null) {
|
|
4347
4355
|
clearTimeout(timerRef.current);
|
|
4348
4356
|
timerRef.current = null;
|
|
4349
4357
|
}
|
|
4350
4358
|
}, []);
|
|
4351
|
-
const scheduleDismiss =
|
|
4359
|
+
const scheduleDismiss = React36.useCallback((ms) => {
|
|
4352
4360
|
clearTimer();
|
|
4353
4361
|
if (!isAutoDismissing) return;
|
|
4354
4362
|
startTimeRef.current = Date.now();
|
|
4355
4363
|
timerRef.current = setTimeout(() => onClose(n.id), ms);
|
|
4356
4364
|
}, [clearTimer, isAutoDismissing, n.id, onClose]);
|
|
4357
|
-
|
|
4365
|
+
React36.useEffect(() => {
|
|
4358
4366
|
if (paused || !isAutoDismissing) return;
|
|
4359
4367
|
scheduleDismiss(remainingRef.current);
|
|
4360
4368
|
return clearTimer;
|
|
@@ -4437,15 +4445,15 @@ function NotificationProvider({
|
|
|
4437
4445
|
children,
|
|
4438
4446
|
position = "top-right"
|
|
4439
4447
|
}) {
|
|
4440
|
-
const [notifications, setNotifications] =
|
|
4448
|
+
const [notifications, setNotifications] = React36.useState([]);
|
|
4441
4449
|
const reduced = framerMotion.useReducedMotion();
|
|
4442
|
-
const open =
|
|
4450
|
+
const open = React36.useCallback((payload) => {
|
|
4443
4451
|
setNotifications((prev) => [
|
|
4444
4452
|
...prev,
|
|
4445
4453
|
{ duration: 4e3, ...payload, id: Date.now() + Math.random() }
|
|
4446
4454
|
]);
|
|
4447
4455
|
}, []);
|
|
4448
|
-
const close =
|
|
4456
|
+
const close = React36.useCallback((id) => {
|
|
4449
4457
|
setNotifications((prev) => prev.filter((n) => n.id !== id));
|
|
4450
4458
|
}, []);
|
|
4451
4459
|
return /* @__PURE__ */ jsxRuntime.jsxs(NotificationContext.Provider, { value: { open, close }, children: [
|
|
@@ -4474,7 +4482,7 @@ function NotificationProvider({
|
|
|
4474
4482
|
] });
|
|
4475
4483
|
}
|
|
4476
4484
|
function useNotification() {
|
|
4477
|
-
const { open } =
|
|
4485
|
+
const { open } = React36.useContext(NotificationContext);
|
|
4478
4486
|
return {
|
|
4479
4487
|
info: (props) => open({ type: "info", ...props }),
|
|
4480
4488
|
success: (props) => open({ type: "success", ...props }),
|
|
@@ -4591,10 +4599,10 @@ function FadingBase({
|
|
|
4591
4599
|
isMounted = false,
|
|
4592
4600
|
children
|
|
4593
4601
|
}) {
|
|
4594
|
-
const [shouldRender, setShouldRender] =
|
|
4595
|
-
const [visible, setVisible] =
|
|
4596
|
-
const timerRef =
|
|
4597
|
-
|
|
4602
|
+
const [shouldRender, setShouldRender] = React36.useState(isMounted);
|
|
4603
|
+
const [visible, setVisible] = React36.useState(false);
|
|
4604
|
+
const timerRef = React36.useRef(null);
|
|
4605
|
+
React36.useEffect(() => {
|
|
4598
4606
|
if (isMounted) {
|
|
4599
4607
|
setShouldRender(true);
|
|
4600
4608
|
const rafId = requestAnimationFrame(() => setVisible(true));
|
|
@@ -4706,14 +4714,14 @@ function ScalableContainer({
|
|
|
4706
4714
|
togglePosition = "top-right",
|
|
4707
4715
|
className = ""
|
|
4708
4716
|
}) {
|
|
4709
|
-
const containerRef =
|
|
4710
|
-
const [internalScaled, setInternalScaled] =
|
|
4717
|
+
const containerRef = React36.useRef(null);
|
|
4718
|
+
const [internalScaled, setInternalScaled] = React36.useState(false);
|
|
4711
4719
|
const isScaled = expanded ?? internalScaled;
|
|
4712
4720
|
const reduced = framerMotion.useReducedMotion();
|
|
4713
|
-
const prevScaled =
|
|
4721
|
+
const prevScaled = React36.useRef(isScaled);
|
|
4714
4722
|
const expandW = targetWidth ?? expandedWidth;
|
|
4715
4723
|
const expandH = targetHeight ?? expandedHeight;
|
|
4716
|
-
|
|
4724
|
+
React36.useEffect(() => {
|
|
4717
4725
|
if (isScaled === prevScaled.current) return;
|
|
4718
4726
|
prevScaled.current = isScaled;
|
|
4719
4727
|
if (typeof window === "undefined") return;
|
|
@@ -4860,17 +4868,17 @@ function CatalogGrid({ items, buttonText, onOpen, className = "" }) {
|
|
|
4860
4868
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex flex-wrap gap-2 ${className}`.trim(), children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(GridCard, { item, buttonText, onOpen }, item.key)) });
|
|
4861
4869
|
}
|
|
4862
4870
|
function CatalogCarousel({ items, buttonText, onOpen, className = "" }) {
|
|
4863
|
-
const [activeIndex, setActiveIndex] =
|
|
4864
|
-
const [indexPool, setIndexPool] =
|
|
4865
|
-
const cardRefs =
|
|
4866
|
-
const getIndexes =
|
|
4871
|
+
const [activeIndex, setActiveIndex] = React36.useState(0);
|
|
4872
|
+
const [indexPool, setIndexPool] = React36.useState([]);
|
|
4873
|
+
const cardRefs = React36.useRef([]);
|
|
4874
|
+
const getIndexes = React36.useMemo(() => {
|
|
4867
4875
|
let nextIndex = activeIndex + 1;
|
|
4868
4876
|
let previousIndex = activeIndex - 1;
|
|
4869
4877
|
if (activeIndex === 0) previousIndex = items.length - 1;
|
|
4870
4878
|
if (activeIndex === items.length - 1) nextIndex = 0;
|
|
4871
4879
|
return { previousIndex, nextIndex };
|
|
4872
4880
|
}, [activeIndex, items.length]);
|
|
4873
|
-
|
|
4881
|
+
React36.useEffect(() => {
|
|
4874
4882
|
const { nextIndex, previousIndex } = getIndexes;
|
|
4875
4883
|
let indexes = [previousIndex, activeIndex, nextIndex];
|
|
4876
4884
|
if (activeIndex !== 0 && activeIndex !== items.length - 1) {
|
|
@@ -5043,8 +5051,8 @@ function writeDismissed(key) {
|
|
|
5043
5051
|
}
|
|
5044
5052
|
}
|
|
5045
5053
|
function useTargetBbox(ref) {
|
|
5046
|
-
const [bbox, setBbox] =
|
|
5047
|
-
|
|
5054
|
+
const [bbox, setBbox] = React36.useState(null);
|
|
5055
|
+
React36.useLayoutEffect(() => {
|
|
5048
5056
|
const el = ref?.current;
|
|
5049
5057
|
if (!el) {
|
|
5050
5058
|
setBbox(null);
|
|
@@ -5074,7 +5082,7 @@ function tooltipStyleFor(bbox, placement) {
|
|
|
5074
5082
|
return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
|
|
5075
5083
|
}
|
|
5076
5084
|
function useFocusTrap(containerRef, active) {
|
|
5077
|
-
|
|
5085
|
+
React36.useEffect(() => {
|
|
5078
5086
|
if (!active) return;
|
|
5079
5087
|
const el = containerRef.current;
|
|
5080
5088
|
if (!el) return;
|
|
@@ -5113,16 +5121,16 @@ function Wizard({
|
|
|
5113
5121
|
onComplete,
|
|
5114
5122
|
onSkip
|
|
5115
5123
|
}) {
|
|
5116
|
-
const tooltipRef =
|
|
5117
|
-
const tooltipTitleId =
|
|
5118
|
-
const tooltipBodyId =
|
|
5124
|
+
const tooltipRef = React36.useRef(null);
|
|
5125
|
+
const tooltipTitleId = React36.useId();
|
|
5126
|
+
const tooltipBodyId = React36.useId();
|
|
5119
5127
|
const reduced = framerMotion.useReducedMotion();
|
|
5120
|
-
const [open, setOpen] =
|
|
5121
|
-
const [activeIndex, setActiveIndex] =
|
|
5128
|
+
const [open, setOpen] = React36.useState(() => steps.length > 0 && !readDismissed(storageKey));
|
|
5129
|
+
const [activeIndex, setActiveIndex] = React36.useState(0);
|
|
5122
5130
|
const step = steps[activeIndex];
|
|
5123
5131
|
const bbox = useTargetBbox(step?.stepRef);
|
|
5124
5132
|
useFocusTrap(tooltipRef, open);
|
|
5125
|
-
|
|
5133
|
+
React36.useEffect(() => {
|
|
5126
5134
|
if (!open || !dismissible) return;
|
|
5127
5135
|
const onKey = (e) => {
|
|
5128
5136
|
if (e.key === "Escape") {
|
|
@@ -5133,12 +5141,12 @@ function Wizard({
|
|
|
5133
5141
|
document.addEventListener("keydown", onKey);
|
|
5134
5142
|
return () => document.removeEventListener("keydown", onKey);
|
|
5135
5143
|
}, [open, dismissible]);
|
|
5136
|
-
const handleSkip =
|
|
5144
|
+
const handleSkip = React36.useCallback(() => {
|
|
5137
5145
|
writeDismissed(storageKey);
|
|
5138
5146
|
setOpen(false);
|
|
5139
5147
|
onSkip?.();
|
|
5140
5148
|
}, [storageKey, onSkip]);
|
|
5141
|
-
const handleComplete =
|
|
5149
|
+
const handleComplete = React36.useCallback(() => {
|
|
5142
5150
|
writeDismissed(storageKey);
|
|
5143
5151
|
setOpen(false);
|
|
5144
5152
|
onComplete?.();
|
|
@@ -5281,7 +5289,7 @@ function Wizard({
|
|
|
5281
5289
|
] });
|
|
5282
5290
|
}
|
|
5283
5291
|
var SearchIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) });
|
|
5284
|
-
var SearchInput =
|
|
5292
|
+
var SearchInput = React36__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
|
|
5285
5293
|
return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5286
5294
|
"div",
|
|
5287
5295
|
{
|
|
@@ -5516,15 +5524,15 @@ function EditableCell({
|
|
|
5516
5524
|
rowIndex,
|
|
5517
5525
|
onCellEdit
|
|
5518
5526
|
}) {
|
|
5519
|
-
const [editing, setEditing] =
|
|
5520
|
-
const editRef =
|
|
5527
|
+
const [editing, setEditing] = React36.useState(false);
|
|
5528
|
+
const editRef = React36.useRef(null);
|
|
5521
5529
|
const value = row[col.keyBind];
|
|
5522
5530
|
const commit = (next) => {
|
|
5523
5531
|
setEditing(false);
|
|
5524
5532
|
onCellEdit?.({ row, key: col.keyBind, value: next, rowIndex });
|
|
5525
5533
|
};
|
|
5526
5534
|
const cancel = () => setEditing(false);
|
|
5527
|
-
|
|
5535
|
+
React36.useEffect(() => {
|
|
5528
5536
|
if (!editing || !col.editor) return;
|
|
5529
5537
|
const onMouseDown = (e) => {
|
|
5530
5538
|
const target = e.target;
|
|
@@ -5583,7 +5591,7 @@ function TableBody({
|
|
|
5583
5591
|
getRowKey,
|
|
5584
5592
|
onCellEdit
|
|
5585
5593
|
}) {
|
|
5586
|
-
const [expanded, setExpanded] =
|
|
5594
|
+
const [expanded, setExpanded] = React36.useState(() => /* @__PURE__ */ new Set());
|
|
5587
5595
|
const reduced = framerMotion.useReducedMotion();
|
|
5588
5596
|
const toggleRow = (rowKey) => {
|
|
5589
5597
|
setExpanded((prev) => {
|
|
@@ -5598,7 +5606,7 @@ function TableBody({
|
|
|
5598
5606
|
return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => {
|
|
5599
5607
|
const rowKey = getRowKey(row, i);
|
|
5600
5608
|
const isExpanded = expanded.has(rowKey);
|
|
5601
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5609
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
|
|
5602
5610
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5603
5611
|
"tr",
|
|
5604
5612
|
{
|
|
@@ -5710,13 +5718,13 @@ function Table({
|
|
|
5710
5718
|
className = "",
|
|
5711
5719
|
style
|
|
5712
5720
|
}) {
|
|
5713
|
-
const searchRef =
|
|
5714
|
-
const [searchTerm, setSearchTerm] =
|
|
5715
|
-
const [perPage, setPerPage] =
|
|
5721
|
+
const searchRef = React36.useRef(null);
|
|
5722
|
+
const [searchTerm, setSearchTerm] = React36.useState("");
|
|
5723
|
+
const [perPage, setPerPage] = React36.useState(
|
|
5716
5724
|
typeof pagination.perPage === "number" ? pagination.perPage : 15
|
|
5717
5725
|
);
|
|
5718
|
-
const [activePage, setActivePage] =
|
|
5719
|
-
const [sortState, setSortState] =
|
|
5726
|
+
const [activePage, setActivePage] = React36.useState(0);
|
|
5727
|
+
const [sortState, setSortState] = React36.useState(defaultSort);
|
|
5720
5728
|
const isServerSide = !!(pagination.enabled && pagination.serverSide);
|
|
5721
5729
|
const handleSort = (col) => {
|
|
5722
5730
|
const key = col.keyBind;
|
|
@@ -5728,8 +5736,8 @@ function Table({
|
|
|
5728
5736
|
onSortChange?.(next);
|
|
5729
5737
|
};
|
|
5730
5738
|
const debounceMs = search?.debounceMs ?? 0;
|
|
5731
|
-
const [debouncedTerm, setDebouncedTerm] =
|
|
5732
|
-
|
|
5739
|
+
const [debouncedTerm, setDebouncedTerm] = React36.useState("");
|
|
5740
|
+
React36.useEffect(() => {
|
|
5733
5741
|
if (debounceMs <= 0) {
|
|
5734
5742
|
setDebouncedTerm(searchTerm);
|
|
5735
5743
|
return;
|
|
@@ -5738,7 +5746,7 @@ function Table({
|
|
|
5738
5746
|
return () => clearTimeout(t);
|
|
5739
5747
|
}, [searchTerm, debounceMs]);
|
|
5740
5748
|
const term = debounceMs > 0 ? debouncedTerm : searchTerm;
|
|
5741
|
-
const filteredRows =
|
|
5749
|
+
const filteredRows = React36.useMemo(() => {
|
|
5742
5750
|
if (isServerSide || !term) return rows;
|
|
5743
5751
|
if (search?.predicate) return rows.filter((row) => search.predicate(row, term));
|
|
5744
5752
|
const cs = !!search?.caseSensitive;
|
|
@@ -5752,7 +5760,7 @@ function Table({
|
|
|
5752
5760
|
};
|
|
5753
5761
|
return rows.filter((row) => keys ? keys.some((k) => test(row[k])) : Object.values(row).some(test));
|
|
5754
5762
|
}, [rows, term, isServerSide, search?.predicate, search?.caseSensitive, search?.matchMode, search?.keys]);
|
|
5755
|
-
const sortedRows =
|
|
5763
|
+
const sortedRows = React36.useMemo(() => {
|
|
5756
5764
|
if (isServerSide || !sortState) return filteredRows;
|
|
5757
5765
|
const col = columns.find((c) => c.keyBind === sortState.key);
|
|
5758
5766
|
const accessor = col?.sortAccessor ?? ((r) => r[sortState.key]);
|
|
@@ -5760,29 +5768,29 @@ function Table({
|
|
|
5760
5768
|
if (sortState.direction === "desc") out.reverse();
|
|
5761
5769
|
return out;
|
|
5762
5770
|
}, [filteredRows, sortState, isServerSide, columns]);
|
|
5763
|
-
const datasets =
|
|
5771
|
+
const datasets = React36.useMemo(() => {
|
|
5764
5772
|
if (isServerSide) return [rows];
|
|
5765
5773
|
return createDatasets(sortedRows, pagination.enabled ? perPage : null);
|
|
5766
5774
|
}, [sortedRows, perPage, pagination.enabled, isServerSide, rows]);
|
|
5767
|
-
const MAX_PAGE =
|
|
5775
|
+
const MAX_PAGE = React36.useMemo(() => {
|
|
5768
5776
|
if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
|
|
5769
5777
|
if (isServerSide && typeof pagination.totalCount === "number")
|
|
5770
5778
|
return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
|
|
5771
5779
|
return datasets.length ? datasets.length - 1 : 0;
|
|
5772
5780
|
}, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
|
|
5773
|
-
const currentPageRows =
|
|
5781
|
+
const currentPageRows = React36.useMemo(() => {
|
|
5774
5782
|
if (isServerSide) return rows;
|
|
5775
5783
|
return datasets[activePage] ?? [];
|
|
5776
5784
|
}, [isServerSide, rows, datasets, activePage]);
|
|
5777
|
-
|
|
5785
|
+
React36.useEffect(() => {
|
|
5778
5786
|
if (pagination.enabled && !isServerSide && typeof pagination.perPage === "number") {
|
|
5779
5787
|
setPerPage(pagination.perPage);
|
|
5780
5788
|
}
|
|
5781
5789
|
}, [pagination.enabled, pagination.perPage, isServerSide]);
|
|
5782
|
-
|
|
5790
|
+
React36.useEffect(() => {
|
|
5783
5791
|
if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
|
|
5784
5792
|
}, [isServerSide, pagination.perPage]);
|
|
5785
|
-
|
|
5793
|
+
React36.useEffect(() => {
|
|
5786
5794
|
if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
|
|
5787
5795
|
setActivePage(pagination.page - 1);
|
|
5788
5796
|
}, [isServerSide, pagination.page]);
|
|
@@ -5871,7 +5879,7 @@ function TableSkeletonBody({
|
|
|
5871
5879
|
i
|
|
5872
5880
|
)) });
|
|
5873
5881
|
}
|
|
5874
|
-
var useIsoLayoutEffect = typeof window !== "undefined" ?
|
|
5882
|
+
var useIsoLayoutEffect = typeof window !== "undefined" ? React36.useLayoutEffect : React36.useEffect;
|
|
5875
5883
|
function VirtualList({
|
|
5876
5884
|
items,
|
|
5877
5885
|
rowHeight,
|
|
@@ -5888,10 +5896,10 @@ function VirtualList({
|
|
|
5888
5896
|
className = "",
|
|
5889
5897
|
style
|
|
5890
5898
|
}) {
|
|
5891
|
-
const scrollRef =
|
|
5892
|
-
const [scrollTop, setScrollTop] =
|
|
5893
|
-
const [viewport, setViewport] =
|
|
5894
|
-
const [term, setTerm] =
|
|
5899
|
+
const scrollRef = React36.useRef(null);
|
|
5900
|
+
const [scrollTop, setScrollTop] = React36.useState(0);
|
|
5901
|
+
const [viewport, setViewport] = React36.useState(typeof height === "number" ? height : 400);
|
|
5902
|
+
const [term, setTerm] = React36.useState("");
|
|
5895
5903
|
useIsoLayoutEffect(() => {
|
|
5896
5904
|
const el = scrollRef.current;
|
|
5897
5905
|
if (!el) return;
|
|
@@ -5902,7 +5910,7 @@ function VirtualList({
|
|
|
5902
5910
|
ro.observe(el);
|
|
5903
5911
|
return () => ro.disconnect();
|
|
5904
5912
|
}, []);
|
|
5905
|
-
const filtered =
|
|
5913
|
+
const filtered = React36.useMemo(() => {
|
|
5906
5914
|
if (!searchable || !term) return items;
|
|
5907
5915
|
if (filter) return items.filter((it) => filter(it, term));
|
|
5908
5916
|
const needle = term.toLowerCase();
|
|
@@ -5973,6 +5981,15 @@ async function sourceToBytes(source, remote) {
|
|
|
5973
5981
|
}
|
|
5974
5982
|
throw new Error("Unsupported source type");
|
|
5975
5983
|
}
|
|
5984
|
+
function downloadBlob(blob, name) {
|
|
5985
|
+
if (typeof document === "undefined") return;
|
|
5986
|
+
const url = URL.createObjectURL(blob);
|
|
5987
|
+
const a = document.createElement("a");
|
|
5988
|
+
a.href = url;
|
|
5989
|
+
a.download = name;
|
|
5990
|
+
a.click();
|
|
5991
|
+
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
5992
|
+
}
|
|
5976
5993
|
function sourceName(source) {
|
|
5977
5994
|
if (typeof File !== "undefined" && source instanceof File) return source.name;
|
|
5978
5995
|
if (isUrlSource(source)) {
|
|
@@ -5983,17 +6000,45 @@ function sourceName(source) {
|
|
|
5983
6000
|
return void 0;
|
|
5984
6001
|
}
|
|
5985
6002
|
var pdfjsPromise = null;
|
|
5986
|
-
function loadPdfjs() {
|
|
6003
|
+
function loadPdfjs(workerSrc) {
|
|
5987
6004
|
if (pdfjsPromise) return pdfjsPromise;
|
|
5988
6005
|
pdfjsPromise = import('pdfjs-dist').then((pdfjs) => {
|
|
5989
6006
|
if (!pdfjs.GlobalWorkerOptions.workerSrc) {
|
|
5990
|
-
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
6007
|
+
pdfjs.GlobalWorkerOptions.workerSrc = workerSrc ?? `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
5991
6008
|
}
|
|
5992
6009
|
return pdfjs;
|
|
5993
6010
|
});
|
|
5994
6011
|
return pdfjsPromise;
|
|
5995
6012
|
}
|
|
5996
6013
|
var GAP = 12;
|
|
6014
|
+
var SEARCH_DEBOUNCE = 220;
|
|
6015
|
+
var TEXT_LAYER_STYLE_ID = "oxygen-pdf-textlayer";
|
|
6016
|
+
var TEXT_LAYER_CSS = `
|
|
6017
|
+
.oxy-textLayer{position:absolute;inset:0;overflow:clip;line-height:1;text-size-adjust:none;forced-color-adjust:none;transform-origin:0 0}
|
|
6018
|
+
.oxy-textLayer span,.oxy-textLayer br{color:transparent;position:absolute;white-space:pre;cursor:text;transform-origin:0 0}
|
|
6019
|
+
.oxy-textLayer span.markedContent{top:0;height:0}
|
|
6020
|
+
.oxy-textLayer ::selection{background:color-mix(in srgb, var(--color-accent) 35%, transparent)}
|
|
6021
|
+
`;
|
|
6022
|
+
function ensureTextLayerStyles() {
|
|
6023
|
+
if (typeof document === "undefined" || document.getElementById(TEXT_LAYER_STYLE_ID)) return;
|
|
6024
|
+
const el = document.createElement("style");
|
|
6025
|
+
el.id = TEXT_LAYER_STYLE_ID;
|
|
6026
|
+
el.textContent = TEXT_LAYER_CSS;
|
|
6027
|
+
document.head.appendChild(el);
|
|
6028
|
+
}
|
|
6029
|
+
function pageIndexAt(offsets, y) {
|
|
6030
|
+
let lo = 0;
|
|
6031
|
+
let hi = offsets.length - 1;
|
|
6032
|
+
let ans = 0;
|
|
6033
|
+
while (lo <= hi) {
|
|
6034
|
+
const mid = lo + hi >> 1;
|
|
6035
|
+
if (offsets[mid] <= y) {
|
|
6036
|
+
ans = mid;
|
|
6037
|
+
lo = mid + 1;
|
|
6038
|
+
} else hi = mid - 1;
|
|
6039
|
+
}
|
|
6040
|
+
return ans;
|
|
6041
|
+
}
|
|
5997
6042
|
function PdfViewer({
|
|
5998
6043
|
source,
|
|
5999
6044
|
remote,
|
|
@@ -6002,37 +6047,53 @@ function PdfViewer({
|
|
|
6002
6047
|
toolbar = true,
|
|
6003
6048
|
thumbnails = false,
|
|
6004
6049
|
textLayer = true,
|
|
6050
|
+
workerSrc,
|
|
6005
6051
|
onLoad,
|
|
6006
6052
|
onError,
|
|
6007
6053
|
onPageChange,
|
|
6054
|
+
height = 600,
|
|
6055
|
+
width,
|
|
6008
6056
|
className = "",
|
|
6009
6057
|
style
|
|
6010
6058
|
}) {
|
|
6011
|
-
const [pdfjs, setPdfjs] =
|
|
6012
|
-
const [doc, setDoc] =
|
|
6013
|
-
const [numPages, setNumPages] =
|
|
6014
|
-
const [baseSize, setBaseSize] =
|
|
6015
|
-
const [
|
|
6016
|
-
const [
|
|
6017
|
-
const [
|
|
6018
|
-
const
|
|
6019
|
-
const
|
|
6020
|
-
const [
|
|
6021
|
-
const [
|
|
6022
|
-
const [
|
|
6023
|
-
const [
|
|
6024
|
-
const [
|
|
6025
|
-
const [
|
|
6026
|
-
const [
|
|
6059
|
+
const [pdfjs, setPdfjs] = React36.useState(null);
|
|
6060
|
+
const [doc, setDoc] = React36.useState(null);
|
|
6061
|
+
const [numPages, setNumPages] = React36.useState(0);
|
|
6062
|
+
const [baseSize, setBaseSize] = React36.useState(null);
|
|
6063
|
+
const [sizes, setSizes] = React36.useState([]);
|
|
6064
|
+
const [status, setStatus] = React36.useState("loading");
|
|
6065
|
+
const [error, setError] = React36.useState(null);
|
|
6066
|
+
const [reloadKey, setReloadKey] = React36.useState(0);
|
|
6067
|
+
const scrollRef = React36.useRef(null);
|
|
6068
|
+
const [scrollTop, setScrollTop] = React36.useState(0);
|
|
6069
|
+
const [viewport, setViewport] = React36.useState({ w: 0, h: 0 });
|
|
6070
|
+
const [zoomMode, setZoomMode] = React36.useState(zoom);
|
|
6071
|
+
const [page, setPage] = React36.useState(initialPage);
|
|
6072
|
+
const [showSearch, setShowSearch] = React36.useState(false);
|
|
6073
|
+
const [query, setQuery] = React36.useState("");
|
|
6074
|
+
const [matchPages, setMatchPages] = React36.useState(null);
|
|
6075
|
+
const [matchIdx, setMatchIdx] = React36.useState(0);
|
|
6076
|
+
const [searching, setSearching] = React36.useState(false);
|
|
6077
|
+
const [pageDraft, setPageDraft] = React36.useState("");
|
|
6078
|
+
const pageEditing = React36.useRef(false);
|
|
6079
|
+
const pageText = React36.useRef(/* @__PURE__ */ new Map());
|
|
6080
|
+
const searchSeq = React36.useRef(0);
|
|
6081
|
+
const searchTimer = React36.useRef(null);
|
|
6082
|
+
const measured = React36.useRef(/* @__PURE__ */ new Set());
|
|
6027
6083
|
const tb = toolbar === true ? { zoom: true, pager: true, download: true, print: true, search: true } : toolbar || {};
|
|
6028
|
-
|
|
6084
|
+
React36.useEffect(() => {
|
|
6029
6085
|
let cancelled = false;
|
|
6030
6086
|
let task;
|
|
6031
6087
|
setStatus("loading");
|
|
6032
6088
|
setError(null);
|
|
6033
6089
|
setDoc(null);
|
|
6034
6090
|
setBaseSize(null);
|
|
6035
|
-
|
|
6091
|
+
setSizes([]);
|
|
6092
|
+
pageText.current.clear();
|
|
6093
|
+
measured.current = /* @__PURE__ */ new Set();
|
|
6094
|
+
setMatchPages(null);
|
|
6095
|
+
setMatchIdx(0);
|
|
6096
|
+
loadPdfjs(workerSrc).then(async (pdfjs2) => {
|
|
6036
6097
|
if (cancelled) return;
|
|
6037
6098
|
setPdfjs(pdfjs2);
|
|
6038
6099
|
const params = isUrlSource(source) ? { url: urlHref(source), httpHeaders: remote?.httpHeaders, withCredentials: remote?.withCredentials } : { data: source instanceof Uint8Array || source instanceof ArrayBuffer ? source : new Uint8Array(await source.arrayBuffer()) };
|
|
@@ -6045,9 +6106,12 @@ function PdfViewer({
|
|
|
6045
6106
|
const first = await pdf.getPage(1);
|
|
6046
6107
|
const vp = first.getViewport({ scale: 1 });
|
|
6047
6108
|
if (cancelled) return;
|
|
6109
|
+
const base = { width: vp.width, height: vp.height };
|
|
6048
6110
|
setDoc(pdf);
|
|
6049
6111
|
setNumPages(pdf.numPages);
|
|
6050
|
-
setBaseSize(
|
|
6112
|
+
setBaseSize(base);
|
|
6113
|
+
setSizes(Array.from({ length: pdf.numPages }, () => base));
|
|
6114
|
+
measured.current.add(1);
|
|
6051
6115
|
setStatus("ready");
|
|
6052
6116
|
onLoad?.({ numPages: pdf.numPages });
|
|
6053
6117
|
}).catch((err) => {
|
|
@@ -6060,11 +6124,11 @@ function PdfViewer({
|
|
|
6060
6124
|
cancelled = true;
|
|
6061
6125
|
task?.destroy?.();
|
|
6062
6126
|
};
|
|
6063
|
-
}, [source, remote, reloadKey]);
|
|
6064
|
-
|
|
6127
|
+
}, [source, remote, reloadKey, workerSrc]);
|
|
6128
|
+
React36.useEffect(() => () => {
|
|
6065
6129
|
doc?.destroy?.();
|
|
6066
6130
|
}, [doc]);
|
|
6067
|
-
|
|
6131
|
+
React36.useEffect(() => {
|
|
6068
6132
|
const el = scrollRef.current;
|
|
6069
6133
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
6070
6134
|
const measure = () => setViewport({ w: el.clientWidth, h: el.clientHeight });
|
|
@@ -6073,83 +6137,119 @@ function PdfViewer({
|
|
|
6073
6137
|
ro.observe(el);
|
|
6074
6138
|
return () => ro.disconnect();
|
|
6075
6139
|
}, [status]);
|
|
6076
|
-
const
|
|
6140
|
+
const handleMeasure = React36.useCallback((p, size) => {
|
|
6141
|
+
setSizes((prev) => {
|
|
6142
|
+
const cur = prev[p - 1];
|
|
6143
|
+
if (cur && Math.abs(cur.width - size.width) < 0.5 && Math.abs(cur.height - size.height) < 0.5) return prev;
|
|
6144
|
+
const next = prev.slice();
|
|
6145
|
+
next[p - 1] = size;
|
|
6146
|
+
return next;
|
|
6147
|
+
});
|
|
6148
|
+
}, []);
|
|
6149
|
+
const scale = React36.useMemo(() => {
|
|
6077
6150
|
if (!baseSize) return 1;
|
|
6078
6151
|
if (typeof zoomMode === "number") return zoomMode;
|
|
6079
|
-
const avail = Math.max(
|
|
6152
|
+
const avail = Math.max(1, (viewport.w || baseSize.width) - 32);
|
|
6080
6153
|
if (zoomMode === "page-width" || zoomMode === "auto") return avail / baseSize.width;
|
|
6081
6154
|
if (zoomMode === "page-fit") {
|
|
6082
|
-
const availH = Math.max(
|
|
6155
|
+
const availH = Math.max(1, (viewport.h || baseSize.height) - 32);
|
|
6083
6156
|
return Math.min(avail / baseSize.width, availH / baseSize.height);
|
|
6084
6157
|
}
|
|
6085
6158
|
return 1;
|
|
6086
6159
|
}, [zoomMode, baseSize, viewport]);
|
|
6087
|
-
const
|
|
6088
|
-
|
|
6089
|
-
|
|
6160
|
+
const { offsets, total } = React36.useMemo(() => {
|
|
6161
|
+
const offs = new Array(sizes.length);
|
|
6162
|
+
let acc = 0;
|
|
6163
|
+
for (let i = 0; i < sizes.length; i++) {
|
|
6164
|
+
offs[i] = acc;
|
|
6165
|
+
acc += sizes[i].height * scale + GAP;
|
|
6166
|
+
}
|
|
6167
|
+
return { offsets: offs, total: acc };
|
|
6168
|
+
}, [sizes, scale]);
|
|
6090
6169
|
const overscan = 1;
|
|
6091
|
-
const
|
|
6092
|
-
const
|
|
6170
|
+
const hasLayout = offsets.length > 0 && total > 0;
|
|
6171
|
+
const startIdx = hasLayout ? Math.max(0, pageIndexAt(offsets, scrollTop) - overscan) : 0;
|
|
6172
|
+
const endIdx = hasLayout ? Math.min(numPages, pageIndexAt(offsets, scrollTop + viewport.h) + 1 + overscan) : 0;
|
|
6093
6173
|
const visiblePages = Array.from({ length: Math.max(0, endIdx - startIdx) }, (_, i) => startIdx + i + 1);
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6174
|
+
const scrollToPage = React36.useCallback((p) => {
|
|
6175
|
+
const el = scrollRef.current;
|
|
6176
|
+
if (!el || !offsets.length) return;
|
|
6177
|
+
const clamped = Math.min(offsets.length, Math.max(1, p));
|
|
6178
|
+
el.scrollTo({ top: offsets[clamped - 1] ?? 0, behavior: "smooth" });
|
|
6179
|
+
}, [offsets]);
|
|
6180
|
+
React36.useEffect(() => {
|
|
6181
|
+
if (!hasLayout) return;
|
|
6182
|
+
const cur = pageIndexAt(offsets, scrollTop + viewport.h / 2) + 1;
|
|
6097
6183
|
if (cur !== page) {
|
|
6098
6184
|
setPage(cur);
|
|
6099
6185
|
onPageChange?.(cur);
|
|
6100
6186
|
}
|
|
6101
|
-
}, [scrollTop,
|
|
6102
|
-
|
|
6103
|
-
const el = scrollRef.current;
|
|
6104
|
-
if (!el || !pageH) return;
|
|
6105
|
-
el.scrollTo({ top: (p - 1) * pageH, behavior: "smooth" });
|
|
6106
|
-
}, [pageH]);
|
|
6107
|
-
React34.useEffect(() => {
|
|
6187
|
+
}, [scrollTop, offsets, viewport.h, numPages]);
|
|
6188
|
+
React36.useEffect(() => {
|
|
6108
6189
|
if (status === "ready" && initialPage > 1) scrollToPage(initialPage);
|
|
6109
|
-
}, [status]);
|
|
6110
|
-
const runSearch =
|
|
6111
|
-
|
|
6112
|
-
if (!doc || !
|
|
6190
|
+
}, [status, initialPage]);
|
|
6191
|
+
const runSearch = React36.useCallback(async (q) => {
|
|
6192
|
+
const needle = q.trim().toLowerCase();
|
|
6193
|
+
if (!doc || !needle) {
|
|
6113
6194
|
setMatchPages(null);
|
|
6114
6195
|
setMatchIdx(0);
|
|
6196
|
+
setSearching(false);
|
|
6115
6197
|
return;
|
|
6116
6198
|
}
|
|
6117
|
-
const
|
|
6199
|
+
const seq = ++searchSeq.current;
|
|
6200
|
+
setSearching(true);
|
|
6118
6201
|
const hits = [];
|
|
6119
6202
|
for (let p = 1; p <= numPages; p++) {
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6203
|
+
let text = pageText.current.get(p);
|
|
6204
|
+
if (text === void 0) {
|
|
6205
|
+
const pg = await doc.getPage(p);
|
|
6206
|
+
const tc = await pg.getTextContent();
|
|
6207
|
+
const built = tc.items.map((it) => "str" in it ? it.str : "").join(" ").toLowerCase();
|
|
6208
|
+
pageText.current.set(p, built);
|
|
6209
|
+
text = built;
|
|
6210
|
+
}
|
|
6211
|
+
if (seq !== searchSeq.current) return;
|
|
6123
6212
|
if (text.includes(needle)) hits.push(p);
|
|
6124
6213
|
}
|
|
6214
|
+
if (seq !== searchSeq.current) return;
|
|
6125
6215
|
setMatchPages(hits);
|
|
6126
6216
|
setMatchIdx(0);
|
|
6217
|
+
setSearching(false);
|
|
6127
6218
|
if (hits.length) scrollToPage(hits[0]);
|
|
6128
6219
|
}, [doc, numPages, scrollToPage]);
|
|
6220
|
+
const onQueryChange = React36.useCallback((v) => {
|
|
6221
|
+
setQuery(v);
|
|
6222
|
+
if (searchTimer.current) clearTimeout(searchTimer.current);
|
|
6223
|
+
if (!v.trim()) {
|
|
6224
|
+
searchSeq.current++;
|
|
6225
|
+
setMatchPages(null);
|
|
6226
|
+
setMatchIdx(0);
|
|
6227
|
+
setSearching(false);
|
|
6228
|
+
return;
|
|
6229
|
+
}
|
|
6230
|
+
searchTimer.current = setTimeout(() => runSearch(v), SEARCH_DEBOUNCE);
|
|
6231
|
+
}, [runSearch]);
|
|
6232
|
+
React36.useEffect(() => () => {
|
|
6233
|
+
if (searchTimer.current) clearTimeout(searchTimer.current);
|
|
6234
|
+
}, []);
|
|
6129
6235
|
const gotoMatch = (dir) => {
|
|
6130
6236
|
if (!matchPages?.length) return;
|
|
6131
6237
|
const next = (matchIdx + dir + matchPages.length) % matchPages.length;
|
|
6132
6238
|
setMatchIdx(next);
|
|
6133
6239
|
scrollToPage(matchPages[next]);
|
|
6134
6240
|
};
|
|
6135
|
-
const getBytes =
|
|
6241
|
+
const getBytes = React36.useCallback(async () => {
|
|
6136
6242
|
if (doc?.getData) return doc.getData();
|
|
6137
6243
|
if (source instanceof Uint8Array) return source;
|
|
6138
6244
|
if (source instanceof ArrayBuffer) return new Uint8Array(source);
|
|
6139
6245
|
if (typeof Blob !== "undefined" && source instanceof Blob) return new Uint8Array(await source.arrayBuffer());
|
|
6140
6246
|
throw new Error("No bytes available");
|
|
6141
6247
|
}, [doc, source]);
|
|
6142
|
-
const
|
|
6248
|
+
const download = React36.useCallback(async () => {
|
|
6143
6249
|
const bytes = await getBytes();
|
|
6144
|
-
|
|
6145
|
-
const url = URL.createObjectURL(blob);
|
|
6146
|
-
const a = document.createElement("a");
|
|
6147
|
-
a.href = url;
|
|
6148
|
-
a.download = sourceName(source) || "document.pdf";
|
|
6149
|
-
a.click();
|
|
6150
|
-
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
6250
|
+
downloadBlob(new Blob([bytes], { type: "application/pdf" }), sourceName(source) || "document.pdf");
|
|
6151
6251
|
}, [getBytes, source]);
|
|
6152
|
-
const print =
|
|
6252
|
+
const print = React36.useCallback(async () => {
|
|
6153
6253
|
const bytes = await getBytes();
|
|
6154
6254
|
const blob = new Blob([bytes], { type: "application/pdf" });
|
|
6155
6255
|
const url = URL.createObjectURL(blob);
|
|
@@ -6173,6 +6273,12 @@ function PdfViewer({
|
|
|
6173
6273
|
const cur = typeof zoomMode === "number" ? zoomMode : scale;
|
|
6174
6274
|
setZoomMode(Math.min(5, Math.max(0.25, +(cur * factor).toFixed(2))));
|
|
6175
6275
|
};
|
|
6276
|
+
const zoomPct = Math.round(scale * 100);
|
|
6277
|
+
const commitPageDraft = () => {
|
|
6278
|
+
pageEditing.current = false;
|
|
6279
|
+
const n = parseInt(pageDraft, 10);
|
|
6280
|
+
if (Number.isFinite(n)) scrollToPage(n);
|
|
6281
|
+
};
|
|
6176
6282
|
if (status === "error") {
|
|
6177
6283
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style, children: [
|
|
6178
6284
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-status-error", children: "Couldn\u2019t load the PDF" }),
|
|
@@ -6180,89 +6286,137 @@ function PdfViewer({
|
|
|
6180
6286
|
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { content: "Retry", size: "sm", variant: "outline", onClick: () => setReloadKey((k) => k + 1) })
|
|
6181
6287
|
] });
|
|
6182
6288
|
}
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
6188
|
-
|
|
6189
|
-
"
|
|
6190
|
-
|
|
6289
|
+
const ready = status === "ready";
|
|
6290
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height, width, ...style }, children: [
|
|
6291
|
+
toolbar !== false && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 flex-col border-b border-border bg-surface", children: [
|
|
6292
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
|
|
6293
|
+
tb.pager && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6294
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Previous page", onClick: () => scrollToPage(page - 1), icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron5, { dir: "up" }), disabled: !ready || page <= 1 }),
|
|
6295
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-xs text-foreground-secondary select-none", children: [
|
|
6296
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6297
|
+
"input",
|
|
6298
|
+
{
|
|
6299
|
+
value: pageEditing.current ? pageDraft : ready ? String(page) : "\u2013",
|
|
6300
|
+
onFocus: () => {
|
|
6301
|
+
pageEditing.current = true;
|
|
6302
|
+
setPageDraft(String(page));
|
|
6303
|
+
},
|
|
6304
|
+
onChange: (e) => setPageDraft(e.target.value.replace(/[^\d]/g, "")),
|
|
6305
|
+
onBlur: commitPageDraft,
|
|
6306
|
+
onKeyDown: (e) => {
|
|
6307
|
+
if (e.key === "Enter") e.target.blur();
|
|
6308
|
+
},
|
|
6309
|
+
disabled: !ready,
|
|
6310
|
+
"aria-label": "Page number",
|
|
6311
|
+
className: "h-6 w-9 rounded border border-border bg-surface-raised text-center tabular-nums text-foreground outline-none focus:border-accent disabled:opacity-50"
|
|
6312
|
+
}
|
|
6313
|
+
),
|
|
6314
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums", children: [
|
|
6315
|
+
"/ ",
|
|
6316
|
+
numPages || "\u2013"
|
|
6317
|
+
] })
|
|
6318
|
+
] }),
|
|
6319
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Next page", onClick: () => scrollToPage(page + 1), icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron5, { dir: "down" }), disabled: !ready || page >= numPages })
|
|
6191
6320
|
] }),
|
|
6192
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6321
|
+
tb.pager && tb.zoom && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-1 h-5 w-px bg-border", "aria-hidden": "true" }),
|
|
6322
|
+
tb.zoom && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6323
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Zoom out", onClick: () => setZoomNum(1 / 1.2), icon: /* @__PURE__ */ jsxRuntime.jsx(MinusIcon, {}), disabled: !ready }),
|
|
6324
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-10 text-center text-xs tabular-nums text-foreground-secondary select-none", children: ready ? `${zoomPct}%` : "\u2013" }),
|
|
6325
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Zoom in", onClick: () => setZoomNum(1.2), icon: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}), disabled: !ready }),
|
|
6326
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Fit width", onClick: () => setZoomMode("page-width"), icon: /* @__PURE__ */ jsxRuntime.jsx(FitWidthIcon, {}), disabled: !ready }),
|
|
6327
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Fit page", onClick: () => setZoomMode("page-fit"), icon: /* @__PURE__ */ jsxRuntime.jsx(FitPageIcon, {}), disabled: !ready })
|
|
6328
|
+
] }),
|
|
6329
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex items-center gap-1", children: [
|
|
6330
|
+
tb.search && /* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: showSearch ? "bordered" : "ghost", size: "sm", title: "Search", onClick: () => setShowSearch((s) => !s), icon: /* @__PURE__ */ jsxRuntime.jsx(SearchIcon2, {}), disabled: !ready }),
|
|
6331
|
+
tb.search && (tb.download || tb.print) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-1 h-5 w-px bg-border", "aria-hidden": "true" }),
|
|
6332
|
+
tb.download && /* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Download", onClick: download, icon: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {}), disabled: !ready }),
|
|
6333
|
+
tb.print && /* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Print", onClick: print, icon: /* @__PURE__ */ jsxRuntime.jsx(PrintIcon, {}), disabled: !ready })
|
|
6334
|
+
] })
|
|
6204
6335
|
] }),
|
|
6205
|
-
tb.search && showSearch && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
6336
|
+
tb.search && showSearch && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-t border-border px-2 py-1.5", children: [
|
|
6337
|
+
/* @__PURE__ */ jsxRuntime.jsx(SearchIcon2, {}),
|
|
6206
6338
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6207
6339
|
"input",
|
|
6208
6340
|
{
|
|
6209
6341
|
autoFocus: true,
|
|
6210
6342
|
value: query,
|
|
6211
|
-
onChange: (e) =>
|
|
6343
|
+
onChange: (e) => onQueryChange(e.target.value),
|
|
6344
|
+
onKeyDown: (e) => {
|
|
6345
|
+
if (e.key === "Enter") gotoMatch(e.shiftKey ? -1 : 1);
|
|
6346
|
+
},
|
|
6212
6347
|
placeholder: "Find in document\u2026",
|
|
6213
|
-
className: "h-7 flex-1
|
|
6348
|
+
className: "h-7 flex-1 bg-transparent text-sm text-foreground outline-none placeholder:text-foreground-muted"
|
|
6214
6349
|
}
|
|
6215
6350
|
),
|
|
6216
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs tabular-nums text-foreground-muted", children: matchPages == null ? "" : matchPages.length ? `${matchIdx + 1}
|
|
6351
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs tabular-nums text-foreground-muted", children: searching ? "Searching\u2026" : matchPages == null ? "" : matchPages.length ? `${matchIdx + 1} of ${matchPages.length}` : "No matches" }),
|
|
6217
6352
|
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Previous match", onClick: () => gotoMatch(-1), icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron5, { dir: "up" }), disabled: !matchPages?.length }),
|
|
6218
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Next match", onClick: () => gotoMatch(1), icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron5, { dir: "down" }), disabled: !matchPages?.length })
|
|
6353
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Next match", onClick: () => gotoMatch(1), icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron5, { dir: "down" }), disabled: !matchPages?.length }),
|
|
6354
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton_default, { type: "ghost", size: "sm", title: "Close search", onClick: () => {
|
|
6355
|
+
setShowSearch(false);
|
|
6356
|
+
onQueryChange("");
|
|
6357
|
+
}, icon: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}) })
|
|
6219
6358
|
] })
|
|
6220
6359
|
] }),
|
|
6221
6360
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1", children: [
|
|
6222
|
-
thumbnails &&
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6361
|
+
thumbnails && ready && doc && baseSize && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-32 flex-shrink-0 overflow-y-auto border-r border-border bg-surface p-2", children: Array.from({ length: numPages }, (_, i) => i + 1).map((p) => {
|
|
6362
|
+
const s = sizes[p - 1] ?? baseSize;
|
|
6363
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6364
|
+
"button",
|
|
6365
|
+
{
|
|
6366
|
+
type: "button",
|
|
6367
|
+
onClick: () => scrollToPage(p),
|
|
6368
|
+
className: cx(
|
|
6369
|
+
"mb-2 block w-full overflow-hidden rounded border bg-surface-raised transition-colors",
|
|
6370
|
+
p === page ? "border-accent ring-1 ring-accent" : "border-border hover:border-border-strong"
|
|
6371
|
+
),
|
|
6372
|
+
style: { aspectRatio: `${s.width} / ${s.height}` },
|
|
6373
|
+
"aria-label": `Page ${p}`,
|
|
6374
|
+
"aria-current": p === page,
|
|
6375
|
+
children: Math.abs(p - page) <= 8 ? /* @__PURE__ */ jsxRuntime.jsx(PdfPage, { pdfjs, doc, page: p, scale: 112 / s.width, textLayer: false }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block py-4 text-center text-xs text-foreground-muted", children: p })
|
|
6376
|
+
},
|
|
6377
|
+
p
|
|
6378
|
+
);
|
|
6379
|
+
}) }),
|
|
6237
6380
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6238
6381
|
"div",
|
|
6239
6382
|
{
|
|
6240
6383
|
ref: scrollRef,
|
|
6241
6384
|
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
6242
6385
|
className: "relative flex-1 overflow-auto bg-background",
|
|
6243
|
-
children:
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6386
|
+
children: !ready || !baseSize ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center gap-3 p-6", children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { width: Math.min((viewport.w || 528) - 48, 560), height: 680, className: "rounded" }) }) : numPages === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-sm text-foreground-muted", children: "Empty document" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: total, position: "relative" }, children: visiblePages.map((p) => {
|
|
6387
|
+
const s = sizes[p - 1] ?? baseSize;
|
|
6388
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6389
|
+
"div",
|
|
6390
|
+
{
|
|
6391
|
+
style: { position: "absolute", top: offsets[p - 1], left: 0, right: 0, display: "flex", justifyContent: "center", paddingTop: GAP / 2 },
|
|
6392
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative shadow-md", style: { width: s.width * scale, height: s.height * scale }, children: /* @__PURE__ */ jsxRuntime.jsx(PdfPage, { pdfjs, doc, page: p, scale, textLayer, onMeasure: handleMeasure }) })
|
|
6393
|
+
},
|
|
6394
|
+
p
|
|
6395
|
+
);
|
|
6396
|
+
}) })
|
|
6251
6397
|
}
|
|
6252
6398
|
)
|
|
6253
6399
|
] })
|
|
6254
6400
|
] });
|
|
6255
6401
|
}
|
|
6256
|
-
function PdfPage({
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6402
|
+
function PdfPage({
|
|
6403
|
+
pdfjs,
|
|
6404
|
+
doc,
|
|
6405
|
+
page,
|
|
6406
|
+
scale,
|
|
6407
|
+
textLayer,
|
|
6408
|
+
onMeasure
|
|
6409
|
+
}) {
|
|
6410
|
+
const canvasRef = React36.useRef(null);
|
|
6411
|
+
const textRef = React36.useRef(null);
|
|
6412
|
+
React36.useEffect(() => {
|
|
6260
6413
|
let cancelled = false;
|
|
6261
6414
|
let renderTask;
|
|
6262
6415
|
(async () => {
|
|
6263
6416
|
const pg = await doc.getPage(page);
|
|
6264
6417
|
if (cancelled) return;
|
|
6265
6418
|
const viewport = pg.getViewport({ scale });
|
|
6419
|
+
onMeasure?.(page, { width: viewport.width / scale, height: viewport.height / scale });
|
|
6266
6420
|
const canvas = canvasRef.current;
|
|
6267
6421
|
if (!canvas) return;
|
|
6268
6422
|
const ratio = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
@@ -6279,6 +6433,7 @@ function PdfPage({ pdfjs, doc, page, scale, textLayer }) {
|
|
|
6279
6433
|
}
|
|
6280
6434
|
if (cancelled || !textLayer || !textRef.current || !pdfjs?.TextLayer) return;
|
|
6281
6435
|
try {
|
|
6436
|
+
ensureTextLayerStyles();
|
|
6282
6437
|
textRef.current.innerHTML = "";
|
|
6283
6438
|
textRef.current.style.setProperty("--scale-factor", String(scale));
|
|
6284
6439
|
const tl = new pdfjs.TextLayer({ textContentSource: pg.streamTextContent(), container: textRef.current, viewport });
|
|
@@ -6290,17 +6445,20 @@ function PdfPage({ pdfjs, doc, page, scale, textLayer }) {
|
|
|
6290
6445
|
cancelled = true;
|
|
6291
6446
|
renderTask?.cancel?.();
|
|
6292
6447
|
};
|
|
6293
|
-
}, [pdfjs, doc, page, scale, textLayer]);
|
|
6448
|
+
}, [pdfjs, doc, page, scale, textLayer, onMeasure]);
|
|
6294
6449
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6295
6450
|
/* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef, className: "block bg-white" }),
|
|
6296
|
-
textLayer && /* @__PURE__ */ jsxRuntime.jsx("div", { ref: textRef, className: "textLayer
|
|
6451
|
+
textLayer && /* @__PURE__ */ jsxRuntime.jsx("div", { ref: textRef, className: "oxy-textLayer", "aria-hidden": "true" })
|
|
6297
6452
|
] });
|
|
6298
6453
|
}
|
|
6299
6454
|
var Chevron5 = ({ dir }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: dir === "up" ? "m6 15 6-6 6 6" : "m6 9 6 6 6-6" }) });
|
|
6300
|
-
var
|
|
6455
|
+
var MinusIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M5 12h14" }) });
|
|
6456
|
+
var PlusIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M12 5v14M5 12h14" }) });
|
|
6457
|
+
var SearchIcon2 = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4 text-foreground-muted", "aria-hidden": "true", children: [
|
|
6301
6458
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "7" }),
|
|
6302
6459
|
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "m21 21-4.3-4.3" })
|
|
6303
6460
|
] });
|
|
6461
|
+
var CloseIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M6 6l12 12M18 6 6 18" }) });
|
|
6304
6462
|
var DownloadIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
|
|
6305
6463
|
var PrintIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9V3h12v6M6 18H4v-7h16v7h-2M8 14h8v7H8z" }) });
|
|
6306
6464
|
var FitWidthIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 12h18m0 0-4-4m4 4-4 4M3 12l4-4m-4 4 4 4" }) });
|
|
@@ -6310,11 +6468,20 @@ var FitPageIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 2
|
|
|
6310
6468
|
] });
|
|
6311
6469
|
var DEFAULT_COL_WIDTH = 140;
|
|
6312
6470
|
var GUTTER = 52;
|
|
6471
|
+
var END_PAD = 12;
|
|
6472
|
+
function compareValues2(a, b) {
|
|
6473
|
+
if (a == null && b == null) return 0;
|
|
6474
|
+
if (a == null) return 1;
|
|
6475
|
+
if (b == null) return -1;
|
|
6476
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
6477
|
+
if (typeof a === "boolean" && typeof b === "boolean") return a === b ? 0 : a ? 1 : -1;
|
|
6478
|
+
return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
|
|
6479
|
+
}
|
|
6313
6480
|
function resolveWidth(w) {
|
|
6314
|
-
if (typeof w === "number") return w;
|
|
6481
|
+
if (typeof w === "number" && Number.isFinite(w)) return w;
|
|
6315
6482
|
if (typeof w === "string") {
|
|
6316
|
-
const
|
|
6317
|
-
if (
|
|
6483
|
+
const m = /^\s*(\d+(?:\.\d+)?)(px)?\s*$/.exec(w);
|
|
6484
|
+
if (m) return parseFloat(m[1]);
|
|
6318
6485
|
}
|
|
6319
6486
|
return DEFAULT_COL_WIDTH;
|
|
6320
6487
|
}
|
|
@@ -6328,7 +6495,11 @@ function DataGrid({
|
|
|
6328
6495
|
rowHeight = 34,
|
|
6329
6496
|
headerHeight = 38,
|
|
6330
6497
|
height = 480,
|
|
6498
|
+
width,
|
|
6331
6499
|
editable = false,
|
|
6500
|
+
sortable = false,
|
|
6501
|
+
sort: sortProp,
|
|
6502
|
+
onSortChange,
|
|
6332
6503
|
virtualize = true,
|
|
6333
6504
|
overscan = 4,
|
|
6334
6505
|
rowNumbers = true,
|
|
@@ -6337,13 +6508,16 @@ function DataGrid({
|
|
|
6337
6508
|
style,
|
|
6338
6509
|
emptyState = "No data"
|
|
6339
6510
|
}) {
|
|
6340
|
-
const scrollRef =
|
|
6341
|
-
const [scroll, setScroll] =
|
|
6342
|
-
const [viewport, setViewport] =
|
|
6343
|
-
const [editing, setEditing] =
|
|
6344
|
-
const [draft, setDraft] =
|
|
6511
|
+
const scrollRef = React36.useRef(null);
|
|
6512
|
+
const [scroll, setScroll] = React36.useState({ top: 0, left: 0 });
|
|
6513
|
+
const [viewport, setViewport] = React36.useState({ w: 0, h: 0 });
|
|
6514
|
+
const [editing, setEditing] = React36.useState(null);
|
|
6515
|
+
const [draft, setDraft] = React36.useState("");
|
|
6516
|
+
const [internalSort, setInternalSort] = React36.useState(null);
|
|
6517
|
+
const sort = sortProp !== void 0 ? sortProp : internalSort;
|
|
6345
6518
|
const gutter = rowNumbers ? GUTTER : 0;
|
|
6346
|
-
const
|
|
6519
|
+
const colSortable = (c) => c.sortable ?? sortable;
|
|
6520
|
+
const { widths, offsets, totalWidth } = React36.useMemo(() => {
|
|
6347
6521
|
const widths2 = columns.map((c) => resolveWidth(c.width));
|
|
6348
6522
|
const offsets2 = [];
|
|
6349
6523
|
let acc = 0;
|
|
@@ -6353,8 +6527,20 @@ function DataGrid({
|
|
|
6353
6527
|
}
|
|
6354
6528
|
return { widths: widths2, offsets: offsets2, totalWidth: acc };
|
|
6355
6529
|
}, [columns]);
|
|
6530
|
+
const order = React36.useMemo(() => {
|
|
6531
|
+
const idx = rows.map((_, i) => i);
|
|
6532
|
+
if (!sort) return idx;
|
|
6533
|
+
const dir = sort.dir === "asc" ? 1 : -1;
|
|
6534
|
+
return idx.sort((ia, ib) => dir * compareValues2(rows[ia]?.[sort.key] ?? null, rows[ib]?.[sort.key] ?? null));
|
|
6535
|
+
}, [rows, sort]);
|
|
6536
|
+
const toggleSort = (key) => {
|
|
6537
|
+
const nextDir = sort?.key !== key ? "asc" : sort.dir === "asc" ? "desc" : null;
|
|
6538
|
+
const next = nextDir ? { key, dir: nextDir } : null;
|
|
6539
|
+
if (sortProp === void 0) setInternalSort(next);
|
|
6540
|
+
onSortChange?.(next);
|
|
6541
|
+
};
|
|
6356
6542
|
const totalHeight = rows.length * rowHeight;
|
|
6357
|
-
|
|
6543
|
+
React36.useEffect(() => {
|
|
6358
6544
|
const el = scrollRef.current;
|
|
6359
6545
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
6360
6546
|
const measure = () => setViewport({ w: el.clientWidth, h: el.clientHeight });
|
|
@@ -6380,17 +6566,17 @@ function DataGrid({
|
|
|
6380
6566
|
}
|
|
6381
6567
|
const visibleRows = Array.from({ length: Math.max(0, rowEnd - rowStart) }, (_, i) => rowStart + i);
|
|
6382
6568
|
const visibleCols = Array.from({ length: Math.max(0, colEnd - colStart) }, (_, i) => colStart + i);
|
|
6383
|
-
const commit =
|
|
6569
|
+
const commit = React36.useCallback(() => {
|
|
6384
6570
|
if (!editing) return;
|
|
6385
6571
|
const col = columns[editing.col];
|
|
6386
|
-
onCellEdit?.({ row: editing.
|
|
6572
|
+
onCellEdit?.({ row: order[editing.disp], column: col.key, value: draft });
|
|
6387
6573
|
setEditing(null);
|
|
6388
|
-
}, [editing, columns, draft, onCellEdit]);
|
|
6389
|
-
const startEdit = (
|
|
6574
|
+
}, [editing, columns, draft, onCellEdit, order]);
|
|
6575
|
+
const startEdit = (disp, col) => {
|
|
6390
6576
|
const c = columns[col];
|
|
6391
6577
|
if (!(c.editable ?? editable)) return;
|
|
6392
|
-
setDraft(displayValue(rows[
|
|
6393
|
-
setEditing({
|
|
6578
|
+
setDraft(displayValue(rows[order[disp]]?.[c.key] ?? ""));
|
|
6579
|
+
setEditing({ disp, col });
|
|
6394
6580
|
};
|
|
6395
6581
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6396
6582
|
"div",
|
|
@@ -6398,12 +6584,12 @@ function DataGrid({
|
|
|
6398
6584
|
ref: scrollRef,
|
|
6399
6585
|
onScroll: (e) => setScroll({ top: e.currentTarget.scrollTop, left: e.currentTarget.scrollLeft }),
|
|
6400
6586
|
className: cx("relative overflow-auto rounded-lg border border-border bg-surface-raised text-sm", className),
|
|
6401
|
-
style: { height, ...style },
|
|
6587
|
+
style: { height, width, ...style },
|
|
6402
6588
|
role: "grid",
|
|
6403
6589
|
"aria-rowcount": rows.length,
|
|
6404
6590
|
"aria-colcount": columns.length,
|
|
6405
6591
|
children: [
|
|
6406
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: gutter + totalWidth, height: headerHeight + totalHeight }, children: [
|
|
6592
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: gutter + totalWidth + END_PAD, height: headerHeight + totalHeight + END_PAD }, children: [
|
|
6407
6593
|
rowNumbers && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6408
6594
|
"div",
|
|
6409
6595
|
{
|
|
@@ -6413,11 +6599,18 @@ function DataGrid({
|
|
|
6413
6599
|
),
|
|
6414
6600
|
visibleCols.map((ci) => {
|
|
6415
6601
|
const c = columns[ci];
|
|
6416
|
-
|
|
6602
|
+
const sortDir = sort?.key === c.key ? sort.dir : null;
|
|
6603
|
+
const canSort = colSortable(c);
|
|
6604
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6417
6605
|
"div",
|
|
6418
6606
|
{
|
|
6419
6607
|
role: "columnheader",
|
|
6420
|
-
|
|
6608
|
+
"aria-sort": sortDir ? sortDir === "asc" ? "ascending" : "descending" : void 0,
|
|
6609
|
+
onClick: canSort ? () => toggleSort(c.key) : void 0,
|
|
6610
|
+
className: cx(
|
|
6611
|
+
"flex items-center gap-1 border-b border-r border-border bg-surface px-3 font-medium text-foreground-secondary",
|
|
6612
|
+
canSort && "cursor-pointer select-none hover:text-foreground"
|
|
6613
|
+
),
|
|
6421
6614
|
style: {
|
|
6422
6615
|
position: "absolute",
|
|
6423
6616
|
top: scroll.top,
|
|
@@ -6427,38 +6620,42 @@ function DataGrid({
|
|
|
6427
6620
|
zIndex: 2,
|
|
6428
6621
|
justifyContent: c.align === "right" ? "flex-end" : c.align === "center" ? "center" : "flex-start"
|
|
6429
6622
|
},
|
|
6430
|
-
children:
|
|
6623
|
+
children: [
|
|
6624
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: c.label ?? c.key }),
|
|
6625
|
+
canSort && /* @__PURE__ */ jsxRuntime.jsx(SortCaret, { dir: sortDir })
|
|
6626
|
+
]
|
|
6431
6627
|
},
|
|
6432
6628
|
`h-${c.key}`
|
|
6433
6629
|
);
|
|
6434
6630
|
}),
|
|
6435
|
-
rowNumbers && visibleRows.map((
|
|
6631
|
+
rowNumbers && visibleRows.map((disp) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6436
6632
|
"div",
|
|
6437
6633
|
{
|
|
6438
6634
|
className: "flex items-center justify-center border-b border-r border-border bg-surface text-xs tabular-nums text-foreground-muted",
|
|
6439
|
-
style: { position: "absolute", left: scroll.left, top: headerHeight +
|
|
6440
|
-
children:
|
|
6635
|
+
style: { position: "absolute", left: scroll.left, top: headerHeight + disp * rowHeight, width: gutter, height: rowHeight, zIndex: 1 },
|
|
6636
|
+
children: disp + 1
|
|
6441
6637
|
},
|
|
6442
|
-
`g-${
|
|
6638
|
+
`g-${disp}`
|
|
6443
6639
|
)),
|
|
6444
|
-
visibleRows.map(
|
|
6445
|
-
|
|
6640
|
+
visibleRows.map((disp) => {
|
|
6641
|
+
const ri = order[disp];
|
|
6642
|
+
return visibleCols.map((ci) => {
|
|
6446
6643
|
const c = columns[ci];
|
|
6447
|
-
const isEditing = editing?.
|
|
6644
|
+
const isEditing = editing?.disp === disp && editing?.col === ci;
|
|
6448
6645
|
const canEdit = c.editable ?? editable;
|
|
6449
6646
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6450
6647
|
"div",
|
|
6451
6648
|
{
|
|
6452
6649
|
role: "gridcell",
|
|
6453
|
-
onDoubleClick: () => startEdit(
|
|
6650
|
+
onDoubleClick: () => startEdit(disp, ci),
|
|
6454
6651
|
className: cx(
|
|
6455
6652
|
"flex items-center border-b border-r border-border px-3",
|
|
6456
|
-
|
|
6653
|
+
disp % 2 ? "bg-surface-raised" : "bg-surface",
|
|
6457
6654
|
canEdit && "cursor-text"
|
|
6458
6655
|
),
|
|
6459
6656
|
style: {
|
|
6460
6657
|
position: "absolute",
|
|
6461
|
-
top: headerHeight +
|
|
6658
|
+
top: headerHeight + disp * rowHeight,
|
|
6462
6659
|
left: gutter + offsets[ci],
|
|
6463
6660
|
width: widths[ci],
|
|
6464
6661
|
height: rowHeight,
|
|
@@ -6479,16 +6676,22 @@ function DataGrid({
|
|
|
6479
6676
|
}
|
|
6480
6677
|
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-foreground", children: displayValue(rows[ri]?.[c.key] ?? "") })
|
|
6481
6678
|
},
|
|
6482
|
-
`${
|
|
6679
|
+
`${disp}-${c.key}`
|
|
6483
6680
|
);
|
|
6484
|
-
})
|
|
6485
|
-
)
|
|
6681
|
+
});
|
|
6682
|
+
})
|
|
6486
6683
|
] }),
|
|
6487
6684
|
rows.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-foreground-muted", style: { top: headerHeight }, children: emptyState })
|
|
6488
6685
|
]
|
|
6489
6686
|
}
|
|
6490
6687
|
);
|
|
6491
6688
|
}
|
|
6689
|
+
function SortCaret({ dir }) {
|
|
6690
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", className: "h-3 w-3 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 1.75, "aria-hidden": "true", children: [
|
|
6691
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 6.5 8 3.5l3 3", className: dir === "asc" ? "text-accent" : "text-foreground-muted opacity-50" }),
|
|
6692
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 9.5 8 12.5l3-3", className: dir === "desc" ? "text-accent" : "text-foreground-muted opacity-50" })
|
|
6693
|
+
] });
|
|
6694
|
+
}
|
|
6492
6695
|
function toColumns(cols) {
|
|
6493
6696
|
return cols.map((c) => typeof c === "string" ? { key: c, label: c } : { ...c, label: c.label ?? c.key });
|
|
6494
6697
|
}
|
|
@@ -6507,13 +6710,16 @@ var xlsxPromise = null;
|
|
|
6507
6710
|
var loadXlsx = () => xlsxPromise ??= import('xlsx');
|
|
6508
6711
|
var jspdfPromise = null;
|
|
6509
6712
|
var loadJspdf = () => jspdfPromise ??= import('jspdf');
|
|
6510
|
-
function
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6713
|
+
function coerceToCellType(prev, next) {
|
|
6714
|
+
if (typeof prev === "number") {
|
|
6715
|
+
const n = Number(next);
|
|
6716
|
+
return next.trim() !== "" && Number.isFinite(n) ? n : next;
|
|
6717
|
+
}
|
|
6718
|
+
if (typeof prev === "boolean") {
|
|
6719
|
+
if (/^(true|false)$/i.test(next.trim())) return next.trim().toLowerCase() === "true";
|
|
6720
|
+
return next;
|
|
6721
|
+
}
|
|
6722
|
+
return next;
|
|
6517
6723
|
}
|
|
6518
6724
|
function Spreadsheet({
|
|
6519
6725
|
source,
|
|
@@ -6524,15 +6730,18 @@ function Spreadsheet({
|
|
|
6524
6730
|
export: exportFormats = ["xlsx", "csv", "pdf"],
|
|
6525
6731
|
fileName,
|
|
6526
6732
|
virtualize = true,
|
|
6733
|
+
sortable = true,
|
|
6734
|
+
height = 480,
|
|
6735
|
+
width,
|
|
6527
6736
|
className = "",
|
|
6528
6737
|
style
|
|
6529
6738
|
}) {
|
|
6530
|
-
const [sheets, setSheets] =
|
|
6531
|
-
const [active, setActive] =
|
|
6532
|
-
const [status, setStatus] =
|
|
6533
|
-
const [error, setError] =
|
|
6534
|
-
const [reloadKey, setReloadKey] =
|
|
6535
|
-
|
|
6739
|
+
const [sheets, setSheets] = React36.useState(Array.isArray(source) ? source : null);
|
|
6740
|
+
const [active, setActive] = React36.useState(0);
|
|
6741
|
+
const [status, setStatus] = React36.useState(Array.isArray(source) ? "ready" : "loading");
|
|
6742
|
+
const [error, setError] = React36.useState(null);
|
|
6743
|
+
const [reloadKey, setReloadKey] = React36.useState(0);
|
|
6744
|
+
React36.useEffect(() => {
|
|
6536
6745
|
if (Array.isArray(source)) {
|
|
6537
6746
|
setSheets(source);
|
|
6538
6747
|
setStatus("ready");
|
|
@@ -6578,35 +6787,38 @@ function Spreadsheet({
|
|
|
6578
6787
|
};
|
|
6579
6788
|
}, [source, remote, reloadKey]);
|
|
6580
6789
|
const sheet = sheets?.[active];
|
|
6581
|
-
const columns =
|
|
6582
|
-
const plainRows =
|
|
6583
|
-
const handleCellEdit =
|
|
6790
|
+
const columns = React36.useMemo(() => sheet ? toColumns(sheet.columns) : [], [sheet]);
|
|
6791
|
+
const plainRows = React36.useMemo(() => sheet ? toPlainRows(sheet, columns) : [], [sheet, columns]);
|
|
6792
|
+
const handleCellEdit = React36.useCallback(({ row, column, value }) => {
|
|
6793
|
+
let coerced = value;
|
|
6584
6794
|
setSheets((prev) => {
|
|
6585
6795
|
if (!prev) return prev;
|
|
6586
6796
|
const next = prev.map((s, i) => i === active ? { ...s, rows: s.rows.map((r) => ({ ...r })) } : s);
|
|
6587
6797
|
const target = next[active];
|
|
6588
6798
|
const existing = target.rows[row]?.[column];
|
|
6799
|
+
const prevValue = cellValue(existing);
|
|
6800
|
+
coerced = coerceToCellType(prevValue, value);
|
|
6589
6801
|
if (existing != null && typeof existing === "object" && "value" in existing) {
|
|
6590
|
-
target.rows[row][column] = { ...existing, value };
|
|
6802
|
+
target.rows[row][column] = { ...existing, value: coerced };
|
|
6591
6803
|
} else {
|
|
6592
|
-
target.rows[row][column] =
|
|
6804
|
+
target.rows[row][column] = coerced;
|
|
6593
6805
|
}
|
|
6594
6806
|
onChange?.(next);
|
|
6595
6807
|
return next;
|
|
6596
6808
|
});
|
|
6597
|
-
onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value });
|
|
6809
|
+
onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value: coerced });
|
|
6598
6810
|
}, [active, onCellEdit, onChange, sheets]);
|
|
6599
|
-
const baseName =
|
|
6811
|
+
const baseName = React36.useMemo(
|
|
6600
6812
|
() => (fileName || (typeof source === "object" && "name" in source ? sourceName(source) : null) || "spreadsheet").replace(/\.[^.]+$/, ""),
|
|
6601
6813
|
[fileName, source]
|
|
6602
6814
|
);
|
|
6603
|
-
const sheetAoa =
|
|
6815
|
+
const sheetAoa = React36.useCallback((s) => {
|
|
6604
6816
|
const cols = toColumns(s.columns);
|
|
6605
6817
|
const header = cols.map((c) => typeof c.label === "string" ? c.label : c.key);
|
|
6606
6818
|
const body = s.rows.map((r) => cols.map((c) => cellValue(r[c.key])));
|
|
6607
6819
|
return [header, ...body];
|
|
6608
6820
|
}, []);
|
|
6609
|
-
const exportXlsx =
|
|
6821
|
+
const exportXlsx = React36.useCallback(async () => {
|
|
6610
6822
|
if (!sheets) return;
|
|
6611
6823
|
const XLSX = await loadXlsx();
|
|
6612
6824
|
const wb = XLSX.utils.book_new();
|
|
@@ -6615,9 +6827,9 @@ function Spreadsheet({
|
|
|
6615
6827
|
XLSX.utils.book_append_sheet(wb, ws, (s.name || "Sheet").slice(0, 31));
|
|
6616
6828
|
});
|
|
6617
6829
|
const out = XLSX.write(wb, { bookType: "xlsx", type: "array" });
|
|
6618
|
-
|
|
6830
|
+
downloadBlob(new Blob([out], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }), `${baseName}.xlsx`);
|
|
6619
6831
|
}, [sheets, sheetAoa, baseName]);
|
|
6620
|
-
const exportCsv =
|
|
6832
|
+
const exportCsv = React36.useCallback(() => {
|
|
6621
6833
|
if (!sheet) return;
|
|
6622
6834
|
const aoa = sheetAoa(sheet);
|
|
6623
6835
|
const esc = (v) => {
|
|
@@ -6625,9 +6837,9 @@ function Spreadsheet({
|
|
|
6625
6837
|
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
|
6626
6838
|
};
|
|
6627
6839
|
const csv = aoa.map((row) => row.map(esc).join(",")).join("\r\n");
|
|
6628
|
-
|
|
6840
|
+
downloadBlob(new Blob([`\uFEFF${csv}`], { type: "text/csv;charset=utf-8" }), `${baseName}.csv`);
|
|
6629
6841
|
}, [sheet, sheetAoa, baseName]);
|
|
6630
|
-
const exportPdf =
|
|
6842
|
+
const exportPdf = React36.useCallback(async () => {
|
|
6631
6843
|
if (!sheet) return;
|
|
6632
6844
|
const { jsPDF } = await loadJspdf();
|
|
6633
6845
|
const doc = new jsPDF({ orientation: "landscape", unit: "pt", format: "a4" });
|
|
@@ -6668,52 +6880,89 @@ function Spreadsheet({
|
|
|
6668
6880
|
else void exportPdf();
|
|
6669
6881
|
};
|
|
6670
6882
|
if (status === "error") {
|
|
6671
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style, children: [
|
|
6883
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style: { height, width, ...style }, children: [
|
|
6672
6884
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-status-error", children: "Couldn\u2019t load the spreadsheet" }),
|
|
6673
6885
|
error?.message && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-xs text-foreground-muted", children: error.message }),
|
|
6674
6886
|
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { content: "Retry", size: "sm", variant: "outline", onClick: () => setReloadKey((k) => k + 1) })
|
|
6675
6887
|
] });
|
|
6676
6888
|
}
|
|
6677
6889
|
if (status === "loading" || !sheets) {
|
|
6678
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("rounded-lg border border-border bg-surface-raised p-4", className), style, children: [
|
|
6890
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("overflow-hidden rounded-lg border border-border bg-surface-raised p-4", className), style: { height, width, ...style }, children: [
|
|
6679
6891
|
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 32, className: "mb-3 rounded" }),
|
|
6680
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height:
|
|
6892
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: "calc(100% - 44px)", className: "rounded" })
|
|
6681
6893
|
] });
|
|
6682
6894
|
}
|
|
6683
6895
|
const formats = exportFormats || [];
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6896
|
+
const exportLabels = {
|
|
6897
|
+
xlsx: "Excel workbook (.xlsx)",
|
|
6898
|
+
csv: "CSV \u2014 this sheet (.csv)",
|
|
6899
|
+
pdf: "PDF table (.pdf)"
|
|
6900
|
+
};
|
|
6901
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height, width, ...style }, children: [
|
|
6902
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center gap-2 border-b border-border bg-surface px-3 py-1.5", children: [
|
|
6903
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-foreground", children: sheet?.name || "Sheet 1" }),
|
|
6904
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden flex-shrink-0 text-xs tabular-nums text-foreground-muted sm:inline", children: [
|
|
6905
|
+
plainRows.length.toLocaleString(),
|
|
6906
|
+
" ",
|
|
6907
|
+
plainRows.length === 1 ? "row" : "rows",
|
|
6908
|
+
" \xB7 ",
|
|
6909
|
+
columns.length,
|
|
6910
|
+
" cols"
|
|
6911
|
+
] }),
|
|
6912
|
+
formats.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6913
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-5 w-px flex-shrink-0 bg-border", "aria-hidden": "true" }),
|
|
6914
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6915
|
+
MenuButton,
|
|
6916
|
+
{
|
|
6917
|
+
label: "Export",
|
|
6918
|
+
size: "sm",
|
|
6919
|
+
variant: "outline",
|
|
6920
|
+
align: "end",
|
|
6921
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon2, {}),
|
|
6922
|
+
items: formats.map((fmt) => ({
|
|
6923
|
+
key: fmt,
|
|
6924
|
+
label: exportLabels[fmt],
|
|
6925
|
+
onSelect: () => runExport(fmt)
|
|
6926
|
+
}))
|
|
6927
|
+
}
|
|
6928
|
+
)
|
|
6929
|
+
] })
|
|
6702
6930
|
] }),
|
|
6703
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6931
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6704
6932
|
DataGrid,
|
|
6705
6933
|
{
|
|
6706
6934
|
columns,
|
|
6707
6935
|
rows: plainRows,
|
|
6708
6936
|
editable,
|
|
6937
|
+
sortable,
|
|
6709
6938
|
virtualize,
|
|
6710
|
-
onCellEdit: handleCellEdit
|
|
6711
|
-
|
|
6712
|
-
|
|
6939
|
+
onCellEdit: handleCellEdit,
|
|
6940
|
+
height: "100%",
|
|
6941
|
+
className: "!rounded-none !border-0"
|
|
6942
|
+
},
|
|
6943
|
+
active
|
|
6944
|
+
) }),
|
|
6945
|
+
sheets.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex flex-shrink-0 items-center gap-1 overflow-x-auto border-t border-border bg-surface px-2 py-1", children: sheets.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6946
|
+
"button",
|
|
6947
|
+
{
|
|
6948
|
+
role: "tab",
|
|
6949
|
+
type: "button",
|
|
6950
|
+
"aria-selected": i === active,
|
|
6951
|
+
onClick: () => setActive(i),
|
|
6952
|
+
className: cx(
|
|
6953
|
+
"flex-shrink-0 rounded-md px-3 py-1 text-xs font-medium transition-colors",
|
|
6954
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
6955
|
+
i === active ? "bg-surface-raised text-foreground shadow-sm" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
|
|
6956
|
+
),
|
|
6957
|
+
children: s.name || `Sheet ${i + 1}`
|
|
6958
|
+
},
|
|
6959
|
+
`${s.name}-${i}`
|
|
6960
|
+
)) })
|
|
6713
6961
|
] });
|
|
6714
6962
|
}
|
|
6963
|
+
var DownloadIcon2 = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
|
|
6715
6964
|
function ThemeSwitch({ checked, onChange, label = "Toggle dark mode", className = "" }) {
|
|
6716
|
-
const id =
|
|
6965
|
+
const id = React36.useId();
|
|
6717
6966
|
return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: `flex items-center gap-2 cursor-pointer select-none ${className}`.trim(), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6718
6967
|
SwitchPrimitive__namespace.Root,
|
|
6719
6968
|
{
|
|
@@ -6811,8 +7060,8 @@ function FlyoutItems({ items }) {
|
|
|
6811
7060
|
}) });
|
|
6812
7061
|
}
|
|
6813
7062
|
function CollapsedFlyout({ item, trigger }) {
|
|
6814
|
-
const [open, setOpen] =
|
|
6815
|
-
const closeTimer =
|
|
7063
|
+
const [open, setOpen] = React36.useState(false);
|
|
7064
|
+
const closeTimer = React36__default.default.useRef(void 0);
|
|
6816
7065
|
const openNow = () => {
|
|
6817
7066
|
window.clearTimeout(closeTimer.current);
|
|
6818
7067
|
setOpen(true);
|
|
@@ -6821,7 +7070,7 @@ function CollapsedFlyout({ item, trigger }) {
|
|
|
6821
7070
|
window.clearTimeout(closeTimer.current);
|
|
6822
7071
|
closeTimer.current = window.setTimeout(() => setOpen(false), 150);
|
|
6823
7072
|
};
|
|
6824
|
-
|
|
7073
|
+
React36__default.default.useEffect(() => () => window.clearTimeout(closeTimer.current), []);
|
|
6825
7074
|
return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2__namespace.Root, { open, onOpenChange: setOpen, modal: false, children: [
|
|
6826
7075
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6827
7076
|
DropdownMenu2__namespace.Trigger,
|
|
@@ -6859,7 +7108,7 @@ function NavItem({
|
|
|
6859
7108
|
depth = 0
|
|
6860
7109
|
}) {
|
|
6861
7110
|
const hasChildren = !!(item.items && item.items.length);
|
|
6862
|
-
const [open, setOpen] =
|
|
7111
|
+
const [open, setOpen] = React36.useState(item.defaultOpen ?? (hasChildren && hasActiveDescendant(item)));
|
|
6863
7112
|
const handleClick = () => {
|
|
6864
7113
|
if (hasChildren && isExpanded) setOpen((o) => !o);
|
|
6865
7114
|
item.onClick?.();
|
|
@@ -6997,7 +7246,7 @@ function Sidebar({
|
|
|
6997
7246
|
}
|
|
6998
7247
|
) });
|
|
6999
7248
|
}
|
|
7000
|
-
var MegaMenuContext =
|
|
7249
|
+
var MegaMenuContext = React36.createContext({ align: "start" });
|
|
7001
7250
|
function MegaMenu({
|
|
7002
7251
|
children,
|
|
7003
7252
|
align = "start",
|
|
@@ -7028,7 +7277,7 @@ function MegaMenu({
|
|
|
7028
7277
|
}
|
|
7029
7278
|
var TOP_ITEM = "group/top inline-flex items-center gap-1.5 h-10 px-3 rounded-md text-sm font-medium select-none text-foreground-secondary hover:text-foreground hover:bg-surface-raised data-[state=open]:text-accent data-[active]:text-accent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent";
|
|
7030
7279
|
function MegaMenuItem({ label, icon, href, children, className = "" }) {
|
|
7031
|
-
const { align } =
|
|
7280
|
+
const { align } = React36.useContext(MegaMenuContext);
|
|
7032
7281
|
const pos = align === "center" ? "left-1/2 -translate-x-1/2" : align === "end" ? "right-0" : "left-0";
|
|
7033
7282
|
if (!children) {
|
|
7034
7283
|
return /* @__PURE__ */ jsxRuntime.jsx(NavigationMenu__namespace.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(NavigationMenu__namespace.Link, { href, className: cx(TOP_ITEM, className), children: [
|
|
@@ -7113,8 +7362,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
|
|
|
7113
7362
|
function MegaMenuFeatured({ children, className = "" }) {
|
|
7114
7363
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx("min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className), children });
|
|
7115
7364
|
}
|
|
7116
|
-
var elementsOfType = (children, type) =>
|
|
7117
|
-
(c) =>
|
|
7365
|
+
var elementsOfType = (children, type) => React36__default.default.Children.toArray(children).filter(
|
|
7366
|
+
(c) => React36__default.default.isValidElement(c) && c.type === type
|
|
7118
7367
|
);
|
|
7119
7368
|
var MOBILE_CHEVRON = /* @__PURE__ */ jsxRuntime.jsx(
|
|
7120
7369
|
"svg",
|
|
@@ -7151,9 +7400,9 @@ function MobileLinkRow({ link, onNavigate }) {
|
|
|
7151
7400
|
);
|
|
7152
7401
|
}
|
|
7153
7402
|
function MobilePanel({ panel, onNavigate }) {
|
|
7154
|
-
const nodes =
|
|
7403
|
+
const nodes = React36__default.default.Children.toArray(panel.props.children);
|
|
7155
7404
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
|
|
7156
|
-
if (!
|
|
7405
|
+
if (!React36__default.default.isValidElement(node)) return null;
|
|
7157
7406
|
const el = node;
|
|
7158
7407
|
if (el.type === MegaMenuSection) {
|
|
7159
7408
|
const { title, children } = el.props;
|
|
@@ -7172,8 +7421,8 @@ function MegaMenuMobile({
|
|
|
7172
7421
|
children,
|
|
7173
7422
|
label
|
|
7174
7423
|
}) {
|
|
7175
|
-
const [open, setOpen] =
|
|
7176
|
-
const [expanded, setExpanded] =
|
|
7424
|
+
const [open, setOpen] = React36.useState(false);
|
|
7425
|
+
const [expanded, setExpanded] = React36.useState(null);
|
|
7177
7426
|
const items = elementsOfType(children, MegaMenuItem);
|
|
7178
7427
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden w-full", children: [
|
|
7179
7428
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -7246,17 +7495,17 @@ function AppShell({
|
|
|
7246
7495
|
children,
|
|
7247
7496
|
className = ""
|
|
7248
7497
|
}) {
|
|
7249
|
-
const [expanded, setExpanded] =
|
|
7250
|
-
const [isMobile, setIsMobile] =
|
|
7251
|
-
const [mobileOpen, setMobileOpen] =
|
|
7252
|
-
|
|
7498
|
+
const [expanded, setExpanded] = React36.useState(sidebarDefaultExpanded);
|
|
7499
|
+
const [isMobile, setIsMobile] = React36.useState(false);
|
|
7500
|
+
const [mobileOpen, setMobileOpen] = React36.useState(false);
|
|
7501
|
+
React36.useEffect(() => {
|
|
7253
7502
|
const mq = window.matchMedia("(max-width: 767px)");
|
|
7254
7503
|
const update = (e) => setIsMobile(e.matches);
|
|
7255
7504
|
update(mq);
|
|
7256
7505
|
mq.addEventListener("change", update);
|
|
7257
7506
|
return () => mq.removeEventListener("change", update);
|
|
7258
7507
|
}, []);
|
|
7259
|
-
|
|
7508
|
+
React36.useEffect(() => {
|
|
7260
7509
|
if (!isMobile) setMobileOpen(false);
|
|
7261
7510
|
}, [isMobile]);
|
|
7262
7511
|
const hasSidebar = sidebarSections.length > 0;
|
|
@@ -7383,7 +7632,7 @@ function SecureLayout({
|
|
|
7383
7632
|
className = ""
|
|
7384
7633
|
}) {
|
|
7385
7634
|
const reduced = framerMotion.useReducedMotion();
|
|
7386
|
-
const cbs =
|
|
7635
|
+
const cbs = React36.useRef({ canAccess, onGranted, onDeny });
|
|
7387
7636
|
cbs.current = { canAccess, onGranted, onDeny };
|
|
7388
7637
|
const rolesKey = JSON.stringify(roles);
|
|
7389
7638
|
const requiredRolesKey = JSON.stringify(requiredRoles);
|
|
@@ -7398,10 +7647,10 @@ function SecureLayout({
|
|
|
7398
7647
|
if (requiredPermissions?.length && !has(permissions, requiredPermissions, requireAllPermissions)) return false;
|
|
7399
7648
|
return true;
|
|
7400
7649
|
};
|
|
7401
|
-
const [state, setState] =
|
|
7650
|
+
const [state, setState] = React36.useState(
|
|
7402
7651
|
() => !passesSync() ? "denied" : canAccess ? "checking" : "granted"
|
|
7403
7652
|
);
|
|
7404
|
-
|
|
7653
|
+
React36.useEffect(() => {
|
|
7405
7654
|
let cancelled = false;
|
|
7406
7655
|
const { canAccess: check, onGranted: granted, onDeny: deny } = cbs.current;
|
|
7407
7656
|
const finish = (ok) => {
|
|
@@ -7562,10 +7811,10 @@ function ThemeProvider({
|
|
|
7562
7811
|
className = "",
|
|
7563
7812
|
style
|
|
7564
7813
|
}) {
|
|
7565
|
-
const id =
|
|
7814
|
+
const id = React36__default.default.useId().replace(/:/g, "");
|
|
7566
7815
|
const scopeClass = `geo-th-${id}`;
|
|
7567
|
-
const divRef =
|
|
7568
|
-
|
|
7816
|
+
const divRef = React36.useRef(null);
|
|
7817
|
+
React36.useEffect(() => {
|
|
7569
7818
|
const el = divRef.current;
|
|
7570
7819
|
if (!el) return;
|
|
7571
7820
|
if (colorScheme === "auto") return;
|
|
@@ -7580,8 +7829,8 @@ function ThemeProvider({
|
|
|
7580
7829
|
}
|
|
7581
7830
|
el.classList.toggle("dark", colorScheme === "dark");
|
|
7582
7831
|
}, [colorScheme]);
|
|
7583
|
-
const lightVars =
|
|
7584
|
-
const darkVarStr =
|
|
7832
|
+
const lightVars = React36.useMemo(() => toCssVars(theme), [theme]);
|
|
7833
|
+
const darkVarStr = React36.useMemo(() => {
|
|
7585
7834
|
if (!darkTheme) return "";
|
|
7586
7835
|
const dvars = toCssVars(darkTheme);
|
|
7587
7836
|
if (!Object.keys(dvars).length) return "";
|
|
@@ -7623,7 +7872,7 @@ function NumberInput({
|
|
|
7623
7872
|
readOnly = false,
|
|
7624
7873
|
precision
|
|
7625
7874
|
}) {
|
|
7626
|
-
const errorId =
|
|
7875
|
+
const errorId = React36.useId();
|
|
7627
7876
|
const hasError = errorMessage != null;
|
|
7628
7877
|
const inferredPrecision = precision ?? (Number.isInteger(step) ? 0 : String(step).split(".")[1]?.length ?? 0);
|
|
7629
7878
|
const round = (n) => {
|
|
@@ -7754,8 +8003,8 @@ function Password({
|
|
|
7754
8003
|
showIcon,
|
|
7755
8004
|
hideIcon
|
|
7756
8005
|
}) {
|
|
7757
|
-
const [visible, setVisible] =
|
|
7758
|
-
const errorId =
|
|
8006
|
+
const [visible, setVisible] = React36.useState(false);
|
|
8007
|
+
const errorId = React36.useId();
|
|
7759
8008
|
const hasError = errorMessage != null;
|
|
7760
8009
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7761
8010
|
Field,
|
|
@@ -7855,7 +8104,7 @@ function PasswordStrength({
|
|
|
7855
8104
|
className = "",
|
|
7856
8105
|
style
|
|
7857
8106
|
}) {
|
|
7858
|
-
const { score, label } =
|
|
8107
|
+
const { score, label } = React36.useMemo(() => scorer(value), [scorer, value]);
|
|
7859
8108
|
const showMatch = confirmValue != null && (value.length > 0 || confirmValue.length > 0);
|
|
7860
8109
|
const matches = value.length > 0 && value === confirmValue;
|
|
7861
8110
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col gap-2", className), style, "aria-live": "polite", children: [
|
|
@@ -7914,8 +8163,8 @@ function RadioTile({
|
|
|
7914
8163
|
errorMessage,
|
|
7915
8164
|
className
|
|
7916
8165
|
}) {
|
|
7917
|
-
const groupId =
|
|
7918
|
-
const errorId =
|
|
8166
|
+
const groupId = React36.useId();
|
|
8167
|
+
const errorId = React36.useId();
|
|
7919
8168
|
const hasError = errorMessage != null;
|
|
7920
8169
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7921
8170
|
Field,
|
|
@@ -7990,7 +8239,7 @@ function Checkbox({
|
|
|
7990
8239
|
}) {
|
|
7991
8240
|
const isChecked = checked ?? value ?? false;
|
|
7992
8241
|
const labelFirst = labelPosition === "left";
|
|
7993
|
-
const errorId =
|
|
8242
|
+
const errorId = React36.useId();
|
|
7994
8243
|
const hasError = errorMessage != null;
|
|
7995
8244
|
const box = /* @__PURE__ */ jsxRuntime.jsx(
|
|
7996
8245
|
CheckboxPrimitive__namespace.Root,
|
|
@@ -8098,8 +8347,8 @@ function RadioGroup({
|
|
|
8098
8347
|
className,
|
|
8099
8348
|
errorMessage
|
|
8100
8349
|
}) {
|
|
8101
|
-
const errorId =
|
|
8102
|
-
const groupId =
|
|
8350
|
+
const errorId = React36.useId();
|
|
8351
|
+
const groupId = React36.useId();
|
|
8103
8352
|
const hasError = errorMessage != null;
|
|
8104
8353
|
const labelFirst = labelPosition === "left";
|
|
8105
8354
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8199,11 +8448,11 @@ function Switch({
|
|
|
8199
8448
|
disabled,
|
|
8200
8449
|
errorMessage
|
|
8201
8450
|
}) {
|
|
8202
|
-
const id =
|
|
8203
|
-
const errorId =
|
|
8451
|
+
const id = React36.useId();
|
|
8452
|
+
const errorId = React36.useId();
|
|
8204
8453
|
const hasError = errorMessage != null;
|
|
8205
8454
|
const isControlled = checked !== void 0;
|
|
8206
|
-
const [internal, setInternal] =
|
|
8455
|
+
const [internal, setInternal] = React36.useState(defaultChecked);
|
|
8207
8456
|
const isOn = isControlled ? checked : internal;
|
|
8208
8457
|
const handle = (c) => {
|
|
8209
8458
|
if (!isControlled) setInternal(c);
|
|
@@ -8279,11 +8528,11 @@ function MultiTagRow({
|
|
|
8279
8528
|
labelFor,
|
|
8280
8529
|
onRemove
|
|
8281
8530
|
}) {
|
|
8282
|
-
const wrapRef =
|
|
8283
|
-
const measureRef =
|
|
8284
|
-
const [visibleCount, setVisibleCount] =
|
|
8531
|
+
const wrapRef = React36.useRef(null);
|
|
8532
|
+
const measureRef = React36.useRef(null);
|
|
8533
|
+
const [visibleCount, setVisibleCount] = React36.useState(values.length);
|
|
8285
8534
|
const key = values.map(String).join("|");
|
|
8286
|
-
|
|
8535
|
+
React36.useLayoutEffect(() => {
|
|
8287
8536
|
const wrap = wrapRef.current;
|
|
8288
8537
|
const measure = measureRef.current;
|
|
8289
8538
|
if (!wrap || !measure) return;
|
|
@@ -8375,18 +8624,21 @@ function Dropdown({
|
|
|
8375
8624
|
labelStyle = {},
|
|
8376
8625
|
placeholder,
|
|
8377
8626
|
size = "md",
|
|
8378
|
-
className = ""
|
|
8627
|
+
className = "",
|
|
8628
|
+
container
|
|
8379
8629
|
}) {
|
|
8380
|
-
const
|
|
8381
|
-
const
|
|
8382
|
-
const [
|
|
8383
|
-
const [
|
|
8384
|
-
const
|
|
8630
|
+
const dialogContainer = useDialogContainer();
|
|
8631
|
+
const portalContainer = container ?? dialogContainer ?? void 0;
|
|
8632
|
+
const [open, setOpen] = React36.useState(false);
|
|
8633
|
+
const [selectedItems, setSelectedItems] = React36.useState([]);
|
|
8634
|
+
const [searchTerm, setSearchTerm] = React36.useState("");
|
|
8635
|
+
const [innerItems, setInnerItems] = React36.useState([]);
|
|
8636
|
+
const errorId = React36.useId();
|
|
8385
8637
|
const hasError = errorMessage != null;
|
|
8386
|
-
|
|
8638
|
+
React36.useEffect(() => {
|
|
8387
8639
|
setInnerItems(items);
|
|
8388
8640
|
}, [items]);
|
|
8389
|
-
|
|
8641
|
+
React36.useEffect(() => {
|
|
8390
8642
|
if (isMultiselect && Array.isArray(value)) {
|
|
8391
8643
|
setSelectedItems(value);
|
|
8392
8644
|
}
|
|
@@ -8482,7 +8734,7 @@ function Dropdown({
|
|
|
8482
8734
|
]
|
|
8483
8735
|
}
|
|
8484
8736
|
) }),
|
|
8485
|
-
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8737
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8486
8738
|
Popover__namespace.Content,
|
|
8487
8739
|
{
|
|
8488
8740
|
align: "start",
|
|
@@ -8579,19 +8831,19 @@ function AutoComplete({
|
|
|
8579
8831
|
required,
|
|
8580
8832
|
htmlFor
|
|
8581
8833
|
}) {
|
|
8582
|
-
const errorId =
|
|
8834
|
+
const errorId = React36.useId();
|
|
8583
8835
|
const hasError = errorMessage != null;
|
|
8584
|
-
const [term, setTerm] =
|
|
8585
|
-
const [open, setOpen] =
|
|
8586
|
-
const [asyncItems, setAsyncItems] =
|
|
8587
|
-
const [loading, setLoading] =
|
|
8836
|
+
const [term, setTerm] = React36.useState("");
|
|
8837
|
+
const [open, setOpen] = React36.useState(false);
|
|
8838
|
+
const [asyncItems, setAsyncItems] = React36.useState([]);
|
|
8839
|
+
const [loading, setLoading] = React36.useState(false);
|
|
8588
8840
|
const isAsync = typeof onSearch === "function";
|
|
8589
|
-
const debounceRef =
|
|
8590
|
-
const requestIdRef =
|
|
8841
|
+
const debounceRef = React36.useRef(null);
|
|
8842
|
+
const requestIdRef = React36.useRef(0);
|
|
8591
8843
|
const staticFiltered = isAsync || !items ? [] : term.trim() ? items.filter(
|
|
8592
8844
|
({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
|
|
8593
8845
|
) : [];
|
|
8594
|
-
|
|
8846
|
+
React36.useEffect(() => {
|
|
8595
8847
|
if (!isAsync) return;
|
|
8596
8848
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8597
8849
|
if (!term.trim()) {
|
|
@@ -8748,15 +9000,15 @@ function TreeSelect({
|
|
|
8748
9000
|
defaultExpandedKeys = [],
|
|
8749
9001
|
size = "md"
|
|
8750
9002
|
}) {
|
|
8751
|
-
const errorId =
|
|
9003
|
+
const errorId = React36.useId();
|
|
8752
9004
|
const hasError = errorMessage != null;
|
|
8753
|
-
const [open, setOpen] =
|
|
8754
|
-
const [expanded, setExpanded] =
|
|
8755
|
-
const [activeIndex, setActiveIndex] =
|
|
8756
|
-
const listRef =
|
|
8757
|
-
const visible =
|
|
8758
|
-
const didSyncOnOpenRef =
|
|
8759
|
-
|
|
9005
|
+
const [open, setOpen] = React36.useState(false);
|
|
9006
|
+
const [expanded, setExpanded] = React36.useState(() => new Set(defaultExpandedKeys));
|
|
9007
|
+
const [activeIndex, setActiveIndex] = React36.useState(0);
|
|
9008
|
+
const listRef = React36.useRef(null);
|
|
9009
|
+
const visible = React36.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
|
|
9010
|
+
const didSyncOnOpenRef = React36.useRef(false);
|
|
9011
|
+
React36.useEffect(() => {
|
|
8760
9012
|
if (!open) {
|
|
8761
9013
|
didSyncOnOpenRef.current = false;
|
|
8762
9014
|
return;
|
|
@@ -8766,7 +9018,7 @@ function TreeSelect({
|
|
|
8766
9018
|
setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
|
|
8767
9019
|
didSyncOnOpenRef.current = true;
|
|
8768
9020
|
}, [open, value]);
|
|
8769
|
-
const selectedNode =
|
|
9021
|
+
const selectedNode = React36.useMemo(
|
|
8770
9022
|
() => value != null ? findNodeByKey(items, value) : null,
|
|
8771
9023
|
[items, value]
|
|
8772
9024
|
);
|
|
@@ -8998,11 +9250,11 @@ function FileInput({
|
|
|
8998
9250
|
required,
|
|
8999
9251
|
icon
|
|
9000
9252
|
}) {
|
|
9001
|
-
const inputRef =
|
|
9002
|
-
const errorId =
|
|
9003
|
-
const [files, setFiles] =
|
|
9004
|
-
const [dragging, setDragging] =
|
|
9005
|
-
const [sizeError, setSizeError] =
|
|
9253
|
+
const inputRef = React36.useRef(null);
|
|
9254
|
+
const errorId = React36.useId();
|
|
9255
|
+
const [files, setFiles] = React36.useState([]);
|
|
9256
|
+
const [dragging, setDragging] = React36.useState(false);
|
|
9257
|
+
const [sizeError, setSizeError] = React36.useState(null);
|
|
9006
9258
|
const effectiveError = errorMessage ?? sizeError ?? void 0;
|
|
9007
9259
|
const openPicker = () => {
|
|
9008
9260
|
if (!disabled) inputRef.current?.click();
|
|
@@ -9193,30 +9445,30 @@ function DatePicker({
|
|
|
9193
9445
|
size = "md",
|
|
9194
9446
|
className = ""
|
|
9195
9447
|
}) {
|
|
9196
|
-
const errorId =
|
|
9448
|
+
const errorId = React36.useId();
|
|
9197
9449
|
const hasError = errorMessage != null;
|
|
9198
|
-
const [open, setOpen] =
|
|
9199
|
-
const [viewMonth, setViewMonth] =
|
|
9200
|
-
const [focusDate, setFocusDate] =
|
|
9201
|
-
const [view, setView] =
|
|
9202
|
-
const gridRef =
|
|
9203
|
-
|
|
9450
|
+
const [open, setOpen] = React36.useState(false);
|
|
9451
|
+
const [viewMonth, setViewMonth] = React36.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
|
|
9452
|
+
const [focusDate, setFocusDate] = React36.useState(() => value ?? /* @__PURE__ */ new Date());
|
|
9453
|
+
const [view, setView] = React36.useState("days");
|
|
9454
|
+
const gridRef = React36.useRef(null);
|
|
9455
|
+
React36.useEffect(() => {
|
|
9204
9456
|
if (!open) return;
|
|
9205
9457
|
const target = value ?? /* @__PURE__ */ new Date();
|
|
9206
9458
|
setViewMonth(startOfMonth2(target));
|
|
9207
9459
|
setFocusDate(target);
|
|
9208
9460
|
setView("days");
|
|
9209
9461
|
}, [open, value]);
|
|
9210
|
-
|
|
9462
|
+
React36.useEffect(() => {
|
|
9211
9463
|
if (!open) return;
|
|
9212
9464
|
const cell = gridRef.current?.querySelector(`[data-day="${defaultFormat3(focusDate)}"]`);
|
|
9213
9465
|
cell?.focus();
|
|
9214
9466
|
}, [open, focusDate]);
|
|
9215
|
-
const weekdays =
|
|
9467
|
+
const weekdays = React36.useMemo(() => {
|
|
9216
9468
|
const ordered = WEEKDAY_SHORT.slice(weekStartsOn).concat(WEEKDAY_SHORT.slice(0, weekStartsOn));
|
|
9217
9469
|
return ordered;
|
|
9218
9470
|
}, [weekStartsOn]);
|
|
9219
|
-
const grid =
|
|
9471
|
+
const grid = React36.useMemo(() => buildGrid(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
|
|
9220
9472
|
const isDisabled = (d) => {
|
|
9221
9473
|
if (min && d < min) return true;
|
|
9222
9474
|
if (max && d > max) return true;
|
|
@@ -9507,10 +9759,10 @@ function TextArea({
|
|
|
9507
9759
|
style,
|
|
9508
9760
|
inputStyle
|
|
9509
9761
|
}) {
|
|
9510
|
-
const errorId =
|
|
9762
|
+
const errorId = React36.useId();
|
|
9511
9763
|
const hasError = errorMessage != null;
|
|
9512
|
-
const ref =
|
|
9513
|
-
|
|
9764
|
+
const ref = React36.useRef(null);
|
|
9765
|
+
React36.useLayoutEffect(() => {
|
|
9514
9766
|
if (!autoGrow) return;
|
|
9515
9767
|
const el = ref.current;
|
|
9516
9768
|
if (!el) return;
|
|
@@ -9582,14 +9834,14 @@ function Slider({
|
|
|
9582
9834
|
name,
|
|
9583
9835
|
htmlFor
|
|
9584
9836
|
}) {
|
|
9585
|
-
const errorId =
|
|
9837
|
+
const errorId = React36.useId();
|
|
9586
9838
|
const hasError = errorMessage != null;
|
|
9587
9839
|
const isRange = Array.isArray(value ?? defaultValue);
|
|
9588
|
-
const [internal, setInternal] =
|
|
9840
|
+
const [internal, setInternal] = React36.useState(
|
|
9589
9841
|
() => toArray(value) ?? toArray(defaultValue) ?? [min]
|
|
9590
9842
|
);
|
|
9591
9843
|
const current = toArray(value) ?? internal;
|
|
9592
|
-
const [dragging, setDragging] =
|
|
9844
|
+
const [dragging, setDragging] = React36.useState(false);
|
|
9593
9845
|
const emit = (arr) => {
|
|
9594
9846
|
setInternal(arr);
|
|
9595
9847
|
const next = isRange ? [arr[0], arr[1]] : arr[0];
|
|
@@ -9684,11 +9936,11 @@ function TagsInput({
|
|
|
9684
9936
|
validate,
|
|
9685
9937
|
separators = ["Enter", ","]
|
|
9686
9938
|
}) {
|
|
9687
|
-
const errorId =
|
|
9688
|
-
const inputRef =
|
|
9689
|
-
const [internal, setInternal] =
|
|
9690
|
-
const [draft, setDraft] =
|
|
9691
|
-
const [localError, setLocalError] =
|
|
9939
|
+
const errorId = React36.useId();
|
|
9940
|
+
const inputRef = React36.useRef(null);
|
|
9941
|
+
const [internal, setInternal] = React36.useState(defaultValue ?? []);
|
|
9942
|
+
const [draft, setDraft] = React36.useState("");
|
|
9943
|
+
const [localError, setLocalError] = React36.useState(null);
|
|
9692
9944
|
const tags = value ?? internal;
|
|
9693
9945
|
const hasError = errorMessage != null || localError != null;
|
|
9694
9946
|
const errorText = errorMessage ?? localError ?? void 0;
|
|
@@ -9819,9 +10071,9 @@ function OtpInput({
|
|
|
9819
10071
|
className,
|
|
9820
10072
|
groupAfter
|
|
9821
10073
|
}) {
|
|
9822
|
-
const errorId =
|
|
10074
|
+
const errorId = React36.useId();
|
|
9823
10075
|
const hasError = errorMessage != null;
|
|
9824
|
-
const refs =
|
|
10076
|
+
const refs = React36.useRef([]);
|
|
9825
10077
|
const chars = Array.from({ length }, (_, i) => value[i] ?? "");
|
|
9826
10078
|
const pattern = mode === "numeric" ? /[0-9]/ : /[a-zA-Z0-9]/;
|
|
9827
10079
|
const emit = (next) => {
|
|
@@ -9870,7 +10122,7 @@ function OtpInput({
|
|
|
9870
10122
|
emit(valid.join(""));
|
|
9871
10123
|
focusBox(valid.length);
|
|
9872
10124
|
};
|
|
9873
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10125
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
|
|
9874
10126
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9875
10127
|
"input",
|
|
9876
10128
|
{
|
|
@@ -9928,9 +10180,9 @@ function Rating({
|
|
|
9928
10180
|
className,
|
|
9929
10181
|
required
|
|
9930
10182
|
}) {
|
|
9931
|
-
const errorId =
|
|
9932
|
-
const [internal, setInternal] =
|
|
9933
|
-
const [hover, setHover] =
|
|
10183
|
+
const errorId = React36.useId();
|
|
10184
|
+
const [internal, setInternal] = React36.useState(defaultValue);
|
|
10185
|
+
const [hover, setHover] = React36.useState(null);
|
|
9934
10186
|
const current = value ?? internal;
|
|
9935
10187
|
const display2 = hover ?? current;
|
|
9936
10188
|
const interactive = !readOnly && !disabled;
|
|
@@ -10053,9 +10305,9 @@ function TimePicker({
|
|
|
10053
10305
|
required,
|
|
10054
10306
|
style
|
|
10055
10307
|
}) {
|
|
10056
|
-
const errorId =
|
|
10308
|
+
const errorId = React36.useId();
|
|
10057
10309
|
const hasError = errorMessage != null;
|
|
10058
|
-
const [open, setOpen] =
|
|
10310
|
+
const [open, setOpen] = React36.useState(false);
|
|
10059
10311
|
const parsed = parse(value) ?? { h: 0, m: 0, s: 0 };
|
|
10060
10312
|
const update = (next) => {
|
|
10061
10313
|
const merged = { ...parsed, ...next };
|
|
@@ -10180,13 +10432,13 @@ function DateRangePicker({
|
|
|
10180
10432
|
required,
|
|
10181
10433
|
style
|
|
10182
10434
|
}) {
|
|
10183
|
-
const errorId =
|
|
10435
|
+
const errorId = React36.useId();
|
|
10184
10436
|
const hasError = errorMessage != null;
|
|
10185
|
-
const [open, setOpen] =
|
|
10186
|
-
const [leftMonth, setLeftMonth] =
|
|
10187
|
-
const [pendingStart, setPendingStart] =
|
|
10188
|
-
const [hoverDate, setHoverDate] =
|
|
10189
|
-
const weekdays =
|
|
10437
|
+
const [open, setOpen] = React36.useState(false);
|
|
10438
|
+
const [leftMonth, setLeftMonth] = React36.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
|
|
10439
|
+
const [pendingStart, setPendingStart] = React36.useState(null);
|
|
10440
|
+
const [hoverDate, setHoverDate] = React36.useState(null);
|
|
10441
|
+
const weekdays = React36.useMemo(
|
|
10190
10442
|
() => WEEKDAY.slice(weekStartsOn).concat(WEEKDAY.slice(0, weekStartsOn)),
|
|
10191
10443
|
[weekStartsOn]
|
|
10192
10444
|
);
|
|
@@ -10363,10 +10615,10 @@ function ColorPicker({
|
|
|
10363
10615
|
required,
|
|
10364
10616
|
placeholder = "Pick a colour\u2026"
|
|
10365
10617
|
}) {
|
|
10366
|
-
const errorId =
|
|
10618
|
+
const errorId = React36.useId();
|
|
10367
10619
|
const hasError = errorMessage != null;
|
|
10368
|
-
const [open, setOpen] =
|
|
10369
|
-
const [draft, setDraft] =
|
|
10620
|
+
const [open, setOpen] = React36.useState(false);
|
|
10621
|
+
const [draft, setDraft] = React36.useState(value);
|
|
10370
10622
|
const valid = HEX_RE.test(value);
|
|
10371
10623
|
const pick = (hex) => {
|
|
10372
10624
|
onChange?.(hex);
|
|
@@ -10454,7 +10706,7 @@ function ColorPicker({
|
|
|
10454
10706
|
}
|
|
10455
10707
|
var CUSTOM_EVENT = "oxy-local-storage";
|
|
10456
10708
|
function useLocalStorage(key, initialValue) {
|
|
10457
|
-
const read =
|
|
10709
|
+
const read = React36.useCallback(() => {
|
|
10458
10710
|
if (typeof window === "undefined") return initialValue;
|
|
10459
10711
|
try {
|
|
10460
10712
|
const item = window.localStorage.getItem(key);
|
|
@@ -10463,8 +10715,8 @@ function useLocalStorage(key, initialValue) {
|
|
|
10463
10715
|
return initialValue;
|
|
10464
10716
|
}
|
|
10465
10717
|
}, [key]);
|
|
10466
|
-
const [stored, setStored] =
|
|
10467
|
-
const setValue =
|
|
10718
|
+
const [stored, setStored] = React36.useState(read);
|
|
10719
|
+
const setValue = React36.useCallback((value) => {
|
|
10468
10720
|
setStored((prev) => {
|
|
10469
10721
|
const next = value instanceof Function ? value(prev) : value;
|
|
10470
10722
|
try {
|
|
@@ -10477,7 +10729,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
10477
10729
|
return next;
|
|
10478
10730
|
});
|
|
10479
10731
|
}, [key]);
|
|
10480
|
-
const remove =
|
|
10732
|
+
const remove = React36.useCallback(() => {
|
|
10481
10733
|
try {
|
|
10482
10734
|
if (typeof window !== "undefined") {
|
|
10483
10735
|
window.localStorage.removeItem(key);
|
|
@@ -10487,10 +10739,10 @@ function useLocalStorage(key, initialValue) {
|
|
|
10487
10739
|
}
|
|
10488
10740
|
setStored(initialValue);
|
|
10489
10741
|
}, [key]);
|
|
10490
|
-
|
|
10742
|
+
React36.useEffect(() => {
|
|
10491
10743
|
setStored(read());
|
|
10492
10744
|
}, [key, read]);
|
|
10493
|
-
|
|
10745
|
+
React36.useEffect(() => {
|
|
10494
10746
|
if (typeof window === "undefined") return;
|
|
10495
10747
|
const onStorage = (e) => {
|
|
10496
10748
|
if (e.key === null || e.key === key) setStored(read());
|
|
@@ -10509,8 +10761,8 @@ function useLocalStorage(key, initialValue) {
|
|
|
10509
10761
|
}
|
|
10510
10762
|
function useMediaQuery(query) {
|
|
10511
10763
|
const get = () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false;
|
|
10512
|
-
const [matches, setMatches] =
|
|
10513
|
-
|
|
10764
|
+
const [matches, setMatches] = React36.useState(get);
|
|
10765
|
+
React36.useEffect(() => {
|
|
10514
10766
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
10515
10767
|
const mql = window.matchMedia(query);
|
|
10516
10768
|
const onChange = () => setMatches(mql.matches);
|
|
@@ -10541,8 +10793,8 @@ function decodeSegment(seg) {
|
|
|
10541
10793
|
}
|
|
10542
10794
|
}
|
|
10543
10795
|
function useJwt(token) {
|
|
10544
|
-
const [, tick] =
|
|
10545
|
-
const decoded =
|
|
10796
|
+
const [, tick] = React36.useState(0);
|
|
10797
|
+
const decoded = React36.useMemo(() => {
|
|
10546
10798
|
if (!token) return { payload: null, header: null, exp: null };
|
|
10547
10799
|
const [h, p] = token.split(".");
|
|
10548
10800
|
const header = decodeSegment(h);
|
|
@@ -10550,7 +10802,7 @@ function useJwt(token) {
|
|
|
10550
10802
|
const exp = payload && typeof payload.exp === "number" ? payload.exp : null;
|
|
10551
10803
|
return { payload, header, exp };
|
|
10552
10804
|
}, [token]);
|
|
10553
|
-
|
|
10805
|
+
React36.useEffect(() => {
|
|
10554
10806
|
if (decoded.exp == null) return;
|
|
10555
10807
|
const ms = decoded.exp * 1e3 - Date.now();
|
|
10556
10808
|
if (ms <= 0) return;
|
|
@@ -10724,13 +10976,13 @@ function SlideShow({
|
|
|
10724
10976
|
style
|
|
10725
10977
|
}) {
|
|
10726
10978
|
const reduced = framerMotion.useReducedMotion();
|
|
10727
|
-
const [index, setIndex] =
|
|
10728
|
-
const [paused, setPaused] =
|
|
10979
|
+
const [index, setIndex] = React36.useState(0);
|
|
10980
|
+
const [paused, setPaused] = React36.useState(false);
|
|
10729
10981
|
const count = slides.length;
|
|
10730
10982
|
const idx = count ? (index % count + count) % count : 0;
|
|
10731
|
-
const go =
|
|
10732
|
-
const timer =
|
|
10733
|
-
|
|
10983
|
+
const go = React36.useCallback((d) => setIndex((i) => i + d), []);
|
|
10984
|
+
const timer = React36.useRef(null);
|
|
10985
|
+
React36.useEffect(() => {
|
|
10734
10986
|
if (!autoPlay || paused || count <= 1) return;
|
|
10735
10987
|
timer.current = setInterval(() => setIndex((i) => i + 1), interval);
|
|
10736
10988
|
return () => {
|
|
@@ -10806,7 +11058,7 @@ function Video({
|
|
|
10806
11058
|
className = "",
|
|
10807
11059
|
style
|
|
10808
11060
|
}) {
|
|
10809
|
-
const [playing, setPlaying] =
|
|
11061
|
+
const [playing, setPlaying] = React36.useState(autoPlay);
|
|
10810
11062
|
const frame = cx("relative w-full overflow-hidden bg-backdrop", framed ? "rounded-2xl border border-border shadow-sm" : "", className);
|
|
10811
11063
|
const ratio = aspect.replace("/", " / ");
|
|
10812
11064
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frame, style: { aspectRatio: ratio, ...style }, children: embedUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -10861,7 +11113,7 @@ function Parallax({
|
|
|
10861
11113
|
style
|
|
10862
11114
|
}) {
|
|
10863
11115
|
const reduced = framerMotion.useReducedMotion();
|
|
10864
|
-
const ref =
|
|
11116
|
+
const ref = React36.useRef(null);
|
|
10865
11117
|
const { scrollYProgress } = framerMotion.useScroll({ target: ref, offset: ["start end", "end start"] });
|
|
10866
11118
|
const shift = Math.max(0, Math.min(1, speed)) * 100;
|
|
10867
11119
|
const y = framerMotion.useTransform(scrollYProgress, [0, 1], reduced ? ["0%", "0%"] : [`-${shift / 2}%`, `${shift / 2}%`]);
|
|
@@ -10929,7 +11181,7 @@ function Blog({
|
|
|
10929
11181
|
post.tag != null && !post.image && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "accent", variant: "soft", size: "sm", children: post.tag }) }),
|
|
10930
11182
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold leading-snug text-foreground transition-colors group-hover:text-accent", children: post.title }),
|
|
10931
11183
|
post.excerpt != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-3 text-sm leading-relaxed text-foreground-secondary", children: post.excerpt }),
|
|
10932
|
-
meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11184
|
+
meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
|
|
10933
11185
|
j > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
10934
11186
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: m })
|
|
10935
11187
|
] }, j)) })
|
|
@@ -11058,8 +11310,8 @@ function LeadCapture({
|
|
|
11058
11310
|
className = "",
|
|
11059
11311
|
style
|
|
11060
11312
|
}) {
|
|
11061
|
-
const [email, setEmail] =
|
|
11062
|
-
const [done, setDone] =
|
|
11313
|
+
const [email, setEmail] = React36.useState("");
|
|
11314
|
+
const [done, setDone] = React36.useState(false);
|
|
11063
11315
|
const submit = (e) => {
|
|
11064
11316
|
e.preventDefault();
|
|
11065
11317
|
const value = email.trim();
|