gridsmith-ui 0.6.3 → 0.6.4
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/charts.js.map +1 -1
- package/dist/{chunk-R5QGJURZ.js → chunk-DDKCQVKO.js} +16 -8
- package/dist/chunk-DDKCQVKO.js.map +1 -0
- package/dist/{chunk-DPF6776I.js → chunk-EKQHHP72.js} +18 -15
- package/dist/chunk-EKQHHP72.js.map +1 -0
- package/dist/{chunk-TYU2LQGK.js → chunk-KXNJJKIV.js} +3 -3
- package/dist/{chunk-TYU2LQGK.js.map → chunk-KXNJJKIV.js.map} +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +2 -2
- package/dist/data-grid.js.map +1 -1
- package/dist/editor.js +7 -4
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +19 -5
- package/dist/index.js +332 -296
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +2 -2
- package/dist/resizable.js +1 -1
- package/dist/{use-breakpoint-Cn51IubK.d.ts → use-breakpoint-BfKzmkxx.d.ts} +3 -0
- package/dist/virtualized.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-DPF6776I.js.map +0 -1
- package/dist/chunk-R5QGJURZ.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Skeleton } from './chunk-QGBG72OB.js';
|
|
2
2
|
export { Skeleton } from './chunk-QGBG72OB.js';
|
|
3
|
-
import { Badge } from './chunk-
|
|
4
|
-
export { Badge } from './chunk-
|
|
5
|
-
import { useBreakpoint } from './chunk-
|
|
6
|
-
export { BreakpointWidthProvider, useBreakpoint } from './chunk-
|
|
7
|
-
import { Tooltip, useTextOverflow, usePosition, Slot } from './chunk-
|
|
8
|
-
export { Tooltip, useTextOverflow } from './chunk-
|
|
3
|
+
import { Badge } from './chunk-KXNJJKIV.js';
|
|
4
|
+
export { Badge } from './chunk-KXNJJKIV.js';
|
|
5
|
+
import { useBreakpoint } from './chunk-EKQHHP72.js';
|
|
6
|
+
export { BreakpointWidthProvider, useBreakpoint } from './chunk-EKQHHP72.js';
|
|
7
|
+
import { Tooltip, useTextOverflow, usePosition, Slot, useLatest } from './chunk-DDKCQVKO.js';
|
|
8
|
+
export { Tooltip, useTextOverflow } from './chunk-DDKCQVKO.js';
|
|
9
9
|
import { Icon } from './chunk-GX6O72IV.js';
|
|
10
|
-
import { cn, GLASS_SURFACE, ACTIVE_RING, GLASS_BACKDROP, GLASS_DROPDOWN, lockBodyScroll, unlockBodyScroll, GLASS_OVERLAY,
|
|
10
|
+
import { cn, GLASS_SURFACE, ACTIVE_RING, GLASS_BACKDROP, GLASS_DROPDOWN, FOCUS_RING, lockBodyScroll, unlockBodyScroll, GLASS_OVERLAY, HAS_FOCUS_RING, FOCUS_WITHIN_RING } from './chunk-TTZSZNJ6.js';
|
|
11
11
|
import { createContext, forwardRef, useContext, useState, useRef, useEffect, useCallback, useId, isValidElement, cloneElement, Fragment as Fragment$1, useMemo, Children, useLayoutEffect } from 'react';
|
|
12
12
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
13
13
|
import { createPortal } from 'react-dom';
|
|
@@ -149,11 +149,13 @@ function DropdownMenu({ trigger, items, align = "end", className, container }) {
|
|
|
149
149
|
if (!isDivider(item) && !item.disabled) acc.push(i);
|
|
150
150
|
return acc;
|
|
151
151
|
}, []);
|
|
152
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
153
|
+
if (open !== prevOpen) {
|
|
154
|
+
setPrevOpen(open);
|
|
155
|
+
if (!open) setFocusedIdx(-1);
|
|
156
|
+
}
|
|
152
157
|
useEffect(() => {
|
|
153
|
-
if (!open)
|
|
154
|
-
setFocusedIdx(-1);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
158
|
+
if (!open) return;
|
|
157
159
|
const onKeyDown = (e) => {
|
|
158
160
|
if (e.key === "Escape") setOpen(false);
|
|
159
161
|
};
|
|
@@ -534,13 +536,15 @@ function Dropdown({
|
|
|
534
536
|
}
|
|
535
537
|
setPos({ top, left, width });
|
|
536
538
|
}, []);
|
|
539
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
540
|
+
if (open !== prevOpen) {
|
|
541
|
+
setPrevOpen(open);
|
|
542
|
+
if (open) setSearch("");
|
|
543
|
+
else setPositioned(false);
|
|
544
|
+
}
|
|
537
545
|
useEffect(() => {
|
|
538
|
-
if (!open)
|
|
539
|
-
setPositioned(false);
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
546
|
+
if (!open) return;
|
|
542
547
|
updatePos();
|
|
543
|
-
setSearch("");
|
|
544
548
|
requestAnimationFrame(() => {
|
|
545
549
|
if (searchRef.current) {
|
|
546
550
|
searchRef.current.focus();
|
|
@@ -570,14 +574,14 @@ function Dropdown({
|
|
|
570
574
|
return () => document.removeEventListener("mousedown", handler);
|
|
571
575
|
}, [open]);
|
|
572
576
|
const typeahead = useRef({ buffer: "", at: 0 });
|
|
573
|
-
const optionButtons = () => Array.from(menuRef.current?.querySelectorAll('[role="option"]') ?? []);
|
|
574
|
-
const focusOption = (idx) => {
|
|
575
|
-
const els = optionButtons();
|
|
576
|
-
if (els.length === 0) return;
|
|
577
|
-
els[(idx % els.length + els.length) % els.length].focus();
|
|
578
|
-
};
|
|
579
577
|
useEffect(() => {
|
|
580
578
|
if (!open) return;
|
|
579
|
+
const optionButtons = () => Array.from(menuRef.current?.querySelectorAll('[role="option"]') ?? []);
|
|
580
|
+
const focusOption = (idx) => {
|
|
581
|
+
const els = optionButtons();
|
|
582
|
+
if (els.length === 0) return;
|
|
583
|
+
els[(idx % els.length + els.length) % els.length].focus();
|
|
584
|
+
};
|
|
581
585
|
const onKey = (e) => {
|
|
582
586
|
const inMenu = menuRef.current?.contains(document.activeElement) || triggerRef.current === document.activeElement;
|
|
583
587
|
if (!inMenu) return;
|
|
@@ -812,6 +816,7 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
812
816
|
const [highlightIdx, setHighlightIdx] = useState(0);
|
|
813
817
|
const inputRef = useRef(null);
|
|
814
818
|
const triggerRef = useRef(null);
|
|
819
|
+
const [triggerWidth, setTriggerWidth] = useState(void 0);
|
|
815
820
|
const listRef = useRef(null);
|
|
816
821
|
const listboxId = useId();
|
|
817
822
|
const pos = usePosition(triggerRef, listRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
@@ -820,9 +825,11 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
820
825
|
);
|
|
821
826
|
const selectedLabel = options.find((o) => o.value === value)?.label ?? "";
|
|
822
827
|
const { ref: overflowRef, isTruncated: labelTruncated } = useTextOverflow({ lines: 1, content: selectedLabel, disabled: open });
|
|
823
|
-
|
|
828
|
+
const [prevQuery, setPrevQuery] = useState(query);
|
|
829
|
+
if (query !== prevQuery) {
|
|
830
|
+
setPrevQuery(query);
|
|
824
831
|
setHighlightIdx(0);
|
|
825
|
-
}
|
|
832
|
+
}
|
|
826
833
|
useEffect(() => {
|
|
827
834
|
if (!open) return;
|
|
828
835
|
const handler = (e) => {
|
|
@@ -870,6 +877,7 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
870
877
|
}, [overflowRef]);
|
|
871
878
|
const triggerContent = /* @__PURE__ */ jsxs("div", { ref: (node) => {
|
|
872
879
|
triggerRef.current = node;
|
|
880
|
+
setTriggerWidth(node?.offsetWidth);
|
|
873
881
|
if (typeof ref === "function") ref(node);
|
|
874
882
|
else if (ref) ref.current = node;
|
|
875
883
|
}, className: cn("relative", className), children: [
|
|
@@ -950,7 +958,7 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
950
958
|
"rounded-[var(--ds-radius-md)]",
|
|
951
959
|
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]"
|
|
952
960
|
),
|
|
953
|
-
style: { top: pos.top, left: pos.left, width:
|
|
961
|
+
style: { top: pos.top, left: pos.left, width: triggerWidth },
|
|
954
962
|
children: /* @__PURE__ */ jsx("div", { style: { padding: "var(--ds-space-1)" }, children: loading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-ds-4", children: /* @__PURE__ */ jsx(Spinner, { size: "sm", label: "Loading options" }) }) : filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-ds-2 py-ds-3 text-sm text-[var(--ds-text-muted)] text-center", children: "No results" }) : filtered.map((opt, i) => /* @__PURE__ */ jsxs(
|
|
955
963
|
"button",
|
|
956
964
|
{
|
|
@@ -1491,7 +1499,7 @@ function getMonthGrid(year, month, weekStartsOn = 0) {
|
|
|
1491
1499
|
const firstOfMonth = new Date(year, month, 1);
|
|
1492
1500
|
const gridStart = startOfWeek(firstOfMonth, weekStartsOn);
|
|
1493
1501
|
const weeks = [];
|
|
1494
|
-
|
|
1502
|
+
const current = new Date(gridStart);
|
|
1495
1503
|
for (let w = 0; w < 6; w++) {
|
|
1496
1504
|
const week = [];
|
|
1497
1505
|
for (let d = 0; d < 7; d++) {
|
|
@@ -2292,11 +2300,11 @@ function NumberInput({
|
|
|
2292
2300
|
const [focused, setFocused] = useState(false);
|
|
2293
2301
|
const [draft, setDraft] = useState(String(value));
|
|
2294
2302
|
const decimals = allowDecimals ?? step % 1 !== 0;
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
}
|
|
2303
|
+
const [prevSync, setPrevSync] = useState({ value, focused });
|
|
2304
|
+
if (value !== prevSync.value || focused !== prevSync.focused) {
|
|
2305
|
+
setPrevSync({ value, focused });
|
|
2306
|
+
if (!focused) setDraft(String(value));
|
|
2307
|
+
}
|
|
2300
2308
|
const clamp = useCallback(
|
|
2301
2309
|
(v) => Math.min(max, Math.max(min, v)),
|
|
2302
2310
|
[min, max]
|
|
@@ -2397,7 +2405,7 @@ function NumberInput({
|
|
|
2397
2405
|
onMouseDown: (e) => {
|
|
2398
2406
|
e.preventDefault();
|
|
2399
2407
|
inputRef.current?.focus();
|
|
2400
|
-
!disabled && !atMin
|
|
2408
|
+
if (!disabled && !atMin) startRepeat(decrement);
|
|
2401
2409
|
},
|
|
2402
2410
|
onMouseUp: stopRepeat,
|
|
2403
2411
|
onMouseLeave: stopRepeat,
|
|
@@ -2453,7 +2461,7 @@ function NumberInput({
|
|
|
2453
2461
|
onMouseDown: (e) => {
|
|
2454
2462
|
e.preventDefault();
|
|
2455
2463
|
inputRef.current?.focus();
|
|
2456
|
-
!disabled && !atMax
|
|
2464
|
+
if (!disabled && !atMax) startRepeat(increment);
|
|
2457
2465
|
},
|
|
2458
2466
|
onMouseUp: stopRepeat,
|
|
2459
2467
|
onMouseLeave: stopRepeat,
|
|
@@ -3012,11 +3020,12 @@ function ColorPicker({
|
|
|
3012
3020
|
const [hexInput, setHexInput] = useState(value);
|
|
3013
3021
|
const satLightRef = useRef(null);
|
|
3014
3022
|
const draggingRef = useRef(false);
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3023
|
+
const [prevValue, setPrevValue] = useState(value);
|
|
3024
|
+
if (value !== prevValue) {
|
|
3025
|
+
setPrevValue(value);
|
|
3026
|
+
setHsl(hexToHsl(value));
|
|
3018
3027
|
setHexInput(value);
|
|
3019
|
-
}
|
|
3028
|
+
}
|
|
3020
3029
|
const emitChange = useCallback(
|
|
3021
3030
|
(newHsl) => {
|
|
3022
3031
|
setHsl(newHsl);
|
|
@@ -3250,17 +3259,15 @@ function useFormContext() {
|
|
|
3250
3259
|
function FormWrapper({ onSubmit, validationMode = "onSubmit", children, className, ref }) {
|
|
3251
3260
|
const [errors, setErrors] = useState({});
|
|
3252
3261
|
const [submitted, setSubmitted] = useState(false);
|
|
3253
|
-
const errorsRef =
|
|
3254
|
-
errorsRef.current = errors;
|
|
3262
|
+
const errorsRef = useLatest(errors);
|
|
3255
3263
|
const pendingSubmit = useRef(false);
|
|
3256
|
-
const onSubmitRef =
|
|
3257
|
-
onSubmitRef.current = onSubmit;
|
|
3264
|
+
const onSubmitRef = useLatest(onSubmit);
|
|
3258
3265
|
useEffect(() => {
|
|
3259
3266
|
if (pendingSubmit.current && submitted) {
|
|
3260
3267
|
pendingSubmit.current = false;
|
|
3261
3268
|
onSubmitRef.current(errorsRef.current);
|
|
3262
3269
|
}
|
|
3263
|
-
}, [submitted, errors]);
|
|
3270
|
+
}, [submitted, errors, errorsRef, onSubmitRef]);
|
|
3264
3271
|
const setError = useCallback((field, message) => {
|
|
3265
3272
|
setErrors((prev) => ({ ...prev, [field]: message }));
|
|
3266
3273
|
}, []);
|
|
@@ -5818,9 +5825,12 @@ function MonthDropdown({
|
|
|
5818
5825
|
offset: 8,
|
|
5819
5826
|
flip: true
|
|
5820
5827
|
});
|
|
5821
|
-
|
|
5828
|
+
const browseSyncKey = open ? currentDate.getTime() : null;
|
|
5829
|
+
const [prevBrowseSyncKey, setPrevBrowseSyncKey] = useState(browseSyncKey);
|
|
5830
|
+
if (browseSyncKey !== prevBrowseSyncKey) {
|
|
5831
|
+
setPrevBrowseSyncKey(browseSyncKey);
|
|
5822
5832
|
if (open) setBrowseYear(currentDate.getFullYear());
|
|
5823
|
-
}
|
|
5833
|
+
}
|
|
5824
5834
|
useEffect(() => {
|
|
5825
5835
|
if (!open) return;
|
|
5826
5836
|
const onKey = (e) => {
|
|
@@ -5938,9 +5948,12 @@ function YearDropdown({
|
|
|
5938
5948
|
});
|
|
5939
5949
|
const currentYear = currentDate.getFullYear();
|
|
5940
5950
|
const [rangeStart, setRangeStart] = useState(() => currentYear - 4);
|
|
5941
|
-
|
|
5951
|
+
const rangeSyncKey = open ? currentYear : null;
|
|
5952
|
+
const [prevRangeSyncKey, setPrevRangeSyncKey] = useState(rangeSyncKey);
|
|
5953
|
+
if (rangeSyncKey !== prevRangeSyncKey) {
|
|
5954
|
+
setPrevRangeSyncKey(rangeSyncKey);
|
|
5942
5955
|
if (open) setRangeStart(currentYear - 4);
|
|
5943
|
-
}
|
|
5956
|
+
}
|
|
5944
5957
|
useEffect(() => {
|
|
5945
5958
|
if (!open) return;
|
|
5946
5959
|
const onKey = (e) => {
|
|
@@ -6662,6 +6675,13 @@ function TruncLabel2({ children }) {
|
|
|
6662
6675
|
if (!isTruncated) return label;
|
|
6663
6676
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: label });
|
|
6664
6677
|
}
|
|
6678
|
+
function allDescendantIds(node) {
|
|
6679
|
+
const ids = [node.id];
|
|
6680
|
+
if (node.children) {
|
|
6681
|
+
for (const child of node.children) ids.push(...allDescendantIds(child));
|
|
6682
|
+
}
|
|
6683
|
+
return ids;
|
|
6684
|
+
}
|
|
6665
6685
|
function TreeView({
|
|
6666
6686
|
nodes,
|
|
6667
6687
|
selectable,
|
|
@@ -6704,13 +6724,6 @@ function TreeView({
|
|
|
6704
6724
|
},
|
|
6705
6725
|
[selectable, multiSelect, onSelect]
|
|
6706
6726
|
);
|
|
6707
|
-
const allDescendantIds = useCallback((node) => {
|
|
6708
|
-
const ids = [node.id];
|
|
6709
|
-
if (node.children) {
|
|
6710
|
-
for (const child of node.children) ids.push(...allDescendantIds(child));
|
|
6711
|
-
}
|
|
6712
|
-
return ids;
|
|
6713
|
-
}, []);
|
|
6714
6727
|
const handleCheck = useCallback(
|
|
6715
6728
|
(node) => {
|
|
6716
6729
|
if (!checkable) return;
|
|
@@ -6726,7 +6739,7 @@ function TreeView({
|
|
|
6726
6739
|
return next;
|
|
6727
6740
|
});
|
|
6728
6741
|
},
|
|
6729
|
-
[checkable,
|
|
6742
|
+
[checkable, onCheck]
|
|
6730
6743
|
);
|
|
6731
6744
|
const getCheckState = useCallback(
|
|
6732
6745
|
(node) => {
|
|
@@ -6737,7 +6750,7 @@ function TreeView({
|
|
|
6737
6750
|
if (checkedCount > 0) return "indeterminate";
|
|
6738
6751
|
return "unchecked";
|
|
6739
6752
|
},
|
|
6740
|
-
[checked
|
|
6753
|
+
[checked]
|
|
6741
6754
|
);
|
|
6742
6755
|
const flatNodes = useCallback(() => {
|
|
6743
6756
|
const result = [];
|
|
@@ -7845,6 +7858,11 @@ var Breadcrumbs = forwardRef(function Breadcrumbs2({
|
|
|
7845
7858
|
function Popover({ open, onOpenChange, trigger, children, side = "bottom", align = "center", width, className, container }) {
|
|
7846
7859
|
const triggerRef = useRef(null);
|
|
7847
7860
|
const floatingRef = useRef(null);
|
|
7861
|
+
const [triggerWidth, setTriggerWidth] = useState(void 0);
|
|
7862
|
+
const setTriggerNode = useCallback((node) => {
|
|
7863
|
+
triggerRef.current = node;
|
|
7864
|
+
setTriggerWidth(node?.offsetWidth);
|
|
7865
|
+
}, []);
|
|
7848
7866
|
const pos = usePosition(triggerRef, floatingRef, open, { side, align, offset: 8, flip: true });
|
|
7849
7867
|
useEffect(() => {
|
|
7850
7868
|
if (!open) return;
|
|
@@ -7870,8 +7888,11 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
|
|
|
7870
7888
|
/* @__PURE__ */ jsx(
|
|
7871
7889
|
Slot,
|
|
7872
7890
|
{
|
|
7873
|
-
ref:
|
|
7874
|
-
onClick: () =>
|
|
7891
|
+
ref: setTriggerNode,
|
|
7892
|
+
onClick: () => {
|
|
7893
|
+
setTriggerWidth(triggerRef.current?.offsetWidth);
|
|
7894
|
+
onOpenChange(!open);
|
|
7895
|
+
},
|
|
7875
7896
|
children: trigger
|
|
7876
7897
|
}
|
|
7877
7898
|
),
|
|
@@ -7891,7 +7912,7 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
|
|
|
7891
7912
|
style: {
|
|
7892
7913
|
top: pos.top,
|
|
7893
7914
|
left: pos.left,
|
|
7894
|
-
width: width === "trigger" ?
|
|
7915
|
+
width: width === "trigger" ? triggerWidth : width === "auto" ? void 0 : width
|
|
7895
7916
|
},
|
|
7896
7917
|
children
|
|
7897
7918
|
}
|
|
@@ -8507,10 +8528,7 @@ function CompactFlyout({
|
|
|
8507
8528
|
onMouseEnter,
|
|
8508
8529
|
onMouseLeave
|
|
8509
8530
|
}) {
|
|
8510
|
-
const
|
|
8511
|
-
useLayoutEffect(() => {
|
|
8512
|
-
setPos(computeCompactFlyoutPos(anchorEl, items.length));
|
|
8513
|
-
}, [anchorEl, items.length]);
|
|
8531
|
+
const pos = useMemo(() => computeCompactFlyoutPos(anchorEl, items.length), [anchorEl, items.length]);
|
|
8514
8532
|
useEffect(() => {
|
|
8515
8533
|
function handler(e) {
|
|
8516
8534
|
if (e.key === "Escape") onClose();
|
|
@@ -8900,7 +8918,7 @@ function CompactNavItem({
|
|
|
8900
8918
|
expanded,
|
|
8901
8919
|
onToggleExpand
|
|
8902
8920
|
}) {
|
|
8903
|
-
const
|
|
8921
|
+
const [triggerEl, setTriggerEl] = useState(null);
|
|
8904
8922
|
const handleMouseEnter = useCallback(() => {
|
|
8905
8923
|
onCancelClose();
|
|
8906
8924
|
if (hasChildren && !isOpen) onOpen(flyoutKey);
|
|
@@ -8919,7 +8937,7 @@ function CompactNavItem({
|
|
|
8919
8937
|
/* @__PURE__ */ jsxs(
|
|
8920
8938
|
"button",
|
|
8921
8939
|
{
|
|
8922
|
-
ref:
|
|
8940
|
+
ref: setTriggerEl,
|
|
8923
8941
|
onMouseEnter: !mobile && hasChildren ? handleMouseEnter : void 0,
|
|
8924
8942
|
onMouseLeave: !mobile && hasChildren && isOpen ? handleMouseLeave : void 0,
|
|
8925
8943
|
onClick: handleClick,
|
|
@@ -8953,12 +8971,12 @@ function CompactNavItem({
|
|
|
8953
8971
|
]
|
|
8954
8972
|
}
|
|
8955
8973
|
),
|
|
8956
|
-
!mobile && isOpen && hasChildren && item.children &&
|
|
8974
|
+
!mobile && isOpen && hasChildren && item.children && triggerEl && /* @__PURE__ */ jsx(
|
|
8957
8975
|
CompactFlyout,
|
|
8958
8976
|
{
|
|
8959
8977
|
parentLabel: item.label,
|
|
8960
8978
|
items: item.children,
|
|
8961
|
-
anchorEl:
|
|
8979
|
+
anchorEl: triggerEl,
|
|
8962
8980
|
portalContainer,
|
|
8963
8981
|
onItemClick,
|
|
8964
8982
|
onClose,
|
|
@@ -9948,6 +9966,187 @@ function Dock({
|
|
|
9948
9966
|
}
|
|
9949
9967
|
);
|
|
9950
9968
|
}
|
|
9969
|
+
function Sheet({ open, onClose, title, children, footer, snapPoints = [0.5, 0.92], container, flush }) {
|
|
9970
|
+
const titleId = useId();
|
|
9971
|
+
const panelRef = useRef(null);
|
|
9972
|
+
const [mounted, setMounted] = useState(open);
|
|
9973
|
+
const [snapIdx, setSnapIdx] = useState(0);
|
|
9974
|
+
const [dragOffset, setDragOffset] = useState(0);
|
|
9975
|
+
const [dragging, setDragging] = useState(false);
|
|
9976
|
+
const dragStartY = useRef(0);
|
|
9977
|
+
const startHeight = useRef(0);
|
|
9978
|
+
const onCloseRef = useLatest(onClose);
|
|
9979
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
9980
|
+
if (open !== prevOpen) {
|
|
9981
|
+
setPrevOpen(open);
|
|
9982
|
+
if (open) {
|
|
9983
|
+
setMounted(true);
|
|
9984
|
+
setSnapIdx(0);
|
|
9985
|
+
setDragOffset(0);
|
|
9986
|
+
}
|
|
9987
|
+
}
|
|
9988
|
+
const viewportHeight = useCallback(
|
|
9989
|
+
() => container instanceof HTMLElement ? container.clientHeight : window.innerHeight,
|
|
9990
|
+
[container]
|
|
9991
|
+
);
|
|
9992
|
+
function handleTransitionEnd() {
|
|
9993
|
+
if (!open) setMounted(false);
|
|
9994
|
+
}
|
|
9995
|
+
useReturnFocus(open);
|
|
9996
|
+
useEffect(() => {
|
|
9997
|
+
if (!open || !mounted) return;
|
|
9998
|
+
const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
|
|
9999
|
+
return () => cancelAnimationFrame(raf);
|
|
10000
|
+
}, [open, mounted]);
|
|
10001
|
+
useEffect(() => {
|
|
10002
|
+
if (!open) return;
|
|
10003
|
+
const onKeyDown = (e) => {
|
|
10004
|
+
if (e.key === "Escape") onCloseRef.current();
|
|
10005
|
+
};
|
|
10006
|
+
document.addEventListener("keydown", onKeyDown);
|
|
10007
|
+
if (!container) lockBodyScroll();
|
|
10008
|
+
return () => {
|
|
10009
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
10010
|
+
if (!container) unlockBodyScroll();
|
|
10011
|
+
};
|
|
10012
|
+
}, [open, container, onCloseRef]);
|
|
10013
|
+
const handlePointerDown = useCallback((e) => {
|
|
10014
|
+
setDragging(true);
|
|
10015
|
+
dragStartY.current = e.clientY;
|
|
10016
|
+
startHeight.current = (snapPoints[snapIdx] ?? snapPoints[0]) * viewportHeight();
|
|
10017
|
+
setDragOffset(0);
|
|
10018
|
+
e.target.setPointerCapture(e.pointerId);
|
|
10019
|
+
}, [snapIdx, snapPoints, viewportHeight]);
|
|
10020
|
+
const handlePointerMove = useCallback((e) => {
|
|
10021
|
+
if (!dragging) return;
|
|
10022
|
+
const delta = dragStartY.current - e.clientY;
|
|
10023
|
+
setDragOffset(delta);
|
|
10024
|
+
}, [dragging]);
|
|
10025
|
+
const handlePointerUp = useCallback(() => {
|
|
10026
|
+
if (!dragging) return;
|
|
10027
|
+
setDragging(false);
|
|
10028
|
+
const currentHeightPx = startHeight.current + dragOffset;
|
|
10029
|
+
const currentFraction = currentHeightPx / viewportHeight();
|
|
10030
|
+
if (currentFraction < snapPoints[0] * 0.6) {
|
|
10031
|
+
onClose();
|
|
10032
|
+
setDragOffset(0);
|
|
10033
|
+
return;
|
|
10034
|
+
}
|
|
10035
|
+
let bestIdx = 0;
|
|
10036
|
+
let bestDist = Math.abs(currentFraction - snapPoints[0]);
|
|
10037
|
+
for (let i = 1; i < snapPoints.length; i++) {
|
|
10038
|
+
const dist = Math.abs(currentFraction - snapPoints[i]);
|
|
10039
|
+
if (dist < bestDist) {
|
|
10040
|
+
bestDist = dist;
|
|
10041
|
+
bestIdx = i;
|
|
10042
|
+
}
|
|
10043
|
+
}
|
|
10044
|
+
setSnapIdx(bestIdx);
|
|
10045
|
+
setDragOffset(0);
|
|
10046
|
+
}, [dragging, dragOffset, snapPoints, onClose, viewportHeight]);
|
|
10047
|
+
if (!mounted) return null;
|
|
10048
|
+
const baseHeight = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;
|
|
10049
|
+
const heightUnit = container ? "%" : "vh";
|
|
10050
|
+
const dragPx = dragging ? dragOffset : 0;
|
|
10051
|
+
const positionClass = container ? "absolute" : "fixed";
|
|
10052
|
+
return createPortal(
|
|
10053
|
+
/* @__PURE__ */ jsxs(
|
|
10054
|
+
"div",
|
|
10055
|
+
{
|
|
10056
|
+
className: cn(
|
|
10057
|
+
`${positionClass} inset-0 z-[var(--ds-z-modal)] transition-opacity duration-[var(--ds-transition-speed)]`,
|
|
10058
|
+
open ? "pointer-events-auto" : "pointer-events-none"
|
|
10059
|
+
),
|
|
10060
|
+
onTransitionEnd: handleTransitionEnd,
|
|
10061
|
+
children: [
|
|
10062
|
+
/* @__PURE__ */ jsx(
|
|
10063
|
+
"div",
|
|
10064
|
+
{
|
|
10065
|
+
className: cn(
|
|
10066
|
+
"absolute inset-0 bg-black/50 transition-opacity duration-[var(--ds-transition-speed)]",
|
|
10067
|
+
open ? "opacity-100" : "opacity-0"
|
|
10068
|
+
),
|
|
10069
|
+
onClick: onClose
|
|
10070
|
+
}
|
|
10071
|
+
),
|
|
10072
|
+
/* @__PURE__ */ jsxs(
|
|
10073
|
+
"div",
|
|
10074
|
+
{
|
|
10075
|
+
ref: panelRef,
|
|
10076
|
+
role: "dialog",
|
|
10077
|
+
"aria-modal": "true",
|
|
10078
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
10079
|
+
"data-ds-sheet": "",
|
|
10080
|
+
className: cn(
|
|
10081
|
+
`${positionClass} bottom-0 left-0 right-0 z-10 flex flex-col`,
|
|
10082
|
+
"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
|
|
10083
|
+
GLASS_OVERLAY,
|
|
10084
|
+
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
10085
|
+
"rounded-t-[var(--ds-radius-xl)]",
|
|
10086
|
+
!dragging && "transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
10087
|
+
open ? "translate-y-0" : "translate-y-full"
|
|
10088
|
+
),
|
|
10089
|
+
style: {
|
|
10090
|
+
containerType: "inline-size",
|
|
10091
|
+
height: dragPx ? `calc(${baseHeight}${heightUnit} + ${dragPx}px)` : `${baseHeight}${heightUnit}`
|
|
10092
|
+
},
|
|
10093
|
+
children: [
|
|
10094
|
+
/* @__PURE__ */ jsx(
|
|
10095
|
+
"div",
|
|
10096
|
+
{
|
|
10097
|
+
className: "flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none",
|
|
10098
|
+
onPointerDown: handlePointerDown,
|
|
10099
|
+
onPointerMove: handlePointerMove,
|
|
10100
|
+
onPointerUp: handlePointerUp,
|
|
10101
|
+
onPointerCancel: handlePointerUp,
|
|
10102
|
+
children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]" })
|
|
10103
|
+
}
|
|
10104
|
+
),
|
|
10105
|
+
title && /* @__PURE__ */ jsxs(
|
|
10106
|
+
"div",
|
|
10107
|
+
{
|
|
10108
|
+
className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
10109
|
+
style: { padding: "var(--ds-space-2) var(--ds-space-5)" },
|
|
10110
|
+
children: [
|
|
10111
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
|
|
10112
|
+
/* @__PURE__ */ jsx(
|
|
10113
|
+
"button",
|
|
10114
|
+
{
|
|
10115
|
+
onClick: onClose,
|
|
10116
|
+
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
10117
|
+
className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
10118
|
+
"aria-label": "Close",
|
|
10119
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
10120
|
+
}
|
|
10121
|
+
)
|
|
10122
|
+
]
|
|
10123
|
+
}
|
|
10124
|
+
),
|
|
10125
|
+
/* @__PURE__ */ jsx(
|
|
10126
|
+
"div",
|
|
10127
|
+
{
|
|
10128
|
+
className: "flex-1 overflow-y-auto",
|
|
10129
|
+
style: flush ? void 0 : { padding: "var(--ds-space-5)" },
|
|
10130
|
+
children
|
|
10131
|
+
}
|
|
10132
|
+
),
|
|
10133
|
+
footer && /* @__PURE__ */ jsx(
|
|
10134
|
+
"div",
|
|
10135
|
+
{
|
|
10136
|
+
className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
10137
|
+
style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
|
|
10138
|
+
children: footer
|
|
10139
|
+
}
|
|
10140
|
+
)
|
|
10141
|
+
]
|
|
10142
|
+
}
|
|
10143
|
+
)
|
|
10144
|
+
]
|
|
10145
|
+
}
|
|
10146
|
+
),
|
|
10147
|
+
container ?? document.body
|
|
10148
|
+
);
|
|
10149
|
+
}
|
|
9951
10150
|
var slideClasses = {
|
|
9952
10151
|
right: {
|
|
9953
10152
|
panel: "top-0 right-0 h-full",
|
|
@@ -9970,19 +10169,23 @@ var borderByPosition = {
|
|
|
9970
10169
|
left: "border-r-[length:var(--ds-border-width)] border-r-[var(--ds-border-default)]",
|
|
9971
10170
|
bottom: "border-t-[length:var(--ds-border-width)] border-t-[var(--ds-border-default)]"
|
|
9972
10171
|
};
|
|
9973
|
-
function Drawer(
|
|
10172
|
+
function Drawer(props) {
|
|
10173
|
+
const { position = "right", mobile, snapPoints, open, onClose, title, children, footer, container, flush } = props;
|
|
10174
|
+
const isPhone = useBreakpoint("sm");
|
|
10175
|
+
const mobileMode = mobile ?? (position === "left" ? "panel" : "sheet");
|
|
10176
|
+
if (isPhone && mobileMode === "sheet") {
|
|
10177
|
+
return /* @__PURE__ */ jsx(Sheet, { open, onClose, title, footer, container, flush, snapPoints, children });
|
|
10178
|
+
}
|
|
10179
|
+
return /* @__PURE__ */ jsx(DrawerPanel, { ...props });
|
|
10180
|
+
}
|
|
10181
|
+
function DrawerPanel({ open, onClose, position = "right", width = "400px", title, children, footer, container, flush, lightBackdrop, topOffset }) {
|
|
9974
10182
|
const titleId = useId();
|
|
9975
10183
|
const { ref: titleOverflowRef, isTruncated: titleTruncated } = useTextOverflow({ lines: 1 });
|
|
9976
10184
|
const isMobile = useBreakpoint("sm");
|
|
9977
10185
|
const panelRef = useRef(null);
|
|
9978
|
-
const [mounted, setMounted] = useState(
|
|
9979
|
-
const onCloseRef =
|
|
9980
|
-
|
|
9981
|
-
useEffect(() => {
|
|
9982
|
-
if (open) {
|
|
9983
|
-
setMounted(true);
|
|
9984
|
-
}
|
|
9985
|
-
}, [open]);
|
|
10186
|
+
const [mounted, setMounted] = useState(open);
|
|
10187
|
+
const onCloseRef = useLatest(onClose);
|
|
10188
|
+
if (open && !mounted) setMounted(true);
|
|
9986
10189
|
function handleTransitionEnd() {
|
|
9987
10190
|
if (!open) setMounted(false);
|
|
9988
10191
|
}
|
|
@@ -9997,7 +10200,7 @@ function Drawer({ open, onClose, position = "right", width = "400px", title, chi
|
|
|
9997
10200
|
document.removeEventListener("keydown", onKeyDown);
|
|
9998
10201
|
if (!container) unlockBodyScroll();
|
|
9999
10202
|
};
|
|
10000
|
-
}, [open, container]);
|
|
10203
|
+
}, [open, container, onCloseRef]);
|
|
10001
10204
|
useReturnFocus(open);
|
|
10002
10205
|
useEffect(() => {
|
|
10003
10206
|
if (!open || !mounted) return;
|
|
@@ -10132,13 +10335,13 @@ var AppShell = forwardRef(function AppShell2({
|
|
|
10132
10335
|
const hasMobileMenu = mobileMenu != null;
|
|
10133
10336
|
const hasMobileNav = mobileNav != null;
|
|
10134
10337
|
const showMobileDrawer = hasMobileMenu && !(isSmallMobile && hasMobileNav);
|
|
10135
|
-
const
|
|
10338
|
+
const [shellEl, setShellEl] = useState(null);
|
|
10136
10339
|
return /* @__PURE__ */ jsx(
|
|
10137
10340
|
AppShellContext,
|
|
10138
10341
|
{
|
|
10139
10342
|
value: { hasSidebar, hasMobileMenu, hasMobileNav, sidebarOpen, setSidebarOpen, isMobile, isTablet },
|
|
10140
10343
|
children: /* @__PURE__ */ jsxs("div", { ref: (el) => {
|
|
10141
|
-
|
|
10344
|
+
setShellEl(el);
|
|
10142
10345
|
if (typeof ref === "function") ref(el);
|
|
10143
10346
|
else if (ref) ref.current = el;
|
|
10144
10347
|
}, className: cn("relative h-screen flex flex-col bg-[var(--ds-bg-canvas)] overflow-hidden", className), children: [
|
|
@@ -10170,7 +10373,7 @@ var AppShell = forwardRef(function AppShell2({
|
|
|
10170
10373
|
onClose: () => setSidebarOpen(false),
|
|
10171
10374
|
position: "left",
|
|
10172
10375
|
width: mobileMenuWidth ?? "var(--ds-drawer-width)",
|
|
10173
|
-
container:
|
|
10376
|
+
container: shellEl ?? void 0,
|
|
10174
10377
|
flush: mobileMenuFlush,
|
|
10175
10378
|
lightBackdrop: mobileMenuLightBackdrop,
|
|
10176
10379
|
topOffset: layout !== "stacked" && navbar != null ? "var(--ds-navbar-height)" : void 0,
|
|
@@ -10649,8 +10852,7 @@ function Dialog({ open, onClose, title, description, children, footer, variant =
|
|
|
10649
10852
|
const overlayRef = useRef(null);
|
|
10650
10853
|
const dialogRef = useRef(null);
|
|
10651
10854
|
const triggerRef = useRef(null);
|
|
10652
|
-
const onCloseRef =
|
|
10653
|
-
onCloseRef.current = onClose;
|
|
10855
|
+
const onCloseRef = useLatest(onClose);
|
|
10654
10856
|
const trapFocus = useCallback((e) => {
|
|
10655
10857
|
if (e.key !== "Tab" || !dialogRef.current) return;
|
|
10656
10858
|
const focusable = dialogRef.current.querySelectorAll(FOCUSABLE);
|
|
@@ -10686,7 +10888,7 @@ function Dialog({ open, onClose, title, description, children, footer, variant =
|
|
|
10686
10888
|
return () => {
|
|
10687
10889
|
document.removeEventListener("keydown", handler);
|
|
10688
10890
|
};
|
|
10689
|
-
}, [open, trapFocus, alert]);
|
|
10891
|
+
}, [open, trapFocus, alert, onCloseRef]);
|
|
10690
10892
|
useEffect(() => {
|
|
10691
10893
|
if (!open) return;
|
|
10692
10894
|
lockBodyScroll();
|
|
@@ -10798,16 +11000,22 @@ function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a co
|
|
|
10798
11000
|
groups.get(g).push(cmd);
|
|
10799
11001
|
}
|
|
10800
11002
|
const flatFiltered = filtered;
|
|
10801
|
-
|
|
11003
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
11004
|
+
if (open !== prevOpen) {
|
|
11005
|
+
setPrevOpen(open);
|
|
10802
11006
|
if (open) {
|
|
10803
11007
|
setQuery("");
|
|
10804
11008
|
setSelectedIdx(0);
|
|
10805
|
-
requestAnimationFrame(() => inputRef.current?.focus());
|
|
10806
11009
|
}
|
|
10807
|
-
}
|
|
10808
|
-
|
|
11010
|
+
}
|
|
11011
|
+
const [prevQuery, setPrevQuery] = useState(query);
|
|
11012
|
+
if (query !== prevQuery) {
|
|
11013
|
+
setPrevQuery(query);
|
|
10809
11014
|
setSelectedIdx(0);
|
|
10810
|
-
}
|
|
11015
|
+
}
|
|
11016
|
+
useEffect(() => {
|
|
11017
|
+
if (open) requestAnimationFrame(() => inputRef.current?.focus());
|
|
11018
|
+
}, [open]);
|
|
10811
11019
|
useEffect(() => {
|
|
10812
11020
|
if (!open) return;
|
|
10813
11021
|
const handler = (e) => {
|
|
@@ -10823,23 +11031,20 @@ function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a co
|
|
|
10823
11031
|
},
|
|
10824
11032
|
[onOpenChange]
|
|
10825
11033
|
);
|
|
10826
|
-
const handleKeyDown =
|
|
10827
|
-
(e)
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10832
|
-
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
},
|
|
10841
|
-
[flatFiltered, selectedIdx, handleSelect]
|
|
10842
|
-
);
|
|
11034
|
+
const handleKeyDown = (e) => {
|
|
11035
|
+
if (e.key === "ArrowDown") {
|
|
11036
|
+
e.preventDefault();
|
|
11037
|
+
setSelectedIdx((prev) => Math.min(prev + 1, flatFiltered.length - 1));
|
|
11038
|
+
listRef.current?.children[Math.min(selectedIdx + 1, flatFiltered.length - 1)]?.scrollIntoView({ block: "nearest" });
|
|
11039
|
+
} else if (e.key === "ArrowUp") {
|
|
11040
|
+
e.preventDefault();
|
|
11041
|
+
setSelectedIdx((prev) => Math.max(prev - 1, 0));
|
|
11042
|
+
listRef.current?.children[Math.max(selectedIdx - 1, 0)]?.scrollIntoView({ block: "nearest" });
|
|
11043
|
+
} else if (e.key === "Enter" && flatFiltered[selectedIdx]) {
|
|
11044
|
+
e.preventDefault();
|
|
11045
|
+
handleSelect(flatFiltered[selectedIdx]);
|
|
11046
|
+
}
|
|
11047
|
+
};
|
|
10843
11048
|
if (!open) return null;
|
|
10844
11049
|
let flatIdx = 0;
|
|
10845
11050
|
return createPortal(
|
|
@@ -11132,179 +11337,6 @@ function ContextMenu({ items, children, className, ref, container }) {
|
|
|
11132
11337
|
}
|
|
11133
11338
|
);
|
|
11134
11339
|
}
|
|
11135
|
-
function Sheet({ open, onClose, title, children, footer, snapPoints = [0.5, 0.92] }) {
|
|
11136
|
-
const titleId = useId();
|
|
11137
|
-
const panelRef = useRef(null);
|
|
11138
|
-
const [mounted, setMounted] = useState(false);
|
|
11139
|
-
const [snapIdx, setSnapIdx] = useState(0);
|
|
11140
|
-
const [dragOffset, setDragOffset] = useState(0);
|
|
11141
|
-
const isDragging = useRef(false);
|
|
11142
|
-
const dragStartY = useRef(0);
|
|
11143
|
-
const startHeight = useRef(0);
|
|
11144
|
-
const onCloseRef = useRef(onClose);
|
|
11145
|
-
onCloseRef.current = onClose;
|
|
11146
|
-
useEffect(() => {
|
|
11147
|
-
if (open) {
|
|
11148
|
-
setMounted(true);
|
|
11149
|
-
setSnapIdx(0);
|
|
11150
|
-
setDragOffset(0);
|
|
11151
|
-
}
|
|
11152
|
-
}, [open]);
|
|
11153
|
-
function handleTransitionEnd() {
|
|
11154
|
-
if (!open) setMounted(false);
|
|
11155
|
-
}
|
|
11156
|
-
useReturnFocus(open);
|
|
11157
|
-
useEffect(() => {
|
|
11158
|
-
if (!open || !mounted) return;
|
|
11159
|
-
const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
|
|
11160
|
-
return () => cancelAnimationFrame(raf);
|
|
11161
|
-
}, [open, mounted]);
|
|
11162
|
-
useEffect(() => {
|
|
11163
|
-
if (!open) return;
|
|
11164
|
-
const onKeyDown = (e) => {
|
|
11165
|
-
if (e.key === "Escape") onCloseRef.current();
|
|
11166
|
-
};
|
|
11167
|
-
document.addEventListener("keydown", onKeyDown);
|
|
11168
|
-
lockBodyScroll();
|
|
11169
|
-
return () => {
|
|
11170
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
11171
|
-
unlockBodyScroll();
|
|
11172
|
-
};
|
|
11173
|
-
}, [open]);
|
|
11174
|
-
const handlePointerDown = useCallback((e) => {
|
|
11175
|
-
isDragging.current = true;
|
|
11176
|
-
dragStartY.current = e.clientY;
|
|
11177
|
-
startHeight.current = (snapPoints[snapIdx] ?? snapPoints[0]) * window.innerHeight;
|
|
11178
|
-
setDragOffset(0);
|
|
11179
|
-
e.target.setPointerCapture(e.pointerId);
|
|
11180
|
-
}, [snapIdx, snapPoints]);
|
|
11181
|
-
const handlePointerMove = useCallback((e) => {
|
|
11182
|
-
if (!isDragging.current) return;
|
|
11183
|
-
const delta = dragStartY.current - e.clientY;
|
|
11184
|
-
setDragOffset(delta);
|
|
11185
|
-
}, []);
|
|
11186
|
-
const handlePointerUp = useCallback(() => {
|
|
11187
|
-
if (!isDragging.current) return;
|
|
11188
|
-
isDragging.current = false;
|
|
11189
|
-
const currentHeightPx = startHeight.current + dragOffset;
|
|
11190
|
-
const currentFraction = currentHeightPx / window.innerHeight;
|
|
11191
|
-
if (currentFraction < snapPoints[0] * 0.6) {
|
|
11192
|
-
onClose();
|
|
11193
|
-
setDragOffset(0);
|
|
11194
|
-
return;
|
|
11195
|
-
}
|
|
11196
|
-
let bestIdx = 0;
|
|
11197
|
-
let bestDist = Math.abs(currentFraction - snapPoints[0]);
|
|
11198
|
-
for (let i = 1; i < snapPoints.length; i++) {
|
|
11199
|
-
const dist = Math.abs(currentFraction - snapPoints[i]);
|
|
11200
|
-
if (dist < bestDist) {
|
|
11201
|
-
bestDist = dist;
|
|
11202
|
-
bestIdx = i;
|
|
11203
|
-
}
|
|
11204
|
-
}
|
|
11205
|
-
setSnapIdx(bestIdx);
|
|
11206
|
-
setDragOffset(0);
|
|
11207
|
-
}, [dragOffset, snapPoints, onClose]);
|
|
11208
|
-
if (!mounted) return null;
|
|
11209
|
-
const baseHeightVh = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;
|
|
11210
|
-
const dragPx = isDragging.current ? dragOffset : 0;
|
|
11211
|
-
return createPortal(
|
|
11212
|
-
/* @__PURE__ */ jsxs(
|
|
11213
|
-
"div",
|
|
11214
|
-
{
|
|
11215
|
-
className: cn(
|
|
11216
|
-
"fixed inset-0 z-[var(--ds-z-modal)] transition-opacity duration-[var(--ds-transition-speed)]",
|
|
11217
|
-
open ? "pointer-events-auto" : "pointer-events-none"
|
|
11218
|
-
),
|
|
11219
|
-
onTransitionEnd: handleTransitionEnd,
|
|
11220
|
-
children: [
|
|
11221
|
-
/* @__PURE__ */ jsx(
|
|
11222
|
-
"div",
|
|
11223
|
-
{
|
|
11224
|
-
className: cn(
|
|
11225
|
-
"absolute inset-0 bg-black/50 transition-opacity duration-[var(--ds-transition-speed)]",
|
|
11226
|
-
open ? "opacity-100" : "opacity-0"
|
|
11227
|
-
),
|
|
11228
|
-
onClick: onClose
|
|
11229
|
-
}
|
|
11230
|
-
),
|
|
11231
|
-
/* @__PURE__ */ jsxs(
|
|
11232
|
-
"div",
|
|
11233
|
-
{
|
|
11234
|
-
ref: panelRef,
|
|
11235
|
-
role: "dialog",
|
|
11236
|
-
"aria-modal": "true",
|
|
11237
|
-
"aria-labelledby": title ? titleId : void 0,
|
|
11238
|
-
className: cn(
|
|
11239
|
-
"fixed bottom-0 left-0 right-0 z-10 flex flex-col",
|
|
11240
|
-
"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
|
|
11241
|
-
GLASS_OVERLAY,
|
|
11242
|
-
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
11243
|
-
"rounded-t-[var(--ds-radius-xl)]",
|
|
11244
|
-
!isDragging.current && "transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
11245
|
-
open ? "translate-y-0" : "translate-y-full"
|
|
11246
|
-
),
|
|
11247
|
-
style: {
|
|
11248
|
-
containerType: "inline-size",
|
|
11249
|
-
height: dragPx ? `calc(${baseHeightVh}vh + ${dragPx}px)` : `${baseHeightVh}vh`
|
|
11250
|
-
},
|
|
11251
|
-
children: [
|
|
11252
|
-
/* @__PURE__ */ jsx(
|
|
11253
|
-
"div",
|
|
11254
|
-
{
|
|
11255
|
-
className: "flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none",
|
|
11256
|
-
onPointerDown: handlePointerDown,
|
|
11257
|
-
onPointerMove: handlePointerMove,
|
|
11258
|
-
onPointerUp: handlePointerUp,
|
|
11259
|
-
onPointerCancel: handlePointerUp,
|
|
11260
|
-
children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]" })
|
|
11261
|
-
}
|
|
11262
|
-
),
|
|
11263
|
-
title && /* @__PURE__ */ jsxs(
|
|
11264
|
-
"div",
|
|
11265
|
-
{
|
|
11266
|
-
className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
11267
|
-
style: { padding: "var(--ds-space-2) var(--ds-space-5)" },
|
|
11268
|
-
children: [
|
|
11269
|
-
/* @__PURE__ */ jsx("h2", { id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
|
|
11270
|
-
/* @__PURE__ */ jsx(
|
|
11271
|
-
"button",
|
|
11272
|
-
{
|
|
11273
|
-
onClick: onClose,
|
|
11274
|
-
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
11275
|
-
className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
11276
|
-
"aria-label": "Close",
|
|
11277
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
11278
|
-
}
|
|
11279
|
-
)
|
|
11280
|
-
]
|
|
11281
|
-
}
|
|
11282
|
-
),
|
|
11283
|
-
/* @__PURE__ */ jsx(
|
|
11284
|
-
"div",
|
|
11285
|
-
{
|
|
11286
|
-
className: "flex-1 overflow-y-auto",
|
|
11287
|
-
style: { padding: "var(--ds-space-5)" },
|
|
11288
|
-
children
|
|
11289
|
-
}
|
|
11290
|
-
),
|
|
11291
|
-
footer && /* @__PURE__ */ jsx(
|
|
11292
|
-
"div",
|
|
11293
|
-
{
|
|
11294
|
-
className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
11295
|
-
style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
|
|
11296
|
-
children: footer
|
|
11297
|
-
}
|
|
11298
|
-
)
|
|
11299
|
-
]
|
|
11300
|
-
}
|
|
11301
|
-
)
|
|
11302
|
-
]
|
|
11303
|
-
}
|
|
11304
|
-
),
|
|
11305
|
-
document.body
|
|
11306
|
-
);
|
|
11307
|
-
}
|
|
11308
11340
|
function TruncTitle({ children }) {
|
|
11309
11341
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
11310
11342
|
const el = /* @__PURE__ */ jsx("span", { ref, className: "truncate", children });
|
|
@@ -11335,7 +11367,10 @@ function NotificationCenter({
|
|
|
11335
11367
|
const [internalFilter, setInternalFilter] = useState("all");
|
|
11336
11368
|
const isControlled = controlledOpen !== void 0;
|
|
11337
11369
|
const open = isControlled ? controlledOpen : internalOpen;
|
|
11338
|
-
const setOpen =
|
|
11370
|
+
const setOpen = useCallback((v) => {
|
|
11371
|
+
if (isControlled) onOpenChange?.(v);
|
|
11372
|
+
else setInternalOpen(v);
|
|
11373
|
+
}, [isControlled, onOpenChange]);
|
|
11339
11374
|
const triggerRef = useRef(null);
|
|
11340
11375
|
const panelRef = useRef(null);
|
|
11341
11376
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "end", offset: 8, flip: true });
|
|
@@ -11359,7 +11394,7 @@ function NotificationCenter({
|
|
|
11359
11394
|
document.removeEventListener("keydown", onKey);
|
|
11360
11395
|
document.removeEventListener("mousedown", onClick);
|
|
11361
11396
|
};
|
|
11362
|
-
}, [open]);
|
|
11397
|
+
}, [open, setOpen]);
|
|
11363
11398
|
const grouped = groupByDate(filteredNotifications);
|
|
11364
11399
|
if (variant === "page") {
|
|
11365
11400
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full", className), children: [
|
|
@@ -11606,11 +11641,13 @@ function Tour({ steps, open, onClose, onComplete, container }) {
|
|
|
11606
11641
|
if (el) setRect(el.getBoundingClientRect());
|
|
11607
11642
|
else setRect(null);
|
|
11608
11643
|
}, [step]);
|
|
11644
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
11645
|
+
if (open !== prevOpen) {
|
|
11646
|
+
setPrevOpen(open);
|
|
11647
|
+
if (!open) setCurrent(0);
|
|
11648
|
+
}
|
|
11609
11649
|
useEffect(() => {
|
|
11610
|
-
if (!open)
|
|
11611
|
-
setCurrent(0);
|
|
11612
|
-
return;
|
|
11613
|
-
}
|
|
11650
|
+
if (!open) return;
|
|
11614
11651
|
measureTarget();
|
|
11615
11652
|
window.addEventListener("resize", measureTarget);
|
|
11616
11653
|
window.addEventListener("scroll", measureTarget, true);
|
|
@@ -11619,16 +11656,6 @@ function Tour({ steps, open, onClose, onComplete, container }) {
|
|
|
11619
11656
|
window.removeEventListener("scroll", measureTarget, true);
|
|
11620
11657
|
};
|
|
11621
11658
|
}, [open, current, measureTarget]);
|
|
11622
|
-
useEffect(() => {
|
|
11623
|
-
if (!open) return;
|
|
11624
|
-
const onKey = (e) => {
|
|
11625
|
-
if (e.key === "Escape") onClose();
|
|
11626
|
-
else if (e.key === "ArrowRight") handleNext();
|
|
11627
|
-
else if (e.key === "ArrowLeft") handlePrev();
|
|
11628
|
-
};
|
|
11629
|
-
document.addEventListener("keydown", onKey);
|
|
11630
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
11631
|
-
});
|
|
11632
11659
|
const handleNext = useCallback(() => {
|
|
11633
11660
|
if (current < steps.length - 1) setCurrent((c) => c + 1);
|
|
11634
11661
|
else {
|
|
@@ -11639,6 +11666,16 @@ function Tour({ steps, open, onClose, onComplete, container }) {
|
|
|
11639
11666
|
const handlePrev = useCallback(() => {
|
|
11640
11667
|
if (current > 0) setCurrent((c) => c - 1);
|
|
11641
11668
|
}, [current]);
|
|
11669
|
+
useEffect(() => {
|
|
11670
|
+
if (!open) return;
|
|
11671
|
+
const onKey = (e) => {
|
|
11672
|
+
if (e.key === "Escape") onClose();
|
|
11673
|
+
else if (e.key === "ArrowRight") handleNext();
|
|
11674
|
+
else if (e.key === "ArrowLeft") handlePrev();
|
|
11675
|
+
};
|
|
11676
|
+
document.addEventListener("keydown", onKey);
|
|
11677
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
11678
|
+
}, [open, onClose, handleNext, handlePrev]);
|
|
11642
11679
|
if (!open || !step) return null;
|
|
11643
11680
|
const padding = 8;
|
|
11644
11681
|
const spotlightRadius = 8;
|
|
@@ -11942,15 +11979,14 @@ function Toast({ variant = "default", message, visible, onDismiss, duration = 3e
|
|
|
11942
11979
|
const timerRef = useRef(void 0);
|
|
11943
11980
|
const startedAtRef = useRef(0);
|
|
11944
11981
|
const remainingRef = useRef(duration);
|
|
11945
|
-
const onDismissRef =
|
|
11946
|
-
onDismissRef.current = onDismiss;
|
|
11982
|
+
const onDismissRef = useLatest(onDismiss);
|
|
11947
11983
|
const startTimer = useCallback((ms) => {
|
|
11948
11984
|
const delay = ms ?? remainingRef.current;
|
|
11949
11985
|
remainingRef.current = delay;
|
|
11950
11986
|
startedAtRef.current = Date.now();
|
|
11951
11987
|
if (!Number.isFinite(delay) || delay <= 0) return;
|
|
11952
11988
|
timerRef.current = setTimeout(() => onDismissRef.current(), delay);
|
|
11953
|
-
}, []);
|
|
11989
|
+
}, [onDismissRef]);
|
|
11954
11990
|
const clearTimer = useCallback(() => {
|
|
11955
11991
|
if (timerRef.current) {
|
|
11956
11992
|
clearTimeout(timerRef.current);
|