gridsmith-ui 0.9.2 → 0.11.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-FDIFQ5UF.js → chunk-CR2KF73R.js} +3 -3
- package/dist/{chunk-FDIFQ5UF.js.map → chunk-CR2KF73R.js.map} +1 -1
- package/dist/{chunk-CQADS7JZ.js → chunk-IYD6ZDM2.js} +7 -6
- package/dist/chunk-IYD6ZDM2.js.map +1 -0
- package/dist/{chunk-RLUK575N.js → chunk-NHQCMOAN.js} +4 -3
- package/dist/chunk-NHQCMOAN.js.map +1 -0
- package/dist/{chunk-ENBESZS2.js → chunk-QJBCZ7BR.js} +3 -3
- package/dist/{chunk-ENBESZS2.js.map → chunk-QJBCZ7BR.js.map} +1 -1
- package/dist/chunk-QNVSMY4R.js +17 -0
- package/dist/chunk-QNVSMY4R.js.map +1 -0
- package/dist/{chunk-OVVRMMCO.js → chunk-U2JT37GJ.js} +4 -4
- package/dist/{chunk-OVVRMMCO.js.map → chunk-U2JT37GJ.js.map} +1 -1
- package/dist/{chunk-Z37HO5NU.js → chunk-YMUCTZXS.js} +10 -7
- package/dist/chunk-YMUCTZXS.js.map +1 -0
- package/dist/data-grid.d.ts +7 -1
- package/dist/data-grid.js +18 -9
- package/dist/data-grid.js.map +1 -1
- package/dist/editor.js +1 -1
- package/dist/index.d.ts +133 -10
- package/dist/index.js +686 -138
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +2 -2
- package/dist/resizable.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-CQADS7JZ.js.map +0 -1
- package/dist/chunk-RG4KUCRS.js +0 -9
- package/dist/chunk-RG4KUCRS.js.map +0 -1
- package/dist/chunk-RLUK575N.js.map +0 -1
- package/dist/chunk-Z37HO5NU.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { useAppShell, ControlSizeContext, Button, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, useDirtyGuard, DiscardConfirm, defaultMaxWidth } from './chunk-
|
|
2
|
-
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-
|
|
1
|
+
import { useAppShell, ControlSizeContext, Button, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, useDirtyGuard, DiscardConfirm, defaultMaxWidth } from './chunk-YMUCTZXS.js';
|
|
2
|
+
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-YMUCTZXS.js';
|
|
3
3
|
import { Skeleton } from './chunk-M3AARGLI.js';
|
|
4
4
|
export { Skeleton } from './chunk-M3AARGLI.js';
|
|
5
|
-
import { useOverlayLayer, useCloseOnFocusOut, focusInitial, rovingTabStop, OVERLAY_CLOSE_ATTR, useNonModalDialog, useFocusTrap } from './chunk-
|
|
6
|
-
import { Link } from './chunk-
|
|
7
|
-
export { CodeBlock, Divider, Link } from './chunk-
|
|
8
|
-
import { Badge } from './chunk-
|
|
9
|
-
export { Badge } from './chunk-
|
|
10
|
-
import { inferColumnKinds, CardValue } from './chunk-
|
|
11
|
-
import { SplitPaneCtx, TableCardCtx } from './chunk-
|
|
5
|
+
import { useOverlayLayer, useCloseOnFocusOut, focusInitial, rovingTabStop, OVERLAY_CLOSE_ATTR, useNonModalDialog, useFocusTrap } from './chunk-NHQCMOAN.js';
|
|
6
|
+
import { Link } from './chunk-QJBCZ7BR.js';
|
|
7
|
+
export { CodeBlock, Divider, Link } from './chunk-QJBCZ7BR.js';
|
|
8
|
+
import { Badge } from './chunk-U2JT37GJ.js';
|
|
9
|
+
export { Badge } from './chunk-U2JT37GJ.js';
|
|
10
|
+
import { inferColumnKinds, CardValue } from './chunk-CR2KF73R.js';
|
|
11
|
+
import { SplitPaneCtx, usePreferences, TableCardCtx, preferenceActionKey } from './chunk-QNVSMY4R.js';
|
|
12
|
+
export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-QNVSMY4R.js';
|
|
12
13
|
import { useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
13
14
|
export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
14
|
-
import { useTextOverflow, Tooltip, usePosition } from './chunk-
|
|
15
|
-
export { Tooltip, useTextOverflow } from './chunk-
|
|
15
|
+
import { useTextOverflow, Tooltip, usePosition } from './chunk-IYD6ZDM2.js';
|
|
16
|
+
export { Tooltip, useTextOverflow } from './chunk-IYD6ZDM2.js';
|
|
16
17
|
import { mergeRefs, Slot } from './chunk-PKLVP5ZB.js';
|
|
17
18
|
import { useLatest } from './chunk-WH2FUFAC.js';
|
|
18
19
|
import { Icon } from './chunk-X4CNZFWC.js';
|
|
@@ -1123,6 +1124,36 @@ function RadioGroup({ value, onChange, options, orientation = "vertical", classN
|
|
|
1123
1124
|
)
|
|
1124
1125
|
] });
|
|
1125
1126
|
}
|
|
1127
|
+
|
|
1128
|
+
// ../../showcase/src/lib/segments.ts
|
|
1129
|
+
function stepValue(spec, current, delta) {
|
|
1130
|
+
if (current === null) return delta > 0 ? spec.min : spec.max;
|
|
1131
|
+
const span = spec.max - spec.min + 1;
|
|
1132
|
+
return spec.min + ((current - spec.min + delta) % span + span) % span;
|
|
1133
|
+
}
|
|
1134
|
+
function typeDigit(spec, buffer, digit) {
|
|
1135
|
+
if (!/^\d$/.test(digit)) return { buffer, value: buffer ? Number(buffer) : null, advance: false };
|
|
1136
|
+
let next = buffer + digit;
|
|
1137
|
+
if (next.length > spec.maxDigits || Number(next) > spec.max) next = digit;
|
|
1138
|
+
const n = Number(next);
|
|
1139
|
+
const value = n >= spec.min && n <= spec.max ? n : null;
|
|
1140
|
+
const full = next.length >= spec.maxDigits;
|
|
1141
|
+
const noRoom = n > 0 && n * 10 > spec.max;
|
|
1142
|
+
return { buffer: next, value, advance: full || noRoom };
|
|
1143
|
+
}
|
|
1144
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
1145
|
+
function timeSegments(use24Hour) {
|
|
1146
|
+
return [
|
|
1147
|
+
{ key: "hour", label: "Hours", min: use24Hour ? 0 : 1, max: use24Hour ? 23 : 12, maxDigits: 2, placeholder: "--" },
|
|
1148
|
+
{ key: "minute", label: "Minutes", min: 0, max: 59, maxDigits: 2, placeholder: "--" }
|
|
1149
|
+
];
|
|
1150
|
+
}
|
|
1151
|
+
function dateSegments(dayFirst, daysInMonth = 31) {
|
|
1152
|
+
const day = { key: "day", label: "Day", min: 1, max: daysInMonth, maxDigits: 2, placeholder: "dd" };
|
|
1153
|
+
const month = { key: "month", label: "Month", min: 1, max: 12, maxDigits: 2, placeholder: "mm" };
|
|
1154
|
+
const year = { key: "year", label: "Year", min: 1, max: 9999, maxDigits: 4, placeholder: "yyyy" };
|
|
1155
|
+
return dayFirst ? [day, month, year] : [month, day, year];
|
|
1156
|
+
}
|
|
1126
1157
|
var CONTROL_HEIGHT2 = {
|
|
1127
1158
|
sm: "h-[var(--ds-control-height-sm)]",
|
|
1128
1159
|
md: "h-[var(--ds-control-height-md)]",
|
|
@@ -1160,6 +1191,44 @@ function isSameDay(a, b) {
|
|
|
1160
1191
|
function formatDate(d) {
|
|
1161
1192
|
return `${MONTHS[d.getMonth()].slice(0, 3)} ${d.getDate()}, ${d.getFullYear()}`;
|
|
1162
1193
|
}
|
|
1194
|
+
function localeDayFirst() {
|
|
1195
|
+
try {
|
|
1196
|
+
const parts = new Intl.DateTimeFormat(void 0).formatToParts(new Date(2e3, 11, 25));
|
|
1197
|
+
return parts.findIndex((p) => p.type === "day") < parts.findIndex((p) => p.type === "month");
|
|
1198
|
+
} catch {
|
|
1199
|
+
return true;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
function validDate(year, monthIndex, day) {
|
|
1203
|
+
if (monthIndex < 0 || monthIndex > 11 || day < 1) return null;
|
|
1204
|
+
const d = new Date(year, monthIndex, day);
|
|
1205
|
+
return d.getFullYear() === year && d.getMonth() === monthIndex && d.getDate() === day ? d : null;
|
|
1206
|
+
}
|
|
1207
|
+
function parseTypedDate(text, dayFirst = localeDayFirst()) {
|
|
1208
|
+
const t = text.trim().replace(/\s+/g, " ");
|
|
1209
|
+
if (!t) return null;
|
|
1210
|
+
let m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(t);
|
|
1211
|
+
if (m) return validDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
1212
|
+
const monthIndex = (name) => MONTHS.findIndex((mm) => mm.toLowerCase().startsWith(name.toLowerCase().replace(/\.$/, "")));
|
|
1213
|
+
m = /^([A-Za-z]{3,})\.?\s+(\d{1,2}),?\s+(\d{4})$/.exec(t);
|
|
1214
|
+
if (m) {
|
|
1215
|
+
const mi = monthIndex(m[1]);
|
|
1216
|
+
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[2]));
|
|
1217
|
+
}
|
|
1218
|
+
m = /^(\d{1,2})\s+([A-Za-z]{3,})\.?,?\s+(\d{4})$/.exec(t);
|
|
1219
|
+
if (m) {
|
|
1220
|
+
const mi = monthIndex(m[2]);
|
|
1221
|
+
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[1]));
|
|
1222
|
+
}
|
|
1223
|
+
m = /^(\d{1,2})[/.-](\d{1,2})[/.-](\d{2,4})$/.exec(t);
|
|
1224
|
+
if (m) {
|
|
1225
|
+
const a = Number(m[1]), b = Number(m[2]);
|
|
1226
|
+
const year = m[3].length === 2 ? 2e3 + Number(m[3]) : Number(m[3]);
|
|
1227
|
+
const [day, month] = a > 12 ? [a, b] : b > 12 ? [b, a] : dayFirst ? [a, b] : [b, a];
|
|
1228
|
+
return validDate(year, month - 1, day);
|
|
1229
|
+
}
|
|
1230
|
+
return null;
|
|
1231
|
+
}
|
|
1163
1232
|
function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, range }) {
|
|
1164
1233
|
const contextSize = useContext(ControlSizeContext);
|
|
1165
1234
|
const size = sizeProp ?? contextSize ?? "md";
|
|
@@ -1177,6 +1246,33 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1177
1246
|
const firstDay = getFirstDayOfWeek(year, month);
|
|
1178
1247
|
const today = useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
1179
1248
|
const isTopLayer = useOverlayLayer(open);
|
|
1249
|
+
const prevMonth = () => setViewDate(new Date(year, month - 1, 1));
|
|
1250
|
+
const nextMonth = () => setViewDate(new Date(year, month + 1, 1));
|
|
1251
|
+
const startOf = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
1252
|
+
const isDisabledDay = (d) => !!min && d < startOf(min) || !!max && d > startOf(max);
|
|
1253
|
+
useCloseOnFocusOut(open, triggerRef, panelRef, () => setOpen(false), isTopLayer);
|
|
1254
|
+
useEffect(() => {
|
|
1255
|
+
if (open) requestAnimationFrame(() => focusInitial(panelRef.current));
|
|
1256
|
+
}, [open]);
|
|
1257
|
+
const closeAndRefocus = () => {
|
|
1258
|
+
setOpen(false);
|
|
1259
|
+
focusSegment(0);
|
|
1260
|
+
};
|
|
1261
|
+
const dayFirst = useMemo(() => localeDayFirst(), []);
|
|
1262
|
+
const [segs, setSegs] = useState(() => value ? { day: value.getDate(), month: value.getMonth() + 1, year: value.getFullYear() } : { day: null, month: null, year: null });
|
|
1263
|
+
const [buffers, setBuffers] = useState({});
|
|
1264
|
+
const lastCommitted = useRef(null);
|
|
1265
|
+
useEffect(() => {
|
|
1266
|
+
if (value && value.getTime() === lastCommitted.current) return;
|
|
1267
|
+
setSegs(value ? { day: value.getDate(), month: value.getMonth() + 1, year: value.getFullYear() } : { day: null, month: null, year: null });
|
|
1268
|
+
setBuffers({});
|
|
1269
|
+
}, [value]);
|
|
1270
|
+
const specs = dateSegments(dayFirst, segs.month && segs.year ? getDaysInMonth(segs.year, segs.month - 1) : 31);
|
|
1271
|
+
const segmentRefs = useRef([]);
|
|
1272
|
+
const focusSegment = (i) => {
|
|
1273
|
+
segmentRefs.current[Math.max(0, Math.min(specs.length - 1, i))]?.focus();
|
|
1274
|
+
};
|
|
1275
|
+
const focusSegmentRef = useLatest(focusSegment);
|
|
1180
1276
|
useEffect(() => {
|
|
1181
1277
|
if (!open) return;
|
|
1182
1278
|
const handler = (e) => {
|
|
@@ -1187,7 +1283,7 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1187
1283
|
const keyHandler = (e) => {
|
|
1188
1284
|
if (e.key === "Escape" && isTopLayer()) {
|
|
1189
1285
|
setOpen(false);
|
|
1190
|
-
|
|
1286
|
+
focusSegmentRef.current(0);
|
|
1191
1287
|
}
|
|
1192
1288
|
};
|
|
1193
1289
|
document.addEventListener("mousedown", handler);
|
|
@@ -1196,18 +1292,88 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1196
1292
|
document.removeEventListener("mousedown", handler);
|
|
1197
1293
|
document.removeEventListener("keydown", keyHandler);
|
|
1198
1294
|
};
|
|
1199
|
-
}, [open, isTopLayer]);
|
|
1200
|
-
const
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1295
|
+
}, [open, isTopLayer, focusSegmentRef]);
|
|
1296
|
+
const [typedInvalid, setTypedInvalid] = useState(false);
|
|
1297
|
+
const commitIfComplete = (next) => {
|
|
1298
|
+
if (next.day === null || next.month === null || next.year === null) {
|
|
1299
|
+
setTypedInvalid(false);
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
const d = validDate(next.year, next.month - 1, next.day);
|
|
1303
|
+
const ok = !!d && (!min || d >= min) && (!max || d <= max);
|
|
1304
|
+
setTypedInvalid(!ok);
|
|
1305
|
+
if (d && ok && !(value && isSameDay(value, d))) {
|
|
1306
|
+
lastCommitted.current = d.getTime();
|
|
1307
|
+
onChange(d);
|
|
1308
|
+
setViewDate(d);
|
|
1309
|
+
}
|
|
1310
|
+
};
|
|
1311
|
+
const setSegment = (key, v, commit = true) => {
|
|
1312
|
+
setSegs((cur) => {
|
|
1313
|
+
const next = { ...cur, [key]: v };
|
|
1314
|
+
if (commit) commitIfComplete(next);
|
|
1315
|
+
return next;
|
|
1316
|
+
});
|
|
1317
|
+
};
|
|
1318
|
+
const applyTyped = (text) => {
|
|
1319
|
+
const d = parseTypedDate(text, dayFirst);
|
|
1320
|
+
if (!d) return;
|
|
1321
|
+
const next = { day: d.getDate(), month: d.getMonth() + 1, year: d.getFullYear() };
|
|
1322
|
+
setSegs(next);
|
|
1323
|
+
setBuffers({});
|
|
1324
|
+
commitIfComplete(next);
|
|
1325
|
+
};
|
|
1326
|
+
const onSegmentKeyDown = (e, index, spec) => {
|
|
1327
|
+
const key = e.key;
|
|
1328
|
+
if (key === "Tab" || key === "Shift" || key === "Escape" || key.startsWith("F")) return;
|
|
1329
|
+
e.preventDefault();
|
|
1330
|
+
const k = spec.key;
|
|
1331
|
+
const clearBuffer = () => setBuffers((b) => ({ ...b, [k]: "" }));
|
|
1332
|
+
if (key === "ArrowLeft") {
|
|
1333
|
+
focusSegment(index - 1);
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
if (key === "ArrowRight") {
|
|
1337
|
+
focusSegment(index + 1);
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
if (key === "ArrowUp" || key === "ArrowDown") {
|
|
1341
|
+
clearBuffer();
|
|
1342
|
+
setSegment(k, stepValue(spec, segs[k], key === "ArrowUp" ? 1 : -1));
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
if (key === "Home") {
|
|
1346
|
+
clearBuffer();
|
|
1347
|
+
setSegment(k, spec.min);
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
if (key === "End") {
|
|
1351
|
+
clearBuffer();
|
|
1352
|
+
setSegment(k, spec.max);
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
if (key === "Backspace" || key === "Delete") {
|
|
1356
|
+
if (segs[k] === null && !buffers[k]) {
|
|
1357
|
+
focusSegment(index - 1);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
clearBuffer();
|
|
1361
|
+
setSegment(k, null, false);
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
if (/^\d$/.test(key)) {
|
|
1365
|
+
const r = typeDigit(spec, buffers[k] ?? "", key);
|
|
1366
|
+
setBuffers((b) => ({ ...b, [k]: r.advance ? "" : r.buffer }));
|
|
1367
|
+
setSegment(k, r.value);
|
|
1368
|
+
if (r.advance) focusSegment(index + 1);
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
const shown = (spec) => {
|
|
1372
|
+
const k = spec.key;
|
|
1373
|
+
const b = buffers[k];
|
|
1374
|
+
if (b && segs[k] === null) return b;
|
|
1375
|
+
if (segs[k] === null) return spec.placeholder;
|
|
1376
|
+
return k === "year" ? String(segs[k]) : pad2(segs[k]);
|
|
1211
1377
|
};
|
|
1212
1378
|
const selectDay = (day) => {
|
|
1213
1379
|
const d = new Date(year, month, day);
|
|
@@ -1227,34 +1393,78 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1227
1393
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
1228
1394
|
label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
1229
1395
|
/* @__PURE__ */ jsxs(
|
|
1230
|
-
"
|
|
1396
|
+
"div",
|
|
1231
1397
|
{
|
|
1232
|
-
id: inputId,
|
|
1233
1398
|
ref: triggerRef,
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
"aria-
|
|
1238
|
-
"aria-
|
|
1239
|
-
"aria-
|
|
1399
|
+
"data-date-field": "",
|
|
1400
|
+
role: "group",
|
|
1401
|
+
id: inputId,
|
|
1402
|
+
"aria-label": label ?? "Date",
|
|
1403
|
+
"aria-description": !value ? placeholder : void 0,
|
|
1404
|
+
"aria-invalid": error || typedInvalid || void 0,
|
|
1405
|
+
onPaste: (e) => {
|
|
1406
|
+
const text = e.clipboardData.getData("text");
|
|
1407
|
+
if (text) {
|
|
1408
|
+
e.preventDefault();
|
|
1409
|
+
applyTyped(text);
|
|
1410
|
+
}
|
|
1411
|
+
},
|
|
1240
1412
|
className: cn(
|
|
1241
1413
|
"flex items-center gap-ds-2 w-full",
|
|
1242
1414
|
CONTROL_HEIGHT2[size],
|
|
1243
1415
|
TEXT_SIZE2[size],
|
|
1244
1416
|
"border-[length:var(--ds-border-width)]",
|
|
1245
|
-
error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
1417
|
+
error || typedInvalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
1246
1418
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
1247
1419
|
"shadow-[var(--ds-input-shadow)]",
|
|
1248
|
-
"transition-colors
|
|
1420
|
+
"transition-colors",
|
|
1249
1421
|
"px-ds-3 py-ds-2",
|
|
1250
|
-
!error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
1422
|
+
!error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)] focus-within:border-[var(--ds-input-border-hover)]",
|
|
1251
1423
|
open && ACTIVE_RING,
|
|
1252
1424
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
1253
|
-
|
|
1425
|
+
"text-[var(--ds-text-primary)]"
|
|
1254
1426
|
),
|
|
1255
1427
|
children: [
|
|
1256
|
-
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)]" }),
|
|
1257
|
-
|
|
1428
|
+
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)] shrink-0" }),
|
|
1429
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center min-w-0 flex-1 tabular-nums", onClick: () => focusSegment(0), children: specs.map((spec, i) => {
|
|
1430
|
+
const k = spec.key;
|
|
1431
|
+
return /* @__PURE__ */ jsxs("span", { className: "contents", children: [
|
|
1432
|
+
i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "px-[1px] text-[var(--ds-text-muted)]", children: "/" }),
|
|
1433
|
+
/* @__PURE__ */ jsx(
|
|
1434
|
+
"span",
|
|
1435
|
+
{
|
|
1436
|
+
ref: (el) => {
|
|
1437
|
+
segmentRefs.current[i] = el;
|
|
1438
|
+
},
|
|
1439
|
+
role: "spinbutton",
|
|
1440
|
+
tabIndex: disabled ? -1 : 0,
|
|
1441
|
+
"data-segment": spec.key,
|
|
1442
|
+
"aria-label": spec.label,
|
|
1443
|
+
"aria-valuemin": spec.min,
|
|
1444
|
+
"aria-valuemax": spec.max,
|
|
1445
|
+
"aria-valuenow": segs[k] ?? void 0,
|
|
1446
|
+
"aria-valuetext": segs[k] === null ? "empty" : String(segs[k]),
|
|
1447
|
+
onKeyDown: (e) => onSegmentKeyDown(e, i, spec),
|
|
1448
|
+
onClick: (e) => e.stopPropagation(),
|
|
1449
|
+
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-primary)] cursor-text", segs[k] === null && !buffers[k] && "text-[var(--ds-text-muted)]"),
|
|
1450
|
+
children: shown(spec)
|
|
1451
|
+
}
|
|
1452
|
+
)
|
|
1453
|
+
] }, spec.key);
|
|
1454
|
+
}) }),
|
|
1455
|
+
/* @__PURE__ */ jsx(
|
|
1456
|
+
"button",
|
|
1457
|
+
{
|
|
1458
|
+
type: "button",
|
|
1459
|
+
"aria-label": "Choose a date",
|
|
1460
|
+
"aria-haspopup": "dialog",
|
|
1461
|
+
"aria-expanded": open,
|
|
1462
|
+
onClick: () => !disabled && setOpen(!open),
|
|
1463
|
+
disabled,
|
|
1464
|
+
className: "shrink-0 -mr-ds-1 rounded-[var(--ds-radius-sm)] text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] disabled:cursor-not-allowed",
|
|
1465
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 })
|
|
1466
|
+
}
|
|
1467
|
+
)
|
|
1258
1468
|
]
|
|
1259
1469
|
}
|
|
1260
1470
|
),
|
|
@@ -1292,8 +1502,8 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1292
1502
|
}
|
|
1293
1503
|
),
|
|
1294
1504
|
/* @__PURE__ */ jsxs("div", { style: { padding: "var(--ds-space-2) var(--ds-space-3)" }, children: [
|
|
1295
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-ds-0.5 mb-ds-1", children: DAYS.map((d) => /* @__PURE__ */ jsx("div", { className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, d)) }),
|
|
1296
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-ds-0.5", onMouseLeave: () => setHover(null), children: cells.map((day, i) => {
|
|
1505
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-ds-0.5 mb-ds-1 tabular-nums", children: DAYS.map((d) => /* @__PURE__ */ jsx("div", { className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, d)) }),
|
|
1506
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-ds-0.5 tabular-nums", onMouseLeave: () => setHover(null), children: cells.map((day, i) => {
|
|
1297
1507
|
if (day === null) return /* @__PURE__ */ jsx("div", {}, `empty-${i}`);
|
|
1298
1508
|
const dateObj = new Date(year, month, day);
|
|
1299
1509
|
const isSelected = !!value && isSameDay(dateObj, value);
|
|
@@ -2080,6 +2290,12 @@ function SliderRange({
|
|
|
2080
2290
|
)
|
|
2081
2291
|
] });
|
|
2082
2292
|
}
|
|
2293
|
+
function fromValue(v, use24Hour) {
|
|
2294
|
+
const m = /^(\d{1,2}):(\d{2})$/.exec(v);
|
|
2295
|
+
if (!m) return { hour: null, minute: null, period: null };
|
|
2296
|
+
const h24 = Number(m[1]);
|
|
2297
|
+
return use24Hour ? { hour: h24, minute: Number(m[2]), period: null } : { hour: h24 % 12 === 0 ? 12 : h24 % 12, minute: Number(m[2]), period: h24 >= 12 ? "PM" : "AM" };
|
|
2298
|
+
}
|
|
2083
2299
|
var CONTROL_HEIGHT4 = {
|
|
2084
2300
|
sm: "h-[var(--ds-control-height-sm)]",
|
|
2085
2301
|
md: "h-[var(--ds-control-height-md)]",
|
|
@@ -2105,6 +2321,23 @@ function generateMinutes(step) {
|
|
|
2105
2321
|
for (let m = 0; m < 60; m += step) mins.push(m);
|
|
2106
2322
|
return mins;
|
|
2107
2323
|
}
|
|
2324
|
+
function parseTypedTime(text, use24Hour) {
|
|
2325
|
+
const t = text.trim().toLowerCase().replace(/\s+/g, " ");
|
|
2326
|
+
if (!t) return null;
|
|
2327
|
+
const m = /^(\d{1,2})(?::?(\d{2}))?\s*(a\.?m\.?|p\.?m\.?|a|p)?$/.exec(t);
|
|
2328
|
+
if (!m) return null;
|
|
2329
|
+
let hour = Number(m[1]);
|
|
2330
|
+
const minute = m[2] === void 0 ? 0 : Number(m[2]);
|
|
2331
|
+
const suffix = m[3]?.replace(/\./g, "");
|
|
2332
|
+
if (Number.isNaN(hour) || minute < 0 || minute > 59) return null;
|
|
2333
|
+
if (suffix) {
|
|
2334
|
+
if (hour < 1 || hour > 12) return null;
|
|
2335
|
+
const pm = suffix.startsWith("p");
|
|
2336
|
+
hour = pm ? hour === 12 ? 12 : hour + 12 : hour === 12 ? 0 : hour;
|
|
2337
|
+
} else if (hour > 23) return null;
|
|
2338
|
+
else if (!use24Hour && hour >= 1 && hour <= 12 && m[2] === void 0) ;
|
|
2339
|
+
return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
|
|
2340
|
+
}
|
|
2108
2341
|
function parseTime(value) {
|
|
2109
2342
|
const [h, m] = value.split(":").map(Number);
|
|
2110
2343
|
const hour = isNaN(h) ? 12 : h;
|
|
@@ -2140,25 +2373,6 @@ function TimePicker({
|
|
|
2140
2373
|
const minutes = generateMinutes(minuteStep);
|
|
2141
2374
|
const isTopLayer = useOverlayLayer(open);
|
|
2142
2375
|
useCloseOnFocusOut(open, triggerRef, panelRef, () => setOpen(false), isTopLayer);
|
|
2143
|
-
useEffect(() => {
|
|
2144
|
-
if (!open) return;
|
|
2145
|
-
const handler = (e) => {
|
|
2146
|
-
if (triggerRef.current?.contains(e.target) || panelRef.current?.contains(e.target)) return;
|
|
2147
|
-
setOpen(false);
|
|
2148
|
-
};
|
|
2149
|
-
const keyHandler = (e) => {
|
|
2150
|
-
if (e.key === "Escape" && isTopLayer()) {
|
|
2151
|
-
setOpen(false);
|
|
2152
|
-
triggerRef.current?.focus();
|
|
2153
|
-
}
|
|
2154
|
-
};
|
|
2155
|
-
document.addEventListener("mousedown", handler);
|
|
2156
|
-
document.addEventListener("keydown", keyHandler);
|
|
2157
|
-
return () => {
|
|
2158
|
-
document.removeEventListener("mousedown", handler);
|
|
2159
|
-
document.removeEventListener("keydown", keyHandler);
|
|
2160
|
-
};
|
|
2161
|
-
}, [open, isTopLayer]);
|
|
2162
2376
|
useEffect(() => {
|
|
2163
2377
|
if (!open) return;
|
|
2164
2378
|
const id2 = requestAnimationFrame(() => {
|
|
@@ -2195,20 +2409,148 @@ function TimePicker({
|
|
|
2195
2409
|
}
|
|
2196
2410
|
onChange(`${pad(h24)}:${pad(minute)}`);
|
|
2197
2411
|
}
|
|
2198
|
-
const
|
|
2412
|
+
const specs = timeSegments(use24Hour);
|
|
2413
|
+
const [segs, setSegs] = useState(() => fromValue(value, use24Hour));
|
|
2414
|
+
const [buffers, setBuffers] = useState({});
|
|
2415
|
+
const lastCommitted = useRef(null);
|
|
2416
|
+
useEffect(() => {
|
|
2417
|
+
if (value === lastCommitted.current) return;
|
|
2418
|
+
setSegs(fromValue(value, use24Hour));
|
|
2419
|
+
setBuffers({});
|
|
2420
|
+
}, [value, use24Hour]);
|
|
2421
|
+
const segmentRefs = useRef([]);
|
|
2422
|
+
const segmentCount = specs.length + (use24Hour ? 0 : 1);
|
|
2423
|
+
const focusSegment = (i) => {
|
|
2424
|
+
const el = segmentRefs.current[Math.max(0, Math.min(segmentCount - 1, i))];
|
|
2425
|
+
el?.focus();
|
|
2426
|
+
};
|
|
2427
|
+
const focusSegmentRef = useLatest(focusSegment);
|
|
2428
|
+
useEffect(() => {
|
|
2429
|
+
if (!open) return;
|
|
2430
|
+
const handler = (e) => {
|
|
2431
|
+
if (triggerRef.current?.contains(e.target) || panelRef.current?.contains(e.target)) return;
|
|
2432
|
+
setOpen(false);
|
|
2433
|
+
};
|
|
2434
|
+
const keyHandler = (e) => {
|
|
2435
|
+
if (e.key === "Escape" && isTopLayer()) {
|
|
2436
|
+
setOpen(false);
|
|
2437
|
+
focusSegmentRef.current(0);
|
|
2438
|
+
}
|
|
2439
|
+
};
|
|
2440
|
+
document.addEventListener("mousedown", handler);
|
|
2441
|
+
document.addEventListener("keydown", keyHandler);
|
|
2442
|
+
return () => {
|
|
2443
|
+
document.removeEventListener("mousedown", handler);
|
|
2444
|
+
document.removeEventListener("keydown", keyHandler);
|
|
2445
|
+
};
|
|
2446
|
+
}, [open, isTopLayer, focusSegmentRef]);
|
|
2447
|
+
const commitIfComplete = (next) => {
|
|
2448
|
+
if (next.hour === null || next.minute === null) return;
|
|
2449
|
+
let h24 = next.hour;
|
|
2450
|
+
if (!use24Hour) {
|
|
2451
|
+
const period = next.period ?? "AM";
|
|
2452
|
+
h24 = period === "AM" ? next.hour === 12 ? 0 : next.hour : next.hour === 12 ? 12 : next.hour + 12;
|
|
2453
|
+
}
|
|
2454
|
+
const out = `${pad2(h24)}:${pad2(next.minute)}`;
|
|
2455
|
+
lastCommitted.current = out;
|
|
2456
|
+
if (out !== value) onChange(out);
|
|
2457
|
+
};
|
|
2458
|
+
const setSegment = (key, v, commit = true) => {
|
|
2459
|
+
setSegs((s) => {
|
|
2460
|
+
const next = { ...s, [key]: v };
|
|
2461
|
+
if (commit) commitIfComplete(next);
|
|
2462
|
+
return next;
|
|
2463
|
+
});
|
|
2464
|
+
};
|
|
2465
|
+
const applyTyped = (text) => {
|
|
2466
|
+
const parsed2 = parseTypedTime(text, use24Hour);
|
|
2467
|
+
if (!parsed2) return;
|
|
2468
|
+
const next = fromValue(parsed2, use24Hour);
|
|
2469
|
+
setSegs(next);
|
|
2470
|
+
setBuffers({});
|
|
2471
|
+
commitIfComplete(next);
|
|
2472
|
+
};
|
|
2473
|
+
const onSegmentKeyDown = (e, index, spec) => {
|
|
2474
|
+
const key = e.key;
|
|
2475
|
+
if (key === "Tab" || key === "Shift" || key === "Escape" || key.startsWith("F")) return;
|
|
2476
|
+
e.preventDefault();
|
|
2477
|
+
if (key === "ArrowLeft") {
|
|
2478
|
+
focusSegment(index - 1);
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
if (key === "ArrowRight") {
|
|
2482
|
+
focusSegment(index + 1);
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
if (!spec) {
|
|
2486
|
+
if (key === "ArrowUp" || key === "ArrowDown" || key === " ") setSegment("period", segs.period === "PM" ? "AM" : "PM");
|
|
2487
|
+
else if (/^[aA]$/.test(key)) setSegment("period", "AM");
|
|
2488
|
+
else if (/^[pP]$/.test(key)) setSegment("period", "PM");
|
|
2489
|
+
else if (key === "Backspace" || key === "Delete") {
|
|
2490
|
+
setSegment("period", null, false);
|
|
2491
|
+
}
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
const k = spec.key;
|
|
2495
|
+
const clearBuffer = () => setBuffers((b) => ({ ...b, [k]: "" }));
|
|
2496
|
+
if (key === "ArrowUp" || key === "ArrowDown") {
|
|
2497
|
+
clearBuffer();
|
|
2498
|
+
setSegment(k, stepValue(spec, segs[k], key === "ArrowUp" ? 1 : -1));
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
if (key === "Home") {
|
|
2502
|
+
clearBuffer();
|
|
2503
|
+
setSegment(k, spec.min);
|
|
2504
|
+
return;
|
|
2505
|
+
}
|
|
2506
|
+
if (key === "End") {
|
|
2507
|
+
clearBuffer();
|
|
2508
|
+
setSegment(k, spec.max);
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2511
|
+
if (key === "Backspace" || key === "Delete") {
|
|
2512
|
+
if (segs[k] === null && !buffers[k]) {
|
|
2513
|
+
focusSegment(index - 1);
|
|
2514
|
+
return;
|
|
2515
|
+
}
|
|
2516
|
+
clearBuffer();
|
|
2517
|
+
setSegment(k, null, false);
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
if (/^\d$/.test(key)) {
|
|
2521
|
+
const r = typeDigit(spec, buffers[k] ?? "", key);
|
|
2522
|
+
setBuffers((b) => ({ ...b, [k]: r.advance ? "" : r.buffer }));
|
|
2523
|
+
setSegment(k, r.value);
|
|
2524
|
+
if (r.advance) focusSegment(index + 1);
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
if (!use24Hour && /^[aApP]$/.test(key)) {
|
|
2528
|
+
setSegment("period", /^[aA]$/.test(key) ? "AM" : "PM");
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
};
|
|
2532
|
+
const shown = (k, spec) => {
|
|
2533
|
+
const b = buffers[k];
|
|
2534
|
+
if (b && segs[k] === null) return b;
|
|
2535
|
+
return segs[k] === null ? spec.placeholder : pad2(segs[k]);
|
|
2536
|
+
};
|
|
2199
2537
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
2200
2538
|
/* @__PURE__ */ jsxs(
|
|
2201
|
-
"
|
|
2539
|
+
"div",
|
|
2202
2540
|
{
|
|
2203
|
-
id,
|
|
2204
2541
|
ref: triggerRef,
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2542
|
+
"data-time-field": "",
|
|
2543
|
+
role: "group",
|
|
2544
|
+
id,
|
|
2545
|
+
"aria-label": "Time",
|
|
2208
2546
|
"aria-invalid": error || void 0,
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2547
|
+
onPaste: (e) => {
|
|
2548
|
+
const text = e.clipboardData.getData("text");
|
|
2549
|
+
if (text) {
|
|
2550
|
+
e.preventDefault();
|
|
2551
|
+
applyTyped(text);
|
|
2552
|
+
}
|
|
2553
|
+
},
|
|
2212
2554
|
className: cn(
|
|
2213
2555
|
"flex w-full items-center gap-ds-2",
|
|
2214
2556
|
CONTROL_HEIGHT4[size],
|
|
@@ -2217,16 +2559,77 @@ function TimePicker({
|
|
|
2217
2559
|
error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
2218
2560
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
2219
2561
|
"shadow-[var(--ds-input-shadow)]",
|
|
2220
|
-
"transition-colors
|
|
2562
|
+
"transition-colors",
|
|
2221
2563
|
"px-ds-3 py-ds-2",
|
|
2222
|
-
!error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
2564
|
+
!error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)] focus-within:border-[var(--ds-input-border-hover)]",
|
|
2223
2565
|
open && ACTIVE_RING,
|
|
2224
2566
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
2225
|
-
|
|
2567
|
+
"text-[var(--ds-text-primary)]"
|
|
2226
2568
|
),
|
|
2227
2569
|
children: [
|
|
2228
|
-
/* @__PURE__ */ jsx(Icon, { name: "clock", size: 14, className: "text-[var(--ds-text-muted)]" }),
|
|
2229
|
-
|
|
2570
|
+
/* @__PURE__ */ jsx(Icon, { name: "clock", size: 14, className: "text-[var(--ds-text-muted)] shrink-0" }),
|
|
2571
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center min-w-0 flex-1 tabular-nums", onClick: () => focusSegment(0), children: [
|
|
2572
|
+
specs.map((spec, i) => {
|
|
2573
|
+
const k = spec.key;
|
|
2574
|
+
return /* @__PURE__ */ jsxs("span", { className: "contents", children: [
|
|
2575
|
+
i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "px-[1px]", children: ":" }),
|
|
2576
|
+
/* @__PURE__ */ jsx(
|
|
2577
|
+
"span",
|
|
2578
|
+
{
|
|
2579
|
+
ref: (el) => {
|
|
2580
|
+
segmentRefs.current[i] = el;
|
|
2581
|
+
},
|
|
2582
|
+
role: "spinbutton",
|
|
2583
|
+
tabIndex: disabled ? -1 : 0,
|
|
2584
|
+
"data-segment": spec.key,
|
|
2585
|
+
"aria-label": spec.label,
|
|
2586
|
+
"aria-valuemin": spec.min,
|
|
2587
|
+
"aria-valuemax": spec.max,
|
|
2588
|
+
"aria-valuenow": segs[k] ?? void 0,
|
|
2589
|
+
"aria-valuetext": segs[k] === null ? "empty" : pad2(segs[k]),
|
|
2590
|
+
onKeyDown: (e) => onSegmentKeyDown(e, i, spec),
|
|
2591
|
+
onClick: (e) => e.stopPropagation(),
|
|
2592
|
+
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-primary)] cursor-text", segs[k] === null && !buffers[k] && "text-[var(--ds-text-muted)]"),
|
|
2593
|
+
children: shown(k, spec)
|
|
2594
|
+
}
|
|
2595
|
+
)
|
|
2596
|
+
] }, spec.key);
|
|
2597
|
+
}),
|
|
2598
|
+
!use24Hour && /* @__PURE__ */ jsx(
|
|
2599
|
+
"span",
|
|
2600
|
+
{
|
|
2601
|
+
ref: (el) => {
|
|
2602
|
+
segmentRefs.current[specs.length] = el;
|
|
2603
|
+
},
|
|
2604
|
+
role: "spinbutton",
|
|
2605
|
+
tabIndex: disabled ? -1 : 0,
|
|
2606
|
+
"data-segment": "period",
|
|
2607
|
+
"aria-label": "AM or PM",
|
|
2608
|
+
"aria-valuemin": 0,
|
|
2609
|
+
"aria-valuemax": 1,
|
|
2610
|
+
"aria-valuenow": segs.period === null ? void 0 : segs.period === "AM" ? 0 : 1,
|
|
2611
|
+
"aria-valuetext": segs.period ?? "empty",
|
|
2612
|
+
onKeyDown: (e) => onSegmentKeyDown(e, specs.length, null),
|
|
2613
|
+
onClick: (e) => e.stopPropagation(),
|
|
2614
|
+
className: cn("ml-ds-1 rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-primary)] cursor-text", segs.period === null && "text-[var(--ds-text-muted)]"),
|
|
2615
|
+
children: segs.period ?? "--"
|
|
2616
|
+
}
|
|
2617
|
+
)
|
|
2618
|
+
] }),
|
|
2619
|
+
/* @__PURE__ */ jsx(
|
|
2620
|
+
"button",
|
|
2621
|
+
{
|
|
2622
|
+
type: "button",
|
|
2623
|
+
"aria-label": "Choose a time",
|
|
2624
|
+
"aria-haspopup": "dialog",
|
|
2625
|
+
"aria-expanded": open,
|
|
2626
|
+
"aria-controls": open ? listboxId : void 0,
|
|
2627
|
+
onClick: () => !disabled && setOpen(!open),
|
|
2628
|
+
disabled,
|
|
2629
|
+
className: "shrink-0 -mr-ds-1 rounded-[var(--ds-radius-sm)] text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] disabled:cursor-not-allowed",
|
|
2630
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 })
|
|
2631
|
+
}
|
|
2632
|
+
)
|
|
2230
2633
|
]
|
|
2231
2634
|
}
|
|
2232
2635
|
),
|
|
@@ -2247,7 +2650,7 @@ function TimePicker({
|
|
|
2247
2650
|
"rounded-[var(--ds-radius-md)]"
|
|
2248
2651
|
),
|
|
2249
2652
|
style: { top: pos.top, left: pos.left },
|
|
2250
|
-
children: /* @__PURE__ */ jsxs("div", { className: "inline-flex p-ds-1 gap-ds-1", children: [
|
|
2653
|
+
children: /* @__PURE__ */ jsxs("div", { className: "inline-flex p-ds-1 gap-ds-1 tabular-nums", children: [
|
|
2251
2654
|
/* @__PURE__ */ jsx("div", { "data-column": true, className: "max-h-48 overflow-y-auto w-ds-10", children: hours.map((h) => /* @__PURE__ */ jsx(
|
|
2252
2655
|
"button",
|
|
2253
2656
|
{
|
|
@@ -2575,7 +2978,7 @@ var Tag = forwardRef(function Tag2({
|
|
|
2575
2978
|
className,
|
|
2576
2979
|
children
|
|
2577
2980
|
}, ref) {
|
|
2578
|
-
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1
|
|
2981
|
+
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1 });
|
|
2579
2982
|
const handleRemove = (e) => {
|
|
2580
2983
|
e.stopPropagation();
|
|
2581
2984
|
onRemove?.();
|
|
@@ -2596,7 +2999,7 @@ var Tag = forwardRef(function Tag2({
|
|
|
2596
2999
|
}
|
|
2597
3000
|
} : void 0,
|
|
2598
3001
|
className: cn(
|
|
2599
|
-
"inline-flex items-center font-medium max-w-full whitespace-nowrap",
|
|
3002
|
+
"inline-flex items-center font-medium max-w-full min-w-0 whitespace-nowrap",
|
|
2600
3003
|
"rounded-[var(--ds-radius-sm)]",
|
|
2601
3004
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
2602
3005
|
sizeStyles[size],
|
|
@@ -2607,7 +3010,7 @@ var Tag = forwardRef(function Tag2({
|
|
|
2607
3010
|
),
|
|
2608
3011
|
style: maxWidth ? { maxWidth } : void 0,
|
|
2609
3012
|
children: [
|
|
2610
|
-
|
|
3013
|
+
/* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate min-w-0", children }),
|
|
2611
3014
|
onRemove && !disabled && /* @__PURE__ */ jsx(
|
|
2612
3015
|
"button",
|
|
2613
3016
|
{
|
|
@@ -3456,7 +3859,10 @@ function collectInvalidFields(form) {
|
|
|
3456
3859
|
}
|
|
3457
3860
|
return out;
|
|
3458
3861
|
}
|
|
3459
|
-
function FormWrapper({ onSubmit, validationMode
|
|
3862
|
+
function FormWrapper({ onSubmit, validationMode: validationModeProp, children, actions, actionsAlign: actionsAlignProp, focusFirstError = true, errorSummary = true, className, ref }) {
|
|
3863
|
+
const preferences = usePreferences();
|
|
3864
|
+
const validationMode = validationModeProp ?? preferences.validationTiming ?? "onSubmit";
|
|
3865
|
+
const actionsAlign = actionsAlignProp ?? preferences.formActions?.align ?? "end";
|
|
3460
3866
|
const [errors, setErrors] = useState({});
|
|
3461
3867
|
const [submitted, setSubmitted] = useState(false);
|
|
3462
3868
|
const [submitCount, setSubmitCount] = useState(0);
|
|
@@ -4318,11 +4724,15 @@ var Card = forwardRef(function Card2({
|
|
|
4318
4724
|
children: /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected })
|
|
4319
4725
|
}
|
|
4320
4726
|
),
|
|
4321
|
-
/* @__PURE__ */ jsx(CardSurfaceCtx, { value: true, children: /* @__PURE__ */ jsx(CardCtx, { value: checkable, children: loading ?
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
/* @__PURE__ */ jsx(
|
|
4325
|
-
|
|
4727
|
+
/* @__PURE__ */ jsx(CardSurfaceCtx, { value: true, children: /* @__PURE__ */ jsx(CardCtx, { value: checkable, children: loading ? (
|
|
4728
|
+
// Round 15 (the owner's 52.1): a placeholder stands where the content will stand — inside the card's
|
|
4729
|
+
// content inset (CardContent's padding), a title-height line then two body lines — never flush against the border.
|
|
4730
|
+
/* @__PURE__ */ jsx("div", { "data-card-loading": "", "aria-busy": "true", className: cn("pr-ds-5 py-ds-4", checkable ? "pl-ds-10" : "pl-ds-5"), children: /* @__PURE__ */ jsxs("div", { className: "space-y-ds-3", children: [
|
|
4731
|
+
/* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-5 w-1/3" }),
|
|
4732
|
+
/* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-full" }),
|
|
4733
|
+
/* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-2/3" })
|
|
4734
|
+
] }) })
|
|
4735
|
+
) : children }) })
|
|
4326
4736
|
]
|
|
4327
4737
|
}
|
|
4328
4738
|
);
|
|
@@ -4331,7 +4741,7 @@ var CardHeader = forwardRef(function CardHeader2({ className, children, actions,
|
|
|
4331
4741
|
const isCheckable = useContext(CardCtx);
|
|
4332
4742
|
const hasActions = actions || menuItems;
|
|
4333
4743
|
const pl = isCheckable ? "pl-ds-10" : "pl-ds-5";
|
|
4334
|
-
const actionsBlock = hasActions ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 shrink-0", children: [
|
|
4744
|
+
const actionsBlock = hasActions ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 shrink-0 ml-auto", children: [
|
|
4335
4745
|
actions,
|
|
4336
4746
|
menuItems && /* @__PURE__ */ jsx(
|
|
4337
4747
|
DropdownMenu,
|
|
@@ -4355,8 +4765,8 @@ var CardHeader = forwardRef(function CardHeader2({ className, children, actions,
|
|
|
4355
4765
|
] }) : null;
|
|
4356
4766
|
const iconBlock = icon ? /* @__PURE__ */ jsx("span", { className: "shrink-0 h-10 w-10 rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-muted)] flex items-center justify-center mb-ds-1", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 20, className: "text-[var(--ds-text-secondary)]" }) }) : null;
|
|
4357
4767
|
if (hasActions) {
|
|
4358
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-4", children: [
|
|
4359
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 min-
|
|
4768
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-ds-4", children: [
|
|
4769
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 grow basis-1/2 [min-width:min-content] break-words", children: [
|
|
4360
4770
|
iconBlock,
|
|
4361
4771
|
children
|
|
4362
4772
|
] }),
|
|
@@ -4767,7 +5177,7 @@ function Table({
|
|
|
4767
5177
|
loading = false,
|
|
4768
5178
|
emptyState,
|
|
4769
5179
|
onRowClick,
|
|
4770
|
-
mobileBreakpoint
|
|
5180
|
+
mobileBreakpoint: mobileBreakpointProp,
|
|
4771
5181
|
ref
|
|
4772
5182
|
}) {
|
|
4773
5183
|
const [internalSortKey, setInternalSortKey] = useState(null);
|
|
@@ -4833,6 +5243,8 @@ function Table({
|
|
|
4833
5243
|
(col) => col.kind ?? inferredKinds.get(col.key),
|
|
4834
5244
|
[inferredKinds]
|
|
4835
5245
|
);
|
|
5246
|
+
const preferences = usePreferences();
|
|
5247
|
+
const mobileBreakpoint = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? "md";
|
|
4836
5248
|
const isMobile = useBreakpoint(mobileBreakpoint);
|
|
4837
5249
|
if (isMobile) {
|
|
4838
5250
|
if (loading) {
|
|
@@ -4915,7 +5327,7 @@ function Table({
|
|
|
4915
5327
|
headerAlign === "right" ? "text-right" : headerAlign === "center" ? "text-center" : "text-left",
|
|
4916
5328
|
isSortable && "cursor-pointer select-none hover:text-[var(--ds-text-primary)]"
|
|
4917
5329
|
),
|
|
4918
|
-
style: col.maxWidth ? { maxWidth: col.maxWidth } : void 0,
|
|
5330
|
+
style: col.maxWidth || col.width || col.minWidth ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth } : void 0,
|
|
4919
5331
|
onClick: isSortable ? () => handleSort(col.key) : void 0,
|
|
4920
5332
|
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-ds-1", children: [
|
|
4921
5333
|
col.header,
|
|
@@ -5005,6 +5417,10 @@ function Table({
|
|
|
5005
5417
|
} else {
|
|
5006
5418
|
inner = cellContent;
|
|
5007
5419
|
}
|
|
5420
|
+
const align = col.align ?? (kind === "number" ? "right" : "left");
|
|
5421
|
+
if (align !== "left" && cellContent !== null && cellContent !== void 0 && typeof cellContent !== "string" && typeof cellContent !== "number") {
|
|
5422
|
+
inner = /* @__PURE__ */ jsx("div", { className: cn("flex items-center", align === "center" ? "justify-center" : "justify-end"), children: inner });
|
|
5423
|
+
}
|
|
5008
5424
|
return /* @__PURE__ */ jsx(
|
|
5009
5425
|
"td",
|
|
5010
5426
|
{
|
|
@@ -5014,7 +5430,7 @@ function Table({
|
|
|
5014
5430
|
alignClass,
|
|
5015
5431
|
shrink && "w-px whitespace-nowrap"
|
|
5016
5432
|
),
|
|
5017
|
-
style: col.maxWidth ? { maxWidth: col.maxWidth } : void 0,
|
|
5433
|
+
style: col.maxWidth || col.width || col.minWidth ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth } : void 0,
|
|
5018
5434
|
children: inner
|
|
5019
5435
|
},
|
|
5020
5436
|
col.key
|
|
@@ -5027,7 +5443,7 @@ function Table({
|
|
|
5027
5443
|
"td",
|
|
5028
5444
|
{
|
|
5029
5445
|
colSpan: columns.length + (selectable ? 1 : 0) + 1,
|
|
5030
|
-
className: "bg-[var(--ds-bg-muted)] px-ds-
|
|
5446
|
+
className: "bg-[var(--ds-bg-muted)] px-ds-6 py-ds-4 text-sm text-[var(--ds-text-primary)]",
|
|
5031
5447
|
children: renderExpanded(row, i)
|
|
5032
5448
|
}
|
|
5033
5449
|
) })
|
|
@@ -6791,8 +7207,10 @@ function renderIcon(icon) {
|
|
|
6791
7207
|
if (isValidElement(icon) && icon.type === Icon) return cloneElement(icon, { size: FRAME_ICON_SIZE });
|
|
6792
7208
|
return icon;
|
|
6793
7209
|
}
|
|
6794
|
-
function EmptyState({ icon, iconFrame = "circle", title, description, action, variant = "empty", bordered = false, className }) {
|
|
6795
|
-
const
|
|
7210
|
+
function EmptyState({ icon, iconFrame = "circle", title, description, action, variant = "empty", bordered = false, style: styleProp, className }) {
|
|
7211
|
+
const preferences = usePreferences();
|
|
7212
|
+
const style = styleProp ?? (preferences.emptyStyle === "text-cta" ? "text" : "illustration");
|
|
7213
|
+
const iconNode = style === "text" ? void 0 : icon === void 0 || icon === null ? void 0 : renderIcon(icon);
|
|
6796
7214
|
return /* @__PURE__ */ jsxs(
|
|
6797
7215
|
"div",
|
|
6798
7216
|
{
|
|
@@ -6803,8 +7221,9 @@ function EmptyState({ icon, iconFrame = "circle", title, description, action, va
|
|
|
6803
7221
|
bordered && "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
6804
7222
|
className
|
|
6805
7223
|
),
|
|
7224
|
+
"data-style": style,
|
|
6806
7225
|
children: [
|
|
6807
|
-
iconFrame === "none" && iconNode ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-ds-4", children: iconNode }) : /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-[var(--ds-radius-full)] bg-[var(--ds-bg-emphasis)] flex items-center justify-center mb-ds-4", children: iconNode ?? /* @__PURE__ */ jsx("span", { className: "text-2xl text-[var(--ds-text-muted)]", children: defaultIcons[variant] }) }),
|
|
7226
|
+
style === "text" ? null : iconFrame === "none" && iconNode ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-ds-4", children: iconNode }) : /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-[var(--ds-radius-full)] bg-[var(--ds-bg-emphasis)] flex items-center justify-center mb-ds-4", children: iconNode ?? /* @__PURE__ */ jsx("span", { className: "text-2xl text-[var(--ds-text-muted)]", children: defaultIcons[variant] }) }),
|
|
6808
7227
|
/* @__PURE__ */ jsx("h3", { className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] text-center", children: title }),
|
|
6809
7228
|
description && /* @__PURE__ */ jsx("p", { className: "mt-ds-1 text-sm text-[var(--ds-text-muted)] max-w-sm text-center", children: description }),
|
|
6810
7229
|
action && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: action })
|
|
@@ -6818,8 +7237,9 @@ function initialsOf(name) {
|
|
|
6818
7237
|
function looksLikeUrl(s) {
|
|
6819
7238
|
return /^(?:https?:|data:|blob:|\/|\.{1,2}\/)/.test(s) || /\.[a-z]{2,5}(?:$|[?#])/i.test(s);
|
|
6820
7239
|
}
|
|
6821
|
-
function EntityCell({ avatar, src, initials, primary, secondary, size
|
|
7240
|
+
function EntityCell({ avatar, src, initials, primary, secondary, size: sizeProp, className }) {
|
|
6822
7241
|
const inTableCard = useContext(TableCardCtx);
|
|
7242
|
+
const size = sizeProp ?? (inTableCard ? "sm" : "md");
|
|
6823
7243
|
let avatarElement;
|
|
6824
7244
|
if (typeof avatar === "string") {
|
|
6825
7245
|
avatarElement = looksLikeUrl(avatar) ? /* @__PURE__ */ jsx(Avatar, { src: avatar, alt: primary, size }) : /* @__PURE__ */ jsx(Avatar, { initials: avatar, alt: primary, size });
|
|
@@ -8334,11 +8754,13 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
8334
8754
|
const interactive = !!item.onClick;
|
|
8335
8755
|
const hasEmphasis = item.unread !== void 0;
|
|
8336
8756
|
const multiline = !!item.description;
|
|
8757
|
+
const stackThis = stackMeta || isPhone && !!item.meta && !!item.actions;
|
|
8758
|
+
const tall = multiline || stackThis && !stackMeta && !!item.leading;
|
|
8337
8759
|
const trailing = item.unread || item.meta ? /* @__PURE__ */ jsxs("div", { className: cn(
|
|
8338
8760
|
"shrink-0 flex items-center gap-ds-2 text-sm",
|
|
8339
8761
|
// Below sm an article's meta sits under the title, left-aligned, whatever alignment its own markup
|
|
8340
8762
|
// carries (round 6: a builder's items-end column put its badge mid-row).
|
|
8341
|
-
|
|
8763
|
+
stackThis && "self-start [&>*]:items-start! [&>*]:text-left!",
|
|
8342
8764
|
isSelected ? "text-[var(--ds-nav-v-active-muted)]" : "text-[var(--ds-text-muted)]"
|
|
8343
8765
|
), children: [
|
|
8344
8766
|
item.unread && /* @__PURE__ */ jsx(
|
|
@@ -8356,7 +8778,7 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
8356
8778
|
{
|
|
8357
8779
|
className: cn(
|
|
8358
8780
|
"flex gap-ds-3 py-ds-3",
|
|
8359
|
-
|
|
8781
|
+
tall ? "items-start" : "items-center",
|
|
8360
8782
|
inset,
|
|
8361
8783
|
interactive && [
|
|
8362
8784
|
"cursor-pointer [transition:var(--ds-transition-interactive)]",
|
|
@@ -8383,7 +8805,7 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
8383
8805
|
}
|
|
8384
8806
|
} : void 0,
|
|
8385
8807
|
children: [
|
|
8386
|
-
item.leading && /* @__PURE__ */ jsx("div", { className: cn("shrink-0",
|
|
8808
|
+
item.leading && /* @__PURE__ */ jsx("div", { className: cn("shrink-0", tall && "mt-ds-0.5"), children: item.leading }),
|
|
8387
8809
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
8388
8810
|
/* @__PURE__ */ jsxs("div", { className: cn("flex gap-ds-2", stackMeta ? "flex-col" : "items-center justify-between"), children: [
|
|
8389
8811
|
/* @__PURE__ */ jsx(
|
|
@@ -8401,9 +8823,10 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
8401
8823
|
(multiline || stackMeta) && trailing
|
|
8402
8824
|
] }),
|
|
8403
8825
|
item.subtitle && /* @__PURE__ */ jsx(TruncText, { className: cn("text-sm", isSelected ? "text-[var(--ds-nav-v-active-muted)]" : "text-[var(--ds-text-secondary)]"), children: item.subtitle }),
|
|
8404
|
-
item.description && /* @__PURE__ */ jsx(TruncText, { className: cn("text-xs", isSelected ? "text-[var(--ds-nav-v-active-muted)]" : "text-[var(--ds-text-muted)]"), children: item.description })
|
|
8826
|
+
item.description && /* @__PURE__ */ jsx(TruncText, { className: cn("text-xs", isSelected ? "text-[var(--ds-nav-v-active-muted)]" : "text-[var(--ds-text-muted)]"), children: item.description }),
|
|
8827
|
+
stackThis && !stackMeta && !multiline && trailing
|
|
8405
8828
|
] }),
|
|
8406
|
-
!multiline && !
|
|
8829
|
+
!multiline && !stackThis && trailing,
|
|
8407
8830
|
item.actions && /* @__PURE__ */ jsx(
|
|
8408
8831
|
"div",
|
|
8409
8832
|
{
|
|
@@ -8862,7 +9285,7 @@ function TabButton({
|
|
|
8862
9285
|
className,
|
|
8863
9286
|
hasPanel
|
|
8864
9287
|
}) {
|
|
8865
|
-
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !truncate });
|
|
9288
|
+
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !truncate && orientation !== "horizontal" });
|
|
8866
9289
|
const isActive = activeTab === id;
|
|
8867
9290
|
const tabId = `ds-tab-${id}`;
|
|
8868
9291
|
const panelId = hasPanel === false ? void 0 : `ds-tabpanel-${id}`;
|
|
@@ -8921,6 +9344,8 @@ function TabButton({
|
|
|
8921
9344
|
onKeyDown,
|
|
8922
9345
|
className: cn(
|
|
8923
9346
|
"px-ds-4 py-ds-2.5 text-sm font-medium",
|
|
9347
|
+
// never wrap: the strip scrolls when the tabs do not fit (round 17, 54.4)
|
|
9348
|
+
!fullWidth && !truncate && "shrink-0 whitespace-nowrap",
|
|
8924
9349
|
disabled ? "cursor-not-allowed opacity-disabled" : "cursor-pointer",
|
|
8925
9350
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
8926
9351
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
@@ -8937,7 +9362,7 @@ function TabButton({
|
|
|
8937
9362
|
countBadge && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: countBadge })
|
|
8938
9363
|
] }) : /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-ds-2 min-w-0", children: [
|
|
8939
9364
|
icon && /* @__PURE__ */ jsx(Icon, { name: icon, size: 16, className: "shrink-0" }),
|
|
8940
|
-
label,
|
|
9365
|
+
/* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate max-w-[24ch]", children: label }),
|
|
8941
9366
|
countBadge
|
|
8942
9367
|
] })
|
|
8943
9368
|
}
|
|
@@ -9400,8 +9825,10 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
|
|
|
9400
9825
|
)
|
|
9401
9826
|
] });
|
|
9402
9827
|
}
|
|
9403
|
-
function Pagination({ currentPage, totalPages, onPageChange, pageSize, pageSizeOptions, onPageSizeChange, className }) {
|
|
9828
|
+
function Pagination({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }) {
|
|
9404
9829
|
const pages = buildPageRange(currentPage, totalPages);
|
|
9830
|
+
const preferences = usePreferences();
|
|
9831
|
+
const pageSize = pageSizeProp ?? preferences.itemsPerPage;
|
|
9405
9832
|
return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", className: cn("flex flex-wrap items-center gap-ds-3", className), children: [
|
|
9406
9833
|
pageSizeOptions && pageSize != null && onPageSizeChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
9407
9834
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--ds-text-muted)] whitespace-nowrap", children: "Rows per page" }),
|
|
@@ -10167,14 +10594,16 @@ function SidebarNav({
|
|
|
10167
10594
|
item.active ? isRoot ? "bg-[var(--ds-sidebar-active-bg)] [background-image:var(--ds-sidebar-active-image)] text-[var(--ds-sidebar-active-text)] font-medium border-l-[length:var(--ds-sidebar-active-rail)] border-[var(--ds-sidebar-active-accent)]" : "bg-[var(--ds-sidebar-active-bg)] [background-image:var(--ds-sidebar-active-image)] text-[var(--ds-sidebar-active-accent)] font-medium" : isRoot ? "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)] border-l-[length:var(--ds-sidebar-active-rail)] border-transparent" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
|
|
10168
10595
|
),
|
|
10169
10596
|
children: [
|
|
10170
|
-
item.icon &&
|
|
10597
|
+
item.icon && // Round 15 (the owner's 52.8): the icon sits in a box one line tall, so a collapsed (icon-only) item is exactly as
|
|
10598
|
+
// tall as the expanded item whose label sets that line — the rail no longer jumps when the sidebar collapses.
|
|
10599
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center shrink-0 min-h-[1lh]", "data-sidebar-icon": "", children: /* @__PURE__ */ jsx(
|
|
10171
10600
|
Icon,
|
|
10172
10601
|
{
|
|
10173
10602
|
name: item.icon,
|
|
10174
10603
|
size: isRoot ? rootIconSize : childIconSize,
|
|
10175
10604
|
className: cn("shrink-0", item.active && "text-[var(--ds-sidebar-active-accent)]")
|
|
10176
10605
|
}
|
|
10177
|
-
),
|
|
10606
|
+
) }),
|
|
10178
10607
|
!collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10179
10608
|
/* @__PURE__ */ jsx(TruncLabel3, { className: isRoot ? "flex-1" : void 0, container: portalContainer ?? void 0, children: item.label }),
|
|
10180
10609
|
item.badge && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: item.badge })
|
|
@@ -10669,6 +11098,15 @@ var FLOATING_BLOCK = cn(
|
|
|
10669
11098
|
"overflow-hidden"
|
|
10670
11099
|
);
|
|
10671
11100
|
var PageContainerContext = createContext(null);
|
|
11101
|
+
function useContentWidth(width) {
|
|
11102
|
+
const ctx = useContext(PageContainerContext);
|
|
11103
|
+
const request = ctx?.requestContentWidth;
|
|
11104
|
+
useEffect(() => {
|
|
11105
|
+
if (!request) return;
|
|
11106
|
+
request(width);
|
|
11107
|
+
return () => request(null);
|
|
11108
|
+
}, [request, width]);
|
|
11109
|
+
}
|
|
10672
11110
|
function usePageContainer() {
|
|
10673
11111
|
return useContext(PageContainerContext);
|
|
10674
11112
|
}
|
|
@@ -10709,6 +11147,7 @@ function floatingBlockPadding(navbarFloating, sidebarFloating, overlap) {
|
|
|
10709
11147
|
var PageContainer = forwardRef(function PageContainer2({
|
|
10710
11148
|
width,
|
|
10711
11149
|
maxWidth = "xl",
|
|
11150
|
+
contentWidth,
|
|
10712
11151
|
padding = "default",
|
|
10713
11152
|
verticalPadding,
|
|
10714
11153
|
centered = true,
|
|
@@ -10729,8 +11168,19 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
10729
11168
|
}, []);
|
|
10730
11169
|
const resolvedMaxWidth = width ? widthToMaxWidth[width] : maxWidth;
|
|
10731
11170
|
const maxWidthValue = maxWidthValues[resolvedMaxWidth];
|
|
11171
|
+
const [requestedWidth, setRequestedWidth] = useState(null);
|
|
11172
|
+
const requestContentWidth = useCallback((w) => setRequestedWidth(w), []);
|
|
11173
|
+
const effectiveContentWidth = contentWidth ?? requestedWidth ?? void 0;
|
|
11174
|
+
const contentCap = effectiveContentWidth ? maxWidthValues[widthToMaxWidth[effectiveContentWidth]] : void 0;
|
|
11175
|
+
const capped = (content) => contentCap ? /* @__PURE__ */ jsx("div", { "data-content-width": effectiveContentWidth, style: { maxWidth: contentCap }, children: content }) : content;
|
|
10732
11176
|
const kids = Children.toArray(children);
|
|
10733
11177
|
const headerIdx = kids.findIndex(isPageHeaderElement);
|
|
11178
|
+
const headerCount = useRef(0);
|
|
11179
|
+
const [wrappedHeader, setWrappedHeader] = useState(false);
|
|
11180
|
+
const reportHeader = useCallback((present) => {
|
|
11181
|
+
headerCount.current = Math.max(0, headerCount.current + (present ? 1 : -1));
|
|
11182
|
+
setWrappedHeader(headerCount.current > 0);
|
|
11183
|
+
}, []);
|
|
10734
11184
|
const launcherCorner = shell?.launcherCorner ?? null;
|
|
10735
11185
|
const vPad = verticalPadding ?? "default";
|
|
10736
11186
|
const launcherPadding = launcherCorner ? { paddingBottom: `max(${bottomPaddingValues[vPad]}, var(--ds-toast-inset-${launcherCorner}, 0px))` } : {};
|
|
@@ -10776,21 +11226,22 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
10776
11226
|
observedRef.current = null;
|
|
10777
11227
|
}, []);
|
|
10778
11228
|
if (headerIdx === -1 || !headerEl || !r) {
|
|
10779
|
-
return /* @__PURE__ */ jsx(
|
|
11229
|
+
return /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement: "inside", containedBreadcrumbs: false, breadcrumbsInsideHeader: false, noBottomMargin: false, overlap: false, setPinnedHeight, reportHeader, requestContentWidth, insidePaddedColumn: true }, children: /* @__PURE__ */ jsx(
|
|
10780
11230
|
"div",
|
|
10781
11231
|
{
|
|
10782
|
-
ref,
|
|
11232
|
+
ref: setRoot,
|
|
11233
|
+
"data-page-container": wrappedHeader ? "" : void 0,
|
|
10783
11234
|
className: cn(
|
|
10784
11235
|
"w-full",
|
|
10785
11236
|
paddingClasses[padding],
|
|
10786
|
-
verticalPaddingClasses[vPad],
|
|
11237
|
+
wrappedHeader ? bottomPaddingClasses[vPad] : verticalPaddingClasses[vPad],
|
|
10787
11238
|
centered && "mx-auto",
|
|
10788
11239
|
className
|
|
10789
11240
|
),
|
|
10790
11241
|
style: { maxWidth: maxWidthValue, containerType: "inline-size", ...launcherPadding },
|
|
10791
|
-
children
|
|
11242
|
+
children: capped(children)
|
|
10792
11243
|
}
|
|
10793
|
-
);
|
|
11244
|
+
) });
|
|
10794
11245
|
}
|
|
10795
11246
|
const rest = kids.filter((_, i) => i !== headerIdx);
|
|
10796
11247
|
const snapping = r.behavior === "snapping";
|
|
@@ -10802,15 +11253,15 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
10802
11253
|
const placement = block ? "block" : r.outside ? "outside" : "inside";
|
|
10803
11254
|
const breadcrumbsInsideHeader = snapping && floatingHeader && contained;
|
|
10804
11255
|
const strip = contained && !breadcrumbsInsideHeader && crumbs ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth: maxWidthValue, separator: r.breadcrumbSeparator, items: headerEl.props.title ? [...crumbs, { label: headerEl.props.title }] : crumbs }) : null;
|
|
10805
|
-
const columnClass = (
|
|
11256
|
+
const columnClass = (pad3) => cn("w-full", paddingClasses[pad3], centered && "mx-auto");
|
|
10806
11257
|
const columnStyle = { maxWidth: maxWidthValue, containerType: "inline-size" };
|
|
10807
|
-
const header = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement, containedBreadcrumbs: contained, breadcrumbsInsideHeader, noBottomMargin: block, overlap: overlapActive, setPinnedHeight }, children: renderHeader ? renderHeader(headerEl) : headerEl });
|
|
11258
|
+
const header = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement, containedBreadcrumbs: contained, breadcrumbsInsideHeader, noBottomMargin: block, overlap: overlapActive, setPinnedHeight, reportHeader, requestContentWidth }, children: renderHeader ? renderHeader(headerEl) : headerEl });
|
|
10808
11259
|
const contentPadding = floatingHeader && shell?.isMobile ? "none" : padding;
|
|
10809
11260
|
const wrapperStyle = floatingHeader || overlapActive ? {
|
|
10810
11261
|
...floatingHeader ? { paddingRight: "var(--ds-space-3)", paddingLeft: r.sidebarFloating ? 0 : "var(--ds-space-3)" } : {},
|
|
10811
11262
|
...overlapActive ? { marginTop: "calc(-1 * var(--ds-overlap, 0px))", position: "relative", zIndex: 1 } : {}
|
|
10812
11263
|
} : void 0;
|
|
10813
|
-
const column = /* @__PURE__ */ jsx("div", { ref: columnRef, className: cn(columnClass(contentPadding), bottomPaddingClasses[vPad], className), style: { ...columnStyle, ...launcherPadding }, children: rest });
|
|
11264
|
+
const column = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement: "inside", containedBreadcrumbs: false, breadcrumbsInsideHeader: false, noBottomMargin: false, overlap: false, setPinnedHeight, reportHeader, requestContentWidth, insidePaddedColumn: true }, children: /* @__PURE__ */ jsx("div", { ref: columnRef, className: cn(columnClass(contentPadding), bottomPaddingClasses[vPad], className), style: { ...columnStyle, ...launcherPadding }, children: capped(rest) }) });
|
|
10814
11265
|
return /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-page-container": "", className: "w-full", children: [
|
|
10815
11266
|
placement === "block" ? /* @__PURE__ */ jsx("div", { style: floatingBlockPadding(r.navbarFloating, r.sidebarFloating, overlapActive), children: /* @__PURE__ */ jsxs("div", { className: FLOATING_BLOCK, children: [
|
|
10816
11267
|
strip,
|
|
@@ -10969,6 +11420,12 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
10969
11420
|
}, ref) {
|
|
10970
11421
|
const shell = useAppShell();
|
|
10971
11422
|
const container = usePageContainer();
|
|
11423
|
+
const reportHeader = container?.reportHeader;
|
|
11424
|
+
useLayoutEffect(() => {
|
|
11425
|
+
if (!reportHeader) return;
|
|
11426
|
+
reportHeader(true);
|
|
11427
|
+
return () => reportHeader(false);
|
|
11428
|
+
}, [reportHeader]);
|
|
10972
11429
|
const r = resolvePageHeader(shell?.theme, {
|
|
10973
11430
|
variant: variantProp,
|
|
10974
11431
|
behavior: behaviorProp,
|
|
@@ -10985,11 +11442,14 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
10985
11442
|
const bcPill = r.breadcrumbStyle === "pill";
|
|
10986
11443
|
const bcSep = r.breadcrumbSeparator;
|
|
10987
11444
|
const contentMaxWidth = contentMaxWidthProp ?? container?.contentMaxWidth;
|
|
11445
|
+
const insidePaddedColumn = !!container?.insidePaddedColumn;
|
|
11446
|
+
const gutterWidth = insidePaddedColumn ? void 0 : contentMaxWidth;
|
|
11447
|
+
const floating = isFloating && !insidePaddedColumn;
|
|
10988
11448
|
const stickyTop = shell ? "top-0" : "top-[var(--ds-navbar-height)]";
|
|
10989
11449
|
const snapping = behavior === "snapping";
|
|
10990
11450
|
const inlineBreadcrumbs = container?.containedBreadcrumbs && !snapping ? void 0 : breadcrumbs;
|
|
10991
11451
|
const hideExpandedBreadcrumbs = hideExpandedBreadcrumbsProp ?? (!!container?.containedBreadcrumbs && snapping);
|
|
10992
|
-
const containedBreadcrumbs = containedBreadcrumbsProp ?? (container?.breadcrumbsInsideHeader && breadcrumbs?.length ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth, separator: bcSep, items: [...breadcrumbs, { label: title }] }) : void 0);
|
|
11452
|
+
const containedBreadcrumbs = containedBreadcrumbsProp ?? (container?.breadcrumbsInsideHeader && breadcrumbs?.length ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth: gutterWidth, separator: bcSep, items: [...breadcrumbs, { label: title }] }) : void 0);
|
|
10993
11453
|
const noBottomMargin = noBottomMarginProp ?? container?.noBottomMargin;
|
|
10994
11454
|
const overlapActive = container?.overlap ?? false;
|
|
10995
11455
|
if (behavior === "snapping") {
|
|
@@ -11007,7 +11467,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11007
11467
|
expandedContent,
|
|
11008
11468
|
collapseOffset,
|
|
11009
11469
|
pinned,
|
|
11010
|
-
contentMaxWidth,
|
|
11470
|
+
contentMaxWidth: gutterWidth,
|
|
11011
11471
|
variant,
|
|
11012
11472
|
intensity,
|
|
11013
11473
|
backgroundImage,
|
|
@@ -11019,7 +11479,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11019
11479
|
as: Heading,
|
|
11020
11480
|
className,
|
|
11021
11481
|
stickyTop,
|
|
11022
|
-
isFloating,
|
|
11482
|
+
isFloating: floating,
|
|
11023
11483
|
navbarFloating,
|
|
11024
11484
|
sidebarFloating,
|
|
11025
11485
|
containedBreadcrumbs,
|
|
@@ -11029,7 +11489,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11029
11489
|
}
|
|
11030
11490
|
let header;
|
|
11031
11491
|
if (variant === "minimal") {
|
|
11032
|
-
header = /* @__PURE__ */ jsx(MinimalHeader, { title, badge, breadcrumbs: inlineBreadcrumbs, actions, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef:
|
|
11492
|
+
header = /* @__PURE__ */ jsx(MinimalHeader, { title, badge, breadcrumbs: inlineBreadcrumbs, actions, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
11033
11493
|
} else if (variant === "tabs-integrated") {
|
|
11034
11494
|
header = /* @__PURE__ */ jsx(
|
|
11035
11495
|
TabsIntegratedHeader,
|
|
@@ -11046,15 +11506,16 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11046
11506
|
breadcrumbSeparator: bcSep,
|
|
11047
11507
|
as: Heading,
|
|
11048
11508
|
className,
|
|
11049
|
-
headerRef:
|
|
11050
|
-
isFloating,
|
|
11051
|
-
contentMaxWidth
|
|
11509
|
+
headerRef: floating ? void 0 : ref,
|
|
11510
|
+
isFloating: floating,
|
|
11511
|
+
contentMaxWidth: gutterWidth
|
|
11052
11512
|
}
|
|
11053
11513
|
);
|
|
11054
11514
|
} else if (variant === "colourful") {
|
|
11055
11515
|
header = /* @__PURE__ */ jsx(
|
|
11056
11516
|
ColourfulHeader,
|
|
11057
11517
|
{
|
|
11518
|
+
gutter: !insidePaddedColumn,
|
|
11058
11519
|
title,
|
|
11059
11520
|
description,
|
|
11060
11521
|
badge,
|
|
@@ -11066,13 +11527,13 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11066
11527
|
intensity,
|
|
11067
11528
|
backgroundImage,
|
|
11068
11529
|
overlapActive,
|
|
11069
|
-
contentMaxWidth,
|
|
11530
|
+
contentMaxWidth: gutterWidth,
|
|
11070
11531
|
breadcrumbPill: bcPill,
|
|
11071
11532
|
breadcrumbSeparator: bcSep,
|
|
11072
11533
|
as: Heading,
|
|
11073
11534
|
className,
|
|
11074
|
-
headerRef:
|
|
11075
|
-
isFloating,
|
|
11535
|
+
headerRef: floating ? void 0 : ref,
|
|
11536
|
+
isFloating: floating,
|
|
11076
11537
|
noBottomMargin
|
|
11077
11538
|
}
|
|
11078
11539
|
);
|
|
@@ -11093,13 +11554,13 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11093
11554
|
breadcrumbSeparator: bcSep,
|
|
11094
11555
|
as: Heading,
|
|
11095
11556
|
className,
|
|
11096
|
-
headerRef:
|
|
11097
|
-
isFloating,
|
|
11098
|
-
contentMaxWidth
|
|
11557
|
+
headerRef: floating ? void 0 : ref,
|
|
11558
|
+
isFloating: floating,
|
|
11559
|
+
contentMaxWidth: gutterWidth
|
|
11099
11560
|
}
|
|
11100
11561
|
);
|
|
11101
11562
|
}
|
|
11102
|
-
if (
|
|
11563
|
+
if (floating) {
|
|
11103
11564
|
return /* @__PURE__ */ jsx(
|
|
11104
11565
|
"div",
|
|
11105
11566
|
{
|
|
@@ -11231,7 +11692,8 @@ function ColourfulHeader({
|
|
|
11231
11692
|
className,
|
|
11232
11693
|
headerRef,
|
|
11233
11694
|
isFloating,
|
|
11234
|
-
noBottomMargin
|
|
11695
|
+
noBottomMargin,
|
|
11696
|
+
gutter = true
|
|
11235
11697
|
}) {
|
|
11236
11698
|
const isBold = intensity === "bold";
|
|
11237
11699
|
const hasBreadcrumbs = !!(breadcrumbs && breadcrumbs.length > 0);
|
|
@@ -11271,11 +11733,12 @@ function ColourfulHeader({
|
|
|
11271
11733
|
"div",
|
|
11272
11734
|
{
|
|
11273
11735
|
className: cn(
|
|
11274
|
-
"relative z-10 w-full mx-auto
|
|
11736
|
+
"relative z-10 w-full mx-auto pb-ds-6",
|
|
11737
|
+
gutter && "px-ds-6",
|
|
11275
11738
|
hasBreadcrumbs ? "pt-ds-3" : "pt-ds-6"
|
|
11276
11739
|
),
|
|
11277
11740
|
style: {
|
|
11278
|
-
maxWidth: contentMaxWidth ?? "var(--ds-bp-xl)",
|
|
11741
|
+
maxWidth: gutter ? contentMaxWidth ?? "var(--ds-bp-xl)" : void 0,
|
|
11279
11742
|
containerType: "inline-size",
|
|
11280
11743
|
...overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px))` } : {}
|
|
11281
11744
|
},
|
|
@@ -11557,7 +12020,7 @@ function SnappingHeader({
|
|
|
11557
12020
|
}
|
|
11558
12021
|
);
|
|
11559
12022
|
if (effectiveMaxWidth) {
|
|
11560
|
-
return /* @__PURE__ */ jsx("div", { className:
|
|
12023
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full mx-auto px-ds-6", style: { maxWidth: effectiveMaxWidth, containerType: "inline-size" }, children: innerContent });
|
|
11561
12024
|
}
|
|
11562
12025
|
return innerContent;
|
|
11563
12026
|
})()
|
|
@@ -12197,8 +12660,7 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
12197
12660
|
hasBorder && "border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
12198
12661
|
GLASS_BACKDROP
|
|
12199
12662
|
);
|
|
12200
|
-
const
|
|
12201
|
-
const padStyle = resolvedSize === "sm" ? "var(--ds-space-2) var(--ds-space-4)" : resolvedSize === "lg" ? `var(--ds-space-2) var(${isMobile ? "--ds-space-3" : "--ds-space-6"})` : `var(--ds-space-1) var(${isMobile ? "--ds-space-3" : "--ds-space-6"})`;
|
|
12663
|
+
const padStyle = resolvedSize === "sm" ? "var(--ds-space-2) var(--ds-space-4)" : resolvedSize === "lg" ? `var(--ds-space-2) var(--ds-space-6)` : `var(--ds-space-1) var(--ds-space-6)`;
|
|
12202
12664
|
const floatingClasses = isFloating ? cn("rounded-[var(--ds-radius-md)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]", GLASS_SURFACE) : void 0;
|
|
12203
12665
|
let headerEl;
|
|
12204
12666
|
if (align === "center") {
|
|
@@ -12365,7 +12827,8 @@ function MobileMenuItem({
|
|
|
12365
12827
|
}
|
|
12366
12828
|
var DEFAULT_BUTTON_ATTR = "data-dialog-default-button";
|
|
12367
12829
|
var sizeClasses = {
|
|
12368
|
-
|
|
12830
|
+
// round 16 (the owner's item 5): the small dialog is 448 px, not 384 — a delete confirmation with a typed field was cramped
|
|
12831
|
+
sm: "max-w-md",
|
|
12369
12832
|
md: "max-w-lg",
|
|
12370
12833
|
lg: "max-w-2xl",
|
|
12371
12834
|
xl: "max-w-4xl",
|
|
@@ -13484,8 +13947,11 @@ function useToast() {
|
|
|
13484
13947
|
if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
|
|
13485
13948
|
return ctx;
|
|
13486
13949
|
}
|
|
13950
|
+
function useToastOptional() {
|
|
13951
|
+
return useContext(ToastContext);
|
|
13952
|
+
}
|
|
13487
13953
|
var toastSeq = 0;
|
|
13488
|
-
function ToastProvider({ children, maxVisible = 1, position = "bottom-right", duration = 5e3, mode, pauseOnHover = true }) {
|
|
13954
|
+
function ToastProvider({ children, maxVisible = 1, position = "bottom-right", duration = 5e3, mode, pauseOnHover = true, coalesce = true }) {
|
|
13489
13955
|
const [queue, setQueue] = useState([]);
|
|
13490
13956
|
const isMobile = useBreakpoint("sm");
|
|
13491
13957
|
const dismiss = useCallback((id) => {
|
|
@@ -13502,11 +13968,24 @@ function ToastProvider({ children, maxVisible = 1, position = "bottom-right", du
|
|
|
13502
13968
|
message,
|
|
13503
13969
|
variant: options.variant ?? "default",
|
|
13504
13970
|
duration: options.duration ?? duration,
|
|
13505
|
-
action: options.action
|
|
13971
|
+
action: options.action,
|
|
13972
|
+
key: options.key ?? options.variant ?? "default"
|
|
13506
13973
|
};
|
|
13507
|
-
|
|
13974
|
+
const slots = Math.max(1, maxVisible);
|
|
13975
|
+
setQueue((q) => {
|
|
13976
|
+
if (q.some((t) => t.id === id)) return q.map((t) => t.id === id ? entry : t);
|
|
13977
|
+
if (coalesce && q.length >= slots) {
|
|
13978
|
+
const waiting = q.findIndex((t, i) => i >= slots && t.key === entry.key);
|
|
13979
|
+
if (waiting >= 0) {
|
|
13980
|
+
const next = [...q];
|
|
13981
|
+
next[waiting] = entry;
|
|
13982
|
+
return next;
|
|
13983
|
+
}
|
|
13984
|
+
}
|
|
13985
|
+
return [...q, entry];
|
|
13986
|
+
});
|
|
13508
13987
|
return id;
|
|
13509
|
-
}, [duration]);
|
|
13988
|
+
}, [duration, maxVisible, coalesce]);
|
|
13510
13989
|
const api = useMemo(() => ({
|
|
13511
13990
|
toast,
|
|
13512
13991
|
success: (m, o) => toast(m, { ...o, variant: "success" }),
|
|
@@ -13561,6 +14040,75 @@ function ToastProvider({ children, maxVisible = 1, position = "bottom-right", du
|
|
|
13561
14040
|
)
|
|
13562
14041
|
] });
|
|
13563
14042
|
}
|
|
14043
|
+
function useDestructiveAction(options) {
|
|
14044
|
+
const { action, title, description, confirmLabel, typeToConfirm, onConfirm, onUndo, undoMessage, severity } = options;
|
|
14045
|
+
const preferences = usePreferences();
|
|
14046
|
+
const toast = useToastOptional();
|
|
14047
|
+
const [open, setOpen] = useState(false);
|
|
14048
|
+
const [typed, setTyped] = useState("");
|
|
14049
|
+
const [busy, setBusy] = useState(false);
|
|
14050
|
+
const key = action ?? preferenceActionKey(title.replace(/\?$/, ""));
|
|
14051
|
+
const mode = preferences.destructiveMode ?? "dialog";
|
|
14052
|
+
const high = severity === "high" || (preferences.highSeverityActions ?? []).includes(key);
|
|
14053
|
+
const label = confirmLabel ?? title.replace(/\?$/, "").split(/\s+/)[0];
|
|
14054
|
+
const listed = (preferences.typeToConfirmActions ?? []).includes(key) || high;
|
|
14055
|
+
const typedText = typeToConfirm && typeToConfirm.trim() ? typeToConfirm : label.toUpperCase();
|
|
14056
|
+
const typedRequired = listed;
|
|
14057
|
+
const undoable = mode === "undo" && !high && typeof onUndo === "function" && toast !== null;
|
|
14058
|
+
const close = () => {
|
|
14059
|
+
setOpen(false);
|
|
14060
|
+
setTyped("");
|
|
14061
|
+
};
|
|
14062
|
+
const failureMessage = (err) => err instanceof Error && err.message ? err.message : `${title.replace(/\?$/, "")} failed. Try again.`;
|
|
14063
|
+
const confirm = async () => {
|
|
14064
|
+
setBusy(true);
|
|
14065
|
+
try {
|
|
14066
|
+
await onConfirm();
|
|
14067
|
+
close();
|
|
14068
|
+
} catch (err) {
|
|
14069
|
+
toast?.error(failureMessage(err));
|
|
14070
|
+
} finally {
|
|
14071
|
+
setBusy(false);
|
|
14072
|
+
}
|
|
14073
|
+
};
|
|
14074
|
+
const run = () => {
|
|
14075
|
+
if (undoable) {
|
|
14076
|
+
void (async () => {
|
|
14077
|
+
try {
|
|
14078
|
+
await onConfirm();
|
|
14079
|
+
} catch (err) {
|
|
14080
|
+
toast.error(failureMessage(err));
|
|
14081
|
+
return;
|
|
14082
|
+
}
|
|
14083
|
+
const seconds = preferences.undoWindowSeconds ?? 5;
|
|
14084
|
+
toast.success(undoMessage ?? `${title.replace(/\?$/, "")} done`, { duration: seconds * 1e3, action: { label: "Undo", onClick: onUndo } });
|
|
14085
|
+
})();
|
|
14086
|
+
return;
|
|
14087
|
+
}
|
|
14088
|
+
setOpen(true);
|
|
14089
|
+
};
|
|
14090
|
+
const matches = !typedRequired || typed.trim().toLowerCase() === typedText.trim().toLowerCase();
|
|
14091
|
+
const element = open ? /* @__PURE__ */ jsx(
|
|
14092
|
+
Dialog,
|
|
14093
|
+
{
|
|
14094
|
+
open,
|
|
14095
|
+
onClose: close,
|
|
14096
|
+
title,
|
|
14097
|
+
description,
|
|
14098
|
+
variant: "destructive",
|
|
14099
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14100
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: close, disabled: busy, children: "Cancel" }),
|
|
14101
|
+
/* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => void confirm(), disabled: !matches || busy, loading: busy, children: label })
|
|
14102
|
+
] }),
|
|
14103
|
+
children: typedRequired && /* @__PURE__ */ jsx(Field, { label: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14104
|
+
"Type ",
|
|
14105
|
+
/* @__PURE__ */ jsx("strong", { children: typedText }),
|
|
14106
|
+
" to confirm"
|
|
14107
|
+
] }), children: /* @__PURE__ */ jsx(Input, { value: typed, onChange: (e) => setTyped(e.target.value), autoComplete: "off" }) })
|
|
14108
|
+
}
|
|
14109
|
+
) : null;
|
|
14110
|
+
return { run, element, open };
|
|
14111
|
+
}
|
|
13564
14112
|
var SectionHeading = forwardRef(function SectionHeading2({
|
|
13565
14113
|
title,
|
|
13566
14114
|
description,
|
|
@@ -13700,6 +14248,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
|
|
|
13700
14248
|
return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
|
|
13701
14249
|
});
|
|
13702
14250
|
|
|
13703
|
-
export { Accordion, ActionPanel, ActionPanelGroup, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimePicker, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, useFormContext, useSidebar, useToast };
|
|
14251
|
+
export { Accordion, ActionPanel, ActionPanelGroup, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimePicker, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, useContentWidth, useDestructiveAction, useFormContext, useSidebar, useToast, useToastOptional };
|
|
13704
14252
|
//# sourceMappingURL=index.js.map
|
|
13705
14253
|
//# sourceMappingURL=index.js.map
|