gridsmith-ui 0.17.1 → 0.17.3
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/README.md +2 -0
- package/dist/charts.d.ts +88 -24
- package/dist/charts.js +1043 -398
- package/dist/charts.js.map +1 -1
- package/dist/{chunk-J43HCK7Q.js → chunk-CIVSNXFG.js} +12 -5
- package/dist/chunk-CIVSNXFG.js.map +1 -0
- package/dist/{chunk-YQABRUWD.js → chunk-JXANCXK6.js} +7 -5
- package/dist/chunk-JXANCXK6.js.map +1 -0
- package/dist/editor.js +1 -1
- package/dist/index.d.ts +102 -40
- package/dist/index.js +683 -358
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +19 -4
- package/dist/kanban.js +137 -31
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.js +2 -2
- package/dist/roots.css +14 -0
- package/dist/tokens.css +280 -5
- package/dist-static/tokens.css +280 -5
- package/package.json +3 -3
- package/dist/chunk-J43HCK7Q.js.map +0 -1
- package/dist/chunk-YQABRUWD.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Button, useAppShell, ControlSizeContext, useDirtyGuard, OverlayCloseCtx, DiscardConfirm, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-
|
|
2
|
-
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-
|
|
1
|
+
import { Button, useAppShell, REACT_VERSION_PROBLEM, ControlSizeContext, useDirtyGuard, OverlayCloseCtx, DiscardConfirm, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-CIVSNXFG.js';
|
|
2
|
+
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-CIVSNXFG.js';
|
|
3
3
|
import { Skeleton } from './chunk-Z63OSN64.js';
|
|
4
4
|
export { Skeleton } from './chunk-Z63OSN64.js';
|
|
5
|
-
import { FOCUSABLE, usePopupFocus, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, focusAfterRemoval, rovingTabStop, useGridKeyboard, useNonModalDialog, usePressMarks, useReturnFocus, useCloseOnFocusOut } from './chunk-
|
|
6
|
-
export { useGridKeyboard } from './chunk-
|
|
5
|
+
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';
|
|
6
|
+
export { useGridKeyboard } from './chunk-JXANCXK6.js';
|
|
7
7
|
import { Link } from './chunk-XGSQOMEY.js';
|
|
8
8
|
export { CodeBlock, Divider, Link } from './chunk-XGSQOMEY.js';
|
|
9
9
|
import { Badge } from './chunk-PVTGMCVR.js';
|
|
@@ -2012,8 +2012,8 @@ function DateRangePicker({
|
|
|
2012
2012
|
};
|
|
2013
2013
|
const previewEnd = value.start && !value.end && hover && hover >= value.start ? hover : null;
|
|
2014
2014
|
const rangeStart = value.start;
|
|
2015
|
-
const
|
|
2016
|
-
const inRange = (d) => !!(rangeStart &&
|
|
2015
|
+
const rangeEnd2 = value.end ?? previewEnd;
|
|
2016
|
+
const inRange = (d) => !!(rangeStart && rangeEnd2 && d > rangeStart && d < rangeEnd2);
|
|
2017
2017
|
const months = [viewDate, addMonths(viewDate, 1)];
|
|
2018
2018
|
const summary = value.start && value.end ? `${fmt(value.start)} \u2013 ${fmt(value.end)}` : value.start ? `${fmt(value.start)} \u2013 \u2026` : null;
|
|
2019
2019
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
@@ -2094,7 +2094,7 @@ function DateRangePicker({
|
|
|
2094
2094
|
getMonthGrid(m.getFullYear(), m.getMonth(), weekStartsOn).map((week, w) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5", children: week.map((d) => {
|
|
2095
2095
|
if (!isSameMonth(d, m)) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, d.toISOString());
|
|
2096
2096
|
const isStart = !!rangeStart && isSameDay2(d, rangeStart);
|
|
2097
|
-
const isEnd = !!
|
|
2097
|
+
const isEnd = !!rangeEnd2 && isSameDay2(d, rangeEnd2);
|
|
2098
2098
|
const between = inRange(d);
|
|
2099
2099
|
const dis = isDisabledDay(d);
|
|
2100
2100
|
return /* @__PURE__ */ jsx(
|
|
@@ -2325,18 +2325,21 @@ function Field({ label, children, hint, error, required, labelAction, id: idProp
|
|
|
2325
2325
|
const { error: errorFlag, ...ariaOnly } = controlProps;
|
|
2326
2326
|
control = cloneElement(child, isNative ? ariaOnly : { ...ariaOnly, ...errorFlag ? { error: true } : {} });
|
|
2327
2327
|
}
|
|
2328
|
-
return
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2328
|
+
return (
|
|
2329
|
+
// In a settings panel a field keeps the narrow reading width however wide the page is (--ds-form-max, Sprint 25.9 A4)
|
|
2330
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-1.5 max-w-[var(--ds-form-max,none)]", className), children: [
|
|
2331
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-2", children: [
|
|
2332
|
+
/* @__PURE__ */ jsxs(Label, { id: labelId, htmlFor: id, children: [
|
|
2333
|
+
label,
|
|
2334
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-ds-0.5 text-[var(--ds-status-error)]", children: "*" })
|
|
2335
|
+
] }),
|
|
2336
|
+
labelAction
|
|
2333
2337
|
] }),
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
] });
|
|
2338
|
+
/* @__PURE__ */ jsx(FieldContext.Provider, { value: fieldContext, children: control }),
|
|
2339
|
+
hint && /* @__PURE__ */ jsx("p", { id: hintId, className: "text-xs text-[var(--ds-text-muted)]", children: hint }),
|
|
2340
|
+
hasError && /* @__PURE__ */ jsx(InlineFieldError, { id: errorId, message: error, className: "mt-0" })
|
|
2341
|
+
] })
|
|
2342
|
+
);
|
|
2340
2343
|
}
|
|
2341
2344
|
function TruncFileName({ children, className }) {
|
|
2342
2345
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
@@ -2506,7 +2509,8 @@ function SliderRange({
|
|
|
2506
2509
|
label,
|
|
2507
2510
|
"aria-label": ariaLabel,
|
|
2508
2511
|
"aria-describedby": describedByProp,
|
|
2509
|
-
trackStyle
|
|
2512
|
+
trackStyle,
|
|
2513
|
+
formatValue
|
|
2510
2514
|
}) {
|
|
2511
2515
|
const field = useField();
|
|
2512
2516
|
const ownId = useId();
|
|
@@ -2519,6 +2523,8 @@ function SliderRange({
|
|
|
2519
2523
|
const high = isRange ? value[1] : value;
|
|
2520
2524
|
const trackRef = useRef(null);
|
|
2521
2525
|
const pct = (v) => (v - min) / (max - min) * 100;
|
|
2526
|
+
const shown = (v) => formatValue ? formatValue(v) : v;
|
|
2527
|
+
const valueText = (v) => formatValue ? formatValue(v) : void 0;
|
|
2522
2528
|
const handleChange = useCallback(
|
|
2523
2529
|
(which, raw) => {
|
|
2524
2530
|
const v = Math.round(raw / step) * step;
|
|
@@ -2571,7 +2577,7 @@ function SliderRange({
|
|
|
2571
2577
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("space-y-ds-1", disabled && "opacity-disabled", className), children: [
|
|
2572
2578
|
(showLabel || showValue) && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-ds-2", showLabel ? "justify-between" : "justify-end"), children: [
|
|
2573
2579
|
showLabel && /* @__PURE__ */ jsx("span", { id: `${ownId}-label`, className: "text-sm font-medium leading-none text-[var(--ds-text-secondary)]", children: label }),
|
|
2574
|
-
showValue && /* @__PURE__ */ jsx("span", { className: "text-xs font-mono tabular-nums text-[var(--ds-text-muted)]", children: isRange ? `${low} \u2013 ${high}` : low })
|
|
2580
|
+
showValue && /* @__PURE__ */ jsx("span", { className: "text-xs font-mono tabular-nums text-[var(--ds-text-muted)]", children: isRange ? `${shown(low)} \u2013 ${shown(high)}` : shown(low) })
|
|
2575
2581
|
] }),
|
|
2576
2582
|
isRange && nameId && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2577
2583
|
/* @__PURE__ */ jsx("span", { id: `${ownId}-minimum`, hidden: true, children: "minimum" }),
|
|
@@ -2604,6 +2610,7 @@ function SliderRange({
|
|
|
2604
2610
|
"aria-valuemin": min,
|
|
2605
2611
|
"aria-valuemax": high,
|
|
2606
2612
|
"aria-valuenow": low,
|
|
2613
|
+
"aria-valuetext": valueText(low),
|
|
2607
2614
|
"aria-invalid": error || void 0,
|
|
2608
2615
|
onKeyDown: handleKeyDown("low"),
|
|
2609
2616
|
onPointerDown: handlePointerDown("low"),
|
|
@@ -2629,6 +2636,7 @@ function SliderRange({
|
|
|
2629
2636
|
"aria-valuemin": isRange ? low : min,
|
|
2630
2637
|
"aria-valuemax": max,
|
|
2631
2638
|
"aria-valuenow": high,
|
|
2639
|
+
"aria-valuetext": valueText(high),
|
|
2632
2640
|
"aria-invalid": error || void 0,
|
|
2633
2641
|
onKeyDown: handleKeyDown("high"),
|
|
2634
2642
|
onPointerDown: handlePointerDown("high"),
|
|
@@ -4302,7 +4310,7 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4302
4310
|
f.message
|
|
4303
4311
|
] }, f.id || f.label)) }) }) : null;
|
|
4304
4312
|
const actionsNode = actions && !drawerFooter ? /* @__PURE__ */ jsx("div", { "data-form-actions": "", className: cn("flex flex-wrap items-center gap-ds-2 pt-ds-2", actionsAlign === "end" ? "justify-end" : "justify-start"), children: actions }) : null;
|
|
4305
|
-
return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted }, children: /* @__PURE__ */ jsxs("form", { ref: setRefs, id: drawerFooter ? formId : void 0, onSubmit: handleSubmit, onFocusCapture: userActed, onInputCapture: userActed, className: cn("flex flex-col gap-ds-5", className), noValidate: true, children: [
|
|
4313
|
+
return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted }, children: /* @__PURE__ */ jsxs("form", { ref: setRefs, id: drawerFooter ? formId : void 0, onSubmit: handleSubmit, onFocusCapture: userActed, onInputCapture: userActed, className: cn("flex flex-col gap-ds-5 max-w-[var(--ds-form-max,none)]", className), noValidate: true, children: [
|
|
4306
4314
|
summaryNode && /* @__PURE__ */ jsx("div", { "data-form-error-summary": "", children: summaryNode }),
|
|
4307
4315
|
children,
|
|
4308
4316
|
actionsNode
|
|
@@ -5381,11 +5389,27 @@ var columnClasses = {
|
|
|
5381
5389
|
3: "grid-cols-3",
|
|
5382
5390
|
4: "grid-cols-4"
|
|
5383
5391
|
};
|
|
5392
|
+
var autoColumnClasses = {
|
|
5393
|
+
horizontal: {
|
|
5394
|
+
2: "grid-cols-[repeat(auto-fill,minmax(max(min(20rem,100%),calc((100%_-_var(--ds-space-8))/2)),1fr))]",
|
|
5395
|
+
3: "grid-cols-[repeat(auto-fill,minmax(max(min(20rem,100%),calc((100%_-_2*var(--ds-space-8))/3)),1fr))]",
|
|
5396
|
+
4: "grid-cols-[repeat(auto-fill,minmax(max(min(20rem,100%),calc((100%_-_3*var(--ds-space-8))/4)),1fr))]"
|
|
5397
|
+
},
|
|
5398
|
+
vertical: {
|
|
5399
|
+
2: "grid-cols-[repeat(auto-fill,minmax(max(min(8rem,100%),calc((100%_-_var(--ds-space-6))/2)),1fr))]",
|
|
5400
|
+
3: "grid-cols-[repeat(auto-fill,minmax(max(min(8rem,100%),calc((100%_-_2*var(--ds-space-6))/3)),1fr))]",
|
|
5401
|
+
4: "grid-cols-[repeat(auto-fill,minmax(max(min(8rem,100%),calc((100%_-_3*var(--ds-space-6))/4)),1fr))]"
|
|
5402
|
+
}
|
|
5403
|
+
};
|
|
5384
5404
|
var spanClasses = {
|
|
5385
5405
|
2: "col-span-2",
|
|
5386
5406
|
3: "col-span-3",
|
|
5387
5407
|
4: "col-span-4"
|
|
5388
5408
|
};
|
|
5409
|
+
function spanClass(span, columns) {
|
|
5410
|
+
if (!span || span <= 1) return void 0;
|
|
5411
|
+
return span >= columns ? "col-span-full" : spanClasses[span];
|
|
5412
|
+
}
|
|
5389
5413
|
var stackBreakpoints = {
|
|
5390
5414
|
sm: "max-sm:grid-cols-1",
|
|
5391
5415
|
md: "max-md:grid-cols-1",
|
|
@@ -5402,6 +5426,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5402
5426
|
}, ref) {
|
|
5403
5427
|
const s = sizeStyles3[size];
|
|
5404
5428
|
const stackBelow = stackBelowProp ?? (columns > 1 ? "sm" : void 0);
|
|
5429
|
+
const templateClass = (layout) => columns > 1 && stackBelow !== "none" ? autoColumnClasses[layout][columns] : columnClasses[columns];
|
|
5405
5430
|
if (orientation === "vertical") {
|
|
5406
5431
|
return /* @__PURE__ */ jsx(
|
|
5407
5432
|
"dl",
|
|
@@ -5409,7 +5434,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5409
5434
|
ref,
|
|
5410
5435
|
className: cn(
|
|
5411
5436
|
"grid",
|
|
5412
|
-
|
|
5437
|
+
templateClass("vertical"),
|
|
5413
5438
|
"gap-x-ds-6 gap-y-ds-1",
|
|
5414
5439
|
stackBelow && stackBelow !== "none" && stackBreakpoints[stackBelow],
|
|
5415
5440
|
dividers && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
|
|
@@ -5420,7 +5445,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5420
5445
|
{
|
|
5421
5446
|
className: cn(
|
|
5422
5447
|
s.py,
|
|
5423
|
-
item.span
|
|
5448
|
+
spanClass(item.span, columns)
|
|
5424
5449
|
),
|
|
5425
5450
|
children: [
|
|
5426
5451
|
/* @__PURE__ */ jsxs(
|
|
@@ -5451,7 +5476,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5451
5476
|
ref,
|
|
5452
5477
|
className: cn(
|
|
5453
5478
|
"grid",
|
|
5454
|
-
|
|
5479
|
+
templateClass("horizontal"),
|
|
5455
5480
|
"gap-x-ds-8",
|
|
5456
5481
|
stackBelow && stackBelow !== "none" && stackBreakpoints[stackBelow],
|
|
5457
5482
|
dividers && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
|
|
@@ -5464,7 +5489,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5464
5489
|
"flex items-start justify-between",
|
|
5465
5490
|
s.py,
|
|
5466
5491
|
s.gap,
|
|
5467
|
-
item.span
|
|
5492
|
+
spanClass(item.span, columns)
|
|
5468
5493
|
),
|
|
5469
5494
|
children: [
|
|
5470
5495
|
/* @__PURE__ */ jsxs(
|
|
@@ -5581,6 +5606,22 @@ function TruncCell({ children, lines }) {
|
|
|
5581
5606
|
if (!isTruncated) return cell;
|
|
5582
5607
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: cell });
|
|
5583
5608
|
}
|
|
5609
|
+
var TITLE_CLASSES = "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] break-words";
|
|
5610
|
+
var FRAME_CLASSES = cn(
|
|
5611
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
5612
|
+
"rounded-[var(--ds-radius-md)]",
|
|
5613
|
+
GLASS_SURFACE,
|
|
5614
|
+
"bg-[var(--ds-bg-surface)]"
|
|
5615
|
+
);
|
|
5616
|
+
function TableHeading({ title, description, actions, titleId, descriptionId, inset }) {
|
|
5617
|
+
return /* @__PURE__ */ jsxs("div", { "data-table-heading": "", className: cn("flex flex-wrap items-start justify-between gap-ds-4", inset ? "px-ds-5 py-ds-4" : "pb-ds-4"), children: [
|
|
5618
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 grow basis-1/2 [min-width:min-content] break-words", children: [
|
|
5619
|
+
/* @__PURE__ */ jsx("h3", { id: titleId, className: TITLE_CLASSES, children: title }),
|
|
5620
|
+
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "text-sm text-[var(--ds-text-muted)]", children: description })
|
|
5621
|
+
] }),
|
|
5622
|
+
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0 ml-auto", children: actions })
|
|
5623
|
+
] });
|
|
5624
|
+
}
|
|
5584
5625
|
function Table({
|
|
5585
5626
|
columns,
|
|
5586
5627
|
data,
|
|
@@ -5601,8 +5642,14 @@ function Table({
|
|
|
5601
5642
|
emptyState,
|
|
5602
5643
|
onRowClick,
|
|
5603
5644
|
mobileBreakpoint: mobileBreakpointProp,
|
|
5645
|
+
title,
|
|
5646
|
+
description,
|
|
5647
|
+
actions,
|
|
5604
5648
|
ref
|
|
5605
5649
|
}) {
|
|
5650
|
+
const headingId = useId();
|
|
5651
|
+
const titleId = `${headingId}-title`;
|
|
5652
|
+
const descriptionId = `${headingId}-description`;
|
|
5606
5653
|
const [internalSortKey, setInternalSortKey] = useState(null);
|
|
5607
5654
|
const [internalSortDir, setInternalSortDir] = useState(null);
|
|
5608
5655
|
const [expandedRows, setExpandedRows] = useState(/* @__PURE__ */ new Set());
|
|
@@ -5669,14 +5716,21 @@ function Table({
|
|
|
5669
5716
|
const preferences = useShellPreferences();
|
|
5670
5717
|
const mobileBreakpoint = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? "md";
|
|
5671
5718
|
const isMobile = useBreakpoint(mobileBreakpoint);
|
|
5719
|
+
const cardHeading = title ? /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: false }) : null;
|
|
5720
|
+
const titledCards = (body) => /* @__PURE__ */ jsxs("div", { ref, "data-ds-list": "", "data-gs": "table", className: cn("flex flex-col", className), children: [
|
|
5721
|
+
cardHeading,
|
|
5722
|
+
body
|
|
5723
|
+
] });
|
|
5672
5724
|
if (isMobile) {
|
|
5673
5725
|
if (loading) {
|
|
5674
|
-
return /* @__PURE__ */ jsx("div", {
|
|
5726
|
+
if (title) return titledCards(/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-ds-10", children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" }) }));
|
|
5727
|
+
return /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", "data-gs": "table", className: cn("flex items-center justify-center py-ds-10", className), children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" }) });
|
|
5675
5728
|
}
|
|
5676
5729
|
if (data.length === 0 && emptyState) {
|
|
5677
|
-
return /* @__PURE__ */ jsx("div", {
|
|
5730
|
+
if (title) return titledCards(/* @__PURE__ */ jsx("div", { className: "py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", children: emptyState }));
|
|
5731
|
+
return /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", "data-gs": "table", className: cn("py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", className), children: emptyState });
|
|
5678
5732
|
}
|
|
5679
|
-
|
|
5733
|
+
const cards = /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx("div", { ref: title ? void 0 : ref, "data-ds-list": title ? void 0 : "", "data-gs": title ? void 0 : "table", className: cn("flex flex-col gap-ds-3 overflow-y-auto", title ? "min-h-0" : className), children: sortedWithIndices.map(({ row, originalIdx }, i) => {
|
|
5680
5734
|
const isSelected = selectedSet.has(originalIdx);
|
|
5681
5735
|
return /* @__PURE__ */ jsxs(
|
|
5682
5736
|
"div",
|
|
@@ -5710,173 +5764,179 @@ function Table({
|
|
|
5710
5764
|
i
|
|
5711
5765
|
);
|
|
5712
5766
|
}) }) });
|
|
5767
|
+
return title ? titledCards(cards) : cards;
|
|
5713
5768
|
}
|
|
5714
|
-
|
|
5715
|
-
"
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5769
|
+
const table = /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", ...title ? { "aria-labelledby": titleId, "aria-describedby": description ? descriptionId : void 0 } : {}, children: [
|
|
5770
|
+
/* @__PURE__ */ jsx("thead", { className: cn("bg-[var(--ds-bg-muted)]", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs("tr", { className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
5771
|
+
selectable && /* @__PURE__ */ jsx("th", { className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3"), children: /* @__PURE__ */ jsx(
|
|
5772
|
+
Checkbox,
|
|
5773
|
+
{
|
|
5774
|
+
checked: allSelected,
|
|
5775
|
+
indeterminate: someSelected,
|
|
5776
|
+
onChange: toggleAll
|
|
5777
|
+
}
|
|
5778
|
+
) }),
|
|
5779
|
+
expandable && /* @__PURE__ */ jsx("th", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3") }),
|
|
5780
|
+
columns.map((col) => {
|
|
5781
|
+
const isSortable = sortable || col.sortable;
|
|
5782
|
+
const isActiveSort = sortKey === col.key;
|
|
5783
|
+
const headerKind = kindOf(col);
|
|
5784
|
+
const headerAlign = col.align ?? (headerKind === "number" ? "right" : "left");
|
|
5785
|
+
const shrink = (headerKind === "number" || headerKind === "date") && !col.maxWidth;
|
|
5786
|
+
return /* @__PURE__ */ jsx(
|
|
5787
|
+
"th",
|
|
5788
|
+
{
|
|
5789
|
+
className: cn(
|
|
5790
|
+
density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
|
|
5791
|
+
shrink && "w-px whitespace-nowrap",
|
|
5792
|
+
"font-[var(--ds-weight-heading)] text-[var(--ds-text-secondary)]",
|
|
5793
|
+
"text-xs uppercase tracking-wider",
|
|
5794
|
+
headerAlign === "right" ? "text-right" : headerAlign === "center" ? "text-center" : "text-left",
|
|
5795
|
+
isSortable && "cursor-pointer select-none hover:text-[var(--ds-text-primary)]"
|
|
5796
|
+
),
|
|
5797
|
+
style: col.maxWidth || col.width || col.minWidth ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth } : void 0,
|
|
5798
|
+
onClick: isSortable ? () => handleSort(col.key) : void 0,
|
|
5799
|
+
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-ds-1", children: [
|
|
5800
|
+
col.header,
|
|
5801
|
+
isSortable && isActiveSort && /* @__PURE__ */ jsx(
|
|
5802
|
+
Icon,
|
|
5803
|
+
{
|
|
5804
|
+
name: "chevron-right",
|
|
5805
|
+
size: 12,
|
|
5806
|
+
className: cn(
|
|
5807
|
+
"transition-transform",
|
|
5808
|
+
sortDir === "asc" ? "-rotate-90" : "rotate-90"
|
|
5809
|
+
)
|
|
5810
|
+
}
|
|
5811
|
+
)
|
|
5812
|
+
] })
|
|
5813
|
+
},
|
|
5814
|
+
col.key
|
|
5815
|
+
);
|
|
5816
|
+
})
|
|
5817
|
+
] }) }),
|
|
5818
|
+
/* @__PURE__ */ jsx("tbody", { children: loading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
5819
|
+
"td",
|
|
5820
|
+
{
|
|
5821
|
+
colSpan: columns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0),
|
|
5822
|
+
className: "px-ds-4 py-ds-10 text-center",
|
|
5823
|
+
children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" })
|
|
5824
|
+
}
|
|
5825
|
+
) }) : data.length === 0 && emptyState ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
5826
|
+
"td",
|
|
5827
|
+
{
|
|
5828
|
+
colSpan: columns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0),
|
|
5829
|
+
className: "px-ds-4 py-ds-10 text-center text-sm text-[var(--ds-text-muted)]",
|
|
5830
|
+
children: emptyState
|
|
5831
|
+
}
|
|
5832
|
+
) }) : sortedWithIndices.map(({ row, originalIdx }, i) => {
|
|
5833
|
+
const isSelected = selectedSet.has(originalIdx);
|
|
5834
|
+
const isExpanded = expandedRows.has(i);
|
|
5835
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5836
|
+
/* @__PURE__ */ jsxs(
|
|
5837
|
+
"tr",
|
|
5838
|
+
{
|
|
5839
|
+
className: cn(
|
|
5840
|
+
"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0",
|
|
5841
|
+
"transition-colors",
|
|
5842
|
+
isSelected ? "bg-[var(--ds-accent-subtle)]" : striped && i % 2 === 1 ? "bg-[var(--ds-bg-muted)]/50" : "hover:bg-[var(--ds-bg-muted)]",
|
|
5843
|
+
onRowClick && "cursor-pointer focus-visible:outline-none focus-visible:shadow-[inset_var(--ds-shadow-focus)]"
|
|
5844
|
+
),
|
|
5845
|
+
onClick: onRowClick ? () => onRowClick(row, originalIdx) : void 0,
|
|
5846
|
+
tabIndex: onRowClick ? 0 : void 0,
|
|
5847
|
+
onKeyDown: onRowClick ? (e) => {
|
|
5848
|
+
if (e.target !== e.currentTarget) return;
|
|
5849
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
5850
|
+
e.preventDefault();
|
|
5851
|
+
onRowClick(row, originalIdx);
|
|
5852
|
+
}
|
|
5853
|
+
} : void 0,
|
|
5854
|
+
children: [
|
|
5855
|
+
selectable && /* @__PURE__ */ jsx("td", { className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3"), children: /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onChange: () => toggleRow(originalIdx) }) }),
|
|
5856
|
+
expandable && /* @__PURE__ */ jsx("td", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3"), children: /* @__PURE__ */ jsx(
|
|
5857
|
+
"button",
|
|
5858
|
+
{
|
|
5859
|
+
onClick: () => toggleExpand(i),
|
|
5860
|
+
className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] cursor-pointer",
|
|
5861
|
+
"aria-expanded": isExpanded,
|
|
5862
|
+
"aria-label": "Expand row",
|
|
5863
|
+
children: /* @__PURE__ */ jsx(
|
|
5760
5864
|
Icon,
|
|
5761
5865
|
{
|
|
5762
5866
|
name: "chevron-right",
|
|
5763
|
-
size:
|
|
5764
|
-
className: cn(
|
|
5765
|
-
"transition-transform",
|
|
5766
|
-
sortDir === "asc" ? "-rotate-90" : "rotate-90"
|
|
5767
|
-
)
|
|
5867
|
+
size: 14,
|
|
5868
|
+
className: cn("transition-transform", isExpanded && "rotate-90")
|
|
5768
5869
|
}
|
|
5769
5870
|
)
|
|
5770
|
-
|
|
5771
|
-
},
|
|
5772
|
-
col
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5871
|
+
}
|
|
5872
|
+
) }),
|
|
5873
|
+
columns.map((col) => {
|
|
5874
|
+
const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
|
|
5875
|
+
const kind = kindOf(col);
|
|
5876
|
+
const alignClass = col.align ? col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left" : kind === "number" ? "text-right" : "text-left";
|
|
5877
|
+
const cellContent = row[col.key];
|
|
5878
|
+
const shrink = (kind === "number" || kind === "date") && !col.maxWidth;
|
|
5879
|
+
let inner;
|
|
5880
|
+
if (truncLines > 0) {
|
|
5881
|
+
inner = /* @__PURE__ */ jsx(TruncCell, { lines: truncLines, children: cellContent });
|
|
5882
|
+
} else if (kind === "email") {
|
|
5883
|
+
inner = /* @__PURE__ */ jsx("span", { className: "max-w-[40ch] truncate inline-block align-bottom", title: typeof cellContent === "string" ? cellContent : void 0, children: cellContent });
|
|
5884
|
+
} else {
|
|
5885
|
+
inner = cellContent;
|
|
5886
|
+
}
|
|
5887
|
+
const align = col.align ?? (kind === "number" ? "right" : "left");
|
|
5888
|
+
if (align !== "left" && cellContent !== null && cellContent !== void 0 && typeof cellContent !== "string" && typeof cellContent !== "number") {
|
|
5889
|
+
inner = /* @__PURE__ */ jsx("div", { className: cn("flex items-center", align === "center" ? "justify-center" : "justify-end"), children: inner });
|
|
5890
|
+
}
|
|
5891
|
+
return /* @__PURE__ */ jsx(
|
|
5892
|
+
"td",
|
|
5893
|
+
{
|
|
5894
|
+
className: cn(
|
|
5895
|
+
density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
|
|
5896
|
+
"text-[var(--ds-text-primary)]",
|
|
5897
|
+
alignClass,
|
|
5898
|
+
shrink && "w-px whitespace-nowrap"
|
|
5899
|
+
),
|
|
5900
|
+
style: col.maxWidth || col.width || col.minWidth ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth } : void 0,
|
|
5901
|
+
children: inner
|
|
5902
|
+
},
|
|
5903
|
+
col.key
|
|
5904
|
+
);
|
|
5905
|
+
})
|
|
5906
|
+
]
|
|
5782
5907
|
}
|
|
5783
|
-
)
|
|
5908
|
+
),
|
|
5909
|
+
expandable && isExpanded && renderExpanded && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
5784
5910
|
"td",
|
|
5785
5911
|
{
|
|
5786
|
-
colSpan: columns.length + (selectable ? 1 : 0) +
|
|
5787
|
-
className: "px-ds-
|
|
5788
|
-
children:
|
|
5912
|
+
colSpan: columns.length + (selectable ? 1 : 0) + 1,
|
|
5913
|
+
className: "bg-[var(--ds-bg-muted)] px-ds-6 py-ds-4 text-sm text-[var(--ds-text-primary)]",
|
|
5914
|
+
children: renderExpanded(row, i)
|
|
5789
5915
|
}
|
|
5790
|
-
) })
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
expandable && /* @__PURE__ */ jsx("td", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3"), children: /* @__PURE__ */ jsx(
|
|
5815
|
-
"button",
|
|
5816
|
-
{
|
|
5817
|
-
onClick: () => toggleExpand(i),
|
|
5818
|
-
className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] cursor-pointer",
|
|
5819
|
-
"aria-expanded": isExpanded,
|
|
5820
|
-
"aria-label": "Expand row",
|
|
5821
|
-
children: /* @__PURE__ */ jsx(
|
|
5822
|
-
Icon,
|
|
5823
|
-
{
|
|
5824
|
-
name: "chevron-right",
|
|
5825
|
-
size: 14,
|
|
5826
|
-
className: cn("transition-transform", isExpanded && "rotate-90")
|
|
5827
|
-
}
|
|
5828
|
-
)
|
|
5829
|
-
}
|
|
5830
|
-
) }),
|
|
5831
|
-
columns.map((col) => {
|
|
5832
|
-
const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
|
|
5833
|
-
const kind = kindOf(col);
|
|
5834
|
-
const alignClass = col.align ? col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left" : kind === "number" ? "text-right" : "text-left";
|
|
5835
|
-
const cellContent = row[col.key];
|
|
5836
|
-
const shrink = (kind === "number" || kind === "date") && !col.maxWidth;
|
|
5837
|
-
let inner;
|
|
5838
|
-
if (truncLines > 0) {
|
|
5839
|
-
inner = /* @__PURE__ */ jsx(TruncCell, { lines: truncLines, children: cellContent });
|
|
5840
|
-
} else if (kind === "email") {
|
|
5841
|
-
inner = /* @__PURE__ */ jsx("span", { className: "max-w-[40ch] truncate inline-block align-bottom", title: typeof cellContent === "string" ? cellContent : void 0, children: cellContent });
|
|
5842
|
-
} else {
|
|
5843
|
-
inner = cellContent;
|
|
5844
|
-
}
|
|
5845
|
-
const align = col.align ?? (kind === "number" ? "right" : "left");
|
|
5846
|
-
if (align !== "left" && cellContent !== null && cellContent !== void 0 && typeof cellContent !== "string" && typeof cellContent !== "number") {
|
|
5847
|
-
inner = /* @__PURE__ */ jsx("div", { className: cn("flex items-center", align === "center" ? "justify-center" : "justify-end"), children: inner });
|
|
5848
|
-
}
|
|
5849
|
-
return /* @__PURE__ */ jsx(
|
|
5850
|
-
"td",
|
|
5851
|
-
{
|
|
5852
|
-
className: cn(
|
|
5853
|
-
density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
|
|
5854
|
-
"text-[var(--ds-text-primary)]",
|
|
5855
|
-
alignClass,
|
|
5856
|
-
shrink && "w-px whitespace-nowrap"
|
|
5857
|
-
),
|
|
5858
|
-
style: col.maxWidth || col.width || col.minWidth ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth } : void 0,
|
|
5859
|
-
children: inner
|
|
5860
|
-
},
|
|
5861
|
-
col.key
|
|
5862
|
-
);
|
|
5863
|
-
})
|
|
5864
|
-
]
|
|
5865
|
-
}
|
|
5866
|
-
),
|
|
5867
|
-
expandable && isExpanded && renderExpanded && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
5868
|
-
"td",
|
|
5869
|
-
{
|
|
5870
|
-
colSpan: columns.length + (selectable ? 1 : 0) + 1,
|
|
5871
|
-
className: "bg-[var(--ds-bg-muted)] px-ds-6 py-ds-4 text-sm text-[var(--ds-text-primary)]",
|
|
5872
|
-
children: renderExpanded(row, i)
|
|
5873
|
-
}
|
|
5874
|
-
) })
|
|
5875
|
-
] }, i);
|
|
5876
|
-
}) })
|
|
5877
|
-
] })
|
|
5878
|
-
}
|
|
5879
|
-
);
|
|
5916
|
+
) })
|
|
5917
|
+
] }, i);
|
|
5918
|
+
}) })
|
|
5919
|
+
] });
|
|
5920
|
+
if (!title) {
|
|
5921
|
+
return /* @__PURE__ */ jsx(
|
|
5922
|
+
"div",
|
|
5923
|
+
{
|
|
5924
|
+
ref,
|
|
5925
|
+
"data-ds-list": "",
|
|
5926
|
+
"data-gs": "table",
|
|
5927
|
+
className: cn(
|
|
5928
|
+
"w-full overflow-x-auto",
|
|
5929
|
+
FRAME_CLASSES,
|
|
5930
|
+
className
|
|
5931
|
+
),
|
|
5932
|
+
children: table
|
|
5933
|
+
}
|
|
5934
|
+
);
|
|
5935
|
+
}
|
|
5936
|
+
return /* @__PURE__ */ jsxs("div", { ref, "data-ds-list": "", "data-gs": "table", className: cn("w-full flex flex-col", FRAME_CLASSES, className), children: [
|
|
5937
|
+
/* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: true }),
|
|
5938
|
+
/* @__PURE__ */ jsx("div", { "data-table-scroll": "", className: "min-h-0 overflow-x-auto rounded-b-[inherit]", children: table })
|
|
5939
|
+
] });
|
|
5880
5940
|
}
|
|
5881
5941
|
function optionsKeyForFit(options) {
|
|
5882
5942
|
return options.map((o) => `${o.value}:${o.label}`).join("|");
|
|
@@ -8386,6 +8446,7 @@ function Carousel({
|
|
|
8386
8446
|
"div",
|
|
8387
8447
|
{
|
|
8388
8448
|
ref,
|
|
8449
|
+
"data-gs-clip": "",
|
|
8389
8450
|
className: cn(
|
|
8390
8451
|
"relative overflow-hidden rounded-[var(--ds-radius-md)]",
|
|
8391
8452
|
"bg-[var(--ds-bg-muted)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
@@ -9329,12 +9390,19 @@ var DAY_MS = 864e5;
|
|
|
9329
9390
|
var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
9330
9391
|
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) / DAY_MS);
|
|
9331
9392
|
function dayOfDate(d) {
|
|
9332
|
-
|
|
9393
|
+
const t = d.getTime();
|
|
9394
|
+
if (Number.isNaN(t)) return NaN;
|
|
9395
|
+
const day = utcDay(d.getFullYear(), d.getMonth(), d.getDate());
|
|
9396
|
+
const first = new Date(t);
|
|
9397
|
+
first.setHours(0, 0, 0, 0);
|
|
9398
|
+
if (first.getTime() === t) return day;
|
|
9333
9399
|
const ms = ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1e3 + d.getMilliseconds();
|
|
9334
|
-
return
|
|
9400
|
+
return day + ms / DAY_MS;
|
|
9335
9401
|
}
|
|
9336
9402
|
function dayOf(value) {
|
|
9403
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : NaN;
|
|
9337
9404
|
if (value instanceof Date) return dayOfDate(value);
|
|
9405
|
+
if (typeof value !== "string") return NaN;
|
|
9338
9406
|
const m = DATE_ONLY.exec(value.trim());
|
|
9339
9407
|
if (!m) return dayOfDate(new Date(value));
|
|
9340
9408
|
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
@@ -9347,10 +9415,15 @@ function dateOfDay(day) {
|
|
|
9347
9415
|
const u = new Date(whole * DAY_MS);
|
|
9348
9416
|
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS));
|
|
9349
9417
|
}
|
|
9418
|
+
function isWholeDay(value) {
|
|
9419
|
+
return typeof value === "string" ? DATE_ONLY.test(value.trim()) : Number.isInteger(dayOf(value));
|
|
9420
|
+
}
|
|
9350
9421
|
function endDayOf(value) {
|
|
9351
9422
|
const day = dayOf(value);
|
|
9352
|
-
|
|
9353
|
-
|
|
9423
|
+
return typeof value !== "number" && isWholeDay(value) ? day + 1 : day;
|
|
9424
|
+
}
|
|
9425
|
+
function rangeEnd(start, end) {
|
|
9426
|
+
return end instanceof Date && !isWholeDay(start) ? dayOf(end) : endDayOf(end);
|
|
9354
9427
|
}
|
|
9355
9428
|
var MINOR = { day: "day", week: "week", month: "month", quarter: "quarter" };
|
|
9356
9429
|
var MAJOR = { day: "month", week: "month", month: "year", quarter: "year" };
|
|
@@ -9408,26 +9481,33 @@ function labelsOf(unit, role, day, locale) {
|
|
|
9408
9481
|
forms = role === "major" ? [f({ month: "long", year: "numeric" }), f({ month: "short", year: "numeric" }), f({ month: "short" }), f({ month: "narrow" })] : [f({ month: "long" }), f({ month: "short" }), f({ month: "narrow" })];
|
|
9409
9482
|
} else if (unit === "quarter") forms = [`Q${Math.floor(new Date(day * DAY_MS).getUTCMonth() / 3) + 1}`];
|
|
9410
9483
|
else forms = [f({ year: "numeric" }), f({ year: "2-digit" })];
|
|
9411
|
-
return
|
|
9484
|
+
return forms;
|
|
9412
9485
|
}
|
|
9413
9486
|
var DENSITY = { day: 56, week: 16, month: 4, quarter: 1.5 };
|
|
9414
9487
|
var todays = /* @__PURE__ */ new WeakMap();
|
|
9488
|
+
var awaiting = /* @__PURE__ */ new WeakSet();
|
|
9489
|
+
function awaitsToday(scale) {
|
|
9490
|
+
return awaiting.has(scale);
|
|
9491
|
+
}
|
|
9415
9492
|
function calendarDay(day) {
|
|
9416
9493
|
const d = Math.floor(day);
|
|
9417
9494
|
return { day: d, weekday: weekday(d), key: keyOf("day", d) };
|
|
9418
9495
|
}
|
|
9419
9496
|
function ticks(unit, role, s) {
|
|
9420
9497
|
const out = [];
|
|
9421
|
-
for (let p = periodStart(unit, s.startDay, s.weekStartsOn); p < s.endDay;
|
|
9498
|
+
for (let p = periodStart(unit, s.startDay, s.weekStartsOn); p < s.endDay; ) {
|
|
9499
|
+
const next = periodAfter(unit, p);
|
|
9422
9500
|
const from = Math.max(p, s.startDay);
|
|
9423
|
-
const to = Math.min(
|
|
9501
|
+
const to = Math.min(next, s.endDay);
|
|
9424
9502
|
out.push({ key: keyOf(unit, p), day: from, x: (from - s.startDay) * s.pxPerDay, width: (to - from) * s.pxPerDay, weekday: weekday(from), labels: labelsOf(unit, role, p, s.locale) });
|
|
9503
|
+
if (!(next > p)) break;
|
|
9504
|
+
p = next;
|
|
9425
9505
|
}
|
|
9426
9506
|
return out;
|
|
9427
9507
|
}
|
|
9428
9508
|
function build(s) {
|
|
9429
9509
|
const { startDay, pxPerDay } = s;
|
|
9430
|
-
const x = (value) => (
|
|
9510
|
+
const x = (value) => (dayOf(value) - startDay) * pxPerDay;
|
|
9431
9511
|
const inRange = (d) => d >= startDay && d < s.endDay;
|
|
9432
9512
|
const todayDay = Math.floor(s.todayValue);
|
|
9433
9513
|
const scale = {
|
|
@@ -9437,9 +9517,9 @@ function build(s) {
|
|
|
9437
9517
|
pxPerDay,
|
|
9438
9518
|
width: (s.endDay - startDay) * pxPerDay,
|
|
9439
9519
|
x,
|
|
9440
|
-
span: (start, end
|
|
9520
|
+
span: (start, end) => {
|
|
9441
9521
|
const x0 = x(start);
|
|
9442
|
-
return { x: x0, width: Math.max(0, (
|
|
9522
|
+
return { x: x0, width: Math.max(0, (rangeEnd(start, end ?? start) - startDay) * pxPerDay - x0) };
|
|
9443
9523
|
},
|
|
9444
9524
|
dayAt: (px) => startDay + px / pxPerDay,
|
|
9445
9525
|
major: ticks(MAJOR[s.zoom], "major", s),
|
|
@@ -9452,9 +9532,7 @@ function build(s) {
|
|
|
9452
9532
|
todays.set(scale, s.todayValue);
|
|
9453
9533
|
return scale;
|
|
9454
9534
|
}
|
|
9455
|
-
var toMinute = (day) => Math.
|
|
9456
|
-
var startIndex = (value) => typeof value === "number" ? value : dayOf(value);
|
|
9457
|
-
var endIndex = (value) => typeof value === "number" ? value : endDayOf(value);
|
|
9535
|
+
var toMinute = (day) => Math.floor(day * 1440 + 1e-6) / 1440;
|
|
9458
9536
|
function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, pad3) {
|
|
9459
9537
|
const fallback = Number.isFinite(todayValue) ? Math.floor(todayValue) : 0;
|
|
9460
9538
|
const a = Number.isFinite(from) ? from : fallback;
|
|
@@ -9470,28 +9548,44 @@ function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, p
|
|
|
9470
9548
|
}
|
|
9471
9549
|
return build({ zoom, startDay, endDay, pxPerDay: pxPerDay > 0 ? pxPerDay : DENSITY[zoom], todayValue, weekStartsOn, locale });
|
|
9472
9550
|
}
|
|
9473
|
-
function
|
|
9474
|
-
if (!(width > scale.width) || !(scale.pxPerDay > 0)) return scale;
|
|
9551
|
+
function extendedEnd(scale, width) {
|
|
9552
|
+
if (!(width > scale.width) || !(scale.pxPerDay > 0)) return scale.endDay;
|
|
9475
9553
|
const unit = MINOR[scale.zoom];
|
|
9476
9554
|
const last = scale.startDay + Math.ceil(width / scale.pxPerDay) - 1;
|
|
9477
|
-
|
|
9555
|
+
return periodAfter(unit, periodStart(unit, last, scale.weekStartsOn));
|
|
9556
|
+
}
|
|
9557
|
+
function extendTimeScaleTo(scale, endDay) {
|
|
9558
|
+
if (!(endDay > scale.endDay)) return scale;
|
|
9478
9559
|
const todayValue = todays.get(scale) ?? scale.now ?? scale.today ?? NaN;
|
|
9479
|
-
|
|
9560
|
+
const extended = build({ zoom: scale.zoom, startDay: scale.startDay, endDay, pxPerDay: scale.pxPerDay, todayValue, weekStartsOn: scale.weekStartsOn, locale: scale.locale });
|
|
9561
|
+
if (awaiting.has(scale)) awaiting.add(extended);
|
|
9562
|
+
return extended;
|
|
9480
9563
|
}
|
|
9564
|
+
var noSubscription = () => () => {
|
|
9565
|
+
};
|
|
9566
|
+
var inBrowser = () => true;
|
|
9567
|
+
var onServer = () => false;
|
|
9481
9568
|
function useTimeScale({ start, end, zoom, today, weekStartsOn = 1, locale, pxPerDay, pad: pad3 = 0 }) {
|
|
9569
|
+
const readable = useSyncExternalStore(noSubscription, inBrowser, onServer);
|
|
9482
9570
|
const [mounted] = useState(() => toMinute(dayOf(/* @__PURE__ */ new Date())));
|
|
9483
|
-
const
|
|
9484
|
-
const
|
|
9485
|
-
const
|
|
9571
|
+
const pending = today === void 0 && !readable;
|
|
9572
|
+
const from = dayOf(start);
|
|
9573
|
+
const to = rangeEnd(start, end);
|
|
9574
|
+
const todayValue = today !== void 0 ? toMinute(dayOf(today)) : pending ? NaN : mounted;
|
|
9486
9575
|
const density = pxPerDay?.[zoom] ?? DENSITY[zoom];
|
|
9487
|
-
return useMemo(() =>
|
|
9576
|
+
return useMemo(() => {
|
|
9577
|
+
const scale = scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, density, pad3);
|
|
9578
|
+
if (pending) awaiting.add(scale);
|
|
9579
|
+
return scale;
|
|
9580
|
+
}, [from, to, zoom, todayValue, weekStartsOn, locale, density, pad3, pending]);
|
|
9488
9581
|
}
|
|
9489
9582
|
function timeExtent(ranges) {
|
|
9490
9583
|
let start = Infinity;
|
|
9491
9584
|
let end = -Infinity;
|
|
9492
9585
|
for (const r of ranges) {
|
|
9586
|
+
if (r == null) continue;
|
|
9493
9587
|
const s = dayOf(r.start);
|
|
9494
|
-
const e = endDayOf(r.
|
|
9588
|
+
const e = r.end == null ? endDayOf(r.start) : rangeEnd(r.start, r.end);
|
|
9495
9589
|
if (Number.isFinite(s)) start = Math.min(start, s);
|
|
9496
9590
|
if (Number.isFinite(e)) end = Math.max(end, e);
|
|
9497
9591
|
}
|
|
@@ -9499,7 +9593,6 @@ function timeExtent(ranges) {
|
|
|
9499
9593
|
}
|
|
9500
9594
|
var DAY_WORDS = { day: "numeric", month: "long" };
|
|
9501
9595
|
var TIME_WORDS = { hour: "2-digit", minute: "2-digit" };
|
|
9502
|
-
var wholeDay = (value) => typeof value === "string" ? DATE_ONLY.test(value.trim()) : Number.isInteger(value instanceof Date ? dayOf(value) : value);
|
|
9503
9596
|
var SEPARATOR = /\s*[\u2010-\u2015\u2212~\uff5e\u301c-]\s*/;
|
|
9504
9597
|
var english = (f) => new Intl.Locale(f.resolvedOptions().locale).language === "en";
|
|
9505
9598
|
function range(f, a, b, to) {
|
|
@@ -9518,11 +9611,13 @@ function range(f, a, b, to) {
|
|
|
9518
9611
|
if (!joined) out.splice(lastOfStart + 1, 0, to);
|
|
9519
9612
|
return out.join("");
|
|
9520
9613
|
}
|
|
9521
|
-
function formatDateRange(start, end
|
|
9522
|
-
const
|
|
9523
|
-
const
|
|
9614
|
+
function formatDateRange(start, end, words) {
|
|
9615
|
+
const { locale, to, day = DAY_WORDS, time = TIME_WORDS } = words ?? {};
|
|
9616
|
+
const until = end ?? start;
|
|
9617
|
+
const from = dayOf(start);
|
|
9618
|
+
const stop = rangeEnd(start, until);
|
|
9524
9619
|
if (!Number.isFinite(from) || !Number.isFinite(stop)) return "";
|
|
9525
|
-
const timed = !
|
|
9620
|
+
const timed = !isWholeDay(start) || !isWholeDay(until);
|
|
9526
9621
|
const first = timed ? from : Math.floor(from);
|
|
9527
9622
|
const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);
|
|
9528
9623
|
const a = new Date(first * DAY_MS);
|
|
@@ -9552,7 +9647,7 @@ function createScrollStore() {
|
|
|
9552
9647
|
var TimeViewportCtx = createContext(null);
|
|
9553
9648
|
var TimeViewportScrollCtx = createContext(null);
|
|
9554
9649
|
var UNMEASURED = { scrollLeft: 0, visibleWidth: 0 };
|
|
9555
|
-
var
|
|
9650
|
+
var noSubscription2 = () => () => {
|
|
9556
9651
|
};
|
|
9557
9652
|
var unmeasured = () => UNMEASURED;
|
|
9558
9653
|
function useTimeViewportLayout() {
|
|
@@ -9562,7 +9657,7 @@ function useTimeViewportLayout() {
|
|
|
9562
9657
|
}
|
|
9563
9658
|
function useTimeViewport() {
|
|
9564
9659
|
const store = useContext(TimeViewportScrollCtx);
|
|
9565
|
-
const scroll = useSyncExternalStore(store?.subscribe ??
|
|
9660
|
+
const scroll = useSyncExternalStore(store?.subscribe ?? noSubscription2, store?.get ?? unmeasured, unmeasured);
|
|
9566
9661
|
return { ...useTimeViewportLayout(), ...scroll };
|
|
9567
9662
|
}
|
|
9568
9663
|
function fitLabels(boxes, measure, { gap = 8, align = "start", visible } = {}) {
|
|
@@ -9812,17 +9907,16 @@ var ROW_HEIGHT = 40;
|
|
|
9812
9907
|
var MARGIN = 16;
|
|
9813
9908
|
var WHEEL_STEP = 50;
|
|
9814
9909
|
var WHEEL_PAUSE = 250;
|
|
9815
|
-
var FIELD = "input, select, textarea, [contenteditable='true']";
|
|
9816
9910
|
var border = "border-[var(--ds-border-subtle)]";
|
|
9817
|
-
function writeScroll(
|
|
9818
|
-
|
|
9819
|
-
|
|
9911
|
+
function writeScroll(rows, left, visibleWidth) {
|
|
9912
|
+
rows?.style.setProperty("--time-scroll", String(left));
|
|
9913
|
+
rows?.style.setProperty("--time-view-end", String(left + visibleWidth));
|
|
9820
9914
|
}
|
|
9821
9915
|
var TimeViewport = forwardRef(function TimeViewport2({
|
|
9822
9916
|
scale,
|
|
9823
9917
|
onZoomChange,
|
|
9824
9918
|
zooms = TIME_ZOOMS,
|
|
9825
|
-
labelWidth
|
|
9919
|
+
labelWidth = 240,
|
|
9826
9920
|
labelHeader,
|
|
9827
9921
|
header,
|
|
9828
9922
|
toolbar,
|
|
@@ -9837,6 +9931,7 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9837
9931
|
}, ref) {
|
|
9838
9932
|
const scrollerRef = useRef(null);
|
|
9839
9933
|
const headerRef = useRef(null);
|
|
9934
|
+
const rowsRef = useRef(null);
|
|
9840
9935
|
const [frame, setFrame] = useState({ width: 0, header: 0 });
|
|
9841
9936
|
useLayoutEffect(() => {
|
|
9842
9937
|
const el = scrollerRef.current;
|
|
@@ -9854,19 +9949,22 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9854
9949
|
return () => ro.disconnect();
|
|
9855
9950
|
}, []);
|
|
9856
9951
|
const phone = frame.width > 0 && frame.width < PHONE_BELOW;
|
|
9857
|
-
const
|
|
9858
|
-
const visibleWidth = Math.max(0, frame.width -
|
|
9859
|
-
const
|
|
9952
|
+
const pinnedWidth = phone ? Math.min(labelWidth, Math.max(MIN_LABEL, Math.round(frame.width * 0.36))) : labelWidth;
|
|
9953
|
+
const visibleWidth = Math.max(0, frame.width - pinnedWidth);
|
|
9954
|
+
const drawnEnd = extendedEnd(scale, visibleWidth);
|
|
9955
|
+
const drawn = useMemo(() => extendTimeScaleTo(scale, drawnEnd), [scale, drawnEnd]);
|
|
9860
9956
|
const [store] = useState(createScrollStore);
|
|
9861
|
-
const
|
|
9862
|
-
const latest = useLatest({ drawn, visibleWidth, labelWidth, headerHeight: frame.header });
|
|
9957
|
+
const wantLeft = useRef(0);
|
|
9958
|
+
const latest = useLatest({ drawn, visibleWidth, labelWidth: pinnedWidth, headerHeight: frame.header });
|
|
9863
9959
|
const setLeft = useCallback((left) => {
|
|
9864
9960
|
const el = scrollerRef.current;
|
|
9865
9961
|
if (!el) return;
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9962
|
+
const target = Math.max(0, left);
|
|
9963
|
+
el.scrollLeft = target;
|
|
9964
|
+
const now = el.scrollLeft;
|
|
9965
|
+
wantLeft.current = Math.abs(now - target) < 1 ? target : now;
|
|
9966
|
+
writeScroll(rowsRef.current, now, latest.current.visibleWidth);
|
|
9967
|
+
store.set({ scrollLeft: now, visibleWidth: latest.current.visibleWidth });
|
|
9870
9968
|
}, [store, latest]);
|
|
9871
9969
|
const api = useMemo(() => {
|
|
9872
9970
|
const ensureVisible = (x0, x1) => {
|
|
@@ -9889,9 +9987,18 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9889
9987
|
},
|
|
9890
9988
|
page(direction) {
|
|
9891
9989
|
const { drawn: s, visibleWidth: vw } = latest.current;
|
|
9892
|
-
const
|
|
9893
|
-
const
|
|
9894
|
-
|
|
9990
|
+
const left = scrollerRef.current?.scrollLeft ?? 0;
|
|
9991
|
+
const target = left + direction * vw;
|
|
9992
|
+
let to = target;
|
|
9993
|
+
let gap = vw / 2;
|
|
9994
|
+
for (const t of s.minor) {
|
|
9995
|
+
const d = Math.abs(t.x - target);
|
|
9996
|
+
if (d <= gap && (t.x - left) * direction >= 1) {
|
|
9997
|
+
to = t.x;
|
|
9998
|
+
gap = d;
|
|
9999
|
+
}
|
|
10000
|
+
}
|
|
10001
|
+
setLeft(to);
|
|
9895
10002
|
},
|
|
9896
10003
|
ensureVisible,
|
|
9897
10004
|
reveal(target) {
|
|
@@ -9912,29 +10019,34 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9912
10019
|
useImperativeHandle(ref, () => api, [api]);
|
|
9913
10020
|
const todayAtX = todayAt === "now" ? drawn.now === null ? null : drawn.x(drawn.now) : drawn.today === null ? null : drawn.x(drawn.today) + drawn.pxPerDay / 2;
|
|
9914
10021
|
const todayX = showToday ? todayAtX : null;
|
|
9915
|
-
const layout = useMemo(() => ({ scale: drawn, labelWidth, showToday, todayX, compact: phone, ...api }), [drawn,
|
|
10022
|
+
const layout = useMemo(() => ({ scale: drawn, labelWidth: pinnedWidth, showToday, todayX, compact: phone, ...api }), [drawn, pinnedWidth, showToday, todayX, phone, api]);
|
|
9916
10023
|
const pending = useRef(null);
|
|
9917
10024
|
const applied = useRef(null);
|
|
9918
10025
|
useLayoutEffect(() => {
|
|
9919
10026
|
const el = scrollerRef.current;
|
|
9920
10027
|
if (!el || visibleWidth <= 0) return;
|
|
9921
|
-
|
|
9922
|
-
|
|
10028
|
+
const left = el.scrollLeft;
|
|
10029
|
+
const publish = () => {
|
|
10030
|
+
writeScroll(rowsRef.current, left, visibleWidth);
|
|
10031
|
+
store.set({ scrollLeft: left, visibleWidth });
|
|
10032
|
+
};
|
|
9923
10033
|
const prev = applied.current;
|
|
9924
|
-
|
|
10034
|
+
let to = null;
|
|
9925
10035
|
if (!prev) {
|
|
10036
|
+
if (initialDate === void 0 && awaitsToday(drawn)) return publish();
|
|
9926
10037
|
const at = initialDate !== void 0 ? drawn.x(initialDate) : todayAtX;
|
|
9927
|
-
if (at !== null && Number.isFinite(at))
|
|
9928
|
-
|
|
10038
|
+
if (at !== null && Number.isFinite(at)) to = at - visibleWidth / 2;
|
|
10039
|
+
} else if (prev.startDay !== drawn.startDay || prev.pxPerDay !== drawn.pxPerDay || prev.visibleWidth !== visibleWidth) {
|
|
10040
|
+
const want = pending.current;
|
|
10041
|
+
pending.current = null;
|
|
10042
|
+
const anchor = want && want.zoom === drawn.zoom ? want : { day: prev.startDay + (wantLeft.current + prev.visibleWidth / 2) / prev.pxPerDay, at: visibleWidth / 2 };
|
|
10043
|
+
to = drawn.x(anchor.day) - anchor.at;
|
|
9929
10044
|
}
|
|
9930
|
-
|
|
9931
|
-
if (
|
|
9932
|
-
|
|
9933
|
-
pending.current = null;
|
|
9934
|
-
const anchor = want && want.zoom === drawn.zoom ? want : { day: prev.startDay + (lastLeft.current + prev.visibleWidth / 2) / prev.pxPerDay, at: visibleWidth / 2 };
|
|
9935
|
-
setLeft(drawn.x(anchor.day) - anchor.at);
|
|
10045
|
+
applied.current = { startDay: drawn.startDay, pxPerDay: drawn.pxPerDay, visibleWidth };
|
|
10046
|
+
if (to === null) return publish();
|
|
10047
|
+
setLeft(to);
|
|
9936
10048
|
const focused = document.activeElement;
|
|
9937
|
-
if (focused instanceof HTMLElement && focused !== el && el.contains(focused)) api.reveal(focused);
|
|
10049
|
+
if (prev && focused instanceof HTMLElement && focused !== el && el.contains(focused)) api.reveal(focused);
|
|
9938
10050
|
}, [drawn, visibleWidth, initialDate, todayAtX, setLeft, store, api]);
|
|
9939
10051
|
const shaded = [];
|
|
9940
10052
|
if (shadeDays && drawn.pxPerDay >= SHADE_MIN) {
|
|
@@ -9956,7 +10068,7 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9956
10068
|
const f = document.activeElement;
|
|
9957
10069
|
if (!(f instanceof HTMLElement) || f === el || !el.contains(f)) return void 0;
|
|
9958
10070
|
const r = f.getBoundingClientRect();
|
|
9959
|
-
const x = (r.left + r.right) / 2 - el.getBoundingClientRect().left -
|
|
10071
|
+
const x = (r.left + r.right) / 2 - el.getBoundingClientRect().left - pinnedWidth;
|
|
9960
10072
|
return x >= 0 && x <= visibleWidth ? x : void 0;
|
|
9961
10073
|
};
|
|
9962
10074
|
const zoom = (direction, at) => {
|
|
@@ -9980,10 +10092,11 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9980
10092
|
};
|
|
9981
10093
|
const onKeyDown = (e) => {
|
|
9982
10094
|
if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
10095
|
+
if (!e.currentTarget.contains(e.target)) return;
|
|
9983
10096
|
if (e.target instanceof HTMLElement && e.target.closest(FIELD)) return;
|
|
9984
|
-
if (
|
|
10097
|
+
if (ZOOM_KEYS.in.includes(e.key)) {
|
|
9985
10098
|
if (zoom(-1)) e.preventDefault();
|
|
9986
|
-
} else if (
|
|
10099
|
+
} else if (ZOOM_KEYS.out.includes(e.key)) {
|
|
9987
10100
|
if (zoom(1)) e.preventDefault();
|
|
9988
10101
|
} else if (e.shiftKey && (e.key === "ArrowLeft" || e.key === "ArrowRight")) {
|
|
9989
10102
|
e.preventDefault();
|
|
@@ -9993,13 +10106,15 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9993
10106
|
const wheel = useRef({ sum: 0, at: -Infinity });
|
|
9994
10107
|
const onWheel = useLatest((e) => {
|
|
9995
10108
|
if (!(e.ctrlKey || e.metaKey) || !onZoomChange) return;
|
|
9996
|
-
e.preventDefault();
|
|
9997
10109
|
const w = wheel.current;
|
|
9998
|
-
if (e.timeStamp - w.at < WHEEL_PAUSE) return;
|
|
10110
|
+
if (e.timeStamp - w.at < WHEEL_PAUSE) return e.preventDefault();
|
|
10111
|
+
const direction = e.deltaY < 0 ? -1 : e.deltaY > 0 ? 1 : 0;
|
|
10112
|
+
if (direction === 0 || zoomTo(direction) === null) return;
|
|
10113
|
+
e.preventDefault();
|
|
9999
10114
|
w.sum += e.deltaY * (e.deltaMode === 1 ? 16 : e.deltaMode === 2 ? 400 : 1);
|
|
10000
10115
|
if (Math.abs(w.sum) < WHEEL_STEP) return;
|
|
10001
10116
|
const el = scrollerRef.current;
|
|
10002
|
-
const x = el ? e.clientX - el.getBoundingClientRect().left -
|
|
10117
|
+
const x = el ? e.clientX - el.getBoundingClientRect().left - pinnedWidth : NaN;
|
|
10003
10118
|
zoom(w.sum < 0 ? -1 : 1, x >= 0 && x <= visibleWidth ? x : void 0);
|
|
10004
10119
|
wheel.current = { sum: 0, at: e.timeStamp };
|
|
10005
10120
|
});
|
|
@@ -10030,9 +10145,10 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10030
10145
|
const onScroll = () => {
|
|
10031
10146
|
const el = scrollerRef.current;
|
|
10032
10147
|
if (!el) return;
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10148
|
+
const left = el.scrollLeft;
|
|
10149
|
+
if (Math.abs(left - wantLeft.current) >= 1) wantLeft.current = left;
|
|
10150
|
+
writeScroll(rowsRef.current, left, visibleWidth);
|
|
10151
|
+
store.set({ scrollLeft: left, visibleWidth });
|
|
10036
10152
|
};
|
|
10037
10153
|
const headerNode = header === void 0 ? /* @__PURE__ */ jsx(TimeScaleHeader, {}) : header;
|
|
10038
10154
|
const hasHeader = headerNode != null || labelHeader != null;
|
|
@@ -10064,14 +10180,14 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10064
10180
|
tabIndex: tabStop ? 0 : void 0,
|
|
10065
10181
|
onScroll,
|
|
10066
10182
|
className: "peer h-full overflow-auto isolate outline-none",
|
|
10067
|
-
style: { scrollPaddingInlineStart:
|
|
10068
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-full flex-col", style: { width:
|
|
10183
|
+
style: { scrollPaddingInlineStart: pinnedWidth, scrollPaddingTop: frame.header },
|
|
10184
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-full flex-col", style: { width: pinnedWidth + drawn.width }, children: [
|
|
10069
10185
|
hasHeader && /* @__PURE__ */ jsxs("div", { ref: headerRef, className: cn("sticky top-0 z-[3] flex shrink-0 bg-[var(--ds-bg-surface)] border-b-[length:var(--ds-border-width)]", border), children: [
|
|
10070
10186
|
/* @__PURE__ */ jsx(
|
|
10071
10187
|
"div",
|
|
10072
10188
|
{
|
|
10073
10189
|
className: cn("sticky start-0 z-[1] flex shrink-0 items-end px-ds-3 py-ds-1.5 bg-[var(--ds-bg-surface)] border-e-[length:var(--ds-border-width)] text-xs font-medium text-[var(--ds-text-secondary)]", border),
|
|
10074
|
-
style: { width:
|
|
10190
|
+
style: { width: pinnedWidth },
|
|
10075
10191
|
children: labelHeader
|
|
10076
10192
|
}
|
|
10077
10193
|
),
|
|
@@ -10090,18 +10206,18 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10090
10206
|
)
|
|
10091
10207
|
] }),
|
|
10092
10208
|
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 flex-col", children: [
|
|
10093
|
-
/* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-y-0", style: { insetInlineStart:
|
|
10209
|
+
/* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-y-0", style: { insetInlineStart: pinnedWidth, width: drawn.width }, children: [
|
|
10094
10210
|
shaded.map((b) => /* @__PURE__ */ jsx("span", { "data-shaded-days": "", className: "absolute inset-y-0 bg-[var(--ds-bg-muted)] opacity-70", style: { insetInlineStart: b.x, width: b.width } }, b.key)),
|
|
10095
10211
|
drawn.minor.slice(1).map((t) => /* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 border-s-[length:1px] border-[var(--ds-border-subtle)]", style: { insetInlineStart: t.x } }, t.key)),
|
|
10096
10212
|
todayX !== null && /* @__PURE__ */ jsx("span", { "data-today-line": "", className: "absolute inset-y-0 -translate-x-1/2 border-s-2 border-[var(--ds-accent-primary)]", style: { insetInlineStart: todayX } })
|
|
10097
10213
|
] }),
|
|
10098
|
-
children,
|
|
10099
|
-
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: cn("sticky start-0 z-[2] min-h-0 flex-1 bg-[var(--ds-bg-surface)] border-e-[length:var(--ds-border-width)]", border), style: { width:
|
|
10214
|
+
/* @__PURE__ */ jsx("div", { ref: rowsRef, "data-time-rows": "", className: "contents", children }),
|
|
10215
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: cn("sticky start-0 z-[2] min-h-0 flex-1 bg-[var(--ds-bg-surface)] border-e-[length:var(--ds-border-width)]", border), style: { width: pinnedWidth } })
|
|
10100
10216
|
] })
|
|
10101
10217
|
] })
|
|
10102
10218
|
}
|
|
10103
10219
|
),
|
|
10104
|
-
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 peer-focus-visible:shadow-[inset_0_0_0_2px_var(--ds-border-focus)]" })
|
|
10220
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 peer-focus-visible:shadow-[inset_0_0_0_2px_var(--ds-border-focus)] peer-focus-visible:outline-2 peer-focus-visible:-outline-offset-2 peer-focus-visible:outline-transparent" })
|
|
10105
10221
|
] })
|
|
10106
10222
|
] }) }) })
|
|
10107
10223
|
);
|
|
@@ -10138,7 +10254,7 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10138
10254
|
const shows = (i) => i === 0 ? fits(0) : `calc(${[fits(i), ...labels.slice(0, i).map((_, j) => `(1 - ${fits(j)})`)].join(" * ")})`;
|
|
10139
10255
|
const named = props["aria-label"] !== void 0 || props["aria-labelledby"] !== void 0;
|
|
10140
10256
|
label = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10141
|
-
/* @__PURE__ */ jsx("span", { "data-time-bar-label": "", "aria-hidden": "true", className: "sticky grid overflow-hidden whitespace-nowrap", style: { ...sticky, paddingInline: inset }, children: labels.map((text, i) => /* @__PURE__ */ jsx("span", { ref: i === 0 ? textRef : void 0, "data-time-bar-form": "", className: "justify-self-start [grid-area:1/1]", style: { opacity: shows(i) }, children: text }, i)) }),
|
|
10257
|
+
/* @__PURE__ */ jsx("span", { "data-time-bar-label": "", "data-gs-clip": "", "aria-hidden": "true", className: "sticky grid overflow-hidden whitespace-nowrap", style: { ...sticky, paddingInline: inset }, children: labels.map((text, i) => /* @__PURE__ */ jsx("span", { ref: i === 0 ? textRef : void 0, "data-time-bar-form": "", className: "justify-self-start [grid-area:1/1]", style: { opacity: shows(i) }, children: text }, i)) }),
|
|
10142
10258
|
!named && /* @__PURE__ */ jsx("span", { className: "sr-only", children: labels[0] })
|
|
10143
10259
|
] });
|
|
10144
10260
|
} else if (children != null && children !== false) {
|
|
@@ -10146,6 +10262,7 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10146
10262
|
"span",
|
|
10147
10263
|
{
|
|
10148
10264
|
"data-time-bar-label": "",
|
|
10265
|
+
"data-gs-clip": "",
|
|
10149
10266
|
className: "sticky flex min-w-0 items-center gap-ds-1 overflow-hidden whitespace-nowrap",
|
|
10150
10267
|
style: { ...sticky, paddingInline: INSET, opacity: `clamp(0, calc((${inView} - ${MIN_TITLE}) * 1000), 1)` },
|
|
10151
10268
|
children: typeof children === "string" ? /* @__PURE__ */ jsx("span", { className: "truncate", children }) : children
|
|
@@ -10157,7 +10274,8 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10157
10274
|
{
|
|
10158
10275
|
...props,
|
|
10159
10276
|
ref: barRef,
|
|
10160
|
-
|
|
10277
|
+
"data-gs-clip": "",
|
|
10278
|
+
className: cn("absolute top-ds-2 bottom-ds-2 flex items-center overflow-clip rounded-[var(--ds-radius-sm)] outline-none focus-visible:outline-hidden focus-visible:shadow-[var(--ds-shadow-focus)]", className),
|
|
10161
10279
|
style: { insetInlineStart: x, width: drawnWidth, ...style },
|
|
10162
10280
|
children: label
|
|
10163
10281
|
}
|
|
@@ -10175,13 +10293,39 @@ var HEAD = 6;
|
|
|
10175
10293
|
var BESIDE = STUB + 6;
|
|
10176
10294
|
var groupKey = (id) => `group:${id}`;
|
|
10177
10295
|
var itemKey = (id) => `item:${id}`;
|
|
10296
|
+
var asDate = (value) => value instanceof Date || typeof value === "string" ? value : void 0;
|
|
10297
|
+
function datesOf(item) {
|
|
10298
|
+
const start = asDate(item.start);
|
|
10299
|
+
if (start === void 0 || !Number.isFinite(dayOf(start))) return null;
|
|
10300
|
+
if (item.milestone || item.end === void 0 || item.end === null) return { start, end: start };
|
|
10301
|
+
const end = asDate(item.end);
|
|
10302
|
+
return end !== void 0 && Number.isFinite(endDayOf(end)) ? { start, end } : null;
|
|
10303
|
+
}
|
|
10304
|
+
function uniqueById(list) {
|
|
10305
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10306
|
+
const repeated = /* @__PURE__ */ new Set();
|
|
10307
|
+
const unique = [];
|
|
10308
|
+
for (const entry of list) {
|
|
10309
|
+
if (seen.has(entry.id)) repeated.add(entry.id);
|
|
10310
|
+
else {
|
|
10311
|
+
seen.add(entry.id);
|
|
10312
|
+
unique.push(entry);
|
|
10313
|
+
}
|
|
10314
|
+
}
|
|
10315
|
+
return repeated.size ? { unique, repeated: [...repeated] } : { unique: list, repeated: [] };
|
|
10316
|
+
}
|
|
10178
10317
|
function ganttRows(items, groups, collapsed) {
|
|
10179
10318
|
const known = new Set(groups.map((g) => g.id));
|
|
10180
10319
|
const byGroup = /* @__PURE__ */ new Map();
|
|
10181
10320
|
const loose = [];
|
|
10182
10321
|
for (const item of items) {
|
|
10183
|
-
if (item.group === void 0 || !known.has(item.group))
|
|
10184
|
-
|
|
10322
|
+
if (item.group === void 0 || !known.has(item.group)) {
|
|
10323
|
+
loose.push(item);
|
|
10324
|
+
continue;
|
|
10325
|
+
}
|
|
10326
|
+
const list = byGroup.get(item.group);
|
|
10327
|
+
if (list) list.push(item);
|
|
10328
|
+
else byGroup.set(item.group, [item]);
|
|
10185
10329
|
}
|
|
10186
10330
|
const shown = groups.filter((g) => byGroup.has(g.id));
|
|
10187
10331
|
const topLevel = shown.length + loose.length;
|
|
@@ -10199,16 +10343,23 @@ function ganttRows(items, groups, collapsed) {
|
|
|
10199
10343
|
return rows;
|
|
10200
10344
|
}
|
|
10201
10345
|
function itemShape(item, scale) {
|
|
10346
|
+
const dates = datesOf(item);
|
|
10347
|
+
if (!dates) return { kind: item.milestone ? "milestone" : "bar", x0: NaN, x1: NaN, in: NaN, out: NaN };
|
|
10202
10348
|
if (item.milestone) {
|
|
10203
|
-
const centre = scale.x((dayOf(
|
|
10349
|
+
const centre = scale.x((dayOf(dates.start) + endDayOf(dates.start)) / 2);
|
|
10204
10350
|
return { kind: "milestone", x0: centre - TIP, x1: centre + TIP, in: centre - TIP, out: centre + TIP };
|
|
10205
10351
|
}
|
|
10206
|
-
const { x, width } = scale.span(
|
|
10352
|
+
const { x, width } = scale.span(dates.start, dates.end);
|
|
10207
10353
|
const x1 = x + Math.max(width, MIN_BAR);
|
|
10208
10354
|
return { kind: "bar", x0: x, x1, in: x, out: x1 };
|
|
10209
10355
|
}
|
|
10210
|
-
function
|
|
10211
|
-
|
|
10356
|
+
function itemsExtent(items) {
|
|
10357
|
+
const ranges = [];
|
|
10358
|
+
for (const item of items) {
|
|
10359
|
+
const dates = datesOf(item);
|
|
10360
|
+
if (dates) ranges.push(dates);
|
|
10361
|
+
}
|
|
10362
|
+
return timeExtent(ranges);
|
|
10212
10363
|
}
|
|
10213
10364
|
var drawable = (shape) => !!shape && Number.isFinite(shape.x0) && Number.isFinite(shape.x1);
|
|
10214
10365
|
function ganttArrows(items, rows, shapeOf, collapsed) {
|
|
@@ -10249,19 +10400,37 @@ function labelPlace(shape, textWidth, scaleWidth, { pad: pad3 = 8, gap = BESIDE
|
|
|
10249
10400
|
return shape.x0 - gap - textWidth >= 0 ? "before" : "after";
|
|
10250
10401
|
}
|
|
10251
10402
|
var TONES = {
|
|
10252
|
-
neutral: { fill: "bg-[var(--ds-status-neutral)]", on: "text-[var(--ds-text-on-neutral)]" },
|
|
10253
|
-
info: { fill: "bg-[var(--ds-status-info)]", on: "text-[var(--ds-text-on-info)]" },
|
|
10403
|
+
neutral: { fill: "bg-[var(--ds-status-neutral)]", on: "text-[var(--ds-text-on-neutral)]", icon: "minus" },
|
|
10404
|
+
info: { fill: "bg-[var(--ds-status-info)]", on: "text-[var(--ds-text-on-info)]", icon: "info" },
|
|
10254
10405
|
success: { fill: "bg-[var(--ds-status-success)]", on: "text-[var(--ds-text-on-success)]", icon: "check" },
|
|
10255
10406
|
warning: { fill: "bg-[var(--ds-status-warning)]", on: "text-[var(--ds-text-on-warning)]", icon: "warning" },
|
|
10256
10407
|
error: { fill: "bg-[var(--ds-status-error)]", on: "text-[var(--ds-text-on-error)]", icon: "error" },
|
|
10257
|
-
accent: { fill: "bg-[var(--ds-accent-primary)]", on: "text-[var(--ds-text-on-primary)]" }
|
|
10408
|
+
accent: { fill: "bg-[var(--ds-accent-primary)]", on: "text-[var(--ds-text-on-primary)]", icon: "star" }
|
|
10258
10409
|
};
|
|
10259
10410
|
var ICON = 12;
|
|
10260
10411
|
var ICON_GAP = 4;
|
|
10261
10412
|
var LEVEL_INDENT = 16;
|
|
10262
10413
|
var TARGET = 24;
|
|
10414
|
+
var NO_DATES = "no dates";
|
|
10263
10415
|
var KNOCKOUT = 2;
|
|
10416
|
+
var EDGE = "border-[length:1px] border-transparent";
|
|
10417
|
+
var EDGE_WIDTH = 1;
|
|
10264
10418
|
var SELECTED = "outline-solid outline-2 outline-offset-2 outline-[var(--ds-text-primary)]";
|
|
10419
|
+
var UNDATED_INSET = 16;
|
|
10420
|
+
var NO_GROUPS = [];
|
|
10421
|
+
var NO_STATUSES = {};
|
|
10422
|
+
var warned = /* @__PURE__ */ new Set();
|
|
10423
|
+
function warnOnce(message) {
|
|
10424
|
+
let dev = false;
|
|
10425
|
+
try {
|
|
10426
|
+
dev = process.env.NODE_ENV !== "production";
|
|
10427
|
+
} catch {
|
|
10428
|
+
dev = false;
|
|
10429
|
+
}
|
|
10430
|
+
if (!dev || warned.has(message)) return;
|
|
10431
|
+
warned.add(message);
|
|
10432
|
+
console.warn(`Gantt: ${message}`);
|
|
10433
|
+
}
|
|
10265
10434
|
function GanttArrows({ arrows, width, height }) {
|
|
10266
10435
|
const { labelWidth } = useTimeViewportLayout();
|
|
10267
10436
|
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", "data-gantt-arrows": "", className: "pointer-events-none absolute top-0 overflow-visible", style: { insetInlineStart: labelWidth, width, height }, children: arrows.map((a) => /* @__PURE__ */ jsxs("g", { "data-from": a.from, "data-to": a.to, "data-routed": a.routed || void 0, className: "text-[var(--ds-text-muted)]", children: [
|
|
@@ -10269,23 +10438,47 @@ function GanttArrows({ arrows, width, height }) {
|
|
|
10269
10438
|
/* @__PURE__ */ jsx("path", { d: a.head, fill: "currentColor" })
|
|
10270
10439
|
] }, a.key)) });
|
|
10271
10440
|
}
|
|
10441
|
+
function Cue({ name, size }) {
|
|
10442
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-gantt-cue": name, className: "flex shrink-0", children: /* @__PURE__ */ jsx(Icon, { name, size }) });
|
|
10443
|
+
}
|
|
10272
10444
|
function Legend({ statuses }) {
|
|
10273
10445
|
const entries = Object.entries(statuses);
|
|
10274
10446
|
if (!entries.length) return null;
|
|
10275
10447
|
return /* @__PURE__ */ jsx("ul", { "aria-label": "Status key", className: "ms-auto flex flex-wrap items-center gap-x-ds-3 gap-y-ds-1 ps-ds-2 text-xs text-[var(--ds-text-secondary)]", children: entries.map(([key, s]) => {
|
|
10276
10448
|
const tone = TONES[s.tone] ?? TONES.neutral;
|
|
10277
10449
|
return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-ds-1.5", children: [
|
|
10278
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("grid size-4 shrink-0 place-items-center rounded-[var(--ds-radius-sm)]", tone.fill, tone.on), children:
|
|
10450
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("grid size-4 shrink-0 place-items-center rounded-[var(--ds-radius-sm)]", EDGE, tone.fill, tone.on), children: /* @__PURE__ */ jsx(Cue, { name: s.icon ?? tone.icon, size: 10 }) }),
|
|
10279
10451
|
s.label
|
|
10280
10452
|
] }, key);
|
|
10281
10453
|
}) });
|
|
10282
10454
|
}
|
|
10455
|
+
function NoDates({ cue, selected, className, ...props }) {
|
|
10456
|
+
const { labelWidth } = useTimeViewportLayout();
|
|
10457
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center", children: /* @__PURE__ */ jsxs(
|
|
10458
|
+
"span",
|
|
10459
|
+
{
|
|
10460
|
+
...props,
|
|
10461
|
+
"data-gantt-shape": "undated",
|
|
10462
|
+
className: cn(
|
|
10463
|
+
"sticky flex cursor-pointer items-center gap-ds-1 whitespace-nowrap rounded-[var(--ds-radius-sm)] border-[length:1px] border-dashed border-[var(--ds-border-default)] px-ds-1.5 py-ds-0.5 text-xs text-[var(--ds-text-secondary)]",
|
|
10464
|
+
"outline-none focus-visible:outline-hidden focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
10465
|
+
selected && SELECTED,
|
|
10466
|
+
className
|
|
10467
|
+
),
|
|
10468
|
+
style: { insetInlineStart: labelWidth + UNDATED_INSET },
|
|
10469
|
+
children: [
|
|
10470
|
+
cue,
|
|
10471
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "No dates" })
|
|
10472
|
+
]
|
|
10473
|
+
}
|
|
10474
|
+
) });
|
|
10475
|
+
}
|
|
10283
10476
|
function Gantt({
|
|
10284
10477
|
items,
|
|
10285
|
-
groups =
|
|
10478
|
+
groups = NO_GROUPS,
|
|
10286
10479
|
selectedId,
|
|
10287
10480
|
onSelect,
|
|
10288
|
-
statuses =
|
|
10481
|
+
statuses = NO_STATUSES,
|
|
10289
10482
|
zoom: zoomProp,
|
|
10290
10483
|
defaultZoom = "week",
|
|
10291
10484
|
onZoomChange,
|
|
@@ -10293,6 +10486,7 @@ function Gantt({
|
|
|
10293
10486
|
weekStartsOn,
|
|
10294
10487
|
locale,
|
|
10295
10488
|
renderLabel,
|
|
10489
|
+
describe,
|
|
10296
10490
|
labelHeader = "Task",
|
|
10297
10491
|
toolbar,
|
|
10298
10492
|
"aria-label": ariaLabel,
|
|
@@ -10304,31 +10498,53 @@ function Gantt({
|
|
|
10304
10498
|
if (zoomProp === void 0) setZoomState(next);
|
|
10305
10499
|
onZoomChange?.(next);
|
|
10306
10500
|
};
|
|
10501
|
+
const zoomable = zoomProp === void 0 || onZoomChange !== void 0;
|
|
10307
10502
|
const [selectedState, setSelectedState] = useState(null);
|
|
10308
|
-
const
|
|
10503
|
+
const [controlled, setControlled] = useState(selectedId !== void 0);
|
|
10504
|
+
const [overridden, setOverridden] = useState(null);
|
|
10505
|
+
if (!controlled && selectedId !== void 0) {
|
|
10506
|
+
setControlled(true);
|
|
10507
|
+
if (selectedState !== null && selectedState !== selectedId) setOverridden(selectedState);
|
|
10508
|
+
}
|
|
10509
|
+
const isControlled = controlled || selectedId !== void 0;
|
|
10510
|
+
const selected = isControlled ? selectedId ?? null : selectedState;
|
|
10511
|
+
useEffect(() => {
|
|
10512
|
+
if (overridden !== null) {
|
|
10513
|
+
warnOnce("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.");
|
|
10514
|
+
}
|
|
10515
|
+
}, [overridden]);
|
|
10309
10516
|
const select = (item) => {
|
|
10310
|
-
if (
|
|
10517
|
+
if (!isControlled) setSelectedState(item?.id ?? null);
|
|
10311
10518
|
onSelect?.(item);
|
|
10312
10519
|
};
|
|
10313
10520
|
const [collapsed, setCollapsed] = useState(() => new Set(groups.filter((g) => g.defaultCollapsed).map((g) => g.id)));
|
|
10314
|
-
const
|
|
10521
|
+
const plan = useMemo(() => uniqueById(items), [items]);
|
|
10522
|
+
const phases = useMemo(() => uniqueById(groups), [groups]);
|
|
10523
|
+
useEffect(() => {
|
|
10524
|
+
const quoted = (ids) => ids.map((id) => `"${id}"`).join(", ");
|
|
10525
|
+
if (plan.repeated.length) warnOnce(`more than one item has the id ${quoted(plan.repeated)}; only the first of each is shown.`);
|
|
10526
|
+
if (phases.repeated.length) warnOnce(`more than one group has the id ${quoted(phases.repeated)}; only the first of each is shown.`);
|
|
10527
|
+
}, [plan, phases]);
|
|
10528
|
+
const tasks = plan.unique;
|
|
10529
|
+
const extent = useMemo(() => itemsExtent(tasks), [tasks]);
|
|
10315
10530
|
const scale = useTimeScale({ start: extent.start, end: extent.end, zoom, today, weekStartsOn, locale, pad: 1 });
|
|
10316
|
-
const rows = useMemo(() => ganttRows(
|
|
10317
|
-
const shapes = useMemo(() => new Map(
|
|
10318
|
-
const extents = useMemo(() => new Map(rows.filter((r) => r.children).map((r) => [r.group.id,
|
|
10319
|
-
const arrows = useMemo(() => ganttArrows(
|
|
10531
|
+
const rows = useMemo(() => ganttRows(tasks, phases.unique, collapsed), [tasks, phases, collapsed]);
|
|
10532
|
+
const shapes = useMemo(() => new Map(tasks.map((i) => [i.id, itemShape(i, scale)])), [tasks, scale]);
|
|
10533
|
+
const extents = useMemo(() => new Map(rows.filter((r) => r.children).map((r) => [r.group.id, itemsExtent(r.children)])), [rows]);
|
|
10534
|
+
const arrows = useMemo(() => ganttArrows(tasks, rows, (i) => shapes.get(i.id), collapsed), [tasks, rows, shapes, collapsed]);
|
|
10320
10535
|
const byKey = useMemo(() => new Map(rows.map((r) => [r.key, r])), [rows]);
|
|
10321
10536
|
const names = useMemo(() => {
|
|
10322
|
-
const byId = new Map(
|
|
10537
|
+
const byId = new Map(tasks.map((i) => [i.id, i]));
|
|
10323
10538
|
const list = new Intl.ListFormat(locale, { type: "conjunction" });
|
|
10324
10539
|
const out = /* @__PURE__ */ new Map();
|
|
10325
|
-
for (const item of
|
|
10540
|
+
for (const item of tasks) {
|
|
10541
|
+
const dates = datesOf(item);
|
|
10326
10542
|
const after = (item.dependsOn ?? []).flatMap((id) => byId.has(id) && id !== item.id ? [byId.get(id).title] : []);
|
|
10327
10543
|
const status = item.status === void 0 ? void 0 : statuses[item.status];
|
|
10328
10544
|
out.set(itemKey(item.id), [
|
|
10329
10545
|
item.title,
|
|
10330
10546
|
item.milestone ? "milestone" : null,
|
|
10331
|
-
formatDateRange(
|
|
10547
|
+
dates ? formatDateRange(dates.start, dates.end, { locale }) : NO_DATES,
|
|
10332
10548
|
status?.label ?? null,
|
|
10333
10549
|
after.length ? `after ${list.format(after)}` : null
|
|
10334
10550
|
].filter((part) => part).join(", "));
|
|
@@ -10337,31 +10553,66 @@ function Gantt({
|
|
|
10337
10553
|
if (!row.group || !row.children) continue;
|
|
10338
10554
|
const e = extents.get(row.group.id);
|
|
10339
10555
|
const count = row.children.length === 1 ? "1 item" : `${row.children.length} items`;
|
|
10340
|
-
|
|
10556
|
+
const span = Number.isFinite(e.start) ? formatDateRange(e.start, e.end, { locale }) : NO_DATES;
|
|
10557
|
+
out.set(row.key, [row.group.title, span, count].filter((part) => part).join(", "));
|
|
10341
10558
|
}
|
|
10342
10559
|
return out;
|
|
10343
|
-
}, [
|
|
10560
|
+
}, [tasks, rows, extents, statuses, locale]);
|
|
10561
|
+
const nameOf = (row) => {
|
|
10562
|
+
const name = names.get(row.key) ?? "";
|
|
10563
|
+
const words = row.item && describe ? describe(row.item) : "";
|
|
10564
|
+
return words ? `${name}, ${words}` : name;
|
|
10565
|
+
};
|
|
10566
|
+
const regionLabel = useMemo(() => {
|
|
10567
|
+
const span = Number.isFinite(extent.start) ? formatDateRange(extent.start, extent.end, { locale }) : "";
|
|
10568
|
+
return `${ariaLabel}, ${span || NO_DATES}`;
|
|
10569
|
+
}, [ariaLabel, extent, locale]);
|
|
10570
|
+
const hasStatuses = useMemo(() => Object.keys(statuses).length > 0, [statuses]);
|
|
10571
|
+
const toneOf = (item) => {
|
|
10572
|
+
const status = item.status === void 0 ? void 0 : statuses[item.status];
|
|
10573
|
+
const tone = TONES[status?.tone ?? "neutral"] ?? TONES.neutral;
|
|
10574
|
+
return { tone, cue: hasStatuses ? status?.icon ?? tone.icon : void 0 };
|
|
10575
|
+
};
|
|
10344
10576
|
const probeRef = useRef(null);
|
|
10345
10577
|
const measure = useTextMeasure(probeRef);
|
|
10346
10578
|
const treeRef = useRef(null);
|
|
10347
10579
|
const viewportRef = useRef(null);
|
|
10348
10580
|
const [activeState, setActive] = useState(null);
|
|
10581
|
+
const [focusWithin, setFocusWithin] = useState(false);
|
|
10349
10582
|
const selectedKey = selected === null ? null : itemKey(selected);
|
|
10350
|
-
const
|
|
10351
|
-
const
|
|
10352
|
-
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
setActive(key);
|
|
10362
|
-
if (treeRef.current?.contains(document.activeElement)) grid.focus(key);
|
|
10583
|
+
const selectedRow = selectedKey !== null && byKey.has(selectedKey) ? selectedKey : null;
|
|
10584
|
+
const lastFocused = activeState !== null && byKey.has(activeState) ? activeState : null;
|
|
10585
|
+
const active = (focusWithin ? lastFocused : null) ?? selectedRow ?? lastFocused ?? rows[0]?.key ?? "";
|
|
10586
|
+
const focusedRow = useRef(null);
|
|
10587
|
+
useLayoutEffect(() => {
|
|
10588
|
+
const was = focusedRow.current;
|
|
10589
|
+
if (!was) return;
|
|
10590
|
+
const row = byKey.get(was.key);
|
|
10591
|
+
if (row) {
|
|
10592
|
+
if (row.index !== was.index) focusedRow.current = { key: was.key, index: row.index };
|
|
10593
|
+
return;
|
|
10363
10594
|
}
|
|
10364
|
-
|
|
10595
|
+
focusedRow.current = null;
|
|
10596
|
+
const now = document.activeElement;
|
|
10597
|
+
if (now && now !== document.body && now.isConnected) return;
|
|
10598
|
+
const tree = treeRef.current;
|
|
10599
|
+
if (tree) focusAfterRemoval(tree.querySelectorAll("[data-grid-key]"), was.index);
|
|
10600
|
+
}, [byKey]);
|
|
10601
|
+
const lastSelected = useRef(selected);
|
|
10602
|
+
useEffect(() => {
|
|
10603
|
+
if (lastSelected.current === selected) return;
|
|
10604
|
+
lastSelected.current = selected;
|
|
10605
|
+
const tree = treeRef.current;
|
|
10606
|
+
if (selected === null || !tree || tree.contains(document.activeElement)) return;
|
|
10607
|
+
const el = tree.querySelector(`[data-grid-key="${CSS.escape(itemKey(selected))}"]`);
|
|
10608
|
+
if (el) viewportRef.current?.reveal(el);
|
|
10609
|
+
}, [selected]);
|
|
10610
|
+
const toggle = (id) => setCollapsed((cur) => {
|
|
10611
|
+
const next = new Set(cur);
|
|
10612
|
+
if (next.has(id)) next.delete(id);
|
|
10613
|
+
else next.add(id);
|
|
10614
|
+
return next;
|
|
10615
|
+
});
|
|
10365
10616
|
const activate = (row) => {
|
|
10366
10617
|
if (row.group) toggle(row.group.id);
|
|
10367
10618
|
else if (row.item) select(row.item);
|
|
@@ -10417,6 +10668,11 @@ function Gantt({
|
|
|
10417
10668
|
}
|
|
10418
10669
|
grid.onKeyDown(e);
|
|
10419
10670
|
};
|
|
10671
|
+
const onTreeBlur = (e) => {
|
|
10672
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
10673
|
+
setFocusWithin(false);
|
|
10674
|
+
if (e.relatedTarget) focusedRow.current = null;
|
|
10675
|
+
};
|
|
10420
10676
|
const onRowClick = (row) => {
|
|
10421
10677
|
if (row.item) select(row.item.id === selected ? null : row.item);
|
|
10422
10678
|
else if (row.group) toggle(row.group.id);
|
|
@@ -10428,25 +10684,33 @@ function Gantt({
|
|
|
10428
10684
|
"aria-level": row.level,
|
|
10429
10685
|
"aria-setsize": row.setSize,
|
|
10430
10686
|
"aria-posinset": row.posInSet,
|
|
10431
|
-
"aria-label":
|
|
10687
|
+
"aria-label": nameOf(row),
|
|
10432
10688
|
"data-grid-key": row.key,
|
|
10433
10689
|
tabIndex: grid.tabIndexOf(row.key),
|
|
10434
|
-
onFocus: () =>
|
|
10690
|
+
onFocus: () => {
|
|
10691
|
+
setActive(row.key);
|
|
10692
|
+
focusedRow.current = { key: row.key, index: row.index };
|
|
10693
|
+
}
|
|
10435
10694
|
});
|
|
10436
10695
|
const renderItem = (row, item) => {
|
|
10437
10696
|
const shape = shapes.get(item.id);
|
|
10438
|
-
|
|
10439
|
-
const tone = TONES[item.status !== void 0 && statuses[item.status]?.tone || "neutral"] ?? TONES.neutral;
|
|
10697
|
+
const dates = datesOf(item);
|
|
10440
10698
|
const isSelected = item.id === selected;
|
|
10441
|
-
const
|
|
10442
|
-
|
|
10699
|
+
const { tone, cue } = toneOf(item);
|
|
10700
|
+
if (!dates || !drawable(shape)) {
|
|
10701
|
+
return /* @__PURE__ */ jsx(NoDates, { ...treeitem(row), "aria-selected": isSelected, selected: isSelected, cue: cue && /* @__PURE__ */ jsx(Cue, { name: cue, size: ICON }) });
|
|
10702
|
+
}
|
|
10703
|
+
const textWidth = measure(item.title) + (cue ? ICON + ICON_GAP : 0) + 2 * KNOCKOUT;
|
|
10704
|
+
const place = labelPlace(shape, textWidth + 2 * EDGE_WIDTH, scale.width);
|
|
10443
10705
|
const beside = place === "after" ? shape.x1 + BESIDE : shape.x0 - BESIDE - textWidth;
|
|
10444
|
-
const icon = tone.icon && /* @__PURE__ */ jsx(Icon, { name: tone.icon, size: ICON, className: "shrink-0" });
|
|
10445
10706
|
const title = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10446
|
-
|
|
10707
|
+
cue && /* @__PURE__ */ jsx(Cue, { name: cue, size: ICON }),
|
|
10447
10708
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: item.title })
|
|
10448
10709
|
] });
|
|
10449
|
-
const shapeBox = shape.kind === "milestone" ?
|
|
10710
|
+
const shapeBox = shape.kind === "milestone" ? (
|
|
10711
|
+
// the target's own outline is its focus indicator in forced colours, which drop the diamond's shadow ring
|
|
10712
|
+
/* @__PURE__ */ jsx("div", { ...treeitem(row), "aria-selected": isSelected, className: "group absolute grid cursor-pointer place-items-center outline-none focus-visible:outline-hidden", style: { insetInlineStart: (shape.x0 + shape.x1) / 2 - TARGET / 2, top: (ROW_HEIGHT2 - TARGET) / 2, width: TARGET, height: TARGET }, children: /* @__PURE__ */ jsx("span", { "data-gantt-shape": "milestone", "data-item": item.id, className: cn("block rotate-45 rounded-[2px] group-focus-visible:shadow-[var(--ds-shadow-focus)]", EDGE, tone.fill, isSelected && SELECTED), style: { width: DIAMOND, height: DIAMOND } }) })
|
|
10713
|
+
) : (
|
|
10450
10714
|
// TimeBar keeps the title in view beside the pinned column while the bar's start is scrolled away
|
|
10451
10715
|
/* @__PURE__ */ jsx(
|
|
10452
10716
|
TimeBar,
|
|
@@ -10455,12 +10719,12 @@ function Gantt({
|
|
|
10455
10719
|
"aria-selected": isSelected,
|
|
10456
10720
|
"data-gantt-shape": "bar",
|
|
10457
10721
|
"data-item": item.id,
|
|
10458
|
-
start:
|
|
10459
|
-
end:
|
|
10722
|
+
start: dates.start,
|
|
10723
|
+
end: dates.end,
|
|
10460
10724
|
minWidth: MIN_BAR,
|
|
10461
|
-
className: cn("cursor-pointer text-xs font-medium", tone.fill, tone.on, isSelected && SELECTED),
|
|
10725
|
+
className: cn("cursor-pointer text-xs font-medium", EDGE, tone.fill, tone.on, isSelected && SELECTED),
|
|
10462
10726
|
style: { top: (ROW_HEIGHT2 - BAR_HEIGHT) / 2, bottom: "auto", height: BAR_HEIGHT },
|
|
10463
|
-
children: place === "inside" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex min-w-0 items-center gap-ds-1 overflow-hidden", children: title })
|
|
10727
|
+
children: place === "inside" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-gs-clip": "", className: "flex min-w-0 items-center gap-ds-1 overflow-hidden", children: title })
|
|
10464
10728
|
}
|
|
10465
10729
|
)
|
|
10466
10730
|
);
|
|
@@ -10479,23 +10743,29 @@ function Gantt({
|
|
|
10479
10743
|
)
|
|
10480
10744
|
] });
|
|
10481
10745
|
};
|
|
10482
|
-
const renderGroup = (row,
|
|
10483
|
-
|
|
10484
|
-
|
|
10485
|
-
/* @__PURE__ */
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10494
|
-
|
|
10495
|
-
|
|
10496
|
-
|
|
10497
|
-
|
|
10498
|
-
|
|
10746
|
+
const renderGroup = (row, group) => {
|
|
10747
|
+
const extent2 = extents.get(group.id);
|
|
10748
|
+
const expanded = !collapsed.has(group.id);
|
|
10749
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10750
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "absolute inset-0 bg-[var(--ds-bg-muted)] opacity-60" }),
|
|
10751
|
+
extent2 && Number.isFinite(extent2.start) ? (
|
|
10752
|
+
// a 24 px target around the thin summary bar it draws
|
|
10753
|
+
/* @__PURE__ */ jsx(
|
|
10754
|
+
TimeBar,
|
|
10755
|
+
{
|
|
10756
|
+
...treeitem(row),
|
|
10757
|
+
"aria-expanded": expanded,
|
|
10758
|
+
"data-gantt-shape": "summary",
|
|
10759
|
+
start: extent2.start,
|
|
10760
|
+
end: extent2.end,
|
|
10761
|
+
minWidth: MIN_BAR,
|
|
10762
|
+
className: "cursor-pointer before:absolute before:inset-x-0 before:top-1/2 before:h-ds-2 before:-translate-y-1/2 before:rounded-[var(--ds-radius-full)] before:border-[length:1px] before:border-transparent before:bg-[var(--ds-text-secondary)]",
|
|
10763
|
+
style: { top: (ROW_HEIGHT2 - TARGET) / 2, bottom: "auto", height: TARGET }
|
|
10764
|
+
}
|
|
10765
|
+
)
|
|
10766
|
+
) : /* @__PURE__ */ jsx(NoDates, { ...treeitem(row), "aria-expanded": expanded })
|
|
10767
|
+
] });
|
|
10768
|
+
};
|
|
10499
10769
|
const label = (row) => {
|
|
10500
10770
|
if (row.group) {
|
|
10501
10771
|
return /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "flex min-w-0 items-center gap-ds-1.5 font-medium", children: [
|
|
@@ -10513,27 +10783,30 @@ function Gantt({
|
|
|
10513
10783
|
] })
|
|
10514
10784
|
);
|
|
10515
10785
|
};
|
|
10516
|
-
|
|
10786
|
+
const legend = /* @__PURE__ */ jsx(Legend, { statuses });
|
|
10787
|
+
const legendApart = toolbar === false && hasStatuses;
|
|
10788
|
+
const chart = /* @__PURE__ */ jsx(
|
|
10517
10789
|
TimeViewport,
|
|
10518
10790
|
{
|
|
10519
10791
|
ref: viewportRef,
|
|
10520
10792
|
scale,
|
|
10521
|
-
onZoomChange: changeZoom,
|
|
10793
|
+
onZoomChange: zoomable ? changeZoom : void 0,
|
|
10522
10794
|
labelHeader,
|
|
10523
10795
|
toolbar: toolbar === false ? false : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10524
10796
|
toolbar,
|
|
10525
|
-
|
|
10797
|
+
legend
|
|
10526
10798
|
] }),
|
|
10527
10799
|
tabStop: false,
|
|
10528
|
-
"aria-label":
|
|
10529
|
-
className,
|
|
10530
|
-
children: /* @__PURE__ */ jsxs("div", { ref: treeRef, role: "tree", "aria-label": ariaLabel, className: "relative", onKeyDown, children: [
|
|
10800
|
+
"aria-label": regionLabel,
|
|
10801
|
+
className: legendApart ? "h-auto flex-1" : className,
|
|
10802
|
+
children: /* @__PURE__ */ jsxs("div", { ref: treeRef, role: "tree", "aria-label": ariaLabel, className: "relative", onKeyDown, onFocus: () => setFocusWithin(true), onBlur: onTreeBlur, children: [
|
|
10531
10803
|
/* @__PURE__ */ jsx("span", { ref: probeRef, "aria-hidden": "true", className: "pointer-events-none invisible absolute whitespace-nowrap text-xs font-medium", children: "0" }),
|
|
10532
10804
|
/* @__PURE__ */ jsx(GanttArrows, { arrows, width: scale.width, height: rows.length * ROW_HEIGHT2 }),
|
|
10533
10805
|
rows.map((row) => /* @__PURE__ */ jsx(
|
|
10534
10806
|
TimeRow,
|
|
10535
10807
|
{
|
|
10536
10808
|
"data-row-key": row.key,
|
|
10809
|
+
height: ROW_HEIGHT2,
|
|
10537
10810
|
label: label(row),
|
|
10538
10811
|
className: "cursor-pointer",
|
|
10539
10812
|
labelClassName: cn(
|
|
@@ -10541,13 +10814,18 @@ function Gantt({
|
|
|
10541
10814
|
row.item && row.item.id === selected && "bg-[image:linear-gradient(var(--ds-accent-subtle),var(--ds-accent-subtle))] text-[var(--ds-accent-subtle-text)]"
|
|
10542
10815
|
),
|
|
10543
10816
|
onClick: () => onRowClick(row),
|
|
10544
|
-
children: row.group ? renderGroup(row,
|
|
10817
|
+
children: row.group ? renderGroup(row, row.group) : renderItem(row, row.item)
|
|
10545
10818
|
},
|
|
10546
10819
|
row.key
|
|
10547
10820
|
))
|
|
10548
10821
|
] })
|
|
10549
10822
|
}
|
|
10550
10823
|
);
|
|
10824
|
+
if (!legendApart) return chart;
|
|
10825
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 w-full min-w-0 flex-col", className), children: [
|
|
10826
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 px-ds-2 py-ds-1.5", children: legend }),
|
|
10827
|
+
chart
|
|
10828
|
+
] });
|
|
10551
10829
|
}
|
|
10552
10830
|
var DEFAULT_OFFSET2 = "var(--ds-space-4)";
|
|
10553
10831
|
var LAUNCHER_SIZES = {
|
|
@@ -11096,6 +11374,7 @@ function TabsList({ children, className }) {
|
|
|
11096
11374
|
{
|
|
11097
11375
|
role: "tablist",
|
|
11098
11376
|
...overflow === "scroll" ? track : {},
|
|
11377
|
+
"data-gs-clip": overflow === "scroll" ? void 0 : "",
|
|
11099
11378
|
className: cn(
|
|
11100
11379
|
trackClasses("horizontal"),
|
|
11101
11380
|
"max-w-full",
|
|
@@ -11200,6 +11479,7 @@ function TabsRoot(props) {
|
|
|
11200
11479
|
{
|
|
11201
11480
|
role: "tablist",
|
|
11202
11481
|
...effectiveOverflow === "scroll" ? track : {},
|
|
11482
|
+
"data-gs-clip": effectiveOverflow === "scroll" ? void 0 : "",
|
|
11203
11483
|
className: cn(
|
|
11204
11484
|
trackClasses("horizontal"),
|
|
11205
11485
|
effectiveOverflow === "scroll" ? SCROLL_TRACK : "overflow-hidden",
|
|
@@ -11217,14 +11497,35 @@ var Tabs = Object.assign(TabsRoot, {
|
|
|
11217
11497
|
Trigger: TabsTrigger,
|
|
11218
11498
|
Content: TabsContent
|
|
11219
11499
|
});
|
|
11220
|
-
var MIN_PANEL_WIDTH =
|
|
11500
|
+
var MIN_PANEL_WIDTH = 560;
|
|
11501
|
+
var PANEL_STYLE = {
|
|
11502
|
+
"--ds-form-max": "calc(var(--ds-bp-md) - 2 * var(--ds-space-6))"
|
|
11503
|
+
};
|
|
11504
|
+
var PANEL_CLASSES = "min-w-0 @container";
|
|
11505
|
+
function useColumnGap(ref) {
|
|
11506
|
+
const [gap, setGap] = useState(0);
|
|
11507
|
+
useLayoutEffect(() => {
|
|
11508
|
+
const el = ref.current;
|
|
11509
|
+
if (!el) return;
|
|
11510
|
+
const read = () => {
|
|
11511
|
+
const px = parseFloat(getComputedStyle(el).columnGap);
|
|
11512
|
+
setGap(Number.isFinite(px) ? px : 0);
|
|
11513
|
+
};
|
|
11514
|
+
read();
|
|
11515
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
11516
|
+
const observer = new ResizeObserver(read);
|
|
11517
|
+
observer.observe(el);
|
|
11518
|
+
return () => observer.disconnect();
|
|
11519
|
+
}, [ref]);
|
|
11520
|
+
return gap;
|
|
11521
|
+
}
|
|
11221
11522
|
function SettingsLayout({
|
|
11222
11523
|
sections,
|
|
11223
11524
|
value,
|
|
11224
11525
|
onChange,
|
|
11225
11526
|
layout: layoutProp,
|
|
11226
11527
|
railWidth = 220,
|
|
11227
|
-
collapseBelow
|
|
11528
|
+
collapseBelow: collapseBelowProp,
|
|
11228
11529
|
"aria-label": ariaLabel = "Settings sections",
|
|
11229
11530
|
children,
|
|
11230
11531
|
className
|
|
@@ -11232,32 +11533,37 @@ function SettingsLayout({
|
|
|
11232
11533
|
const shell = useAppShell();
|
|
11233
11534
|
const layout = layoutProp ?? shell?.theme?.settingsLayout ?? "sidebar";
|
|
11234
11535
|
const rootRef = useRef(null);
|
|
11536
|
+
const gap = useColumnGap(rootRef);
|
|
11537
|
+
const collapseBelow = collapseBelowProp ?? railWidth + gap + MIN_PANEL_WIDTH;
|
|
11235
11538
|
const compact = useCompact(rootRef, collapseBelow);
|
|
11236
11539
|
const tabs = sections.map((s) => ({ id: s.id, label: s.label, icon: s.icon, group: s.group, disabled: s.disabled }));
|
|
11237
11540
|
const stickyTop = shell ? "var(--ds-sticky-offset, 0px)" : "calc(var(--ds-navbar-height) + var(--ds-sticky-offset, 0px))";
|
|
11238
11541
|
if (layout === "tabs") {
|
|
11239
11542
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "tabs", className: cn("flex flex-col gap-ds-6", className), children: [
|
|
11240
11543
|
/* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(Tabs, { orientation: "horizontal", mobile: "dropdown", tabs, activeTab: value, onTabChange: onChange }) }),
|
|
11241
|
-
/* @__PURE__ */ jsx("div", {
|
|
11544
|
+
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: PANEL_CLASSES, style: PANEL_STYLE, children })
|
|
11242
11545
|
] });
|
|
11243
11546
|
}
|
|
11244
11547
|
if (compact) {
|
|
11245
|
-
return
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11548
|
+
return (
|
|
11549
|
+
// gap-x-ds-8 is the rail's gap, unused in one column: the threshold reads the same gap as the row (useColumnGap)
|
|
11550
|
+
/* @__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: [
|
|
11551
|
+
/* @__PURE__ */ jsx(
|
|
11552
|
+
Dropdown,
|
|
11553
|
+
{
|
|
11554
|
+
"aria-label": ariaLabel,
|
|
11555
|
+
options: sections.filter((s) => !s.disabled).map((s) => ({ id: s.id, label: s.label, group: s.group })),
|
|
11556
|
+
value,
|
|
11557
|
+
onChange: (v) => onChange(v)
|
|
11558
|
+
}
|
|
11559
|
+
),
|
|
11560
|
+
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: PANEL_CLASSES, style: PANEL_STYLE, children })
|
|
11561
|
+
] })
|
|
11562
|
+
);
|
|
11257
11563
|
}
|
|
11258
11564
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "sidebar", className: cn("flex flex-row items-start gap-ds-8", className), children: [
|
|
11259
11565
|
/* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, className: "sticky self-start shrink-0", style: { width: `${railWidth}px`, top: stickyTop }, children: /* @__PURE__ */ jsx(Tabs, { orientation: "vertical", tabs, activeTab: value, onTabChange: onChange, className: "w-full" }) }),
|
|
11260
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1
|
|
11566
|
+
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: cn("flex-1", PANEL_CLASSES), style: PANEL_STYLE, children })
|
|
11261
11567
|
] });
|
|
11262
11568
|
}
|
|
11263
11569
|
function SeparatorIcon({ type, size }) {
|
|
@@ -12969,6 +13275,16 @@ var widthToMaxWidth = {
|
|
|
12969
13275
|
full: "full",
|
|
12970
13276
|
narrow: "md"
|
|
12971
13277
|
};
|
|
13278
|
+
var dataWidthOf = {
|
|
13279
|
+
sm: "sm",
|
|
13280
|
+
md: "narrow",
|
|
13281
|
+
lg: "lg",
|
|
13282
|
+
xl: "constrained",
|
|
13283
|
+
full: "full"
|
|
13284
|
+
};
|
|
13285
|
+
function pageMaxWidth(resolved) {
|
|
13286
|
+
return resolved === "md" ? `var(--ds-page-max, ${maxWidthValues.md})` : maxWidthValues[resolved];
|
|
13287
|
+
}
|
|
12972
13288
|
var paddingClasses = {
|
|
12973
13289
|
none: "",
|
|
12974
13290
|
default: "px-ds-6",
|
|
@@ -13053,6 +13369,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13053
13369
|
className,
|
|
13054
13370
|
renderHeader
|
|
13055
13371
|
}, ref) {
|
|
13372
|
+
if (REACT_VERSION_PROBLEM) throw new Error(REACT_VERSION_PROBLEM);
|
|
13056
13373
|
const shell = useAppShell();
|
|
13057
13374
|
const rootRef = useRef(null);
|
|
13058
13375
|
const setRoot = useCallback((node) => {
|
|
@@ -13065,7 +13382,8 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13065
13382
|
else rootRef.current?.style.removeProperty("--ds-sticky-offset");
|
|
13066
13383
|
}, []);
|
|
13067
13384
|
const resolvedMaxWidth = width ? widthToMaxWidth[width] : maxWidth;
|
|
13068
|
-
const maxWidthValue =
|
|
13385
|
+
const maxWidthValue = pageMaxWidth(resolvedMaxWidth);
|
|
13386
|
+
const dataWidth = dataWidthOf[resolvedMaxWidth];
|
|
13069
13387
|
const [requestedWidth, setRequestedWidth] = useState(null);
|
|
13070
13388
|
const requestContentWidth = useCallback((w) => setRequestedWidth(w), []);
|
|
13071
13389
|
const effectiveContentWidth = contentWidth ?? requestedWidth ?? void 0;
|
|
@@ -13129,6 +13447,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13129
13447
|
{
|
|
13130
13448
|
ref: setRoot,
|
|
13131
13449
|
"data-page-container": wrappedHeader ? "" : void 0,
|
|
13450
|
+
"data-width": dataWidth,
|
|
13132
13451
|
className: cn(
|
|
13133
13452
|
"w-full",
|
|
13134
13453
|
paddingClasses[padding],
|
|
@@ -13160,7 +13479,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13160
13479
|
...overlapActive ? { marginTop: "calc(-1 * var(--ds-overlap, 0px))", position: "relative", zIndex: 1 } : {}
|
|
13161
13480
|
} : void 0;
|
|
13162
13481
|
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) }) });
|
|
13163
|
-
return /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-page-container": "", className: "w-full", children: [
|
|
13482
|
+
return /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-page-container": "", "data-width": dataWidth, className: "w-full", children: [
|
|
13164
13483
|
placement === "block" ? /* @__PURE__ */ jsx("div", { style: floatingBlockPadding(r.navbarFloating, r.sidebarFloating, overlapActive), children: /* @__PURE__ */ jsxs("div", { className: FLOATING_BLOCK, children: [
|
|
13165
13484
|
strip,
|
|
13166
13485
|
colourful ? header : /* @__PURE__ */ jsx("div", { className: columnClass(padding), style: columnStyle, children: header })
|
|
@@ -13421,7 +13740,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
13421
13740
|
}
|
|
13422
13741
|
let header;
|
|
13423
13742
|
if (variant === "minimal") {
|
|
13424
|
-
header = /* @__PURE__ */ jsx(MinimalHeader, { title, caption, focusBack, badge, breadcrumbs: inlineBreadcrumbs, actions, tabs, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
13743
|
+
header = /* @__PURE__ */ jsx(MinimalHeader, { title, description, caption, focusBack, badge, breadcrumbs: inlineBreadcrumbs, actions, tabs, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
13425
13744
|
} else if (variant === "tabs-integrated") {
|
|
13426
13745
|
header = /* @__PURE__ */ jsx(
|
|
13427
13746
|
TabsIntegratedHeader,
|
|
@@ -13596,6 +13915,7 @@ function DefaultHeader({
|
|
|
13596
13915
|
}
|
|
13597
13916
|
function MinimalHeader({
|
|
13598
13917
|
title,
|
|
13918
|
+
description,
|
|
13599
13919
|
caption,
|
|
13600
13920
|
focusBack,
|
|
13601
13921
|
badge,
|
|
@@ -13623,6 +13943,7 @@ function MinimalHeader({
|
|
|
13623
13943
|
] }),
|
|
13624
13944
|
actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
|
|
13625
13945
|
] }),
|
|
13946
|
+
description && /* @__PURE__ */ jsx(ClampedText, { className: "mt-ds-1 text-sm text-[var(--ds-text-secondary)]", children: description }),
|
|
13626
13947
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
13627
13948
|
] }) });
|
|
13628
13949
|
}
|
|
@@ -13911,6 +14232,7 @@ function SnappingHeader({
|
|
|
13911
14232
|
] }),
|
|
13912
14233
|
actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
|
|
13913
14234
|
] }),
|
|
14235
|
+
description && /* @__PURE__ */ jsx(ClampedText, { className: "mt-ds-1 text-sm text-[var(--ds-text-secondary)]", children: description }),
|
|
13914
14236
|
filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-3", children: filters }) }),
|
|
13915
14237
|
expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-3", children: expandedContent }),
|
|
13916
14238
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
@@ -16028,7 +16350,9 @@ function Toast({ variant = "default", message, visible, onDismiss, duration = 5e
|
|
|
16028
16350
|
var ToastContext = createContext(null);
|
|
16029
16351
|
function useToast() {
|
|
16030
16352
|
const ctx = useContext(ToastContext);
|
|
16031
|
-
if (!ctx)
|
|
16353
|
+
if (!ctx) {
|
|
16354
|
+
throw new Error("useToast must be used within <ToastProvider>: the app shell's (get_app_shell writes it around AppShell). A page outside the shell (sign-in, a public page) shows its messages inline instead: an Alert above the form, and each field's error below the field.");
|
|
16355
|
+
}
|
|
16032
16356
|
return ctx;
|
|
16033
16357
|
}
|
|
16034
16358
|
function useToastOptional() {
|
|
@@ -16271,6 +16595,7 @@ var SectionHeading = forwardRef(function SectionHeading2({
|
|
|
16271
16595
|
"div",
|
|
16272
16596
|
{
|
|
16273
16597
|
ref,
|
|
16598
|
+
"data-gs": "section-heading",
|
|
16274
16599
|
"data-variant": variant,
|
|
16275
16600
|
className: cn(
|
|
16276
16601
|
pane ? "shrink-0 px-ds-4 pt-ds-4 pb-ds-3 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]" : "mb-[var(--ds-heading-gap)]",
|
|
@@ -16286,7 +16611,7 @@ var SectionHeading = forwardRef(function SectionHeading2({
|
|
|
16286
16611
|
), children: [
|
|
16287
16612
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
16288
16613
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
16289
|
-
/* @__PURE__ */ jsx("h2", { className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
|
|
16614
|
+
/* @__PURE__ */ jsx("h2", { className: cn("font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", pane ? "truncate" : "min-w-0 break-words"), children: title }),
|
|
16290
16615
|
badge,
|
|
16291
16616
|
count !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "neutral", size: "sm", children: count })
|
|
16292
16617
|
] }),
|