gridsmith-ui 0.21.0 → 0.23.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/chat.js +3 -3
- package/dist/chunk-3BRQRKDO.js +72 -0
- package/dist/chunk-3BRQRKDO.js.map +1 -0
- package/dist/{chunk-GGVASDXT.js → chunk-6PL7FXYH.js} +284 -521
- package/dist/chunk-6PL7FXYH.js.map +1 -0
- package/dist/chunk-7TOJ4G7S.js +197 -0
- package/dist/chunk-7TOJ4G7S.js.map +1 -0
- package/dist/chunk-CKWITUSH.js +40 -0
- package/dist/chunk-CKWITUSH.js.map +1 -0
- package/dist/{chunk-ILIODA7W.js → chunk-CXMV7SXJ.js} +4 -3
- package/dist/chunk-CXMV7SXJ.js.map +1 -0
- package/dist/{chunk-EQDR57AM.js → chunk-EYMGLK4M.js} +3 -3
- package/dist/{chunk-EQDR57AM.js.map → chunk-EYMGLK4M.js.map} +1 -1
- package/dist/chunk-ICNWPNMM.js +1363 -0
- package/dist/chunk-ICNWPNMM.js.map +1 -0
- package/dist/chunk-IVCVNAXG.js +115 -0
- package/dist/chunk-IVCVNAXG.js.map +1 -0
- package/dist/{chunk-XYDIBW3J.js → chunk-SBTBMAIU.js} +4 -3
- package/dist/chunk-SBTBMAIU.js.map +1 -0
- package/dist/data-grid.d.ts +38 -4
- package/dist/data-grid.js +305 -264
- package/dist/data-grid.js.map +1 -1
- package/dist/editor.js +10 -3
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +122 -146
- package/dist/index.js +1091 -1885
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +4 -2
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.d.ts +1 -1
- package/dist/resizable.js +26 -14
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +24 -4
- package/dist/{table-utils-GounRE6s.d.ts → table-utils-BkjNEWts.d.ts} +5 -1
- package/dist/tokens.css +20 -3
- package/dist/use-pagination-DiJo0aW5.d.ts +153 -0
- package/dist/virtualized.d.ts +11 -1
- package/dist/virtualized.js +69 -18
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +20 -3
- package/package.json +1 -1
- package/dist/chunk-GGVASDXT.js.map +0 -1
- package/dist/chunk-ILIODA7W.js.map +0 -1
- package/dist/chunk-JN37OVTP.js +0 -67
- package/dist/chunk-JN37OVTP.js.map +0 -1
- package/dist/chunk-TKVTZWBN.js +0 -50
- package/dist/chunk-TKVTZWBN.js.map +0 -1
- package/dist/chunk-XYDIBW3J.js.map +0 -1
|
@@ -1,161 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PreferencesContext } from './chunk-TKVTZWBN.js';
|
|
1
|
+
import { PreferencesContext, Button } from './chunk-7TOJ4G7S.js';
|
|
3
2
|
import { useBreakpoint, readBreakpointPx } from './chunk-CRQ6KCRD.js';
|
|
4
|
-
import {
|
|
3
|
+
import { FormChangeCtx, useOverlayLayer, useReturnFocus, useFocusTrap, focusInitial, useNonModalDialog, OVERLAY_CLOSE_ATTR } from './chunk-RT7RYGC3.js';
|
|
4
|
+
import { SurfaceBoundary } from './chunk-CKWITUSH.js';
|
|
5
|
+
import { useTextOverflow, Tooltip } from './chunk-CXMV7SXJ.js';
|
|
5
6
|
import { useLatest } from './chunk-WH2FUFAC.js';
|
|
6
7
|
import { Icon } from './chunk-4LDYR7QP.js';
|
|
7
8
|
import { cn, lockBodyScroll, unlockBodyScroll, OVERLAY_SURFACE, GLASS_OVERLAY } from './chunk-M2QRNBDQ.js';
|
|
8
|
-
import {
|
|
9
|
-
import { createContext, forwardRef, useContext, version, useState, useCallback, useRef, useEffect, isValidElement, useMemo, useId, useLayoutEffect } from 'react';
|
|
9
|
+
import { createContext, version, forwardRef, useState, useCallback, useRef, useEffect, isValidElement, useContext, useMemo, useId, useLayoutEffect } from 'react';
|
|
10
10
|
import { createPortal } from 'react-dom';
|
|
11
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
11
12
|
|
|
12
|
-
var sizes = {
|
|
13
|
-
sm: "h-4 w-4 border-[1.5px]",
|
|
14
|
-
md: "h-6 w-6 border-2",
|
|
15
|
-
lg: "h-8 w-8 border-[2.5px]"
|
|
16
|
-
};
|
|
17
|
-
function Spinner({ size = "md", color = "default", label = "Loading", className }) {
|
|
18
|
-
return /* @__PURE__ */ jsx(
|
|
19
|
-
"span",
|
|
20
|
-
{
|
|
21
|
-
role: "status",
|
|
22
|
-
"aria-label": label,
|
|
23
|
-
className: cn(
|
|
24
|
-
"inline-block rounded-[var(--ds-radius-full)] animate-spin",
|
|
25
|
-
color === "inherit" ? "border-current/30 border-t-current" : "border-[var(--ds-bg-emphasis)] border-t-[var(--ds-accent-primary)]",
|
|
26
|
-
sizes[size],
|
|
27
|
-
className
|
|
28
|
-
)
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
var ControlSizeContext = createContext(null);
|
|
33
|
-
var ButtonSizeContext = ControlSizeContext;
|
|
34
|
-
var variantStyles = {
|
|
35
|
-
default: "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box] text-[var(--ds-text-on-primary)] border-transparent hover:bg-[var(--ds-accent-primary-hover)] hover:brightness-110",
|
|
36
|
-
secondary: "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]",
|
|
37
|
-
tertiary: "bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)] border-transparent hover:brightness-95",
|
|
38
|
-
outline: "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]",
|
|
39
|
-
ghost: "bg-transparent text-[var(--ds-text-primary)] border-transparent hover:bg-[var(--ds-bg-muted)] shadow-none",
|
|
40
|
-
destructive: "bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)] border-transparent hover:opacity-90",
|
|
41
|
-
success: "bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)] border-transparent hover:opacity-90",
|
|
42
|
-
warning: "bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)] border-transparent hover:opacity-90",
|
|
43
|
-
link: "bg-transparent text-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary-hover)] hover:underline"
|
|
44
|
-
};
|
|
45
|
-
var sizeStyles = {
|
|
46
|
-
// xs / icon-xs: dense tool chrome (builder toolbars, inline row actions).
|
|
47
|
-
xs: "h-ds-6 px-ds-3 py-0 text-xs",
|
|
48
|
-
sm: "h-[var(--ds-control-height-sm)] px-ds-4 py-ds-1 text-xs",
|
|
49
|
-
md: "h-[var(--ds-control-height-md)] px-ds-6 py-ds-2 text-sm",
|
|
50
|
-
lg: "h-[var(--ds-control-height-lg)] px-ds-8 py-ds-3 text-base",
|
|
51
|
-
"icon-xs": "h-ds-6 w-ds-6 p-0",
|
|
52
|
-
"icon-sm": "h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] p-0",
|
|
53
|
-
icon: "h-[var(--ds-control-height-md)] w-[var(--ds-control-height-md)] p-0",
|
|
54
|
-
"icon-lg": "h-[var(--ds-control-height-lg)] w-[var(--ds-control-height-lg)] p-0"
|
|
55
|
-
};
|
|
56
|
-
var linkSizeStyles = {
|
|
57
|
-
xs: "text-xs",
|
|
58
|
-
sm: "text-xs",
|
|
59
|
-
md: "text-sm",
|
|
60
|
-
lg: "text-base",
|
|
61
|
-
"icon-xs": "text-xs",
|
|
62
|
-
"icon-sm": "text-xs",
|
|
63
|
-
icon: "text-sm",
|
|
64
|
-
"icon-lg": "text-base"
|
|
65
|
-
};
|
|
66
|
-
var iconPaddingReduce = {
|
|
67
|
-
xs: 2,
|
|
68
|
-
sm: 2,
|
|
69
|
-
md: 4,
|
|
70
|
-
lg: 6
|
|
71
|
-
};
|
|
72
|
-
var HOVER_SCALE_CAP = { "--_btn-scale": "min(var(--ds-hover-scale), 1.02)" };
|
|
73
|
-
var Button = forwardRef(function Button2({ variant = "default", size: sizeProp, iconLeft, iconRight, loading, className, children, disabled, style, onClick, ...props }, ref) {
|
|
74
|
-
const contextSize = useContext(ControlSizeContext);
|
|
75
|
-
const size = sizeProp ?? contextSize ?? "md";
|
|
76
|
-
const isLink = variant === "link";
|
|
77
|
-
const spinnerSize = size === "lg" || size === "icon-lg" ? "md" : "sm";
|
|
78
|
-
let paddingStyle;
|
|
79
|
-
const isIconSize = size === "icon" || size === "icon-xs" || size === "icon-sm" || size === "icon-lg";
|
|
80
|
-
if (!isIconSize && !isLink && (iconLeft || iconRight)) {
|
|
81
|
-
const reduce = iconPaddingReduce[size];
|
|
82
|
-
paddingStyle = {};
|
|
83
|
-
if (iconLeft) paddingStyle.paddingLeft = `calc(${getCssPadding(size)} - ${reduce}px)`;
|
|
84
|
-
if (iconRight) paddingStyle.paddingRight = `calc(${getCssPadding(size)} - ${reduce}px)`;
|
|
85
|
-
}
|
|
86
|
-
const isLoading = loading && !disabled;
|
|
87
|
-
const isDisabled = !!disabled;
|
|
88
|
-
const handleClick = isLoading ? (e) => {
|
|
89
|
-
e.preventDefault();
|
|
90
|
-
} : onClick;
|
|
91
|
-
const ariaLabel = props["aria-label"];
|
|
92
|
-
const inTooltip = useContext(TooltipCtx);
|
|
93
|
-
const btn = /* @__PURE__ */ jsxs(
|
|
94
|
-
"button",
|
|
95
|
-
{
|
|
96
|
-
ref,
|
|
97
|
-
"data-variant": variant,
|
|
98
|
-
className: cn(
|
|
99
|
-
"relative inline-flex items-center justify-center gap-ds-2 whitespace-nowrap font-medium",
|
|
100
|
-
isLink ? cn(
|
|
101
|
-
"px-0 py-ds-0.5 h-auto",
|
|
102
|
-
linkSizeStyles[size],
|
|
103
|
-
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
104
|
-
"focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2",
|
|
105
|
-
"cursor-pointer",
|
|
106
|
-
"active:text-[var(--ds-accent-primary-active)]"
|
|
107
|
-
) : cn(
|
|
108
|
-
"border-[length:var(--ds-border-width)]",
|
|
109
|
-
"rounded-[var(--ds-radius-md)]",
|
|
110
|
-
"shadow-[var(--ds-shadow-button)]",
|
|
111
|
-
"hover:scale-[var(--_btn-scale)] hover:-translate-y-[var(--ds-hover-lift)]",
|
|
112
|
-
"active:shadow-[var(--ds-shadow-button-pressed)] active:translate-x-[var(--ds-press-depth)] active:translate-y-[var(--ds-press-depth)]",
|
|
113
|
-
"[transition:var(--ds-transition-interactive)]",
|
|
114
|
-
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
115
|
-
"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
116
|
-
sizeStyles[size]
|
|
117
|
-
),
|
|
118
|
-
variantStyles[variant],
|
|
119
|
-
isLoading && !isLink && "cursor-wait pointer-events-none",
|
|
120
|
-
className
|
|
121
|
-
),
|
|
122
|
-
disabled: isDisabled,
|
|
123
|
-
"aria-busy": isLoading || void 0,
|
|
124
|
-
"aria-disabled": isLoading && !disabled ? true : void 0,
|
|
125
|
-
onClick: handleClick,
|
|
126
|
-
style: isLink ? style : { ...HOVER_SCALE_CAP, ...paddingStyle, ...style },
|
|
127
|
-
...props,
|
|
128
|
-
children: [
|
|
129
|
-
loading && !isLink && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { size: spinnerSize, color: "inherit" }) }),
|
|
130
|
-
/* @__PURE__ */ jsxs("span", { className: cn("inline-flex items-center gap-ds-2 min-w-0", loading && !isLink && "invisible"), children: [
|
|
131
|
-
iconLeft,
|
|
132
|
-
children,
|
|
133
|
-
iconRight
|
|
134
|
-
] })
|
|
135
|
-
]
|
|
136
|
-
}
|
|
137
|
-
);
|
|
138
|
-
if (isIconSize && ariaLabel && !inTooltip) {
|
|
139
|
-
return /* @__PURE__ */ jsx(Tooltip, { content: ariaLabel, children: btn });
|
|
140
|
-
}
|
|
141
|
-
return btn;
|
|
142
|
-
});
|
|
143
|
-
function getCssPadding(size) {
|
|
144
|
-
switch (size) {
|
|
145
|
-
case "xs":
|
|
146
|
-
return "var(--ds-space-3)";
|
|
147
|
-
case "sm":
|
|
148
|
-
return "var(--ds-space-4)";
|
|
149
|
-
case "md":
|
|
150
|
-
return "var(--ds-space-6)";
|
|
151
|
-
case "lg":
|
|
152
|
-
return "var(--ds-space-8)";
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function triggerType(node) {
|
|
156
|
-
if (!isValidElement(node)) return {};
|
|
157
|
-
return (node.type === "button" || node.type === Button) && node.props.type === void 0 ? { type: "button" } : {};
|
|
158
|
-
}
|
|
159
13
|
function transitionMs(el) {
|
|
160
14
|
const cs = getComputedStyle(el);
|
|
161
15
|
const parse = (list) => list.split(",").map((raw) => {
|
|
@@ -201,6 +55,126 @@ function useCloseSettle(open, elRef, onSettled) {
|
|
|
201
55
|
};
|
|
202
56
|
}, [open, elRef, cb]);
|
|
203
57
|
}
|
|
58
|
+
var STEP = 16;
|
|
59
|
+
var BIG_STEP = 64;
|
|
60
|
+
function clamp(v, min, max) {
|
|
61
|
+
return Math.min(Math.max(v, min), max);
|
|
62
|
+
}
|
|
63
|
+
function ResizeEdge({ edge, width, min, max, defaultWidth, onResize, label, onDraggingChange, className }) {
|
|
64
|
+
const [dragging, setDragging] = useState(false);
|
|
65
|
+
const start = useRef(null);
|
|
66
|
+
const latestOnResize = useLatest(onResize);
|
|
67
|
+
const direction = edge === "left" ? -1 : 1;
|
|
68
|
+
const onPointerDown = useCallback(
|
|
69
|
+
(e) => {
|
|
70
|
+
if (e.button !== 0) return;
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
start.current = { x: e.clientX, width };
|
|
73
|
+
setDragging(true);
|
|
74
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
75
|
+
},
|
|
76
|
+
[width]
|
|
77
|
+
);
|
|
78
|
+
const onPointerMove = useCallback(
|
|
79
|
+
(e) => {
|
|
80
|
+
if (!start.current) return;
|
|
81
|
+
const next = clamp(start.current.width + direction * (e.clientX - start.current.x), min, max());
|
|
82
|
+
latestOnResize.current(next);
|
|
83
|
+
},
|
|
84
|
+
[direction, min, max, latestOnResize]
|
|
85
|
+
);
|
|
86
|
+
const endDrag = useCallback(() => {
|
|
87
|
+
start.current = null;
|
|
88
|
+
setDragging(false);
|
|
89
|
+
}, []);
|
|
90
|
+
const latestOnDraggingChange = useLatest(onDraggingChange);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
latestOnDraggingChange.current?.(dragging);
|
|
93
|
+
}, [dragging, latestOnDraggingChange]);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!dragging) return;
|
|
96
|
+
const onKey = (e) => {
|
|
97
|
+
if (e.key !== "Escape" || !start.current) return;
|
|
98
|
+
latestOnResize.current(start.current.width);
|
|
99
|
+
endDrag();
|
|
100
|
+
};
|
|
101
|
+
document.addEventListener("keydown", onKey);
|
|
102
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
103
|
+
}, [dragging, endDrag, latestOnResize]);
|
|
104
|
+
const onKeyDown = (e) => {
|
|
105
|
+
const step = e.shiftKey ? BIG_STEP : STEP;
|
|
106
|
+
let next = null;
|
|
107
|
+
if (e.key === "ArrowLeft") next = width - direction * step;
|
|
108
|
+
else if (e.key === "ArrowRight") next = width + direction * step;
|
|
109
|
+
else if (e.key === "Home") next = min;
|
|
110
|
+
else if (e.key === "End") next = max();
|
|
111
|
+
else if (e.key === "Enter") next = defaultWidth;
|
|
112
|
+
if (next === null) return;
|
|
113
|
+
e.preventDefault();
|
|
114
|
+
onResize(clamp(next, min, max()));
|
|
115
|
+
};
|
|
116
|
+
return /* @__PURE__ */ jsx(
|
|
117
|
+
"div",
|
|
118
|
+
{
|
|
119
|
+
role: "separator",
|
|
120
|
+
tabIndex: 0,
|
|
121
|
+
"aria-orientation": "vertical",
|
|
122
|
+
"aria-label": label,
|
|
123
|
+
"aria-valuemin": min,
|
|
124
|
+
"aria-valuemax": max(),
|
|
125
|
+
"aria-valuenow": Math.round(width),
|
|
126
|
+
"data-resize-edge": edge,
|
|
127
|
+
"data-dragging": dragging || void 0,
|
|
128
|
+
onPointerDown,
|
|
129
|
+
onPointerMove,
|
|
130
|
+
onPointerUp: endDrag,
|
|
131
|
+
onPointerCancel: endDrag,
|
|
132
|
+
onDoubleClick: () => onResize(clamp(defaultWidth, min, max())),
|
|
133
|
+
onKeyDown,
|
|
134
|
+
className: cn(
|
|
135
|
+
// A narrow absolutely-positioned strip over the edge — never a flex child that takes width.
|
|
136
|
+
"group/edge absolute top-0 bottom-0 z-10 w-ds-2 cursor-col-resize touch-none select-none outline-none",
|
|
137
|
+
edge === "left" ? "-left-ds-1" : "-right-ds-1",
|
|
138
|
+
className
|
|
139
|
+
),
|
|
140
|
+
children: /* @__PURE__ */ jsx(
|
|
141
|
+
"div",
|
|
142
|
+
{
|
|
143
|
+
"aria-hidden": "true",
|
|
144
|
+
className: cn(
|
|
145
|
+
"absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 transition-[width,background-color] duration-[var(--ds-transition-speed)]",
|
|
146
|
+
"group-hover/edge:w-[3px] group-hover/edge:bg-[var(--ds-accent-primary)]",
|
|
147
|
+
"group-focus-visible/edge:w-[3px] group-focus-visible/edge:bg-[var(--ds-accent-primary)]",
|
|
148
|
+
dragging && "w-[3px] bg-[var(--ds-accent-primary)]"
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
var remembered = /* @__PURE__ */ new Map();
|
|
156
|
+
function useRememberedWidth(key) {
|
|
157
|
+
const [width, setWidth] = useState(() => key ? remembered.get(key) ?? null : null);
|
|
158
|
+
const remember = useCallback(
|
|
159
|
+
(w) => {
|
|
160
|
+
setWidth(w);
|
|
161
|
+
if (!key) return;
|
|
162
|
+
if (w === null) remembered.delete(key);
|
|
163
|
+
else remembered.set(key, w);
|
|
164
|
+
},
|
|
165
|
+
[key]
|
|
166
|
+
);
|
|
167
|
+
return [width, remember];
|
|
168
|
+
}
|
|
169
|
+
function pxOf(length) {
|
|
170
|
+
if (!length) return null;
|
|
171
|
+
const m = /^(\d+(?:\.\d+)?)px$/.exec(length.trim());
|
|
172
|
+
return m ? parseFloat(m[1]) : null;
|
|
173
|
+
}
|
|
174
|
+
function defaultMaxWidth(container) {
|
|
175
|
+
const base = container instanceof HTMLElement ? container.clientWidth : typeof window !== "undefined" ? window.innerWidth : 1200;
|
|
176
|
+
return Math.round(base * 0.6);
|
|
177
|
+
}
|
|
204
178
|
var OVERLAY_ROOT_ATTR = "data-overlay-root";
|
|
205
179
|
function controlsOf(root) {
|
|
206
180
|
if (!root) return "";
|
|
@@ -356,7 +330,7 @@ function DiscardConfirm({ open, onKeep, onDiscard }) {
|
|
|
356
330
|
"aria-label": "Unsaved changes",
|
|
357
331
|
"data-discard-confirm": "",
|
|
358
332
|
className: "shrink-0 flex flex-wrap items-center justify-between gap-ds-3 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-status-warning-bg)]",
|
|
359
|
-
style: { padding: "var(--ds-space-3) var(--ds-
|
|
333
|
+
style: { padding: "var(--ds-space-3) var(--ds-page-gutter)" },
|
|
360
334
|
children: [
|
|
361
335
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--ds-text-primary)]", children: "You have unsaved changes." }),
|
|
362
336
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
@@ -367,328 +341,26 @@ function DiscardConfirm({ open, onKeep, onDiscard }) {
|
|
|
367
341
|
}
|
|
368
342
|
);
|
|
369
343
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const [dragOffset, setDragOffset] = useState(0);
|
|
382
|
-
const [dragging, setDragging] = useState(false);
|
|
383
|
-
const dragStartY = useRef(0);
|
|
384
|
-
const startHeight = useRef(0);
|
|
385
|
-
const onCloseRef = useLatest(onClose);
|
|
386
|
-
const [prevOpen, setPrevOpen] = useState(open);
|
|
387
|
-
if (open !== prevOpen) {
|
|
388
|
-
setPrevOpen(open);
|
|
389
|
-
if (open) {
|
|
390
|
-
setMounted(true);
|
|
391
|
-
setHidden(false);
|
|
392
|
-
setSnapIdx(0);
|
|
393
|
-
setDragOffset(0);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
if (open && !mounted) setMounted(true);
|
|
397
|
-
if (open && hidden) setHidden(false);
|
|
398
|
-
const viewportHeight = useCallback(
|
|
399
|
-
() => container instanceof HTMLElement ? container.clientHeight : window.innerHeight,
|
|
400
|
-
[container]
|
|
401
|
-
);
|
|
402
|
-
useCloseSettle(open, panelRef, () => {
|
|
403
|
-
if (keepMounted) setHidden(true);
|
|
404
|
-
else setMounted(false);
|
|
405
|
-
});
|
|
406
|
-
useReturnFocus(open, panelRef);
|
|
407
|
-
useEffect(() => {
|
|
408
|
-
if (!open || !mounted) return;
|
|
409
|
-
const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
|
|
410
|
-
return () => cancelAnimationFrame(raf);
|
|
411
|
-
}, [open, mounted]);
|
|
412
|
-
const isTopLayer = useOverlayLayer(open);
|
|
413
|
-
useFocusTrap(panelRef, open, isTopLayer);
|
|
414
|
-
useEffect(() => {
|
|
415
|
-
if (!open) return;
|
|
416
|
-
const onKeyDown = (e) => {
|
|
417
|
-
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
418
|
-
e.preventDefault();
|
|
419
|
-
onCloseRef.current();
|
|
420
|
-
};
|
|
421
|
-
document.addEventListener("keydown", onKeyDown);
|
|
422
|
-
if (!container) lockBodyScroll();
|
|
423
|
-
return () => {
|
|
424
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
425
|
-
if (!container) unlockBodyScroll();
|
|
344
|
+
var DrawerWidthCtx = createContext(null);
|
|
345
|
+
function useScrollbarInset() {
|
|
346
|
+
const observer = useRef(null);
|
|
347
|
+
return useCallback((el) => {
|
|
348
|
+
observer.current?.disconnect();
|
|
349
|
+
observer.current = null;
|
|
350
|
+
if (!el) return;
|
|
351
|
+
const measure = () => {
|
|
352
|
+
const style = getComputedStyle(el);
|
|
353
|
+
const borders = (parseFloat(style.borderLeftWidth) || 0) + (parseFloat(style.borderRightWidth) || 0);
|
|
354
|
+
el.style.setProperty("--gs-scrollbar", `${Math.max(0, el.offsetWidth - el.clientWidth - borders)}px`);
|
|
426
355
|
};
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
setDragOffset(0);
|
|
433
|
-
e.target.setPointerCapture(e.pointerId);
|
|
434
|
-
}, [snapIdx, snapPoints, viewportHeight]);
|
|
435
|
-
const handlePointerMove = useCallback((e) => {
|
|
436
|
-
if (!dragging) return;
|
|
437
|
-
const delta = dragStartY.current - e.clientY;
|
|
438
|
-
setDragOffset(delta);
|
|
439
|
-
}, [dragging]);
|
|
440
|
-
const handlePointerUp = useCallback(() => {
|
|
441
|
-
if (!dragging) return;
|
|
442
|
-
setDragging(false);
|
|
443
|
-
const currentHeightPx = startHeight.current + dragOffset;
|
|
444
|
-
const currentFraction = currentHeightPx / viewportHeight();
|
|
445
|
-
if (currentFraction < snapPoints[0] * 0.6) {
|
|
446
|
-
onClose();
|
|
447
|
-
setDragOffset(0);
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
let bestIdx = 0;
|
|
451
|
-
let bestDist = Math.abs(currentFraction - snapPoints[0]);
|
|
452
|
-
for (let i = 1; i < snapPoints.length; i++) {
|
|
453
|
-
const dist = Math.abs(currentFraction - snapPoints[i]);
|
|
454
|
-
if (dist < bestDist) {
|
|
455
|
-
bestDist = dist;
|
|
456
|
-
bestIdx = i;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
setSnapIdx(bestIdx);
|
|
460
|
-
setDragOffset(0);
|
|
461
|
-
}, [dragging, dragOffset, snapPoints, onClose, viewportHeight]);
|
|
462
|
-
if (!mounted) return null;
|
|
463
|
-
const baseHeight = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;
|
|
464
|
-
const heightUnit = container ? "%" : "vh";
|
|
465
|
-
const dragPx = dragging ? dragOffset : 0;
|
|
466
|
-
const positionClass = container ? "absolute" : "fixed";
|
|
467
|
-
return createPortal(
|
|
468
|
-
/* @__PURE__ */ jsxs(
|
|
469
|
-
"div",
|
|
470
|
-
{
|
|
471
|
-
hidden: keepMounted && hidden ? true : void 0,
|
|
472
|
-
className: cn(
|
|
473
|
-
`${positionClass} inset-0 z-[var(--ds-z-modal)] transition-opacity duration-[var(--ds-transition-speed)]`,
|
|
474
|
-
open ? "pointer-events-auto" : "pointer-events-none"
|
|
475
|
-
),
|
|
476
|
-
children: [
|
|
477
|
-
/* @__PURE__ */ jsx(
|
|
478
|
-
"div",
|
|
479
|
-
{
|
|
480
|
-
className: cn(
|
|
481
|
-
"absolute inset-0 bg-black/50 transition-opacity duration-[var(--ds-transition-speed)]",
|
|
482
|
-
open ? "opacity-100" : "opacity-0"
|
|
483
|
-
),
|
|
484
|
-
onClick: onClose
|
|
485
|
-
}
|
|
486
|
-
),
|
|
487
|
-
/* @__PURE__ */ jsxs(
|
|
488
|
-
"div",
|
|
489
|
-
{
|
|
490
|
-
ref: panelRef,
|
|
491
|
-
id,
|
|
492
|
-
role: "dialog",
|
|
493
|
-
"data-gs": "sheet",
|
|
494
|
-
...{ [OVERLAY_ROOT_ATTR]: "" },
|
|
495
|
-
"aria-modal": "true",
|
|
496
|
-
"aria-labelledby": title ? titleId : labelledBy,
|
|
497
|
-
"data-ds-sheet": "",
|
|
498
|
-
className: cn(
|
|
499
|
-
`${positionClass} bottom-0 left-0 right-0 z-10 flex flex-col`,
|
|
500
|
-
OVERLAY_SURFACE,
|
|
501
|
-
"text-[var(--ds-text-primary)]",
|
|
502
|
-
GLASS_OVERLAY,
|
|
503
|
-
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
504
|
-
"rounded-t-[var(--ds-radius-xl)]",
|
|
505
|
-
!dragging && "transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
506
|
-
open ? "translate-y-0" : "translate-y-full"
|
|
507
|
-
),
|
|
508
|
-
style: {
|
|
509
|
-
containerType: "inline-size",
|
|
510
|
-
height: dragPx ? `calc(${baseHeight}${heightUnit} + ${dragPx}px)` : `${baseHeight}${heightUnit}`
|
|
511
|
-
},
|
|
512
|
-
children: [
|
|
513
|
-
/* @__PURE__ */ jsx(
|
|
514
|
-
"div",
|
|
515
|
-
{
|
|
516
|
-
className: "flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none",
|
|
517
|
-
onPointerDown: handlePointerDown,
|
|
518
|
-
onPointerMove: handlePointerMove,
|
|
519
|
-
onPointerUp: handlePointerUp,
|
|
520
|
-
onPointerCancel: handlePointerUp,
|
|
521
|
-
children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]" })
|
|
522
|
-
}
|
|
523
|
-
),
|
|
524
|
-
title && /* @__PURE__ */ jsxs(
|
|
525
|
-
"div",
|
|
526
|
-
{
|
|
527
|
-
className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
528
|
-
style: { padding: "var(--ds-space-2) var(--ds-space-5)" },
|
|
529
|
-
children: [
|
|
530
|
-
/* @__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 }),
|
|
531
|
-
/* @__PURE__ */ jsx(
|
|
532
|
-
"button",
|
|
533
|
-
{
|
|
534
|
-
type: "button",
|
|
535
|
-
onClick: onClose,
|
|
536
|
-
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
537
|
-
className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
538
|
-
"aria-label": "Close",
|
|
539
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
540
|
-
}
|
|
541
|
-
)
|
|
542
|
-
]
|
|
543
|
-
}
|
|
544
|
-
),
|
|
545
|
-
/* @__PURE__ */ jsx(
|
|
546
|
-
"div",
|
|
547
|
-
{
|
|
548
|
-
className: "flex-1 overflow-y-auto",
|
|
549
|
-
style: flush ? void 0 : { padding: "var(--ds-space-5)" },
|
|
550
|
-
children: guards ? /* @__PURE__ */ jsx(OverlayCloseCtx, { value: guard.requestClose, children: standalone ? /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children }) : children }) : children
|
|
551
|
-
}
|
|
552
|
-
),
|
|
553
|
-
confirm,
|
|
554
|
-
guards && /* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
555
|
-
footer && /* @__PURE__ */ jsx(
|
|
556
|
-
"div",
|
|
557
|
-
{
|
|
558
|
-
className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
559
|
-
style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
|
|
560
|
-
children: footer
|
|
561
|
-
}
|
|
562
|
-
)
|
|
563
|
-
]
|
|
564
|
-
}
|
|
565
|
-
)
|
|
566
|
-
]
|
|
567
|
-
}
|
|
568
|
-
),
|
|
569
|
-
container ?? document.body
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
var STEP = 16;
|
|
573
|
-
var BIG_STEP = 64;
|
|
574
|
-
function clamp(v, min, max) {
|
|
575
|
-
return Math.min(Math.max(v, min), max);
|
|
576
|
-
}
|
|
577
|
-
function ResizeEdge({ edge, width, min, max, defaultWidth, onResize, label, onDraggingChange, className }) {
|
|
578
|
-
const [dragging, setDragging] = useState(false);
|
|
579
|
-
const start = useRef(null);
|
|
580
|
-
const latestOnResize = useLatest(onResize);
|
|
581
|
-
const direction = edge === "left" ? -1 : 1;
|
|
582
|
-
const onPointerDown = useCallback(
|
|
583
|
-
(e) => {
|
|
584
|
-
if (e.button !== 0) return;
|
|
585
|
-
e.preventDefault();
|
|
586
|
-
start.current = { x: e.clientX, width };
|
|
587
|
-
setDragging(true);
|
|
588
|
-
e.currentTarget.setPointerCapture(e.pointerId);
|
|
589
|
-
},
|
|
590
|
-
[width]
|
|
591
|
-
);
|
|
592
|
-
const onPointerMove = useCallback(
|
|
593
|
-
(e) => {
|
|
594
|
-
if (!start.current) return;
|
|
595
|
-
const next = clamp(start.current.width + direction * (e.clientX - start.current.x), min, max());
|
|
596
|
-
latestOnResize.current(next);
|
|
597
|
-
},
|
|
598
|
-
[direction, min, max, latestOnResize]
|
|
599
|
-
);
|
|
600
|
-
const endDrag = useCallback(() => {
|
|
601
|
-
start.current = null;
|
|
602
|
-
setDragging(false);
|
|
356
|
+
measure();
|
|
357
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
358
|
+
const o = new ResizeObserver(measure);
|
|
359
|
+
o.observe(el);
|
|
360
|
+
observer.current = o;
|
|
603
361
|
}, []);
|
|
604
|
-
const latestOnDraggingChange = useLatest(onDraggingChange);
|
|
605
|
-
useEffect(() => {
|
|
606
|
-
latestOnDraggingChange.current?.(dragging);
|
|
607
|
-
}, [dragging, latestOnDraggingChange]);
|
|
608
|
-
useEffect(() => {
|
|
609
|
-
if (!dragging) return;
|
|
610
|
-
const onKey = (e) => {
|
|
611
|
-
if (e.key !== "Escape" || !start.current) return;
|
|
612
|
-
latestOnResize.current(start.current.width);
|
|
613
|
-
endDrag();
|
|
614
|
-
};
|
|
615
|
-
document.addEventListener("keydown", onKey);
|
|
616
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
617
|
-
}, [dragging, endDrag, latestOnResize]);
|
|
618
|
-
const onKeyDown = (e) => {
|
|
619
|
-
const step = e.shiftKey ? BIG_STEP : STEP;
|
|
620
|
-
let next = null;
|
|
621
|
-
if (e.key === "ArrowLeft") next = width - direction * step;
|
|
622
|
-
else if (e.key === "ArrowRight") next = width + direction * step;
|
|
623
|
-
else if (e.key === "Home") next = min;
|
|
624
|
-
else if (e.key === "End") next = max();
|
|
625
|
-
else if (e.key === "Enter") next = defaultWidth;
|
|
626
|
-
if (next === null) return;
|
|
627
|
-
e.preventDefault();
|
|
628
|
-
onResize(clamp(next, min, max()));
|
|
629
|
-
};
|
|
630
|
-
return /* @__PURE__ */ jsx(
|
|
631
|
-
"div",
|
|
632
|
-
{
|
|
633
|
-
role: "separator",
|
|
634
|
-
tabIndex: 0,
|
|
635
|
-
"aria-orientation": "vertical",
|
|
636
|
-
"aria-label": label,
|
|
637
|
-
"aria-valuemin": min,
|
|
638
|
-
"aria-valuemax": max(),
|
|
639
|
-
"aria-valuenow": Math.round(width),
|
|
640
|
-
"data-resize-edge": edge,
|
|
641
|
-
"data-dragging": dragging || void 0,
|
|
642
|
-
onPointerDown,
|
|
643
|
-
onPointerMove,
|
|
644
|
-
onPointerUp: endDrag,
|
|
645
|
-
onPointerCancel: endDrag,
|
|
646
|
-
onDoubleClick: () => onResize(clamp(defaultWidth, min, max())),
|
|
647
|
-
onKeyDown,
|
|
648
|
-
className: cn(
|
|
649
|
-
// A narrow absolutely-positioned strip over the edge — never a flex child that takes width.
|
|
650
|
-
"group/edge absolute top-0 bottom-0 z-10 w-ds-2 cursor-col-resize touch-none select-none outline-none",
|
|
651
|
-
edge === "left" ? "-left-ds-1" : "-right-ds-1",
|
|
652
|
-
className
|
|
653
|
-
),
|
|
654
|
-
children: /* @__PURE__ */ jsx(
|
|
655
|
-
"div",
|
|
656
|
-
{
|
|
657
|
-
"aria-hidden": "true",
|
|
658
|
-
className: cn(
|
|
659
|
-
"absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 transition-[width,background-color] duration-[var(--ds-transition-speed)]",
|
|
660
|
-
"group-hover/edge:w-[3px] group-hover/edge:bg-[var(--ds-accent-primary)]",
|
|
661
|
-
"group-focus-visible/edge:w-[3px] group-focus-visible/edge:bg-[var(--ds-accent-primary)]",
|
|
662
|
-
dragging && "w-[3px] bg-[var(--ds-accent-primary)]"
|
|
663
|
-
)
|
|
664
|
-
}
|
|
665
|
-
)
|
|
666
|
-
}
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
var remembered = /* @__PURE__ */ new Map();
|
|
670
|
-
function useRememberedWidth(key) {
|
|
671
|
-
const [width, setWidth] = useState(() => key ? remembered.get(key) ?? null : null);
|
|
672
|
-
const remember = useCallback(
|
|
673
|
-
(w) => {
|
|
674
|
-
setWidth(w);
|
|
675
|
-
if (!key) return;
|
|
676
|
-
if (w === null) remembered.delete(key);
|
|
677
|
-
else remembered.set(key, w);
|
|
678
|
-
},
|
|
679
|
-
[key]
|
|
680
|
-
);
|
|
681
|
-
return [width, remember];
|
|
682
|
-
}
|
|
683
|
-
function pxOf(length) {
|
|
684
|
-
if (!length) return null;
|
|
685
|
-
const m = /^(\d+(?:\.\d+)?)px$/.exec(length.trim());
|
|
686
|
-
return m ? parseFloat(m[1]) : null;
|
|
687
|
-
}
|
|
688
|
-
function defaultMaxWidth(container) {
|
|
689
|
-
const base = container instanceof HTMLElement ? container.clientWidth : typeof window !== "undefined" ? window.innerWidth : 1200;
|
|
690
|
-
return Math.round(base * 0.6);
|
|
691
362
|
}
|
|
363
|
+
var insetLessScrollbar = (gutter) => `max(0px, calc(${gutter} - var(--gs-scrollbar, 0px)))`;
|
|
692
364
|
var DrawerFooterCtx = createContext(null);
|
|
693
365
|
var slideClasses = {
|
|
694
366
|
right: {
|
|
@@ -713,7 +385,8 @@ var borderByPosition = {
|
|
|
713
385
|
bottom: "border-t-[length:var(--ds-border-width)] border-t-[var(--ds-border-default)]"
|
|
714
386
|
};
|
|
715
387
|
function Drawer(props) {
|
|
716
|
-
const { position = "right", mobile,
|
|
388
|
+
const { position = "right", mobile, open, onClose, footer, dirty, onDiscard } = props;
|
|
389
|
+
const shellWidth = useContext(DrawerWidthCtx) ?? void 0;
|
|
717
390
|
const isPhone = useBreakpoint("sm");
|
|
718
391
|
const mobileMode = mobile ?? (position === "left" ? "panel" : "sheet");
|
|
719
392
|
const { marked, mark } = useOverlayMark(open);
|
|
@@ -736,15 +409,16 @@ function Drawer(props) {
|
|
|
736
409
|
() => ({ registerActions, unregisterActions }),
|
|
737
410
|
[registerActions, unregisterActions]
|
|
738
411
|
);
|
|
739
|
-
|
|
740
|
-
return /* @__PURE__ */ jsx(DrawerFooterCtx, { value: footerCtx, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: guard.requestClose, children: /* @__PURE__ */ jsx(Sheet, { open, onClose: guard.requestClose, title, footer: effectiveFooter, confirm, container, flush, snapPoints, keepMounted, id, labelledBy, children }) }) }) });
|
|
741
|
-
}
|
|
742
|
-
return /* @__PURE__ */ jsx(DrawerFooterCtx, { value: footerCtx, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: guard.requestClose, children: /* @__PURE__ */ jsx(DrawerPanel, { ...props, footer: effectiveFooter, onClose: guard.requestClose, confirm }) }) }) });
|
|
412
|
+
return /* @__PURE__ */ jsx(DrawerFooterCtx, { value: footerCtx, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: guard.requestClose, children: /* @__PURE__ */ jsx(DrawerPanel, { ...props, width: props.width ?? shellWidth, form: isPhone && mobileMode === "sheet" ? "sheet" : "panel", footer: effectiveFooter, onClose: guard.requestClose, confirm }) }) }) });
|
|
743
413
|
}
|
|
744
|
-
|
|
414
|
+
var INSET = "var(--ds-page-gutter)";
|
|
415
|
+
var DEFAULT_SNAPS = [0.5, 0.92];
|
|
416
|
+
function DrawerPanel({ form, open, onClose, position = "right", width = "400px", title, children, footer, container, flush, lightBackdrop, topOffset, modal = true, keepMounted = false, id, labelledBy, resizable = false, maxWidth, snapPoints = DEFAULT_SNAPS, confirm }) {
|
|
417
|
+
const sheet = form === "sheet";
|
|
745
418
|
const nonModal = !modal;
|
|
419
|
+
const blocking = !nonModal || sheet;
|
|
746
420
|
const [chosen, remember] = useRememberedWidth(id ?? labelledBy);
|
|
747
|
-
const canResize = nonModal && resizable && position !== "bottom";
|
|
421
|
+
const canResize = !sheet && nonModal && resizable && position !== "bottom";
|
|
748
422
|
const effectiveWidth = canResize && chosen !== null ? `${chosen}px` : width;
|
|
749
423
|
const minPx = pxOf(width) ?? 320;
|
|
750
424
|
const maxPx = () => pxOf(maxWidth) ?? defaultMaxWidth(container instanceof Element ? container : null);
|
|
@@ -754,40 +428,104 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
754
428
|
const panelRef = useRef(null);
|
|
755
429
|
const [mounted, setMounted] = useState(open);
|
|
756
430
|
const [hidden, setHidden] = useState(!open);
|
|
431
|
+
const [snapIdx, setSnapIdx] = useState(0);
|
|
432
|
+
const [dragOffset, setDragOffset] = useState(0);
|
|
433
|
+
const [dragging, setDragging] = useState(false);
|
|
434
|
+
const dragStartY = useRef(0);
|
|
435
|
+
const startHeight = useRef(0);
|
|
757
436
|
const onCloseRef = useLatest(onClose);
|
|
437
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
438
|
+
if (open !== prevOpen) {
|
|
439
|
+
setPrevOpen(open);
|
|
440
|
+
if (open) {
|
|
441
|
+
setSnapIdx(0);
|
|
442
|
+
setDragOffset(0);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
758
445
|
if (open && !mounted) setMounted(true);
|
|
759
446
|
if (open && hidden) setHidden(false);
|
|
760
447
|
const isTopLayer = useOverlayLayer(open);
|
|
761
448
|
useEffect(() => {
|
|
762
|
-
if (!open ||
|
|
449
|
+
if (!open || !blocking) return;
|
|
763
450
|
const onKeyDown = (e) => {
|
|
764
451
|
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
765
452
|
e.preventDefault();
|
|
766
453
|
onCloseRef.current();
|
|
767
454
|
};
|
|
768
455
|
document.addEventListener("keydown", onKeyDown);
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
456
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
457
|
+
}, [open, blocking, onCloseRef, isTopLayer]);
|
|
458
|
+
useEffect(() => {
|
|
459
|
+
if (!open || !blocking || container) return;
|
|
460
|
+
lockBodyScroll();
|
|
461
|
+
return () => unlockBodyScroll();
|
|
462
|
+
}, [open, blocking, container]);
|
|
775
463
|
useReturnFocus(open && !nonModal, panelRef);
|
|
776
|
-
useFocusTrap(panelRef, open &&
|
|
464
|
+
useFocusTrap(panelRef, open && blocking && (sheet || !topOffset), isTopLayer);
|
|
777
465
|
useEffect(() => {
|
|
778
466
|
if (!open || !mounted || nonModal) return;
|
|
779
467
|
const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
|
|
780
468
|
return () => cancelAnimationFrame(raf);
|
|
781
469
|
}, [open, mounted, nonModal]);
|
|
782
470
|
useNonModalDialog(panelRef, open && mounted && nonModal, onClose, isTopLayer);
|
|
471
|
+
const wasBlocking = useRef(blocking);
|
|
472
|
+
useEffect(() => {
|
|
473
|
+
const was = wasBlocking.current;
|
|
474
|
+
wasBlocking.current = blocking;
|
|
475
|
+
if (!open || !mounted || !blocking || was) return;
|
|
476
|
+
const panel = panelRef.current;
|
|
477
|
+
if (panel && !panel.contains(document.activeElement)) focusInitial(panel);
|
|
478
|
+
}, [open, mounted, blocking]);
|
|
479
|
+
const bodyRef = useScrollbarInset();
|
|
783
480
|
useCloseSettle(open, panelRef, () => {
|
|
784
481
|
if (keepMounted) setHidden(true);
|
|
785
482
|
else setMounted(false);
|
|
786
483
|
});
|
|
484
|
+
const viewportHeight = useCallback(
|
|
485
|
+
() => container instanceof HTMLElement ? container.clientHeight : window.innerHeight,
|
|
486
|
+
[container]
|
|
487
|
+
);
|
|
488
|
+
const handlePointerDown = useCallback((e) => {
|
|
489
|
+
setDragging(true);
|
|
490
|
+
dragStartY.current = e.clientY;
|
|
491
|
+
startHeight.current = (snapPoints[snapIdx] ?? snapPoints[0]) * viewportHeight();
|
|
492
|
+
setDragOffset(0);
|
|
493
|
+
e.target.setPointerCapture(e.pointerId);
|
|
494
|
+
}, [snapIdx, snapPoints, viewportHeight]);
|
|
495
|
+
const handlePointerMove = useCallback((e) => {
|
|
496
|
+
if (!dragging) return;
|
|
497
|
+
setDragOffset(dragStartY.current - e.clientY);
|
|
498
|
+
}, [dragging]);
|
|
499
|
+
const handlePointerUp = useCallback(() => {
|
|
500
|
+
if (!dragging) return;
|
|
501
|
+
setDragging(false);
|
|
502
|
+
const currentFraction = (startHeight.current + dragOffset) / viewportHeight();
|
|
503
|
+
if (currentFraction < snapPoints[0] * 0.6) {
|
|
504
|
+
onClose();
|
|
505
|
+
setDragOffset(0);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
let bestIdx = 0;
|
|
509
|
+
let bestDist = Math.abs(currentFraction - snapPoints[0]);
|
|
510
|
+
for (let i = 1; i < snapPoints.length; i++) {
|
|
511
|
+
const dist = Math.abs(currentFraction - snapPoints[i]);
|
|
512
|
+
if (dist < bestDist) {
|
|
513
|
+
bestDist = dist;
|
|
514
|
+
bestIdx = i;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
setSnapIdx(bestIdx);
|
|
518
|
+
setDragOffset(0);
|
|
519
|
+
}, [dragging, dragOffset, snapPoints, onClose, viewportHeight]);
|
|
787
520
|
if (!mounted) return null;
|
|
788
521
|
const slide = slideClasses[position];
|
|
789
522
|
const isHorizontal = position === "left" || position === "right";
|
|
790
523
|
const positionClass = container ? "absolute" : "fixed";
|
|
524
|
+
const offset = sheet ? void 0 : topOffset;
|
|
525
|
+
const baseHeight = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;
|
|
526
|
+
const heightUnit = container ? "%" : "vh";
|
|
527
|
+
const dragPx = dragging ? dragOffset : 0;
|
|
528
|
+
const heading = "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate";
|
|
791
529
|
return createPortal(
|
|
792
530
|
/* @__PURE__ */ jsxs(
|
|
793
531
|
"div",
|
|
@@ -797,17 +535,17 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
797
535
|
`${positionClass} transition-opacity duration-[var(--ds-transition-speed)]`,
|
|
798
536
|
// A non-modal panel never intercepts the page: the wrapper is inert to the
|
|
799
537
|
// pointer and only the panel itself accepts events.
|
|
800
|
-
|
|
801
|
-
|
|
538
|
+
blocking ? cn("z-[var(--ds-z-modal)]", open ? "pointer-events-auto" : "pointer-events-none") : "z-[var(--ds-z-overlay)] pointer-events-none",
|
|
539
|
+
offset ? "left-0 right-0 bottom-0" : "inset-0"
|
|
802
540
|
),
|
|
803
|
-
style:
|
|
541
|
+
style: offset ? { top: offset } : void 0,
|
|
804
542
|
children: [
|
|
805
|
-
|
|
543
|
+
blocking && /* @__PURE__ */ jsx(
|
|
806
544
|
"div",
|
|
807
545
|
{
|
|
808
546
|
className: cn(
|
|
809
547
|
"absolute inset-0 transition-opacity duration-[var(--ds-transition-speed)]",
|
|
810
|
-
lightBackdrop ? "bg-black/15" : cn("bg-black/50", "[backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]"),
|
|
548
|
+
sheet ? "bg-black/50" : lightBackdrop ? "bg-black/15" : cn("bg-black/50", "[backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]"),
|
|
811
549
|
open ? "opacity-100" : "opacity-0"
|
|
812
550
|
),
|
|
813
551
|
onClick: onClose
|
|
@@ -819,11 +557,15 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
819
557
|
ref: panelRef,
|
|
820
558
|
id,
|
|
821
559
|
role: "dialog",
|
|
822
|
-
"data-gs": "drawer",
|
|
560
|
+
"data-gs": sheet ? "sheet" : "drawer",
|
|
561
|
+
"data-ds-sheet": sheet ? "" : void 0,
|
|
823
562
|
...{ [OVERLAY_ROOT_ATTR]: "" },
|
|
824
|
-
"aria-modal":
|
|
563
|
+
"aria-modal": blocking ? "true" : void 0,
|
|
825
564
|
"aria-labelledby": title ? titleId : labelledBy,
|
|
826
|
-
style: {
|
|
565
|
+
style: sheet ? {
|
|
566
|
+
containerType: "inline-size",
|
|
567
|
+
height: dragPx ? `calc(${baseHeight}${heightUnit} + ${dragPx}px)` : `${baseHeight}${heightUnit}`
|
|
568
|
+
} : {
|
|
827
569
|
containerType: "inline-size",
|
|
828
570
|
width: isHorizontal ? effectiveWidth : void 0,
|
|
829
571
|
maxWidth: isHorizontal ? "100%" : void 0,
|
|
@@ -832,23 +574,42 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
832
574
|
},
|
|
833
575
|
className: cn(
|
|
834
576
|
`${positionClass} z-10 flex flex-col`,
|
|
835
|
-
|
|
577
|
+
!blocking && "pointer-events-auto",
|
|
836
578
|
OVERLAY_SURFACE,
|
|
837
579
|
"text-[var(--ds-text-primary)]",
|
|
838
580
|
GLASS_OVERLAY,
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
581
|
+
sheet ? cn(
|
|
582
|
+
"bottom-0 left-0 right-0",
|
|
583
|
+
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
584
|
+
"rounded-t-[var(--ds-radius-xl)]",
|
|
585
|
+
!dragging && "transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
586
|
+
open ? "translate-y-0" : "translate-y-full"
|
|
587
|
+
) : cn(
|
|
588
|
+
// flush drops the edge border for children that draw their own (the mobile
|
|
589
|
+
// menu's Sidebar); a non-modal panel has no backdrop to separate it from
|
|
590
|
+
// the page, so it always keeps the border.
|
|
591
|
+
(!flush || nonModal) && borderByPosition[position],
|
|
592
|
+
"transition-transform duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
593
|
+
isHorizontal && position === "left" && "rounded-r-[var(--ds-radius-lg)] overflow-hidden",
|
|
594
|
+
isHorizontal && position === "right" && "rounded-l-[var(--ds-radius-lg)] overflow-hidden",
|
|
595
|
+
!isHorizontal && "rounded-t-[var(--ds-radius-lg)] overflow-hidden",
|
|
596
|
+
(lightBackdrop || nonModal) && "shadow-[var(--ds-shadow-overlay)]",
|
|
597
|
+
slide.panel,
|
|
598
|
+
open ? slide.open : slide.closed
|
|
599
|
+
)
|
|
850
600
|
),
|
|
851
601
|
children: [
|
|
602
|
+
sheet && /* @__PURE__ */ jsx(
|
|
603
|
+
"div",
|
|
604
|
+
{
|
|
605
|
+
className: "flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none",
|
|
606
|
+
onPointerDown: handlePointerDown,
|
|
607
|
+
onPointerMove: handlePointerMove,
|
|
608
|
+
onPointerUp: handlePointerUp,
|
|
609
|
+
onPointerCancel: handlePointerUp,
|
|
610
|
+
children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]" })
|
|
611
|
+
}
|
|
612
|
+
),
|
|
852
613
|
canResize && open && /* @__PURE__ */ jsx(
|
|
853
614
|
ResizeEdge,
|
|
854
615
|
{
|
|
@@ -864,13 +625,13 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
864
625
|
title && /* @__PURE__ */ jsxs(
|
|
865
626
|
"div",
|
|
866
627
|
{
|
|
867
|
-
className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
868
|
-
style: {
|
|
869
|
-
padding:
|
|
628
|
+
className: "flex items-center justify-between gap-ds-3 shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
629
|
+
style: sheet ? { padding: `var(--ds-space-2) ${INSET}` } : {
|
|
630
|
+
padding: `var(--ds-space-3) ${INSET}`,
|
|
870
631
|
minHeight: "calc(var(--ds-space-unit) * 6 + 1.75rem + 2px + var(--ds-border-width))"
|
|
871
632
|
},
|
|
872
633
|
children: [
|
|
873
|
-
titleTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: title, children: /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className:
|
|
634
|
+
!sheet && titleTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: title, children: /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className: heading, children: title }) }) : /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className: heading, children: title }),
|
|
874
635
|
/* @__PURE__ */ jsx(
|
|
875
636
|
"button",
|
|
876
637
|
{
|
|
@@ -888,9 +649,10 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
888
649
|
/* @__PURE__ */ jsx(
|
|
889
650
|
"div",
|
|
890
651
|
{
|
|
652
|
+
ref: bodyRef,
|
|
891
653
|
className: "flex-1 overflow-y-auto",
|
|
892
|
-
style: flush ? void 0 : { padding:
|
|
893
|
-
children
|
|
654
|
+
style: flush ? void 0 : { padding: `var(--ds-space-5) ${insetLessScrollbar(INSET)} var(--ds-space-5) ${INSET}` },
|
|
655
|
+
children: /* @__PURE__ */ jsx(SurfaceBoundary, { children })
|
|
894
656
|
}
|
|
895
657
|
),
|
|
896
658
|
confirm,
|
|
@@ -898,7 +660,7 @@ function DrawerPanel({ open, onClose, position = "right", width = "400px", title
|
|
|
898
660
|
"div",
|
|
899
661
|
{
|
|
900
662
|
className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
901
|
-
style: { padding:
|
|
663
|
+
style: { padding: `var(--ds-space-3) ${INSET}` },
|
|
902
664
|
children: footer
|
|
903
665
|
}
|
|
904
666
|
)
|
|
@@ -966,7 +728,8 @@ var AppShell = forwardRef(function AppShell2({
|
|
|
966
728
|
preferences,
|
|
967
729
|
currentPath,
|
|
968
730
|
homePath = "/",
|
|
969
|
-
focus
|
|
731
|
+
focus,
|
|
732
|
+
drawerWidth = "520px"
|
|
970
733
|
}, ref) {
|
|
971
734
|
if (REACT_VERSION_PROBLEM) throw new Error(REACT_VERSION_PROBLEM);
|
|
972
735
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
@@ -1025,10 +788,10 @@ var AppShell = forwardRef(function AppShell2({
|
|
|
1025
788
|
const hasLauncher = !!launcher && !isSmallMobile;
|
|
1026
789
|
const launcherProps = isValidElement(launcher) ? launcher.props : null;
|
|
1027
790
|
const launcherCorner = !hasLauncher ? null : launcherProps?.variant === "ribbon" ? null : launcherProps?.edge === "bottom-left" ? "bottom-left" : launcherProps?.edge === "right" || launcherProps?.edge === "left" || launcherProps?.edge === "bottom" ? null : "bottom-right";
|
|
1028
|
-
return /* @__PURE__ */ jsx(PreferencesContext, { value: preferences ?? null, children: /* @__PURE__ */ jsx(
|
|
791
|
+
return /* @__PURE__ */ jsx(PreferencesContext, { value: preferences ?? null, children: /* @__PURE__ */ jsx(DrawerWidthCtx, { value: drawerWidth, children: /* @__PURE__ */ jsx(
|
|
1029
792
|
AppShellContext,
|
|
1030
793
|
{
|
|
1031
|
-
value: { hasSidebar, hasMobileMenu, hasMobileNav, sidebarOpen, setSidebarOpen, isMobile, isTablet, sidebarCollapsed, setSidebarCollapsed: setUserCollapsed, asideOpen, setAsideOpen, asideSide, asideFloating, setAsideFloating, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome, hasLauncher, launcherCorner, hasFooter, focus: focus ?? null, hasUnsavedChanges: unsavedCount > 0, addUnsavedChanges },
|
|
794
|
+
value: { hasSidebar, hasMobileMenu, hasMobileNav, sidebarOpen, setSidebarOpen, isMobile, isTablet, sidebarCollapsed, setSidebarCollapsed: setUserCollapsed, asideOpen, setAsideOpen, asideSide, asideFloating, setAsideFloating, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome, hasLauncher, launcherCorner, hasFooter, focus: focus ?? null, hasUnsavedChanges: unsavedCount > 0, addUnsavedChanges, drawerWidth },
|
|
1032
795
|
children: /* @__PURE__ */ jsxs("div", { ref: (el) => {
|
|
1033
796
|
setShellEl(el);
|
|
1034
797
|
if (typeof ref === "function") ref(el);
|
|
@@ -1082,7 +845,7 @@ var AppShell = forwardRef(function AppShell2({
|
|
|
1082
845
|
!isSmallMobile && launcher
|
|
1083
846
|
] })
|
|
1084
847
|
}
|
|
1085
|
-
) });
|
|
848
|
+
) }) });
|
|
1086
849
|
});
|
|
1087
850
|
function useCompact(ref, breakpoint, band = 0) {
|
|
1088
851
|
const px = typeof breakpoint === "number" ? breakpoint : readBreakpointPx(breakpoint);
|
|
@@ -1111,6 +874,6 @@ function useElementWidth(ref) {
|
|
|
1111
874
|
return width;
|
|
1112
875
|
}
|
|
1113
876
|
|
|
1114
|
-
export { AppShell,
|
|
1115
|
-
//# sourceMappingURL=chunk-
|
|
1116
|
-
//# sourceMappingURL=chunk-
|
|
877
|
+
export { AppShell, DiscardConfirm, Drawer, DrawerFooterCtx, DrawerPanel, OVERLAY_ROOT_ATTR, OverlayCloseCtx, OverlayMarkCtx, OverlayMarkScope, REACT_VERSION_PROBLEM, ResizeEdge, SkipLink, defaultMaxWidth, insetLessScrollbar, pxOf, useAppShell, useBelow, useCloseSettle, useCompact, useDirtyGuard, useElementWidth, useOverlayMark, useRememberedWidth, useScrollbarInset, useUnsavedChanges };
|
|
878
|
+
//# sourceMappingURL=chunk-6PL7FXYH.js.map
|
|
879
|
+
//# sourceMappingURL=chunk-6PL7FXYH.js.map
|