gridsmith-ui 0.20.0 → 0.21.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/{chunk-6MXHGH3D.js → chunk-GGVASDXT.js} +90 -14
- package/dist/chunk-GGVASDXT.js.map +1 -0
- package/dist/{chunk-JXANCXK6.js → chunk-RT7RYGC3.js} +39 -4
- package/dist/chunk-RT7RYGC3.js.map +1 -0
- package/dist/editor.d.ts +6 -5
- package/dist/editor.js +47 -11
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +26 -14
- package/dist/index.js +408 -244
- package/dist/index.js.map +1 -1
- package/dist/resizable.js +6 -6
- package/dist/resizable.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6MXHGH3D.js.map +0 -1
- package/dist/chunk-JXANCXK6.js.map +0 -1
- package/dist/chunk-XVB55M3N.js +0 -42
- package/dist/chunk-XVB55M3N.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { Button, useAppShell, REACT_VERSION_PROBLEM, ControlSizeContext, useOverlayMark, useDirtyGuard,
|
|
2
|
-
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-
|
|
1
|
+
import { Button, useAppShell, REACT_VERSION_PROBLEM, ControlSizeContext, triggerType, useOverlayMark, useDirtyGuard, OverlayMarkScope, OverlayCloseCtx, DiscardConfirm, OVERLAY_ROOT_ATTR, Spinner, OverlayMarkCtx, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-GGVASDXT.js';
|
|
2
|
+
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-GGVASDXT.js';
|
|
3
3
|
import { Skeleton, TITLE_TEXT } from './chunk-NCIZQYXQ.js';
|
|
4
4
|
export { Skeleton } from './chunk-NCIZQYXQ.js';
|
|
5
|
-
import { useReportedChange, useOptionalFormContext,
|
|
6
|
-
export { useFormContext } from './chunk-
|
|
7
|
-
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, focusAfterRemoval, rovingTabStop, useGridKeyboard, useNonModalDialog, usePressMarks, useReturnFocus, useCloseOnFocusOut } from './chunk-JXANCXK6.js';
|
|
8
|
-
export { useGridKeyboard } from './chunk-JXANCXK6.js';
|
|
5
|
+
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, FormChangeCtx, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, useReportedChange, focusAfterRemoval, useOptionalFormContext, rovingTabStop, useGridKeyboard, FormCtx, useNonModalDialog, usePressMarks, useReturnFocus, useCloseOnFocusOut } from './chunk-RT7RYGC3.js';
|
|
6
|
+
export { useFormContext, useGridKeyboard } from './chunk-RT7RYGC3.js';
|
|
9
7
|
import { Link } from './chunk-EQDR57AM.js';
|
|
10
8
|
export { CodeBlock, Divider, Link } from './chunk-EQDR57AM.js';
|
|
11
9
|
import { Badge } from './chunk-XYDIBW3J.js';
|
|
@@ -84,6 +82,7 @@ function DropdownMenu({ trigger, items, align = "end", className, container }) {
|
|
|
84
82
|
/* @__PURE__ */ jsx(
|
|
85
83
|
Slot,
|
|
86
84
|
{
|
|
85
|
+
...triggerType(trigger),
|
|
87
86
|
ref: triggerRef,
|
|
88
87
|
onClick: () => {
|
|
89
88
|
setOpen(!open);
|
|
@@ -180,13 +179,14 @@ function BulkActionBar({ selectedCount, actions, onClearSelection, className })
|
|
|
180
179
|
isMobile ? /* @__PURE__ */ jsx(
|
|
181
180
|
DropdownMenu,
|
|
182
181
|
{
|
|
183
|
-
trigger: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", iconLeft: /* @__PURE__ */ jsx(Icon, { name: "more-vertical", size: 14 }), children: "Actions" }),
|
|
182
|
+
trigger: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", iconLeft: /* @__PURE__ */ jsx(Icon, { name: "more-vertical", size: 14 }), children: "Actions" }),
|
|
184
183
|
items: dropdownItems,
|
|
185
184
|
align: "start"
|
|
186
185
|
}
|
|
187
186
|
) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2", children: actions.map((action, i) => /* @__PURE__ */ jsx(
|
|
188
187
|
Button,
|
|
189
188
|
{
|
|
189
|
+
type: "button",
|
|
190
190
|
variant: "secondary",
|
|
191
191
|
size: "sm",
|
|
192
192
|
onClick: action.onClick,
|
|
@@ -208,6 +208,7 @@ function BulkActionBar({ selectedCount, actions, onClearSelection, className })
|
|
|
208
208
|
}
|
|
209
209
|
);
|
|
210
210
|
}
|
|
211
|
+
var UNCONTROLLED = /* @__PURE__ */ Symbol("uncontrolled");
|
|
211
212
|
var valueOf = (e) => {
|
|
212
213
|
const t = e.target;
|
|
213
214
|
if (!t) return void 0;
|
|
@@ -226,7 +227,7 @@ var INPUT_TEXT = {
|
|
|
226
227
|
function Input({ className, size: sizeProp, error = false, prefix, suffix, ...props }) {
|
|
227
228
|
const contextSize = useContext(ControlSizeContext);
|
|
228
229
|
const size = sizeProp ?? contextSize ?? "md";
|
|
229
|
-
const onChange = useReportedChange(props.onChange, props.value, valueOf);
|
|
230
|
+
const onChange = useReportedChange(props.onChange, props.value === void 0 ? UNCONTROLLED : props.value, valueOf);
|
|
230
231
|
const borderColor = error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]";
|
|
231
232
|
const hoverBorder = !error && !props.disabled && !props.readOnly ? "hover:border-[var(--ds-input-border-hover)]" : "";
|
|
232
233
|
if (prefix || suffix) {
|
|
@@ -298,7 +299,7 @@ function Input({ className, size: sizeProp, error = false, prefix, suffix, ...pr
|
|
|
298
299
|
);
|
|
299
300
|
}
|
|
300
301
|
function Textarea({ className, autoResize, maxRows, error = false, ref, ...props }) {
|
|
301
|
-
const onChange = useReportedChange(props.onChange, props.value, valueOf);
|
|
302
|
+
const onChange = useReportedChange(props.onChange, props.value === void 0 ? UNCONTROLLED : props.value, valueOf);
|
|
302
303
|
const internalRef = useRef(null);
|
|
303
304
|
const textareaRef = ref ?? internalRef;
|
|
304
305
|
const resize = useCallback(() => {
|
|
@@ -1175,10 +1176,11 @@ var CHECKBOX_SIZES = {
|
|
|
1175
1176
|
sm: { box: "h-[16px] w-[16px]", glyph: 10, label: "text-xs" },
|
|
1176
1177
|
md: { box: "h-[18px] w-[18px]", glyph: 12, label: "text-sm" }
|
|
1177
1178
|
};
|
|
1178
|
-
function Checkbox({ checked, onChange: onChangeProp, label, size = "md", disabled = false, indeterminate = false, className, ref }) {
|
|
1179
|
+
function Checkbox({ checked, onChange: onChangeProp, label, size = "md", disabled = false, indeterminate = false, className, ref, ...wiring }) {
|
|
1179
1180
|
const onChange = useReportedChange(onChangeProp, checked);
|
|
1180
1181
|
const internalRef = useRef(null);
|
|
1181
1182
|
const dims = CHECKBOX_SIZES[size];
|
|
1183
|
+
const control = useFieldControl(wiring);
|
|
1182
1184
|
const mergedRef = useCallback(
|
|
1183
1185
|
(node) => {
|
|
1184
1186
|
internalRef.current = node;
|
|
@@ -1206,6 +1208,11 @@ function Checkbox({ checked, onChange: onChangeProp, label, size = "md", disable
|
|
|
1206
1208
|
{
|
|
1207
1209
|
ref: mergedRef,
|
|
1208
1210
|
type: "checkbox",
|
|
1211
|
+
id: control.id,
|
|
1212
|
+
"aria-labelledby": wiring["aria-labelledby"],
|
|
1213
|
+
"aria-describedby": control.describedBy,
|
|
1214
|
+
"aria-invalid": control.invalid || void 0,
|
|
1215
|
+
required: control.required || void 0,
|
|
1209
1216
|
checked,
|
|
1210
1217
|
disabled,
|
|
1211
1218
|
onChange: (e) => onChange(e.target.checked),
|
|
@@ -1268,10 +1275,11 @@ function CheckboxGroupItem({ value, label, disabled, groupValue, onGroupChange }
|
|
|
1268
1275
|
}
|
|
1269
1276
|
);
|
|
1270
1277
|
}
|
|
1271
|
-
function RadioGroup({ value, onChange: onChangeProp, options, orientation = "vertical", className, label }) {
|
|
1278
|
+
function RadioGroup({ value, onChange: onChangeProp, options, orientation = "vertical", className, label, ...wiring }) {
|
|
1272
1279
|
const onChange = useReportedChange(onChangeProp, value);
|
|
1273
1280
|
const groupRef = useRef(null);
|
|
1274
1281
|
const groupId = useId();
|
|
1282
|
+
const control = useFieldControl(wiring);
|
|
1275
1283
|
const enabledOptions = options.filter((o) => !o.disabled);
|
|
1276
1284
|
const tabStop = rovingTabStop(options, (o) => o.value === value, (o) => !!o.disabled);
|
|
1277
1285
|
function handleKeyDown(e) {
|
|
@@ -1301,7 +1309,11 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
1301
1309
|
{
|
|
1302
1310
|
ref: groupRef,
|
|
1303
1311
|
role: "radiogroup",
|
|
1304
|
-
|
|
1312
|
+
id: control.id,
|
|
1313
|
+
"aria-labelledby": label ? groupId : control.labelId,
|
|
1314
|
+
"aria-describedby": control.describedBy,
|
|
1315
|
+
"aria-invalid": control.invalid || void 0,
|
|
1316
|
+
"aria-required": control.required || void 0,
|
|
1305
1317
|
className: cn(
|
|
1306
1318
|
"flex",
|
|
1307
1319
|
orientation === "vertical" ? "flex-col gap-ds-2" : "flex-row flex-wrap gap-ds-3"
|
|
@@ -1796,13 +1808,13 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1796
1808
|
className: "flex items-center justify-between bg-[var(--ds-bg-muted)] rounded-t-[var(--ds-radius-md)]",
|
|
1797
1809
|
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1798
1810
|
children: [
|
|
1799
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: prevMonth, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
1811
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: prevMonth, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
1800
1812
|
/* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: [
|
|
1801
1813
|
MONTHS[month],
|
|
1802
1814
|
" ",
|
|
1803
1815
|
year
|
|
1804
1816
|
] }),
|
|
1805
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: nextMonth, "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
1817
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: nextMonth, "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
1806
1818
|
]
|
|
1807
1819
|
}
|
|
1808
1820
|
),
|
|
@@ -1865,6 +1877,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1865
1877
|
/* @__PURE__ */ jsx(
|
|
1866
1878
|
Button,
|
|
1867
1879
|
{
|
|
1880
|
+
type: "button",
|
|
1868
1881
|
variant: "ghost",
|
|
1869
1882
|
size: "sm",
|
|
1870
1883
|
onClick: () => {
|
|
@@ -1878,6 +1891,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1878
1891
|
value && /* @__PURE__ */ jsx(
|
|
1879
1892
|
Button,
|
|
1880
1893
|
{
|
|
1894
|
+
type: "button",
|
|
1881
1895
|
variant: "ghost",
|
|
1882
1896
|
size: "sm",
|
|
1883
1897
|
onClick: () => choose(null),
|
|
@@ -2264,7 +2278,7 @@ function DateRangePicker({
|
|
|
2264
2278
|
),
|
|
2265
2279
|
style: { top: pos.top, left: pos.left },
|
|
2266
2280
|
children: [
|
|
2267
|
-
presets.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-ds-0.5 p-ds-2 border-r-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] min-w-[140px]", children: presets.map((p) => /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "justify-start", onClick: () => {
|
|
2281
|
+
presets.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-ds-0.5 p-ds-2 border-r-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] min-w-[140px]", children: presets.map((p) => /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "justify-start", onClick: () => {
|
|
2268
2282
|
const r = p.range();
|
|
2269
2283
|
returnFocus();
|
|
2270
2284
|
onChange(r);
|
|
@@ -2273,7 +2287,7 @@ function DateRangePicker({
|
|
|
2273
2287
|
}, children: p.label }, p.label)) }),
|
|
2274
2288
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
2275
2289
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between bg-[var(--ds-bg-muted)] rounded-tr-[var(--ds-radius-md)] px-ds-3 py-ds-2", children: [
|
|
2276
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => pageMonths(-1), "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
2290
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => pageMonths(-1), "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
2277
2291
|
/* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: [
|
|
2278
2292
|
MONTHS2[months[0].getMonth()],
|
|
2279
2293
|
" ",
|
|
@@ -2283,7 +2297,7 @@ function DateRangePicker({
|
|
|
2283
2297
|
" ",
|
|
2284
2298
|
months[1].getFullYear()
|
|
2285
2299
|
] }),
|
|
2286
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => pageMonths(1), "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
2300
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => pageMonths(1), "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
2287
2301
|
] }),
|
|
2288
2302
|
/* @__PURE__ */ jsx("div", { ref: gridRef, onKeyDown: grid.onKeyDown, className: "flex gap-ds-4 px-ds-3 py-ds-2", onMouseLeave: () => setHover(null), children: months.map((m) => /* @__PURE__ */ jsxs("div", { role: "grid", "aria-label": `${MONTHS2[m.getMonth()]} ${m.getFullYear()}`, className: "w-[224px] flex flex-col gap-ds-0.5", children: [
|
|
2289
2303
|
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: dayNames.map((d) => /* @__PURE__ */ jsx("div", { role: "columnheader", className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, d)) }),
|
|
@@ -2324,7 +2338,7 @@ function DateRangePicker({
|
|
|
2324
2338
|
] }, `${m.getFullYear()}-${m.getMonth()}`)) }),
|
|
2325
2339
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center bg-[var(--ds-bg-muted)] border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-br-[var(--ds-radius-md)] px-ds-3 py-ds-2", children: [
|
|
2326
2340
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--ds-text-muted)]", children: value.start && !value.end ? "Now pick an end date" : summary ?? "Pick a start date" }),
|
|
2327
|
-
(value.start || value.end) && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => {
|
|
2341
|
+
(value.start || value.end) && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => {
|
|
2328
2342
|
onChange({ start: null, end: null });
|
|
2329
2343
|
setHover(null);
|
|
2330
2344
|
}, children: "Clear" })
|
|
@@ -2474,6 +2488,21 @@ function Progress({ value, max = 100, variant = "default", size = "md", indeterm
|
|
|
2474
2488
|
] })
|
|
2475
2489
|
] });
|
|
2476
2490
|
}
|
|
2491
|
+
|
|
2492
|
+
// ../../showcase/src/lib/dev-warn.ts
|
|
2493
|
+
var warned = /* @__PURE__ */ new Set();
|
|
2494
|
+
function warnOnce(component, message) {
|
|
2495
|
+
let dev = false;
|
|
2496
|
+
try {
|
|
2497
|
+
dev = process.env.NODE_ENV !== "production";
|
|
2498
|
+
} catch {
|
|
2499
|
+
dev = false;
|
|
2500
|
+
}
|
|
2501
|
+
const text = `${component}: ${message}`;
|
|
2502
|
+
if (!dev || warned.has(text)) return;
|
|
2503
|
+
warned.add(text);
|
|
2504
|
+
console.warn(text);
|
|
2505
|
+
}
|
|
2477
2506
|
function TruncFileName({ children, className }) {
|
|
2478
2507
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
2479
2508
|
const el = /* @__PURE__ */ jsx("p", { ref, className: cn("truncate", className), children });
|
|
@@ -2488,6 +2517,8 @@ function formatSize(bytes) {
|
|
|
2488
2517
|
}
|
|
2489
2518
|
var running = (item) => item.status === "queued" || item.status === "uploading";
|
|
2490
2519
|
var failureOf = (err) => err instanceof Error && err.message ? err.message : "The upload didn't work.";
|
|
2520
|
+
var percentOf = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.min(100, value)) : 0;
|
|
2521
|
+
var STILL_UPLOADING = "Wait for your files to finish uploading";
|
|
2491
2522
|
function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accept, multiple = true, maxSize, className, error = false, label, id }) {
|
|
2492
2523
|
const controlled = files !== void 0;
|
|
2493
2524
|
const [own, setOwn] = useState([]);
|
|
@@ -2508,8 +2539,6 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2508
2539
|
const rejectedId = `${ownId}-rejected`;
|
|
2509
2540
|
const showLabel = label != null && !field;
|
|
2510
2541
|
const constraints = fileConstraints(accept, maxSize, multiple);
|
|
2511
|
-
const invalid = error || rejected != null;
|
|
2512
|
-
const describedBy = [constraints ? constraintsId : null, field?.describedBy, rejected ? rejectedId : null].filter(Boolean).join(" ") || void 0;
|
|
2513
2542
|
const patch = (itemId, change) => setOwn((prev) => prev.map((i) => i.id === itemId ? { ...i, ...change } : i));
|
|
2514
2543
|
const stop = (itemId) => {
|
|
2515
2544
|
controllers.current.get(itemId)?.abort();
|
|
@@ -2531,7 +2560,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2531
2560
|
attempt = Promise.resolve(run(item.file, {
|
|
2532
2561
|
signal: controller.signal,
|
|
2533
2562
|
onProgress: (percent) => {
|
|
2534
|
-
if (!controller.signal.aborted) patch(item.id, { progress:
|
|
2563
|
+
if (!controller.signal.aborted) patch(item.id, { progress: percentOf(percent) });
|
|
2535
2564
|
}
|
|
2536
2565
|
}));
|
|
2537
2566
|
} catch (err) {
|
|
@@ -2539,6 +2568,11 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2539
2568
|
}
|
|
2540
2569
|
attempt.then(() => settle({ status: "done", progress: 100 }), (err) => settle({ status: "error", error: failureOf(err) }));
|
|
2541
2570
|
};
|
|
2571
|
+
const [hadUpload, setHadUpload] = useState(!!upload);
|
|
2572
|
+
if (!controlled && !!upload !== hadUpload) {
|
|
2573
|
+
setHadUpload(!!upload);
|
|
2574
|
+
setOwn((prev) => prev.map((i) => upload ? i.status === "added" && i.file ? { ...i, status: "queued" } : i : i.status === "queued" ? { ...i, status: "error", error: "The upload couldn't start." } : i));
|
|
2575
|
+
}
|
|
2542
2576
|
useEffect(() => {
|
|
2543
2577
|
if (controlled || !upload) return;
|
|
2544
2578
|
let active = own.filter((i) => i.status === "uploading" && controllers.current.has(i.id)).length;
|
|
@@ -2564,31 +2598,67 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2564
2598
|
useEffect(() => {
|
|
2565
2599
|
if (!overlayOpen && !controlled) stopAll();
|
|
2566
2600
|
}, [overlayOpen, controlled, stopAll]);
|
|
2567
|
-
const busy = shown.some(
|
|
2601
|
+
const busy = shown.some((i) => i.status === "uploading" || i.status === "queued" && (controlled || !!upload));
|
|
2568
2602
|
useEffect(() => {
|
|
2569
2603
|
if (!busy || !overlayMark) return;
|
|
2570
2604
|
return overlayMark.hold();
|
|
2571
2605
|
}, [busy, overlayMark]);
|
|
2572
|
-
const
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2606
|
+
const form = useOptionalFormContext();
|
|
2607
|
+
const waitingKey = `${inputId}-uploads`;
|
|
2608
|
+
const waitingId = `${ownId}-waiting`;
|
|
2609
|
+
const busyRef = useLatest(busy);
|
|
2610
|
+
const registerCheck = form?.register;
|
|
2611
|
+
useEffect(() => registerCheck?.(waitingKey, () => busyRef.current ? STILL_UPLOADING : void 0), [registerCheck, waitingKey, busyRef]);
|
|
2612
|
+
const waiting = form?.errors[waitingKey];
|
|
2613
|
+
const clearWaiting = form?.setError;
|
|
2614
|
+
useEffect(() => {
|
|
2615
|
+
if (!busy && waiting) clearWaiting?.(waitingKey, void 0);
|
|
2616
|
+
}, [busy, waiting, clearWaiting, waitingKey]);
|
|
2617
|
+
useEffect(() => {
|
|
2618
|
+
const owner = inputRef.current?.form;
|
|
2619
|
+
if (!owner) return;
|
|
2620
|
+
const clear = () => setRejected(null);
|
|
2621
|
+
owner.addEventListener("submit", clear);
|
|
2622
|
+
return () => owner.removeEventListener("submit", clear);
|
|
2623
|
+
}, []);
|
|
2624
|
+
const invalid = error || rejected != null || !!waiting;
|
|
2625
|
+
const describedBy = [constraints ? constraintsId : null, field?.describedBy, rejected ? rejectedId : null, waiting ? waitingId : null].filter(Boolean).join(" ") || void 0;
|
|
2626
|
+
useEffect(() => {
|
|
2627
|
+
if (controlled && !onFiles) warnOnce("FileUpload", "`files` without `onFiles`: the page's list never gets the files the user picks. Add them in onFiles.");
|
|
2628
|
+
if (controlled && upload) warnOnce("FileUpload", "pass `files` or `upload`, not both: with `files` the page runs the uploads and FileUpload shows them.");
|
|
2629
|
+
if (!onRemove) warnOnce("FileUpload", "no `onRemove`: Remove shows only on a failed file, since the page would still have a file the user removed.");
|
|
2630
|
+
const ids = shown.map((i) => i.id);
|
|
2631
|
+
if (new Set(ids).size !== ids.length) warnOnce("FileUpload", "two files in the list share an id: give each file its own (the same file picked twice is two files).");
|
|
2632
|
+
}, [controlled, onFiles, upload, onRemove, shown]);
|
|
2633
|
+
const [heard, setHeard] = useState({ text: "", n: 0 });
|
|
2634
|
+
const signature2 = shown.map((i) => `${i.id}\0${i.status}`).join("");
|
|
2635
|
+
const [seen, setSeen] = useState(() => ({ signature: signature2, statuses: new Map(shown.map((i) => [i.id, i.status])) }));
|
|
2636
|
+
if (signature2 !== seen.signature) {
|
|
2575
2637
|
const said = [];
|
|
2576
2638
|
for (const item of shown) {
|
|
2577
|
-
const before = seen.get(item.id);
|
|
2639
|
+
const before = seen.statuses.get(item.id);
|
|
2578
2640
|
if (!before || before === item.status) continue;
|
|
2579
2641
|
if (item.status === "done") said.push(`${item.name} uploaded`);
|
|
2580
2642
|
else if (item.status === "error") said.push(`${item.name} didn't upload: ${item.error ?? "the upload failed"}`);
|
|
2581
2643
|
}
|
|
2582
|
-
setSeen(new Map(shown.map((i) => [i.id, i.status])));
|
|
2583
|
-
if (said.length) setHeard(said.join(". "));
|
|
2644
|
+
setSeen({ signature: signature2, statuses: new Map(shown.map((i) => [i.id, i.status])) });
|
|
2645
|
+
if (said.length) setHeard((h) => ({ text: said.join(". "), n: h.n + 1 }));
|
|
2584
2646
|
}
|
|
2585
2647
|
const pendingFocus = useRef(null);
|
|
2648
|
+
const lastAction = useRef(null);
|
|
2586
2649
|
useEffect(() => {
|
|
2587
|
-
const
|
|
2588
|
-
if (
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2650
|
+
const gone = pendingFocus.current;
|
|
2651
|
+
if (gone && !shown.some((i) => i.id === gone.id)) {
|
|
2652
|
+
pendingFocus.current = null;
|
|
2653
|
+
const rows = Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).map((row2) => row2.querySelector("button")).filter((b) => !!b);
|
|
2654
|
+
focusAfterRemoval(rows, gone.index, inputRef.current);
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
const last = lastAction.current;
|
|
2658
|
+
const active = document.activeElement;
|
|
2659
|
+
if (!last || last.el.isConnected || active && active !== document.body) return;
|
|
2660
|
+
const row = Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).find((li) => li.dataset.uploadId === last.id);
|
|
2661
|
+
row?.querySelector("button")?.focus();
|
|
2592
2662
|
}, [shown]);
|
|
2593
2663
|
const addFiles = useCallback(
|
|
2594
2664
|
(fileList) => {
|
|
@@ -2615,7 +2685,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2615
2685
|
);
|
|
2616
2686
|
const indexOf = (item) => shown.findIndex((i) => i.id === item.id);
|
|
2617
2687
|
const cancel = (item) => {
|
|
2618
|
-
pendingFocus.current = indexOf(item);
|
|
2688
|
+
pendingFocus.current = { id: item.id, index: indexOf(item) };
|
|
2619
2689
|
if (!controlled) {
|
|
2620
2690
|
stop(item.id);
|
|
2621
2691
|
setOwn((prev) => prev.filter((i) => i.id !== item.id));
|
|
@@ -2627,7 +2697,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2627
2697
|
onRetry?.(item);
|
|
2628
2698
|
};
|
|
2629
2699
|
const remove = (item) => {
|
|
2630
|
-
pendingFocus.current = indexOf(item);
|
|
2700
|
+
pendingFocus.current = { id: item.id, index: indexOf(item) };
|
|
2631
2701
|
reportChange?.();
|
|
2632
2702
|
if (!controlled) {
|
|
2633
2703
|
stop(item.id);
|
|
@@ -2637,7 +2707,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2637
2707
|
};
|
|
2638
2708
|
const canCancel = !controlled || !!onCancel;
|
|
2639
2709
|
const canRetry = !controlled || !!onRetry;
|
|
2640
|
-
const canRemove = !controlled
|
|
2710
|
+
const canRemove = (item) => !!onRemove || !controlled && item.status === "error";
|
|
2641
2711
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-ds-3", className), children: [
|
|
2642
2712
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-ds-1.5", children: [
|
|
2643
2713
|
showLabel && /* @__PURE__ */ jsx(Label, { htmlFor: inputId, children: label }),
|
|
@@ -2691,14 +2761,20 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2691
2761
|
]
|
|
2692
2762
|
}
|
|
2693
2763
|
),
|
|
2694
|
-
rejected && /* @__PURE__ */ jsx(InlineFieldError, { id: rejectedId, message: rejected, className: "mt-0" })
|
|
2764
|
+
rejected && /* @__PURE__ */ jsx(InlineFieldError, { id: rejectedId, message: rejected, className: "mt-0" }),
|
|
2765
|
+
waiting && /* @__PURE__ */ jsx(InlineFieldError, { id: waitingId, message: waiting, className: "mt-0" })
|
|
2695
2766
|
] }),
|
|
2696
2767
|
shown.length > 0 && /* @__PURE__ */ jsx("ul", { ref: listRef, className: "space-y-ds-2", children: shown.map((item) => {
|
|
2697
|
-
const
|
|
2768
|
+
const progress = percentOf(item.progress);
|
|
2769
|
+
const words = item.status === "queued" ? "Waiting" : item.status === "uploading" ? `${Math.round(progress)}%` : item.status === "done" ? "Uploaded" : item.status === "error" ? "Failed" : null;
|
|
2698
2770
|
return /* @__PURE__ */ jsxs(
|
|
2699
2771
|
"li",
|
|
2700
2772
|
{
|
|
2773
|
+
"data-upload-id": item.id,
|
|
2701
2774
|
"data-upload-status": item.status,
|
|
2775
|
+
onFocus: (e) => {
|
|
2776
|
+
if (e.target instanceof HTMLButtonElement) lastAction.current = { id: item.id, el: e.target };
|
|
2777
|
+
},
|
|
2702
2778
|
className: cn(
|
|
2703
2779
|
"flex items-center gap-ds-3 text-sm",
|
|
2704
2780
|
"border-[length:var(--ds-border-width)]",
|
|
@@ -2711,20 +2787,20 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2711
2787
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2712
2788
|
/* @__PURE__ */ jsx(TruncFileName, { className: "text-[var(--ds-text-primary)]", children: item.name }),
|
|
2713
2789
|
(item.size != null || words) && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-muted)]", children: [item.size != null ? formatSize(item.size) : null, words].filter(Boolean).join(" \xB7 ") }),
|
|
2714
|
-
item.status === "uploading" && /* @__PURE__ */ jsx(Progress, { value:
|
|
2790
|
+
item.status === "uploading" && /* @__PURE__ */ jsx(Progress, { value: progress, size: "sm", label: `Uploading ${item.name}`, className: "mt-ds-1" }),
|
|
2715
2791
|
item.status === "error" && /* @__PURE__ */ jsx("p", { className: "mt-ds-1 text-xs text-[var(--ds-status-error)]", children: item.error ?? "The upload didn't work." })
|
|
2716
2792
|
] }),
|
|
2717
2793
|
item.status === "done" && /* @__PURE__ */ jsx(Icon, { name: "check", size: 16, className: "text-[var(--ds-status-success)] shrink-0", "aria-hidden": "true" }),
|
|
2718
2794
|
running(item) && canCancel && // the visible word starts the name, which says which file (WCAG 2.5.3)
|
|
2719
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => cancel(item), "aria-label": `Cancel ${item.name}`, children: "Cancel" }),
|
|
2720
|
-
item.status === "error" && canRetry && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => retry(item), "aria-label": `Retry ${item.name}`, children: "Retry" }),
|
|
2721
|
-
!running(item) && canRemove && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => remove(item), "aria-label": `Remove ${item.name}`, children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 14 }) })
|
|
2795
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => cancel(item), "aria-label": `Cancel ${item.name}`, children: "Cancel" }),
|
|
2796
|
+
item.status === "error" && canRetry && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => retry(item), "aria-label": `Retry ${item.name}`, children: "Retry" }),
|
|
2797
|
+
!running(item) && canRemove(item) && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => remove(item), "aria-label": `Remove ${item.name}`, children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 14 }) })
|
|
2722
2798
|
]
|
|
2723
2799
|
},
|
|
2724
2800
|
item.id
|
|
2725
2801
|
);
|
|
2726
2802
|
}) }),
|
|
2727
|
-
/* @__PURE__ */ jsx("
|
|
2803
|
+
/* @__PURE__ */ jsx("div", { role: "status", className: "sr-only", children: /* @__PURE__ */ jsx("span", { children: heard.text }, heard.n) })
|
|
2728
2804
|
] });
|
|
2729
2805
|
}
|
|
2730
2806
|
function SliderRange({
|
|
@@ -3418,7 +3494,7 @@ function NumberInput({
|
|
|
3418
3494
|
setFocused(false);
|
|
3419
3495
|
const parsed = parseFloat(draft);
|
|
3420
3496
|
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
3421
|
-
const committed = commitValue(parsed);
|
|
3497
|
+
const committed = commitValue(parsed, draft === String(value));
|
|
3422
3498
|
setDraft(String(committed));
|
|
3423
3499
|
} else {
|
|
3424
3500
|
const fallback = isFinite(min) ? min : 0;
|
|
@@ -3949,11 +4025,13 @@ function Rating({
|
|
|
3949
4025
|
readOnly = false,
|
|
3950
4026
|
size = "md",
|
|
3951
4027
|
className,
|
|
3952
|
-
error = false
|
|
4028
|
+
error = false,
|
|
4029
|
+
...wiring
|
|
3953
4030
|
}) {
|
|
3954
4031
|
const onChange = useReportedChange(onChangeProp, value);
|
|
3955
4032
|
const [hoverValue, setHoverValue] = useState(null);
|
|
3956
4033
|
const displayValue = hoverValue ?? value;
|
|
4034
|
+
const control = useFieldControl({ ...wiring, error: error || void 0 });
|
|
3957
4035
|
const handleClick = useCallback(
|
|
3958
4036
|
(starIdx, isLeftHalf) => {
|
|
3959
4037
|
if (readOnly || !onChangeProp) return;
|
|
@@ -4020,8 +4098,12 @@ function Rating({
|
|
|
4020
4098
|
"div",
|
|
4021
4099
|
{
|
|
4022
4100
|
role: readOnly ? "img" : "radiogroup",
|
|
4023
|
-
|
|
4024
|
-
"aria-
|
|
4101
|
+
id: control.id,
|
|
4102
|
+
"aria-label": readOnly || !control.labelId ? `Rating: ${value} out of ${max}` : void 0,
|
|
4103
|
+
"aria-labelledby": readOnly ? void 0 : control.labelId,
|
|
4104
|
+
"aria-describedby": control.describedBy,
|
|
4105
|
+
"aria-invalid": readOnly ? void 0 : control.invalid || void 0,
|
|
4106
|
+
"aria-required": readOnly ? void 0 : control.required || void 0,
|
|
4025
4107
|
onKeyDown: readOnly ? void 0 : handleKeyDown,
|
|
4026
4108
|
className: cn(
|
|
4027
4109
|
"inline-flex items-center gap-ds-0.5",
|
|
@@ -4431,11 +4513,6 @@ var Alert = forwardRef(function Alert2({
|
|
|
4431
4513
|
}
|
|
4432
4514
|
);
|
|
4433
4515
|
});
|
|
4434
|
-
function controlsOf(form) {
|
|
4435
|
-
if (!form) return "";
|
|
4436
|
-
const controls = form.querySelectorAll("input, select, textarea, [role='combobox'], [role='radiogroup'], [role='checkbox'], [role='switch'], [role='slider'], [role='spinbutton'], [contenteditable='true']");
|
|
4437
|
-
return Array.from(controls).map((el) => el.id || el.getAttribute("name") || el.getAttribute("role") || el.tagName).join("|");
|
|
4438
|
-
}
|
|
4439
4516
|
var isThenable = (value) => !!value && typeof value.then === "function";
|
|
4440
4517
|
function stampFormId(node, formId) {
|
|
4441
4518
|
return Children.map(node, (child) => {
|
|
@@ -4494,29 +4571,18 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4494
4571
|
const pendingFocus = useRef(false);
|
|
4495
4572
|
const onSubmitRef = useLatest(onSubmit);
|
|
4496
4573
|
const overlayMark = useContext(OverlayMarkCtx);
|
|
4497
|
-
const reportChange = overlayMark ? overlayMark.report : null;
|
|
4498
|
-
|
|
4499
|
-
useEffect(() => {
|
|
4500
|
-
if (!savedCheck) return;
|
|
4501
|
-
const form = formRef.current;
|
|
4502
|
-
if (form && !form.querySelector("[aria-invalid='true']") && controlsOf(form) === savedCheck.controls) overlayMark?.clear();
|
|
4503
|
-
}, [savedCheck, overlayMark]);
|
|
4574
|
+
const reportChange = useMemo(() => overlayMark ? () => overlayMark.report(formId) : null, [overlayMark, formId]);
|
|
4575
|
+
useEffect(() => overlayMark?.attach(formId), [overlayMark, formId]);
|
|
4504
4576
|
useEffect(() => {
|
|
4505
4577
|
if (pendingSubmit.current && submitted) {
|
|
4506
4578
|
pendingSubmit.current = false;
|
|
4507
|
-
const
|
|
4508
|
-
const passed = Object.keys(errorsRef.current).length === 0 && !form?.querySelector("[aria-invalid='true']");
|
|
4509
|
-
const controls = controlsOf(form);
|
|
4579
|
+
const answer = overlayMark?.submit(formId, { element: () => formRef.current, failing: () => Object.keys(errorsRef.current).length > 0 });
|
|
4510
4580
|
const result = onSubmitRef.current(errorsRef.current);
|
|
4511
|
-
if (!
|
|
4512
|
-
if (isThenable(result))
|
|
4513
|
-
|
|
4514
|
-
});
|
|
4515
|
-
} else {
|
|
4516
|
-
setSavedCheck({ controls });
|
|
4517
|
-
}
|
|
4581
|
+
if (!answer) return;
|
|
4582
|
+
if (isThenable(result)) void result.then(() => answer.settle("resolved"));
|
|
4583
|
+
else answer.settle("returned");
|
|
4518
4584
|
}
|
|
4519
|
-
}, [submitted, submitCount, errors, errorsRef, onSubmitRef, overlayMark]);
|
|
4585
|
+
}, [submitted, submitCount, errors, errorsRef, onSubmitRef, overlayMark, formId]);
|
|
4520
4586
|
const submittedRef = useLatest(submitted);
|
|
4521
4587
|
const errorSummaryRef = useLatest(errorSummary);
|
|
4522
4588
|
const summaryRef = useRef(null);
|
|
@@ -4601,7 +4667,9 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4601
4667
|
}, []);
|
|
4602
4668
|
const handleSubmit = useCallback(
|
|
4603
4669
|
(e) => {
|
|
4670
|
+
if (e.target !== e.currentTarget) return;
|
|
4604
4671
|
e.preventDefault();
|
|
4672
|
+
e.stopPropagation();
|
|
4605
4673
|
if (checks.current.size > 0) {
|
|
4606
4674
|
const found = /* @__PURE__ */ new Map();
|
|
4607
4675
|
for (const [field, check] of checks.current) found.set(field, check());
|
|
@@ -4645,16 +4713,26 @@ var FOCUSABLE2 = "input:not([disabled]):not([type='hidden']), select:not([disabl
|
|
|
4645
4713
|
function AddAnother({ items, getId, itemName, columns, renderRow, onAdd, onRemove, addLabel = "Add another", label, minItems = 1, maxItems, className }) {
|
|
4646
4714
|
const listRef = useRef(null);
|
|
4647
4715
|
const addRef = useRef(null);
|
|
4716
|
+
const reportChange = useContext(FormChangeCtx);
|
|
4717
|
+
const getIdRef = useLatest(getId);
|
|
4648
4718
|
const pending = useRef(null);
|
|
4649
|
-
const firstFields = () => Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).map((row) => row.querySelector(FOCUSABLE2)).filter((el) => !!el);
|
|
4650
4719
|
useEffect(() => {
|
|
4651
4720
|
const next = pending.current;
|
|
4652
4721
|
if (!next) return;
|
|
4722
|
+
const rows = () => Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []);
|
|
4723
|
+
const firstFields = () => rows().map((row) => row.querySelector(FOCUSABLE2)).filter((el) => !!el);
|
|
4724
|
+
const ids = items.map((item) => getIdRef.current(item));
|
|
4725
|
+
if (next.kind === "remove") {
|
|
4726
|
+
if (ids.includes(next.id)) return;
|
|
4727
|
+
pending.current = null;
|
|
4728
|
+
focusAfterRemoval(firstFields(), next.index, addRef.current);
|
|
4729
|
+
return;
|
|
4730
|
+
}
|
|
4731
|
+
const added = ids.findIndex((id) => !next.before.has(id));
|
|
4732
|
+
if (added === -1) return;
|
|
4653
4733
|
pending.current = null;
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
else focusAfterRemoval(fields, next.index, addRef.current);
|
|
4657
|
-
}, [items]);
|
|
4734
|
+
rows()[added]?.querySelector(FOCUSABLE2)?.focus();
|
|
4735
|
+
}, [items, getIdRef]);
|
|
4658
4736
|
const canRemove = items.length > minItems;
|
|
4659
4737
|
const canAdd = maxItems === void 0 || items.length < maxItems;
|
|
4660
4738
|
const grid = { "--gs-add-another-cols": `repeat(${columns.length}, minmax(0, 1fr)) max-content` };
|
|
@@ -4669,13 +4747,15 @@ function AddAnother({ items, getId, itemName, columns, renderRow, onAdd, onRemov
|
|
|
4669
4747
|
/* @__PURE__ */ jsx(AddAnotherRowCtx.Provider, { value: true, children: renderRow(item, index, (column) => `${column}, ${itemName(index)}`) }),
|
|
4670
4748
|
canRemove && // the visible "Remove" starts its name, which says whose row it removes (WCAG 2.5.3 label in name)
|
|
4671
4749
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Remove ${itemName(index)}`, className: "justify-self-start @min-[30rem]:mt-[calc((var(--ds-control-height-md)-var(--ds-control-height-sm))/2)]", onClick: () => {
|
|
4672
|
-
pending.current = { kind: "remove", index };
|
|
4750
|
+
pending.current = { kind: "remove", id, index };
|
|
4751
|
+
reportChange?.();
|
|
4673
4752
|
onRemove(id);
|
|
4674
4753
|
}, children: "Remove" })
|
|
4675
4754
|
] }, id);
|
|
4676
4755
|
}) }),
|
|
4677
4756
|
canAdd && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { ref: addRef, type: "button", variant: "secondary", onClick: () => {
|
|
4678
|
-
pending.current = { kind: "add" };
|
|
4757
|
+
pending.current = { kind: "add", before: new Set(items.map(getId)) };
|
|
4758
|
+
reportChange?.();
|
|
4679
4759
|
onAdd();
|
|
4680
4760
|
}, children: addLabel }) })
|
|
4681
4761
|
] });
|
|
@@ -4695,7 +4775,7 @@ function TransferList({
|
|
|
4695
4775
|
className,
|
|
4696
4776
|
ref
|
|
4697
4777
|
}) {
|
|
4698
|
-
const onChange = useReportedChange(onChangeProp, selected);
|
|
4778
|
+
const onChange = useReportedChange(onChangeProp, selected, (_available, chosen) => chosen);
|
|
4699
4779
|
const [checkedAvailable, setCheckedAvailable] = useState(/* @__PURE__ */ new Set());
|
|
4700
4780
|
const [checkedSelected, setCheckedSelected] = useState(/* @__PURE__ */ new Set());
|
|
4701
4781
|
const [searchLeft, setSearchLeft] = useState("");
|
|
@@ -8433,66 +8513,70 @@ function TableToolbar({
|
|
|
8433
8513
|
const paged = total !== void 0 && !!pagination && pagination.pageSize > 0 && total > pagination.pageSize;
|
|
8434
8514
|
const countText = total === void 0 ? null : grows ? shown < total ? `Showing ${shown} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${total} ${noun(total)}` : null : paged ? `Showing ${Math.min((pagination.page - 1) * pagination.pageSize + 1, total)}\u2013${Math.min(pagination.page * pagination.pageSize, total)} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${total} ${noun(total)}` : null;
|
|
8435
8515
|
if (!hasControls && countText === null && !hasChips) return null;
|
|
8436
|
-
return
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
placeholder: search.placeholder ?? search.label,
|
|
8443
|
-
value: search.value,
|
|
8444
|
-
size,
|
|
8445
|
-
onChange: (e) => search.onChange(e.target.value),
|
|
8446
|
-
className: cn("flex-1 min-w-[160px]", !searchFills && "max-w-[280px]")
|
|
8447
|
-
}
|
|
8448
|
-
),
|
|
8449
|
-
primaryFilter && (compact ? /* @__PURE__ */ jsx(
|
|
8450
|
-
Dropdown,
|
|
8451
|
-
{
|
|
8452
|
-
"aria-label": primaryFilter.label,
|
|
8453
|
-
options: primaryFilter.options.map((o) => ({ id: o.value, label: o.label })),
|
|
8454
|
-
value: primaryFilter.value,
|
|
8455
|
-
onChange: (v) => primaryFilter.onChange(v),
|
|
8456
|
-
size,
|
|
8457
|
-
className: "w-[150px]"
|
|
8458
|
-
}
|
|
8459
|
-
) : /* @__PURE__ */ jsx(
|
|
8460
|
-
SegmentedControl,
|
|
8461
|
-
{
|
|
8462
|
-
"aria-label": primaryFilter.label,
|
|
8463
|
-
options: primaryFilter.options,
|
|
8464
|
-
value: primaryFilter.value,
|
|
8465
|
-
size,
|
|
8466
|
-
onChange: primaryFilter.onChange
|
|
8467
|
-
}
|
|
8468
|
-
)),
|
|
8469
|
-
(filters || actions) && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-ds-2 justify-end", inPane ? "flex-none" : "flex-1"), children: [
|
|
8470
|
-
filters && /* @__PURE__ */ jsxs(
|
|
8471
|
-
Button,
|
|
8516
|
+
return (
|
|
8517
|
+
// a list's search and filters are how it's viewed, not a form's data: they never mark an overlay's form (0.21.0)
|
|
8518
|
+
/* @__PURE__ */ jsx(FormChangeCtx, { value: null, children: /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-3 min-w-0 mb-ds-3 last:mb-0", className), "data-table-toolbar": "", children: [
|
|
8519
|
+
hasControls && /* @__PURE__ */ jsxs("div", { ref: rowRef, className: "flex items-center gap-ds-2 flex-wrap", children: [
|
|
8520
|
+
search && /* @__PURE__ */ jsx(
|
|
8521
|
+
Input,
|
|
8472
8522
|
{
|
|
8473
|
-
|
|
8523
|
+
"aria-label": search.label,
|
|
8524
|
+
placeholder: search.placeholder ?? search.label,
|
|
8525
|
+
value: search.value,
|
|
8474
8526
|
size,
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
"aria-expanded": open,
|
|
8478
|
-
"aria-controls": filterRowId,
|
|
8479
|
-
className: "mr-auto",
|
|
8480
|
-
children: [
|
|
8481
|
-
"Filters",
|
|
8482
|
-
count > 0 && !open && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "xs", className: "ml-ds-1", children: count })
|
|
8483
|
-
]
|
|
8527
|
+
onChange: (e) => search.onChange(e.target.value),
|
|
8528
|
+
className: cn("flex-1 min-w-[160px]", !searchFills && "max-w-[280px]")
|
|
8484
8529
|
}
|
|
8485
8530
|
),
|
|
8486
|
-
|
|
8531
|
+
primaryFilter && (compact ? /* @__PURE__ */ jsx(
|
|
8532
|
+
Dropdown,
|
|
8533
|
+
{
|
|
8534
|
+
"aria-label": primaryFilter.label,
|
|
8535
|
+
options: primaryFilter.options.map((o) => ({ id: o.value, label: o.label })),
|
|
8536
|
+
value: primaryFilter.value,
|
|
8537
|
+
onChange: (v) => primaryFilter.onChange(v),
|
|
8538
|
+
size,
|
|
8539
|
+
className: "w-[150px]"
|
|
8540
|
+
}
|
|
8541
|
+
) : /* @__PURE__ */ jsx(
|
|
8542
|
+
SegmentedControl,
|
|
8543
|
+
{
|
|
8544
|
+
"aria-label": primaryFilter.label,
|
|
8545
|
+
options: primaryFilter.options,
|
|
8546
|
+
value: primaryFilter.value,
|
|
8547
|
+
size,
|
|
8548
|
+
onChange: primaryFilter.onChange
|
|
8549
|
+
}
|
|
8550
|
+
)),
|
|
8551
|
+
(filters || actions) && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-ds-2 justify-end", inPane ? "flex-none" : "flex-1"), children: [
|
|
8552
|
+
filters && /* @__PURE__ */ jsxs(
|
|
8553
|
+
Button,
|
|
8554
|
+
{
|
|
8555
|
+
type: "button",
|
|
8556
|
+
variant: open ? "secondary" : "outline",
|
|
8557
|
+
size,
|
|
8558
|
+
iconLeft: /* @__PURE__ */ jsx(Icon, { name: "filter", size: iconSize }),
|
|
8559
|
+
onClick: () => setOpen(!open),
|
|
8560
|
+
"aria-expanded": open,
|
|
8561
|
+
"aria-controls": filterRowId,
|
|
8562
|
+
className: "mr-auto",
|
|
8563
|
+
children: [
|
|
8564
|
+
"Filters",
|
|
8565
|
+
count > 0 && !open && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "xs", className: "ml-ds-1", children: count })
|
|
8566
|
+
]
|
|
8567
|
+
}
|
|
8568
|
+
),
|
|
8569
|
+
actions
|
|
8570
|
+
] })
|
|
8571
|
+
] }),
|
|
8572
|
+
filters && open && /* @__PURE__ */ jsx("div", { id: filterRowId, className: "flex items-center gap-ds-3 flex-wrap", children: filters }),
|
|
8573
|
+
(countText !== null || hasChips) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 flex-wrap", children: [
|
|
8574
|
+
countText !== null && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--ds-text-muted)]", "aria-live": "polite", "data-result-count": "", children: countText }),
|
|
8575
|
+
activeFilters?.map((f) => /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "subtle", onRemove: f.onRemove, children: f.label }, f.id)),
|
|
8576
|
+
hasChips && onClearAll && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: onClearAll, children: "Clear all" })
|
|
8487
8577
|
] })
|
|
8488
|
-
] })
|
|
8489
|
-
|
|
8490
|
-
(countText !== null || hasChips) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 flex-wrap", children: [
|
|
8491
|
-
countText !== null && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--ds-text-muted)]", "aria-live": "polite", "data-result-count": "", children: countText }),
|
|
8492
|
-
activeFilters?.map((f) => /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "subtle", onRemove: f.onRemove, children: f.label }, f.id)),
|
|
8493
|
-
hasChips && onClearAll && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClearAll, children: "Clear all" })
|
|
8494
|
-
] })
|
|
8495
|
-
] }) });
|
|
8578
|
+
] }) }) })
|
|
8579
|
+
);
|
|
8496
8580
|
}
|
|
8497
8581
|
var ICON_TEXT_OFFSET = "calc((2rem - 1.25rem) / 2)";
|
|
8498
8582
|
function Marker({ item, vertical }) {
|
|
@@ -8657,6 +8741,8 @@ function CollapsibleTrigger({ children, className }) {
|
|
|
8657
8741
|
if (isValidElement(children)) {
|
|
8658
8742
|
const child = children;
|
|
8659
8743
|
return cloneElement(child, {
|
|
8744
|
+
// a Button trigger in a form toggles; it never submits the form (0.21.0)
|
|
8745
|
+
...triggerType(child),
|
|
8660
8746
|
"aria-expanded": isOpen,
|
|
8661
8747
|
className: cn(child.props.className, className),
|
|
8662
8748
|
onClick: (e) => {
|
|
@@ -9206,7 +9292,7 @@ function ActionsRow({ message, onAction }) {
|
|
|
9206
9292
|
),
|
|
9207
9293
|
children: message.actions.map((a) => {
|
|
9208
9294
|
const { id, label, icon } = resolveAction(a);
|
|
9209
|
-
return /* @__PURE__ */ jsx(Tooltip, { content: label, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": label, onClick: () => run(id), children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 14 }) }) }, id);
|
|
9295
|
+
return /* @__PURE__ */ jsx(Tooltip, { content: label, children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": label, onClick: () => run(id), children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 14 }) }) }, id);
|
|
9210
9296
|
})
|
|
9211
9297
|
}
|
|
9212
9298
|
);
|
|
@@ -9343,12 +9429,13 @@ function ChatInputBar({ onSend, busy, onStop, onAttach, onVoice, placeholder })
|
|
|
9343
9429
|
),
|
|
9344
9430
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-ds-2 pb-ds-1.5", children: [
|
|
9345
9431
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-0.5", children: [
|
|
9346
|
-
onAttach && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Add attachment", onClick: onAttach, className: compact, children: /* @__PURE__ */ jsx(Icon, { name: "paperclip", size: glyph }) }),
|
|
9347
|
-
onVoice && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Voice message", onClick: onVoice, className: compact, children: /* @__PURE__ */ jsx(Icon, { name: "mic", size: glyph }) })
|
|
9432
|
+
onAttach && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Add attachment", onClick: onAttach, className: compact, children: /* @__PURE__ */ jsx(Icon, { name: "paperclip", size: glyph }) }),
|
|
9433
|
+
onVoice && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Voice message", onClick: onVoice, className: compact, children: /* @__PURE__ */ jsx(Icon, { name: "mic", size: glyph }) })
|
|
9348
9434
|
] }),
|
|
9349
|
-
busy ? /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "icon-sm", "aria-label": "Stop generating", onClick: onStop, className: compact, children: /* @__PURE__ */ jsx(Icon, { name: "square", size: glyph }) }) : /* @__PURE__ */ jsx(
|
|
9435
|
+
busy ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "tertiary", size: "icon-sm", "aria-label": "Stop generating", onClick: onStop, className: compact, children: /* @__PURE__ */ jsx(Icon, { name: "square", size: glyph }) }) : /* @__PURE__ */ jsx(
|
|
9350
9436
|
Button,
|
|
9351
9437
|
{
|
|
9438
|
+
type: "button",
|
|
9352
9439
|
variant: text.trim() ? "default" : "ghost",
|
|
9353
9440
|
size: "icon-sm",
|
|
9354
9441
|
"aria-label": "Send message",
|
|
@@ -9462,7 +9549,7 @@ function ChatMessageList({
|
|
|
9462
9549
|
}),
|
|
9463
9550
|
typingUser && /* @__PURE__ */ jsx(TypingIndicator, { name: typingUser })
|
|
9464
9551
|
] }) }),
|
|
9465
|
-
showJump && !empty && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-ds-2 flex justify-center", children: /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "xs", className: "pointer-events-auto rounded-[var(--ds-radius-full)]", onClick: scrollToBottom, children: [
|
|
9552
|
+
showJump && !empty && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-ds-2 flex justify-center", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "secondary", size: "xs", className: "pointer-events-auto rounded-[var(--ds-radius-full)]", onClick: scrollToBottom, children: [
|
|
9466
9553
|
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 }),
|
|
9467
9554
|
"Jump to latest"
|
|
9468
9555
|
] }) })
|
|
@@ -9517,10 +9604,11 @@ function ChatPanel({
|
|
|
9517
9604
|
] }),
|
|
9518
9605
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-ds-1", children: [
|
|
9519
9606
|
actions,
|
|
9520
|
-
onNewConversation && /* @__PURE__ */ jsx(Tooltip, { content: "New conversation", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "New conversation", onClick: onNewConversation, children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 16 }) }) }),
|
|
9607
|
+
onNewConversation && /* @__PURE__ */ jsx(Tooltip, { content: "New conversation", children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "New conversation", onClick: onNewConversation, children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 16 }) }) }),
|
|
9521
9608
|
onExpandedChange && /* @__PURE__ */ jsx(Tooltip, { content: expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
|
|
9522
9609
|
Button,
|
|
9523
9610
|
{
|
|
9611
|
+
type: "button",
|
|
9524
9612
|
variant: "ghost",
|
|
9525
9613
|
size: "icon-sm",
|
|
9526
9614
|
"aria-label": expanded ? "Collapse" : "Expand",
|
|
@@ -9529,7 +9617,7 @@ function ChatPanel({
|
|
|
9529
9617
|
children: /* @__PURE__ */ jsx(Icon, { name: expanded ? "minimize-2" : "maximize-2", size: 16 })
|
|
9530
9618
|
}
|
|
9531
9619
|
) }),
|
|
9532
|
-
/* @__PURE__ */ jsx(Tooltip, { content: "Close", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Close", onClick: onClose, ...{ [OVERLAY_CLOSE_ATTR]: "" }, children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 }) }) })
|
|
9620
|
+
/* @__PURE__ */ jsx(Tooltip, { content: "Close", children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Close", onClick: onClose, ...{ [OVERLAY_CLOSE_ATTR]: "" }, children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 }) }) })
|
|
9533
9621
|
] })
|
|
9534
9622
|
]
|
|
9535
9623
|
}
|
|
@@ -10766,15 +10854,15 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10766
10854
|
const hasHeader = headerNode != null || labelHeader != null;
|
|
10767
10855
|
const bar = toolbar === false ? null : /* @__PURE__ */ jsxs("div", { className: cn("flex shrink-0 flex-wrap items-center gap-ds-1 px-ds-2 py-ds-1.5 border-b-[length:var(--ds-border-width)]", border), children: [
|
|
10768
10856
|
onZoomChange && levels.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10769
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Zoom out", "aria-disabled": !canZoomOut || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(1), children: /* @__PURE__ */ jsx(Icon, { name: "minus", size: 14 }) }),
|
|
10857
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Zoom out", "aria-disabled": !canZoomOut || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(1), children: /* @__PURE__ */ jsx(Icon, { name: "minus", size: 14 }) }),
|
|
10770
10858
|
/* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "min-w-[4.5rem] text-center text-xs text-[var(--ds-text-secondary)]", children: ZOOM_NAMES[scale.zoom] }),
|
|
10771
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Zoom in", "aria-disabled": !canZoomIn || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(-1), children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 14 }) })
|
|
10859
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Zoom in", "aria-disabled": !canZoomIn || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(-1), children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 14 }) })
|
|
10772
10860
|
] }),
|
|
10773
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Previous period", onClick: () => api.page(-1), children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 14 }) }),
|
|
10774
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", disabled: todayAtX === null, onClick: () => {
|
|
10861
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Previous period", onClick: () => api.page(-1), children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 14 }) }),
|
|
10862
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", disabled: todayAtX === null, onClick: () => {
|
|
10775
10863
|
if (todayAtX !== null) setLeft(todayAtX - visibleWidth / 2);
|
|
10776
10864
|
}, children: "Today" }),
|
|
10777
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Next period", onClick: () => api.page(1), children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) }),
|
|
10865
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Next period", onClick: () => api.page(1), children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) }),
|
|
10778
10866
|
toolbar
|
|
10779
10867
|
] });
|
|
10780
10868
|
return (
|
|
@@ -11031,16 +11119,16 @@ var SELECTED = "outline-solid outline-2 outline-offset-2 outline-[var(--ds-text-
|
|
|
11031
11119
|
var UNDATED_INSET = 16;
|
|
11032
11120
|
var NO_GROUPS = [];
|
|
11033
11121
|
var NO_STATUSES = {};
|
|
11034
|
-
var
|
|
11035
|
-
function
|
|
11122
|
+
var warned2 = /* @__PURE__ */ new Set();
|
|
11123
|
+
function warnOnce2(message) {
|
|
11036
11124
|
let dev = false;
|
|
11037
11125
|
try {
|
|
11038
11126
|
dev = process.env.NODE_ENV !== "production";
|
|
11039
11127
|
} catch {
|
|
11040
11128
|
dev = false;
|
|
11041
11129
|
}
|
|
11042
|
-
if (!dev ||
|
|
11043
|
-
|
|
11130
|
+
if (!dev || warned2.has(message)) return;
|
|
11131
|
+
warned2.add(message);
|
|
11044
11132
|
console.warn(`Gantt: ${message}`);
|
|
11045
11133
|
}
|
|
11046
11134
|
function GanttArrows({ arrows, width, height }) {
|
|
@@ -11122,7 +11210,7 @@ function Gantt({
|
|
|
11122
11210
|
const selected = isControlled ? selectedId ?? null : selectedState;
|
|
11123
11211
|
useEffect(() => {
|
|
11124
11212
|
if (overridden !== null) {
|
|
11125
|
-
|
|
11213
|
+
warnOnce2("selectedId was given a value after the Gantt had kept a selection of its own. To control the selection, pass selectedId from the first render (null for none); to let the Gantt keep it, leave selectedId out.");
|
|
11126
11214
|
}
|
|
11127
11215
|
}, [overridden]);
|
|
11128
11216
|
const select = (item) => {
|
|
@@ -11134,8 +11222,8 @@ function Gantt({
|
|
|
11134
11222
|
const phases = useMemo(() => uniqueById(groups), [groups]);
|
|
11135
11223
|
useEffect(() => {
|
|
11136
11224
|
const quoted = (ids) => ids.map((id) => `"${id}"`).join(", ");
|
|
11137
|
-
if (plan.repeated.length)
|
|
11138
|
-
if (phases.repeated.length)
|
|
11225
|
+
if (plan.repeated.length) warnOnce2(`more than one item has the id ${quoted(plan.repeated)}; only the first of each is shown.`);
|
|
11226
|
+
if (phases.repeated.length) warnOnce2(`more than one group has the id ${quoted(phases.repeated)}; only the first of each is shown.`);
|
|
11139
11227
|
}, [plan, phases]);
|
|
11140
11228
|
const tasks = plan.unique;
|
|
11141
11229
|
const extent = useMemo(() => itemsExtent(tasks), [tasks]);
|
|
@@ -12032,14 +12120,17 @@ function TabsRoot(props) {
|
|
|
12032
12120
|
const { tabs, mobile = "scroll" } = props;
|
|
12033
12121
|
const collapseToDropdown = isMobile && (orientation === "responsive" || mobile === "dropdown");
|
|
12034
12122
|
if (collapseToDropdown) {
|
|
12035
|
-
return
|
|
12036
|
-
|
|
12037
|
-
{
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12123
|
+
return (
|
|
12124
|
+
// choosing a tab is navigation, never a change to a form around it (0.21.0)
|
|
12125
|
+
/* @__PURE__ */ jsx(FormChangeCtx, { value: null, children: /* @__PURE__ */ jsx(
|
|
12126
|
+
Dropdown,
|
|
12127
|
+
{
|
|
12128
|
+
options: tabs.filter((t) => !t.disabled).map((t) => ({ id: t.id, label: t.label, group: t.group })),
|
|
12129
|
+
value: activeTab,
|
|
12130
|
+
onChange: (v) => onTabChange(v),
|
|
12131
|
+
className
|
|
12132
|
+
}
|
|
12133
|
+
) })
|
|
12043
12134
|
);
|
|
12044
12135
|
}
|
|
12045
12136
|
if (effectiveOrientation === "vertical") {
|
|
@@ -12141,7 +12232,7 @@ function SettingsLayout({
|
|
|
12141
12232
|
return (
|
|
12142
12233
|
// gap-x-ds-8 is the rail's gap, unused in one column: the threshold reads the same gap as the row (useColumnGap)
|
|
12143
12234
|
/* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "sidebar", "data-collapsed": "true", className: cn("flex flex-col gap-y-ds-6 gap-x-ds-8", className), children: [
|
|
12144
|
-
/* @__PURE__ */ jsx(
|
|
12235
|
+
/* @__PURE__ */ jsx(FormChangeCtx, { value: null, children: /* @__PURE__ */ jsx(
|
|
12145
12236
|
Dropdown,
|
|
12146
12237
|
{
|
|
12147
12238
|
"aria-label": ariaLabel,
|
|
@@ -12149,7 +12240,7 @@ function SettingsLayout({
|
|
|
12149
12240
|
value,
|
|
12150
12241
|
onChange: (v) => onChange(v)
|
|
12151
12242
|
}
|
|
12152
|
-
),
|
|
12243
|
+
) }),
|
|
12153
12244
|
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: PANEL_CLASSES, style: PANEL_STYLE, children })
|
|
12154
12245
|
] })
|
|
12155
12246
|
);
|
|
@@ -12435,6 +12526,7 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
|
|
|
12435
12526
|
/* @__PURE__ */ jsx(
|
|
12436
12527
|
Slot,
|
|
12437
12528
|
{
|
|
12529
|
+
...triggerType(trigger),
|
|
12438
12530
|
ref: setTriggerNode,
|
|
12439
12531
|
onClick: () => {
|
|
12440
12532
|
setTriggerWidth(triggerRef.current?.offsetWidth);
|
|
@@ -12507,7 +12599,7 @@ function LoadMore({ hasMore, onLoadMore, loadMoreLabel, currentPage, scroll, cla
|
|
|
12507
12599
|
if (!hasMore) return null;
|
|
12508
12600
|
return /* @__PURE__ */ jsxs("div", { "data-ds-pager": "", "data-pagination-mode": scroll ? "infinite-scroll" : "load-more", className: cn("flex flex-col items-center", className), children: [
|
|
12509
12601
|
scroll && /* @__PURE__ */ jsx("div", { ref: marker, "data-load-more-trigger": "", "aria-hidden": "true", className: "h-px w-full" }),
|
|
12510
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onLoadMore, children: loadMoreLabel ?? "Load more" })
|
|
12602
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: onLoadMore, children: loadMoreLabel ?? "Load more" })
|
|
12511
12603
|
] });
|
|
12512
12604
|
}
|
|
12513
12605
|
function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }) {
|
|
@@ -12517,7 +12609,7 @@ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSize
|
|
|
12517
12609
|
return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", "data-ds-pager": "", className: cn("flex flex-wrap items-center gap-ds-3", className), children: [
|
|
12518
12610
|
pageSizeOptions && pageSize != null && onPageSizeChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
12519
12611
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--ds-text-muted)] whitespace-nowrap", children: "Rows per page" }),
|
|
12520
|
-
/* @__PURE__ */ jsx(
|
|
12612
|
+
/* @__PURE__ */ jsx(FormChangeCtx, { value: null, children: /* @__PURE__ */ jsx(
|
|
12521
12613
|
Dropdown,
|
|
12522
12614
|
{
|
|
12523
12615
|
options: pageSizeOptions.map((n) => ({ id: String(n), label: String(n) })),
|
|
@@ -12526,7 +12618,7 @@ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSize
|
|
|
12526
12618
|
size: "sm",
|
|
12527
12619
|
className: "w-[4.5rem]"
|
|
12528
12620
|
}
|
|
12529
|
-
)
|
|
12621
|
+
) })
|
|
12530
12622
|
] }),
|
|
12531
12623
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-1", children: [
|
|
12532
12624
|
/* @__PURE__ */ jsx(
|
|
@@ -13898,6 +13990,16 @@ function useToastOptional() {
|
|
|
13898
13990
|
}
|
|
13899
13991
|
var toastSeq = 0;
|
|
13900
13992
|
var heardSeq = 0;
|
|
13993
|
+
var HEARD_MS = 7e3;
|
|
13994
|
+
var RUN_END_MS = 20;
|
|
13995
|
+
var isThenable2 = (value) => !!value && typeof value.then === "function";
|
|
13996
|
+
function textOf(node) {
|
|
13997
|
+
if (node == null || typeof node === "boolean") return "";
|
|
13998
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
13999
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
14000
|
+
if (typeof node === "object" && "props" in node) return textOf(node.props.children);
|
|
14001
|
+
return "";
|
|
14002
|
+
}
|
|
13901
14003
|
var mergeable = (e) => !e.action && e.variant !== "error";
|
|
13902
14004
|
function fill(entries, slots) {
|
|
13903
14005
|
let shown = entries.filter((e) => e.shown).length;
|
|
@@ -13917,14 +14019,18 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13917
14019
|
const [list, setList] = useState([]);
|
|
13918
14020
|
const entries = useRef([]);
|
|
13919
14021
|
const isMobile = useBreakpoint("sm");
|
|
13920
|
-
const
|
|
14022
|
+
const shownDuringRuns = useRef([]);
|
|
14023
|
+
const showSeq = useRef(0);
|
|
14024
|
+
const runs = useRef(/* @__PURE__ */ new Map());
|
|
14025
|
+
const runSeq = useRef(0);
|
|
13921
14026
|
const [heard, setHeard] = useState([]);
|
|
13922
14027
|
const [hovered, setHovered] = useState(false);
|
|
13923
14028
|
const [focusInside, setFocusInside] = useState(false);
|
|
13924
14029
|
const paused = pauseOnHover && hovered || focusInside;
|
|
13925
14030
|
const stackRef = useRef(null);
|
|
13926
14031
|
const returnTo = useRef(null);
|
|
13927
|
-
const
|
|
14032
|
+
const pressed = useRef(/* @__PURE__ */ new Set());
|
|
14033
|
+
const pointerAt = useRef(0);
|
|
13928
14034
|
const viaKey = useRef(false);
|
|
13929
14035
|
const refocus = useRef(false);
|
|
13930
14036
|
const pendingHeard = useRef(/* @__PURE__ */ new Map());
|
|
@@ -13943,58 +14049,75 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13943
14049
|
entries.current = fill(next, slots);
|
|
13944
14050
|
setList(entries.current);
|
|
13945
14051
|
}, [slots]);
|
|
13946
|
-
|
|
13947
|
-
if (slots !== slotsSeen) {
|
|
13948
|
-
setSlotsSeen(slots);
|
|
14052
|
+
useEffect(() => {
|
|
13949
14053
|
let kept = 0;
|
|
13950
|
-
|
|
14054
|
+
const reslotted = entries.current.map((e) => e.shown && ++kept > slots ? { ...e, shown: false } : e);
|
|
14055
|
+
const next = fill(reslotted, slots);
|
|
14056
|
+
if (next.length === entries.current.length && next.every((e, i) => e === entries.current[i])) return;
|
|
14057
|
+
commit(next);
|
|
14058
|
+
}, [slots, commit]);
|
|
14059
|
+
if (list.every((t) => !t.shown) && (hovered || focusInside)) {
|
|
14060
|
+
setHovered(false);
|
|
14061
|
+
setFocusInside(false);
|
|
13951
14062
|
}
|
|
13952
|
-
|
|
13953
|
-
entries.current = list;
|
|
13954
|
-
}, [list]);
|
|
14063
|
+
const clearTimers = useRef(/* @__PURE__ */ new Set());
|
|
13955
14064
|
const announce = useCallback((entry) => {
|
|
13956
14065
|
pendingHeard.current.set(entry.id, entry);
|
|
13957
14066
|
if (heardTimer.current) return;
|
|
13958
14067
|
heardTimer.current = setTimeout(() => {
|
|
13959
14068
|
heardTimer.current = void 0;
|
|
13960
|
-
const batch = [...pendingHeard.current.values()]
|
|
14069
|
+
const batch = [...pendingHeard.current.values()].map((e) => {
|
|
14070
|
+
const words = textOf(e.message).trim();
|
|
14071
|
+
const sentence = !words || /[.!?…]$/.test(words) ? words : `${words}.`;
|
|
14072
|
+
return { id: `heard-${++heardSeq}`, assertive: e.variant === "error", text: e.action ? `${sentence} Press F8 to reach ${e.action.label}.`.trim() : sentence };
|
|
14073
|
+
}).filter((h) => h.text);
|
|
13961
14074
|
pendingHeard.current.clear();
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
14075
|
+
if (!batch.length) return;
|
|
14076
|
+
setHeard((list2) => [...list2, ...batch].slice(-5));
|
|
14077
|
+
const ids = new Set(batch.map((h) => h.id));
|
|
14078
|
+
const timer = setTimeout(() => {
|
|
14079
|
+
clearTimers.current.delete(timer);
|
|
14080
|
+
setHeard((list2) => list2.filter((h) => !ids.has(h.id)));
|
|
14081
|
+
}, HEARD_MS);
|
|
14082
|
+
clearTimers.current.add(timer);
|
|
13970
14083
|
}, 0);
|
|
13971
14084
|
}, []);
|
|
13972
14085
|
useEffect(() => () => {
|
|
13973
14086
|
if (heardTimer.current) clearTimeout(heardTimer.current);
|
|
14087
|
+
heardTimer.current = void 0;
|
|
14088
|
+
clearTimers.current.forEach(clearTimeout);
|
|
14089
|
+
clearTimers.current.clear();
|
|
13974
14090
|
}, []);
|
|
13975
|
-
const leaving = useCallback(() => {
|
|
13976
|
-
|
|
14091
|
+
const leaving = useCallback((id) => {
|
|
14092
|
+
const stack = stackRef.current;
|
|
14093
|
+
const holder = id === void 0 ? stack : [...stack?.querySelectorAll("[data-toast-id]") ?? []].find((n) => n.getAttribute("data-toast-id") === id);
|
|
14094
|
+
if (!holder?.contains(document.activeElement)) return;
|
|
13977
14095
|
refocus.current = true;
|
|
13978
14096
|
setFocusInside(false);
|
|
13979
14097
|
}, []);
|
|
13980
14098
|
const remove = useCallback((id) => {
|
|
13981
|
-
leaving();
|
|
14099
|
+
leaving(id);
|
|
13982
14100
|
commit(entries.current.filter((t) => t.id !== id));
|
|
13983
14101
|
}, [commit, leaving]);
|
|
13984
14102
|
const dismissAll = useCallback(() => {
|
|
13985
14103
|
leaving();
|
|
13986
14104
|
commit([]);
|
|
13987
14105
|
}, [commit, leaving]);
|
|
14106
|
+
const noteShown = useCallback((id, variant, action, fresh) => {
|
|
14107
|
+
if (runs.current.size) shownDuringRuns.current.push({ seq: ++showSeq.current, at: Date.now(), id, variant, action, fresh });
|
|
14108
|
+
}, []);
|
|
13988
14109
|
const update = useCallback((id, message, options = {}) => {
|
|
13989
14110
|
const list2 = entries.current;
|
|
13990
14111
|
const at = list2.findIndex((t2) => t2.id === id);
|
|
13991
14112
|
if (at === -1) return;
|
|
14113
|
+
pressed.current.delete(id);
|
|
13992
14114
|
const t = list2[at];
|
|
13993
14115
|
const next = [...list2];
|
|
13994
14116
|
next[at] = { ...t, message, variant: options.variant ?? t.variant, duration: options.duration ?? t.duration, action: options.action ?? t.action, actionWindow: options.actionWindow ?? t.actionWindow, key: options.key ?? t.key, version: t.version + 1 };
|
|
13995
14117
|
commit(next);
|
|
13996
14118
|
announce(next[at]);
|
|
13997
|
-
|
|
14119
|
+
noteShown(id, next[at].variant, !!next[at].action, false);
|
|
14120
|
+
}, [commit, announce, noteShown]);
|
|
13998
14121
|
const toast = useCallback((message, options = {}) => {
|
|
13999
14122
|
const list2 = entries.current;
|
|
14000
14123
|
const base = { message, variant: options.variant ?? "default", duration: options.duration ?? duration, action: options.action, actionWindow: options.actionWindow, key: options.key };
|
|
@@ -14003,41 +14126,31 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
14003
14126
|
if (at !== -1) {
|
|
14004
14127
|
const next = [...list2];
|
|
14005
14128
|
next[at] = { ...list2[at], ...base, version: list2[at].version + 1 };
|
|
14006
|
-
|
|
14129
|
+
pressed.current.delete(options.id);
|
|
14007
14130
|
commit(next);
|
|
14008
14131
|
announce(next[at]);
|
|
14132
|
+
noteShown(options.id, base.variant, !!base.action, false);
|
|
14009
14133
|
return options.id;
|
|
14010
14134
|
}
|
|
14011
14135
|
}
|
|
14012
|
-
while (answering.current.length) {
|
|
14013
|
-
const answered = answering.current.shift();
|
|
14014
|
-
const at = list2.findIndex((t) => t.id === answered);
|
|
14015
|
-
if (at === -1) continue;
|
|
14016
|
-
const next = [...list2];
|
|
14017
|
-
next[at] = { ...list2[at], ...base, version: list2[at].version + 1 };
|
|
14018
|
-
createdIds.current.push(answered);
|
|
14019
|
-
commit(next);
|
|
14020
|
-
announce(next[at]);
|
|
14021
|
-
return answered;
|
|
14022
|
-
}
|
|
14023
14136
|
if (coalesce && base.key && mergeable(base)) {
|
|
14024
14137
|
const at = list2.findIndex((t) => t.key === base.key && mergeable(t));
|
|
14025
14138
|
if (at !== -1) {
|
|
14026
14139
|
const next = [...list2];
|
|
14027
14140
|
next[at] = { ...list2[at], ...base, version: list2[at].version + 1 };
|
|
14028
|
-
createdIds.current.push(list2[at].id);
|
|
14029
14141
|
commit(next);
|
|
14030
14142
|
announce(next[at]);
|
|
14143
|
+
noteShown(list2[at].id, base.variant, !!base.action, false);
|
|
14031
14144
|
return list2[at].id;
|
|
14032
14145
|
}
|
|
14033
14146
|
}
|
|
14034
14147
|
const id = options.id ?? `toast-${++toastSeq}`;
|
|
14035
14148
|
const entry = { id, ...base, shown: false, version: 0 };
|
|
14036
|
-
createdIds.current.push(id);
|
|
14037
14149
|
commit([...list2, entry]);
|
|
14038
14150
|
announce(entry);
|
|
14151
|
+
noteShown(id, base.variant, !!base.action, true);
|
|
14039
14152
|
return id;
|
|
14040
|
-
}, [duration, coalesce, commit, announce]);
|
|
14153
|
+
}, [duration, coalesce, commit, announce, noteShown]);
|
|
14041
14154
|
const api = useMemo(() => ({
|
|
14042
14155
|
toast,
|
|
14043
14156
|
success: (m, o) => toast(m, { ...o, variant: "success" }),
|
|
@@ -14059,34 +14172,53 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
14059
14172
|
}
|
|
14060
14173
|
}), [toast, update, remove, dismissAll, duration]);
|
|
14061
14174
|
const ledger = useMemo(() => ({
|
|
14062
|
-
|
|
14063
|
-
|
|
14064
|
-
|
|
14065
|
-
|
|
14066
|
-
|
|
14067
|
-
|
|
14068
|
-
|
|
14175
|
+
begin: () => {
|
|
14176
|
+
const run = ++runSeq.current;
|
|
14177
|
+
const overlapped = runs.current.size > 0;
|
|
14178
|
+
if (overlapped) runs.current.forEach((r) => {
|
|
14179
|
+
r.overlapped = true;
|
|
14180
|
+
});
|
|
14181
|
+
runs.current.set(run, { from: showSeq.current, overlapped });
|
|
14182
|
+
return run;
|
|
14183
|
+
},
|
|
14184
|
+
end: (run) => {
|
|
14185
|
+
const watched = runs.current.get(run);
|
|
14186
|
+
runs.current.delete(run);
|
|
14187
|
+
if (!watched) return { problem: false };
|
|
14188
|
+
const during = shownDuringRuns.current.filter((s) => s.seq > watched.from);
|
|
14189
|
+
const oldest = Math.min(...[...runs.current.values()].map((r) => r.from));
|
|
14190
|
+
shownDuringRuns.current = runs.current.size ? shownDuringRuns.current.filter((s) => s.seq > oldest) : [];
|
|
14191
|
+
const problem = during.some((s) => s.variant === "error" || s.variant === "warning");
|
|
14192
|
+
const endedAt = Date.now();
|
|
14193
|
+
const confirmations = during.filter((s) => s.fresh && !s.action && (s.variant === "success" || s.variant === "default"));
|
|
14194
|
+
if (watched.overlapped || confirmations.length !== 1 || endedAt - confirmations[0].at > RUN_END_MS) return { problem };
|
|
14195
|
+
const entry = entries.current.find((t) => t.id === confirmations[0].id);
|
|
14196
|
+
return { problem, own: entry && !entry.action ? { id: entry.id, message: entry.message, variant: entry.variant } : void 0 };
|
|
14197
|
+
},
|
|
14198
|
+
has: (id) => entries.current.some((t) => t.id === id)
|
|
14069
14199
|
}), []);
|
|
14070
14200
|
const pressAction = useCallback((id) => {
|
|
14071
14201
|
const entry = entries.current.find((t) => t.id === id);
|
|
14072
14202
|
if (!entry?.action) return;
|
|
14073
14203
|
const run = entry.action.onClick;
|
|
14074
|
-
leaving();
|
|
14204
|
+
leaving(id);
|
|
14075
14205
|
commit(entries.current.map((t) => t.id === id ? { ...t, action: void 0, actionWindow: void 0, version: t.version + 1 } : t));
|
|
14076
|
-
|
|
14206
|
+
pressed.current.add(id);
|
|
14077
14207
|
const done = () => {
|
|
14078
|
-
|
|
14079
|
-
|
|
14080
|
-
|
|
14081
|
-
|
|
14208
|
+
if (pressed.current.delete(id)) remove(id);
|
|
14209
|
+
};
|
|
14210
|
+
const failed = (err) => {
|
|
14211
|
+
done();
|
|
14212
|
+
console.error(err);
|
|
14082
14213
|
};
|
|
14083
14214
|
let result;
|
|
14084
14215
|
try {
|
|
14085
14216
|
result = run();
|
|
14086
|
-
} catch {
|
|
14087
|
-
|
|
14217
|
+
} catch (err) {
|
|
14218
|
+
failed(err);
|
|
14219
|
+
return;
|
|
14088
14220
|
}
|
|
14089
|
-
if (result
|
|
14221
|
+
if (isThenable2(result)) result.then(done, failed);
|
|
14090
14222
|
else done();
|
|
14091
14223
|
}, [commit, leaving, remove]);
|
|
14092
14224
|
const lapse = useCallback((id) => {
|
|
@@ -14120,8 +14252,11 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
14120
14252
|
const back = returnTo.current;
|
|
14121
14253
|
const next = stackRef.current?.querySelector("button");
|
|
14122
14254
|
const main = document.querySelector("main");
|
|
14255
|
+
const byPointer = Date.now() - pointerAt.current < 1e3;
|
|
14123
14256
|
if (back?.isConnected) back.focus();
|
|
14124
|
-
else if (
|
|
14257
|
+
else if (byPointer) {
|
|
14258
|
+
if (stackRef.current?.contains(document.activeElement)) document.activeElement.blur();
|
|
14259
|
+
} else if (next) next.focus();
|
|
14125
14260
|
else if (main) {
|
|
14126
14261
|
if (!main.hasAttribute("tabindex")) {
|
|
14127
14262
|
main.setAttribute("tabindex", "-1");
|
|
@@ -14136,8 +14271,8 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
14136
14271
|
const hasBottomNav = isMobile && bottomNavs > 0;
|
|
14137
14272
|
return /* @__PURE__ */ jsx(ToastContext.Provider, { value: api, children: /* @__PURE__ */ jsxs(ToastLedgerCtx.Provider, { value: ledger, children: [
|
|
14138
14273
|
/* @__PURE__ */ jsx(BottomNavPresenceCtx.Provider, { value: registerBottomNav, children }),
|
|
14139
|
-
/* @__PURE__ */ jsx("div", { className: "sr-only",
|
|
14140
|
-
/* @__PURE__ */ jsx("div", { className: "sr-only",
|
|
14274
|
+
/* @__PURE__ */ jsx("div", { className: "sr-only", "aria-live": "polite", "data-toast-announcer": "polite", children: heard.filter((h) => !h.assertive).map((h) => /* @__PURE__ */ jsx("p", { children: h.text }, h.id)) }),
|
|
14275
|
+
/* @__PURE__ */ jsx("div", { className: "sr-only", "aria-live": "assertive", "data-toast-announcer": "assertive", children: heard.filter((h) => h.assertive).map((h) => /* @__PURE__ */ jsx("p", { children: h.text }, h.id)) }),
|
|
14141
14276
|
shown.length > 0 && createPortal(
|
|
14142
14277
|
/* @__PURE__ */ jsxs(
|
|
14143
14278
|
"div",
|
|
@@ -14150,6 +14285,9 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
14150
14285
|
"data-toast-stack": "",
|
|
14151
14286
|
onMouseEnter: () => setHovered(true),
|
|
14152
14287
|
onMouseLeave: () => setHovered(false),
|
|
14288
|
+
onPointerDownCapture: () => {
|
|
14289
|
+
pointerAt.current = Date.now();
|
|
14290
|
+
},
|
|
14153
14291
|
onFocusCapture: (e) => {
|
|
14154
14292
|
setFocusInside(true);
|
|
14155
14293
|
const from = e.relatedTarget;
|
|
@@ -14166,7 +14304,7 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
14166
14304
|
),
|
|
14167
14305
|
style: hasBottomNav ? { bottom: "calc(var(--ds-space-12) + var(--ds-space-2) + var(--ds-space-4) + env(safe-area-inset-bottom))" } : void 0,
|
|
14168
14306
|
children: [
|
|
14169
|
-
shown.map((t) => /* @__PURE__ */ jsx("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx(
|
|
14307
|
+
shown.map((t) => /* @__PURE__ */ jsx("div", { "data-toast-id": t.id, className: "pointer-events-auto", children: /* @__PURE__ */ jsx(
|
|
14170
14308
|
Toast,
|
|
14171
14309
|
{
|
|
14172
14310
|
inline: true,
|
|
@@ -15963,7 +16101,9 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15963
16101
|
"form",
|
|
15964
16102
|
{
|
|
15965
16103
|
onSubmit: (e) => {
|
|
16104
|
+
if (e.target !== e.currentTarget) return;
|
|
15966
16105
|
e.preventDefault();
|
|
16106
|
+
e.stopPropagation();
|
|
15967
16107
|
if (variant === "destructive") return;
|
|
15968
16108
|
const submitter = e.nativeEvent.submitter;
|
|
15969
16109
|
const implicit = !submitter || submitter === defaultButtonRef.current;
|
|
@@ -15992,6 +16132,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15992
16132
|
{
|
|
15993
16133
|
ref: dialogRef,
|
|
15994
16134
|
role: alert ? "alertdialog" : "dialog",
|
|
16135
|
+
...{ [OVERLAY_ROOT_ATTR]: "" },
|
|
15995
16136
|
"aria-modal": "true",
|
|
15996
16137
|
"data-gs": "dialog",
|
|
15997
16138
|
"aria-labelledby": titleId,
|
|
@@ -16032,7 +16173,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
16032
16173
|
}
|
|
16033
16174
|
),
|
|
16034
16175
|
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description }),
|
|
16035
|
-
children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: /* @__PURE__ */ jsx(
|
|
16176
|
+
children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) }) })
|
|
16036
16177
|
] })
|
|
16037
16178
|
] }) }),
|
|
16038
16179
|
/* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
@@ -16193,7 +16334,7 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
16193
16334
|
}
|
|
16194
16335
|
focus.onExit?.();
|
|
16195
16336
|
};
|
|
16196
|
-
const exitControl = focus ? /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: requestExit, children: focus.exitLabel ?? (focus.kind === "before-app" ? "Save and log out" : "Exit") }) : null;
|
|
16337
|
+
const exitControl = focus ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: requestExit, children: focus.exitLabel ?? (focus.kind === "before-app" ? "Save and log out" : "Exit") }) : null;
|
|
16197
16338
|
const shownUserMenu = focus?.kind === "before-app" ? null : userMenu;
|
|
16198
16339
|
const asking = confirmExit && focus?.kind === "in-app" && !!appShell?.hasUnsavedChanges;
|
|
16199
16340
|
if (confirmExit && !asking) setConfirmExit(false);
|
|
@@ -16209,8 +16350,8 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
16209
16350
|
alert: true,
|
|
16210
16351
|
container: shellEl ?? void 0,
|
|
16211
16352
|
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16212
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setConfirmExit(false), children: "Keep editing" }),
|
|
16213
|
-
/* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => {
|
|
16353
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: () => setConfirmExit(false), children: "Keep editing" }),
|
|
16354
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "destructive", onClick: () => {
|
|
16214
16355
|
setConfirmExit(false);
|
|
16215
16356
|
focus.onExit?.();
|
|
16216
16357
|
}, children: "Discard changes" })
|
|
@@ -17410,42 +17551,65 @@ function useDestructiveAction(options) {
|
|
|
17410
17551
|
};
|
|
17411
17552
|
const failureMessage = (err) => err instanceof Error && err.message ? err.message : `${title.replace(/\?$/, "")} failed. Try again.`;
|
|
17412
17553
|
const done = doneMessage ?? undoMessage ?? pastTenseOf(label);
|
|
17554
|
+
const watch = async (step) => {
|
|
17555
|
+
const run2 = ledger?.begin();
|
|
17556
|
+
try {
|
|
17557
|
+
await step();
|
|
17558
|
+
} catch (err) {
|
|
17559
|
+
if (run2 !== void 0) ledger.end(run2);
|
|
17560
|
+
throw err;
|
|
17561
|
+
}
|
|
17562
|
+
return run2 !== void 0 ? ledger.end(run2) : { problem: false };
|
|
17563
|
+
};
|
|
17413
17564
|
const confirm = async () => {
|
|
17414
17565
|
setBusy(true);
|
|
17415
|
-
const before = ledger?.created() ?? 0;
|
|
17416
17566
|
try {
|
|
17417
|
-
await onConfirm
|
|
17567
|
+
const seen = await watch(onConfirm);
|
|
17418
17568
|
close();
|
|
17419
|
-
if (toast &&
|
|
17569
|
+
if (toast && !seen.problem && !seen.own) toast.success(done);
|
|
17420
17570
|
} catch (err) {
|
|
17421
17571
|
toast?.error(failureMessage(err));
|
|
17422
17572
|
} finally {
|
|
17423
17573
|
setBusy(false);
|
|
17424
17574
|
}
|
|
17425
17575
|
};
|
|
17426
|
-
const undo = async () => {
|
|
17576
|
+
const undo = async (id) => {
|
|
17577
|
+
const here = () => !!toast && (ledger?.has(id) ?? false);
|
|
17427
17578
|
try {
|
|
17428
|
-
await onUndo
|
|
17429
|
-
|
|
17579
|
+
const seen = await watch(onUndo);
|
|
17580
|
+
if (seen.problem) {
|
|
17581
|
+
if (here()) toast.dismiss(id);
|
|
17582
|
+
} else if (seen.own) {
|
|
17583
|
+
if (here()) {
|
|
17584
|
+
toast.update(id, seen.own.message, { variant: seen.own.variant });
|
|
17585
|
+
toast.dismiss(seen.own.id);
|
|
17586
|
+
}
|
|
17587
|
+
} else if (here()) toast.update(id, restoredMessage ?? "Restored", { variant: "success" });
|
|
17588
|
+
else toast?.success(restoredMessage ?? "Restored");
|
|
17430
17589
|
} catch (err) {
|
|
17431
|
-
|
|
17590
|
+
const message = err instanceof Error && err.message ? err.message : "Undo didn't work. Try again.";
|
|
17591
|
+
if (here()) toast.update(id, message, { variant: "error" });
|
|
17592
|
+
else toast?.error(message);
|
|
17432
17593
|
}
|
|
17433
17594
|
};
|
|
17434
17595
|
const run = () => {
|
|
17435
17596
|
if (undoable) {
|
|
17436
17597
|
void (async () => {
|
|
17437
|
-
|
|
17598
|
+
let seen;
|
|
17438
17599
|
try {
|
|
17439
|
-
await onConfirm
|
|
17600
|
+
seen = await watch(onConfirm);
|
|
17440
17601
|
} catch (err) {
|
|
17441
17602
|
toast.error(failureMessage(err));
|
|
17442
17603
|
return;
|
|
17443
17604
|
}
|
|
17605
|
+
if (seen.problem) return;
|
|
17444
17606
|
const seconds = preferences.undoWindowSeconds ?? 5;
|
|
17445
|
-
|
|
17446
|
-
const
|
|
17447
|
-
if (
|
|
17448
|
-
|
|
17607
|
+
let id = "";
|
|
17608
|
+
const undoAction = { label: "Undo", onClick: () => undo(id) };
|
|
17609
|
+
if (seen.own) {
|
|
17610
|
+
id = seen.own.id;
|
|
17611
|
+
toast.update(id, seen.own.message, { action: undoAction, actionWindow: seconds * 1e3 });
|
|
17612
|
+
} else id = toast.success(done, { action: undoAction, actionWindow: seconds * 1e3 });
|
|
17449
17613
|
})();
|
|
17450
17614
|
return;
|
|
17451
17615
|
}
|
|
@@ -17461,8 +17625,8 @@ function useDestructiveAction(options) {
|
|
|
17461
17625
|
description,
|
|
17462
17626
|
variant: "destructive",
|
|
17463
17627
|
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17464
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: close, disabled: busy, children: "Cancel" }),
|
|
17465
|
-
/* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => void confirm(), disabled: !matches2 || busy, loading: busy, children: label })
|
|
17628
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: close, disabled: busy, children: "Cancel" }),
|
|
17629
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "destructive", onClick: () => void confirm(), disabled: !matches2 || busy, loading: busy, children: label })
|
|
17466
17630
|
] }),
|
|
17467
17631
|
children: typedRequired && /* @__PURE__ */ jsx(Field, { label: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17468
17632
|
"Type ",
|
|
@@ -17511,7 +17675,7 @@ var PAST_TENSE = {
|
|
|
17511
17675
|
reject: "Rejected",
|
|
17512
17676
|
decline: "Declined"
|
|
17513
17677
|
};
|
|
17514
|
-
var
|
|
17678
|
+
var warned3 = /* @__PURE__ */ new Set();
|
|
17515
17679
|
function pastTenseOf(label) {
|
|
17516
17680
|
const words = label.trim().toLowerCase().split(/\s+/);
|
|
17517
17681
|
const found = PAST_TENSE[words.slice(0, 2).join(" ")] ?? PAST_TENSE[words[0] ?? ""];
|
|
@@ -17522,8 +17686,8 @@ function pastTenseOf(label) {
|
|
|
17522
17686
|
} catch {
|
|
17523
17687
|
dev = false;
|
|
17524
17688
|
}
|
|
17525
|
-
if (dev && !
|
|
17526
|
-
|
|
17689
|
+
if (dev && !warned3.has(label)) {
|
|
17690
|
+
warned3.add(label);
|
|
17527
17691
|
console.warn(`useDestructiveAction: "${label}" isn't a verb the hook knows; pass doneMessage so the confirmation says what happened.`);
|
|
17528
17692
|
}
|
|
17529
17693
|
return "Done";
|