@geomak/ui 6.24.1 → 6.26.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 +928 -513
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +702 -288
- package/dist/index.js.map +1 -1
- package/dist/styles.css +24 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var chunkOAV4TA4B_cjs = require('./chunk-OAV4TA4B.cjs');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
-
var
|
|
5
|
+
var React29 = require('react');
|
|
6
6
|
var reactDom = require('react-dom');
|
|
7
7
|
var AvatarPrimitive = require('@radix-ui/react-avatar');
|
|
8
8
|
var DropdownMenu = require('@radix-ui/react-dropdown-menu');
|
|
@@ -12,12 +12,12 @@ var TooltipPrimitive = require('@radix-ui/react-tooltip');
|
|
|
12
12
|
var TabsPrimitive = require('@radix-ui/react-tabs');
|
|
13
13
|
var AccordionPrimitive = require('@radix-ui/react-accordion');
|
|
14
14
|
var Popover = require('@radix-ui/react-popover');
|
|
15
|
+
var ToggleGroup = require('@radix-ui/react-toggle-group');
|
|
15
16
|
var ContextMenuPrimitive = require('@radix-ui/react-context-menu');
|
|
16
17
|
var SwitchPrimitive = require('@radix-ui/react-switch');
|
|
17
18
|
var NavigationMenu = require('@radix-ui/react-navigation-menu');
|
|
18
19
|
var CheckboxPrimitive = require('@radix-ui/react-checkbox');
|
|
19
20
|
var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
|
|
20
|
-
var ToggleGroup = require('@radix-ui/react-toggle-group');
|
|
21
21
|
var SliderPrimitive = require('@radix-ui/react-slider');
|
|
22
22
|
|
|
23
23
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -40,7 +40,7 @@ function _interopNamespace(e) {
|
|
|
40
40
|
return Object.freeze(n);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
var
|
|
43
|
+
var React29__default = /*#__PURE__*/_interopDefault(React29);
|
|
44
44
|
var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
|
|
45
45
|
var DropdownMenu__namespace = /*#__PURE__*/_interopNamespace(DropdownMenu);
|
|
46
46
|
var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
|
|
@@ -48,12 +48,12 @@ var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitiv
|
|
|
48
48
|
var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
|
|
49
49
|
var AccordionPrimitive__namespace = /*#__PURE__*/_interopNamespace(AccordionPrimitive);
|
|
50
50
|
var Popover__namespace = /*#__PURE__*/_interopNamespace(Popover);
|
|
51
|
+
var ToggleGroup__namespace = /*#__PURE__*/_interopNamespace(ToggleGroup);
|
|
51
52
|
var ContextMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(ContextMenuPrimitive);
|
|
52
53
|
var SwitchPrimitive__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitive);
|
|
53
54
|
var NavigationMenu__namespace = /*#__PURE__*/_interopNamespace(NavigationMenu);
|
|
54
55
|
var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
|
|
55
56
|
var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
|
|
56
|
-
var ToggleGroup__namespace = /*#__PURE__*/_interopNamespace(ToggleGroup);
|
|
57
57
|
var SliderPrimitive__namespace = /*#__PURE__*/_interopNamespace(SliderPrimitive);
|
|
58
58
|
|
|
59
59
|
var Moon = ({ color = "gray" }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: color, viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: color, className: "w-8 h-8", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" }) });
|
|
@@ -216,8 +216,8 @@ Icon.Copy = Copy;
|
|
|
216
216
|
Icon.CircleStack = CircleStack;
|
|
217
217
|
var icons_default = Icon;
|
|
218
218
|
function Portal({ children, target }) {
|
|
219
|
-
const [resolved, setResolved] =
|
|
220
|
-
|
|
219
|
+
const [resolved, setResolved] = React29.useState(null);
|
|
220
|
+
React29.useEffect(() => {
|
|
221
221
|
if (target === null) {
|
|
222
222
|
setResolved(null);
|
|
223
223
|
return;
|
|
@@ -651,7 +651,7 @@ function IconButton({
|
|
|
651
651
|
className = "",
|
|
652
652
|
style
|
|
653
653
|
}) {
|
|
654
|
-
const colorScheme =
|
|
654
|
+
const colorScheme = React29.useMemo(() => {
|
|
655
655
|
if (type === "primary") {
|
|
656
656
|
return "bg-accent text-accent-fg hover:bg-accent-hover";
|
|
657
657
|
}
|
|
@@ -730,7 +730,7 @@ var SIZE_CLASSES = {
|
|
|
730
730
|
md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
|
|
731
731
|
lg: "h-11 px-5 text-sm gap-2 rounded-xl"
|
|
732
732
|
};
|
|
733
|
-
var Button =
|
|
733
|
+
var Button = React29__default.default.forwardRef(function Button2({
|
|
734
734
|
content,
|
|
735
735
|
variant = "primary",
|
|
736
736
|
size = "md",
|
|
@@ -838,7 +838,7 @@ function MenuButton({
|
|
|
838
838
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
839
839
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
|
|
840
840
|
].join(" "),
|
|
841
|
-
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
841
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
|
|
842
842
|
item.separatorBefore && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Separator, { className: "my-1 h-px bg-border" }),
|
|
843
843
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
844
844
|
DropdownMenu__namespace.Item,
|
|
@@ -1081,9 +1081,9 @@ function Tooltip({
|
|
|
1081
1081
|
] }) });
|
|
1082
1082
|
}
|
|
1083
1083
|
var TooltipProvider = TooltipPrimitive__namespace.Provider;
|
|
1084
|
-
var TabsContext =
|
|
1084
|
+
var TabsContext = React29.createContext(null);
|
|
1085
1085
|
function useTabsContext() {
|
|
1086
|
-
const ctx =
|
|
1086
|
+
const ctx = React29.useContext(TabsContext);
|
|
1087
1087
|
if (!ctx) throw new Error("Tabs.List / Tabs.Trigger / Tabs.Panel must be rendered inside <Tabs>.");
|
|
1088
1088
|
return ctx;
|
|
1089
1089
|
}
|
|
@@ -1105,26 +1105,26 @@ function Tabs({
|
|
|
1105
1105
|
children
|
|
1106
1106
|
}) {
|
|
1107
1107
|
const isControlled = value !== void 0;
|
|
1108
|
-
const [internal, setInternal] =
|
|
1108
|
+
const [internal, setInternal] = React29.useState(defaultValue);
|
|
1109
1109
|
const current = isControlled ? value : internal;
|
|
1110
1110
|
const reduced = !!framerMotion.useReducedMotion();
|
|
1111
|
-
const indicatorId =
|
|
1112
|
-
const select =
|
|
1111
|
+
const indicatorId = React29.useId();
|
|
1112
|
+
const select = React29.useCallback((next) => {
|
|
1113
1113
|
if (!isControlled) setInternal(next);
|
|
1114
1114
|
onValueChange?.(next);
|
|
1115
1115
|
}, [isControlled, onValueChange]);
|
|
1116
|
-
const registry =
|
|
1117
|
-
const orderRef =
|
|
1118
|
-
const [, bump] =
|
|
1119
|
-
const registerTab =
|
|
1116
|
+
const registry = React29.useRef(/* @__PURE__ */ new Map());
|
|
1117
|
+
const orderRef = React29.useRef(0);
|
|
1118
|
+
const [, bump] = React29.useState(0);
|
|
1119
|
+
const registerTab = React29.useCallback((val, meta) => {
|
|
1120
1120
|
const existing = registry.current.get(val);
|
|
1121
1121
|
registry.current.set(val, { ...meta, order: existing?.order ?? orderRef.current++ });
|
|
1122
1122
|
if (!existing) bump((v) => v + 1);
|
|
1123
1123
|
}, []);
|
|
1124
|
-
const unregisterTab =
|
|
1124
|
+
const unregisterTab = React29.useCallback((val) => {
|
|
1125
1125
|
if (registry.current.delete(val)) bump((v) => v + 1);
|
|
1126
1126
|
}, []);
|
|
1127
|
-
const getTabs =
|
|
1127
|
+
const getTabs = React29.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 })), []);
|
|
1128
1128
|
return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, variant, size, orientation, indicatorId, reduced, select, registerTab, unregisterTab, getTabs }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1129
1129
|
TabsPrimitive__namespace.Root,
|
|
1130
1130
|
{
|
|
@@ -1144,10 +1144,10 @@ function Tabs({
|
|
|
1144
1144
|
function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
|
|
1145
1145
|
const { variant, orientation, reduced, value } = useTabsContext();
|
|
1146
1146
|
const horizontal = orientation === "horizontal";
|
|
1147
|
-
const scrollRef =
|
|
1148
|
-
const [edges, setEdges] =
|
|
1147
|
+
const scrollRef = React29.useRef(null);
|
|
1148
|
+
const [edges, setEdges] = React29.useState({ start: false, end: false });
|
|
1149
1149
|
const scrollable = variant !== "segmented";
|
|
1150
|
-
|
|
1150
|
+
React29.useLayoutEffect(() => {
|
|
1151
1151
|
const el = scrollRef.current;
|
|
1152
1152
|
if (!el || !scrollable) return;
|
|
1153
1153
|
const update = () => {
|
|
@@ -1172,13 +1172,13 @@ function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
|
|
|
1172
1172
|
ro.disconnect();
|
|
1173
1173
|
};
|
|
1174
1174
|
}, [horizontal, scrollable, children]);
|
|
1175
|
-
const nudge =
|
|
1175
|
+
const nudge = React29.useCallback((dir) => {
|
|
1176
1176
|
const el = scrollRef.current;
|
|
1177
1177
|
if (!el) return;
|
|
1178
1178
|
const amount = (horizontal ? el.clientWidth : el.clientHeight) * 0.7 * dir;
|
|
1179
1179
|
el.scrollBy({ [horizontal ? "left" : "top"]: amount, behavior: reduced ? "auto" : "smooth" });
|
|
1180
1180
|
}, [horizontal, reduced]);
|
|
1181
|
-
|
|
1181
|
+
React29.useLayoutEffect(() => {
|
|
1182
1182
|
const el = scrollRef.current;
|
|
1183
1183
|
if (!el || !scrollable) return;
|
|
1184
1184
|
const active = el.querySelector("[role=tab][data-state=active]");
|
|
@@ -1236,9 +1236,9 @@ function Chevron2({ side, orientation, onClick }) {
|
|
|
1236
1236
|
function OverflowMenu() {
|
|
1237
1237
|
const { getTabs, value, select, orientation } = useTabsContext();
|
|
1238
1238
|
const horizontal = orientation === "horizontal";
|
|
1239
|
-
const [open, setOpen] =
|
|
1240
|
-
const wrapRef =
|
|
1241
|
-
const timer =
|
|
1239
|
+
const [open, setOpen] = React29.useState(false);
|
|
1240
|
+
const wrapRef = React29.useRef(null);
|
|
1241
|
+
const timer = React29.useRef(null);
|
|
1242
1242
|
const openNow = () => {
|
|
1243
1243
|
if (timer.current) clearTimeout(timer.current);
|
|
1244
1244
|
setOpen(true);
|
|
@@ -1246,7 +1246,7 @@ function OverflowMenu() {
|
|
|
1246
1246
|
const closeSoon = () => {
|
|
1247
1247
|
timer.current = setTimeout(() => setOpen(false), 160);
|
|
1248
1248
|
};
|
|
1249
|
-
|
|
1249
|
+
React29.useLayoutEffect(() => {
|
|
1250
1250
|
if (!open) return;
|
|
1251
1251
|
const onDoc = (e) => {
|
|
1252
1252
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -1327,7 +1327,7 @@ function TabsTrigger({ value, icon, badge, closeable, onClose, disabled, classNa
|
|
|
1327
1327
|
const isActive = active === value;
|
|
1328
1328
|
const horizontal = orientation === "horizontal";
|
|
1329
1329
|
const sz = SIZE[size];
|
|
1330
|
-
|
|
1330
|
+
React29.useLayoutEffect(() => {
|
|
1331
1331
|
registerTab(value, { label: children, icon, disabled });
|
|
1332
1332
|
return () => unregisterTab(value);
|
|
1333
1333
|
}, [value, children, icon, disabled, registerTab, unregisterTab]);
|
|
@@ -1525,7 +1525,7 @@ function Tree({
|
|
|
1525
1525
|
item.key
|
|
1526
1526
|
)) });
|
|
1527
1527
|
}
|
|
1528
|
-
var AccordionCtx =
|
|
1528
|
+
var AccordionCtx = React29.createContext({ variant: "separated" });
|
|
1529
1529
|
function Accordion2({
|
|
1530
1530
|
children,
|
|
1531
1531
|
type = "single",
|
|
@@ -1584,7 +1584,7 @@ var Chevron3 = /* @__PURE__ */ jsxRuntime.jsx(
|
|
|
1584
1584
|
}
|
|
1585
1585
|
);
|
|
1586
1586
|
function AccordionItem({ value, title, icon, children, disabled, className = "" }) {
|
|
1587
|
-
const { variant } =
|
|
1587
|
+
const { variant } = React29.useContext(AccordionCtx);
|
|
1588
1588
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1589
1589
|
AccordionPrimitive__namespace.Item,
|
|
1590
1590
|
{
|
|
@@ -1643,7 +1643,7 @@ function Breadcrumbs({
|
|
|
1643
1643
|
className = "",
|
|
1644
1644
|
style
|
|
1645
1645
|
}) {
|
|
1646
|
-
const [expanded, setExpanded] =
|
|
1646
|
+
const [expanded, setExpanded] = React29.useState(false);
|
|
1647
1647
|
const shouldCollapse = maxItems > 0 && items.length > maxItems && !expanded;
|
|
1648
1648
|
const visible = [];
|
|
1649
1649
|
if (shouldCollapse) {
|
|
@@ -1827,8 +1827,8 @@ function Stepper({
|
|
|
1827
1827
|
className = ""
|
|
1828
1828
|
}) {
|
|
1829
1829
|
const reduced = framerMotion.useReducedMotion();
|
|
1830
|
-
const [forcedVertical, setForcedVertical] =
|
|
1831
|
-
|
|
1830
|
+
const [forcedVertical, setForcedVertical] = React29.useState(false);
|
|
1831
|
+
React29.useEffect(() => {
|
|
1832
1832
|
if (!responsive || orientation === "vertical") return;
|
|
1833
1833
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1834
1834
|
const mq = window.matchMedia("(max-width: 767px)");
|
|
@@ -1937,7 +1937,7 @@ function Kbd({
|
|
|
1937
1937
|
style
|
|
1938
1938
|
}) {
|
|
1939
1939
|
if (keys && keys.length > 0) {
|
|
1940
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: ["inline-flex items-center gap-1", className].filter(Boolean).join(" "), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1940
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: ["inline-flex items-center gap-1", className].filter(Boolean).join(" "), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
|
|
1941
1941
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
|
|
1942
1942
|
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
|
|
1943
1943
|
] }, `${k}-${i}`)) });
|
|
@@ -2028,13 +2028,13 @@ function FlatCarousel({
|
|
|
2028
2028
|
className = "",
|
|
2029
2029
|
style
|
|
2030
2030
|
}) {
|
|
2031
|
-
const scrollerRef =
|
|
2032
|
-
const slides =
|
|
2033
|
-
const [active, setActive] =
|
|
2034
|
-
const [atStart, setAtStart] =
|
|
2035
|
-
const [atEnd, setAtEnd] =
|
|
2031
|
+
const scrollerRef = React29.useRef(null);
|
|
2032
|
+
const slides = React29__default.default.Children.toArray(children);
|
|
2033
|
+
const [active, setActive] = React29.useState(0);
|
|
2034
|
+
const [atStart, setAtStart] = React29.useState(true);
|
|
2035
|
+
const [atEnd, setAtEnd] = React29.useState(false);
|
|
2036
2036
|
const width = typeof itemWidth === "number" ? `${itemWidth}px` : itemWidth;
|
|
2037
|
-
const update =
|
|
2037
|
+
const update = React29.useCallback(() => {
|
|
2038
2038
|
const el = scrollerRef.current;
|
|
2039
2039
|
if (!el) return;
|
|
2040
2040
|
setAtStart(el.scrollLeft <= 1);
|
|
@@ -2043,7 +2043,7 @@ function FlatCarousel({
|
|
|
2043
2043
|
const slideW = first ? first.getBoundingClientRect().width + gap : el.clientWidth;
|
|
2044
2044
|
setActive(Math.round(el.scrollLeft / slideW));
|
|
2045
2045
|
}, [gap]);
|
|
2046
|
-
|
|
2046
|
+
React29.useEffect(() => {
|
|
2047
2047
|
update();
|
|
2048
2048
|
const el = scrollerRef.current;
|
|
2049
2049
|
if (!el) return;
|
|
@@ -2084,9 +2084,9 @@ function RotatingCarousel({
|
|
|
2084
2084
|
className = "",
|
|
2085
2085
|
style
|
|
2086
2086
|
}) {
|
|
2087
|
-
const slides =
|
|
2087
|
+
const slides = React29__default.default.Children.toArray(children);
|
|
2088
2088
|
const count = slides.length;
|
|
2089
|
-
const [active, setActive] =
|
|
2089
|
+
const [active, setActive] = React29.useState(0);
|
|
2090
2090
|
const reduced = framerMotion.useReducedMotion();
|
|
2091
2091
|
const wrap = (n) => count > 0 ? (n % count + count) % count : 0;
|
|
2092
2092
|
const idx = wrap(active);
|
|
@@ -2236,7 +2236,7 @@ function FAB({
|
|
|
2236
2236
|
className = "",
|
|
2237
2237
|
style
|
|
2238
2238
|
}) {
|
|
2239
|
-
const [open, setOpen] =
|
|
2239
|
+
const [open, setOpen] = React29.useState(false);
|
|
2240
2240
|
const reduced = framerMotion.useReducedMotion();
|
|
2241
2241
|
const hasDial = !!actions && actions.length > 0;
|
|
2242
2242
|
const bottom = position.startsWith("bottom");
|
|
@@ -2338,8 +2338,8 @@ function PopConfirm({
|
|
|
2338
2338
|
onOpenChange,
|
|
2339
2339
|
className = ""
|
|
2340
2340
|
}) {
|
|
2341
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
2342
|
-
const [loading, setLoading] =
|
|
2341
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React29.useState(false);
|
|
2342
|
+
const [loading, setLoading] = React29.useState(false);
|
|
2343
2343
|
const isOpen = open ?? uncontrolledOpen;
|
|
2344
2344
|
const setOpen = (next) => {
|
|
2345
2345
|
onOpenChange?.(next);
|
|
@@ -2426,16 +2426,16 @@ function LogoutTimer({
|
|
|
2426
2426
|
logoutLabel = "Sign out now"
|
|
2427
2427
|
}) {
|
|
2428
2428
|
const reduced = framerMotion.useReducedMotion();
|
|
2429
|
-
const [warning, setWarning] =
|
|
2430
|
-
const [remaining, setRemaining] =
|
|
2431
|
-
const idleTimer =
|
|
2432
|
-
const tick =
|
|
2433
|
-
const deadline =
|
|
2434
|
-
const warningRef =
|
|
2435
|
-
const lastReset =
|
|
2436
|
-
const cbs =
|
|
2429
|
+
const [warning, setWarning] = React29.useState(false);
|
|
2430
|
+
const [remaining, setRemaining] = React29.useState(countdown);
|
|
2431
|
+
const idleTimer = React29.useRef(null);
|
|
2432
|
+
const tick = React29.useRef(null);
|
|
2433
|
+
const deadline = React29.useRef(0);
|
|
2434
|
+
const warningRef = React29.useRef(false);
|
|
2435
|
+
const lastReset = React29.useRef(0);
|
|
2436
|
+
const cbs = React29.useRef({ onLogout, onContinue, onWarning });
|
|
2437
2437
|
cbs.current = { onLogout, onContinue, onWarning };
|
|
2438
|
-
const clearTimers =
|
|
2438
|
+
const clearTimers = React29.useCallback(() => {
|
|
2439
2439
|
if (idleTimer.current) {
|
|
2440
2440
|
clearTimeout(idleTimer.current);
|
|
2441
2441
|
idleTimer.current = null;
|
|
@@ -2445,13 +2445,13 @@ function LogoutTimer({
|
|
|
2445
2445
|
tick.current = null;
|
|
2446
2446
|
}
|
|
2447
2447
|
}, []);
|
|
2448
|
-
const logout =
|
|
2448
|
+
const logout = React29.useCallback(() => {
|
|
2449
2449
|
clearTimers();
|
|
2450
2450
|
warningRef.current = false;
|
|
2451
2451
|
setWarning(false);
|
|
2452
2452
|
cbs.current.onLogout();
|
|
2453
2453
|
}, [clearTimers]);
|
|
2454
|
-
const startIdle =
|
|
2454
|
+
const startIdle = React29.useCallback(() => {
|
|
2455
2455
|
if (idleTimer.current) clearTimeout(idleTimer.current);
|
|
2456
2456
|
idleTimer.current = setTimeout(() => {
|
|
2457
2457
|
warningRef.current = true;
|
|
@@ -2466,7 +2466,7 @@ function LogoutTimer({
|
|
|
2466
2466
|
}, 250);
|
|
2467
2467
|
}, timeout);
|
|
2468
2468
|
}, [timeout, countdown, logout]);
|
|
2469
|
-
const stay =
|
|
2469
|
+
const stay = React29.useCallback(() => {
|
|
2470
2470
|
if (tick.current) {
|
|
2471
2471
|
clearInterval(tick.current);
|
|
2472
2472
|
tick.current = null;
|
|
@@ -2476,7 +2476,7 @@ function LogoutTimer({
|
|
|
2476
2476
|
cbs.current.onContinue?.();
|
|
2477
2477
|
startIdle();
|
|
2478
2478
|
}, [startIdle]);
|
|
2479
|
-
|
|
2479
|
+
React29.useEffect(() => {
|
|
2480
2480
|
if (!enabled) {
|
|
2481
2481
|
clearTimers();
|
|
2482
2482
|
warningRef.current = false;
|
|
@@ -2548,16 +2548,16 @@ function Calendar2({
|
|
|
2548
2548
|
className = "",
|
|
2549
2549
|
style
|
|
2550
2550
|
}) {
|
|
2551
|
-
const today =
|
|
2552
|
-
const [internalMonth, setInternalMonth] =
|
|
2551
|
+
const today = React29.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
|
|
2552
|
+
const [internalMonth, setInternalMonth] = React29.useState(() => month ?? defaultMonth ?? value ?? today);
|
|
2553
2553
|
const visible = month ?? internalMonth;
|
|
2554
2554
|
const setMonth = (next) => {
|
|
2555
2555
|
onMonthChange?.(next);
|
|
2556
2556
|
if (month === void 0) setInternalMonth(next);
|
|
2557
2557
|
};
|
|
2558
|
-
const grid =
|
|
2559
|
-
const weekdays =
|
|
2560
|
-
const eventsByDay =
|
|
2558
|
+
const grid = React29.useMemo(() => buildGrid(visible, weekStartsOn), [visible, weekStartsOn]);
|
|
2559
|
+
const weekdays = React29.useMemo(() => Array.from({ length: 7 }, (_, i) => WEEKDAYS[(i + weekStartsOn) % 7]), [weekStartsOn]);
|
|
2560
|
+
const eventsByDay = React29.useMemo(() => {
|
|
2561
2561
|
const map = /* @__PURE__ */ new Map();
|
|
2562
2562
|
for (const ev of events ?? []) {
|
|
2563
2563
|
const key = startOfDay(ev.date).toDateString();
|
|
@@ -2600,7 +2600,7 @@ function Calendar2({
|
|
|
2600
2600
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-0.5", role: "grid", children: grid.map((d, i) => {
|
|
2601
2601
|
const inMonth = d.getMonth() === visible.getMonth();
|
|
2602
2602
|
const isSelected = value != null && sameDay(d, value);
|
|
2603
|
-
const
|
|
2603
|
+
const isToday2 = sameDay(d, today);
|
|
2604
2604
|
const isDisabled = disabled(d);
|
|
2605
2605
|
const dayEvents = eventsByDay.get(d.toDateString()) ?? [];
|
|
2606
2606
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2609,7 +2609,7 @@ function Calendar2({
|
|
|
2609
2609
|
type: "button",
|
|
2610
2610
|
role: "gridcell",
|
|
2611
2611
|
"aria-selected": isSelected,
|
|
2612
|
-
"aria-current":
|
|
2612
|
+
"aria-current": isToday2 ? "date" : void 0,
|
|
2613
2613
|
disabled: isDisabled,
|
|
2614
2614
|
onClick: () => onChange?.(startOfDay(d)),
|
|
2615
2615
|
className: [
|
|
@@ -2617,24 +2617,662 @@ function Calendar2({
|
|
|
2617
2617
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
2618
2618
|
isSelected ? "bg-accent text-accent-fg font-semibold" : inMonth ? "text-foreground hover:bg-surface-raised" : "text-foreground-muted hover:bg-surface-raised",
|
|
2619
2619
|
isDisabled ? "opacity-40 cursor-not-allowed hover:bg-transparent" : "",
|
|
2620
|
-
!isSelected &&
|
|
2620
|
+
!isSelected && isToday2 ? "ring-1 ring-inset ring-accent/60" : ""
|
|
2621
2621
|
].filter(Boolean).join(" "),
|
|
2622
2622
|
children: [
|
|
2623
2623
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "leading-none", children: d.getDate() }),
|
|
2624
2624
|
dayEvents.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-1 flex gap-0.5", children: dayEvents.slice(0, 3).map((ev, j) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2625
2625
|
"span",
|
|
2626
2626
|
{
|
|
2627
|
-
title: ev.label,
|
|
2628
|
-
className: "h-1 w-1 rounded-full",
|
|
2629
|
-
style: { backgroundColor: ev.color ?? (isSelected ? "var(--color-accent-fg)" : "var(--color-accent)") }
|
|
2627
|
+
title: ev.label,
|
|
2628
|
+
className: "h-1 w-1 rounded-full",
|
|
2629
|
+
style: { backgroundColor: ev.color ?? (isSelected ? "var(--color-accent-fg)" : "var(--color-accent)") }
|
|
2630
|
+
},
|
|
2631
|
+
j
|
|
2632
|
+
)) })
|
|
2633
|
+
]
|
|
2634
|
+
},
|
|
2635
|
+
i
|
|
2636
|
+
);
|
|
2637
|
+
}) })
|
|
2638
|
+
] });
|
|
2639
|
+
}
|
|
2640
|
+
var FIELD_SIZE = {
|
|
2641
|
+
sm: { control: "h-control-sm", text: "text-xs", padX: "px-2.5", gap: "gap-1.5" },
|
|
2642
|
+
md: { control: "h-control-md", text: "text-sm", padX: "px-3", gap: "gap-2" },
|
|
2643
|
+
lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
|
|
2644
|
+
};
|
|
2645
|
+
var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent";
|
|
2646
|
+
var FOCUS_ELEMENT = "focus:outline-none focus:border-accent data-[state=open]:border-accent";
|
|
2647
|
+
var FOCUS_WITHIN_ERROR = "focus-within:border-status-error";
|
|
2648
|
+
var FOCUS_ELEMENT_ERROR = "focus:border-status-error data-[state=open]:border-status-error";
|
|
2649
|
+
function fieldShell({
|
|
2650
|
+
size = "md",
|
|
2651
|
+
hasError = false,
|
|
2652
|
+
disabled = false,
|
|
2653
|
+
focusWithin = false,
|
|
2654
|
+
sized = true
|
|
2655
|
+
} = {}) {
|
|
2656
|
+
const s = FIELD_SIZE[size];
|
|
2657
|
+
return [
|
|
2658
|
+
"w-full rounded-lg border bg-surface text-foreground",
|
|
2659
|
+
"transition-[color,box-shadow,border-color] duration-150",
|
|
2660
|
+
s.text,
|
|
2661
|
+
sized ? `${s.control} ${s.padX}` : "",
|
|
2662
|
+
// resting border
|
|
2663
|
+
hasError ? "border-status-error" : "border-border",
|
|
2664
|
+
// hover (only when interactive + no error)
|
|
2665
|
+
disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
|
|
2666
|
+
// focus
|
|
2667
|
+
focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
|
|
2668
|
+
hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
|
|
2669
|
+
// placeholder colour for native inputs
|
|
2670
|
+
"placeholder:text-foreground-muted"
|
|
2671
|
+
].filter(Boolean).join(" ");
|
|
2672
|
+
}
|
|
2673
|
+
function FieldHelpIcon({ text }) {
|
|
2674
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { title: text, placement: "top", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2675
|
+
"button",
|
|
2676
|
+
{
|
|
2677
|
+
type: "button",
|
|
2678
|
+
"aria-label": "More information",
|
|
2679
|
+
className: "inline-flex items-center justify-center rounded-full text-foreground-muted transition-colors hover:text-foreground focus:outline-none focus-visible:text-accent",
|
|
2680
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [
|
|
2681
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.25" }),
|
|
2682
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M8 7.4v3.4" }),
|
|
2683
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "5.1", r: "0.65", fill: "currentColor", stroke: "none" })
|
|
2684
|
+
] })
|
|
2685
|
+
}
|
|
2686
|
+
) });
|
|
2687
|
+
}
|
|
2688
|
+
function FieldLabel({
|
|
2689
|
+
label,
|
|
2690
|
+
htmlFor,
|
|
2691
|
+
required,
|
|
2692
|
+
helperText,
|
|
2693
|
+
horizontal = false,
|
|
2694
|
+
align = "start",
|
|
2695
|
+
style,
|
|
2696
|
+
width,
|
|
2697
|
+
className = ""
|
|
2698
|
+
}) {
|
|
2699
|
+
if (label == null && helperText == null) return null;
|
|
2700
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2701
|
+
"div",
|
|
2702
|
+
{
|
|
2703
|
+
style: { width: horizontal ? width : void 0, ...style },
|
|
2704
|
+
className: [
|
|
2705
|
+
"flex items-center gap-1",
|
|
2706
|
+
horizontal ? "flex-shrink-0 whitespace-nowrap" : "",
|
|
2707
|
+
// Only the 'start' alignment needs the top nudge; 'center' relies
|
|
2708
|
+
// on the row's items-center to line up with a short control.
|
|
2709
|
+
horizontal && align === "start" ? "mt-2" : "",
|
|
2710
|
+
className
|
|
2711
|
+
].filter(Boolean).join(" "),
|
|
2712
|
+
children: [
|
|
2713
|
+
label != null && /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor, className: "text-sm font-medium text-foreground select-none", children: [
|
|
2714
|
+
label,
|
|
2715
|
+
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
|
|
2716
|
+
] }),
|
|
2717
|
+
helperText != null && /* @__PURE__ */ jsxRuntime.jsx(FieldHelpIcon, { text: helperText })
|
|
2718
|
+
]
|
|
2719
|
+
}
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
function Field({
|
|
2723
|
+
label,
|
|
2724
|
+
htmlFor,
|
|
2725
|
+
errorId,
|
|
2726
|
+
errorMessage,
|
|
2727
|
+
layout = "vertical",
|
|
2728
|
+
required,
|
|
2729
|
+
helperText,
|
|
2730
|
+
labelAlign = "start",
|
|
2731
|
+
labelStyle,
|
|
2732
|
+
labelWidth,
|
|
2733
|
+
className = "",
|
|
2734
|
+
children
|
|
2735
|
+
}) {
|
|
2736
|
+
const hasError = errorMessage != null;
|
|
2737
|
+
const horizontal = layout === "horizontal";
|
|
2738
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2739
|
+
"div",
|
|
2740
|
+
{
|
|
2741
|
+
className: [
|
|
2742
|
+
"flex",
|
|
2743
|
+
horizontal ? `flex-row gap-3 ${labelAlign === "center" ? "items-center" : "items-start"}` : "flex-col gap-1.5",
|
|
2744
|
+
className
|
|
2745
|
+
].filter(Boolean).join(" "),
|
|
2746
|
+
children: [
|
|
2747
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2748
|
+
FieldLabel,
|
|
2749
|
+
{
|
|
2750
|
+
label,
|
|
2751
|
+
htmlFor,
|
|
2752
|
+
required,
|
|
2753
|
+
helperText,
|
|
2754
|
+
horizontal,
|
|
2755
|
+
align: labelAlign,
|
|
2756
|
+
style: labelStyle,
|
|
2757
|
+
width: labelWidth
|
|
2758
|
+
}
|
|
2759
|
+
),
|
|
2760
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
2761
|
+
children,
|
|
2762
|
+
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
|
|
2763
|
+
] })
|
|
2764
|
+
]
|
|
2765
|
+
}
|
|
2766
|
+
);
|
|
2767
|
+
}
|
|
2768
|
+
var SIZE5 = {
|
|
2769
|
+
sm: { h: "h-control-sm", text: "text-xs", pad: "px-2.5" },
|
|
2770
|
+
md: { h: "h-control-md", text: "text-sm", pad: "px-3.5" },
|
|
2771
|
+
lg: { h: "h-control-lg", text: "text-sm", pad: "px-4" }
|
|
2772
|
+
};
|
|
2773
|
+
function SegmentedControl({
|
|
2774
|
+
options,
|
|
2775
|
+
value,
|
|
2776
|
+
defaultValue,
|
|
2777
|
+
onChange,
|
|
2778
|
+
size = "md",
|
|
2779
|
+
fullWidth = false,
|
|
2780
|
+
disabled,
|
|
2781
|
+
label,
|
|
2782
|
+
layout = "vertical",
|
|
2783
|
+
helperText,
|
|
2784
|
+
className,
|
|
2785
|
+
name,
|
|
2786
|
+
required,
|
|
2787
|
+
errorMessage,
|
|
2788
|
+
"aria-label": ariaLabel
|
|
2789
|
+
}) {
|
|
2790
|
+
const sz = SIZE5[size];
|
|
2791
|
+
const groupId = React29.useId();
|
|
2792
|
+
const errorId = React29.useId();
|
|
2793
|
+
const hasError = errorMessage != null;
|
|
2794
|
+
const isControlled = value !== void 0;
|
|
2795
|
+
const [internal, setInternal] = React29.useState(defaultValue);
|
|
2796
|
+
const current = isControlled ? value : internal;
|
|
2797
|
+
const handle = (v) => {
|
|
2798
|
+
if (!v) return;
|
|
2799
|
+
if (!isControlled) setInternal(v);
|
|
2800
|
+
onChange?.(v);
|
|
2801
|
+
};
|
|
2802
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2803
|
+
Field,
|
|
2804
|
+
{
|
|
2805
|
+
className,
|
|
2806
|
+
label,
|
|
2807
|
+
htmlFor: groupId,
|
|
2808
|
+
errorId,
|
|
2809
|
+
errorMessage,
|
|
2810
|
+
layout,
|
|
2811
|
+
required,
|
|
2812
|
+
helperText,
|
|
2813
|
+
children: [
|
|
2814
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: current ?? "" }),
|
|
2815
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2816
|
+
ToggleGroup__namespace.Root,
|
|
2817
|
+
{
|
|
2818
|
+
id: groupId,
|
|
2819
|
+
type: "single",
|
|
2820
|
+
value: current,
|
|
2821
|
+
onValueChange: handle,
|
|
2822
|
+
disabled,
|
|
2823
|
+
"aria-label": ariaLabel ?? (typeof label === "string" ? label : void 0),
|
|
2824
|
+
"aria-invalid": hasError || void 0,
|
|
2825
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
2826
|
+
className: [
|
|
2827
|
+
"inline-flex items-center gap-1 rounded-lg border bg-surface-raised p-1",
|
|
2828
|
+
hasError ? "border-status-error" : "border-border",
|
|
2829
|
+
sz.h,
|
|
2830
|
+
fullWidth ? "flex w-full" : "w-fit",
|
|
2831
|
+
disabled ? "opacity-60 cursor-not-allowed" : ""
|
|
2832
|
+
].filter(Boolean).join(" "),
|
|
2833
|
+
children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2834
|
+
ToggleGroup__namespace.Item,
|
|
2835
|
+
{
|
|
2836
|
+
value: opt.value,
|
|
2837
|
+
disabled: opt.disabled,
|
|
2838
|
+
className: [
|
|
2839
|
+
"inline-flex items-center justify-center gap-1.5 rounded-md select-none whitespace-nowrap",
|
|
2840
|
+
"transition-colors duration-150 h-full",
|
|
2841
|
+
sz.text,
|
|
2842
|
+
sz.pad,
|
|
2843
|
+
fullWidth ? "flex-1" : "",
|
|
2844
|
+
// Resting: muted text, transparent. Hover lifts the text.
|
|
2845
|
+
"text-foreground-secondary hover:text-foreground",
|
|
2846
|
+
// Active: surface-white pill + accent text + subtle shadow.
|
|
2847
|
+
"data-[state=on]:bg-surface data-[state=on]:text-accent data-[state=on]:shadow-sm",
|
|
2848
|
+
"focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
|
|
2849
|
+
"disabled:opacity-40 disabled:cursor-not-allowed"
|
|
2850
|
+
].filter(Boolean).join(" "),
|
|
2851
|
+
children: [
|
|
2852
|
+
opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: opt.icon }),
|
|
2853
|
+
opt.label
|
|
2854
|
+
]
|
|
2855
|
+
},
|
|
2856
|
+
opt.value
|
|
2857
|
+
))
|
|
2858
|
+
}
|
|
2859
|
+
)
|
|
2860
|
+
]
|
|
2861
|
+
}
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
// src/components/core/scheduler.utils.ts
|
|
2866
|
+
var MONTHS2 = [
|
|
2867
|
+
"January",
|
|
2868
|
+
"February",
|
|
2869
|
+
"March",
|
|
2870
|
+
"April",
|
|
2871
|
+
"May",
|
|
2872
|
+
"June",
|
|
2873
|
+
"July",
|
|
2874
|
+
"August",
|
|
2875
|
+
"September",
|
|
2876
|
+
"October",
|
|
2877
|
+
"November",
|
|
2878
|
+
"December"
|
|
2879
|
+
];
|
|
2880
|
+
var MONTHS_SHORT = MONTHS2.map((m) => m.slice(0, 3));
|
|
2881
|
+
var WEEKDAYS2 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
2882
|
+
var toDate = (d) => d instanceof Date ? d : new Date(d);
|
|
2883
|
+
var startOfDay2 = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
2884
|
+
var addDays = (d, n) => {
|
|
2885
|
+
const x = new Date(d);
|
|
2886
|
+
x.setDate(x.getDate() + n);
|
|
2887
|
+
return x;
|
|
2888
|
+
};
|
|
2889
|
+
var addMonths2 = (d, n) => new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
2890
|
+
var sameDay2 = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
2891
|
+
var isToday = (d) => sameDay2(d, /* @__PURE__ */ new Date());
|
|
2892
|
+
var isSameMonth = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
2893
|
+
var startOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
|
|
2894
|
+
var endOfMonth = (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0);
|
|
2895
|
+
var startOfWeek = (d, weekStartsOn) => {
|
|
2896
|
+
const x = startOfDay2(d);
|
|
2897
|
+
const diff = (x.getDay() - weekStartsOn + 7) % 7;
|
|
2898
|
+
return addDays(x, -diff);
|
|
2899
|
+
};
|
|
2900
|
+
var buildMonthGrid = (cursor, weekStartsOn) => {
|
|
2901
|
+
const start = startOfWeek(startOfMonth(cursor), weekStartsOn);
|
|
2902
|
+
return Array.from({ length: 42 }, (_, i) => addDays(start, i));
|
|
2903
|
+
};
|
|
2904
|
+
var getWeekDays = (cursor, weekStartsOn) => {
|
|
2905
|
+
const start = startOfWeek(cursor, weekStartsOn);
|
|
2906
|
+
return Array.from({ length: 7 }, (_, i) => addDays(start, i));
|
|
2907
|
+
};
|
|
2908
|
+
var monthRange = (cursor) => ({
|
|
2909
|
+
from: startOfMonth(cursor),
|
|
2910
|
+
to: endOfMonth(cursor)
|
|
2911
|
+
});
|
|
2912
|
+
var weekRange = (cursor, weekStartsOn) => {
|
|
2913
|
+
const from = startOfWeek(cursor, weekStartsOn);
|
|
2914
|
+
return { from, to: addDays(from, 6) };
|
|
2915
|
+
};
|
|
2916
|
+
var weekdayLabels = (weekStartsOn) => Array.from({ length: 7 }, (_, i) => WEEKDAYS2[(i + weekStartsOn) % 7]);
|
|
2917
|
+
var monthYearLabel = (d) => `${MONTHS2[d.getMonth()]} ${d.getFullYear()}`;
|
|
2918
|
+
var weekLabel = (cursor, weekStartsOn) => {
|
|
2919
|
+
const from = startOfWeek(cursor, weekStartsOn);
|
|
2920
|
+
const to = addDays(from, 6);
|
|
2921
|
+
const m = (d) => MONTHS2[d.getMonth()].slice(0, 3);
|
|
2922
|
+
if (from.getMonth() === to.getMonth()) {
|
|
2923
|
+
return `${m(from)} ${from.getDate()} \u2013 ${to.getDate()}, ${to.getFullYear()}`;
|
|
2924
|
+
}
|
|
2925
|
+
const yearPart = from.getFullYear() === to.getFullYear() ? `${to.getFullYear()}` : "";
|
|
2926
|
+
return `${m(from)} ${from.getDate()} \u2013 ${m(to)} ${to.getDate()}${yearPart ? `, ${yearPart}` : `, ${from.getFullYear()}/${to.getFullYear()}`}`;
|
|
2927
|
+
};
|
|
2928
|
+
var minutesIntoDay = (d) => d.getHours() * 60 + d.getMinutes();
|
|
2929
|
+
var hourLabel = (hour) => `${String(hour).padStart(2, "0")}:00`;
|
|
2930
|
+
var timeLabel = (d) => `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
2931
|
+
var normalize = (e) => {
|
|
2932
|
+
const start = toDate(e.start);
|
|
2933
|
+
const end = e.end ? toDate(e.end) : new Date(start.getTime() + 36e5);
|
|
2934
|
+
return { ...e, start, end };
|
|
2935
|
+
};
|
|
2936
|
+
var Spinner2 = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", className: "h-5 w-5 animate-spin text-accent", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.755 10.059a7.5 7.5 0 0112.548-3.364l1.903 1.903h-3.183a.75.75 0 100 1.5h4.992a.75.75 0 00.75-.75V4.356a.75.75 0 00-1.5 0v3.18l-1.9-1.9A9 9 0 003.306 9.67a.75.75 0 101.45.388zm15.408 3.352a.75.75 0 00-.919.53 7.5 7.5 0 01-12.548 3.364l-1.902-1.903h3.183a.75.75 0 000-1.5H2.984a.75.75 0 00-.75.75v4.992a.75.75 0 001.5 0v-3.18l1.9 1.9a9 9 0 0015.059-4.035.75.75 0 00-.53-.918z" }) });
|
|
2937
|
+
var Plus = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 5v14M5 12h14" }) });
|
|
2938
|
+
var Chevron4 = ({ dir }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: dir === "left" ? "M15 19l-7-7 7-7" : "M9 5l7 7-7 7" }) });
|
|
2939
|
+
function Scheduler({
|
|
2940
|
+
events: controlledEvents,
|
|
2941
|
+
loadEvents,
|
|
2942
|
+
defaultView = "month",
|
|
2943
|
+
defaultDate,
|
|
2944
|
+
weekStartsOn = 0,
|
|
2945
|
+
dayHours = [0, 24],
|
|
2946
|
+
hourHeight = 48,
|
|
2947
|
+
onSelectSlot,
|
|
2948
|
+
onSelectEvent,
|
|
2949
|
+
onNewEvent,
|
|
2950
|
+
className = "",
|
|
2951
|
+
style
|
|
2952
|
+
}) {
|
|
2953
|
+
const reduced = framerMotion.useReducedMotion();
|
|
2954
|
+
const [view, setView] = React29.useState(defaultView);
|
|
2955
|
+
const [cursor, setCursor] = React29.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
|
|
2956
|
+
const [loaded, setLoaded] = React29.useState([]);
|
|
2957
|
+
const [loading, setLoading] = React29.useState(false);
|
|
2958
|
+
const [dir, setDir] = React29.useState(0);
|
|
2959
|
+
const loaderRef = React29.useRef(loadEvents);
|
|
2960
|
+
loaderRef.current = loadEvents;
|
|
2961
|
+
const range = React29.useMemo(
|
|
2962
|
+
() => view === "month" ? monthRange(cursor) : weekRange(cursor, weekStartsOn),
|
|
2963
|
+
[view, cursor, weekStartsOn]
|
|
2964
|
+
);
|
|
2965
|
+
const fromKey = range.from.getTime();
|
|
2966
|
+
const toKey = range.to.getTime();
|
|
2967
|
+
React29.useEffect(() => {
|
|
2968
|
+
const loader = loaderRef.current;
|
|
2969
|
+
if (!loader) return;
|
|
2970
|
+
let cancelled = false;
|
|
2971
|
+
setLoading(true);
|
|
2972
|
+
Promise.resolve(loader({ from: new Date(fromKey), to: new Date(toKey) }, view)).then((evts) => {
|
|
2973
|
+
if (!cancelled) setLoaded(evts);
|
|
2974
|
+
}).catch(() => {
|
|
2975
|
+
if (!cancelled) setLoaded([]);
|
|
2976
|
+
}).finally(() => {
|
|
2977
|
+
if (!cancelled) setLoading(false);
|
|
2978
|
+
});
|
|
2979
|
+
return () => {
|
|
2980
|
+
cancelled = true;
|
|
2981
|
+
};
|
|
2982
|
+
}, [fromKey, toKey, view]);
|
|
2983
|
+
const events = React29.useMemo(
|
|
2984
|
+
() => (controlledEvents ?? loaded).map(normalize),
|
|
2985
|
+
[controlledEvents, loaded]
|
|
2986
|
+
);
|
|
2987
|
+
const go = React29.useCallback((delta) => {
|
|
2988
|
+
setDir(delta);
|
|
2989
|
+
setCursor((c) => view === "month" ? addMonths2(c, delta) : addDays(c, delta * 7));
|
|
2990
|
+
}, [view]);
|
|
2991
|
+
const goToday = React29.useCallback(() => {
|
|
2992
|
+
setDir(0);
|
|
2993
|
+
setCursor(/* @__PURE__ */ new Date());
|
|
2994
|
+
}, []);
|
|
2995
|
+
const title = view === "month" ? monthYearLabel(cursor) : weekLabel(cursor, weekStartsOn);
|
|
2996
|
+
const slide = reduced ? { duration: 0 } : { duration: 0.22, ease: [0.16, 1, 0.3, 1] };
|
|
2997
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2998
|
+
"div",
|
|
2999
|
+
{
|
|
3000
|
+
className: ["flex flex-col overflow-hidden rounded-xl border border-border bg-surface", className].filter(Boolean).join(" "),
|
|
3001
|
+
style,
|
|
3002
|
+
children: [
|
|
3003
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b border-border px-4 py-3", children: [
|
|
3004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3005
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "left" }), title: "Previous", onClick: () => go(-1) }),
|
|
3006
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "right" }), title: "Next", onClick: () => go(1) }),
|
|
3007
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { variant: "ghost", size: "sm", content: "Today", onClick: goToday }),
|
|
3008
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3009
|
+
MonthYearPicker,
|
|
3010
|
+
{
|
|
3011
|
+
label: title,
|
|
3012
|
+
cursor,
|
|
3013
|
+
onPick: (d) => {
|
|
3014
|
+
setDir(0);
|
|
3015
|
+
setCursor(d);
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
),
|
|
3019
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx(Spinner2, {})
|
|
3020
|
+
] }),
|
|
3021
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3022
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3023
|
+
SegmentedControl,
|
|
3024
|
+
{
|
|
3025
|
+
size: "sm",
|
|
3026
|
+
"aria-label": "Calendar view",
|
|
3027
|
+
value: view,
|
|
3028
|
+
onChange: (v) => setView(v),
|
|
3029
|
+
options: [{ value: "month", label: "Month" }, { value: "week", label: "Week" }]
|
|
3030
|
+
}
|
|
3031
|
+
),
|
|
3032
|
+
onNewEvent && /* @__PURE__ */ jsxRuntime.jsx(Button_default, { size: "sm", icon: /* @__PURE__ */ jsxRuntime.jsx(Plus, {}), content: "New event", onClick: onNewEvent })
|
|
3033
|
+
] })
|
|
3034
|
+
] }),
|
|
3035
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3036
|
+
framerMotion.motion.div,
|
|
3037
|
+
{
|
|
3038
|
+
initial: { opacity: 0, x: reduced ? 0 : dir * 24 },
|
|
3039
|
+
animate: { opacity: 1, x: 0 },
|
|
3040
|
+
transition: slide,
|
|
3041
|
+
className: "h-full",
|
|
3042
|
+
children: view === "month" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3043
|
+
MonthView,
|
|
3044
|
+
{
|
|
3045
|
+
cursor,
|
|
3046
|
+
weekStartsOn,
|
|
3047
|
+
events,
|
|
3048
|
+
onSelectSlot,
|
|
3049
|
+
onSelectEvent
|
|
3050
|
+
}
|
|
3051
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3052
|
+
WeekView,
|
|
3053
|
+
{
|
|
3054
|
+
cursor,
|
|
3055
|
+
weekStartsOn,
|
|
3056
|
+
events,
|
|
3057
|
+
dayHours,
|
|
3058
|
+
hourHeight,
|
|
3059
|
+
onSelectSlot,
|
|
3060
|
+
onSelectEvent
|
|
3061
|
+
}
|
|
3062
|
+
)
|
|
3063
|
+
},
|
|
3064
|
+
`${view}-${range.from.getTime()}`
|
|
3065
|
+
) })
|
|
3066
|
+
]
|
|
3067
|
+
}
|
|
3068
|
+
);
|
|
3069
|
+
}
|
|
3070
|
+
function MonthYearPicker({ label, cursor, onPick }) {
|
|
3071
|
+
const [open, setOpen] = React29.useState(false);
|
|
3072
|
+
const [viewYear, setViewYear] = React29.useState(cursor.getFullYear());
|
|
3073
|
+
React29.useEffect(() => {
|
|
3074
|
+
if (open) setViewYear(cursor.getFullYear());
|
|
3075
|
+
}, [open, cursor]);
|
|
3076
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
3077
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3078
|
+
"button",
|
|
3079
|
+
{
|
|
3080
|
+
type: "button",
|
|
3081
|
+
className: "group ml-1 inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 text-lg font-semibold tracking-tight text-foreground transition-colors hover:bg-background focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
3082
|
+
children: [
|
|
3083
|
+
label,
|
|
3084
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-4 w-4 text-foreground-muted transition-transform duration-150 group-data-[state=open]:rotate-180", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" }) })
|
|
3085
|
+
]
|
|
3086
|
+
}
|
|
3087
|
+
) }),
|
|
3088
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3089
|
+
Popover__namespace.Content,
|
|
3090
|
+
{
|
|
3091
|
+
align: "start",
|
|
3092
|
+
sideOffset: 8,
|
|
3093
|
+
className: [
|
|
3094
|
+
"z-[400] w-64 rounded-lg border border-border bg-surface p-3 shadow-lg",
|
|
3095
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
3096
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
|
|
3097
|
+
].join(" "),
|
|
3098
|
+
children: [
|
|
3099
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
3100
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton, { size: "sm", type: "bordered", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "left" }), title: "Previous year", onClick: () => setViewYear((y) => y - 1) }),
|
|
3101
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold tabular-nums text-foreground", children: viewYear }),
|
|
3102
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton, { size: "sm", type: "bordered", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "right" }), title: "Next year", onClick: () => setViewYear((y) => y + 1) })
|
|
3103
|
+
] }),
|
|
3104
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-1", children: MONTHS_SHORT.map((m, i) => {
|
|
3105
|
+
const current = i === cursor.getMonth() && viewYear === cursor.getFullYear();
|
|
3106
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3107
|
+
"button",
|
|
3108
|
+
{
|
|
3109
|
+
type: "button",
|
|
3110
|
+
onClick: () => {
|
|
3111
|
+
onPick(new Date(viewYear, i, 1));
|
|
3112
|
+
setOpen(false);
|
|
3113
|
+
},
|
|
3114
|
+
className: [
|
|
3115
|
+
"rounded-md px-2 py-1.5 text-sm transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
3116
|
+
current ? "bg-accent font-semibold text-accent-fg" : "text-foreground hover:bg-background"
|
|
3117
|
+
].join(" "),
|
|
3118
|
+
children: m
|
|
3119
|
+
},
|
|
3120
|
+
m
|
|
3121
|
+
);
|
|
3122
|
+
}) })
|
|
3123
|
+
]
|
|
3124
|
+
}
|
|
3125
|
+
) })
|
|
3126
|
+
] });
|
|
3127
|
+
}
|
|
3128
|
+
var MAX_CHIPS = 3;
|
|
3129
|
+
function MonthView({
|
|
3130
|
+
cursor,
|
|
3131
|
+
weekStartsOn,
|
|
3132
|
+
events,
|
|
3133
|
+
onSelectSlot,
|
|
3134
|
+
onSelectEvent
|
|
3135
|
+
}) {
|
|
3136
|
+
const grid = React29.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
|
|
3137
|
+
const labels = weekdayLabels(weekStartsOn);
|
|
3138
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
|
|
3139
|
+
/* @__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)) }),
|
|
3140
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid flex-1 grid-cols-7 grid-rows-6", children: grid.map((day, i) => {
|
|
3141
|
+
const inMonth = isSameMonth(day, cursor);
|
|
3142
|
+
const dayEvents = events.filter((e) => sameDay2(e.start, day));
|
|
3143
|
+
const today = isToday(day);
|
|
3144
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3145
|
+
"button",
|
|
3146
|
+
{
|
|
3147
|
+
type: "button",
|
|
3148
|
+
onClick: () => onSelectSlot?.(day),
|
|
3149
|
+
className: [
|
|
3150
|
+
"group flex min-h-[5rem] flex-col gap-1 border-b border-r border-border p-1.5 text-left transition-colors",
|
|
3151
|
+
"[&:nth-child(7n)]:border-r-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent",
|
|
3152
|
+
// surface===surface-raised in light mode, so hover lifts toward the
|
|
3153
|
+
// cool chart-mist background instead (a visible, on-brand tint).
|
|
3154
|
+
inMonth ? "bg-surface hover:bg-background" : "bg-background hover:bg-surface"
|
|
3155
|
+
].join(" "),
|
|
3156
|
+
children: [
|
|
3157
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3158
|
+
"span",
|
|
3159
|
+
{
|
|
3160
|
+
className: [
|
|
3161
|
+
"flex h-6 w-6 items-center justify-center self-start rounded-full text-xs tabular-nums",
|
|
3162
|
+
today ? "bg-accent font-semibold text-accent-fg" : inMonth ? "text-foreground" : "text-foreground-muted"
|
|
3163
|
+
].join(" "),
|
|
3164
|
+
children: day.getDate()
|
|
3165
|
+
}
|
|
3166
|
+
),
|
|
3167
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
3168
|
+
dayEvents.slice(0, MAX_CHIPS).map((e) => /* @__PURE__ */ jsxRuntime.jsx(EventChip, { event: e, onSelect: onSelectEvent }, e.id)),
|
|
3169
|
+
dayEvents.length > MAX_CHIPS && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-1 text-[11px] font-medium text-foreground-muted", children: [
|
|
3170
|
+
"+",
|
|
3171
|
+
dayEvents.length - MAX_CHIPS,
|
|
3172
|
+
" more"
|
|
3173
|
+
] })
|
|
3174
|
+
] })
|
|
3175
|
+
]
|
|
3176
|
+
},
|
|
3177
|
+
i
|
|
3178
|
+
);
|
|
3179
|
+
}) })
|
|
3180
|
+
] });
|
|
3181
|
+
}
|
|
3182
|
+
function EventChip({ event, onSelect }) {
|
|
3183
|
+
const color = event.color ?? "var(--color-accent)";
|
|
3184
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3185
|
+
"button",
|
|
3186
|
+
{
|
|
3187
|
+
type: "button",
|
|
3188
|
+
onClick: (e) => {
|
|
3189
|
+
e.stopPropagation();
|
|
3190
|
+
onSelect?.(event);
|
|
3191
|
+
},
|
|
3192
|
+
title: `${event.title} \xB7 ${timeLabel(event.start)}`,
|
|
3193
|
+
className: "flex items-center gap-1.5 truncate rounded px-1 py-0.5 text-left text-[11px] font-medium text-foreground hover:opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
3194
|
+
children: [
|
|
3195
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 flex-shrink-0 rounded-full", style: { backgroundColor: color } }),
|
|
3196
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: event.title })
|
|
3197
|
+
]
|
|
3198
|
+
}
|
|
3199
|
+
);
|
|
3200
|
+
}
|
|
3201
|
+
function WeekView({
|
|
3202
|
+
cursor,
|
|
3203
|
+
weekStartsOn,
|
|
3204
|
+
events,
|
|
3205
|
+
dayHours,
|
|
3206
|
+
hourHeight,
|
|
3207
|
+
onSelectSlot,
|
|
3208
|
+
onSelectEvent
|
|
3209
|
+
}) {
|
|
3210
|
+
const days = React29.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
|
|
3211
|
+
const labels = React29.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
|
|
3212
|
+
const dow = (d) => labels[(d.getDay() - weekStartsOn + 7) % 7];
|
|
3213
|
+
const [startHour, endHour] = dayHours;
|
|
3214
|
+
const hours = React29.useMemo(
|
|
3215
|
+
() => Array.from({ length: endHour - startHour }, (_, i) => startHour + i),
|
|
3216
|
+
[startHour, endHour]
|
|
3217
|
+
);
|
|
3218
|
+
const spanMinutes = (endHour - startHour) * 60;
|
|
3219
|
+
const gridHeight = hours.length * hourHeight;
|
|
3220
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
|
|
3221
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid border-b border-border", style: { gridTemplateColumns: `3.5rem repeat(7, 1fr)` }, children: [
|
|
3222
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-r border-border" }),
|
|
3223
|
+
days.map((d) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-r border-border px-1 py-1.5 text-center last:border-r-0", children: [
|
|
3224
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] font-medium uppercase tracking-wide text-foreground-muted", children: dow(d) }),
|
|
3225
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: ["mx-auto mt-0.5 flex h-6 w-6 items-center justify-center rounded-full text-xs tabular-nums", isToday(d) ? "bg-accent font-semibold text-accent-fg" : "text-foreground"].join(" "), children: d.getDate() })
|
|
3226
|
+
] }, d.getTime()))
|
|
3227
|
+
] }),
|
|
3228
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid", style: { gridTemplateColumns: `3.5rem repeat(7, 1fr)`, height: gridHeight }, children: [
|
|
3229
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative border-r border-border", children: hours.map((h, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-1 -translate-y-1/2 text-[10px] tabular-nums text-foreground-muted", style: { top: i * hourHeight }, children: i === 0 ? "" : hourLabel(h) }, h)) }),
|
|
3230
|
+
days.map((day) => {
|
|
3231
|
+
const dayEvents = events.filter((e) => sameDay2(e.start, day) && !e.allDay);
|
|
3232
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative border-r border-border last:border-r-0", children: [
|
|
3233
|
+
hours.map((h, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3234
|
+
"button",
|
|
3235
|
+
{
|
|
3236
|
+
type: "button",
|
|
3237
|
+
"aria-label": `${dow(day)} ${day.getDate()} ${hourLabel(h)}`,
|
|
3238
|
+
onClick: () => onSelectSlot?.(new Date(day.getFullYear(), day.getMonth(), day.getDate(), h)),
|
|
3239
|
+
className: "absolute left-0 right-0 border-b border-border hover:bg-background focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent",
|
|
3240
|
+
style: { top: i * hourHeight, height: hourHeight }
|
|
3241
|
+
},
|
|
3242
|
+
h
|
|
3243
|
+
)),
|
|
3244
|
+
dayEvents.map((e) => {
|
|
3245
|
+
const top = (minutesIntoDay(e.start) - startHour * 60) / spanMinutes * gridHeight;
|
|
3246
|
+
const durMin = Math.max(20, (e.end.getTime() - e.start.getTime()) / 6e4);
|
|
3247
|
+
const height = durMin / spanMinutes * gridHeight;
|
|
3248
|
+
const color = e.color ?? "var(--color-accent)";
|
|
3249
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3250
|
+
"button",
|
|
3251
|
+
{
|
|
3252
|
+
type: "button",
|
|
3253
|
+
onClick: (ev) => {
|
|
3254
|
+
ev.stopPropagation();
|
|
3255
|
+
onSelectEvent?.(e);
|
|
3256
|
+
},
|
|
3257
|
+
title: `${e.title} \xB7 ${timeLabel(e.start)}\u2013${timeLabel(e.end)}`,
|
|
3258
|
+
className: "absolute left-0.5 right-0.5 overflow-hidden rounded-md border px-1.5 py-0.5 text-left text-[11px] leading-tight text-foreground shadow-sm transition-shadow hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
3259
|
+
style: {
|
|
3260
|
+
top: Math.max(0, top),
|
|
3261
|
+
height,
|
|
3262
|
+
backgroundColor: `color-mix(in oklab, ${color} 14%, var(--color-surface))`,
|
|
3263
|
+
borderColor: `color-mix(in oklab, ${color} 40%, var(--color-surface))`
|
|
3264
|
+
},
|
|
3265
|
+
children: [
|
|
3266
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: e.title }),
|
|
3267
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate", style: { color }, children: timeLabel(e.start) })
|
|
3268
|
+
]
|
|
2630
3269
|
},
|
|
2631
|
-
|
|
2632
|
-
)
|
|
2633
|
-
|
|
2634
|
-
},
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
}) })
|
|
3270
|
+
e.id
|
|
3271
|
+
);
|
|
3272
|
+
})
|
|
3273
|
+
] }, day.getTime());
|
|
3274
|
+
})
|
|
3275
|
+
] }) })
|
|
2638
3276
|
] });
|
|
2639
3277
|
}
|
|
2640
3278
|
function DefaultIllustration() {
|
|
@@ -2764,17 +3402,17 @@ function Cart({
|
|
|
2764
3402
|
] })
|
|
2765
3403
|
] });
|
|
2766
3404
|
}
|
|
2767
|
-
var CartContext =
|
|
3405
|
+
var CartContext = React29.createContext(null);
|
|
2768
3406
|
var clampQty = (qty, max) => {
|
|
2769
3407
|
const lower = Math.max(1, Math.round(qty));
|
|
2770
3408
|
return max != null ? Math.min(lower, max) : lower;
|
|
2771
3409
|
};
|
|
2772
3410
|
function CartProvider({ children, initialItems = [], onChange }) {
|
|
2773
|
-
const [items, setItems] =
|
|
2774
|
-
|
|
3411
|
+
const [items, setItems] = React29.useState(initialItems);
|
|
3412
|
+
React29.useEffect(() => {
|
|
2775
3413
|
onChange?.(items);
|
|
2776
3414
|
}, [items]);
|
|
2777
|
-
const addToCart =
|
|
3415
|
+
const addToCart = React29.useCallback((item, quantity) => {
|
|
2778
3416
|
const addQty = quantity ?? item.quantity ?? 1;
|
|
2779
3417
|
setItems((prev) => {
|
|
2780
3418
|
const existing = prev.find((it) => it.id === item.id);
|
|
@@ -2787,29 +3425,29 @@ function CartProvider({ children, initialItems = [], onChange }) {
|
|
|
2787
3425
|
return [...prev, { ...rest, quantity: clampQty(addQty, item.max) }];
|
|
2788
3426
|
});
|
|
2789
3427
|
}, []);
|
|
2790
|
-
const removeFromCart =
|
|
3428
|
+
const removeFromCart = React29.useCallback((id) => {
|
|
2791
3429
|
setItems((prev) => prev.filter((it) => it.id !== id));
|
|
2792
3430
|
}, []);
|
|
2793
|
-
const updateQuantity =
|
|
3431
|
+
const updateQuantity = React29.useCallback((id, quantity) => {
|
|
2794
3432
|
setItems(
|
|
2795
3433
|
(prev) => prev.map((it) => it.id === id ? { ...it, quantity: clampQty(quantity, it.max) } : it)
|
|
2796
3434
|
);
|
|
2797
3435
|
}, []);
|
|
2798
|
-
const clearCart =
|
|
2799
|
-
const isInCart =
|
|
2800
|
-
const getItemCount =
|
|
2801
|
-
const getCartTotal =
|
|
3436
|
+
const clearCart = React29.useCallback(() => setItems([]), []);
|
|
3437
|
+
const isInCart = React29.useCallback((id) => items.some((it) => it.id === id), [items]);
|
|
3438
|
+
const getItemCount = React29.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
|
|
3439
|
+
const getCartTotal = React29.useCallback(
|
|
2802
3440
|
() => items.reduce((sum, it) => sum + it.price * it.quantity, 0),
|
|
2803
3441
|
[items]
|
|
2804
3442
|
);
|
|
2805
|
-
const value =
|
|
3443
|
+
const value = React29.useMemo(
|
|
2806
3444
|
() => ({ items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal }),
|
|
2807
3445
|
[items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal]
|
|
2808
3446
|
);
|
|
2809
3447
|
return /* @__PURE__ */ jsxRuntime.jsx(CartContext.Provider, { value, children });
|
|
2810
3448
|
}
|
|
2811
3449
|
function useCart() {
|
|
2812
|
-
const ctx =
|
|
3450
|
+
const ctx = React29.useContext(CartContext);
|
|
2813
3451
|
if (!ctx) {
|
|
2814
3452
|
throw new Error("useCart must be used within a <CartProvider>.");
|
|
2815
3453
|
}
|
|
@@ -3143,11 +3781,11 @@ function buildBindings(store, name, kind, snap) {
|
|
|
3143
3781
|
|
|
3144
3782
|
// src/form/useForm.ts
|
|
3145
3783
|
function useForm(options = {}) {
|
|
3146
|
-
const ref =
|
|
3784
|
+
const ref = React29.useRef(null);
|
|
3147
3785
|
if (ref.current === null) ref.current = new FormStore(options);
|
|
3148
3786
|
const store = ref.current;
|
|
3149
|
-
|
|
3150
|
-
const make =
|
|
3787
|
+
React29.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
3788
|
+
const make = React29.useCallback(
|
|
3151
3789
|
(kind) => (name, rules) => {
|
|
3152
3790
|
if (rules !== void 0) store.setRule(name, rules);
|
|
3153
3791
|
return buildBindings(store, name, kind, store.getFieldSnapshot(name));
|
|
@@ -3176,9 +3814,9 @@ function useForm(options = {}) {
|
|
|
3176
3814
|
fieldTarget: make("target")
|
|
3177
3815
|
};
|
|
3178
3816
|
}
|
|
3179
|
-
var FormContext =
|
|
3817
|
+
var FormContext = React29.createContext(null);
|
|
3180
3818
|
function useFormStore() {
|
|
3181
|
-
const store =
|
|
3819
|
+
const store = React29.useContext(FormContext);
|
|
3182
3820
|
if (!store) {
|
|
3183
3821
|
throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
|
|
3184
3822
|
}
|
|
@@ -3192,8 +3830,8 @@ function Form({
|
|
|
3192
3830
|
children,
|
|
3193
3831
|
...rest
|
|
3194
3832
|
}) {
|
|
3195
|
-
const ref =
|
|
3196
|
-
const bypass =
|
|
3833
|
+
const ref = React29.useRef(null);
|
|
3834
|
+
const bypass = React29.useRef(false);
|
|
3197
3835
|
const handleSubmit = async (e) => {
|
|
3198
3836
|
if (bypass.current) {
|
|
3199
3837
|
bypass.current = false;
|
|
@@ -3245,12 +3883,12 @@ function useFormField(name, options = {}) {
|
|
|
3245
3883
|
const store = useFormStore();
|
|
3246
3884
|
const { kind = "value", rules } = options;
|
|
3247
3885
|
if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
|
|
3248
|
-
|
|
3886
|
+
React29.useEffect(() => {
|
|
3249
3887
|
return () => {
|
|
3250
3888
|
if (rules !== void 0) store.removeRule(name);
|
|
3251
3889
|
};
|
|
3252
3890
|
}, [store, name]);
|
|
3253
|
-
const snap =
|
|
3891
|
+
const snap = React29.useSyncExternalStore(
|
|
3254
3892
|
store.subscribe,
|
|
3255
3893
|
() => store.getFieldSnapshot(name)
|
|
3256
3894
|
);
|
|
@@ -3262,7 +3900,7 @@ function FormField({ name, kind, rules, children }) {
|
|
|
3262
3900
|
}
|
|
3263
3901
|
function useFieldArray(name) {
|
|
3264
3902
|
const store = useFormStore();
|
|
3265
|
-
|
|
3903
|
+
React29.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
3266
3904
|
const arr = store.getValue(name) ?? [];
|
|
3267
3905
|
const keys = store.getKeys(name);
|
|
3268
3906
|
return {
|
|
@@ -3273,134 +3911,6 @@ function useFieldArray(name) {
|
|
|
3273
3911
|
replace: (items) => store.setValue(name, items, { validate: false })
|
|
3274
3912
|
};
|
|
3275
3913
|
}
|
|
3276
|
-
var FIELD_SIZE = {
|
|
3277
|
-
sm: { control: "h-control-sm", text: "text-xs", padX: "px-2.5", gap: "gap-1.5" },
|
|
3278
|
-
md: { control: "h-control-md", text: "text-sm", padX: "px-3", gap: "gap-2" },
|
|
3279
|
-
lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
|
|
3280
|
-
};
|
|
3281
|
-
var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent";
|
|
3282
|
-
var FOCUS_ELEMENT = "focus:outline-none focus:border-accent data-[state=open]:border-accent";
|
|
3283
|
-
var FOCUS_WITHIN_ERROR = "focus-within:border-status-error";
|
|
3284
|
-
var FOCUS_ELEMENT_ERROR = "focus:border-status-error data-[state=open]:border-status-error";
|
|
3285
|
-
function fieldShell({
|
|
3286
|
-
size = "md",
|
|
3287
|
-
hasError = false,
|
|
3288
|
-
disabled = false,
|
|
3289
|
-
focusWithin = false,
|
|
3290
|
-
sized = true
|
|
3291
|
-
} = {}) {
|
|
3292
|
-
const s = FIELD_SIZE[size];
|
|
3293
|
-
return [
|
|
3294
|
-
"w-full rounded-lg border bg-surface text-foreground",
|
|
3295
|
-
"transition-[color,box-shadow,border-color] duration-150",
|
|
3296
|
-
s.text,
|
|
3297
|
-
sized ? `${s.control} ${s.padX}` : "",
|
|
3298
|
-
// resting border
|
|
3299
|
-
hasError ? "border-status-error" : "border-border",
|
|
3300
|
-
// hover (only when interactive + no error)
|
|
3301
|
-
disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
|
|
3302
|
-
// focus
|
|
3303
|
-
focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
|
|
3304
|
-
hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
|
|
3305
|
-
// placeholder colour for native inputs
|
|
3306
|
-
"placeholder:text-foreground-muted"
|
|
3307
|
-
].filter(Boolean).join(" ");
|
|
3308
|
-
}
|
|
3309
|
-
function FieldHelpIcon({ text }) {
|
|
3310
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { title: text, placement: "top", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3311
|
-
"button",
|
|
3312
|
-
{
|
|
3313
|
-
type: "button",
|
|
3314
|
-
"aria-label": "More information",
|
|
3315
|
-
className: "inline-flex items-center justify-center rounded-full text-foreground-muted transition-colors hover:text-foreground focus:outline-none focus-visible:text-accent",
|
|
3316
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [
|
|
3317
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.25" }),
|
|
3318
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M8 7.4v3.4" }),
|
|
3319
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "5.1", r: "0.65", fill: "currentColor", stroke: "none" })
|
|
3320
|
-
] })
|
|
3321
|
-
}
|
|
3322
|
-
) });
|
|
3323
|
-
}
|
|
3324
|
-
function FieldLabel({
|
|
3325
|
-
label,
|
|
3326
|
-
htmlFor,
|
|
3327
|
-
required,
|
|
3328
|
-
helperText,
|
|
3329
|
-
horizontal = false,
|
|
3330
|
-
align = "start",
|
|
3331
|
-
style,
|
|
3332
|
-
width,
|
|
3333
|
-
className = ""
|
|
3334
|
-
}) {
|
|
3335
|
-
if (label == null && helperText == null) return null;
|
|
3336
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3337
|
-
"div",
|
|
3338
|
-
{
|
|
3339
|
-
style: { width: horizontal ? width : void 0, ...style },
|
|
3340
|
-
className: [
|
|
3341
|
-
"flex items-center gap-1",
|
|
3342
|
-
horizontal ? "flex-shrink-0 whitespace-nowrap" : "",
|
|
3343
|
-
// Only the 'start' alignment needs the top nudge; 'center' relies
|
|
3344
|
-
// on the row's items-center to line up with a short control.
|
|
3345
|
-
horizontal && align === "start" ? "mt-2" : "",
|
|
3346
|
-
className
|
|
3347
|
-
].filter(Boolean).join(" "),
|
|
3348
|
-
children: [
|
|
3349
|
-
label != null && /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor, className: "text-sm font-medium text-foreground select-none", children: [
|
|
3350
|
-
label,
|
|
3351
|
-
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
|
|
3352
|
-
] }),
|
|
3353
|
-
helperText != null && /* @__PURE__ */ jsxRuntime.jsx(FieldHelpIcon, { text: helperText })
|
|
3354
|
-
]
|
|
3355
|
-
}
|
|
3356
|
-
);
|
|
3357
|
-
}
|
|
3358
|
-
function Field({
|
|
3359
|
-
label,
|
|
3360
|
-
htmlFor,
|
|
3361
|
-
errorId,
|
|
3362
|
-
errorMessage,
|
|
3363
|
-
layout = "vertical",
|
|
3364
|
-
required,
|
|
3365
|
-
helperText,
|
|
3366
|
-
labelAlign = "start",
|
|
3367
|
-
labelStyle,
|
|
3368
|
-
labelWidth,
|
|
3369
|
-
className = "",
|
|
3370
|
-
children
|
|
3371
|
-
}) {
|
|
3372
|
-
const hasError = errorMessage != null;
|
|
3373
|
-
const horizontal = layout === "horizontal";
|
|
3374
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3375
|
-
"div",
|
|
3376
|
-
{
|
|
3377
|
-
className: [
|
|
3378
|
-
"flex",
|
|
3379
|
-
horizontal ? `flex-row gap-3 ${labelAlign === "center" ? "items-center" : "items-start"}` : "flex-col gap-1.5",
|
|
3380
|
-
className
|
|
3381
|
-
].filter(Boolean).join(" "),
|
|
3382
|
-
children: [
|
|
3383
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3384
|
-
FieldLabel,
|
|
3385
|
-
{
|
|
3386
|
-
label,
|
|
3387
|
-
htmlFor,
|
|
3388
|
-
required,
|
|
3389
|
-
helperText,
|
|
3390
|
-
horizontal,
|
|
3391
|
-
align: labelAlign,
|
|
3392
|
-
style: labelStyle,
|
|
3393
|
-
width: labelWidth
|
|
3394
|
-
}
|
|
3395
|
-
),
|
|
3396
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
3397
|
-
children,
|
|
3398
|
-
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
|
|
3399
|
-
] })
|
|
3400
|
-
]
|
|
3401
|
-
}
|
|
3402
|
-
);
|
|
3403
|
-
}
|
|
3404
3914
|
function TextInput({
|
|
3405
3915
|
value,
|
|
3406
3916
|
onChange,
|
|
@@ -3423,7 +3933,7 @@ function TextInput({
|
|
|
3423
3933
|
suffix,
|
|
3424
3934
|
id
|
|
3425
3935
|
}) {
|
|
3426
|
-
const errorId =
|
|
3936
|
+
const errorId = React29.useId();
|
|
3427
3937
|
const hasError = errorMessage != null;
|
|
3428
3938
|
const hasAdornment = prefix != null || suffix != null;
|
|
3429
3939
|
const inputId = htmlFor ?? id;
|
|
@@ -3540,8 +4050,8 @@ function expiryError(value, now = /* @__PURE__ */ new Date()) {
|
|
|
3540
4050
|
const mm = Number(m[1]);
|
|
3541
4051
|
const yy = Number(m[2]);
|
|
3542
4052
|
if (mm < 1 || mm > 12) return "Invalid month";
|
|
3543
|
-
const
|
|
3544
|
-
if (
|
|
4053
|
+
const endOfMonth2 = new Date(2e3 + yy, mm, 0, 23, 59, 59, 999);
|
|
4054
|
+
if (endOfMonth2 < now) return "Card has expired";
|
|
3545
4055
|
return void 0;
|
|
3546
4056
|
}
|
|
3547
4057
|
function cvvError(value, cardNumber) {
|
|
@@ -3584,7 +4094,7 @@ function CreditCardForm({
|
|
|
3584
4094
|
className = "",
|
|
3585
4095
|
style
|
|
3586
4096
|
}) {
|
|
3587
|
-
const initial =
|
|
4097
|
+
const initial = React29.useRef({
|
|
3588
4098
|
number: formatCardNumber(defaultValue?.number ?? ""),
|
|
3589
4099
|
name: defaultValue?.name ?? "",
|
|
3590
4100
|
expiry: formatExpiry(defaultValue?.expiry ?? ""),
|
|
@@ -3593,7 +4103,7 @@ function CreditCardForm({
|
|
|
3593
4103
|
const form = useForm({ initialValues: initial });
|
|
3594
4104
|
const numberStr = String(form.values.number ?? "");
|
|
3595
4105
|
const brand = detectBrand(numberStr);
|
|
3596
|
-
|
|
4106
|
+
React29.useEffect(() => {
|
|
3597
4107
|
onChange?.(toCard(form.values));
|
|
3598
4108
|
}, [form.values.number, form.values.name, form.values.expiry, form.values.cvv]);
|
|
3599
4109
|
const numberBind = form.fieldNative("number", {
|
|
@@ -3716,7 +4226,7 @@ function Checkout({
|
|
|
3716
4226
|
] })
|
|
3717
4227
|
] });
|
|
3718
4228
|
}
|
|
3719
|
-
var NotificationContext =
|
|
4229
|
+
var NotificationContext = React29.createContext({
|
|
3720
4230
|
open: () => void 0,
|
|
3721
4231
|
close: () => void 0
|
|
3722
4232
|
});
|
|
@@ -3774,26 +4284,26 @@ function NotificationItem({
|
|
|
3774
4284
|
onClose,
|
|
3775
4285
|
reduced
|
|
3776
4286
|
}) {
|
|
3777
|
-
const [paused, setPaused] =
|
|
4287
|
+
const [paused, setPaused] = React29.useState(false);
|
|
3778
4288
|
const duration = n.duration ?? 4e3;
|
|
3779
4289
|
const isAutoDismissing = isFinite(duration) && duration > 0;
|
|
3780
4290
|
const showProgress = !reduced && isAutoDismissing;
|
|
3781
|
-
const timerRef =
|
|
3782
|
-
const startTimeRef =
|
|
3783
|
-
const remainingRef =
|
|
3784
|
-
const clearTimer =
|
|
4291
|
+
const timerRef = React29.useRef(null);
|
|
4292
|
+
const startTimeRef = React29.useRef(0);
|
|
4293
|
+
const remainingRef = React29.useRef(duration);
|
|
4294
|
+
const clearTimer = React29.useCallback(() => {
|
|
3785
4295
|
if (timerRef.current !== null) {
|
|
3786
4296
|
clearTimeout(timerRef.current);
|
|
3787
4297
|
timerRef.current = null;
|
|
3788
4298
|
}
|
|
3789
4299
|
}, []);
|
|
3790
|
-
const scheduleDismiss =
|
|
4300
|
+
const scheduleDismiss = React29.useCallback((ms) => {
|
|
3791
4301
|
clearTimer();
|
|
3792
4302
|
if (!isAutoDismissing) return;
|
|
3793
4303
|
startTimeRef.current = Date.now();
|
|
3794
4304
|
timerRef.current = setTimeout(() => onClose(n.id), ms);
|
|
3795
4305
|
}, [clearTimer, isAutoDismissing, n.id, onClose]);
|
|
3796
|
-
|
|
4306
|
+
React29.useEffect(() => {
|
|
3797
4307
|
if (paused || !isAutoDismissing) return;
|
|
3798
4308
|
scheduleDismiss(remainingRef.current);
|
|
3799
4309
|
return clearTimer;
|
|
@@ -3876,15 +4386,15 @@ function NotificationProvider({
|
|
|
3876
4386
|
children,
|
|
3877
4387
|
position = "top-right"
|
|
3878
4388
|
}) {
|
|
3879
|
-
const [notifications, setNotifications] =
|
|
4389
|
+
const [notifications, setNotifications] = React29.useState([]);
|
|
3880
4390
|
const reduced = framerMotion.useReducedMotion();
|
|
3881
|
-
const open =
|
|
4391
|
+
const open = React29.useCallback((payload) => {
|
|
3882
4392
|
setNotifications((prev) => [
|
|
3883
4393
|
...prev,
|
|
3884
4394
|
{ duration: 4e3, ...payload, id: Date.now() + Math.random() }
|
|
3885
4395
|
]);
|
|
3886
4396
|
}, []);
|
|
3887
|
-
const close =
|
|
4397
|
+
const close = React29.useCallback((id) => {
|
|
3888
4398
|
setNotifications((prev) => prev.filter((n) => n.id !== id));
|
|
3889
4399
|
}, []);
|
|
3890
4400
|
return /* @__PURE__ */ jsxRuntime.jsxs(NotificationContext.Provider, { value: { open, close }, children: [
|
|
@@ -3913,7 +4423,7 @@ function NotificationProvider({
|
|
|
3913
4423
|
] });
|
|
3914
4424
|
}
|
|
3915
4425
|
function useNotification() {
|
|
3916
|
-
const { open } =
|
|
4426
|
+
const { open } = React29.useContext(NotificationContext);
|
|
3917
4427
|
return {
|
|
3918
4428
|
info: (props) => open({ type: "info", ...props }),
|
|
3919
4429
|
success: (props) => open({ type: "success", ...props }),
|
|
@@ -4030,10 +4540,10 @@ function FadingBase({
|
|
|
4030
4540
|
isMounted = false,
|
|
4031
4541
|
children
|
|
4032
4542
|
}) {
|
|
4033
|
-
const [shouldRender, setShouldRender] =
|
|
4034
|
-
const [visible, setVisible] =
|
|
4035
|
-
const timerRef =
|
|
4036
|
-
|
|
4543
|
+
const [shouldRender, setShouldRender] = React29.useState(isMounted);
|
|
4544
|
+
const [visible, setVisible] = React29.useState(false);
|
|
4545
|
+
const timerRef = React29.useRef(null);
|
|
4546
|
+
React29.useEffect(() => {
|
|
4037
4547
|
if (isMounted) {
|
|
4038
4548
|
setShouldRender(true);
|
|
4039
4549
|
const rafId = requestAnimationFrame(() => setVisible(true));
|
|
@@ -4131,8 +4641,8 @@ function ScalableContainer({
|
|
|
4131
4641
|
togglePosition = "top-right",
|
|
4132
4642
|
className = ""
|
|
4133
4643
|
}) {
|
|
4134
|
-
const containerRef =
|
|
4135
|
-
const [internalScaled, setInternalScaled] =
|
|
4644
|
+
const containerRef = React29.useRef(null);
|
|
4645
|
+
const [internalScaled, setInternalScaled] = React29.useState(false);
|
|
4136
4646
|
const isScaled = expanded ?? internalScaled;
|
|
4137
4647
|
const reduced = framerMotion.useReducedMotion();
|
|
4138
4648
|
const onToggle = () => {
|
|
@@ -4270,17 +4780,17 @@ function CatalogGrid({ items, buttonText, onOpen, className = "" }) {
|
|
|
4270
4780
|
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)) });
|
|
4271
4781
|
}
|
|
4272
4782
|
function CatalogCarousel({ items, buttonText, onOpen, className = "" }) {
|
|
4273
|
-
const [activeIndex, setActiveIndex] =
|
|
4274
|
-
const [indexPool, setIndexPool] =
|
|
4275
|
-
const cardRefs =
|
|
4276
|
-
const getIndexes =
|
|
4783
|
+
const [activeIndex, setActiveIndex] = React29.useState(0);
|
|
4784
|
+
const [indexPool, setIndexPool] = React29.useState([]);
|
|
4785
|
+
const cardRefs = React29.useRef([]);
|
|
4786
|
+
const getIndexes = React29.useMemo(() => {
|
|
4277
4787
|
let nextIndex = activeIndex + 1;
|
|
4278
4788
|
let previousIndex = activeIndex - 1;
|
|
4279
4789
|
if (activeIndex === 0) previousIndex = items.length - 1;
|
|
4280
4790
|
if (activeIndex === items.length - 1) nextIndex = 0;
|
|
4281
4791
|
return { previousIndex, nextIndex };
|
|
4282
4792
|
}, [activeIndex, items.length]);
|
|
4283
|
-
|
|
4793
|
+
React29.useEffect(() => {
|
|
4284
4794
|
const { nextIndex, previousIndex } = getIndexes;
|
|
4285
4795
|
let indexes = [previousIndex, activeIndex, nextIndex];
|
|
4286
4796
|
if (activeIndex !== 0 && activeIndex !== items.length - 1) {
|
|
@@ -4453,8 +4963,8 @@ function writeDismissed(key) {
|
|
|
4453
4963
|
}
|
|
4454
4964
|
}
|
|
4455
4965
|
function useTargetBbox(ref) {
|
|
4456
|
-
const [bbox, setBbox] =
|
|
4457
|
-
|
|
4966
|
+
const [bbox, setBbox] = React29.useState(null);
|
|
4967
|
+
React29.useLayoutEffect(() => {
|
|
4458
4968
|
const el = ref?.current;
|
|
4459
4969
|
if (!el) {
|
|
4460
4970
|
setBbox(null);
|
|
@@ -4484,7 +4994,7 @@ function tooltipStyleFor(bbox, placement) {
|
|
|
4484
4994
|
return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
|
|
4485
4995
|
}
|
|
4486
4996
|
function useFocusTrap(containerRef, active) {
|
|
4487
|
-
|
|
4997
|
+
React29.useEffect(() => {
|
|
4488
4998
|
if (!active) return;
|
|
4489
4999
|
const el = containerRef.current;
|
|
4490
5000
|
if (!el) return;
|
|
@@ -4523,16 +5033,16 @@ function Wizard({
|
|
|
4523
5033
|
onComplete,
|
|
4524
5034
|
onSkip
|
|
4525
5035
|
}) {
|
|
4526
|
-
const tooltipRef =
|
|
4527
|
-
const tooltipTitleId =
|
|
4528
|
-
const tooltipBodyId =
|
|
5036
|
+
const tooltipRef = React29.useRef(null);
|
|
5037
|
+
const tooltipTitleId = React29.useId();
|
|
5038
|
+
const tooltipBodyId = React29.useId();
|
|
4529
5039
|
const reduced = framerMotion.useReducedMotion();
|
|
4530
|
-
const [open, setOpen] =
|
|
4531
|
-
const [activeIndex, setActiveIndex] =
|
|
5040
|
+
const [open, setOpen] = React29.useState(() => steps.length > 0 && !readDismissed(storageKey));
|
|
5041
|
+
const [activeIndex, setActiveIndex] = React29.useState(0);
|
|
4532
5042
|
const step = steps[activeIndex];
|
|
4533
5043
|
const bbox = useTargetBbox(step?.stepRef);
|
|
4534
5044
|
useFocusTrap(tooltipRef, open);
|
|
4535
|
-
|
|
5045
|
+
React29.useEffect(() => {
|
|
4536
5046
|
if (!open || !dismissible) return;
|
|
4537
5047
|
const onKey = (e) => {
|
|
4538
5048
|
if (e.key === "Escape") {
|
|
@@ -4543,12 +5053,12 @@ function Wizard({
|
|
|
4543
5053
|
document.addEventListener("keydown", onKey);
|
|
4544
5054
|
return () => document.removeEventListener("keydown", onKey);
|
|
4545
5055
|
}, [open, dismissible]);
|
|
4546
|
-
const handleSkip =
|
|
5056
|
+
const handleSkip = React29.useCallback(() => {
|
|
4547
5057
|
writeDismissed(storageKey);
|
|
4548
5058
|
setOpen(false);
|
|
4549
5059
|
onSkip?.();
|
|
4550
5060
|
}, [storageKey, onSkip]);
|
|
4551
|
-
const handleComplete =
|
|
5061
|
+
const handleComplete = React29.useCallback(() => {
|
|
4552
5062
|
writeDismissed(storageKey);
|
|
4553
5063
|
setOpen(false);
|
|
4554
5064
|
onComplete?.();
|
|
@@ -4691,7 +5201,7 @@ function Wizard({
|
|
|
4691
5201
|
] });
|
|
4692
5202
|
}
|
|
4693
5203
|
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" }) });
|
|
4694
|
-
var SearchInput =
|
|
5204
|
+
var SearchInput = React29__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
|
|
4695
5205
|
return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4696
5206
|
"div",
|
|
4697
5207
|
{
|
|
@@ -4745,11 +5255,11 @@ function MultiTagRow({
|
|
|
4745
5255
|
labelFor,
|
|
4746
5256
|
onRemove
|
|
4747
5257
|
}) {
|
|
4748
|
-
const wrapRef =
|
|
4749
|
-
const measureRef =
|
|
4750
|
-
const [visibleCount, setVisibleCount] =
|
|
5258
|
+
const wrapRef = React29.useRef(null);
|
|
5259
|
+
const measureRef = React29.useRef(null);
|
|
5260
|
+
const [visibleCount, setVisibleCount] = React29.useState(values.length);
|
|
4751
5261
|
const key = values.map(String).join("|");
|
|
4752
|
-
|
|
5262
|
+
React29.useLayoutEffect(() => {
|
|
4753
5263
|
const wrap = wrapRef.current;
|
|
4754
5264
|
const measure = measureRef.current;
|
|
4755
5265
|
if (!wrap || !measure) return;
|
|
@@ -4843,16 +5353,16 @@ function Dropdown({
|
|
|
4843
5353
|
size = "md",
|
|
4844
5354
|
className = ""
|
|
4845
5355
|
}) {
|
|
4846
|
-
const [open, setOpen] =
|
|
4847
|
-
const [selectedItems, setSelectedItems] =
|
|
4848
|
-
const [searchTerm, setSearchTerm] =
|
|
4849
|
-
const [innerItems, setInnerItems] =
|
|
4850
|
-
const errorId =
|
|
5356
|
+
const [open, setOpen] = React29.useState(false);
|
|
5357
|
+
const [selectedItems, setSelectedItems] = React29.useState([]);
|
|
5358
|
+
const [searchTerm, setSearchTerm] = React29.useState("");
|
|
5359
|
+
const [innerItems, setInnerItems] = React29.useState([]);
|
|
5360
|
+
const errorId = React29.useId();
|
|
4851
5361
|
const hasError = errorMessage != null;
|
|
4852
|
-
|
|
5362
|
+
React29.useEffect(() => {
|
|
4853
5363
|
setInnerItems(items);
|
|
4854
5364
|
}, [items]);
|
|
4855
|
-
|
|
5365
|
+
React29.useEffect(() => {
|
|
4856
5366
|
if (isMultiselect && Array.isArray(value)) {
|
|
4857
5367
|
setSelectedItems(value);
|
|
4858
5368
|
}
|
|
@@ -5177,7 +5687,7 @@ function TableBody({
|
|
|
5177
5687
|
expandRow,
|
|
5178
5688
|
getRowKey
|
|
5179
5689
|
}) {
|
|
5180
|
-
const [expanded, setExpanded] =
|
|
5690
|
+
const [expanded, setExpanded] = React29.useState(() => /* @__PURE__ */ new Set());
|
|
5181
5691
|
const reduced = framerMotion.useReducedMotion();
|
|
5182
5692
|
const toggleRow = (rowKey) => {
|
|
5183
5693
|
setExpanded((prev) => {
|
|
@@ -5192,7 +5702,7 @@ function TableBody({
|
|
|
5192
5702
|
return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => {
|
|
5193
5703
|
const rowKey = getRowKey(row, i);
|
|
5194
5704
|
const isExpanded = expanded.has(rowKey);
|
|
5195
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5705
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
|
|
5196
5706
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5197
5707
|
"tr",
|
|
5198
5708
|
{
|
|
@@ -5248,9 +5758,9 @@ function Pagination({
|
|
|
5248
5758
|
const matchedOption = picker.find(
|
|
5249
5759
|
(o) => o.label === options.perPage || o.value === options.perPage
|
|
5250
5760
|
);
|
|
5251
|
-
const [perPageKey, setPerPageKey] =
|
|
5761
|
+
const [perPageKey, setPerPageKey] = React29.useState(() => matchedOption?.key ?? picker[0]?.key);
|
|
5252
5762
|
const displayPerPageKey = serverSide ? matchedOption?.key ?? perPageKey : perPageKey;
|
|
5253
|
-
|
|
5763
|
+
React29.useEffect(() => {
|
|
5254
5764
|
if (serverSide && options.perPage != null) {
|
|
5255
5765
|
const next = picker.find((o) => o.label === options.perPage || o.value === options.perPage);
|
|
5256
5766
|
if (next) setPerPageKey(next.key);
|
|
@@ -5314,14 +5824,14 @@ function Table({
|
|
|
5314
5824
|
className = "",
|
|
5315
5825
|
style
|
|
5316
5826
|
}) {
|
|
5317
|
-
const searchRef =
|
|
5318
|
-
const [searchTerm, setSearchTerm] =
|
|
5319
|
-
const [perPage, setPerPage] =
|
|
5827
|
+
const searchRef = React29.useRef(null);
|
|
5828
|
+
const [searchTerm, setSearchTerm] = React29.useState("");
|
|
5829
|
+
const [perPage, setPerPage] = React29.useState(
|
|
5320
5830
|
typeof pagination.perPage === "number" ? pagination.perPage : 15
|
|
5321
5831
|
);
|
|
5322
|
-
const [activePage, setActivePage] =
|
|
5832
|
+
const [activePage, setActivePage] = React29.useState(0);
|
|
5323
5833
|
const isServerSide = !!(pagination.enabled && pagination.serverSide);
|
|
5324
|
-
const filteredRows =
|
|
5834
|
+
const filteredRows = React29.useMemo(() => {
|
|
5325
5835
|
if (isServerSide || !searchTerm) return rows;
|
|
5326
5836
|
const term = searchTerm.toLowerCase();
|
|
5327
5837
|
return rows.filter(
|
|
@@ -5330,29 +5840,29 @@ function Table({
|
|
|
5330
5840
|
)
|
|
5331
5841
|
);
|
|
5332
5842
|
}, [rows, searchTerm, isServerSide]);
|
|
5333
|
-
const datasets =
|
|
5843
|
+
const datasets = React29.useMemo(() => {
|
|
5334
5844
|
if (isServerSide) return [rows];
|
|
5335
5845
|
return createDatasets(filteredRows, pagination.enabled ? perPage : null);
|
|
5336
5846
|
}, [filteredRows, perPage, pagination.enabled, isServerSide, rows]);
|
|
5337
|
-
const MAX_PAGE =
|
|
5847
|
+
const MAX_PAGE = React29.useMemo(() => {
|
|
5338
5848
|
if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
|
|
5339
5849
|
if (isServerSide && typeof pagination.totalCount === "number")
|
|
5340
5850
|
return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
|
|
5341
5851
|
return datasets.length ? datasets.length - 1 : 0;
|
|
5342
5852
|
}, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
|
|
5343
|
-
const currentPageRows =
|
|
5853
|
+
const currentPageRows = React29.useMemo(() => {
|
|
5344
5854
|
if (isServerSide) return rows;
|
|
5345
5855
|
return datasets[activePage] ?? [];
|
|
5346
5856
|
}, [isServerSide, rows, datasets, activePage]);
|
|
5347
|
-
|
|
5857
|
+
React29.useEffect(() => {
|
|
5348
5858
|
if (pagination.enabled && !isServerSide && typeof pagination.perPage === "number") {
|
|
5349
5859
|
setPerPage(pagination.perPage);
|
|
5350
5860
|
}
|
|
5351
5861
|
}, [pagination.enabled, pagination.perPage, isServerSide]);
|
|
5352
|
-
|
|
5862
|
+
React29.useEffect(() => {
|
|
5353
5863
|
if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
|
|
5354
5864
|
}, [isServerSide, pagination.perPage]);
|
|
5355
|
-
|
|
5865
|
+
React29.useEffect(() => {
|
|
5356
5866
|
if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
|
|
5357
5867
|
setActivePage(pagination.page - 1);
|
|
5358
5868
|
}, [isServerSide, pagination.page]);
|
|
@@ -5436,7 +5946,7 @@ function TableSkeletonBody({
|
|
|
5436
5946
|
)) });
|
|
5437
5947
|
}
|
|
5438
5948
|
function ThemeSwitch({ checked, onChange, label = "Toggle dark mode", className = "" }) {
|
|
5439
|
-
const id =
|
|
5949
|
+
const id = React29.useId();
|
|
5440
5950
|
return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: `flex items-center gap-2 cursor-pointer select-none ${className}`.trim(), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5441
5951
|
SwitchPrimitive__namespace.Root,
|
|
5442
5952
|
{
|
|
@@ -5620,7 +6130,7 @@ function Sidebar({
|
|
|
5620
6130
|
}
|
|
5621
6131
|
) });
|
|
5622
6132
|
}
|
|
5623
|
-
var MegaMenuContext =
|
|
6133
|
+
var MegaMenuContext = React29.createContext({ align: "start" });
|
|
5624
6134
|
function MegaMenu({
|
|
5625
6135
|
children,
|
|
5626
6136
|
align = "start",
|
|
@@ -5651,7 +6161,7 @@ function MegaMenu({
|
|
|
5651
6161
|
}
|
|
5652
6162
|
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";
|
|
5653
6163
|
function MegaMenuItem({ label, icon, href, children, className = "" }) {
|
|
5654
|
-
const { align } =
|
|
6164
|
+
const { align } = React29.useContext(MegaMenuContext);
|
|
5655
6165
|
const pos = align === "center" ? "left-1/2 -translate-x-1/2" : align === "end" ? "right-0" : "left-0";
|
|
5656
6166
|
if (!children) {
|
|
5657
6167
|
return /* @__PURE__ */ jsxRuntime.jsx(NavigationMenu__namespace.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(NavigationMenu__namespace.Link, { href, className: [TOP_ITEM, className].filter(Boolean).join(" "), children: [
|
|
@@ -5736,8 +6246,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
|
|
|
5736
6246
|
function MegaMenuFeatured({ children, className = "" }) {
|
|
5737
6247
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className].filter(Boolean).join(" "), children });
|
|
5738
6248
|
}
|
|
5739
|
-
var elementsOfType = (children, type) =>
|
|
5740
|
-
(c) =>
|
|
6249
|
+
var elementsOfType = (children, type) => React29__default.default.Children.toArray(children).filter(
|
|
6250
|
+
(c) => React29__default.default.isValidElement(c) && c.type === type
|
|
5741
6251
|
);
|
|
5742
6252
|
var MOBILE_CHEVRON = /* @__PURE__ */ jsxRuntime.jsx(
|
|
5743
6253
|
"svg",
|
|
@@ -5774,9 +6284,9 @@ function MobileLinkRow({ link, onNavigate }) {
|
|
|
5774
6284
|
);
|
|
5775
6285
|
}
|
|
5776
6286
|
function MobilePanel({ panel, onNavigate }) {
|
|
5777
|
-
const nodes =
|
|
6287
|
+
const nodes = React29__default.default.Children.toArray(panel.props.children);
|
|
5778
6288
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
|
|
5779
|
-
if (!
|
|
6289
|
+
if (!React29__default.default.isValidElement(node)) return null;
|
|
5780
6290
|
const el = node;
|
|
5781
6291
|
if (el.type === MegaMenuSection) {
|
|
5782
6292
|
const { title, children } = el.props;
|
|
@@ -5795,8 +6305,8 @@ function MegaMenuMobile({
|
|
|
5795
6305
|
children,
|
|
5796
6306
|
label
|
|
5797
6307
|
}) {
|
|
5798
|
-
const [open, setOpen] =
|
|
5799
|
-
const [expanded, setExpanded] =
|
|
6308
|
+
const [open, setOpen] = React29.useState(false);
|
|
6309
|
+
const [expanded, setExpanded] = React29.useState(null);
|
|
5800
6310
|
const items = elementsOfType(children, MegaMenuItem);
|
|
5801
6311
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden w-full", children: [
|
|
5802
6312
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -5869,17 +6379,17 @@ function AppShell({
|
|
|
5869
6379
|
children,
|
|
5870
6380
|
className = ""
|
|
5871
6381
|
}) {
|
|
5872
|
-
const [expanded, setExpanded] =
|
|
5873
|
-
const [isMobile, setIsMobile] =
|
|
5874
|
-
const [mobileOpen, setMobileOpen] =
|
|
5875
|
-
|
|
6382
|
+
const [expanded, setExpanded] = React29.useState(sidebarDefaultExpanded);
|
|
6383
|
+
const [isMobile, setIsMobile] = React29.useState(false);
|
|
6384
|
+
const [mobileOpen, setMobileOpen] = React29.useState(false);
|
|
6385
|
+
React29.useEffect(() => {
|
|
5876
6386
|
const mq = window.matchMedia("(max-width: 767px)");
|
|
5877
6387
|
const update = (e) => setIsMobile(e.matches);
|
|
5878
6388
|
update(mq);
|
|
5879
6389
|
mq.addEventListener("change", update);
|
|
5880
6390
|
return () => mq.removeEventListener("change", update);
|
|
5881
6391
|
}, []);
|
|
5882
|
-
|
|
6392
|
+
React29.useEffect(() => {
|
|
5883
6393
|
if (!isMobile) setMobileOpen(false);
|
|
5884
6394
|
}, [isMobile]);
|
|
5885
6395
|
const hasSidebar = sidebarSections.length > 0;
|
|
@@ -5986,7 +6496,7 @@ function tokenValid(token) {
|
|
|
5986
6496
|
return exp * 1e3 > Date.now();
|
|
5987
6497
|
}
|
|
5988
6498
|
var has = (have, need, all) => all ? need.every((n) => have?.includes(n)) : need.some((n) => have?.includes(n));
|
|
5989
|
-
var
|
|
6499
|
+
var Spinner3 = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", className: "h-6 w-6 animate-spin text-accent", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.755 10.059a7.5 7.5 0 0112.548-3.364l1.903 1.903h-3.183a.75.75 0 100 1.5h4.992a.75.75 0 00.75-.75V4.356a.75.75 0 00-1.5 0v3.18l-1.9-1.9A9 9 0 003.306 9.67a.75.75 0 101.45.388zm15.408 3.352a.75.75 0 00-.919.53 7.5 7.5 0 01-12.548 3.364l-1.902-1.903h3.183a.75.75 0 000-1.5H2.984a.75.75 0 00-.75.75v4.992a.75.75 0 001.5 0v-3.18l1.9 1.9a9 9 0 0015.059-4.035.75.75 0 00-.53-.918z" }) });
|
|
5990
6500
|
function SecureLayout({
|
|
5991
6501
|
children,
|
|
5992
6502
|
isAuthenticated,
|
|
@@ -6006,7 +6516,7 @@ function SecureLayout({
|
|
|
6006
6516
|
className = ""
|
|
6007
6517
|
}) {
|
|
6008
6518
|
const reduced = framerMotion.useReducedMotion();
|
|
6009
|
-
const cbs =
|
|
6519
|
+
const cbs = React29.useRef({ canAccess, onGranted, onDeny });
|
|
6010
6520
|
cbs.current = { canAccess, onGranted, onDeny };
|
|
6011
6521
|
const rolesKey = JSON.stringify(roles);
|
|
6012
6522
|
const requiredRolesKey = JSON.stringify(requiredRoles);
|
|
@@ -6021,10 +6531,10 @@ function SecureLayout({
|
|
|
6021
6531
|
if (requiredPermissions?.length && !has(permissions, requiredPermissions, requireAllPermissions)) return false;
|
|
6022
6532
|
return true;
|
|
6023
6533
|
};
|
|
6024
|
-
const [state, setState] =
|
|
6534
|
+
const [state, setState] = React29.useState(
|
|
6025
6535
|
() => !passesSync() ? "denied" : canAccess ? "checking" : "granted"
|
|
6026
6536
|
);
|
|
6027
|
-
|
|
6537
|
+
React29.useEffect(() => {
|
|
6028
6538
|
let cancelled = false;
|
|
6029
6539
|
const { canAccess: check, onGranted: granted, onDeny: deny } = cbs.current;
|
|
6030
6540
|
const finish = (ok) => {
|
|
@@ -6062,7 +6572,7 @@ function SecureLayout({
|
|
|
6062
6572
|
]);
|
|
6063
6573
|
if (state === "checking") {
|
|
6064
6574
|
if (loadingFallback === null) return null;
|
|
6065
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["flex min-h-[8rem] items-center justify-center", className].filter(Boolean).join(" "), children: loadingFallback !== void 0 ? loadingFallback : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6575
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["flex min-h-[8rem] items-center justify-center", className].filter(Boolean).join(" "), children: loadingFallback !== void 0 ? loadingFallback : /* @__PURE__ */ jsxRuntime.jsx(Spinner3, {}) });
|
|
6066
6576
|
}
|
|
6067
6577
|
if (state === "denied") {
|
|
6068
6578
|
if (fallback === null) return null;
|
|
@@ -6185,10 +6695,10 @@ function ThemeProvider({
|
|
|
6185
6695
|
className = "",
|
|
6186
6696
|
style
|
|
6187
6697
|
}) {
|
|
6188
|
-
const id =
|
|
6698
|
+
const id = React29__default.default.useId().replace(/:/g, "");
|
|
6189
6699
|
const scopeClass = `geo-th-${id}`;
|
|
6190
|
-
const divRef =
|
|
6191
|
-
|
|
6700
|
+
const divRef = React29.useRef(null);
|
|
6701
|
+
React29.useEffect(() => {
|
|
6192
6702
|
const el = divRef.current;
|
|
6193
6703
|
if (!el) return;
|
|
6194
6704
|
if (colorScheme === "auto") return;
|
|
@@ -6203,8 +6713,8 @@ function ThemeProvider({
|
|
|
6203
6713
|
}
|
|
6204
6714
|
el.classList.toggle("dark", colorScheme === "dark");
|
|
6205
6715
|
}, [colorScheme]);
|
|
6206
|
-
const lightVars =
|
|
6207
|
-
const darkVarStr =
|
|
6716
|
+
const lightVars = React29.useMemo(() => toCssVars(theme), [theme]);
|
|
6717
|
+
const darkVarStr = React29.useMemo(() => {
|
|
6208
6718
|
if (!darkTheme) return "";
|
|
6209
6719
|
const dvars = toCssVars(darkTheme);
|
|
6210
6720
|
if (!Object.keys(dvars).length) return "";
|
|
@@ -6246,7 +6756,7 @@ function NumberInput({
|
|
|
6246
6756
|
readOnly = false,
|
|
6247
6757
|
precision
|
|
6248
6758
|
}) {
|
|
6249
|
-
const errorId =
|
|
6759
|
+
const errorId = React29.useId();
|
|
6250
6760
|
const hasError = errorMessage != null;
|
|
6251
6761
|
const inferredPrecision = precision ?? (Number.isInteger(step) ? 0 : String(step).split(".")[1]?.length ?? 0);
|
|
6252
6762
|
const round = (n) => {
|
|
@@ -6377,8 +6887,8 @@ function Password({
|
|
|
6377
6887
|
showIcon,
|
|
6378
6888
|
hideIcon
|
|
6379
6889
|
}) {
|
|
6380
|
-
const [visible, setVisible] =
|
|
6381
|
-
const errorId =
|
|
6890
|
+
const [visible, setVisible] = React29.useState(false);
|
|
6891
|
+
const errorId = React29.useId();
|
|
6382
6892
|
const hasError = errorMessage != null;
|
|
6383
6893
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6384
6894
|
Field,
|
|
@@ -6451,7 +6961,7 @@ function Checkbox({
|
|
|
6451
6961
|
}) {
|
|
6452
6962
|
const isChecked = checked ?? value ?? false;
|
|
6453
6963
|
const labelFirst = labelPosition === "left";
|
|
6454
|
-
const errorId =
|
|
6964
|
+
const errorId = React29.useId();
|
|
6455
6965
|
const hasError = errorMessage != null;
|
|
6456
6966
|
const box = /* @__PURE__ */ jsxRuntime.jsx(
|
|
6457
6967
|
CheckboxPrimitive__namespace.Root,
|
|
@@ -6559,8 +7069,8 @@ function RadioGroup({
|
|
|
6559
7069
|
className,
|
|
6560
7070
|
errorMessage
|
|
6561
7071
|
}) {
|
|
6562
|
-
const errorId =
|
|
6563
|
-
const groupId =
|
|
7072
|
+
const errorId = React29.useId();
|
|
7073
|
+
const groupId = React29.useId();
|
|
6564
7074
|
const hasError = errorMessage != null;
|
|
6565
7075
|
const labelFirst = labelPosition === "left";
|
|
6566
7076
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6660,11 +7170,11 @@ function Switch({
|
|
|
6660
7170
|
disabled,
|
|
6661
7171
|
errorMessage
|
|
6662
7172
|
}) {
|
|
6663
|
-
const id =
|
|
6664
|
-
const errorId =
|
|
7173
|
+
const id = React29.useId();
|
|
7174
|
+
const errorId = React29.useId();
|
|
6665
7175
|
const hasError = errorMessage != null;
|
|
6666
7176
|
const isControlled = checked !== void 0;
|
|
6667
|
-
const [internal, setInternal] =
|
|
7177
|
+
const [internal, setInternal] = React29.useState(defaultChecked);
|
|
6668
7178
|
const isOn = isControlled ? checked : internal;
|
|
6669
7179
|
const handle = (c) => {
|
|
6670
7180
|
if (!isControlled) setInternal(c);
|
|
@@ -6737,19 +7247,19 @@ function AutoComplete({
|
|
|
6737
7247
|
required,
|
|
6738
7248
|
htmlFor
|
|
6739
7249
|
}) {
|
|
6740
|
-
const errorId =
|
|
7250
|
+
const errorId = React29.useId();
|
|
6741
7251
|
const hasError = errorMessage != null;
|
|
6742
|
-
const [term, setTerm] =
|
|
6743
|
-
const [open, setOpen] =
|
|
6744
|
-
const [asyncItems, setAsyncItems] =
|
|
6745
|
-
const [loading, setLoading] =
|
|
7252
|
+
const [term, setTerm] = React29.useState("");
|
|
7253
|
+
const [open, setOpen] = React29.useState(false);
|
|
7254
|
+
const [asyncItems, setAsyncItems] = React29.useState([]);
|
|
7255
|
+
const [loading, setLoading] = React29.useState(false);
|
|
6746
7256
|
const isAsync = typeof onSearch === "function";
|
|
6747
|
-
const debounceRef =
|
|
6748
|
-
const requestIdRef =
|
|
7257
|
+
const debounceRef = React29.useRef(null);
|
|
7258
|
+
const requestIdRef = React29.useRef(0);
|
|
6749
7259
|
const staticFiltered = isAsync || !items ? [] : term.trim() ? items.filter(
|
|
6750
7260
|
({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
|
|
6751
7261
|
) : [];
|
|
6752
|
-
|
|
7262
|
+
React29.useEffect(() => {
|
|
6753
7263
|
if (!isAsync) return;
|
|
6754
7264
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
6755
7265
|
if (!term.trim()) {
|
|
@@ -6905,15 +7415,15 @@ function TreeSelect({
|
|
|
6905
7415
|
defaultExpandedKeys = [],
|
|
6906
7416
|
size = "md"
|
|
6907
7417
|
}) {
|
|
6908
|
-
const errorId =
|
|
7418
|
+
const errorId = React29.useId();
|
|
6909
7419
|
const hasError = errorMessage != null;
|
|
6910
|
-
const [open, setOpen] =
|
|
6911
|
-
const [expanded, setExpanded] =
|
|
6912
|
-
const [activeIndex, setActiveIndex] =
|
|
6913
|
-
const listRef =
|
|
6914
|
-
const visible =
|
|
6915
|
-
const didSyncOnOpenRef =
|
|
6916
|
-
|
|
7420
|
+
const [open, setOpen] = React29.useState(false);
|
|
7421
|
+
const [expanded, setExpanded] = React29.useState(() => new Set(defaultExpandedKeys));
|
|
7422
|
+
const [activeIndex, setActiveIndex] = React29.useState(0);
|
|
7423
|
+
const listRef = React29.useRef(null);
|
|
7424
|
+
const visible = React29.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
|
|
7425
|
+
const didSyncOnOpenRef = React29.useRef(false);
|
|
7426
|
+
React29.useEffect(() => {
|
|
6917
7427
|
if (!open) {
|
|
6918
7428
|
didSyncOnOpenRef.current = false;
|
|
6919
7429
|
return;
|
|
@@ -6923,7 +7433,7 @@ function TreeSelect({
|
|
|
6923
7433
|
setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
|
|
6924
7434
|
didSyncOnOpenRef.current = true;
|
|
6925
7435
|
}, [open, value]);
|
|
6926
|
-
const selectedNode =
|
|
7436
|
+
const selectedNode = React29.useMemo(
|
|
6927
7437
|
() => value != null ? findNodeByKey(items, value) : null,
|
|
6928
7438
|
[items, value]
|
|
6929
7439
|
);
|
|
@@ -7154,11 +7664,11 @@ function FileInput({
|
|
|
7154
7664
|
required,
|
|
7155
7665
|
icon
|
|
7156
7666
|
}) {
|
|
7157
|
-
const inputRef =
|
|
7158
|
-
const errorId =
|
|
7159
|
-
const [files, setFiles] =
|
|
7160
|
-
const [dragging, setDragging] =
|
|
7161
|
-
const [sizeError, setSizeError] =
|
|
7667
|
+
const inputRef = React29.useRef(null);
|
|
7668
|
+
const errorId = React29.useId();
|
|
7669
|
+
const [files, setFiles] = React29.useState([]);
|
|
7670
|
+
const [dragging, setDragging] = React29.useState(false);
|
|
7671
|
+
const [sizeError, setSizeError] = React29.useState(null);
|
|
7162
7672
|
const effectiveError = errorMessage ?? sizeError ?? void 0;
|
|
7163
7673
|
const openPicker = () => {
|
|
7164
7674
|
if (!disabled) inputRef.current?.click();
|
|
@@ -7296,15 +7806,15 @@ var WEEKDAY_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
|
7296
7806
|
function isSameDay(a, b) {
|
|
7297
7807
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
7298
7808
|
}
|
|
7299
|
-
function
|
|
7809
|
+
function startOfMonth2(d) {
|
|
7300
7810
|
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
7301
7811
|
}
|
|
7302
|
-
function
|
|
7812
|
+
function addDays2(d, n) {
|
|
7303
7813
|
const c = new Date(d);
|
|
7304
7814
|
c.setDate(c.getDate() + n);
|
|
7305
7815
|
return c;
|
|
7306
7816
|
}
|
|
7307
|
-
function
|
|
7817
|
+
function addMonths3(d, n) {
|
|
7308
7818
|
const c = new Date(d);
|
|
7309
7819
|
c.setMonth(c.getMonth() + n);
|
|
7310
7820
|
return c;
|
|
@@ -7316,12 +7826,12 @@ function defaultFormat3(d) {
|
|
|
7316
7826
|
return `${y}-${m}-${day}`;
|
|
7317
7827
|
}
|
|
7318
7828
|
function buildGrid2(viewMonth, weekStartsOn) {
|
|
7319
|
-
const first =
|
|
7829
|
+
const first = startOfMonth2(viewMonth);
|
|
7320
7830
|
const startOffset = (first.getDay() - weekStartsOn + 7) % 7;
|
|
7321
|
-
const gridStart =
|
|
7831
|
+
const gridStart = addDays2(first, -startOffset);
|
|
7322
7832
|
const cells = [];
|
|
7323
7833
|
for (let i = 0; i < 42; i++) {
|
|
7324
|
-
const d =
|
|
7834
|
+
const d = addDays2(gridStart, i);
|
|
7325
7835
|
cells.push({ date: d, outside: d.getMonth() !== viewMonth.getMonth() });
|
|
7326
7836
|
}
|
|
7327
7837
|
const rows = [];
|
|
@@ -7349,30 +7859,30 @@ function DatePicker({
|
|
|
7349
7859
|
size = "md",
|
|
7350
7860
|
className = ""
|
|
7351
7861
|
}) {
|
|
7352
|
-
const errorId =
|
|
7862
|
+
const errorId = React29.useId();
|
|
7353
7863
|
const hasError = errorMessage != null;
|
|
7354
|
-
const [open, setOpen] =
|
|
7355
|
-
const [viewMonth, setViewMonth] =
|
|
7356
|
-
const [focusDate, setFocusDate] =
|
|
7357
|
-
const [view, setView] =
|
|
7358
|
-
const gridRef =
|
|
7359
|
-
|
|
7864
|
+
const [open, setOpen] = React29.useState(false);
|
|
7865
|
+
const [viewMonth, setViewMonth] = React29.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
|
|
7866
|
+
const [focusDate, setFocusDate] = React29.useState(() => value ?? /* @__PURE__ */ new Date());
|
|
7867
|
+
const [view, setView] = React29.useState("days");
|
|
7868
|
+
const gridRef = React29.useRef(null);
|
|
7869
|
+
React29.useEffect(() => {
|
|
7360
7870
|
if (!open) return;
|
|
7361
7871
|
const target = value ?? /* @__PURE__ */ new Date();
|
|
7362
|
-
setViewMonth(
|
|
7872
|
+
setViewMonth(startOfMonth2(target));
|
|
7363
7873
|
setFocusDate(target);
|
|
7364
7874
|
setView("days");
|
|
7365
7875
|
}, [open, value]);
|
|
7366
|
-
|
|
7876
|
+
React29.useEffect(() => {
|
|
7367
7877
|
if (!open) return;
|
|
7368
7878
|
const cell = gridRef.current?.querySelector(`[data-day="${defaultFormat3(focusDate)}"]`);
|
|
7369
7879
|
cell?.focus();
|
|
7370
7880
|
}, [open, focusDate]);
|
|
7371
|
-
const weekdays =
|
|
7881
|
+
const weekdays = React29.useMemo(() => {
|
|
7372
7882
|
const ordered = WEEKDAY_SHORT.slice(weekStartsOn).concat(WEEKDAY_SHORT.slice(0, weekStartsOn));
|
|
7373
7883
|
return ordered;
|
|
7374
7884
|
}, [weekStartsOn]);
|
|
7375
|
-
const grid =
|
|
7885
|
+
const grid = React29.useMemo(() => buildGrid2(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
|
|
7376
7886
|
const isDisabled = (d) => {
|
|
7377
7887
|
if (min && d < min) return true;
|
|
7378
7888
|
if (max && d > max) return true;
|
|
@@ -7385,9 +7895,9 @@ function DatePicker({
|
|
|
7385
7895
|
};
|
|
7386
7896
|
const onKey = (e) => {
|
|
7387
7897
|
const next = (delta) => {
|
|
7388
|
-
const nd =
|
|
7898
|
+
const nd = addDays2(focusDate, delta);
|
|
7389
7899
|
setFocusDate(nd);
|
|
7390
|
-
if (nd.getMonth() !== viewMonth.getMonth()) setViewMonth(
|
|
7900
|
+
if (nd.getMonth() !== viewMonth.getMonth()) setViewMonth(startOfMonth2(nd));
|
|
7391
7901
|
};
|
|
7392
7902
|
if (e.key === "ArrowLeft") {
|
|
7393
7903
|
e.preventDefault();
|
|
@@ -7403,22 +7913,22 @@ function DatePicker({
|
|
|
7403
7913
|
next(7);
|
|
7404
7914
|
} else if (e.key === "PageUp") {
|
|
7405
7915
|
e.preventDefault();
|
|
7406
|
-
const nm =
|
|
7916
|
+
const nm = addMonths3(viewMonth, -1);
|
|
7407
7917
|
setViewMonth(nm);
|
|
7408
|
-
setFocusDate((d) =>
|
|
7918
|
+
setFocusDate((d) => addMonths3(d, -1));
|
|
7409
7919
|
} else if (e.key === "PageDown") {
|
|
7410
7920
|
e.preventDefault();
|
|
7411
|
-
const nm =
|
|
7921
|
+
const nm = addMonths3(viewMonth, 1);
|
|
7412
7922
|
setViewMonth(nm);
|
|
7413
|
-
setFocusDate((d) =>
|
|
7923
|
+
setFocusDate((d) => addMonths3(d, 1));
|
|
7414
7924
|
} else if (e.key === "Home") {
|
|
7415
7925
|
e.preventDefault();
|
|
7416
7926
|
const dow = (focusDate.getDay() - weekStartsOn + 7) % 7;
|
|
7417
|
-
setFocusDate(
|
|
7927
|
+
setFocusDate(addDays2(focusDate, -dow));
|
|
7418
7928
|
} else if (e.key === "End") {
|
|
7419
7929
|
e.preventDefault();
|
|
7420
7930
|
const dow = (focusDate.getDay() - weekStartsOn + 7) % 7;
|
|
7421
|
-
setFocusDate(
|
|
7931
|
+
setFocusDate(addDays2(focusDate, 6 - dow));
|
|
7422
7932
|
} else if (e.key === "Enter" || e.key === " ") {
|
|
7423
7933
|
e.preventDefault();
|
|
7424
7934
|
selectDate(focusDate);
|
|
@@ -7475,7 +7985,7 @@ function DatePicker({
|
|
|
7475
7985
|
{
|
|
7476
7986
|
type: "button",
|
|
7477
7987
|
onClick: () => {
|
|
7478
|
-
if (view === "days") setViewMonth(
|
|
7988
|
+
if (view === "days") setViewMonth(addMonths3(viewMonth, -1));
|
|
7479
7989
|
else if (view === "months") setViewMonth(new Date(viewMonth.getFullYear() - 1, viewMonth.getMonth(), 1));
|
|
7480
7990
|
else setViewMonth(new Date(viewMonth.getFullYear() - 10, viewMonth.getMonth(), 1));
|
|
7481
7991
|
},
|
|
@@ -7510,7 +8020,7 @@ function DatePicker({
|
|
|
7510
8020
|
{
|
|
7511
8021
|
type: "button",
|
|
7512
8022
|
onClick: () => {
|
|
7513
|
-
if (view === "days") setViewMonth(
|
|
8023
|
+
if (view === "days") setViewMonth(addMonths3(viewMonth, 1));
|
|
7514
8024
|
else if (view === "months") setViewMonth(new Date(viewMonth.getFullYear() + 1, viewMonth.getMonth(), 1));
|
|
7515
8025
|
else setViewMonth(new Date(viewMonth.getFullYear() + 10, viewMonth.getMonth(), 1));
|
|
7516
8026
|
},
|
|
@@ -7662,10 +8172,10 @@ function TextArea({
|
|
|
7662
8172
|
style,
|
|
7663
8173
|
inputStyle
|
|
7664
8174
|
}) {
|
|
7665
|
-
const errorId =
|
|
8175
|
+
const errorId = React29.useId();
|
|
7666
8176
|
const hasError = errorMessage != null;
|
|
7667
|
-
const ref =
|
|
7668
|
-
|
|
8177
|
+
const ref = React29.useRef(null);
|
|
8178
|
+
React29.useLayoutEffect(() => {
|
|
7669
8179
|
if (!autoGrow) return;
|
|
7670
8180
|
const el = ref.current;
|
|
7671
8181
|
if (!el) return;
|
|
@@ -7712,102 +8222,6 @@ function TextArea({
|
|
|
7712
8222
|
}
|
|
7713
8223
|
);
|
|
7714
8224
|
}
|
|
7715
|
-
var SIZE5 = {
|
|
7716
|
-
sm: { h: "h-control-sm", text: "text-xs", pad: "px-2.5" },
|
|
7717
|
-
md: { h: "h-control-md", text: "text-sm", pad: "px-3.5" },
|
|
7718
|
-
lg: { h: "h-control-lg", text: "text-sm", pad: "px-4" }
|
|
7719
|
-
};
|
|
7720
|
-
function SegmentedControl({
|
|
7721
|
-
options,
|
|
7722
|
-
value,
|
|
7723
|
-
defaultValue,
|
|
7724
|
-
onChange,
|
|
7725
|
-
size = "md",
|
|
7726
|
-
fullWidth = false,
|
|
7727
|
-
disabled,
|
|
7728
|
-
label,
|
|
7729
|
-
layout = "vertical",
|
|
7730
|
-
helperText,
|
|
7731
|
-
className,
|
|
7732
|
-
name,
|
|
7733
|
-
required,
|
|
7734
|
-
errorMessage,
|
|
7735
|
-
"aria-label": ariaLabel
|
|
7736
|
-
}) {
|
|
7737
|
-
const sz = SIZE5[size];
|
|
7738
|
-
const groupId = React27.useId();
|
|
7739
|
-
const errorId = React27.useId();
|
|
7740
|
-
const hasError = errorMessage != null;
|
|
7741
|
-
const isControlled = value !== void 0;
|
|
7742
|
-
const [internal, setInternal] = React27.useState(defaultValue);
|
|
7743
|
-
const current = isControlled ? value : internal;
|
|
7744
|
-
const handle = (v) => {
|
|
7745
|
-
if (!v) return;
|
|
7746
|
-
if (!isControlled) setInternal(v);
|
|
7747
|
-
onChange?.(v);
|
|
7748
|
-
};
|
|
7749
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7750
|
-
Field,
|
|
7751
|
-
{
|
|
7752
|
-
className,
|
|
7753
|
-
label,
|
|
7754
|
-
htmlFor: groupId,
|
|
7755
|
-
errorId,
|
|
7756
|
-
errorMessage,
|
|
7757
|
-
layout,
|
|
7758
|
-
required,
|
|
7759
|
-
helperText,
|
|
7760
|
-
children: [
|
|
7761
|
-
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: current ?? "" }),
|
|
7762
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7763
|
-
ToggleGroup__namespace.Root,
|
|
7764
|
-
{
|
|
7765
|
-
id: groupId,
|
|
7766
|
-
type: "single",
|
|
7767
|
-
value: current,
|
|
7768
|
-
onValueChange: handle,
|
|
7769
|
-
disabled,
|
|
7770
|
-
"aria-label": ariaLabel ?? (typeof label === "string" ? label : void 0),
|
|
7771
|
-
"aria-invalid": hasError || void 0,
|
|
7772
|
-
"aria-describedby": hasError ? errorId : void 0,
|
|
7773
|
-
className: [
|
|
7774
|
-
"inline-flex items-center gap-1 rounded-lg border bg-surface-raised p-1",
|
|
7775
|
-
hasError ? "border-status-error" : "border-border",
|
|
7776
|
-
sz.h,
|
|
7777
|
-
fullWidth ? "flex w-full" : "w-fit",
|
|
7778
|
-
disabled ? "opacity-60 cursor-not-allowed" : ""
|
|
7779
|
-
].filter(Boolean).join(" "),
|
|
7780
|
-
children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7781
|
-
ToggleGroup__namespace.Item,
|
|
7782
|
-
{
|
|
7783
|
-
value: opt.value,
|
|
7784
|
-
disabled: opt.disabled,
|
|
7785
|
-
className: [
|
|
7786
|
-
"inline-flex items-center justify-center gap-1.5 rounded-md select-none whitespace-nowrap",
|
|
7787
|
-
"transition-colors duration-150 h-full",
|
|
7788
|
-
sz.text,
|
|
7789
|
-
sz.pad,
|
|
7790
|
-
fullWidth ? "flex-1" : "",
|
|
7791
|
-
// Resting: muted text, transparent. Hover lifts the text.
|
|
7792
|
-
"text-foreground-secondary hover:text-foreground",
|
|
7793
|
-
// Active: surface-white pill + accent text + subtle shadow.
|
|
7794
|
-
"data-[state=on]:bg-surface data-[state=on]:text-accent data-[state=on]:shadow-sm",
|
|
7795
|
-
"focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
|
|
7796
|
-
"disabled:opacity-40 disabled:cursor-not-allowed"
|
|
7797
|
-
].filter(Boolean).join(" "),
|
|
7798
|
-
children: [
|
|
7799
|
-
opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: opt.icon }),
|
|
7800
|
-
opt.label
|
|
7801
|
-
]
|
|
7802
|
-
},
|
|
7803
|
-
opt.value
|
|
7804
|
-
))
|
|
7805
|
-
}
|
|
7806
|
-
)
|
|
7807
|
-
]
|
|
7808
|
-
}
|
|
7809
|
-
);
|
|
7810
|
-
}
|
|
7811
8225
|
var TRACK_H = { sm: "h-1", md: "h-1.5", lg: "h-2" };
|
|
7812
8226
|
var THUMB = { sm: "h-3.5 w-3.5", md: "h-4 w-4", lg: "h-5 w-5" };
|
|
7813
8227
|
var toArray = (v) => v == null ? void 0 : Array.isArray(v) ? v : [v];
|
|
@@ -7833,14 +8247,14 @@ function Slider({
|
|
|
7833
8247
|
name,
|
|
7834
8248
|
htmlFor
|
|
7835
8249
|
}) {
|
|
7836
|
-
const errorId =
|
|
8250
|
+
const errorId = React29.useId();
|
|
7837
8251
|
const hasError = errorMessage != null;
|
|
7838
8252
|
const isRange = Array.isArray(value ?? defaultValue);
|
|
7839
|
-
const [internal, setInternal] =
|
|
8253
|
+
const [internal, setInternal] = React29.useState(
|
|
7840
8254
|
() => toArray(value) ?? toArray(defaultValue) ?? [min]
|
|
7841
8255
|
);
|
|
7842
8256
|
const current = toArray(value) ?? internal;
|
|
7843
|
-
const [dragging, setDragging] =
|
|
8257
|
+
const [dragging, setDragging] = React29.useState(false);
|
|
7844
8258
|
const emit = (arr) => {
|
|
7845
8259
|
setInternal(arr);
|
|
7846
8260
|
const next = isRange ? [arr[0], arr[1]] : arr[0];
|
|
@@ -7935,11 +8349,11 @@ function TagsInput({
|
|
|
7935
8349
|
validate,
|
|
7936
8350
|
separators = ["Enter", ","]
|
|
7937
8351
|
}) {
|
|
7938
|
-
const errorId =
|
|
7939
|
-
const inputRef =
|
|
7940
|
-
const [internal, setInternal] =
|
|
7941
|
-
const [draft, setDraft] =
|
|
7942
|
-
const [localError, setLocalError] =
|
|
8352
|
+
const errorId = React29.useId();
|
|
8353
|
+
const inputRef = React29.useRef(null);
|
|
8354
|
+
const [internal, setInternal] = React29.useState(defaultValue ?? []);
|
|
8355
|
+
const [draft, setDraft] = React29.useState("");
|
|
8356
|
+
const [localError, setLocalError] = React29.useState(null);
|
|
7943
8357
|
const tags = value ?? internal;
|
|
7944
8358
|
const hasError = errorMessage != null || localError != null;
|
|
7945
8359
|
const errorText = errorMessage ?? localError ?? void 0;
|
|
@@ -8070,9 +8484,9 @@ function OtpInput({
|
|
|
8070
8484
|
className,
|
|
8071
8485
|
groupAfter
|
|
8072
8486
|
}) {
|
|
8073
|
-
const errorId =
|
|
8487
|
+
const errorId = React29.useId();
|
|
8074
8488
|
const hasError = errorMessage != null;
|
|
8075
|
-
const refs =
|
|
8489
|
+
const refs = React29.useRef([]);
|
|
8076
8490
|
const chars = Array.from({ length }, (_, i) => value[i] ?? "");
|
|
8077
8491
|
const pattern = mode === "numeric" ? /[0-9]/ : /[a-zA-Z0-9]/;
|
|
8078
8492
|
const emit = (next) => {
|
|
@@ -8121,7 +8535,7 @@ function OtpInput({
|
|
|
8121
8535
|
emit(valid.join(""));
|
|
8122
8536
|
focusBox(valid.length);
|
|
8123
8537
|
};
|
|
8124
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8538
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
|
|
8125
8539
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8126
8540
|
"input",
|
|
8127
8541
|
{
|
|
@@ -8179,9 +8593,9 @@ function Rating({
|
|
|
8179
8593
|
className,
|
|
8180
8594
|
required
|
|
8181
8595
|
}) {
|
|
8182
|
-
const errorId =
|
|
8183
|
-
const [internal, setInternal] =
|
|
8184
|
-
const [hover, setHover] =
|
|
8596
|
+
const errorId = React29.useId();
|
|
8597
|
+
const [internal, setInternal] = React29.useState(defaultValue);
|
|
8598
|
+
const [hover, setHover] = React29.useState(null);
|
|
8185
8599
|
const current = value ?? internal;
|
|
8186
8600
|
const display2 = hover ?? current;
|
|
8187
8601
|
const interactive = !readOnly && !disabled;
|
|
@@ -8304,9 +8718,9 @@ function TimePicker({
|
|
|
8304
8718
|
required,
|
|
8305
8719
|
style
|
|
8306
8720
|
}) {
|
|
8307
|
-
const errorId =
|
|
8721
|
+
const errorId = React29.useId();
|
|
8308
8722
|
const hasError = errorMessage != null;
|
|
8309
|
-
const [open, setOpen] =
|
|
8723
|
+
const [open, setOpen] = React29.useState(false);
|
|
8310
8724
|
const parsed = parse(value) ?? { h: 0, m: 0, s: 0 };
|
|
8311
8725
|
const update = (next) => {
|
|
8312
8726
|
const merged = { ...parsed, ...next };
|
|
@@ -8391,22 +8805,22 @@ function TimePicker({
|
|
|
8391
8805
|
}
|
|
8392
8806
|
var MONTH_NAMES2 = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
8393
8807
|
var WEEKDAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
8394
|
-
var
|
|
8395
|
-
var
|
|
8396
|
-
var
|
|
8808
|
+
var startOfMonth3 = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
|
|
8809
|
+
var addMonths4 = (d, n) => new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
8810
|
+
var addDays3 = (d, n) => {
|
|
8397
8811
|
const c = new Date(d);
|
|
8398
8812
|
c.setDate(c.getDate() + n);
|
|
8399
8813
|
return c;
|
|
8400
8814
|
};
|
|
8401
8815
|
var isSameDay2 = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
8402
|
-
var
|
|
8816
|
+
var startOfDay3 = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
8403
8817
|
var defaultFmt = (d) => `${d.getFullYear()}-${`${d.getMonth() + 1}`.padStart(2, "0")}-${`${d.getDate()}`.padStart(2, "0")}`;
|
|
8404
8818
|
function buildGrid3(viewMonth, weekStartsOn) {
|
|
8405
|
-
const first =
|
|
8819
|
+
const first = startOfMonth3(viewMonth);
|
|
8406
8820
|
const offset = (first.getDay() - weekStartsOn + 7) % 7;
|
|
8407
|
-
const gridStart =
|
|
8821
|
+
const gridStart = addDays3(first, -offset);
|
|
8408
8822
|
return Array.from({ length: 42 }, (_, i) => {
|
|
8409
|
-
const d =
|
|
8823
|
+
const d = addDays3(gridStart, i);
|
|
8410
8824
|
return { date: d, outside: d.getMonth() !== viewMonth.getMonth() };
|
|
8411
8825
|
});
|
|
8412
8826
|
}
|
|
@@ -8430,23 +8844,23 @@ function DateRangePicker({
|
|
|
8430
8844
|
required,
|
|
8431
8845
|
style
|
|
8432
8846
|
}) {
|
|
8433
|
-
const errorId =
|
|
8847
|
+
const errorId = React29.useId();
|
|
8434
8848
|
const hasError = errorMessage != null;
|
|
8435
|
-
const [open, setOpen] =
|
|
8436
|
-
const [leftMonth, setLeftMonth] =
|
|
8437
|
-
const [pendingStart, setPendingStart] =
|
|
8438
|
-
const [hoverDate, setHoverDate] =
|
|
8439
|
-
const weekdays =
|
|
8849
|
+
const [open, setOpen] = React29.useState(false);
|
|
8850
|
+
const [leftMonth, setLeftMonth] = React29.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
|
|
8851
|
+
const [pendingStart, setPendingStart] = React29.useState(null);
|
|
8852
|
+
const [hoverDate, setHoverDate] = React29.useState(null);
|
|
8853
|
+
const weekdays = React29.useMemo(
|
|
8440
8854
|
() => WEEKDAY.slice(weekStartsOn).concat(WEEKDAY.slice(0, weekStartsOn)),
|
|
8441
8855
|
[weekStartsOn]
|
|
8442
8856
|
);
|
|
8443
|
-
const isDisabled = (d) => min && d <
|
|
8857
|
+
const isDisabled = (d) => min && d < startOfDay3(min) || max && d > startOfDay3(max);
|
|
8444
8858
|
const effective = pendingStart ? { start: pendingStart, end: hoverDate } : value;
|
|
8445
8859
|
const inRange = (d) => {
|
|
8446
8860
|
const { start, end } = effective;
|
|
8447
8861
|
if (!start || !end) return false;
|
|
8448
8862
|
const [a, b] = start <= end ? [start, end] : [end, start];
|
|
8449
|
-
return d >=
|
|
8863
|
+
return d >= startOfDay3(a) && d <= startOfDay3(b);
|
|
8450
8864
|
};
|
|
8451
8865
|
const onDayClick = (d) => {
|
|
8452
8866
|
if (isDisabled(d)) return;
|
|
@@ -8553,7 +8967,7 @@ function DateRangePicker({
|
|
|
8553
8967
|
"button",
|
|
8554
8968
|
{
|
|
8555
8969
|
type: "button",
|
|
8556
|
-
onClick: () => setLeftMonth(
|
|
8970
|
+
onClick: () => setLeftMonth(addMonths4(leftMonth, -1)),
|
|
8557
8971
|
"aria-label": "Previous month",
|
|
8558
8972
|
className: "absolute -top-1 left-0 w-7 h-7 inline-flex items-center justify-center rounded-md hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
8559
8973
|
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) })
|
|
@@ -8566,13 +8980,13 @@ function DateRangePicker({
|
|
|
8566
8980
|
"button",
|
|
8567
8981
|
{
|
|
8568
8982
|
type: "button",
|
|
8569
|
-
onClick: () => setLeftMonth(
|
|
8983
|
+
onClick: () => setLeftMonth(addMonths4(leftMonth, 1)),
|
|
8570
8984
|
"aria-label": "Next month",
|
|
8571
8985
|
className: "absolute -top-1 right-0 w-7 h-7 inline-flex items-center justify-center rounded-md hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
8572
8986
|
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
|
|
8573
8987
|
}
|
|
8574
8988
|
),
|
|
8575
|
-
renderMonth(
|
|
8989
|
+
renderMonth(addMonths4(leftMonth, 1))
|
|
8576
8990
|
] })
|
|
8577
8991
|
] })
|
|
8578
8992
|
]
|
|
@@ -8612,10 +9026,10 @@ function ColorPicker({
|
|
|
8612
9026
|
required,
|
|
8613
9027
|
placeholder = "Pick a colour\u2026"
|
|
8614
9028
|
}) {
|
|
8615
|
-
const errorId =
|
|
9029
|
+
const errorId = React29.useId();
|
|
8616
9030
|
const hasError = errorMessage != null;
|
|
8617
|
-
const [open, setOpen] =
|
|
8618
|
-
const [draft, setDraft] =
|
|
9031
|
+
const [open, setOpen] = React29.useState(false);
|
|
9032
|
+
const [draft, setDraft] = React29.useState(value);
|
|
8619
9033
|
const valid = HEX_RE.test(value);
|
|
8620
9034
|
const pick = (hex) => {
|
|
8621
9035
|
onChange?.(hex);
|
|
@@ -8776,6 +9190,7 @@ exports.Portal = Portal;
|
|
|
8776
9190
|
exports.RadioGroup = RadioGroup;
|
|
8777
9191
|
exports.Rating = Rating;
|
|
8778
9192
|
exports.ScalableContainer = ScalableContainer;
|
|
9193
|
+
exports.Scheduler = Scheduler;
|
|
8779
9194
|
exports.SearchInput = SearchInput_default;
|
|
8780
9195
|
exports.SecureLayout = SecureLayout;
|
|
8781
9196
|
exports.SegmentedControl = SegmentedControl;
|