gridsmith-ui 0.17.1 → 0.17.2
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/{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 +61 -33
- package/dist/index.js +376 -158
- 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/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(
|
|
@@ -9329,12 +9329,19 @@ var DAY_MS = 864e5;
|
|
|
9329
9329
|
var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
9330
9330
|
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) / DAY_MS);
|
|
9331
9331
|
function dayOfDate(d) {
|
|
9332
|
-
|
|
9332
|
+
const t = d.getTime();
|
|
9333
|
+
if (Number.isNaN(t)) return NaN;
|
|
9334
|
+
const day = utcDay(d.getFullYear(), d.getMonth(), d.getDate());
|
|
9335
|
+
const first = new Date(t);
|
|
9336
|
+
first.setHours(0, 0, 0, 0);
|
|
9337
|
+
if (first.getTime() === t) return day;
|
|
9333
9338
|
const ms = ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1e3 + d.getMilliseconds();
|
|
9334
|
-
return
|
|
9339
|
+
return day + ms / DAY_MS;
|
|
9335
9340
|
}
|
|
9336
9341
|
function dayOf(value) {
|
|
9342
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : NaN;
|
|
9337
9343
|
if (value instanceof Date) return dayOfDate(value);
|
|
9344
|
+
if (typeof value !== "string") return NaN;
|
|
9338
9345
|
const m = DATE_ONLY.exec(value.trim());
|
|
9339
9346
|
if (!m) return dayOfDate(new Date(value));
|
|
9340
9347
|
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
@@ -9347,10 +9354,15 @@ function dateOfDay(day) {
|
|
|
9347
9354
|
const u = new Date(whole * DAY_MS);
|
|
9348
9355
|
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS));
|
|
9349
9356
|
}
|
|
9357
|
+
function isWholeDay(value) {
|
|
9358
|
+
return typeof value === "string" ? DATE_ONLY.test(value.trim()) : Number.isInteger(dayOf(value));
|
|
9359
|
+
}
|
|
9350
9360
|
function endDayOf(value) {
|
|
9351
9361
|
const day = dayOf(value);
|
|
9352
|
-
|
|
9353
|
-
|
|
9362
|
+
return typeof value !== "number" && isWholeDay(value) ? day + 1 : day;
|
|
9363
|
+
}
|
|
9364
|
+
function rangeEnd(start, end) {
|
|
9365
|
+
return end instanceof Date && !isWholeDay(start) ? dayOf(end) : endDayOf(end);
|
|
9354
9366
|
}
|
|
9355
9367
|
var MINOR = { day: "day", week: "week", month: "month", quarter: "quarter" };
|
|
9356
9368
|
var MAJOR = { day: "month", week: "month", month: "year", quarter: "year" };
|
|
@@ -9408,26 +9420,33 @@ function labelsOf(unit, role, day, locale) {
|
|
|
9408
9420
|
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
9421
|
} else if (unit === "quarter") forms = [`Q${Math.floor(new Date(day * DAY_MS).getUTCMonth() / 3) + 1}`];
|
|
9410
9422
|
else forms = [f({ year: "numeric" }), f({ year: "2-digit" })];
|
|
9411
|
-
return
|
|
9423
|
+
return forms;
|
|
9412
9424
|
}
|
|
9413
9425
|
var DENSITY = { day: 56, week: 16, month: 4, quarter: 1.5 };
|
|
9414
9426
|
var todays = /* @__PURE__ */ new WeakMap();
|
|
9427
|
+
var awaiting = /* @__PURE__ */ new WeakSet();
|
|
9428
|
+
function awaitsToday(scale) {
|
|
9429
|
+
return awaiting.has(scale);
|
|
9430
|
+
}
|
|
9415
9431
|
function calendarDay(day) {
|
|
9416
9432
|
const d = Math.floor(day);
|
|
9417
9433
|
return { day: d, weekday: weekday(d), key: keyOf("day", d) };
|
|
9418
9434
|
}
|
|
9419
9435
|
function ticks(unit, role, s) {
|
|
9420
9436
|
const out = [];
|
|
9421
|
-
for (let p = periodStart(unit, s.startDay, s.weekStartsOn); p < s.endDay;
|
|
9437
|
+
for (let p = periodStart(unit, s.startDay, s.weekStartsOn); p < s.endDay; ) {
|
|
9438
|
+
const next = periodAfter(unit, p);
|
|
9422
9439
|
const from = Math.max(p, s.startDay);
|
|
9423
|
-
const to = Math.min(
|
|
9440
|
+
const to = Math.min(next, s.endDay);
|
|
9424
9441
|
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) });
|
|
9442
|
+
if (!(next > p)) break;
|
|
9443
|
+
p = next;
|
|
9425
9444
|
}
|
|
9426
9445
|
return out;
|
|
9427
9446
|
}
|
|
9428
9447
|
function build(s) {
|
|
9429
9448
|
const { startDay, pxPerDay } = s;
|
|
9430
|
-
const x = (value) => (
|
|
9449
|
+
const x = (value) => (dayOf(value) - startDay) * pxPerDay;
|
|
9431
9450
|
const inRange = (d) => d >= startDay && d < s.endDay;
|
|
9432
9451
|
const todayDay = Math.floor(s.todayValue);
|
|
9433
9452
|
const scale = {
|
|
@@ -9437,9 +9456,9 @@ function build(s) {
|
|
|
9437
9456
|
pxPerDay,
|
|
9438
9457
|
width: (s.endDay - startDay) * pxPerDay,
|
|
9439
9458
|
x,
|
|
9440
|
-
span: (start, end
|
|
9459
|
+
span: (start, end) => {
|
|
9441
9460
|
const x0 = x(start);
|
|
9442
|
-
return { x: x0, width: Math.max(0, (
|
|
9461
|
+
return { x: x0, width: Math.max(0, (rangeEnd(start, end ?? start) - startDay) * pxPerDay - x0) };
|
|
9443
9462
|
},
|
|
9444
9463
|
dayAt: (px) => startDay + px / pxPerDay,
|
|
9445
9464
|
major: ticks(MAJOR[s.zoom], "major", s),
|
|
@@ -9452,9 +9471,7 @@ function build(s) {
|
|
|
9452
9471
|
todays.set(scale, s.todayValue);
|
|
9453
9472
|
return scale;
|
|
9454
9473
|
}
|
|
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);
|
|
9474
|
+
var toMinute = (day) => Math.floor(day * 1440 + 1e-6) / 1440;
|
|
9458
9475
|
function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, pad3) {
|
|
9459
9476
|
const fallback = Number.isFinite(todayValue) ? Math.floor(todayValue) : 0;
|
|
9460
9477
|
const a = Number.isFinite(from) ? from : fallback;
|
|
@@ -9470,28 +9487,44 @@ function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, p
|
|
|
9470
9487
|
}
|
|
9471
9488
|
return build({ zoom, startDay, endDay, pxPerDay: pxPerDay > 0 ? pxPerDay : DENSITY[zoom], todayValue, weekStartsOn, locale });
|
|
9472
9489
|
}
|
|
9473
|
-
function
|
|
9474
|
-
if (!(width > scale.width) || !(scale.pxPerDay > 0)) return scale;
|
|
9490
|
+
function extendedEnd(scale, width) {
|
|
9491
|
+
if (!(width > scale.width) || !(scale.pxPerDay > 0)) return scale.endDay;
|
|
9475
9492
|
const unit = MINOR[scale.zoom];
|
|
9476
9493
|
const last = scale.startDay + Math.ceil(width / scale.pxPerDay) - 1;
|
|
9477
|
-
|
|
9494
|
+
return periodAfter(unit, periodStart(unit, last, scale.weekStartsOn));
|
|
9495
|
+
}
|
|
9496
|
+
function extendTimeScaleTo(scale, endDay) {
|
|
9497
|
+
if (!(endDay > scale.endDay)) return scale;
|
|
9478
9498
|
const todayValue = todays.get(scale) ?? scale.now ?? scale.today ?? NaN;
|
|
9479
|
-
|
|
9499
|
+
const extended = build({ zoom: scale.zoom, startDay: scale.startDay, endDay, pxPerDay: scale.pxPerDay, todayValue, weekStartsOn: scale.weekStartsOn, locale: scale.locale });
|
|
9500
|
+
if (awaiting.has(scale)) awaiting.add(extended);
|
|
9501
|
+
return extended;
|
|
9480
9502
|
}
|
|
9503
|
+
var noSubscription = () => () => {
|
|
9504
|
+
};
|
|
9505
|
+
var inBrowser = () => true;
|
|
9506
|
+
var onServer = () => false;
|
|
9481
9507
|
function useTimeScale({ start, end, zoom, today, weekStartsOn = 1, locale, pxPerDay, pad: pad3 = 0 }) {
|
|
9508
|
+
const readable = useSyncExternalStore(noSubscription, inBrowser, onServer);
|
|
9482
9509
|
const [mounted] = useState(() => toMinute(dayOf(/* @__PURE__ */ new Date())));
|
|
9483
|
-
const
|
|
9484
|
-
const
|
|
9485
|
-
const
|
|
9510
|
+
const pending = today === void 0 && !readable;
|
|
9511
|
+
const from = dayOf(start);
|
|
9512
|
+
const to = rangeEnd(start, end);
|
|
9513
|
+
const todayValue = today !== void 0 ? toMinute(dayOf(today)) : pending ? NaN : mounted;
|
|
9486
9514
|
const density = pxPerDay?.[zoom] ?? DENSITY[zoom];
|
|
9487
|
-
return useMemo(() =>
|
|
9515
|
+
return useMemo(() => {
|
|
9516
|
+
const scale = scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, density, pad3);
|
|
9517
|
+
if (pending) awaiting.add(scale);
|
|
9518
|
+
return scale;
|
|
9519
|
+
}, [from, to, zoom, todayValue, weekStartsOn, locale, density, pad3, pending]);
|
|
9488
9520
|
}
|
|
9489
9521
|
function timeExtent(ranges) {
|
|
9490
9522
|
let start = Infinity;
|
|
9491
9523
|
let end = -Infinity;
|
|
9492
9524
|
for (const r of ranges) {
|
|
9525
|
+
if (r == null) continue;
|
|
9493
9526
|
const s = dayOf(r.start);
|
|
9494
|
-
const e = endDayOf(r.
|
|
9527
|
+
const e = r.end == null ? endDayOf(r.start) : rangeEnd(r.start, r.end);
|
|
9495
9528
|
if (Number.isFinite(s)) start = Math.min(start, s);
|
|
9496
9529
|
if (Number.isFinite(e)) end = Math.max(end, e);
|
|
9497
9530
|
}
|
|
@@ -9499,7 +9532,6 @@ function timeExtent(ranges) {
|
|
|
9499
9532
|
}
|
|
9500
9533
|
var DAY_WORDS = { day: "numeric", month: "long" };
|
|
9501
9534
|
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
9535
|
var SEPARATOR = /\s*[\u2010-\u2015\u2212~\uff5e\u301c-]\s*/;
|
|
9504
9536
|
var english = (f) => new Intl.Locale(f.resolvedOptions().locale).language === "en";
|
|
9505
9537
|
function range(f, a, b, to) {
|
|
@@ -9518,11 +9550,13 @@ function range(f, a, b, to) {
|
|
|
9518
9550
|
if (!joined) out.splice(lastOfStart + 1, 0, to);
|
|
9519
9551
|
return out.join("");
|
|
9520
9552
|
}
|
|
9521
|
-
function formatDateRange(start, end
|
|
9522
|
-
const
|
|
9523
|
-
const
|
|
9553
|
+
function formatDateRange(start, end, words) {
|
|
9554
|
+
const { locale, to, day = DAY_WORDS, time = TIME_WORDS } = words ?? {};
|
|
9555
|
+
const until = end ?? start;
|
|
9556
|
+
const from = dayOf(start);
|
|
9557
|
+
const stop = rangeEnd(start, until);
|
|
9524
9558
|
if (!Number.isFinite(from) || !Number.isFinite(stop)) return "";
|
|
9525
|
-
const timed = !
|
|
9559
|
+
const timed = !isWholeDay(start) || !isWholeDay(until);
|
|
9526
9560
|
const first = timed ? from : Math.floor(from);
|
|
9527
9561
|
const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);
|
|
9528
9562
|
const a = new Date(first * DAY_MS);
|
|
@@ -9552,7 +9586,7 @@ function createScrollStore() {
|
|
|
9552
9586
|
var TimeViewportCtx = createContext(null);
|
|
9553
9587
|
var TimeViewportScrollCtx = createContext(null);
|
|
9554
9588
|
var UNMEASURED = { scrollLeft: 0, visibleWidth: 0 };
|
|
9555
|
-
var
|
|
9589
|
+
var noSubscription2 = () => () => {
|
|
9556
9590
|
};
|
|
9557
9591
|
var unmeasured = () => UNMEASURED;
|
|
9558
9592
|
function useTimeViewportLayout() {
|
|
@@ -9562,7 +9596,7 @@ function useTimeViewportLayout() {
|
|
|
9562
9596
|
}
|
|
9563
9597
|
function useTimeViewport() {
|
|
9564
9598
|
const store = useContext(TimeViewportScrollCtx);
|
|
9565
|
-
const scroll = useSyncExternalStore(store?.subscribe ??
|
|
9599
|
+
const scroll = useSyncExternalStore(store?.subscribe ?? noSubscription2, store?.get ?? unmeasured, unmeasured);
|
|
9566
9600
|
return { ...useTimeViewportLayout(), ...scroll };
|
|
9567
9601
|
}
|
|
9568
9602
|
function fitLabels(boxes, measure, { gap = 8, align = "start", visible } = {}) {
|
|
@@ -9812,17 +9846,16 @@ var ROW_HEIGHT = 40;
|
|
|
9812
9846
|
var MARGIN = 16;
|
|
9813
9847
|
var WHEEL_STEP = 50;
|
|
9814
9848
|
var WHEEL_PAUSE = 250;
|
|
9815
|
-
var FIELD = "input, select, textarea, [contenteditable='true']";
|
|
9816
9849
|
var border = "border-[var(--ds-border-subtle)]";
|
|
9817
|
-
function writeScroll(
|
|
9818
|
-
|
|
9819
|
-
|
|
9850
|
+
function writeScroll(rows, left, visibleWidth) {
|
|
9851
|
+
rows?.style.setProperty("--time-scroll", String(left));
|
|
9852
|
+
rows?.style.setProperty("--time-view-end", String(left + visibleWidth));
|
|
9820
9853
|
}
|
|
9821
9854
|
var TimeViewport = forwardRef(function TimeViewport2({
|
|
9822
9855
|
scale,
|
|
9823
9856
|
onZoomChange,
|
|
9824
9857
|
zooms = TIME_ZOOMS,
|
|
9825
|
-
labelWidth
|
|
9858
|
+
labelWidth = 240,
|
|
9826
9859
|
labelHeader,
|
|
9827
9860
|
header,
|
|
9828
9861
|
toolbar,
|
|
@@ -9837,6 +9870,7 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9837
9870
|
}, ref) {
|
|
9838
9871
|
const scrollerRef = useRef(null);
|
|
9839
9872
|
const headerRef = useRef(null);
|
|
9873
|
+
const rowsRef = useRef(null);
|
|
9840
9874
|
const [frame, setFrame] = useState({ width: 0, header: 0 });
|
|
9841
9875
|
useLayoutEffect(() => {
|
|
9842
9876
|
const el = scrollerRef.current;
|
|
@@ -9854,19 +9888,22 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9854
9888
|
return () => ro.disconnect();
|
|
9855
9889
|
}, []);
|
|
9856
9890
|
const phone = frame.width > 0 && frame.width < PHONE_BELOW;
|
|
9857
|
-
const
|
|
9858
|
-
const visibleWidth = Math.max(0, frame.width -
|
|
9859
|
-
const
|
|
9891
|
+
const pinnedWidth = phone ? Math.min(labelWidth, Math.max(MIN_LABEL, Math.round(frame.width * 0.36))) : labelWidth;
|
|
9892
|
+
const visibleWidth = Math.max(0, frame.width - pinnedWidth);
|
|
9893
|
+
const drawnEnd = extendedEnd(scale, visibleWidth);
|
|
9894
|
+
const drawn = useMemo(() => extendTimeScaleTo(scale, drawnEnd), [scale, drawnEnd]);
|
|
9860
9895
|
const [store] = useState(createScrollStore);
|
|
9861
|
-
const
|
|
9862
|
-
const latest = useLatest({ drawn, visibleWidth, labelWidth, headerHeight: frame.header });
|
|
9896
|
+
const wantLeft = useRef(0);
|
|
9897
|
+
const latest = useLatest({ drawn, visibleWidth, labelWidth: pinnedWidth, headerHeight: frame.header });
|
|
9863
9898
|
const setLeft = useCallback((left) => {
|
|
9864
9899
|
const el = scrollerRef.current;
|
|
9865
9900
|
if (!el) return;
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9901
|
+
const target = Math.max(0, left);
|
|
9902
|
+
el.scrollLeft = target;
|
|
9903
|
+
const now = el.scrollLeft;
|
|
9904
|
+
wantLeft.current = Math.abs(now - target) < 1 ? target : now;
|
|
9905
|
+
writeScroll(rowsRef.current, now, latest.current.visibleWidth);
|
|
9906
|
+
store.set({ scrollLeft: now, visibleWidth: latest.current.visibleWidth });
|
|
9870
9907
|
}, [store, latest]);
|
|
9871
9908
|
const api = useMemo(() => {
|
|
9872
9909
|
const ensureVisible = (x0, x1) => {
|
|
@@ -9889,9 +9926,18 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9889
9926
|
},
|
|
9890
9927
|
page(direction) {
|
|
9891
9928
|
const { drawn: s, visibleWidth: vw } = latest.current;
|
|
9892
|
-
const
|
|
9893
|
-
const
|
|
9894
|
-
|
|
9929
|
+
const left = scrollerRef.current?.scrollLeft ?? 0;
|
|
9930
|
+
const target = left + direction * vw;
|
|
9931
|
+
let to = target;
|
|
9932
|
+
let gap = vw / 2;
|
|
9933
|
+
for (const t of s.minor) {
|
|
9934
|
+
const d = Math.abs(t.x - target);
|
|
9935
|
+
if (d <= gap && (t.x - left) * direction >= 1) {
|
|
9936
|
+
to = t.x;
|
|
9937
|
+
gap = d;
|
|
9938
|
+
}
|
|
9939
|
+
}
|
|
9940
|
+
setLeft(to);
|
|
9895
9941
|
},
|
|
9896
9942
|
ensureVisible,
|
|
9897
9943
|
reveal(target) {
|
|
@@ -9912,29 +9958,34 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9912
9958
|
useImperativeHandle(ref, () => api, [api]);
|
|
9913
9959
|
const todayAtX = todayAt === "now" ? drawn.now === null ? null : drawn.x(drawn.now) : drawn.today === null ? null : drawn.x(drawn.today) + drawn.pxPerDay / 2;
|
|
9914
9960
|
const todayX = showToday ? todayAtX : null;
|
|
9915
|
-
const layout = useMemo(() => ({ scale: drawn, labelWidth, showToday, todayX, compact: phone, ...api }), [drawn,
|
|
9961
|
+
const layout = useMemo(() => ({ scale: drawn, labelWidth: pinnedWidth, showToday, todayX, compact: phone, ...api }), [drawn, pinnedWidth, showToday, todayX, phone, api]);
|
|
9916
9962
|
const pending = useRef(null);
|
|
9917
9963
|
const applied = useRef(null);
|
|
9918
9964
|
useLayoutEffect(() => {
|
|
9919
9965
|
const el = scrollerRef.current;
|
|
9920
9966
|
if (!el || visibleWidth <= 0) return;
|
|
9921
|
-
|
|
9922
|
-
|
|
9967
|
+
const left = el.scrollLeft;
|
|
9968
|
+
const publish = () => {
|
|
9969
|
+
writeScroll(rowsRef.current, left, visibleWidth);
|
|
9970
|
+
store.set({ scrollLeft: left, visibleWidth });
|
|
9971
|
+
};
|
|
9923
9972
|
const prev = applied.current;
|
|
9924
|
-
|
|
9973
|
+
let to = null;
|
|
9925
9974
|
if (!prev) {
|
|
9975
|
+
if (initialDate === void 0 && awaitsToday(drawn)) return publish();
|
|
9926
9976
|
const at = initialDate !== void 0 ? drawn.x(initialDate) : todayAtX;
|
|
9927
|
-
if (at !== null && Number.isFinite(at))
|
|
9928
|
-
|
|
9977
|
+
if (at !== null && Number.isFinite(at)) to = at - visibleWidth / 2;
|
|
9978
|
+
} else if (prev.startDay !== drawn.startDay || prev.pxPerDay !== drawn.pxPerDay || prev.visibleWidth !== visibleWidth) {
|
|
9979
|
+
const want = pending.current;
|
|
9980
|
+
pending.current = null;
|
|
9981
|
+
const anchor = want && want.zoom === drawn.zoom ? want : { day: prev.startDay + (wantLeft.current + prev.visibleWidth / 2) / prev.pxPerDay, at: visibleWidth / 2 };
|
|
9982
|
+
to = drawn.x(anchor.day) - anchor.at;
|
|
9929
9983
|
}
|
|
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);
|
|
9984
|
+
applied.current = { startDay: drawn.startDay, pxPerDay: drawn.pxPerDay, visibleWidth };
|
|
9985
|
+
if (to === null) return publish();
|
|
9986
|
+
setLeft(to);
|
|
9936
9987
|
const focused = document.activeElement;
|
|
9937
|
-
if (focused instanceof HTMLElement && focused !== el && el.contains(focused)) api.reveal(focused);
|
|
9988
|
+
if (prev && focused instanceof HTMLElement && focused !== el && el.contains(focused)) api.reveal(focused);
|
|
9938
9989
|
}, [drawn, visibleWidth, initialDate, todayAtX, setLeft, store, api]);
|
|
9939
9990
|
const shaded = [];
|
|
9940
9991
|
if (shadeDays && drawn.pxPerDay >= SHADE_MIN) {
|
|
@@ -9956,7 +10007,7 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9956
10007
|
const f = document.activeElement;
|
|
9957
10008
|
if (!(f instanceof HTMLElement) || f === el || !el.contains(f)) return void 0;
|
|
9958
10009
|
const r = f.getBoundingClientRect();
|
|
9959
|
-
const x = (r.left + r.right) / 2 - el.getBoundingClientRect().left -
|
|
10010
|
+
const x = (r.left + r.right) / 2 - el.getBoundingClientRect().left - pinnedWidth;
|
|
9960
10011
|
return x >= 0 && x <= visibleWidth ? x : void 0;
|
|
9961
10012
|
};
|
|
9962
10013
|
const zoom = (direction, at) => {
|
|
@@ -9980,10 +10031,11 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9980
10031
|
};
|
|
9981
10032
|
const onKeyDown = (e) => {
|
|
9982
10033
|
if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
10034
|
+
if (!e.currentTarget.contains(e.target)) return;
|
|
9983
10035
|
if (e.target instanceof HTMLElement && e.target.closest(FIELD)) return;
|
|
9984
|
-
if (
|
|
10036
|
+
if (ZOOM_KEYS.in.includes(e.key)) {
|
|
9985
10037
|
if (zoom(-1)) e.preventDefault();
|
|
9986
|
-
} else if (
|
|
10038
|
+
} else if (ZOOM_KEYS.out.includes(e.key)) {
|
|
9987
10039
|
if (zoom(1)) e.preventDefault();
|
|
9988
10040
|
} else if (e.shiftKey && (e.key === "ArrowLeft" || e.key === "ArrowRight")) {
|
|
9989
10041
|
e.preventDefault();
|
|
@@ -9993,13 +10045,15 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
9993
10045
|
const wheel = useRef({ sum: 0, at: -Infinity });
|
|
9994
10046
|
const onWheel = useLatest((e) => {
|
|
9995
10047
|
if (!(e.ctrlKey || e.metaKey) || !onZoomChange) return;
|
|
9996
|
-
e.preventDefault();
|
|
9997
10048
|
const w = wheel.current;
|
|
9998
|
-
if (e.timeStamp - w.at < WHEEL_PAUSE) return;
|
|
10049
|
+
if (e.timeStamp - w.at < WHEEL_PAUSE) return e.preventDefault();
|
|
10050
|
+
const direction = e.deltaY < 0 ? -1 : e.deltaY > 0 ? 1 : 0;
|
|
10051
|
+
if (direction === 0 || zoomTo(direction) === null) return;
|
|
10052
|
+
e.preventDefault();
|
|
9999
10053
|
w.sum += e.deltaY * (e.deltaMode === 1 ? 16 : e.deltaMode === 2 ? 400 : 1);
|
|
10000
10054
|
if (Math.abs(w.sum) < WHEEL_STEP) return;
|
|
10001
10055
|
const el = scrollerRef.current;
|
|
10002
|
-
const x = el ? e.clientX - el.getBoundingClientRect().left -
|
|
10056
|
+
const x = el ? e.clientX - el.getBoundingClientRect().left - pinnedWidth : NaN;
|
|
10003
10057
|
zoom(w.sum < 0 ? -1 : 1, x >= 0 && x <= visibleWidth ? x : void 0);
|
|
10004
10058
|
wheel.current = { sum: 0, at: e.timeStamp };
|
|
10005
10059
|
});
|
|
@@ -10030,9 +10084,10 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10030
10084
|
const onScroll = () => {
|
|
10031
10085
|
const el = scrollerRef.current;
|
|
10032
10086
|
if (!el) return;
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10087
|
+
const left = el.scrollLeft;
|
|
10088
|
+
if (Math.abs(left - wantLeft.current) >= 1) wantLeft.current = left;
|
|
10089
|
+
writeScroll(rowsRef.current, left, visibleWidth);
|
|
10090
|
+
store.set({ scrollLeft: left, visibleWidth });
|
|
10036
10091
|
};
|
|
10037
10092
|
const headerNode = header === void 0 ? /* @__PURE__ */ jsx(TimeScaleHeader, {}) : header;
|
|
10038
10093
|
const hasHeader = headerNode != null || labelHeader != null;
|
|
@@ -10064,14 +10119,14 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10064
10119
|
tabIndex: tabStop ? 0 : void 0,
|
|
10065
10120
|
onScroll,
|
|
10066
10121
|
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:
|
|
10122
|
+
style: { scrollPaddingInlineStart: pinnedWidth, scrollPaddingTop: frame.header },
|
|
10123
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-full flex-col", style: { width: pinnedWidth + drawn.width }, children: [
|
|
10069
10124
|
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
10125
|
/* @__PURE__ */ jsx(
|
|
10071
10126
|
"div",
|
|
10072
10127
|
{
|
|
10073
10128
|
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:
|
|
10129
|
+
style: { width: pinnedWidth },
|
|
10075
10130
|
children: labelHeader
|
|
10076
10131
|
}
|
|
10077
10132
|
),
|
|
@@ -10090,18 +10145,18 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10090
10145
|
)
|
|
10091
10146
|
] }),
|
|
10092
10147
|
/* @__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:
|
|
10148
|
+
/* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-y-0", style: { insetInlineStart: pinnedWidth, width: drawn.width }, children: [
|
|
10094
10149
|
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
10150
|
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
10151
|
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
10152
|
] }),
|
|
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:
|
|
10153
|
+
/* @__PURE__ */ jsx("div", { ref: rowsRef, "data-time-rows": "", className: "contents", children }),
|
|
10154
|
+
/* @__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
10155
|
] })
|
|
10101
10156
|
] })
|
|
10102
10157
|
}
|
|
10103
10158
|
),
|
|
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)]" })
|
|
10159
|
+
/* @__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
10160
|
] })
|
|
10106
10161
|
] }) }) })
|
|
10107
10162
|
);
|
|
@@ -10157,7 +10212,7 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10157
10212
|
{
|
|
10158
10213
|
...props,
|
|
10159
10214
|
ref: barRef,
|
|
10160
|
-
className: cn("absolute top-ds-2 bottom-ds-2 flex items-center overflow-clip rounded-[var(--ds-radius-sm)] outline-none focus-visible:shadow-[var(--ds-shadow-focus)]", className),
|
|
10215
|
+
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
10216
|
style: { insetInlineStart: x, width: drawnWidth, ...style },
|
|
10162
10217
|
children: label
|
|
10163
10218
|
}
|
|
@@ -10175,13 +10230,39 @@ var HEAD = 6;
|
|
|
10175
10230
|
var BESIDE = STUB + 6;
|
|
10176
10231
|
var groupKey = (id) => `group:${id}`;
|
|
10177
10232
|
var itemKey = (id) => `item:${id}`;
|
|
10233
|
+
var asDate = (value) => value instanceof Date || typeof value === "string" ? value : void 0;
|
|
10234
|
+
function datesOf(item) {
|
|
10235
|
+
const start = asDate(item.start);
|
|
10236
|
+
if (start === void 0 || !Number.isFinite(dayOf(start))) return null;
|
|
10237
|
+
if (item.milestone || item.end === void 0 || item.end === null) return { start, end: start };
|
|
10238
|
+
const end = asDate(item.end);
|
|
10239
|
+
return end !== void 0 && Number.isFinite(endDayOf(end)) ? { start, end } : null;
|
|
10240
|
+
}
|
|
10241
|
+
function uniqueById(list) {
|
|
10242
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10243
|
+
const repeated = /* @__PURE__ */ new Set();
|
|
10244
|
+
const unique = [];
|
|
10245
|
+
for (const entry of list) {
|
|
10246
|
+
if (seen.has(entry.id)) repeated.add(entry.id);
|
|
10247
|
+
else {
|
|
10248
|
+
seen.add(entry.id);
|
|
10249
|
+
unique.push(entry);
|
|
10250
|
+
}
|
|
10251
|
+
}
|
|
10252
|
+
return repeated.size ? { unique, repeated: [...repeated] } : { unique: list, repeated: [] };
|
|
10253
|
+
}
|
|
10178
10254
|
function ganttRows(items, groups, collapsed) {
|
|
10179
10255
|
const known = new Set(groups.map((g) => g.id));
|
|
10180
10256
|
const byGroup = /* @__PURE__ */ new Map();
|
|
10181
10257
|
const loose = [];
|
|
10182
10258
|
for (const item of items) {
|
|
10183
|
-
if (item.group === void 0 || !known.has(item.group))
|
|
10184
|
-
|
|
10259
|
+
if (item.group === void 0 || !known.has(item.group)) {
|
|
10260
|
+
loose.push(item);
|
|
10261
|
+
continue;
|
|
10262
|
+
}
|
|
10263
|
+
const list = byGroup.get(item.group);
|
|
10264
|
+
if (list) list.push(item);
|
|
10265
|
+
else byGroup.set(item.group, [item]);
|
|
10185
10266
|
}
|
|
10186
10267
|
const shown = groups.filter((g) => byGroup.has(g.id));
|
|
10187
10268
|
const topLevel = shown.length + loose.length;
|
|
@@ -10199,16 +10280,23 @@ function ganttRows(items, groups, collapsed) {
|
|
|
10199
10280
|
return rows;
|
|
10200
10281
|
}
|
|
10201
10282
|
function itemShape(item, scale) {
|
|
10283
|
+
const dates = datesOf(item);
|
|
10284
|
+
if (!dates) return { kind: item.milestone ? "milestone" : "bar", x0: NaN, x1: NaN, in: NaN, out: NaN };
|
|
10202
10285
|
if (item.milestone) {
|
|
10203
|
-
const centre = scale.x((dayOf(
|
|
10286
|
+
const centre = scale.x((dayOf(dates.start) + endDayOf(dates.start)) / 2);
|
|
10204
10287
|
return { kind: "milestone", x0: centre - TIP, x1: centre + TIP, in: centre - TIP, out: centre + TIP };
|
|
10205
10288
|
}
|
|
10206
|
-
const { x, width } = scale.span(
|
|
10289
|
+
const { x, width } = scale.span(dates.start, dates.end);
|
|
10207
10290
|
const x1 = x + Math.max(width, MIN_BAR);
|
|
10208
10291
|
return { kind: "bar", x0: x, x1, in: x, out: x1 };
|
|
10209
10292
|
}
|
|
10210
|
-
function
|
|
10211
|
-
|
|
10293
|
+
function itemsExtent(items) {
|
|
10294
|
+
const ranges = [];
|
|
10295
|
+
for (const item of items) {
|
|
10296
|
+
const dates = datesOf(item);
|
|
10297
|
+
if (dates) ranges.push(dates);
|
|
10298
|
+
}
|
|
10299
|
+
return timeExtent(ranges);
|
|
10212
10300
|
}
|
|
10213
10301
|
var drawable = (shape) => !!shape && Number.isFinite(shape.x0) && Number.isFinite(shape.x1);
|
|
10214
10302
|
function ganttArrows(items, rows, shapeOf, collapsed) {
|
|
@@ -10249,19 +10337,37 @@ function labelPlace(shape, textWidth, scaleWidth, { pad: pad3 = 8, gap = BESIDE
|
|
|
10249
10337
|
return shape.x0 - gap - textWidth >= 0 ? "before" : "after";
|
|
10250
10338
|
}
|
|
10251
10339
|
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)]" },
|
|
10340
|
+
neutral: { fill: "bg-[var(--ds-status-neutral)]", on: "text-[var(--ds-text-on-neutral)]", icon: "minus" },
|
|
10341
|
+
info: { fill: "bg-[var(--ds-status-info)]", on: "text-[var(--ds-text-on-info)]", icon: "info" },
|
|
10254
10342
|
success: { fill: "bg-[var(--ds-status-success)]", on: "text-[var(--ds-text-on-success)]", icon: "check" },
|
|
10255
10343
|
warning: { fill: "bg-[var(--ds-status-warning)]", on: "text-[var(--ds-text-on-warning)]", icon: "warning" },
|
|
10256
10344
|
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)]" }
|
|
10345
|
+
accent: { fill: "bg-[var(--ds-accent-primary)]", on: "text-[var(--ds-text-on-primary)]", icon: "star" }
|
|
10258
10346
|
};
|
|
10259
10347
|
var ICON = 12;
|
|
10260
10348
|
var ICON_GAP = 4;
|
|
10261
10349
|
var LEVEL_INDENT = 16;
|
|
10262
10350
|
var TARGET = 24;
|
|
10351
|
+
var NO_DATES = "no dates";
|
|
10263
10352
|
var KNOCKOUT = 2;
|
|
10353
|
+
var EDGE = "border-[length:1px] border-transparent";
|
|
10354
|
+
var EDGE_WIDTH = 1;
|
|
10264
10355
|
var SELECTED = "outline-solid outline-2 outline-offset-2 outline-[var(--ds-text-primary)]";
|
|
10356
|
+
var UNDATED_INSET = 16;
|
|
10357
|
+
var NO_GROUPS = [];
|
|
10358
|
+
var NO_STATUSES = {};
|
|
10359
|
+
var warned = /* @__PURE__ */ new Set();
|
|
10360
|
+
function warnOnce(message) {
|
|
10361
|
+
let dev = false;
|
|
10362
|
+
try {
|
|
10363
|
+
dev = process.env.NODE_ENV !== "production";
|
|
10364
|
+
} catch {
|
|
10365
|
+
dev = false;
|
|
10366
|
+
}
|
|
10367
|
+
if (!dev || warned.has(message)) return;
|
|
10368
|
+
warned.add(message);
|
|
10369
|
+
console.warn(`Gantt: ${message}`);
|
|
10370
|
+
}
|
|
10265
10371
|
function GanttArrows({ arrows, width, height }) {
|
|
10266
10372
|
const { labelWidth } = useTimeViewportLayout();
|
|
10267
10373
|
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 +10375,47 @@ function GanttArrows({ arrows, width, height }) {
|
|
|
10269
10375
|
/* @__PURE__ */ jsx("path", { d: a.head, fill: "currentColor" })
|
|
10270
10376
|
] }, a.key)) });
|
|
10271
10377
|
}
|
|
10378
|
+
function Cue({ name, size }) {
|
|
10379
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-gantt-cue": name, className: "flex shrink-0", children: /* @__PURE__ */ jsx(Icon, { name, size }) });
|
|
10380
|
+
}
|
|
10272
10381
|
function Legend({ statuses }) {
|
|
10273
10382
|
const entries = Object.entries(statuses);
|
|
10274
10383
|
if (!entries.length) return null;
|
|
10275
10384
|
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
10385
|
const tone = TONES[s.tone] ?? TONES.neutral;
|
|
10277
10386
|
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:
|
|
10387
|
+
/* @__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
10388
|
s.label
|
|
10280
10389
|
] }, key);
|
|
10281
10390
|
}) });
|
|
10282
10391
|
}
|
|
10392
|
+
function NoDates({ cue, selected, className, ...props }) {
|
|
10393
|
+
const { labelWidth } = useTimeViewportLayout();
|
|
10394
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center", children: /* @__PURE__ */ jsxs(
|
|
10395
|
+
"span",
|
|
10396
|
+
{
|
|
10397
|
+
...props,
|
|
10398
|
+
"data-gantt-shape": "undated",
|
|
10399
|
+
className: cn(
|
|
10400
|
+
"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)]",
|
|
10401
|
+
"outline-none focus-visible:outline-hidden focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
10402
|
+
selected && SELECTED,
|
|
10403
|
+
className
|
|
10404
|
+
),
|
|
10405
|
+
style: { insetInlineStart: labelWidth + UNDATED_INSET },
|
|
10406
|
+
children: [
|
|
10407
|
+
cue,
|
|
10408
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "No dates" })
|
|
10409
|
+
]
|
|
10410
|
+
}
|
|
10411
|
+
) });
|
|
10412
|
+
}
|
|
10283
10413
|
function Gantt({
|
|
10284
10414
|
items,
|
|
10285
|
-
groups =
|
|
10415
|
+
groups = NO_GROUPS,
|
|
10286
10416
|
selectedId,
|
|
10287
10417
|
onSelect,
|
|
10288
|
-
statuses =
|
|
10418
|
+
statuses = NO_STATUSES,
|
|
10289
10419
|
zoom: zoomProp,
|
|
10290
10420
|
defaultZoom = "week",
|
|
10291
10421
|
onZoomChange,
|
|
@@ -10293,6 +10423,7 @@ function Gantt({
|
|
|
10293
10423
|
weekStartsOn,
|
|
10294
10424
|
locale,
|
|
10295
10425
|
renderLabel,
|
|
10426
|
+
describe,
|
|
10296
10427
|
labelHeader = "Task",
|
|
10297
10428
|
toolbar,
|
|
10298
10429
|
"aria-label": ariaLabel,
|
|
@@ -10304,31 +10435,53 @@ function Gantt({
|
|
|
10304
10435
|
if (zoomProp === void 0) setZoomState(next);
|
|
10305
10436
|
onZoomChange?.(next);
|
|
10306
10437
|
};
|
|
10438
|
+
const zoomable = zoomProp === void 0 || onZoomChange !== void 0;
|
|
10307
10439
|
const [selectedState, setSelectedState] = useState(null);
|
|
10308
|
-
const
|
|
10440
|
+
const [controlled, setControlled] = useState(selectedId !== void 0);
|
|
10441
|
+
const [overridden, setOverridden] = useState(null);
|
|
10442
|
+
if (!controlled && selectedId !== void 0) {
|
|
10443
|
+
setControlled(true);
|
|
10444
|
+
if (selectedState !== null && selectedState !== selectedId) setOverridden(selectedState);
|
|
10445
|
+
}
|
|
10446
|
+
const isControlled = controlled || selectedId !== void 0;
|
|
10447
|
+
const selected = isControlled ? selectedId ?? null : selectedState;
|
|
10448
|
+
useEffect(() => {
|
|
10449
|
+
if (overridden !== null) {
|
|
10450
|
+
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.");
|
|
10451
|
+
}
|
|
10452
|
+
}, [overridden]);
|
|
10309
10453
|
const select = (item) => {
|
|
10310
|
-
if (
|
|
10454
|
+
if (!isControlled) setSelectedState(item?.id ?? null);
|
|
10311
10455
|
onSelect?.(item);
|
|
10312
10456
|
};
|
|
10313
10457
|
const [collapsed, setCollapsed] = useState(() => new Set(groups.filter((g) => g.defaultCollapsed).map((g) => g.id)));
|
|
10314
|
-
const
|
|
10458
|
+
const plan = useMemo(() => uniqueById(items), [items]);
|
|
10459
|
+
const phases = useMemo(() => uniqueById(groups), [groups]);
|
|
10460
|
+
useEffect(() => {
|
|
10461
|
+
const quoted = (ids) => ids.map((id) => `"${id}"`).join(", ");
|
|
10462
|
+
if (plan.repeated.length) warnOnce(`more than one item has the id ${quoted(plan.repeated)}; only the first of each is shown.`);
|
|
10463
|
+
if (phases.repeated.length) warnOnce(`more than one group has the id ${quoted(phases.repeated)}; only the first of each is shown.`);
|
|
10464
|
+
}, [plan, phases]);
|
|
10465
|
+
const tasks = plan.unique;
|
|
10466
|
+
const extent = useMemo(() => itemsExtent(tasks), [tasks]);
|
|
10315
10467
|
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(
|
|
10468
|
+
const rows = useMemo(() => ganttRows(tasks, phases.unique, collapsed), [tasks, phases, collapsed]);
|
|
10469
|
+
const shapes = useMemo(() => new Map(tasks.map((i) => [i.id, itemShape(i, scale)])), [tasks, scale]);
|
|
10470
|
+
const extents = useMemo(() => new Map(rows.filter((r) => r.children).map((r) => [r.group.id, itemsExtent(r.children)])), [rows]);
|
|
10471
|
+
const arrows = useMemo(() => ganttArrows(tasks, rows, (i) => shapes.get(i.id), collapsed), [tasks, rows, shapes, collapsed]);
|
|
10320
10472
|
const byKey = useMemo(() => new Map(rows.map((r) => [r.key, r])), [rows]);
|
|
10321
10473
|
const names = useMemo(() => {
|
|
10322
|
-
const byId = new Map(
|
|
10474
|
+
const byId = new Map(tasks.map((i) => [i.id, i]));
|
|
10323
10475
|
const list = new Intl.ListFormat(locale, { type: "conjunction" });
|
|
10324
10476
|
const out = /* @__PURE__ */ new Map();
|
|
10325
|
-
for (const item of
|
|
10477
|
+
for (const item of tasks) {
|
|
10478
|
+
const dates = datesOf(item);
|
|
10326
10479
|
const after = (item.dependsOn ?? []).flatMap((id) => byId.has(id) && id !== item.id ? [byId.get(id).title] : []);
|
|
10327
10480
|
const status = item.status === void 0 ? void 0 : statuses[item.status];
|
|
10328
10481
|
out.set(itemKey(item.id), [
|
|
10329
10482
|
item.title,
|
|
10330
10483
|
item.milestone ? "milestone" : null,
|
|
10331
|
-
formatDateRange(
|
|
10484
|
+
dates ? formatDateRange(dates.start, dates.end, { locale }) : NO_DATES,
|
|
10332
10485
|
status?.label ?? null,
|
|
10333
10486
|
after.length ? `after ${list.format(after)}` : null
|
|
10334
10487
|
].filter((part) => part).join(", "));
|
|
@@ -10337,31 +10490,66 @@ function Gantt({
|
|
|
10337
10490
|
if (!row.group || !row.children) continue;
|
|
10338
10491
|
const e = extents.get(row.group.id);
|
|
10339
10492
|
const count = row.children.length === 1 ? "1 item" : `${row.children.length} items`;
|
|
10340
|
-
|
|
10493
|
+
const span = Number.isFinite(e.start) ? formatDateRange(e.start, e.end, { locale }) : NO_DATES;
|
|
10494
|
+
out.set(row.key, [row.group.title, span, count].filter((part) => part).join(", "));
|
|
10341
10495
|
}
|
|
10342
10496
|
return out;
|
|
10343
|
-
}, [
|
|
10497
|
+
}, [tasks, rows, extents, statuses, locale]);
|
|
10498
|
+
const nameOf = (row) => {
|
|
10499
|
+
const name = names.get(row.key) ?? "";
|
|
10500
|
+
const words = row.item && describe ? describe(row.item) : "";
|
|
10501
|
+
return words ? `${name}, ${words}` : name;
|
|
10502
|
+
};
|
|
10503
|
+
const regionLabel = useMemo(() => {
|
|
10504
|
+
const span = Number.isFinite(extent.start) ? formatDateRange(extent.start, extent.end, { locale }) : "";
|
|
10505
|
+
return `${ariaLabel}, ${span || NO_DATES}`;
|
|
10506
|
+
}, [ariaLabel, extent, locale]);
|
|
10507
|
+
const hasStatuses = useMemo(() => Object.keys(statuses).length > 0, [statuses]);
|
|
10508
|
+
const toneOf = (item) => {
|
|
10509
|
+
const status = item.status === void 0 ? void 0 : statuses[item.status];
|
|
10510
|
+
const tone = TONES[status?.tone ?? "neutral"] ?? TONES.neutral;
|
|
10511
|
+
return { tone, cue: hasStatuses ? status?.icon ?? tone.icon : void 0 };
|
|
10512
|
+
};
|
|
10344
10513
|
const probeRef = useRef(null);
|
|
10345
10514
|
const measure = useTextMeasure(probeRef);
|
|
10346
10515
|
const treeRef = useRef(null);
|
|
10347
10516
|
const viewportRef = useRef(null);
|
|
10348
10517
|
const [activeState, setActive] = useState(null);
|
|
10518
|
+
const [focusWithin, setFocusWithin] = useState(false);
|
|
10349
10519
|
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);
|
|
10520
|
+
const selectedRow = selectedKey !== null && byKey.has(selectedKey) ? selectedKey : null;
|
|
10521
|
+
const lastFocused = activeState !== null && byKey.has(activeState) ? activeState : null;
|
|
10522
|
+
const active = (focusWithin ? lastFocused : null) ?? selectedRow ?? lastFocused ?? rows[0]?.key ?? "";
|
|
10523
|
+
const focusedRow = useRef(null);
|
|
10524
|
+
useLayoutEffect(() => {
|
|
10525
|
+
const was = focusedRow.current;
|
|
10526
|
+
if (!was) return;
|
|
10527
|
+
const row = byKey.get(was.key);
|
|
10528
|
+
if (row) {
|
|
10529
|
+
if (row.index !== was.index) focusedRow.current = { key: was.key, index: row.index };
|
|
10530
|
+
return;
|
|
10363
10531
|
}
|
|
10364
|
-
|
|
10532
|
+
focusedRow.current = null;
|
|
10533
|
+
const now = document.activeElement;
|
|
10534
|
+
if (now && now !== document.body && now.isConnected) return;
|
|
10535
|
+
const tree = treeRef.current;
|
|
10536
|
+
if (tree) focusAfterRemoval(tree.querySelectorAll("[data-grid-key]"), was.index);
|
|
10537
|
+
}, [byKey]);
|
|
10538
|
+
const lastSelected = useRef(selected);
|
|
10539
|
+
useEffect(() => {
|
|
10540
|
+
if (lastSelected.current === selected) return;
|
|
10541
|
+
lastSelected.current = selected;
|
|
10542
|
+
const tree = treeRef.current;
|
|
10543
|
+
if (selected === null || !tree || tree.contains(document.activeElement)) return;
|
|
10544
|
+
const el = tree.querySelector(`[data-grid-key="${CSS.escape(itemKey(selected))}"]`);
|
|
10545
|
+
if (el) viewportRef.current?.reveal(el);
|
|
10546
|
+
}, [selected]);
|
|
10547
|
+
const toggle = (id) => setCollapsed((cur) => {
|
|
10548
|
+
const next = new Set(cur);
|
|
10549
|
+
if (next.has(id)) next.delete(id);
|
|
10550
|
+
else next.add(id);
|
|
10551
|
+
return next;
|
|
10552
|
+
});
|
|
10365
10553
|
const activate = (row) => {
|
|
10366
10554
|
if (row.group) toggle(row.group.id);
|
|
10367
10555
|
else if (row.item) select(row.item);
|
|
@@ -10417,6 +10605,11 @@ function Gantt({
|
|
|
10417
10605
|
}
|
|
10418
10606
|
grid.onKeyDown(e);
|
|
10419
10607
|
};
|
|
10608
|
+
const onTreeBlur = (e) => {
|
|
10609
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
10610
|
+
setFocusWithin(false);
|
|
10611
|
+
if (e.relatedTarget) focusedRow.current = null;
|
|
10612
|
+
};
|
|
10420
10613
|
const onRowClick = (row) => {
|
|
10421
10614
|
if (row.item) select(row.item.id === selected ? null : row.item);
|
|
10422
10615
|
else if (row.group) toggle(row.group.id);
|
|
@@ -10428,25 +10621,33 @@ function Gantt({
|
|
|
10428
10621
|
"aria-level": row.level,
|
|
10429
10622
|
"aria-setsize": row.setSize,
|
|
10430
10623
|
"aria-posinset": row.posInSet,
|
|
10431
|
-
"aria-label":
|
|
10624
|
+
"aria-label": nameOf(row),
|
|
10432
10625
|
"data-grid-key": row.key,
|
|
10433
10626
|
tabIndex: grid.tabIndexOf(row.key),
|
|
10434
|
-
onFocus: () =>
|
|
10627
|
+
onFocus: () => {
|
|
10628
|
+
setActive(row.key);
|
|
10629
|
+
focusedRow.current = { key: row.key, index: row.index };
|
|
10630
|
+
}
|
|
10435
10631
|
});
|
|
10436
10632
|
const renderItem = (row, item) => {
|
|
10437
10633
|
const shape = shapes.get(item.id);
|
|
10438
|
-
|
|
10439
|
-
const tone = TONES[item.status !== void 0 && statuses[item.status]?.tone || "neutral"] ?? TONES.neutral;
|
|
10634
|
+
const dates = datesOf(item);
|
|
10440
10635
|
const isSelected = item.id === selected;
|
|
10441
|
-
const
|
|
10442
|
-
|
|
10636
|
+
const { tone, cue } = toneOf(item);
|
|
10637
|
+
if (!dates || !drawable(shape)) {
|
|
10638
|
+
return /* @__PURE__ */ jsx(NoDates, { ...treeitem(row), "aria-selected": isSelected, selected: isSelected, cue: cue && /* @__PURE__ */ jsx(Cue, { name: cue, size: ICON }) });
|
|
10639
|
+
}
|
|
10640
|
+
const textWidth = measure(item.title) + (cue ? ICON + ICON_GAP : 0) + 2 * KNOCKOUT;
|
|
10641
|
+
const place = labelPlace(shape, textWidth + 2 * EDGE_WIDTH, scale.width);
|
|
10443
10642
|
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
10643
|
const title = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10446
|
-
|
|
10644
|
+
cue && /* @__PURE__ */ jsx(Cue, { name: cue, size: ICON }),
|
|
10447
10645
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: item.title })
|
|
10448
10646
|
] });
|
|
10449
|
-
const shapeBox = shape.kind === "milestone" ?
|
|
10647
|
+
const shapeBox = shape.kind === "milestone" ? (
|
|
10648
|
+
// the target's own outline is its focus indicator in forced colours, which drop the diamond's shadow ring
|
|
10649
|
+
/* @__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 } }) })
|
|
10650
|
+
) : (
|
|
10450
10651
|
// TimeBar keeps the title in view beside the pinned column while the bar's start is scrolled away
|
|
10451
10652
|
/* @__PURE__ */ jsx(
|
|
10452
10653
|
TimeBar,
|
|
@@ -10455,10 +10656,10 @@ function Gantt({
|
|
|
10455
10656
|
"aria-selected": isSelected,
|
|
10456
10657
|
"data-gantt-shape": "bar",
|
|
10457
10658
|
"data-item": item.id,
|
|
10458
|
-
start:
|
|
10459
|
-
end:
|
|
10659
|
+
start: dates.start,
|
|
10660
|
+
end: dates.end,
|
|
10460
10661
|
minWidth: MIN_BAR,
|
|
10461
|
-
className: cn("cursor-pointer text-xs font-medium", tone.fill, tone.on, isSelected && SELECTED),
|
|
10662
|
+
className: cn("cursor-pointer text-xs font-medium", EDGE, tone.fill, tone.on, isSelected && SELECTED),
|
|
10462
10663
|
style: { top: (ROW_HEIGHT2 - BAR_HEIGHT) / 2, bottom: "auto", height: BAR_HEIGHT },
|
|
10463
10664
|
children: place === "inside" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex min-w-0 items-center gap-ds-1 overflow-hidden", children: title })
|
|
10464
10665
|
}
|
|
@@ -10479,23 +10680,29 @@ function Gantt({
|
|
|
10479
10680
|
)
|
|
10480
10681
|
] });
|
|
10481
10682
|
};
|
|
10482
|
-
const renderGroup = (row,
|
|
10483
|
-
|
|
10484
|
-
|
|
10485
|
-
/* @__PURE__ */
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10494
|
-
|
|
10495
|
-
|
|
10496
|
-
|
|
10497
|
-
|
|
10498
|
-
|
|
10683
|
+
const renderGroup = (row, group) => {
|
|
10684
|
+
const extent2 = extents.get(group.id);
|
|
10685
|
+
const expanded = !collapsed.has(group.id);
|
|
10686
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10687
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "absolute inset-0 bg-[var(--ds-bg-muted)] opacity-60" }),
|
|
10688
|
+
extent2 && Number.isFinite(extent2.start) ? (
|
|
10689
|
+
// a 24 px target around the thin summary bar it draws
|
|
10690
|
+
/* @__PURE__ */ jsx(
|
|
10691
|
+
TimeBar,
|
|
10692
|
+
{
|
|
10693
|
+
...treeitem(row),
|
|
10694
|
+
"aria-expanded": expanded,
|
|
10695
|
+
"data-gantt-shape": "summary",
|
|
10696
|
+
start: extent2.start,
|
|
10697
|
+
end: extent2.end,
|
|
10698
|
+
minWidth: MIN_BAR,
|
|
10699
|
+
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)]",
|
|
10700
|
+
style: { top: (ROW_HEIGHT2 - TARGET) / 2, bottom: "auto", height: TARGET }
|
|
10701
|
+
}
|
|
10702
|
+
)
|
|
10703
|
+
) : /* @__PURE__ */ jsx(NoDates, { ...treeitem(row), "aria-expanded": expanded })
|
|
10704
|
+
] });
|
|
10705
|
+
};
|
|
10499
10706
|
const label = (row) => {
|
|
10500
10707
|
if (row.group) {
|
|
10501
10708
|
return /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "flex min-w-0 items-center gap-ds-1.5 font-medium", children: [
|
|
@@ -10513,27 +10720,30 @@ function Gantt({
|
|
|
10513
10720
|
] })
|
|
10514
10721
|
);
|
|
10515
10722
|
};
|
|
10516
|
-
|
|
10723
|
+
const legend = /* @__PURE__ */ jsx(Legend, { statuses });
|
|
10724
|
+
const legendApart = toolbar === false && hasStatuses;
|
|
10725
|
+
const chart = /* @__PURE__ */ jsx(
|
|
10517
10726
|
TimeViewport,
|
|
10518
10727
|
{
|
|
10519
10728
|
ref: viewportRef,
|
|
10520
10729
|
scale,
|
|
10521
|
-
onZoomChange: changeZoom,
|
|
10730
|
+
onZoomChange: zoomable ? changeZoom : void 0,
|
|
10522
10731
|
labelHeader,
|
|
10523
10732
|
toolbar: toolbar === false ? false : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10524
10733
|
toolbar,
|
|
10525
|
-
|
|
10734
|
+
legend
|
|
10526
10735
|
] }),
|
|
10527
10736
|
tabStop: false,
|
|
10528
|
-
"aria-label":
|
|
10529
|
-
className,
|
|
10530
|
-
children: /* @__PURE__ */ jsxs("div", { ref: treeRef, role: "tree", "aria-label": ariaLabel, className: "relative", onKeyDown, children: [
|
|
10737
|
+
"aria-label": regionLabel,
|
|
10738
|
+
className: legendApart ? "h-auto flex-1" : className,
|
|
10739
|
+
children: /* @__PURE__ */ jsxs("div", { ref: treeRef, role: "tree", "aria-label": ariaLabel, className: "relative", onKeyDown, onFocus: () => setFocusWithin(true), onBlur: onTreeBlur, children: [
|
|
10531
10740
|
/* @__PURE__ */ jsx("span", { ref: probeRef, "aria-hidden": "true", className: "pointer-events-none invisible absolute whitespace-nowrap text-xs font-medium", children: "0" }),
|
|
10532
10741
|
/* @__PURE__ */ jsx(GanttArrows, { arrows, width: scale.width, height: rows.length * ROW_HEIGHT2 }),
|
|
10533
10742
|
rows.map((row) => /* @__PURE__ */ jsx(
|
|
10534
10743
|
TimeRow,
|
|
10535
10744
|
{
|
|
10536
10745
|
"data-row-key": row.key,
|
|
10746
|
+
height: ROW_HEIGHT2,
|
|
10537
10747
|
label: label(row),
|
|
10538
10748
|
className: "cursor-pointer",
|
|
10539
10749
|
labelClassName: cn(
|
|
@@ -10541,13 +10751,18 @@ function Gantt({
|
|
|
10541
10751
|
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
10752
|
),
|
|
10543
10753
|
onClick: () => onRowClick(row),
|
|
10544
|
-
children: row.group ? renderGroup(row,
|
|
10754
|
+
children: row.group ? renderGroup(row, row.group) : renderItem(row, row.item)
|
|
10545
10755
|
},
|
|
10546
10756
|
row.key
|
|
10547
10757
|
))
|
|
10548
10758
|
] })
|
|
10549
10759
|
}
|
|
10550
10760
|
);
|
|
10761
|
+
if (!legendApart) return chart;
|
|
10762
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 w-full min-w-0 flex-col", className), children: [
|
|
10763
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 px-ds-2 py-ds-1.5", children: legend }),
|
|
10764
|
+
chart
|
|
10765
|
+
] });
|
|
10551
10766
|
}
|
|
10552
10767
|
var DEFAULT_OFFSET2 = "var(--ds-space-4)";
|
|
10553
10768
|
var LAUNCHER_SIZES = {
|
|
@@ -13053,6 +13268,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13053
13268
|
className,
|
|
13054
13269
|
renderHeader
|
|
13055
13270
|
}, ref) {
|
|
13271
|
+
if (REACT_VERSION_PROBLEM) throw new Error(REACT_VERSION_PROBLEM);
|
|
13056
13272
|
const shell = useAppShell();
|
|
13057
13273
|
const rootRef = useRef(null);
|
|
13058
13274
|
const setRoot = useCallback((node) => {
|
|
@@ -16028,7 +16244,9 @@ function Toast({ variant = "default", message, visible, onDismiss, duration = 5e
|
|
|
16028
16244
|
var ToastContext = createContext(null);
|
|
16029
16245
|
function useToast() {
|
|
16030
16246
|
const ctx = useContext(ToastContext);
|
|
16031
|
-
if (!ctx)
|
|
16247
|
+
if (!ctx) {
|
|
16248
|
+
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.");
|
|
16249
|
+
}
|
|
16032
16250
|
return ctx;
|
|
16033
16251
|
}
|
|
16034
16252
|
function useToastOptional() {
|