@zendir/ui 0.1.14 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/react/astro/SimulationControls.js +3 -3
- package/dist/react/astro/SimulationControls.js.map +1 -1
- package/dist/react/astro/UnifiedTimeline.d.ts +70 -8
- package/dist/react/astro/UnifiedTimeline.js +886 -260
- package/dist/react/astro/UnifiedTimeline.js.map +1 -1
- package/dist/react/astro/index.d.ts +2 -1
- package/dist/react/charts/GroundTrackMap.d.ts +40 -1
- package/dist/react/charts/GroundTrackMap.js +98 -47
- package/dist/react/charts/GroundTrackMap.js.map +1 -1
- package/dist/react/charts/GroundTrackMapLeaflet.d.ts +11 -2
- package/dist/react/charts/GroundTrackMapLeaflet.js +128 -15
- package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
- package/dist/react/charts/index.d.ts +1 -1
- package/dist/react/charts/unified/theme.d.ts +7 -7
- package/dist/react/context/CategoryContext.d.ts +51 -0
- package/dist/react/context/CategoryContext.js +36 -0
- package/dist/react/context/CategoryContext.js.map +1 -0
- package/dist/react/context/index.d.ts +2 -0
- package/dist/react/index.d.ts +6 -4
- package/dist/react/types.d.ts +26 -0
- package/dist/react/types.js.map +1 -1
- package/dist/react/utils/categoryPalette.d.ts +43 -0
- package/dist/react/utils/categoryPalette.js +104 -0
- package/dist/react/utils/categoryPalette.js.map +1 -0
- package/dist/react/utils/index.d.ts +1 -0
- package/dist/react/utils/index.js.map +1 -1
- package/dist/react.js +6 -0
- package/dist/react.js.map +1 -1
- package/dist/style.css +49 -0
- package/package.json +1 -1
|
@@ -1,10 +1,140 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useState, useCallback, useMemo, useRef } from "react";
|
|
3
3
|
import { classNames, safeAccentText } from "../utils/index.js";
|
|
4
|
+
import { useCategoryPalette } from "../context/CategoryContext.js";
|
|
4
5
|
import { Icon } from "../core/Icon.js";
|
|
5
6
|
import { Badge } from "../core/Badge.js";
|
|
6
7
|
import { Tooltip } from "../core/Tooltip.js";
|
|
8
|
+
import { Button } from "../core/Button.js";
|
|
9
|
+
import { useBreakpoint } from "../core/layout/useBreakpoint.js";
|
|
7
10
|
import { useTheme } from "../theme/ThemeProvider.js";
|
|
11
|
+
const Z = {
|
|
12
|
+
/** Base layer for track events / scatter dots */
|
|
13
|
+
trackEvent: 1,
|
|
14
|
+
/** Hovered track event raised above siblings */
|
|
15
|
+
trackEventHovered: 20,
|
|
16
|
+
/** Sticky column elements (playhead, track labels) */
|
|
17
|
+
sticky: 15,
|
|
18
|
+
/** Floating day-marker lines above track content */
|
|
19
|
+
dayMarker: 5,
|
|
20
|
+
/** Loading overlay covering chart content */
|
|
21
|
+
loadingOverlay: 100,
|
|
22
|
+
/** Floating tooltips — above all chart chrome */
|
|
23
|
+
tooltip: 1e3
|
|
24
|
+
};
|
|
25
|
+
const TIMELINE_FILTER_TEAM_NONE = "__zendir_team_none__";
|
|
26
|
+
const TIMELINE_FILTER_TEAM_LEGACY = "__zendir_team_legacy__";
|
|
27
|
+
function getTimelineTeamAccent(event) {
|
|
28
|
+
const t = event.team;
|
|
29
|
+
if (t == null ? void 0 : t.color) {
|
|
30
|
+
return { color: t.color, id: t.id, label: t.label };
|
|
31
|
+
}
|
|
32
|
+
if (event.color) {
|
|
33
|
+
return { color: event.color };
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function getTimelineTeamDisplayLabel(event, accent) {
|
|
38
|
+
if (accent.label) return accent.label;
|
|
39
|
+
if (accent.id !== void 0 && accent.id !== "") return String(accent.id);
|
|
40
|
+
const args = event.arguments;
|
|
41
|
+
const argsTeam = args == null ? void 0 : args.Team;
|
|
42
|
+
if (argsTeam !== void 0 && argsTeam !== "") return String(argsTeam);
|
|
43
|
+
return event.badge || "Team";
|
|
44
|
+
}
|
|
45
|
+
function getTimelineTeamFilterKey(event) {
|
|
46
|
+
const accent = getTimelineTeamAccent(event);
|
|
47
|
+
if (!accent) return TIMELINE_FILTER_TEAM_NONE;
|
|
48
|
+
if (accent.id === void 0 || accent.id === "") return TIMELINE_FILTER_TEAM_LEGACY;
|
|
49
|
+
return String(accent.id);
|
|
50
|
+
}
|
|
51
|
+
const ALL_TIMELINE_STATUSES = [
|
|
52
|
+
"off",
|
|
53
|
+
"standby",
|
|
54
|
+
"normal",
|
|
55
|
+
"caution",
|
|
56
|
+
"serious",
|
|
57
|
+
"critical"
|
|
58
|
+
];
|
|
59
|
+
function getTimelineEventDisplayStatus(event) {
|
|
60
|
+
if (event.badgeVariant && event.badgeVariant !== "default" && event.badgeVariant !== "primary") {
|
|
61
|
+
return event.badgeVariant;
|
|
62
|
+
}
|
|
63
|
+
return event.status ?? "normal";
|
|
64
|
+
}
|
|
65
|
+
function isTimelineFilterActive(filter) {
|
|
66
|
+
return Boolean(
|
|
67
|
+
filter.search && filter.search.trim() || filter.tracks && filter.tracks.length > 0 || filter.status && filter.status.length > 0 || filter.eventShape && filter.eventShape !== "all" || filter.teams && filter.teams.length > 0 || filter.teamColoredOnly
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
function normalizeTimelineFilter(f) {
|
|
71
|
+
var _a, _b, _c, _d;
|
|
72
|
+
const o = {};
|
|
73
|
+
const s = (_a = f.search) == null ? void 0 : _a.trim();
|
|
74
|
+
if (s) o.search = s;
|
|
75
|
+
if ((_b = f.tracks) == null ? void 0 : _b.length) o.tracks = [...f.tracks];
|
|
76
|
+
if ((_c = f.status) == null ? void 0 : _c.length) o.status = [...f.status];
|
|
77
|
+
if (f.eventShape && f.eventShape !== "all") o.eventShape = f.eventShape;
|
|
78
|
+
if ((_d = f.teams) == null ? void 0 : _d.length) o.teams = [...f.teams];
|
|
79
|
+
if (f.teamColoredOnly) o.teamColoredOnly = true;
|
|
80
|
+
return o;
|
|
81
|
+
}
|
|
82
|
+
function matchesTimelineFilter(event, filter) {
|
|
83
|
+
var _a, _b, _c, _d, _e, _f;
|
|
84
|
+
if (!isTimelineFilterActive(filter)) return true;
|
|
85
|
+
if ((_a = filter.tracks) == null ? void 0 : _a.length) {
|
|
86
|
+
const tid = event.track ?? "default";
|
|
87
|
+
if (!filter.tracks.includes(tid)) return false;
|
|
88
|
+
}
|
|
89
|
+
if ((_b = filter.status) == null ? void 0 : _b.length) {
|
|
90
|
+
const ds = getTimelineEventDisplayStatus(event);
|
|
91
|
+
if (!filter.status.includes(ds)) return false;
|
|
92
|
+
}
|
|
93
|
+
const q = (_c = filter.search) == null ? void 0 : _c.trim().toLowerCase();
|
|
94
|
+
if (q) {
|
|
95
|
+
const argStr = event.arguments ? Object.values(event.arguments).map((v) => String(v)).join(" ") : "";
|
|
96
|
+
const accent = getTimelineTeamAccent(event);
|
|
97
|
+
const teamHay = accent ? [accent.label, accent.id !== void 0 ? String(accent.id) : ""].filter(Boolean).join(" ") : "";
|
|
98
|
+
const hay = [
|
|
99
|
+
event.title,
|
|
100
|
+
event.subtitle,
|
|
101
|
+
event.badge,
|
|
102
|
+
event.track,
|
|
103
|
+
argStr,
|
|
104
|
+
teamHay
|
|
105
|
+
].filter(Boolean).join(" ").toLowerCase();
|
|
106
|
+
if (!hay.includes(q)) return false;
|
|
107
|
+
}
|
|
108
|
+
if (filter.eventShape === "point") {
|
|
109
|
+
const endT = (_d = event.end) == null ? void 0 : _d.getTime();
|
|
110
|
+
const st = event.start.getTime();
|
|
111
|
+
if (endT != null && endT > st) return false;
|
|
112
|
+
}
|
|
113
|
+
if (filter.eventShape === "range") {
|
|
114
|
+
const endT = (_e = event.end) == null ? void 0 : _e.getTime();
|
|
115
|
+
const st = event.start.getTime();
|
|
116
|
+
if (endT == null || endT <= st) return false;
|
|
117
|
+
}
|
|
118
|
+
if ((_f = filter.teams) == null ? void 0 : _f.length) {
|
|
119
|
+
const teamKey = getTimelineTeamFilterKey(event);
|
|
120
|
+
if (!filter.teams.includes(teamKey)) return false;
|
|
121
|
+
}
|
|
122
|
+
if (filter.teamColoredOnly && !(filter.teams && filter.teams.length > 0) && !getTimelineTeamAccent(event)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
function countTimelineFilterChips(filter) {
|
|
128
|
+
var _a, _b, _c;
|
|
129
|
+
let n = 0;
|
|
130
|
+
if ((_a = filter.search) == null ? void 0 : _a.trim()) n++;
|
|
131
|
+
if ((_b = filter.tracks) == null ? void 0 : _b.length) n++;
|
|
132
|
+
if ((_c = filter.status) == null ? void 0 : _c.length) n++;
|
|
133
|
+
if (filter.eventShape && filter.eventShape !== "all") n++;
|
|
134
|
+
if (filter.teams && filter.teams.length > 0) n++;
|
|
135
|
+
if (filter.teamColoredOnly && !(filter.teams && filter.teams.length > 0)) n++;
|
|
136
|
+
return n;
|
|
137
|
+
}
|
|
8
138
|
function TimelineStatusMarker({
|
|
9
139
|
status,
|
|
10
140
|
fillColor,
|
|
@@ -44,6 +174,7 @@ const EventListItem = memo(function EventListItem2({
|
|
|
44
174
|
];
|
|
45
175
|
const displayStatus = event.badgeVariant && event.badgeVariant !== "default" && event.badgeVariant !== "primary" ? event.badgeVariant : event.status ?? "normal";
|
|
46
176
|
const markerColor = tokens.colors.status[displayStatus];
|
|
177
|
+
const teamAccent = getTimelineTeamAccent(event);
|
|
47
178
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "16px" }, children: [
|
|
48
179
|
/* @__PURE__ */ jsxs(
|
|
49
180
|
"div",
|
|
@@ -81,7 +212,7 @@ const EventListItem = memo(function EventListItem2({
|
|
|
81
212
|
position: "relative",
|
|
82
213
|
flex: 1,
|
|
83
214
|
marginBottom: "16px",
|
|
84
|
-
padding:
|
|
215
|
+
padding: teamAccent ? "19px 20px 16px 20px" : "16px 20px",
|
|
85
216
|
backgroundColor: tokens.colors.background.surface,
|
|
86
217
|
border: `1px solid ${hovered ? tokens.colors.accent.primary : tokens.colors.border.muted}`,
|
|
87
218
|
borderRadius: tokens.borderRadius.lg,
|
|
@@ -91,7 +222,7 @@ const EventListItem = memo(function EventListItem2({
|
|
|
91
222
|
boxShadow: hovered ? `0 4px 20px ${tokens.colors.accent.primary}15, 0 0 0 1px ${tokens.colors.accent.primary}20` : "none"
|
|
92
223
|
},
|
|
93
224
|
children: [
|
|
94
|
-
|
|
225
|
+
teamAccent && /* @__PURE__ */ jsx(
|
|
95
226
|
"div",
|
|
96
227
|
{
|
|
97
228
|
style: {
|
|
@@ -100,7 +231,7 @@ const EventListItem = memo(function EventListItem2({
|
|
|
100
231
|
left: 0,
|
|
101
232
|
right: 0,
|
|
102
233
|
height: 3,
|
|
103
|
-
backgroundColor:
|
|
234
|
+
backgroundColor: teamAccent.color
|
|
104
235
|
}
|
|
105
236
|
}
|
|
106
237
|
),
|
|
@@ -313,6 +444,7 @@ const ChartView = memo(function ChartView2({
|
|
|
313
444
|
const [hoveredEvent, setHoveredEvent] = useState(null);
|
|
314
445
|
const [tooltipPos, setTooltipPos] = useState(null);
|
|
315
446
|
const scrollContainerRef = useRef(null);
|
|
447
|
+
const [scrollX, setScrollX] = useState(0);
|
|
316
448
|
const totalDuration = end.getTime() - start.getTime();
|
|
317
449
|
const trackLabelWidth = 130;
|
|
318
450
|
const timeLabels = useMemo(() => {
|
|
@@ -416,6 +548,22 @@ const ChartView = memo(function ChartView2({
|
|
|
416
548
|
if (!status) return tokens.colors.accent.primary;
|
|
417
549
|
return tokens.colors.status[status] || tokens.colors.accent.primary;
|
|
418
550
|
};
|
|
551
|
+
const isEventVisible = useCallback(
|
|
552
|
+
(event) => {
|
|
553
|
+
const container = scrollContainerRef.current;
|
|
554
|
+
if (!container) return true;
|
|
555
|
+
const viewportWidth = container.clientWidth - trackLabelWidth;
|
|
556
|
+
if (viewportWidth <= 0) return true;
|
|
557
|
+
const totalWidth = container.scrollWidth - trackLabelWidth;
|
|
558
|
+
const eventStartMs = event.start.getTime();
|
|
559
|
+
const eventEndMs = (event.end ?? new Date(eventStartMs + 3e5)).getTime();
|
|
560
|
+
const leftPx = (eventStartMs - start.getTime()) / totalDuration * totalWidth;
|
|
561
|
+
const rightPx = (eventEndMs - start.getTime()) / totalDuration * totalWidth;
|
|
562
|
+
const overscan = 50;
|
|
563
|
+
return rightPx >= scrollX - overscan && leftPx <= scrollX + viewportWidth + overscan;
|
|
564
|
+
},
|
|
565
|
+
[start, totalDuration, scrollX, trackLabelWidth]
|
|
566
|
+
);
|
|
419
567
|
const getStatusLabel = (status) => {
|
|
420
568
|
const labels = {
|
|
421
569
|
normal: "Normal",
|
|
@@ -437,6 +585,7 @@ const ChartView = memo(function ChartView2({
|
|
|
437
585
|
{
|
|
438
586
|
ref: scrollContainerRef,
|
|
439
587
|
className: "zendir-timeline-scroll",
|
|
588
|
+
onScroll: (e) => setScrollX(e.currentTarget.scrollLeft),
|
|
440
589
|
style: {
|
|
441
590
|
overflowX: "auto",
|
|
442
591
|
overflowY: "hidden",
|
|
@@ -460,7 +609,7 @@ const ChartView = memo(function ChartView2({
|
|
|
460
609
|
borderBottom: `1px solid ${tokens.colors.accent.primary}20`,
|
|
461
610
|
position: "sticky",
|
|
462
611
|
top: 0,
|
|
463
|
-
zIndex:
|
|
612
|
+
zIndex: Z.trackEventHovered,
|
|
464
613
|
backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
|
|
465
614
|
...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" }
|
|
466
615
|
},
|
|
@@ -473,7 +622,7 @@ const ChartView = memo(function ChartView2({
|
|
|
473
622
|
flexShrink: 0,
|
|
474
623
|
position: "sticky",
|
|
475
624
|
left: 0,
|
|
476
|
-
zIndex:
|
|
625
|
+
zIndex: Z.trackEventHovered + 5,
|
|
477
626
|
backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
|
|
478
627
|
...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
|
|
479
628
|
borderRight: `1px solid ${tokens.colors.border.muted}30`,
|
|
@@ -502,7 +651,7 @@ const ChartView = memo(function ChartView2({
|
|
|
502
651
|
display: "flex",
|
|
503
652
|
flexDirection: "column",
|
|
504
653
|
alignItems: "center",
|
|
505
|
-
zIndex:
|
|
654
|
+
zIndex: Z.dayMarker
|
|
506
655
|
},
|
|
507
656
|
children: /* @__PURE__ */ jsx(
|
|
508
657
|
"span",
|
|
@@ -562,7 +711,7 @@ const ChartView = memo(function ChartView2({
|
|
|
562
711
|
flexShrink: 0,
|
|
563
712
|
position: "sticky",
|
|
564
713
|
left: 0,
|
|
565
|
-
zIndex:
|
|
714
|
+
zIndex: Z.sticky,
|
|
566
715
|
display: "flex",
|
|
567
716
|
alignItems: "center",
|
|
568
717
|
paddingLeft: 12,
|
|
@@ -599,25 +748,28 @@ const ChartView = memo(function ChartView2({
|
|
|
599
748
|
bottom: 0,
|
|
600
749
|
width: 1,
|
|
601
750
|
backgroundColor: `${tokens.colors.status.caution}25`,
|
|
602
|
-
zIndex:
|
|
751
|
+
zIndex: Z.trackEvent,
|
|
603
752
|
pointerEvents: "none"
|
|
604
753
|
}
|
|
605
754
|
},
|
|
606
755
|
`day-line-${index}`
|
|
607
756
|
)),
|
|
608
|
-
(eventsByTrack[track.id] || []).map((event) => {
|
|
757
|
+
(eventsByTrack[track.id] || []).filter(isEventVisible).map((event) => {
|
|
609
758
|
const { left, width } = getEventPosition(event);
|
|
610
|
-
const
|
|
759
|
+
const displayStatus = event.badgeVariant && event.badgeVariant !== "default" && event.badgeVariant !== "primary" ? event.badgeVariant : event.status ?? "normal";
|
|
760
|
+
const color = getStatusColor(displayStatus);
|
|
611
761
|
const isHovered = hoveredEvent === event.id;
|
|
612
762
|
const overlap = eventOverlaps[event.id];
|
|
613
763
|
const hasOverlap = overlap && overlap.overlapCount > 0;
|
|
614
|
-
const
|
|
764
|
+
const teamAccent = getTimelineTeamAccent(event);
|
|
765
|
+
const cardHeight = hasOverlap ? 30 : 38;
|
|
615
766
|
const stackOffset = overlap ? overlap.stackIndex * 30 : 0;
|
|
616
767
|
const baseTop = ((track.height || trackHeight) - cardHeight) / 2;
|
|
617
768
|
return /* @__PURE__ */ jsxs(
|
|
618
769
|
"button",
|
|
619
770
|
{
|
|
620
771
|
type: "button",
|
|
772
|
+
"aria-label": `${event.title}${event.status ? `, status: ${event.status}` : ""}`,
|
|
621
773
|
onClick: () => onEventClick == null ? void 0 : onEventClick(event),
|
|
622
774
|
onMouseEnter: (e) => {
|
|
623
775
|
setHoveredEvent(event.id);
|
|
@@ -628,6 +780,15 @@ const ChartView = memo(function ChartView2({
|
|
|
628
780
|
setHoveredEvent(null);
|
|
629
781
|
setTooltipPos(null);
|
|
630
782
|
},
|
|
783
|
+
onFocus: (e) => {
|
|
784
|
+
setHoveredEvent(event.id);
|
|
785
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
786
|
+
setTooltipPos({ x: rect.left + rect.width / 2, y: rect.top - 8 });
|
|
787
|
+
},
|
|
788
|
+
onBlur: () => {
|
|
789
|
+
setHoveredEvent(null);
|
|
790
|
+
setTooltipPos(null);
|
|
791
|
+
},
|
|
631
792
|
className: "zendir-timeline-region",
|
|
632
793
|
style: {
|
|
633
794
|
position: "absolute",
|
|
@@ -643,13 +804,13 @@ const ChartView = memo(function ChartView2({
|
|
|
643
804
|
display: "flex",
|
|
644
805
|
alignItems: "center",
|
|
645
806
|
overflow: "hidden",
|
|
646
|
-
zIndex: isHovered ?
|
|
807
|
+
zIndex: isHovered ? Z.trackEventHovered : Z.trackEvent,
|
|
647
808
|
boxShadow: isHovered ? `0 8px 24px rgba(0, 0, 0, 0.5), 0 0 0 1px ${color}60` : "0 2px 6px rgba(0, 0, 0, 0.25)",
|
|
648
809
|
transition: "all 150ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
649
810
|
transform: isHovered ? "translateY(-3px) scale(1.02)" : "none"
|
|
650
811
|
},
|
|
651
812
|
children: [
|
|
652
|
-
|
|
813
|
+
teamAccent ? /* @__PURE__ */ jsx(
|
|
653
814
|
"div",
|
|
654
815
|
{
|
|
655
816
|
style: {
|
|
@@ -657,57 +818,63 @@ const ChartView = memo(function ChartView2({
|
|
|
657
818
|
top: 0,
|
|
658
819
|
left: 0,
|
|
659
820
|
right: 0,
|
|
660
|
-
height:
|
|
661
|
-
backgroundColor:
|
|
662
|
-
borderRadius: "4px 4px 0 0"
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
"div",
|
|
668
|
-
{
|
|
669
|
-
style: {
|
|
670
|
-
width: 4,
|
|
671
|
-
height: "100%",
|
|
672
|
-
backgroundColor: color,
|
|
673
|
-
flexShrink: 0,
|
|
674
|
-
borderRadius: "2px 0 0 2px"
|
|
675
|
-
}
|
|
821
|
+
height: 2,
|
|
822
|
+
backgroundColor: teamAccent.color,
|
|
823
|
+
borderRadius: "4px 4px 0 0",
|
|
824
|
+
zIndex: 1,
|
|
825
|
+
pointerEvents: "none"
|
|
826
|
+
},
|
|
827
|
+
"aria-hidden": true
|
|
676
828
|
}
|
|
677
|
-
),
|
|
829
|
+
) : null,
|
|
678
830
|
/* @__PURE__ */ jsxs(
|
|
679
831
|
"div",
|
|
680
832
|
{
|
|
681
833
|
style: {
|
|
682
834
|
flex: 1,
|
|
683
|
-
padding:
|
|
835
|
+
padding: `${teamAccent ? 6 : 4}px 8px 4px 8px`,
|
|
684
836
|
overflow: "hidden",
|
|
685
|
-
minWidth: 0
|
|
837
|
+
minWidth: 0,
|
|
838
|
+
display: "flex",
|
|
839
|
+
flexDirection: "column",
|
|
840
|
+
justifyContent: "center"
|
|
686
841
|
},
|
|
687
842
|
children: [
|
|
688
|
-
/* @__PURE__ */
|
|
843
|
+
/* @__PURE__ */ jsxs(
|
|
689
844
|
"div",
|
|
690
845
|
{
|
|
691
846
|
style: {
|
|
692
847
|
display: "flex",
|
|
693
848
|
alignItems: "center",
|
|
694
|
-
gap:
|
|
849
|
+
gap: 6,
|
|
850
|
+
minWidth: 0
|
|
695
851
|
},
|
|
696
|
-
children:
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
852
|
+
children: [
|
|
853
|
+
/* @__PURE__ */ jsx(
|
|
854
|
+
TimelineStatusMarker,
|
|
855
|
+
{
|
|
856
|
+
status: displayStatus,
|
|
857
|
+
fillColor: color,
|
|
858
|
+
size: hasOverlap ? 8 : 10
|
|
859
|
+
}
|
|
860
|
+
),
|
|
861
|
+
/* @__PURE__ */ jsx(
|
|
862
|
+
"span",
|
|
863
|
+
{
|
|
864
|
+
style: {
|
|
865
|
+
fontSize: "0.6875rem",
|
|
866
|
+
fontWeight: 500,
|
|
867
|
+
// AstroUXDS medium (was 600)
|
|
868
|
+
color: "#fff",
|
|
869
|
+
whiteSpace: "nowrap",
|
|
870
|
+
overflow: "hidden",
|
|
871
|
+
textOverflow: "ellipsis",
|
|
872
|
+
minWidth: 0
|
|
873
|
+
},
|
|
874
|
+
children: event.title
|
|
875
|
+
}
|
|
876
|
+
)
|
|
877
|
+
]
|
|
711
878
|
}
|
|
712
879
|
),
|
|
713
880
|
event.subtitle && !hasOverlap && /* @__PURE__ */ jsx(
|
|
@@ -719,7 +886,8 @@ const ChartView = memo(function ChartView2({
|
|
|
719
886
|
whiteSpace: "nowrap",
|
|
720
887
|
overflow: "hidden",
|
|
721
888
|
textOverflow: "ellipsis",
|
|
722
|
-
marginTop: 1
|
|
889
|
+
marginTop: 1,
|
|
890
|
+
paddingLeft: 16
|
|
723
891
|
},
|
|
724
892
|
children: event.subtitle
|
|
725
893
|
}
|
|
@@ -745,7 +913,7 @@ const ChartView = memo(function ChartView2({
|
|
|
745
913
|
fontWeight: 700,
|
|
746
914
|
color: "#000",
|
|
747
915
|
boxShadow: "0 2px 6px rgba(0, 0, 0, 0.3)",
|
|
748
|
-
zIndex:
|
|
916
|
+
zIndex: Z.sticky - 5
|
|
749
917
|
},
|
|
750
918
|
title: `${overlap.overlapCount + 1} overlapping events`,
|
|
751
919
|
children: [
|
|
@@ -777,7 +945,7 @@ const ChartView = memo(function ChartView2({
|
|
|
777
945
|
width: 2,
|
|
778
946
|
backgroundColor: tokens.colors.accent.primary,
|
|
779
947
|
boxShadow: `0 0 12px ${tokens.colors.accent.primary}`,
|
|
780
|
-
zIndex:
|
|
948
|
+
zIndex: Z.trackEventHovered,
|
|
781
949
|
pointerEvents: "none"
|
|
782
950
|
},
|
|
783
951
|
children: [
|
|
@@ -828,8 +996,8 @@ const ChartView = memo(function ChartView2({
|
|
|
828
996
|
}
|
|
829
997
|
),
|
|
830
998
|
hoveredEventData && tooltipPos && (() => {
|
|
831
|
-
var _a;
|
|
832
999
|
const tooltipColor = getStatusColor(hoveredEventData.status);
|
|
1000
|
+
const teamTip = getTimelineTeamAccent(hoveredEventData);
|
|
833
1001
|
return /* @__PURE__ */ jsxs(
|
|
834
1002
|
"div",
|
|
835
1003
|
{
|
|
@@ -838,7 +1006,7 @@ const ChartView = memo(function ChartView2({
|
|
|
838
1006
|
left: tooltipPos.x,
|
|
839
1007
|
top: tooltipPos.y,
|
|
840
1008
|
transform: "translate(-50%, -100%)",
|
|
841
|
-
zIndex:
|
|
1009
|
+
zIndex: Z.tooltip,
|
|
842
1010
|
pointerEvents: "none",
|
|
843
1011
|
animation: "zendir-tooltip-appear 150ms ease"
|
|
844
1012
|
},
|
|
@@ -897,9 +1065,9 @@ const ChartView = memo(function ChartView2({
|
|
|
897
1065
|
}
|
|
898
1066
|
)
|
|
899
1067
|
] }),
|
|
900
|
-
|
|
901
|
-
/* @__PURE__ */ jsx("div", { style: { width: 8, height: 8, borderRadius: 2, backgroundColor:
|
|
902
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color:
|
|
1068
|
+
teamTip && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 6 }, children: [
|
|
1069
|
+
/* @__PURE__ */ jsx("div", { style: { width: 8, height: 8, borderRadius: 2, backgroundColor: teamTip.color, flexShrink: 0 } }),
|
|
1070
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color: teamTip.color, fontWeight: 500 }, children: getTimelineTeamDisplayLabel(hoveredEventData, teamTip) })
|
|
903
1071
|
] }),
|
|
904
1072
|
/* @__PURE__ */ jsx(
|
|
905
1073
|
"div",
|
|
@@ -1180,11 +1348,14 @@ const ScatterView = memo(function ScatterView2({
|
|
|
1180
1348
|
const color = getStatusColor(event.status);
|
|
1181
1349
|
const isHovered = hoveredEvent === event.id;
|
|
1182
1350
|
const dotSize = isHovered ? 16 : 12;
|
|
1351
|
+
const hitboxPad = Math.max(0, (24 - dotSize) / 2);
|
|
1183
1352
|
const effectiveStatus = event.status ?? "normal";
|
|
1353
|
+
const scatterTeamAccent = getTimelineTeamAccent(event);
|
|
1184
1354
|
return /* @__PURE__ */ jsx(
|
|
1185
1355
|
"button",
|
|
1186
1356
|
{
|
|
1187
1357
|
type: "button",
|
|
1358
|
+
"aria-label": `${event.title}${event.status ? `, status: ${event.status}` : ""}`,
|
|
1188
1359
|
onClick: () => onEventClick == null ? void 0 : onEventClick(event),
|
|
1189
1360
|
onMouseEnter: (e) => {
|
|
1190
1361
|
setHoveredEvent(event.id);
|
|
@@ -1195,23 +1366,33 @@ const ScatterView = memo(function ScatterView2({
|
|
|
1195
1366
|
setHoveredEvent(null);
|
|
1196
1367
|
setTooltipPosition(null);
|
|
1197
1368
|
},
|
|
1369
|
+
onFocus: (e) => {
|
|
1370
|
+
setHoveredEvent(event.id);
|
|
1371
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
1372
|
+
setTooltipPosition({ x: rect.left + rect.width / 2, y: rect.top });
|
|
1373
|
+
},
|
|
1374
|
+
onBlur: () => {
|
|
1375
|
+
setHoveredEvent(null);
|
|
1376
|
+
setTooltipPosition(null);
|
|
1377
|
+
},
|
|
1198
1378
|
style: {
|
|
1199
1379
|
position: "absolute",
|
|
1200
1380
|
left: `${leftPercent}%`,
|
|
1201
1381
|
transform: "translateX(-50%)",
|
|
1382
|
+
/* visible size + transparent padding = ≥24px touch/click target */
|
|
1202
1383
|
width: dotSize,
|
|
1203
1384
|
height: dotSize,
|
|
1204
|
-
padding:
|
|
1385
|
+
padding: hitboxPad,
|
|
1205
1386
|
background: "none",
|
|
1206
1387
|
border: "none",
|
|
1207
1388
|
cursor: "pointer",
|
|
1208
1389
|
transition: "all 200ms cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
1209
|
-
zIndex: isHovered ?
|
|
1390
|
+
zIndex: isHovered ? Z.trackEventHovered : Z.trackEvent,
|
|
1210
1391
|
lineHeight: 0,
|
|
1211
1392
|
borderRadius: "50%",
|
|
1212
|
-
|
|
1393
|
+
boxSizing: "content-box",
|
|
1394
|
+
boxShadow: scatterTeamAccent ? `0 0 0 2px ${scatterTeamAccent.color}` : void 0
|
|
1213
1395
|
},
|
|
1214
|
-
"aria-label": event.title,
|
|
1215
1396
|
children: /* @__PURE__ */ jsx(TimelineStatusMarker, { status: effectiveStatus, fillColor: color, size: dotSize })
|
|
1216
1397
|
},
|
|
1217
1398
|
event.id
|
|
@@ -1228,8 +1409,8 @@ const ScatterView = memo(function ScatterView2({
|
|
|
1228
1409
|
}
|
|
1229
1410
|
),
|
|
1230
1411
|
hoveredEventData && tooltipPosition && (() => {
|
|
1231
|
-
var _a;
|
|
1232
1412
|
const scatterTipColor = getStatusColor(hoveredEventData.status);
|
|
1413
|
+
const scatterTeamTip = getTimelineTeamAccent(hoveredEventData);
|
|
1233
1414
|
return /* @__PURE__ */ jsxs(
|
|
1234
1415
|
"div",
|
|
1235
1416
|
{
|
|
@@ -1245,7 +1426,7 @@ const ScatterView = memo(function ScatterView2({
|
|
|
1245
1426
|
padding: "12px 16px",
|
|
1246
1427
|
minWidth: 200,
|
|
1247
1428
|
maxWidth: 320,
|
|
1248
|
-
zIndex:
|
|
1429
|
+
zIndex: Z.tooltip,
|
|
1249
1430
|
boxShadow: `0 12px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px ${scatterTipColor}20`,
|
|
1250
1431
|
backdropFilter: "blur(12px)",
|
|
1251
1432
|
animation: "zendir-tooltip-in 150ms cubic-bezier(0.34, 1.56, 0.64, 1)"
|
|
@@ -1305,9 +1486,9 @@ const ScatterView = memo(function ScatterView2({
|
|
|
1305
1486
|
}
|
|
1306
1487
|
)
|
|
1307
1488
|
] }),
|
|
1308
|
-
|
|
1309
|
-
/* @__PURE__ */ jsx("div", { style: { width: 8, height: 8, borderRadius: 2, backgroundColor:
|
|
1310
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color:
|
|
1489
|
+
scatterTeamTip && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 6 }, children: [
|
|
1490
|
+
/* @__PURE__ */ jsx("div", { style: { width: 8, height: 8, borderRadius: 2, backgroundColor: scatterTeamTip.color, flexShrink: 0 } }),
|
|
1491
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.6875rem", color: scatterTeamTip.color, fontWeight: 500 }, children: getTimelineTeamDisplayLabel(hoveredEventData, scatterTeamTip) })
|
|
1311
1492
|
] }),
|
|
1312
1493
|
/* @__PURE__ */ jsx(
|
|
1313
1494
|
"div",
|
|
@@ -1404,6 +1585,243 @@ const ScatterView = memo(function ScatterView2({
|
|
|
1404
1585
|
` })
|
|
1405
1586
|
] });
|
|
1406
1587
|
});
|
|
1588
|
+
function buildTeamFilterOptions(events, tokens, categoryLabel = "team") {
|
|
1589
|
+
const map = /* @__PURE__ */ new Map();
|
|
1590
|
+
for (const event of events) {
|
|
1591
|
+
const key = getTimelineTeamFilterKey(event);
|
|
1592
|
+
if (map.has(key)) continue;
|
|
1593
|
+
const accent = getTimelineTeamAccent(event);
|
|
1594
|
+
const isNone = key === TIMELINE_FILTER_TEAM_NONE;
|
|
1595
|
+
const isLegacy = key === TIMELINE_FILTER_TEAM_LEGACY;
|
|
1596
|
+
const label = isNone ? `No ${categoryLabel.toLowerCase()}` : isLegacy ? "Accent only" : accent ? getTimelineTeamDisplayLabel(event, accent) : key;
|
|
1597
|
+
const color = isNone ? "" : (accent == null ? void 0 : accent.color) ?? tokens.colors.text.tertiary;
|
|
1598
|
+
map.set(key, { key, label, color, isNoneBucket: isNone });
|
|
1599
|
+
}
|
|
1600
|
+
const list = [...map.values()];
|
|
1601
|
+
list.sort((a, b) => {
|
|
1602
|
+
if (a.isNoneBucket !== b.isNoneBucket) return a.isNoneBucket ? 1 : -1;
|
|
1603
|
+
if (a.key === TIMELINE_FILTER_TEAM_LEGACY) return b.key === TIMELINE_FILTER_TEAM_NONE ? -1 : 1;
|
|
1604
|
+
if (b.key === TIMELINE_FILTER_TEAM_LEGACY) return a.key === TIMELINE_FILTER_TEAM_NONE ? 1 : -1;
|
|
1605
|
+
return a.label.localeCompare(b.label, void 0, { sensitivity: "base" });
|
|
1606
|
+
});
|
|
1607
|
+
return list;
|
|
1608
|
+
}
|
|
1609
|
+
const TimelineFiltersPanel = memo(function TimelineFiltersPanel2({
|
|
1610
|
+
filter,
|
|
1611
|
+
onFilterChange,
|
|
1612
|
+
trackOptions,
|
|
1613
|
+
events,
|
|
1614
|
+
expanded,
|
|
1615
|
+
teamLabel
|
|
1616
|
+
}) {
|
|
1617
|
+
const { tokens, theme } = useTheme();
|
|
1618
|
+
const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
|
|
1619
|
+
const accentColor = tokens.colors.accent.primary;
|
|
1620
|
+
const teamOptions = useMemo(() => buildTeamFilterOptions(events, tokens, teamLabel), [events, tokens, teamLabel]);
|
|
1621
|
+
const patch = useCallback(
|
|
1622
|
+
(partial) => {
|
|
1623
|
+
onFilterChange(normalizeTimelineFilter({ ...filter, ...partial }));
|
|
1624
|
+
},
|
|
1625
|
+
[filter, onFilterChange]
|
|
1626
|
+
);
|
|
1627
|
+
const clearAll = useCallback(() => {
|
|
1628
|
+
onFilterChange({});
|
|
1629
|
+
}, [onFilterChange]);
|
|
1630
|
+
const toggleTrack = useCallback(
|
|
1631
|
+
(id) => {
|
|
1632
|
+
const cur = filter.tracks ?? [];
|
|
1633
|
+
const next = cur.includes(id) ? cur.filter((t) => t !== id) : [...cur, id];
|
|
1634
|
+
patch({ tracks: next.length ? next : void 0 });
|
|
1635
|
+
},
|
|
1636
|
+
[filter.tracks, patch]
|
|
1637
|
+
);
|
|
1638
|
+
const toggleStatus = useCallback(
|
|
1639
|
+
(st) => {
|
|
1640
|
+
const cur = filter.status ?? [];
|
|
1641
|
+
const next = cur.includes(st) ? cur.filter((s) => s !== st) : [...cur, st];
|
|
1642
|
+
patch({ status: next.length ? next : void 0 });
|
|
1643
|
+
},
|
|
1644
|
+
[filter.status, patch]
|
|
1645
|
+
);
|
|
1646
|
+
const toggleTeam = useCallback(
|
|
1647
|
+
(teamKey) => {
|
|
1648
|
+
const cur = filter.teams ?? [];
|
|
1649
|
+
const next = cur.includes(teamKey) ? cur.filter((k) => k !== teamKey) : [...cur, teamKey];
|
|
1650
|
+
patch({ teams: next.length ? next : void 0 });
|
|
1651
|
+
},
|
|
1652
|
+
[filter.teams, patch]
|
|
1653
|
+
);
|
|
1654
|
+
const pillStyle = useCallback(
|
|
1655
|
+
(active, tintColor) => {
|
|
1656
|
+
const c = tintColor || accentColor;
|
|
1657
|
+
return {
|
|
1658
|
+
padding: "2px 8px",
|
|
1659
|
+
borderRadius: tokens.borderRadius.md,
|
|
1660
|
+
fontSize: tokens.typography.fontSize.xs,
|
|
1661
|
+
fontWeight: 500,
|
|
1662
|
+
textTransform: "uppercase",
|
|
1663
|
+
letterSpacing: "0.06em",
|
|
1664
|
+
lineHeight: 1.4,
|
|
1665
|
+
border: `1px solid ${active ? `${c}66` : tokens.colors.border.muted}`,
|
|
1666
|
+
backgroundColor: active ? `${c}22` : "transparent",
|
|
1667
|
+
color: active ? c : tokens.colors.text.secondary,
|
|
1668
|
+
cursor: "pointer",
|
|
1669
|
+
transition: tokens.animation.fast
|
|
1670
|
+
};
|
|
1671
|
+
},
|
|
1672
|
+
[accentColor, tokens]
|
|
1673
|
+
);
|
|
1674
|
+
const sectionHeader = (text) => /* @__PURE__ */ jsx(
|
|
1675
|
+
"div",
|
|
1676
|
+
{
|
|
1677
|
+
style: {
|
|
1678
|
+
fontSize: tokens.typography.fontSize.xs,
|
|
1679
|
+
fontWeight: 700,
|
|
1680
|
+
letterSpacing: "0.06em",
|
|
1681
|
+
textTransform: "uppercase",
|
|
1682
|
+
color: tokens.colors.text.tertiary,
|
|
1683
|
+
marginBottom: 8
|
|
1684
|
+
},
|
|
1685
|
+
children: text
|
|
1686
|
+
}
|
|
1687
|
+
);
|
|
1688
|
+
if (!expanded) return null;
|
|
1689
|
+
return /* @__PURE__ */ jsxs(
|
|
1690
|
+
"div",
|
|
1691
|
+
{
|
|
1692
|
+
id: "zendir-timeline-filters-panel",
|
|
1693
|
+
style: {
|
|
1694
|
+
padding: `${tokens.spacing.smd} ${tokens.spacing.md}`,
|
|
1695
|
+
borderBottom: `1px solid ${tokens.colors.border.muted}`,
|
|
1696
|
+
backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
|
|
1697
|
+
...isTransparentTheme && { backdropFilter: "blur(8px)", WebkitBackdropFilter: "blur(8px)" },
|
|
1698
|
+
display: "flex",
|
|
1699
|
+
flexDirection: "column",
|
|
1700
|
+
gap: tokens.spacing.smd
|
|
1701
|
+
},
|
|
1702
|
+
children: [
|
|
1703
|
+
trackOptions.length > 0 ? /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Filter by track", children: [
|
|
1704
|
+
sectionHeader("Tracks"),
|
|
1705
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: tokens.spacing.xs }, children: trackOptions.map((t) => {
|
|
1706
|
+
var _a;
|
|
1707
|
+
const active = ((_a = filter.tracks) == null ? void 0 : _a.includes(t.id)) ?? false;
|
|
1708
|
+
return /* @__PURE__ */ jsx("button", { type: "button", "aria-pressed": active, onClick: () => toggleTrack(t.id), style: pillStyle(active), children: t.label }, t.id);
|
|
1709
|
+
}) })
|
|
1710
|
+
] }) : null,
|
|
1711
|
+
/* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Filter by status", children: [
|
|
1712
|
+
sectionHeader("Status"),
|
|
1713
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: tokens.spacing.xs }, children: ALL_TIMELINE_STATUSES.map((st) => {
|
|
1714
|
+
var _a;
|
|
1715
|
+
const active = ((_a = filter.status) == null ? void 0 : _a.includes(st)) ?? false;
|
|
1716
|
+
const statusColor = st ? tokens.colors.status[st] : accentColor;
|
|
1717
|
+
return /* @__PURE__ */ jsxs(
|
|
1718
|
+
"button",
|
|
1719
|
+
{
|
|
1720
|
+
type: "button",
|
|
1721
|
+
"aria-pressed": active,
|
|
1722
|
+
onClick: () => toggleStatus(st),
|
|
1723
|
+
style: {
|
|
1724
|
+
...pillStyle(active, statusColor),
|
|
1725
|
+
display: "inline-flex",
|
|
1726
|
+
alignItems: "center",
|
|
1727
|
+
gap: 6
|
|
1728
|
+
},
|
|
1729
|
+
children: [
|
|
1730
|
+
/* @__PURE__ */ jsx(
|
|
1731
|
+
"span",
|
|
1732
|
+
{
|
|
1733
|
+
style: {
|
|
1734
|
+
width: 8,
|
|
1735
|
+
height: 8,
|
|
1736
|
+
borderRadius: "50%",
|
|
1737
|
+
backgroundColor: active ? statusColor : `${statusColor}50`,
|
|
1738
|
+
flexShrink: 0,
|
|
1739
|
+
transition: tokens.animation.fast
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
),
|
|
1743
|
+
st
|
|
1744
|
+
]
|
|
1745
|
+
},
|
|
1746
|
+
st
|
|
1747
|
+
);
|
|
1748
|
+
}) })
|
|
1749
|
+
] }),
|
|
1750
|
+
/* @__PURE__ */ jsxs(
|
|
1751
|
+
"div",
|
|
1752
|
+
{
|
|
1753
|
+
style: {
|
|
1754
|
+
display: "flex",
|
|
1755
|
+
flexWrap: "wrap",
|
|
1756
|
+
gap: `${tokens.spacing.smd} ${tokens.spacing.lg}`,
|
|
1757
|
+
alignItems: "flex-start"
|
|
1758
|
+
},
|
|
1759
|
+
children: [
|
|
1760
|
+
/* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Filter by duration", style: { minWidth: 0 }, children: [
|
|
1761
|
+
sectionHeader("Duration"),
|
|
1762
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: tokens.spacing.xs }, children: ["all", "point", "range"].map((key) => {
|
|
1763
|
+
const active = (filter.eventShape ?? "all") === key;
|
|
1764
|
+
return /* @__PURE__ */ jsx("button", { type: "button", "aria-pressed": active, onClick: () => patch({ eventShape: key }), style: pillStyle(active), children: key === "all" ? "All" : key === "point" ? "Instant" : "Range" }, key);
|
|
1765
|
+
}) })
|
|
1766
|
+
] }),
|
|
1767
|
+
teamOptions.length > 0 ? /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": `Filter by ${teamLabel.toLowerCase()}`, style: { flex: 1, minWidth: 180 }, children: [
|
|
1768
|
+
sectionHeader(teamLabel),
|
|
1769
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: tokens.spacing.xs }, children: teamOptions.map((opt) => {
|
|
1770
|
+
var _a, _b, _c;
|
|
1771
|
+
const active = ((_a = filter.teams) == null ? void 0 : _a.includes(opt.key)) ?? false;
|
|
1772
|
+
return /* @__PURE__ */ jsxs(
|
|
1773
|
+
"button",
|
|
1774
|
+
{
|
|
1775
|
+
type: "button",
|
|
1776
|
+
"aria-pressed": active,
|
|
1777
|
+
onClick: () => toggleTeam(opt.key),
|
|
1778
|
+
style: {
|
|
1779
|
+
...pillStyle(active, opt.color || void 0),
|
|
1780
|
+
display: "inline-flex",
|
|
1781
|
+
alignItems: "center",
|
|
1782
|
+
gap: 6,
|
|
1783
|
+
maxWidth: "100%"
|
|
1784
|
+
},
|
|
1785
|
+
children: [
|
|
1786
|
+
opt.isNoneBucket ? /* @__PURE__ */ jsx(
|
|
1787
|
+
"span",
|
|
1788
|
+
{
|
|
1789
|
+
style: {
|
|
1790
|
+
width: 8,
|
|
1791
|
+
height: 8,
|
|
1792
|
+
borderRadius: "50%",
|
|
1793
|
+
border: `${((_c = (_b = tokens.borders) == null ? void 0 : _b.width) == null ? void 0 : _c.thick) ?? "2px"} solid ${tokens.colors.border.muted}`,
|
|
1794
|
+
flexShrink: 0,
|
|
1795
|
+
boxSizing: "border-box"
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
) : /* @__PURE__ */ jsx(
|
|
1799
|
+
"span",
|
|
1800
|
+
{
|
|
1801
|
+
style: {
|
|
1802
|
+
width: 8,
|
|
1803
|
+
height: 8,
|
|
1804
|
+
borderRadius: "50%",
|
|
1805
|
+
backgroundColor: opt.color,
|
|
1806
|
+
flexShrink: 0
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
),
|
|
1810
|
+
/* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: opt.label })
|
|
1811
|
+
]
|
|
1812
|
+
},
|
|
1813
|
+
opt.key
|
|
1814
|
+
);
|
|
1815
|
+
}) })
|
|
1816
|
+
] }) : null
|
|
1817
|
+
]
|
|
1818
|
+
}
|
|
1819
|
+
),
|
|
1820
|
+
isTimelineFilterActive(filter) ? /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ jsx(Button, { variant: "borderless", size: "small", onClick: clearAll, children: "Clear all" }) }) : null
|
|
1821
|
+
]
|
|
1822
|
+
}
|
|
1823
|
+
);
|
|
1824
|
+
});
|
|
1407
1825
|
const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
1408
1826
|
title = "Timeline",
|
|
1409
1827
|
events,
|
|
@@ -1421,7 +1839,9 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1421
1839
|
timeFormat = "absolute",
|
|
1422
1840
|
zoomable = false,
|
|
1423
1841
|
initialZoom = 1,
|
|
1424
|
-
showFilters: _showFilters =
|
|
1842
|
+
showFilters: _showFilters = true,
|
|
1843
|
+
filtersDefaultExpanded = false,
|
|
1844
|
+
hideEmptyTracksWhenFiltered = true,
|
|
1425
1845
|
filter: _filter,
|
|
1426
1846
|
onFilterChange: _onFilterChange,
|
|
1427
1847
|
showCount: _showCount = true,
|
|
@@ -1430,13 +1850,34 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1430
1850
|
showPlayhead = true,
|
|
1431
1851
|
playheadTime,
|
|
1432
1852
|
onPlayheadChange: _onPlayheadChangeTimeline,
|
|
1433
|
-
showDayMarkers = true
|
|
1853
|
+
showDayMarkers = true,
|
|
1854
|
+
teamLabel: teamLabelProp
|
|
1434
1855
|
}) {
|
|
1435
1856
|
const { tokens, theme } = useTheme();
|
|
1436
1857
|
const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
|
|
1858
|
+
const { isMobile } = useBreakpoint();
|
|
1859
|
+
const categoryCtx = useCategoryPalette();
|
|
1860
|
+
const teamLabel = teamLabelProp ?? (categoryCtx == null ? void 0 : categoryCtx.categoryLabel) ?? "Teams";
|
|
1437
1861
|
const [internalViewMode, setInternalViewMode] = useState(defaultView);
|
|
1438
1862
|
const [zoom, setZoom] = useState(initialZoom);
|
|
1439
1863
|
const [_internalFilter, _setInternalFilter] = useState({});
|
|
1864
|
+
const [filtersExpanded, setFiltersExpanded] = useState(filtersDefaultExpanded);
|
|
1865
|
+
const filter = _filter !== void 0 ? _filter : _internalFilter;
|
|
1866
|
+
const filterChipCount = _showFilters ? countTimelineFilterChips(filter) : 0;
|
|
1867
|
+
const setFilter = useCallback(
|
|
1868
|
+
(next) => {
|
|
1869
|
+
const n = normalizeTimelineFilter(next);
|
|
1870
|
+
if (_filter === void 0) _setInternalFilter(n);
|
|
1871
|
+
_onFilterChange == null ? void 0 : _onFilterChange(n);
|
|
1872
|
+
},
|
|
1873
|
+
[_filter, _onFilterChange]
|
|
1874
|
+
);
|
|
1875
|
+
const patchFilter = useCallback(
|
|
1876
|
+
(partial) => {
|
|
1877
|
+
setFilter(normalizeTimelineFilter({ ...filter, ...partial }));
|
|
1878
|
+
},
|
|
1879
|
+
[filter, setFilter]
|
|
1880
|
+
);
|
|
1440
1881
|
const viewMode = controlledViewMode ?? internalViewMode;
|
|
1441
1882
|
const handleViewModeChange = useCallback((mode) => {
|
|
1442
1883
|
setInternalViewMode(mode);
|
|
@@ -1481,9 +1922,28 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1481
1922
|
height: trackHeight
|
|
1482
1923
|
}));
|
|
1483
1924
|
}, [events, tracks, trackHeight]);
|
|
1925
|
+
const filteredEvents = useMemo(
|
|
1926
|
+
() => events.filter((e) => matchesTimelineFilter(e, filter)),
|
|
1927
|
+
[events, filter]
|
|
1928
|
+
);
|
|
1929
|
+
const effectiveTracksForViews = useMemo(() => {
|
|
1930
|
+
if (!hideEmptyTracksWhenFiltered || !isTimelineFilterActive(filter)) return effectiveTracks;
|
|
1931
|
+
const ids = new Set(filteredEvents.map((e) => e.track || "default"));
|
|
1932
|
+
return effectiveTracks.filter((t) => ids.has(t.id));
|
|
1933
|
+
}, [effectiveTracks, filteredEvents, filter, hideEmptyTracksWhenFiltered]);
|
|
1934
|
+
const trackOptionsForToolbar = useMemo(() => {
|
|
1935
|
+
if (tracks.length > 0) return tracks.map((t) => ({ id: t.id, label: t.label }));
|
|
1936
|
+
const u = /* @__PURE__ */ new Set();
|
|
1937
|
+
events.forEach((e) => {
|
|
1938
|
+
if (e.track) u.add(e.track);
|
|
1939
|
+
});
|
|
1940
|
+
if (u.size === 0) return [{ id: "default", label: "Events" }];
|
|
1941
|
+
return [...u].sort().map((id) => ({ id, label: id }));
|
|
1942
|
+
}, [events, tracks]);
|
|
1484
1943
|
const sortedEvents = useMemo(() => {
|
|
1485
|
-
return [...
|
|
1486
|
-
}, [
|
|
1944
|
+
return [...filteredEvents].sort((a, b) => b.start.getTime() - a.start.getTime());
|
|
1945
|
+
}, [filteredEvents]);
|
|
1946
|
+
const countLabel = !_showCount ? title : `${title} (${filteredEvents.length}${filteredEvents.length !== events.length ? ` / ${events.length}` : ""})`;
|
|
1487
1947
|
return /* @__PURE__ */ jsxs(
|
|
1488
1948
|
"div",
|
|
1489
1949
|
{
|
|
@@ -1501,202 +1961,323 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1501
1961
|
{
|
|
1502
1962
|
style: {
|
|
1503
1963
|
display: "flex",
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
padding:
|
|
1964
|
+
flexDirection: isMobile ? "column" : "row",
|
|
1965
|
+
alignItems: isMobile ? "stretch" : "center",
|
|
1966
|
+
padding: `${tokens.spacing.smd} ${tokens.spacing.md}`,
|
|
1967
|
+
gap: isMobile ? tokens.spacing.xs : tokens.spacing.sm,
|
|
1507
1968
|
borderBottom: `1px solid ${tokens.colors.border.muted}`
|
|
1508
1969
|
},
|
|
1509
1970
|
children: [
|
|
1510
|
-
/* @__PURE__ */ jsxs(
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
style: {
|
|
1514
|
-
margin: 0,
|
|
1515
|
-
fontSize: "1rem",
|
|
1516
|
-
fontWeight: 500,
|
|
1517
|
-
// AstroUXDS medium (was 600)
|
|
1518
|
-
color: tokens.colors.text.primary
|
|
1519
|
-
},
|
|
1520
|
-
children: [
|
|
1521
|
-
title,
|
|
1522
|
-
" (",
|
|
1523
|
-
events.length,
|
|
1524
|
-
")"
|
|
1525
|
-
]
|
|
1526
|
-
}
|
|
1527
|
-
),
|
|
1528
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
1529
|
-
zoomable && (viewMode === "chart" || viewMode === "scatter") && /* @__PURE__ */ jsxs(
|
|
1530
|
-
"div",
|
|
1971
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.sm }, children: [
|
|
1972
|
+
/* @__PURE__ */ jsx(
|
|
1973
|
+
"h3",
|
|
1531
1974
|
{
|
|
1532
1975
|
style: {
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1976
|
+
margin: 0,
|
|
1977
|
+
fontSize: "1rem",
|
|
1978
|
+
fontWeight: 500,
|
|
1979
|
+
// AstroUXDS medium
|
|
1980
|
+
color: tokens.colors.text.primary,
|
|
1981
|
+
whiteSpace: "nowrap",
|
|
1982
|
+
flexShrink: 0
|
|
1538
1983
|
},
|
|
1539
|
-
children:
|
|
1540
|
-
/* @__PURE__ */ jsx(Tooltip, { content: "Zoom out", children: /* @__PURE__ */ jsx(
|
|
1541
|
-
"button",
|
|
1542
|
-
{
|
|
1543
|
-
type: "button",
|
|
1544
|
-
"aria-label": "Zoom out",
|
|
1545
|
-
onClick: () => setZoom(Math.max(zoom - 0.5, 1)),
|
|
1546
|
-
disabled: zoom <= 1,
|
|
1547
|
-
style: {
|
|
1548
|
-
width: 28,
|
|
1549
|
-
height: 28,
|
|
1550
|
-
display: "flex",
|
|
1551
|
-
alignItems: "center",
|
|
1552
|
-
justifyContent: "center",
|
|
1553
|
-
backgroundColor: zoom <= 1 ? "transparent" : tokens.colors.background.elevated,
|
|
1554
|
-
border: `1px solid ${tokens.colors.border.muted}`,
|
|
1555
|
-
borderRadius: tokens.borderRadius.sm,
|
|
1556
|
-
color: zoom <= 1 ? tokens.colors.text.tertiary : tokens.colors.text.primary,
|
|
1557
|
-
cursor: zoom <= 1 ? "not-allowed" : "pointer",
|
|
1558
|
-
fontSize: "1rem",
|
|
1559
|
-
fontWeight: 500,
|
|
1560
|
-
// AstroUXDS medium (was 600)
|
|
1561
|
-
opacity: zoom <= 1 ? 0.5 : 1
|
|
1562
|
-
},
|
|
1563
|
-
children: "−"
|
|
1564
|
-
}
|
|
1565
|
-
) }),
|
|
1566
|
-
/* @__PURE__ */ jsxs(
|
|
1567
|
-
"span",
|
|
1568
|
-
{
|
|
1569
|
-
style: {
|
|
1570
|
-
minWidth: 40,
|
|
1571
|
-
textAlign: "center",
|
|
1572
|
-
fontSize: "0.75rem",
|
|
1573
|
-
fontFamily: tokens.typography.fontFamily.mono,
|
|
1574
|
-
color: tokens.colors.text.secondary
|
|
1575
|
-
},
|
|
1576
|
-
children: [
|
|
1577
|
-
Math.round(zoom * 100),
|
|
1578
|
-
"%"
|
|
1579
|
-
]
|
|
1580
|
-
}
|
|
1581
|
-
),
|
|
1582
|
-
/* @__PURE__ */ jsx(Tooltip, { content: "Zoom in", children: /* @__PURE__ */ jsx(
|
|
1583
|
-
"button",
|
|
1584
|
-
{
|
|
1585
|
-
type: "button",
|
|
1586
|
-
"aria-label": "Zoom in",
|
|
1587
|
-
onClick: () => setZoom(Math.min(zoom + 0.5, 4)),
|
|
1588
|
-
disabled: zoom >= 4,
|
|
1589
|
-
style: {
|
|
1590
|
-
width: 28,
|
|
1591
|
-
height: 28,
|
|
1592
|
-
display: "flex",
|
|
1593
|
-
alignItems: "center",
|
|
1594
|
-
justifyContent: "center",
|
|
1595
|
-
backgroundColor: zoom >= 4 ? "transparent" : tokens.colors.background.elevated,
|
|
1596
|
-
border: `1px solid ${tokens.colors.border.muted}`,
|
|
1597
|
-
borderRadius: tokens.borderRadius.sm,
|
|
1598
|
-
color: zoom >= 4 ? tokens.colors.text.tertiary : tokens.colors.text.primary,
|
|
1599
|
-
cursor: zoom >= 4 ? "not-allowed" : "pointer",
|
|
1600
|
-
fontSize: "1rem",
|
|
1601
|
-
fontWeight: 500,
|
|
1602
|
-
// AstroUXDS medium (was 600)
|
|
1603
|
-
opacity: zoom >= 4 ? 0.5 : 1
|
|
1604
|
-
},
|
|
1605
|
-
children: "+"
|
|
1606
|
-
}
|
|
1607
|
-
) }),
|
|
1608
|
-
/* @__PURE__ */ jsx(Tooltip, { content: "Reset zoom", children: /* @__PURE__ */ jsx(
|
|
1609
|
-
"button",
|
|
1610
|
-
{
|
|
1611
|
-
type: "button",
|
|
1612
|
-
"aria-label": "Reset zoom",
|
|
1613
|
-
onClick: () => setZoom(1),
|
|
1614
|
-
style: {
|
|
1615
|
-
height: 28,
|
|
1616
|
-
padding: "0 10px",
|
|
1617
|
-
display: "flex",
|
|
1618
|
-
alignItems: "center",
|
|
1619
|
-
justifyContent: "center",
|
|
1620
|
-
backgroundColor: tokens.colors.background.elevated,
|
|
1621
|
-
border: `1px solid ${tokens.colors.border.muted}`,
|
|
1622
|
-
borderRadius: tokens.borderRadius.sm,
|
|
1623
|
-
color: tokens.colors.text.secondary,
|
|
1624
|
-
cursor: "pointer",
|
|
1625
|
-
fontSize: "0.6875rem",
|
|
1626
|
-
fontWeight: 500
|
|
1627
|
-
},
|
|
1628
|
-
children: "FIT"
|
|
1629
|
-
}
|
|
1630
|
-
) })
|
|
1631
|
-
]
|
|
1984
|
+
children: countLabel
|
|
1632
1985
|
}
|
|
1633
1986
|
),
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
};
|
|
1652
|
-
const labels = {
|
|
1653
|
-
chart: "Gantt Chart",
|
|
1654
|
-
list: "List View",
|
|
1655
|
-
scatter: "Scatter View"
|
|
1656
|
-
};
|
|
1657
|
-
return /* @__PURE__ */ jsx(Tooltip, { content: labels[mode], children: /* @__PURE__ */ jsx(
|
|
1658
|
-
"button",
|
|
1659
|
-
{
|
|
1660
|
-
type: "button",
|
|
1661
|
-
"aria-label": labels[mode],
|
|
1662
|
-
onClick: () => handleViewModeChange(mode),
|
|
1663
|
-
style: {
|
|
1664
|
-
display: "flex",
|
|
1665
|
-
alignItems: "center",
|
|
1666
|
-
justifyContent: "center",
|
|
1667
|
-
width: "32px",
|
|
1668
|
-
height: "32px",
|
|
1669
|
-
backgroundColor: isActive ? tokens.colors.accent.primary : "transparent",
|
|
1670
|
-
border: "none",
|
|
1671
|
-
borderRadius: tokens.borderRadius.md,
|
|
1672
|
-
color: isActive ? "#ffffff" : tokens.colors.text.secondary,
|
|
1673
|
-
cursor: "pointer",
|
|
1674
|
-
transition: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1675
|
-
transform: isActive ? "scale(1)" : "scale(0.95)",
|
|
1676
|
-
boxShadow: isActive ? `0 2px 8px ${tokens.colors.accent.primary}40` : "none"
|
|
1677
|
-
},
|
|
1678
|
-
onMouseEnter: (e) => {
|
|
1679
|
-
if (!isActive) {
|
|
1680
|
-
e.currentTarget.style.backgroundColor = `${tokens.colors.accent.primary}20`;
|
|
1681
|
-
e.currentTarget.style.transform = "scale(1)";
|
|
1682
|
-
}
|
|
1683
|
-
},
|
|
1684
|
-
onMouseLeave: (e) => {
|
|
1685
|
-
if (!isActive) {
|
|
1686
|
-
e.currentTarget.style.backgroundColor = "transparent";
|
|
1687
|
-
e.currentTarget.style.transform = "scale(0.95)";
|
|
1688
|
-
}
|
|
1689
|
-
},
|
|
1690
|
-
children: /* @__PURE__ */ jsx(Icon, { name: icons[mode], size: 16 })
|
|
1987
|
+
!isMobile && /* @__PURE__ */ jsx("div", { style: { flex: 1 } })
|
|
1988
|
+
] }),
|
|
1989
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.sm, flex: isMobile ? void 0 : 1, justifyContent: isMobile ? "space-between" : "flex-end" }, children: [
|
|
1990
|
+
_showFilters && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.xs, flex: isMobile ? 1 : void 0, flexShrink: 0 }, children: [
|
|
1991
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", width: isMobile ? "100%" : 180 }, children: [
|
|
1992
|
+
/* @__PURE__ */ jsx(
|
|
1993
|
+
Icon,
|
|
1994
|
+
{
|
|
1995
|
+
name: "search",
|
|
1996
|
+
size: 14,
|
|
1997
|
+
style: {
|
|
1998
|
+
position: "absolute",
|
|
1999
|
+
left: 8,
|
|
2000
|
+
top: "50%",
|
|
2001
|
+
transform: "translateY(-50%)",
|
|
2002
|
+
color: tokens.colors.text.tertiary,
|
|
2003
|
+
pointerEvents: "none"
|
|
1691
2004
|
}
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
2005
|
+
}
|
|
2006
|
+
),
|
|
2007
|
+
/* @__PURE__ */ jsx(
|
|
2008
|
+
"input",
|
|
2009
|
+
{
|
|
2010
|
+
type: "search",
|
|
2011
|
+
value: filter.search ?? "",
|
|
2012
|
+
onChange: (e) => patchFilter({ search: e.target.value || void 0 }),
|
|
2013
|
+
placeholder: "Search…",
|
|
2014
|
+
"aria-label": "Search timeline events",
|
|
2015
|
+
style: {
|
|
2016
|
+
width: "100%",
|
|
2017
|
+
boxSizing: "border-box",
|
|
2018
|
+
height: tokens.elementSize.sm,
|
|
2019
|
+
paddingLeft: 28,
|
|
2020
|
+
paddingRight: 8,
|
|
2021
|
+
borderRadius: tokens.borderRadius.md,
|
|
2022
|
+
border: `1px solid ${tokens.colors.border.muted}`,
|
|
2023
|
+
backgroundColor: tokens.colors.background.base,
|
|
2024
|
+
color: tokens.colors.text.primary,
|
|
2025
|
+
fontSize: tokens.typography.fontSize.sm,
|
|
2026
|
+
fontFamily: "inherit",
|
|
2027
|
+
outline: "none",
|
|
2028
|
+
transition: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
2029
|
+
},
|
|
2030
|
+
onFocus: (e) => {
|
|
2031
|
+
e.target.style.borderColor = tokens.colors.accent.primary;
|
|
2032
|
+
e.target.style.boxShadow = `0 0 0 3px ${tokens.colors.accent.primary}50, 0 0 20px ${tokens.colors.accent.primary}15`;
|
|
2033
|
+
},
|
|
2034
|
+
onBlur: (e) => {
|
|
2035
|
+
e.target.style.borderColor = tokens.colors.border.muted;
|
|
2036
|
+
e.target.style.boxShadow = "none";
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
)
|
|
2040
|
+
] }),
|
|
2041
|
+
/* @__PURE__ */ jsx(Tooltip, { content: filtersExpanded ? "Hide filters" : "Show filters", children: /* @__PURE__ */ jsxs(
|
|
2042
|
+
"button",
|
|
2043
|
+
{
|
|
2044
|
+
type: "button",
|
|
2045
|
+
"aria-label": filtersExpanded ? "Hide filters" : "Show filters",
|
|
2046
|
+
"aria-expanded": filtersExpanded,
|
|
2047
|
+
"aria-controls": "zendir-timeline-filters-panel",
|
|
2048
|
+
onClick: () => setFiltersExpanded((v) => !v),
|
|
2049
|
+
style: {
|
|
2050
|
+
position: "relative",
|
|
2051
|
+
display: "flex",
|
|
2052
|
+
alignItems: "center",
|
|
2053
|
+
justifyContent: "center",
|
|
2054
|
+
width: 28,
|
|
2055
|
+
height: 28,
|
|
2056
|
+
border: `1px solid ${filterChipCount > 0 ? `${tokens.colors.accent.primary}80` : tokens.colors.border.muted}`,
|
|
2057
|
+
borderRadius: tokens.borderRadius.sm,
|
|
2058
|
+
backgroundColor: filterChipCount > 0 ? `${tokens.colors.accent.primary}12` : "transparent",
|
|
2059
|
+
color: filterChipCount > 0 ? tokens.colors.accent.primary : tokens.colors.text.secondary,
|
|
2060
|
+
cursor: "pointer",
|
|
2061
|
+
transition: tokens.animation.fast
|
|
2062
|
+
},
|
|
2063
|
+
children: [
|
|
2064
|
+
/* @__PURE__ */ jsx(Icon, { name: "filter", size: 16 }),
|
|
2065
|
+
filterChipCount > 0 ? /* @__PURE__ */ jsx(
|
|
2066
|
+
"span",
|
|
2067
|
+
{
|
|
2068
|
+
style: {
|
|
2069
|
+
position: "absolute",
|
|
2070
|
+
top: -4,
|
|
2071
|
+
right: -4,
|
|
2072
|
+
minWidth: 14,
|
|
2073
|
+
height: 14,
|
|
2074
|
+
borderRadius: "50%",
|
|
2075
|
+
backgroundColor: tokens.colors.accent.primary,
|
|
2076
|
+
color: "#fff",
|
|
2077
|
+
fontSize: "0.5625rem",
|
|
2078
|
+
fontWeight: 700,
|
|
2079
|
+
display: "flex",
|
|
2080
|
+
alignItems: "center",
|
|
2081
|
+
justifyContent: "center",
|
|
2082
|
+
lineHeight: 1
|
|
2083
|
+
},
|
|
2084
|
+
children: filterChipCount
|
|
2085
|
+
}
|
|
2086
|
+
) : null
|
|
2087
|
+
]
|
|
2088
|
+
}
|
|
2089
|
+
) })
|
|
2090
|
+
] }),
|
|
2091
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12, flexShrink: 0 }, children: [
|
|
2092
|
+
zoomable && (viewMode === "chart" || viewMode === "scatter") && /* @__PURE__ */ jsxs(
|
|
2093
|
+
"div",
|
|
2094
|
+
{
|
|
2095
|
+
style: {
|
|
2096
|
+
display: "flex",
|
|
2097
|
+
alignItems: "center",
|
|
2098
|
+
gap: 4,
|
|
2099
|
+
paddingRight: 12,
|
|
2100
|
+
borderRight: `1px solid ${tokens.colors.border.muted}`
|
|
2101
|
+
},
|
|
2102
|
+
children: [
|
|
2103
|
+
/* @__PURE__ */ jsx(Tooltip, { content: "Zoom out", children: /* @__PURE__ */ jsx(
|
|
2104
|
+
"button",
|
|
2105
|
+
{
|
|
2106
|
+
type: "button",
|
|
2107
|
+
"aria-label": "Zoom out",
|
|
2108
|
+
onClick: () => setZoom(Math.max(zoom - 0.5, 1)),
|
|
2109
|
+
disabled: zoom <= 1,
|
|
2110
|
+
style: {
|
|
2111
|
+
width: 28,
|
|
2112
|
+
height: 28,
|
|
2113
|
+
display: "flex",
|
|
2114
|
+
alignItems: "center",
|
|
2115
|
+
justifyContent: "center",
|
|
2116
|
+
backgroundColor: zoom <= 1 ? "transparent" : tokens.colors.background.elevated,
|
|
2117
|
+
border: `1px solid ${tokens.colors.border.muted}`,
|
|
2118
|
+
borderRadius: tokens.borderRadius.sm,
|
|
2119
|
+
color: zoom <= 1 ? tokens.colors.text.tertiary : tokens.colors.text.primary,
|
|
2120
|
+
cursor: zoom <= 1 ? "not-allowed" : "pointer",
|
|
2121
|
+
fontSize: "1rem",
|
|
2122
|
+
fontWeight: 500,
|
|
2123
|
+
// AstroUXDS medium (was 600)
|
|
2124
|
+
opacity: zoom <= 1 ? 0.5 : 1
|
|
2125
|
+
},
|
|
2126
|
+
children: "−"
|
|
2127
|
+
}
|
|
2128
|
+
) }),
|
|
2129
|
+
/* @__PURE__ */ jsxs(
|
|
2130
|
+
"span",
|
|
2131
|
+
{
|
|
2132
|
+
style: {
|
|
2133
|
+
minWidth: 40,
|
|
2134
|
+
textAlign: "center",
|
|
2135
|
+
fontSize: "0.75rem",
|
|
2136
|
+
fontFamily: tokens.typography.fontFamily.mono,
|
|
2137
|
+
color: tokens.colors.text.secondary
|
|
2138
|
+
},
|
|
2139
|
+
children: [
|
|
2140
|
+
Math.round(zoom * 100),
|
|
2141
|
+
"%"
|
|
2142
|
+
]
|
|
2143
|
+
}
|
|
2144
|
+
),
|
|
2145
|
+
/* @__PURE__ */ jsx(Tooltip, { content: "Zoom in", children: /* @__PURE__ */ jsx(
|
|
2146
|
+
"button",
|
|
2147
|
+
{
|
|
2148
|
+
type: "button",
|
|
2149
|
+
"aria-label": "Zoom in",
|
|
2150
|
+
onClick: () => setZoom(Math.min(zoom + 0.5, 4)),
|
|
2151
|
+
disabled: zoom >= 4,
|
|
2152
|
+
style: {
|
|
2153
|
+
width: 28,
|
|
2154
|
+
height: 28,
|
|
2155
|
+
display: "flex",
|
|
2156
|
+
alignItems: "center",
|
|
2157
|
+
justifyContent: "center",
|
|
2158
|
+
backgroundColor: zoom >= 4 ? "transparent" : tokens.colors.background.elevated,
|
|
2159
|
+
border: `1px solid ${tokens.colors.border.muted}`,
|
|
2160
|
+
borderRadius: tokens.borderRadius.sm,
|
|
2161
|
+
color: zoom >= 4 ? tokens.colors.text.tertiary : tokens.colors.text.primary,
|
|
2162
|
+
cursor: zoom >= 4 ? "not-allowed" : "pointer",
|
|
2163
|
+
fontSize: "1rem",
|
|
2164
|
+
fontWeight: 500,
|
|
2165
|
+
// AstroUXDS medium (was 600)
|
|
2166
|
+
opacity: zoom >= 4 ? 0.5 : 1
|
|
2167
|
+
},
|
|
2168
|
+
children: "+"
|
|
2169
|
+
}
|
|
2170
|
+
) }),
|
|
2171
|
+
/* @__PURE__ */ jsx(Tooltip, { content: "Reset zoom", children: /* @__PURE__ */ jsx(
|
|
2172
|
+
"button",
|
|
2173
|
+
{
|
|
2174
|
+
type: "button",
|
|
2175
|
+
"aria-label": "Reset zoom",
|
|
2176
|
+
onClick: () => setZoom(1),
|
|
2177
|
+
style: {
|
|
2178
|
+
height: 28,
|
|
2179
|
+
padding: "0 10px",
|
|
2180
|
+
display: "flex",
|
|
2181
|
+
alignItems: "center",
|
|
2182
|
+
justifyContent: "center",
|
|
2183
|
+
backgroundColor: tokens.colors.background.elevated,
|
|
2184
|
+
border: `1px solid ${tokens.colors.border.muted}`,
|
|
2185
|
+
borderRadius: tokens.borderRadius.sm,
|
|
2186
|
+
color: tokens.colors.text.secondary,
|
|
2187
|
+
cursor: "pointer",
|
|
2188
|
+
fontSize: "0.6875rem",
|
|
2189
|
+
fontWeight: 500
|
|
2190
|
+
},
|
|
2191
|
+
children: "FIT"
|
|
2192
|
+
}
|
|
2193
|
+
) })
|
|
2194
|
+
]
|
|
2195
|
+
}
|
|
2196
|
+
),
|
|
2197
|
+
showViewToggle && /* @__PURE__ */ jsx(
|
|
2198
|
+
"div",
|
|
2199
|
+
{
|
|
2200
|
+
role: "group",
|
|
2201
|
+
"aria-label": "View mode",
|
|
2202
|
+
style: {
|
|
2203
|
+
display: "flex",
|
|
2204
|
+
gap: "2px",
|
|
2205
|
+
backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.elevated,
|
|
2206
|
+
...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
|
|
2207
|
+
padding: "4px",
|
|
2208
|
+
borderRadius: tokens.borderRadius.lg
|
|
2209
|
+
},
|
|
2210
|
+
children: ["chart", "list", "scatter"].map((mode) => {
|
|
2211
|
+
const isActive = viewMode === mode;
|
|
2212
|
+
const icons = {
|
|
2213
|
+
chart: "chart",
|
|
2214
|
+
list: "list",
|
|
2215
|
+
scatter: "timeline"
|
|
2216
|
+
};
|
|
2217
|
+
const labels = {
|
|
2218
|
+
chart: "Gantt Chart",
|
|
2219
|
+
list: "List View",
|
|
2220
|
+
scatter: "Scatter View"
|
|
2221
|
+
};
|
|
2222
|
+
return /* @__PURE__ */ jsx(Tooltip, { content: labels[mode], children: /* @__PURE__ */ jsx(
|
|
2223
|
+
"button",
|
|
2224
|
+
{
|
|
2225
|
+
type: "button",
|
|
2226
|
+
"aria-label": labels[mode],
|
|
2227
|
+
"aria-pressed": isActive,
|
|
2228
|
+
onClick: () => handleViewModeChange(mode),
|
|
2229
|
+
style: {
|
|
2230
|
+
display: "flex",
|
|
2231
|
+
alignItems: "center",
|
|
2232
|
+
justifyContent: "center",
|
|
2233
|
+
width: "32px",
|
|
2234
|
+
height: "32px",
|
|
2235
|
+
backgroundColor: isActive ? tokens.colors.accent.primary : "transparent",
|
|
2236
|
+
border: "none",
|
|
2237
|
+
borderRadius: tokens.borderRadius.md,
|
|
2238
|
+
color: isActive ? "#ffffff" : tokens.colors.text.secondary,
|
|
2239
|
+
cursor: "pointer",
|
|
2240
|
+
transition: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
2241
|
+
transform: isActive ? "scale(1)" : "scale(0.95)",
|
|
2242
|
+
boxShadow: isActive ? `0 2px 8px ${tokens.colors.accent.primary}40` : "none"
|
|
2243
|
+
},
|
|
2244
|
+
onMouseEnter: (e) => {
|
|
2245
|
+
if (!isActive) {
|
|
2246
|
+
e.currentTarget.style.backgroundColor = `${tokens.colors.accent.primary}20`;
|
|
2247
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
2248
|
+
}
|
|
2249
|
+
},
|
|
2250
|
+
onMouseLeave: (e) => {
|
|
2251
|
+
if (!isActive) {
|
|
2252
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
2253
|
+
e.currentTarget.style.transform = "scale(0.95)";
|
|
2254
|
+
}
|
|
2255
|
+
},
|
|
2256
|
+
children: /* @__PURE__ */ jsx(Icon, { name: icons[mode], size: 16 })
|
|
2257
|
+
}
|
|
2258
|
+
) }, mode);
|
|
2259
|
+
})
|
|
2260
|
+
}
|
|
2261
|
+
)
|
|
2262
|
+
] }),
|
|
2263
|
+
" "
|
|
2264
|
+
] }),
|
|
2265
|
+
" "
|
|
1697
2266
|
]
|
|
1698
2267
|
}
|
|
1699
2268
|
),
|
|
2269
|
+
" ",
|
|
2270
|
+
_showFilters ? /* @__PURE__ */ jsx(
|
|
2271
|
+
TimelineFiltersPanel,
|
|
2272
|
+
{
|
|
2273
|
+
filter,
|
|
2274
|
+
onFilterChange: setFilter,
|
|
2275
|
+
trackOptions: trackOptionsForToolbar,
|
|
2276
|
+
events,
|
|
2277
|
+
expanded: filtersExpanded,
|
|
2278
|
+
teamLabel
|
|
2279
|
+
}
|
|
2280
|
+
) : null,
|
|
1700
2281
|
loading && /* @__PURE__ */ jsx(
|
|
1701
2282
|
"div",
|
|
1702
2283
|
{
|
|
@@ -1708,7 +2289,7 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1708
2289
|
justifyContent: "center",
|
|
1709
2290
|
backgroundColor: `${tokens.colors.background.overlay}80`,
|
|
1710
2291
|
backdropFilter: "blur(4px)",
|
|
1711
|
-
zIndex:
|
|
2292
|
+
zIndex: Z.loadingOverlay
|
|
1712
2293
|
},
|
|
1713
2294
|
children: /* @__PURE__ */ jsx(
|
|
1714
2295
|
"div",
|
|
@@ -1751,6 +2332,43 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1751
2332
|
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.875rem" }, children: "No events to display" })
|
|
1752
2333
|
]
|
|
1753
2334
|
}
|
|
2335
|
+
) : filteredEvents.length === 0 ? /* @__PURE__ */ jsxs(
|
|
2336
|
+
"div",
|
|
2337
|
+
{
|
|
2338
|
+
style: {
|
|
2339
|
+
display: "flex",
|
|
2340
|
+
flexDirection: "column",
|
|
2341
|
+
alignItems: "center",
|
|
2342
|
+
justifyContent: "center",
|
|
2343
|
+
padding: "48px 24px",
|
|
2344
|
+
color: tokens.colors.text.tertiary,
|
|
2345
|
+
gap: 12,
|
|
2346
|
+
textAlign: "center"
|
|
2347
|
+
},
|
|
2348
|
+
children: [
|
|
2349
|
+
/* @__PURE__ */ jsx(Icon, { name: "search", size: 32 }),
|
|
2350
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "0.875rem", color: tokens.colors.text.secondary }, children: "No events match the current filters." }),
|
|
2351
|
+
_showFilters && isTimelineFilterActive(filter) ? /* @__PURE__ */ jsx(
|
|
2352
|
+
"button",
|
|
2353
|
+
{
|
|
2354
|
+
type: "button",
|
|
2355
|
+
onClick: () => setFilter({}),
|
|
2356
|
+
style: {
|
|
2357
|
+
marginTop: 4,
|
|
2358
|
+
padding: "8px 16px",
|
|
2359
|
+
borderRadius: tokens.borderRadius.md,
|
|
2360
|
+
border: `1px solid ${tokens.colors.accent.primary}`,
|
|
2361
|
+
backgroundColor: `${tokens.colors.accent.primary}18`,
|
|
2362
|
+
color: tokens.colors.accent.primary,
|
|
2363
|
+
cursor: "pointer",
|
|
2364
|
+
fontSize: "0.8125rem",
|
|
2365
|
+
fontWeight: 500
|
|
2366
|
+
},
|
|
2367
|
+
children: "Clear filters"
|
|
2368
|
+
}
|
|
2369
|
+
) : null
|
|
2370
|
+
]
|
|
2371
|
+
}
|
|
1754
2372
|
) : viewMode === "list" ? (
|
|
1755
2373
|
// List View
|
|
1756
2374
|
sortedEvents.map((event, index) => /* @__PURE__ */ jsx(
|
|
@@ -1767,8 +2385,8 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1767
2385
|
/* @__PURE__ */ jsx(
|
|
1768
2386
|
ScatterView,
|
|
1769
2387
|
{
|
|
1770
|
-
events,
|
|
1771
|
-
tracks:
|
|
2388
|
+
events: filteredEvents,
|
|
2389
|
+
tracks: effectiveTracksForViews,
|
|
1772
2390
|
start,
|
|
1773
2391
|
end,
|
|
1774
2392
|
trackHeight,
|
|
@@ -1783,8 +2401,8 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1783
2401
|
/* @__PURE__ */ jsx(
|
|
1784
2402
|
ChartView,
|
|
1785
2403
|
{
|
|
1786
|
-
events,
|
|
1787
|
-
tracks:
|
|
2404
|
+
events: filteredEvents,
|
|
2405
|
+
tracks: effectiveTracksForViews,
|
|
1788
2406
|
start,
|
|
1789
2407
|
end,
|
|
1790
2408
|
trackHeight,
|
|
@@ -1810,6 +2428,14 @@ const UnifiedTimeline = memo(function UnifiedTimeline2({
|
|
|
1810
2428
|
);
|
|
1811
2429
|
});
|
|
1812
2430
|
export {
|
|
1813
|
-
|
|
2431
|
+
TIMELINE_FILTER_TEAM_LEGACY,
|
|
2432
|
+
TIMELINE_FILTER_TEAM_NONE,
|
|
2433
|
+
UnifiedTimeline,
|
|
2434
|
+
getTimelineEventDisplayStatus,
|
|
2435
|
+
getTimelineTeamAccent,
|
|
2436
|
+
getTimelineTeamDisplayLabel,
|
|
2437
|
+
getTimelineTeamFilterKey,
|
|
2438
|
+
isTimelineFilterActive,
|
|
2439
|
+
matchesTimelineFilter
|
|
1814
2440
|
};
|
|
1815
2441
|
//# sourceMappingURL=UnifiedTimeline.js.map
|