@cere/cere-design-system 0.1.0 → 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/README.md +76 -0
- package/dist/buttons.d.mts +27 -22
- package/dist/buttons.d.ts +27 -22
- package/dist/buttons.js +5 -5
- package/dist/buttons.mjs +4 -4
- package/dist/charts.d.mts +1 -23
- package/dist/charts.d.ts +1 -23
- package/dist/charts.js +2 -9
- package/dist/charts.js.map +1 -1
- package/dist/charts.mjs +1 -8
- package/dist/{chunk-THQKYTQE.js → chunk-2KDN37PQ.js} +28 -32
- package/dist/chunk-2KDN37PQ.js.map +1 -0
- package/dist/{chunk-3WCMINE5.mjs → chunk-34LFXT6C.mjs} +25 -29
- package/dist/chunk-34LFXT6C.mjs.map +1 -0
- package/dist/chunk-3KCXCVOX.mjs +411 -0
- package/dist/chunk-3KCXCVOX.mjs.map +1 -0
- package/dist/{chunk-NXTVJ6PY.js → chunk-4OKTICU5.js} +10 -10
- package/dist/chunk-4OKTICU5.js.map +1 -0
- package/dist/{chunk-FN5YL4BK.js → chunk-72TQ56EP.js} +47 -45
- package/dist/chunk-72TQ56EP.js.map +1 -0
- package/dist/{chunk-QYYQYZHV.js → chunk-7KXKK2RE.js} +3 -5
- package/dist/chunk-7KXKK2RE.js.map +1 -0
- package/dist/{chunk-CCN6M4LI.js → chunk-ARSCL4ZZ.js} +18 -10
- package/dist/chunk-ARSCL4ZZ.js.map +1 -0
- package/dist/chunk-AWVNEU6R.mjs +1478 -0
- package/dist/chunk-AWVNEU6R.mjs.map +1 -0
- package/dist/{chunk-CUCKULYC.mjs → chunk-BH4FNZKK.mjs} +74 -1260
- package/dist/chunk-BH4FNZKK.mjs.map +1 -0
- package/dist/{chunk-FFZ5S7PQ.mjs → chunk-BOQPWZIB.mjs} +6 -5
- package/dist/chunk-BOQPWZIB.mjs.map +1 -0
- package/dist/chunk-BT7XUTT5.mjs +392 -0
- package/dist/chunk-BT7XUTT5.mjs.map +1 -0
- package/dist/{chunk-ATIFLPH6.mjs → chunk-D7D25O6E.mjs} +4 -2
- package/dist/{chunk-ATIFLPH6.mjs.map → chunk-D7D25O6E.mjs.map} +1 -1
- package/dist/{chunk-JS4IB5IU.mjs → chunk-DRGMEIPT.mjs} +2 -2
- package/dist/chunk-DRGMEIPT.mjs.map +1 -0
- package/dist/{chunk-KF2Y7HO3.js → chunk-DZXNYLVG.js} +43 -246
- package/dist/chunk-DZXNYLVG.js.map +1 -0
- package/dist/{chunk-IE6GCHDI.mjs → chunk-GR52ENYI.mjs} +26 -29
- package/dist/chunk-GR52ENYI.mjs.map +1 -0
- package/dist/chunk-GTBKQXXI.js +1472 -0
- package/dist/chunk-GTBKQXXI.js.map +1 -0
- package/dist/{chunk-463SRKKD.js → chunk-HJ24WKU4.js} +14 -5
- package/dist/chunk-HJ24WKU4.js.map +1 -0
- package/dist/{chunk-EOF3QNPF.js → chunk-KKIKOIMP.js} +140 -1028
- package/dist/chunk-KKIKOIMP.js.map +1 -0
- package/dist/{chunk-MNM6HE72.js → chunk-LVJSKRX3.js} +16 -15
- package/dist/chunk-LVJSKRX3.js.map +1 -0
- package/dist/{chunk-KPDYKK3V.js → chunk-PFZZJZ64.js} +8 -8
- package/dist/{chunk-KPDYKK3V.js.map → chunk-PFZZJZ64.js.map} +1 -1
- package/dist/{chunk-KVBMZNWT.mjs → chunk-POCAW2G4.mjs} +18 -10
- package/dist/chunk-POCAW2G4.mjs.map +1 -0
- package/dist/{chunk-L2TIGA7I.js → chunk-QCFLZ7X3.js} +39 -42
- package/dist/chunk-QCFLZ7X3.js.map +1 -0
- package/dist/{chunk-6EUAU67C.mjs → chunk-SG2TD7FQ.mjs} +8 -8
- package/dist/chunk-SG2TD7FQ.mjs.map +1 -0
- package/dist/{chunk-QY65OUAC.mjs → chunk-SSFALO6S.mjs} +13 -4
- package/dist/chunk-SSFALO6S.mjs.map +1 -0
- package/dist/{chunk-PWF2NJDB.mjs → chunk-WC2TCWXK.mjs} +82 -14
- package/dist/chunk-WC2TCWXK.mjs.map +1 -0
- package/dist/{chunk-ZGCN5WCG.js → chunk-XZZZ4MZV.js} +83 -15
- package/dist/chunk-XZZZ4MZV.js.map +1 -0
- package/dist/chunk-YCDCQSYH.js +411 -0
- package/dist/chunk-YCDCQSYH.js.map +1 -0
- package/dist/{chunk-CWJ4OU6W.mjs → chunk-ZDAZYIXB.mjs} +2 -4
- package/dist/chunk-ZDAZYIXB.mjs.map +1 -0
- package/dist/feedback.d.mts +20 -8
- package/dist/feedback.d.ts +20 -8
- package/dist/feedback.js +5 -5
- package/dist/feedback.mjs +4 -4
- package/dist/fonts/HumanSans-BlackOblique.otf +0 -0
- package/dist/fonts/HumanSans-Thin.otf +0 -0
- package/dist/fonts/HumanSans-ThinOblique.otf +0 -0
- package/dist/fonts/human-sans-font.css +88 -0
- package/dist/fonts/human-sans.css +3 -0
- package/dist/fonts/inter.css +3 -0
- package/dist/icons.d.mts +2 -3
- package/dist/icons.d.ts +2 -3
- package/dist/icons.js +2 -2
- package/dist/icons.mjs +1 -1
- package/dist/index.d.mts +37 -8
- package/dist/index.d.ts +37 -8
- package/dist/index.js +23 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -113
- package/dist/index.mjs.map +1 -1
- package/dist/inputs.d.mts +23 -3
- package/dist/inputs.d.ts +23 -3
- package/dist/inputs.js +5 -5
- package/dist/inputs.js.map +1 -1
- package/dist/inputs.mjs +15 -15
- package/dist/layout.d.mts +37 -283
- package/dist/layout.d.ts +37 -283
- package/dist/layout.js +8 -32
- package/dist/layout.js.map +1 -1
- package/dist/layout.mjs +16 -40
- package/dist/navigation.d.mts +9 -114
- package/dist/navigation.d.ts +9 -114
- package/dist/navigation.js +5 -9
- package/dist/navigation.js.map +1 -1
- package/dist/navigation.mjs +6 -10
- package/dist/third-party.d.mts +3 -527
- package/dist/third-party.d.ts +3 -527
- package/dist/third-party.js +2 -40
- package/dist/third-party.js.map +1 -1
- package/dist/third-party.mjs +3 -41
- package/dist/tokens.css +45 -71
- package/dist/utilities.js +2 -4
- package/dist/utilities.js.map +1 -1
- package/dist/utilities.mjs +2 -4
- package/package.json +23 -9
- package/dist/WorkflowNode-BnxXO6t_.d.mts +0 -46
- package/dist/WorkflowNode-BnxXO6t_.d.ts +0 -46
- package/dist/chunk-27JEWSWA.mjs +0 -233
- package/dist/chunk-27JEWSWA.mjs.map +0 -1
- package/dist/chunk-3WCMINE5.mjs.map +0 -1
- package/dist/chunk-463SRKKD.js.map +0 -1
- package/dist/chunk-6EUAU67C.mjs.map +0 -1
- package/dist/chunk-AIY6222Q.js +0 -11
- package/dist/chunk-AIY6222Q.js.map +0 -1
- package/dist/chunk-AJBM7IE6.mjs +0 -2366
- package/dist/chunk-AJBM7IE6.mjs.map +0 -1
- package/dist/chunk-CCN6M4LI.js.map +0 -1
- package/dist/chunk-CUCKULYC.mjs.map +0 -1
- package/dist/chunk-CWJ4OU6W.mjs.map +0 -1
- package/dist/chunk-EOF3QNPF.js.map +0 -1
- package/dist/chunk-FFZ5S7PQ.mjs.map +0 -1
- package/dist/chunk-FN5YL4BK.js.map +0 -1
- package/dist/chunk-HLH2VWXL.js +0 -2658
- package/dist/chunk-HLH2VWXL.js.map +0 -1
- package/dist/chunk-IE6GCHDI.mjs.map +0 -1
- package/dist/chunk-JS4IB5IU.mjs.map +0 -1
- package/dist/chunk-KF2Y7HO3.js.map +0 -1
- package/dist/chunk-KVBMZNWT.mjs.map +0 -1
- package/dist/chunk-L2TIGA7I.js.map +0 -1
- package/dist/chunk-MNM6HE72.js.map +0 -1
- package/dist/chunk-NXTVJ6PY.js.map +0 -1
- package/dist/chunk-PWF2NJDB.mjs.map +0 -1
- package/dist/chunk-QD6RLAO2.mjs +0 -11
- package/dist/chunk-QD6RLAO2.mjs.map +0 -1
- package/dist/chunk-QY65OUAC.mjs.map +0 -1
- package/dist/chunk-QYYQYZHV.js.map +0 -1
- package/dist/chunk-T7LPABOL.mjs +0 -595
- package/dist/chunk-T7LPABOL.mjs.map +0 -1
- package/dist/chunk-THQKYTQE.js.map +0 -1
- package/dist/chunk-X7E6GMFL.js +0 -233
- package/dist/chunk-X7E6GMFL.js.map +0 -1
- package/dist/chunk-XF66WQZE.mjs +0 -1535
- package/dist/chunk-XF66WQZE.mjs.map +0 -1
- package/dist/chunk-YQOZPLTY.js +0 -1535
- package/dist/chunk-YQOZPLTY.js.map +0 -1
- package/dist/chunk-ZGCN5WCG.js.map +0 -1
- package/dist/index.css +0 -79
- package/dist/index.css.map +0 -1
- /package/dist/{HumanSans-Black-C4YJONK7.otf → fonts/HumanSans-Black.otf} +0 -0
- /package/dist/{HumanSans-Bold-4EAJ3L3T.otf → fonts/HumanSans-Bold.otf} +0 -0
- /package/dist/{HumanSans-BoldOblique-4D325T4F.otf → fonts/HumanSans-BoldOblique.otf} +0 -0
- /package/dist/{HumanSans-ExtraLight-VL7DEKQ4.otf → fonts/HumanSans-ExtraLight.otf} +0 -0
- /package/dist/{HumanSans-ExtraLightOblique-VK2JTUXF.otf → fonts/HumanSans-ExtraLightOblique.otf} +0 -0
- /package/dist/{HumanSans-Light-YV7AFKRB.otf → fonts/HumanSans-Light.otf} +0 -0
- /package/dist/{HumanSans-LightOblique-VIXV7QA6.otf → fonts/HumanSans-LightOblique.otf} +0 -0
- /package/dist/{HumanSans-Medium-UULJ3PIR.otf → fonts/HumanSans-Medium.otf} +0 -0
- /package/dist/{HumanSans-MediumOblique-M7FHDZRS.otf → fonts/HumanSans-MediumOblique.otf} +0 -0
- /package/dist/{HumanSans-Regular-QMFEP3F6.otf → fonts/HumanSans-Regular.otf} +0 -0
- /package/dist/{HumanSans-RegularOblique-YPKQJAAM.otf → fonts/HumanSans-RegularOblique.otf} +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// src/components/charts/ChartWidget/ChartWidget.tsx
|
|
2
|
+
import Box from "@mui/material/Box";
|
|
3
|
+
import Stack from "@mui/material/Stack";
|
|
4
|
+
import Typography from "@mui/material/Typography";
|
|
5
|
+
import { styled, useTheme } from "@mui/material/styles";
|
|
6
|
+
import { LineChart } from "@mui/x-charts";
|
|
7
|
+
import size from "byte-size";
|
|
8
|
+
import { format } from "date-fns";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var Chart = styled(Box)(() => ({
|
|
11
|
+
height: 200
|
|
12
|
+
}));
|
|
13
|
+
var ChartWidget = ({
|
|
14
|
+
title,
|
|
15
|
+
value,
|
|
16
|
+
history,
|
|
17
|
+
formatValue = (value2) => size(value2 || 0).toString()
|
|
18
|
+
}) => {
|
|
19
|
+
const theme = useTheme();
|
|
20
|
+
return /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
|
|
21
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: title }),
|
|
22
|
+
/* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: value }),
|
|
23
|
+
/* @__PURE__ */ jsx(Chart, { children: /* @__PURE__ */ jsx(
|
|
24
|
+
LineChart,
|
|
25
|
+
{
|
|
26
|
+
dataset: history || [],
|
|
27
|
+
axisHighlight: { x: "none", y: "none" },
|
|
28
|
+
grid: { horizontal: true, vertical: false },
|
|
29
|
+
margin: { top: 10, right: 20, bottom: 40, left: 40 },
|
|
30
|
+
colors: [theme.palette.primary.main],
|
|
31
|
+
slots: {
|
|
32
|
+
noDataOverlay: () => null
|
|
33
|
+
},
|
|
34
|
+
yAxis: [
|
|
35
|
+
{
|
|
36
|
+
dataKey: "value",
|
|
37
|
+
disableLine: true,
|
|
38
|
+
disableTicks: true,
|
|
39
|
+
min: history?.length ? void 0 : 0,
|
|
40
|
+
max: history?.length ? void 0 : 100,
|
|
41
|
+
tickNumber: history?.length ? void 0 : 5,
|
|
42
|
+
valueFormatter: (value2) => formatValue(value2 || 0),
|
|
43
|
+
tickLabelStyle: {
|
|
44
|
+
fontSize: 10
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
xAxis: [
|
|
49
|
+
{
|
|
50
|
+
dataKey: "date",
|
|
51
|
+
min: history && Math.min(...history.map((record) => +record.date)),
|
|
52
|
+
max: history && Math.max(...history.map((record) => +record.date)),
|
|
53
|
+
disableLine: true,
|
|
54
|
+
disableTicks: true,
|
|
55
|
+
valueFormatter: (date) => format(date, "do MMM"),
|
|
56
|
+
tickPlacement: "end",
|
|
57
|
+
tickNumber: 1,
|
|
58
|
+
tickLabelStyle: {
|
|
59
|
+
fontSize: 10,
|
|
60
|
+
transform: "translate(-16px, 16px) rotate(-30deg)"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
series: [
|
|
65
|
+
{
|
|
66
|
+
curve: "linear",
|
|
67
|
+
dataKey: "value",
|
|
68
|
+
showMark: false,
|
|
69
|
+
valueFormatter: (value2) => formatValue(value2 || 0)
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
) })
|
|
74
|
+
] });
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// src/components/charts/TimeSeriesGraph/TimeSeriesGraph.tsx
|
|
78
|
+
import { useCallback, useMemo, useState } from "react";
|
|
79
|
+
import Box2 from "@mui/material/Box";
|
|
80
|
+
import Card from "@mui/material/Card";
|
|
81
|
+
import CardHeader from "@mui/material/CardHeader";
|
|
82
|
+
import CardMedia from "@mui/material/CardMedia";
|
|
83
|
+
import CircularProgress from "@mui/material/CircularProgress";
|
|
84
|
+
import Divider from "@mui/material/Divider";
|
|
85
|
+
import Stack3 from "@mui/material/Stack";
|
|
86
|
+
import Typography3 from "@mui/material/Typography";
|
|
87
|
+
import { styled as styled2, useTheme as useTheme2 } from "@mui/material/styles";
|
|
88
|
+
import { LineChart as LineChart2 } from "@mui/x-charts";
|
|
89
|
+
import { format as format2 } from "date-fns";
|
|
90
|
+
|
|
91
|
+
// src/components/charts/TimeSeriesGraph/TimeRangeSelect.tsx
|
|
92
|
+
import MenuItem from "@mui/material/MenuItem";
|
|
93
|
+
import TextField from "@mui/material/TextField";
|
|
94
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
95
|
+
var TimeRangeSelect = ({ options, value, onChange }) => /* @__PURE__ */ jsx2(
|
|
96
|
+
TextField,
|
|
97
|
+
{
|
|
98
|
+
select: true,
|
|
99
|
+
size: "small",
|
|
100
|
+
value: value ?? (options.length > 0 ? options[0].value : ""),
|
|
101
|
+
onChange: (e) => onChange?.(e.target.value),
|
|
102
|
+
"aria-label": "Time range selector",
|
|
103
|
+
sx: { minWidth: 120 },
|
|
104
|
+
children: options.map((option) => /* @__PURE__ */ jsx2(MenuItem, { value: option.value, children: option.label }, option.value))
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// src/components/charts/TimeSeriesGraph/SummaryStats.tsx
|
|
109
|
+
import Stack2 from "@mui/material/Stack";
|
|
110
|
+
import Typography2 from "@mui/material/Typography";
|
|
111
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
112
|
+
var formatSummaryValue = (value, unit) => {
|
|
113
|
+
const displayValue = typeof value === "number" ? value.toLocaleString() : value;
|
|
114
|
+
return unit ? `${displayValue} ${unit}` : displayValue;
|
|
115
|
+
};
|
|
116
|
+
var SummaryStats = ({ items }) => {
|
|
117
|
+
if (items.length === 0) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return /* @__PURE__ */ jsx3(
|
|
121
|
+
Stack2,
|
|
122
|
+
{
|
|
123
|
+
direction: "row",
|
|
124
|
+
spacing: 3,
|
|
125
|
+
padding: 2,
|
|
126
|
+
flexWrap: "wrap",
|
|
127
|
+
useFlexGap: true,
|
|
128
|
+
role: "list",
|
|
129
|
+
"aria-label": "Summary statistics",
|
|
130
|
+
children: items.map((item) => /* @__PURE__ */ jsxs2(
|
|
131
|
+
Stack2,
|
|
132
|
+
{
|
|
133
|
+
direction: "row",
|
|
134
|
+
alignItems: "center",
|
|
135
|
+
spacing: 1,
|
|
136
|
+
role: "listitem",
|
|
137
|
+
children: [
|
|
138
|
+
/* @__PURE__ */ jsx3(Typography2, { variant: "body2", color: "text.secondary", children: item.label }),
|
|
139
|
+
/* @__PURE__ */ jsx3(Typography2, { variant: "h5", fontWeight: 600, children: formatSummaryValue(item.value, item.unit) })
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
item.label
|
|
143
|
+
))
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/components/charts/TimeSeriesGraph/TimeSeriesGraph.tsx
|
|
149
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
150
|
+
var ChartContainer = styled2(Box2)({
|
|
151
|
+
position: "relative",
|
|
152
|
+
height: 320
|
|
153
|
+
});
|
|
154
|
+
var LoadingOverlay = styled2(Box2)(({ theme }) => ({
|
|
155
|
+
position: "absolute",
|
|
156
|
+
inset: 0,
|
|
157
|
+
display: "flex",
|
|
158
|
+
alignItems: "center",
|
|
159
|
+
justifyContent: "center",
|
|
160
|
+
backgroundColor: "rgba(255, 255, 255, 0.7)",
|
|
161
|
+
zIndex: 1,
|
|
162
|
+
borderRadius: theme.shape.borderRadius
|
|
163
|
+
}));
|
|
164
|
+
var LegendDot = styled2(Box2, {
|
|
165
|
+
shouldForwardProp: (prop) => prop !== "dotColor"
|
|
166
|
+
})(({ dotColor }) => ({
|
|
167
|
+
width: 14,
|
|
168
|
+
height: 14,
|
|
169
|
+
borderRadius: 4,
|
|
170
|
+
backgroundColor: dotColor,
|
|
171
|
+
flexShrink: 0
|
|
172
|
+
}));
|
|
173
|
+
var formatYAxisValue = (value) => {
|
|
174
|
+
const absValue = Math.abs(value);
|
|
175
|
+
if (absValue >= 1e9) {
|
|
176
|
+
return `${(value / 1e9).toFixed(absValue % 1e9 === 0 ? 0 : 1)}B`;
|
|
177
|
+
}
|
|
178
|
+
if (absValue >= 1e6) {
|
|
179
|
+
return `${(value / 1e6).toFixed(absValue % 1e6 === 0 ? 0 : 1)}M`;
|
|
180
|
+
}
|
|
181
|
+
if (absValue >= 1e3) {
|
|
182
|
+
return `${(value / 1e3).toFixed(absValue % 1e3 === 0 ? 0 : 1)}K`;
|
|
183
|
+
}
|
|
184
|
+
return String(value);
|
|
185
|
+
};
|
|
186
|
+
var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
|
|
187
|
+
var inferXAxisFormat = (min, max) => {
|
|
188
|
+
if (!min || !max) return "do MMM";
|
|
189
|
+
const spanMs = max.getTime() - min.getTime();
|
|
190
|
+
return spanMs <= TWENTY_FOUR_HOURS_MS ? "HH:mm" : "do MMM";
|
|
191
|
+
};
|
|
192
|
+
var buildDataset = (series, hiddenSeries) => {
|
|
193
|
+
const timestampMap = /* @__PURE__ */ new Map();
|
|
194
|
+
series.forEach((s) => {
|
|
195
|
+
if (hiddenSeries.has(s.name)) return;
|
|
196
|
+
s.data.forEach((dp) => {
|
|
197
|
+
const ts = dp.timestamp.getTime();
|
|
198
|
+
if (!timestampMap.has(ts)) {
|
|
199
|
+
timestampMap.set(ts, { timestamp: dp.timestamp });
|
|
200
|
+
}
|
|
201
|
+
timestampMap.get(ts)[s.name] = dp.value;
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
return Array.from(timestampMap.values()).sort(
|
|
205
|
+
(a, b) => a.timestamp.getTime() - b.timestamp.getTime()
|
|
206
|
+
);
|
|
207
|
+
};
|
|
208
|
+
var TimeSeriesGraph = ({
|
|
209
|
+
title,
|
|
210
|
+
series,
|
|
211
|
+
timeRangeOptions,
|
|
212
|
+
selectedTimeRange,
|
|
213
|
+
onTimeRangeChange,
|
|
214
|
+
summaryItems,
|
|
215
|
+
showSummary = true,
|
|
216
|
+
headerAction,
|
|
217
|
+
loading = false,
|
|
218
|
+
xAxisFormat
|
|
219
|
+
}) => {
|
|
220
|
+
const theme = useTheme2();
|
|
221
|
+
const [hiddenSeries, setHiddenSeries] = useState(/* @__PURE__ */ new Set());
|
|
222
|
+
const dataset = useMemo(() => buildDataset(series, hiddenSeries), [series, hiddenSeries]);
|
|
223
|
+
const visibleSeries = useMemo(
|
|
224
|
+
() => series.filter((s) => !hiddenSeries.has(s.name)),
|
|
225
|
+
[series, hiddenSeries]
|
|
226
|
+
);
|
|
227
|
+
const chartColors = useMemo(() => visibleSeries.map((s) => s.color), [visibleSeries]);
|
|
228
|
+
const handleLegendToggle = useCallback((seriesName) => {
|
|
229
|
+
setHiddenSeries((prev) => {
|
|
230
|
+
const next = new Set(prev);
|
|
231
|
+
if (next.has(seriesName)) {
|
|
232
|
+
next.delete(seriesName);
|
|
233
|
+
} else {
|
|
234
|
+
next.add(seriesName);
|
|
235
|
+
}
|
|
236
|
+
return next;
|
|
237
|
+
});
|
|
238
|
+
}, []);
|
|
239
|
+
const timeBounds = useMemo(() => {
|
|
240
|
+
if (dataset.length === 0) return { min: void 0, max: void 0 };
|
|
241
|
+
const timestamps = dataset.map((row) => row.timestamp.getTime());
|
|
242
|
+
return {
|
|
243
|
+
min: new Date(Math.min(...timestamps)),
|
|
244
|
+
max: new Date(Math.max(...timestamps))
|
|
245
|
+
};
|
|
246
|
+
}, [dataset]);
|
|
247
|
+
const resolvedXAxisFormat = useMemo(
|
|
248
|
+
() => xAxisFormat ?? inferXAxisFormat(timeBounds.min, timeBounds.max),
|
|
249
|
+
[xAxisFormat, timeBounds.min, timeBounds.max]
|
|
250
|
+
);
|
|
251
|
+
const hasData = dataset.length > 0;
|
|
252
|
+
const shouldShowSummary = showSummary && summaryItems && summaryItems.length > 0;
|
|
253
|
+
const headerActionElement = /* @__PURE__ */ jsxs3(Stack3, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
254
|
+
headerAction,
|
|
255
|
+
timeRangeOptions && timeRangeOptions.length > 0 && /* @__PURE__ */ jsx4(
|
|
256
|
+
TimeRangeSelect,
|
|
257
|
+
{
|
|
258
|
+
options: timeRangeOptions,
|
|
259
|
+
value: selectedTimeRange,
|
|
260
|
+
onChange: onTimeRangeChange
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
] });
|
|
264
|
+
const showHeader = !!title || !!headerAction || timeRangeOptions && timeRangeOptions.length > 0;
|
|
265
|
+
return /* @__PURE__ */ jsxs3(
|
|
266
|
+
Card,
|
|
267
|
+
{
|
|
268
|
+
"aria-label": title ? `Line chart showing ${title}` : "Line chart",
|
|
269
|
+
role: "figure",
|
|
270
|
+
children: [
|
|
271
|
+
showHeader && /* @__PURE__ */ jsx4(
|
|
272
|
+
CardHeader,
|
|
273
|
+
{
|
|
274
|
+
title,
|
|
275
|
+
titleTypographyProps: {
|
|
276
|
+
variant: "subtitle1",
|
|
277
|
+
fontWeight: 500
|
|
278
|
+
},
|
|
279
|
+
action: headerActionElement
|
|
280
|
+
}
|
|
281
|
+
),
|
|
282
|
+
/* @__PURE__ */ jsxs3(CardMedia, { children: [
|
|
283
|
+
/* @__PURE__ */ jsxs3(ChartContainer, { children: [
|
|
284
|
+
loading && /* @__PURE__ */ jsx4(LoadingOverlay, { role: "status", "aria-label": "Loading chart data", children: /* @__PURE__ */ jsx4(CircularProgress, { size: 40 }) }),
|
|
285
|
+
/* @__PURE__ */ jsx4(
|
|
286
|
+
LineChart2,
|
|
287
|
+
{
|
|
288
|
+
dataset,
|
|
289
|
+
axisHighlight: { x: "line", y: "none" },
|
|
290
|
+
grid: { horizontal: true, vertical: false },
|
|
291
|
+
margin: { top: 10, right: 20, bottom: 40, left: 50 },
|
|
292
|
+
colors: chartColors.length > 0 ? chartColors : [theme.palette.primary.main],
|
|
293
|
+
slots: {
|
|
294
|
+
noDataOverlay: () => null
|
|
295
|
+
},
|
|
296
|
+
tooltip: { trigger: hasData ? "axis" : "none" },
|
|
297
|
+
yAxis: [
|
|
298
|
+
{
|
|
299
|
+
disableLine: true,
|
|
300
|
+
disableTicks: true,
|
|
301
|
+
min: hasData ? void 0 : 0,
|
|
302
|
+
max: hasData ? void 0 : 100,
|
|
303
|
+
tickNumber: hasData ? void 0 : 5,
|
|
304
|
+
valueFormatter: (value) => formatYAxisValue(value || 0),
|
|
305
|
+
tickLabelStyle: {
|
|
306
|
+
fontSize: 10
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
],
|
|
310
|
+
xAxis: [
|
|
311
|
+
{
|
|
312
|
+
dataKey: "timestamp",
|
|
313
|
+
scaleType: "time",
|
|
314
|
+
min: timeBounds.min,
|
|
315
|
+
max: timeBounds.max,
|
|
316
|
+
disableLine: true,
|
|
317
|
+
disableTicks: true,
|
|
318
|
+
valueFormatter: (date) => format2(date, resolvedXAxisFormat),
|
|
319
|
+
tickLabelStyle: {
|
|
320
|
+
fontSize: 10
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
],
|
|
324
|
+
series: visibleSeries.map((s) => ({
|
|
325
|
+
curve: "linear",
|
|
326
|
+
dataKey: s.name,
|
|
327
|
+
label: s.name,
|
|
328
|
+
showMark: false,
|
|
329
|
+
connectNulls: false
|
|
330
|
+
})),
|
|
331
|
+
slotProps: {
|
|
332
|
+
legend: { hidden: true }
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
)
|
|
336
|
+
] }),
|
|
337
|
+
series.length > 0 && /* @__PURE__ */ jsx4(
|
|
338
|
+
Stack3,
|
|
339
|
+
{
|
|
340
|
+
direction: "row",
|
|
341
|
+
spacing: 2,
|
|
342
|
+
justifyContent: "center",
|
|
343
|
+
paddingY: 1,
|
|
344
|
+
flexWrap: "wrap",
|
|
345
|
+
useFlexGap: true,
|
|
346
|
+
role: "list",
|
|
347
|
+
"aria-label": "Chart legend",
|
|
348
|
+
children: series.map((s) => {
|
|
349
|
+
const isHidden = hiddenSeries.has(s.name);
|
|
350
|
+
return /* @__PURE__ */ jsxs3(
|
|
351
|
+
Stack3,
|
|
352
|
+
{
|
|
353
|
+
direction: "row",
|
|
354
|
+
spacing: 1,
|
|
355
|
+
alignItems: "center",
|
|
356
|
+
role: "listitem",
|
|
357
|
+
onClick: () => handleLegendToggle(s.name),
|
|
358
|
+
sx: {
|
|
359
|
+
cursor: "pointer",
|
|
360
|
+
opacity: isHidden ? 0.4 : 1,
|
|
361
|
+
transition: "opacity 0.2s ease",
|
|
362
|
+
userSelect: "none"
|
|
363
|
+
},
|
|
364
|
+
"aria-pressed": !isHidden,
|
|
365
|
+
"aria-label": `Toggle ${s.name} visibility`,
|
|
366
|
+
children: [
|
|
367
|
+
/* @__PURE__ */ jsx4(LegendDot, { dotColor: s.color }),
|
|
368
|
+
/* @__PURE__ */ jsx4(Typography3, { variant: "body2", children: s.name })
|
|
369
|
+
]
|
|
370
|
+
},
|
|
371
|
+
s.name
|
|
372
|
+
);
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
] }),
|
|
377
|
+
shouldShowSummary && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
378
|
+
/* @__PURE__ */ jsx4(Divider, {}),
|
|
379
|
+
/* @__PURE__ */ jsx4(SummaryStats, { items: summaryItems })
|
|
380
|
+
] })
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
export {
|
|
387
|
+
ChartWidget,
|
|
388
|
+
TimeRangeSelect,
|
|
389
|
+
SummaryStats,
|
|
390
|
+
TimeSeriesGraph
|
|
391
|
+
};
|
|
392
|
+
//# sourceMappingURL=chunk-BT7XUTT5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/charts/ChartWidget/ChartWidget.tsx","../src/components/charts/TimeSeriesGraph/TimeSeriesGraph.tsx","../src/components/charts/TimeSeriesGraph/TimeRangeSelect.tsx","../src/components/charts/TimeSeriesGraph/SummaryStats.tsx"],"sourcesContent":["import { ReactNode } from 'react';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport { styled, useTheme } from '@mui/material/styles';\nimport { LineChart } from '@mui/x-charts';\nimport size from 'byte-size';\nimport { format } from 'date-fns';\n\ntype ChartWidgetHistoryRecord = {\n date: Date;\n value: number;\n};\n\nexport type ChartWidgetProps = {\n title: string;\n value?: ReactNode;\n history?: ChartWidgetHistoryRecord[];\n formatValue?: (value: number) => string;\n};\n\nconst Chart = styled(Box)(() => ({\n height: 200,\n}));\n\nexport const ChartWidget = ({\n title,\n value,\n history,\n formatValue = (value) => size(value || 0).toString(),\n}: ChartWidgetProps) => {\n const theme = useTheme();\n\n return (\n <Stack spacing={1}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {title}\n </Typography>\n <Typography fontWeight=\"bold\">{value}</Typography>\n\n <Chart>\n <LineChart\n dataset={history || []}\n axisHighlight={{ x: 'none', y: 'none' }}\n grid={{ horizontal: true, vertical: false }}\n margin={{ top: 10, right: 20, bottom: 40, left: 40 }}\n colors={[theme.palette.primary.main]}\n slots={{\n noDataOverlay: () => null,\n }}\n yAxis={[\n {\n dataKey: 'value',\n disableLine: true,\n disableTicks: true,\n min: history?.length ? undefined : 0,\n max: history?.length ? undefined : 100,\n tickNumber: history?.length ? undefined : 5,\n valueFormatter: (value) => formatValue(value || 0),\n tickLabelStyle: {\n fontSize: 10,\n },\n },\n ]}\n xAxis={[\n {\n dataKey: 'date',\n min: history && Math.min(...history.map((record) => +record.date)),\n max: history && Math.max(...history.map((record) => +record.date)),\n disableLine: true,\n disableTicks: true,\n valueFormatter: (date) => format(date, 'do MMM'),\n tickPlacement: 'end',\n tickNumber: 1,\n\n tickLabelStyle: {\n fontSize: 10,\n transform: 'translate(-16px, 16px) rotate(-30deg)',\n },\n },\n ]}\n series={[\n {\n curve: 'linear',\n dataKey: 'value',\n showMark: false,\n valueFormatter: (value) => formatValue(value || 0),\n },\n ]}\n />\n </Chart>\n </Stack>\n );\n};\n","import { ReactNode, useCallback, useMemo, useState } from 'react';\nimport Box from '@mui/material/Box';\nimport Card from '@mui/material/Card';\nimport CardHeader from '@mui/material/CardHeader';\nimport CardMedia from '@mui/material/CardMedia';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Divider from '@mui/material/Divider';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport { styled, useTheme } from '@mui/material/styles';\nimport { LineChart } from '@mui/x-charts';\nimport { format } from 'date-fns';\n\nimport { TimeRangeSelect, type TimeRangeOption } from './TimeRangeSelect';\nimport { SummaryStats, type SummaryItem } from './SummaryStats';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * A single data point in a time series.\n * Use `null` for the value to represent missing/gap data — the line will break.\n */\nexport interface DataPoint {\n /** Timestamp of the observation */\n timestamp: Date;\n /** Numeric value, or `null` to indicate a gap in the data */\n value: number | null;\n}\n\n/**\n * Represents one line on the graph (a named data series).\n */\nexport interface DataSeries {\n /** Unique display name for this series (shown in legend) */\n name: string;\n /** CSS color string for the line and legend indicator */\n color: string;\n /** Ordered array of data points */\n data: DataPoint[];\n}\n\nexport interface TimeSeriesGraphProps {\n /** Optional title displayed at the top-left of the graph card */\n title?: string;\n /**\n * Array of data series to render. Each series becomes one line on the graph.\n * There is no hardcoded limit on the number of series.\n */\n series: DataSeries[];\n /**\n * Configurable time range options for the dropdown selector.\n * When omitted, the time range dropdown is not rendered.\n */\n timeRangeOptions?: TimeRangeOption[];\n /** Currently selected time range value (controlled) */\n selectedTimeRange?: string;\n /** Callback invoked when the user picks a different time range */\n onTimeRangeChange?: (value: string) => void;\n /**\n * Optional array of summary statistics displayed below the graph.\n * When omitted or empty, the summary section is hidden.\n */\n summaryItems?: SummaryItem[];\n /**\n * Whether to show the summary statistics section.\n * Defaults to `true`. Set to `false` to explicitly hide, even when `summaryItems` are provided.\n */\n showSummary?: boolean;\n /**\n * Optional header action element rendered to the right of the title\n * (e.g., a secondary dropdown or filter control).\n */\n headerAction?: ReactNode;\n /**\n * When `true`, shows a loading overlay (spinner) over the graph area\n * while the header remains visible and interactive.\n */\n loading?: boolean;\n /**\n * Override the x-axis date format string (date-fns format tokens).\n * When omitted, the format is auto-detected from the data's time span:\n * - <= 24 hours → `'HH:mm'`\n * - > 24 hours → `'do MMM'`\n */\n xAxisFormat?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Styled helpers\n// ---------------------------------------------------------------------------\n\nconst ChartContainer = styled(Box)({\n position: 'relative',\n height: 320,\n});\n\nconst LoadingOverlay = styled(Box)(({ theme }) => ({\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'rgba(255, 255, 255, 0.7)',\n zIndex: 1,\n borderRadius: theme.shape.borderRadius,\n}));\n\nconst LegendDot = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'dotColor',\n})<{ dotColor: string }>(({ dotColor }) => ({\n width: 14,\n height: 14,\n borderRadius: 4,\n backgroundColor: dotColor,\n flexShrink: 0,\n}));\n\n// ---------------------------------------------------------------------------\n// Utility functions\n// ---------------------------------------------------------------------------\n\n/**\n * Formats large Y-axis values into shorthand notation.\n * 1,000 → 1K, 1,000,000 → 1M, 1,000,000,000 → 1B\n */\nconst formatYAxisValue = (value: number): string => {\n const absValue = Math.abs(value);\n if (absValue >= 1_000_000_000) {\n return `${(value / 1_000_000_000).toFixed(absValue % 1_000_000_000 === 0 ? 0 : 1)}B`;\n }\n if (absValue >= 1_000_000) {\n return `${(value / 1_000_000).toFixed(absValue % 1_000_000 === 0 ? 0 : 1)}M`;\n }\n if (absValue >= 1_000) {\n return `${(value / 1_000).toFixed(absValue % 1_000 === 0 ? 0 : 1)}K`;\n }\n return String(value);\n};\n\nconst TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Infers the appropriate x-axis date format string based on the time span of the data.\n * - Span <= 24 hours → `'HH:mm'` (e.g., \"14:30\")\n * - Span > 24 hours → `'do MMM'` (e.g., \"2nd Jan\")\n */\nexport const inferXAxisFormat = (\n min: Date | undefined,\n max: Date | undefined,\n): string => {\n if (!min || !max) return 'do MMM';\n const spanMs = max.getTime() - min.getTime();\n return spanMs <= TWENTY_FOUR_HOURS_MS ? 'HH:mm' : 'do MMM';\n};\n\n/** A single row in the chart dataset — timestamp plus one field per series. */\ntype DatasetRow = Record<string, string | number | Date | null | undefined>;\n\n/**\n * Builds the unified dataset array that MUI X-Charts expects.\n * Each row is keyed by timestamp with one field per series.\n */\nconst buildDataset = (\n series: DataSeries[],\n hiddenSeries: Set<string>,\n): DatasetRow[] => {\n // Collect all unique timestamps across all visible series\n const timestampMap = new Map<number, DatasetRow>();\n\n series.forEach((s) => {\n if (hiddenSeries.has(s.name)) return;\n s.data.forEach((dp) => {\n const ts = dp.timestamp.getTime();\n if (!timestampMap.has(ts)) {\n timestampMap.set(ts, { timestamp: dp.timestamp } as DatasetRow);\n }\n timestampMap.get(ts)![s.name] = dp.value;\n });\n });\n\n // Sort by timestamp ascending\n return Array.from(timestampMap.values()).sort(\n (a, b) => (a.timestamp as Date).getTime() - (b.timestamp as Date).getTime(),\n );\n};\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * A reusable time series graph component that displays one or more data lines\n * over a shared time axis. Supports configurable time range selection,\n * optional summary statistics, interactive legend toggling, crosshair tooltips,\n * and a loading state.\n *\n * Built on `@mui/x-charts` LineChart and the Cere Design System theme.\n *\n * @example\n * ```tsx\n * <TimeSeriesGraph\n * title=\"Engagement over time\"\n * series={[\n * { name: 'Engagements', color: '#6750A4', data: engagementData },\n * { name: 'Unique Streams', color: '#4caf50', data: streamData },\n * ]}\n * timeRangeOptions={[\n * { label: 'Last hour', value: 'hour' },\n * { label: '24 hours', value: 'day' },\n * { label: '1 week', value: 'week' },\n * { label: '1 month', value: 'month' },\n * ]}\n * selectedTimeRange=\"week\"\n * onTimeRangeChange={(range) => fetchData(range)}\n * summaryItems={[\n * { label: 'Total Engagements', value: 11372 },\n * { label: 'Daily Engagements', value: 156 },\n * ]}\n * />\n * ```\n *\n * Figma reference: [ROB Design - Node 162:1172](https://www.figma.com/design/xky11VbkkFcgZLwZE8BdCN/ROB?node-id=162-1172&m=dev)\n */\nexport const TimeSeriesGraph = ({\n title,\n series,\n timeRangeOptions,\n selectedTimeRange,\n onTimeRangeChange,\n summaryItems,\n showSummary = true,\n headerAction,\n loading = false,\n xAxisFormat,\n}: TimeSeriesGraphProps) => {\n const theme = useTheme();\n const [hiddenSeries, setHiddenSeries] = useState<Set<string>>(new Set());\n\n // Build the MUI X-Charts dataset from visible series\n const dataset = useMemo(() => buildDataset(series, hiddenSeries), [series, hiddenSeries]);\n\n // Visible series (exclude hidden)\n const visibleSeries = useMemo(\n () => series.filter((s) => !hiddenSeries.has(s.name)),\n [series, hiddenSeries],\n );\n\n // Colors array matching the order of visible series\n const chartColors = useMemo(() => visibleSeries.map((s) => s.color), [visibleSeries]);\n\n // Toggle a series' visibility\n const handleLegendToggle = useCallback((seriesName: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev);\n if (next.has(seriesName)) {\n next.delete(seriesName);\n } else {\n next.add(seriesName);\n }\n return next;\n });\n }, []);\n\n // Compute time bounds for the X-axis from visible data\n const timeBounds = useMemo(() => {\n if (dataset.length === 0) return { min: undefined, max: undefined };\n const timestamps = dataset.map((row) => (row.timestamp as Date).getTime());\n return {\n min: new Date(Math.min(...timestamps)),\n max: new Date(Math.max(...timestamps)),\n };\n }, [dataset]);\n\n // Resolve the x-axis date format: explicit prop wins, otherwise auto-detect\n const resolvedXAxisFormat = useMemo(\n () => xAxisFormat ?? inferXAxisFormat(timeBounds.min, timeBounds.max),\n [xAxisFormat, timeBounds.min, timeBounds.max],\n );\n\n // Determine whether we have data to display\n const hasData = dataset.length > 0;\n\n // Whether to render the summary section\n const shouldShowSummary = showSummary && summaryItems && summaryItems.length > 0;\n\n // Build the header action area (time range + optional custom action)\n const headerActionElement = (\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n {headerAction}\n {timeRangeOptions && timeRangeOptions.length > 0 && (\n <TimeRangeSelect\n options={timeRangeOptions}\n value={selectedTimeRange}\n onChange={onTimeRangeChange}\n />\n )}\n </Stack>\n );\n\n // Determine whether to show the header at all\n const showHeader = !!title || !!headerAction || (timeRangeOptions && timeRangeOptions.length > 0);\n\n return (\n <Card\n aria-label={title ? `Line chart showing ${title}` : 'Line chart'}\n role=\"figure\"\n >\n {showHeader && (\n <CardHeader\n title={title}\n titleTypographyProps={{\n variant: 'subtitle1',\n fontWeight: 500,\n }}\n action={headerActionElement}\n />\n )}\n\n <CardMedia>\n <ChartContainer>\n {loading && (\n <LoadingOverlay role=\"status\" aria-label=\"Loading chart data\">\n <CircularProgress size={40} />\n </LoadingOverlay>\n )}\n\n <LineChart\n dataset={dataset}\n axisHighlight={{ x: 'line', y: 'none' }}\n grid={{ horizontal: true, vertical: false }}\n margin={{ top: 10, right: 20, bottom: 40, left: 50 }}\n colors={chartColors.length > 0 ? chartColors : [theme.palette.primary.main]}\n slots={{\n noDataOverlay: () => null,\n }}\n tooltip={{ trigger: hasData ? 'axis' : 'none' }}\n yAxis={[\n {\n disableLine: true,\n disableTicks: true,\n min: hasData ? undefined : 0,\n max: hasData ? undefined : 100,\n tickNumber: hasData ? undefined : 5,\n valueFormatter: (value: number) => formatYAxisValue(value || 0),\n tickLabelStyle: {\n fontSize: 10,\n },\n },\n ]}\n xAxis={[\n {\n dataKey: 'timestamp',\n scaleType: 'time',\n min: timeBounds.min,\n max: timeBounds.max,\n disableLine: true,\n disableTicks: true,\n valueFormatter: (date: Date) => format(date, resolvedXAxisFormat),\n tickLabelStyle: {\n fontSize: 10,\n },\n },\n ]}\n series={visibleSeries.map((s) => ({\n curve: 'linear' as const,\n dataKey: s.name,\n label: s.name,\n showMark: false,\n connectNulls: false,\n }))}\n // Hide the built-in legend — we render a custom one below\n slotProps={{\n legend: { hidden: true },\n }}\n />\n </ChartContainer>\n\n {/* Custom interactive legend */}\n {series.length > 0 && (\n <Stack\n direction=\"row\"\n spacing={2}\n justifyContent=\"center\"\n paddingY={1}\n flexWrap=\"wrap\"\n useFlexGap\n role=\"list\"\n aria-label=\"Chart legend\"\n >\n {series.map((s) => {\n const isHidden = hiddenSeries.has(s.name);\n return (\n <Stack\n key={s.name}\n direction=\"row\"\n spacing={1}\n alignItems=\"center\"\n role=\"listitem\"\n onClick={() => handleLegendToggle(s.name)}\n sx={{\n cursor: 'pointer',\n opacity: isHidden ? 0.4 : 1,\n transition: 'opacity 0.2s ease',\n userSelect: 'none',\n }}\n aria-pressed={!isHidden}\n aria-label={`Toggle ${s.name} visibility`}\n >\n <LegendDot dotColor={s.color} />\n <Typography variant=\"body2\">{s.name}</Typography>\n </Stack>\n );\n })}\n </Stack>\n )}\n </CardMedia>\n\n {/* Summary statistics */}\n {shouldShowSummary && (\n <>\n <Divider />\n <SummaryStats items={summaryItems!} />\n </>\n )}\n </Card>\n );\n};\n","import MenuItem from '@mui/material/MenuItem';\nimport TextField from '@mui/material/TextField';\n\n/**\n * Represents a single time range option in the dropdown.\n */\nexport interface TimeRangeOption {\n /** Display label shown in the dropdown (e.g., \"1 week\") */\n label: string;\n /** Value identifier passed to the callback on selection */\n value: string;\n}\n\nexport interface TimeRangeSelectProps {\n /** Available time range options */\n options: TimeRangeOption[];\n /** Currently selected time range value */\n value?: string;\n /** Callback invoked when user selects a different time range */\n onChange?: (value: string) => void;\n}\n\n/**\n * Configurable time range dropdown selector.\n * Renders a compact select field with the provided time range options.\n *\n * @example\n * ```tsx\n * <TimeRangeSelect\n * options={[\n * { label: 'Last hour', value: 'hour' },\n * { label: '24 hours', value: 'day' },\n * { label: '1 week', value: 'week' },\n * ]}\n * value=\"week\"\n * onChange={(value) => console.log(value)}\n * />\n * ```\n */\nexport const TimeRangeSelect = ({ options, value, onChange }: TimeRangeSelectProps) => (\n <TextField\n select\n size=\"small\"\n value={value ?? (options.length > 0 ? options[0].value : '')}\n onChange={(e) => onChange?.(e.target.value)}\n aria-label=\"Time range selector\"\n sx={{ minWidth: 120 }}\n >\n {options.map((option) => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </TextField>\n);\n","import Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\n\n/**\n * Represents a single summary statistic item displayed below the graph.\n */\nexport interface SummaryItem {\n /** Descriptive label (e.g., \"Total Engagements\") */\n label: string;\n /** Numeric or string value (e.g., \"13.72\" or 11372) */\n value: string | number;\n /** Optional unit suffix (e.g., \"K\", \"GB\", \"%\") */\n unit?: string;\n}\n\nexport interface SummaryStatsProps {\n /** Array of summary items to display */\n items: SummaryItem[];\n}\n\n/**\n * Formats a summary value with its optional unit.\n */\nconst formatSummaryValue = (value: string | number, unit?: string): string => {\n const displayValue = typeof value === 'number' ? value.toLocaleString() : value;\n return unit ? `${displayValue} ${unit}` : displayValue;\n};\n\n/**\n * Renders a horizontal row of summary statistics below the graph.\n * Each item shows a label with its corresponding value and optional unit.\n *\n * Matches the Figma design layout with label in secondary text color\n * and value in bold heading typography.\n *\n * @example\n * ```tsx\n * <SummaryStats\n * items={[\n * { label: 'Total Engagements', value: 11372 },\n * { label: 'Total Consumed', value: '156.91', unit: 'GB' },\n * ]}\n * />\n * ```\n */\nexport const SummaryStats = ({ items }: SummaryStatsProps) => {\n if (items.length === 0) {\n return null;\n }\n\n return (\n <Stack\n direction=\"row\"\n spacing={3}\n padding={2}\n flexWrap=\"wrap\"\n useFlexGap\n role=\"list\"\n aria-label=\"Summary statistics\"\n >\n {items.map((item) => (\n <Stack\n key={item.label}\n direction=\"row\"\n alignItems=\"center\"\n spacing={1}\n role=\"listitem\"\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {item.label}\n </Typography>\n <Typography variant=\"h5\" fontWeight={600}>\n {formatSummaryValue(item.value, item.unit)}\n </Typography>\n </Stack>\n ))}\n </Stack>\n );\n};\n"],"mappings":"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","names":["value","Box","Stack","Typography","styled","useTheme","LineChart","format","jsx","Stack","Typography","jsx","jsxs","jsx","jsxs","styled","Box","useTheme","Stack","LineChart","format","Typography"]}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
workflowChromeColors,
|
|
9
9
|
workflowConnectionColors,
|
|
10
10
|
workflowNodeColors
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WC2TCWXK.mjs";
|
|
12
12
|
|
|
13
13
|
// src/theme/spacing.ts
|
|
14
14
|
var borderRadius = {
|
|
@@ -43,6 +43,8 @@ var semantic = {
|
|
|
43
43
|
surface: {
|
|
44
44
|
default: primitives.white,
|
|
45
45
|
paper: primitives.white,
|
|
46
|
+
// Divergent near-violet #7B2CBF (rgba 123,44,191). NOT the brand violet
|
|
47
|
+
// (#aa44f2). Kept distinct in Track A; collapse deferred to Track C.
|
|
46
48
|
selected: "rgba(123, 44, 191, 0.1)",
|
|
47
49
|
hover: "rgba(0, 0, 0, 0.04)"
|
|
48
50
|
},
|
|
@@ -275,4 +277,4 @@ export {
|
|
|
275
277
|
colors,
|
|
276
278
|
theme
|
|
277
279
|
};
|
|
278
|
-
//# sourceMappingURL=chunk-
|
|
280
|
+
//# sourceMappingURL=chunk-D7D25O6E.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/theme/spacing.ts","../src/theme/surfaceVariants/webLight.ts","../src/theme/surfaceVariants/index.ts","../src/theme/index.ts","../src/theme/semantic.ts","../src/theme/components.ts"],"sourcesContent":["/**\n * Spacing and sizing tokens for the design system.\n *\n * Centralizes border-radius, component-specific sizing, and spacing\n * constants that were previously scattered across component files.\n */\n\nexport const borderRadius = {\n /** Small: alerts, compact elements */\n sm: 8,\n /** Medium: buttons, inputs, selects */\n md: 12,\n /** Large: chips, cards, global default */\n lg: 16,\n /** Extra large: hero surfaces, dialogs */\n xl: 20,\n /** Pill: fully rounded badges, on-gradient buttons */\n pill: 999,\n} as const;\n\nexport const componentSizing = {\n workflow: {\n nodeIconSize: 18,\n inspectorWidth: 320,\n },\n deployment: {\n entityIconSize: 16,\n chevronSize: 16,\n panelRadius: 12,\n },\n} as const;\n","/**\n * Surface variant: web-light.\n *\n * The marketplace + vault product palette. Both apps render on a light\n * surface; the older audit synthesis (which assumed marketplace was dark)\n * was wrong. There is no shipping dark variant today; that lands as part\n * of the dark-mode work (blocker `B5` in `DESIGN_SYSTEM_TODO.md`).\n *\n * This variant currently mirrors `webSurfaceTokens` verbatim. Future\n * work may diverge (e.g. a vault-specific accent override), at which\n * point a new named variant should be added rather than forking values\n * in app land.\n *\n * See `company-memory-bank/00-foundations/design-system.md` §4.\n */\n\nimport { webSurfaceTokens } from '../webSurfaceTokens';\n\nexport const webLight = webSurfaceTokens;\nexport type WebLightVariant = typeof webLight;\n","import { webLight } from './webLight';\n\n/**\n * Named surface variants. Consumers pick one variant per product surface\n * by importing the matching CSS layer (`@cere/cere-design-system/surfaces/<name>.css`)\n * AND optionally referencing the typed token bag here at the TS layer.\n *\n * Today there is only `webLight` (the shipped marketplace + vault\n * palette). A future `webDark` lands with the dark-mode work\n * (`DESIGN_SYSTEM_TODO.md` blocker `B5`).\n *\n * See `company-memory-bank/00-foundations/design-system.md` §4.\n */\nexport const surfaceVariants = { webLight } as const;\nexport type SurfaceVariant = keyof typeof surfaceVariants;\n\nexport { webLight };\nexport type { WebLightVariant } from './webLight';\n","/**\n * Design system theme barrel.\n *\n * Composes the MUI theme from token modules and re-exports everything\n * the public API needs. Internal structure:\n *\n * primitives.ts - Tier 1: raw color values (hue + shade)\n * semantic.ts - Tier 2: intent-based tokens\n * typography.ts - Font family and type scale\n * components.ts - MUI component style overrides\n * spacing.ts - Border radius and sizing constants\n */\n\nimport { createTheme, Theme } from '@mui/material/styles';\n// Side-effect: register custom Typography variants with MUI's type system.\nimport './typography-augment';\n\n// Token modules\nimport { primitives, deploymentEntityColors, deploymentStatusColors, workflowNodeColors, workflowConnectionColors, workflowChromeColors } from './primitives';\nimport { semantic } from './semantic';\nimport { typography } from './typography';\nimport { components } from './components';\nimport { borderRadius } from './spacing';\n\n// ---------------------------------------------------------------------------\n// Module augmentation: type-safe access to theme.palette.deployment/workflow\n// ---------------------------------------------------------------------------\ndeclare module '@mui/material/styles' {\n interface TypeBackground {\n selected: string;\n }\n interface Palette {\n deployment: {\n entity: typeof deploymentEntityColors;\n status: typeof deploymentStatusColors;\n };\n workflow: {\n node: typeof workflowNodeColors;\n connection: typeof workflowConnectionColors;\n chrome: typeof workflowChromeColors;\n };\n }\n interface PaletteOptions {\n deployment?: {\n entity?: Record<string, string>;\n status?: Record<string, string>;\n };\n workflow?: {\n node?: Partial<typeof workflowNodeColors>;\n connection?: Partial<typeof workflowConnectionColors>;\n chrome?: Partial<typeof workflowChromeColors>;\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Backwards-compatible `colors` object (same shape, derived from tokens)\n// ---------------------------------------------------------------------------\nconst colors = {\n primary: {\n main: semantic.action.primary,\n light: semantic.action.primary,\n dark: semantic.action.primaryHover,\n contrastText: semantic.text.contrast,\n },\n secondary: {\n main: primitives.neutral[600],\n light: primitives.neutral[900],\n dark: primitives.neutral[300],\n contrastText: semantic.text.contrast,\n },\n success: {\n main: semantic.feedback.success.main,\n light: semantic.feedback.success.light,\n dark: semantic.feedback.success.dark,\n contrastText: semantic.text.contrast,\n },\n error: {\n main: semantic.feedback.error.main,\n light: semantic.feedback.error.light,\n dark: semantic.feedback.error.dark,\n contrastText: semantic.text.contrast,\n },\n warning: {\n main: semantic.feedback.warning.main,\n light: semantic.feedback.warning.light,\n dark: semantic.feedback.warning.dark,\n contrastText: semantic.text.contrast,\n },\n tertiary: {\n main: semantic.feedback.warning.main,\n light: semantic.feedback.warning.light,\n dark: semantic.feedback.warning.dark,\n contrastText: primitives.nearBlack,\n },\n grey: primitives.grey,\n text: {\n primary: semantic.text.primary,\n secondary: semantic.text.secondary,\n disabled: semantic.text.disabled,\n },\n background: {\n default: semantic.surface.default,\n paper: semantic.surface.paper,\n selected: semantic.surface.selected,\n },\n};\n\n// ---------------------------------------------------------------------------\n// Theme composition\n// ---------------------------------------------------------------------------\nconst baseTheme = createTheme({\n cssVariables: true,\n palette: {\n mode: 'light',\n primary: colors.primary,\n secondary: colors.secondary,\n success: colors.success,\n error: colors.error,\n warning: colors.warning,\n grey: colors.grey,\n text: colors.text,\n background: colors.background,\n },\n typography,\n shape: {\n borderRadius: borderRadius.lg,\n },\n components,\n});\n\n// Extend palette with deployment dashboard and workflow tokens\nexport const theme: Theme = createTheme(baseTheme, {\n palette: {\n deployment: {\n entity: deploymentEntityColors,\n status: deploymentStatusColors,\n },\n workflow: {\n node: workflowNodeColors,\n connection: workflowConnectionColors,\n chrome: workflowChromeColors,\n },\n },\n});\n\n// ---------------------------------------------------------------------------\n// Public exports (preserve every name the old barrel exported)\n// ---------------------------------------------------------------------------\nexport { colors };\nexport { semantic, deploymentSurfaceTokens } from './semantic';\nexport {\n primitives,\n robPrimaryPalette,\n robPaletteExtended,\n deploymentEntityColors,\n deploymentStatusColors,\n workflowNodeColors,\n workflowConnectionColors,\n workflowChromeColors,\n deploymentSurface,\n} from './primitives';\nexport { borderRadius, componentSizing } from './spacing';\nexport { motion } from './motion';\nexport { webSurfaceTokens } from './webSurfaceTokens';\nexport type { WebSurfaceTokenKey } from './webSurfaceTokens';\nexport { surfaceVariants, webLight } from './surfaceVariants';\nexport type { SurfaceVariant, WebLightVariant } from './surfaceVariants';\n","/**\n * Tier 2: Semantic color tokens.\n *\n * Intent-based tokens that map primitives to UI roles. Components\n * should reference these (or theme.palette) instead of raw hex values.\n *\n * To change the color scheme: edit the mappings here. Zero component changes.\n */\n\nimport { primitives, deploymentSurface } from './primitives';\n\nexport const semantic = {\n action: {\n primary: primitives.violet[500],\n primaryHover: primitives.violet[600],\n disabled: primitives.grey[400],\n },\n surface: {\n default: primitives.white,\n paper: primitives.white,\n selected: 'rgba(123, 44, 191, 0.1)',\n hover: 'rgba(0, 0, 0, 0.04)',\n },\n text: {\n primary: primitives.nearBlack,\n secondary: primitives.neutral[600],\n disabled: primitives.neutral[900],\n contrast: primitives.white,\n },\n border: {\n default: primitives.grey[300],\n subtle: 'rgba(0, 0, 0, 0.05)',\n },\n feedback: {\n success: {\n main: primitives.green[500],\n light: primitives.green[400],\n dark: primitives.green[600],\n },\n error: {\n main: primitives.red[500],\n light: primitives.red[400],\n dark: primitives.red[600],\n },\n warning: {\n main: primitives.amber[500],\n light: primitives.amber[400],\n dark: primitives.amber[600],\n },\n },\n} as const;\n\n/**\n * Shared Figma surface/stroke tokens used across deployment dashboard\n * components. Referenced by semantic name rather than raw hex.\n */\nexport const deploymentSurfaceTokens = {\n /** Surface/high background (Figma #fefcff) */\n surfaceHigh: deploymentSurface.surfaceHigh,\n /** Stroke/Outside border (Figma #e6e6e6) */\n strokeOutside: deploymentSurface.strokeOutside,\n /** Default card border (Figma #cdcccd) */\n borderDefault: deploymentSurface.borderDefault,\n /** Primary text (Figma #1d1b20) */\n textPrimary: deploymentSurface.textPrimary,\n /** Secondary/muted text (Figma #818083) */\n textSecondary: deploymentSurface.textSecondary,\n /** Accent blue for workspace border, capacity bar, chevrons (Figma #5865f2) */\n accentBlue: deploymentSurface.accentBlue,\n /** Workspace card shadow */\n workspaceShadow: '0px 8px 12px rgba(26, 10, 124, 0.1)',\n /** Hover state for context menu items */\n hoverLight: deploymentSurface.hoverLight,\n /** Generic hover overlay (buttons, icon-buttons, rows) */\n hoverOverlay: 'rgba(0, 0, 0, 0.04)',\n /** Blue-50 highlight background for active menu items (Figma blue-50) */\n highlightBg: deploymentSurface.highlightBg,\n /** Blue-50 highlight background hover state */\n highlightBgHover: deploymentSurface.highlightBgHover,\n /** Blue-100 highlight border for active menu items (Figma blue-100) */\n highlightBorder: deploymentSurface.highlightBorder,\n /** Switch track enabled (Figma basic/green #53b96a) */\n switchGreen: deploymentSurface.switchGreen,\n /** Switch track disabled/off (Figma neutral track) */\n switchTrackOff: deploymentSurface.switchTrackOff,\n} as const;\n","/**\n * MUI component style overrides for the design system.\n *\n * Centralized overrides applied via createTheme({ components }).\n * Keeps the theme barrel focused on composition.\n */\n\nimport type { Components, Theme } from '@mui/material/styles';\nimport { borderRadius } from './spacing';\n\nexport const components: Components<Omit<Theme, 'components'>> = {\n MuiButton: {\n styleOverrides: {\n root: {\n textTransform: 'none',\n borderRadius: borderRadius.md,\n fontWeight: 600,\n padding: '8px 24px',\n boxShadow: 'none',\n '&:hover': {\n boxShadow: 'none',\n },\n },\n sizeSmall: {\n padding: '4px 12px',\n fontSize: '12px',\n },\n sizeMedium: {\n padding: '8px 24px',\n fontSize: '14px',\n },\n sizeLarge: {\n padding: '12px 24px',\n fontSize: '16px',\n },\n },\n },\n MuiTextField: {\n styleOverrides: {\n root: {\n '& .MuiOutlinedInput-root': {\n borderRadius: borderRadius.md,\n },\n },\n },\n },\n MuiSelect: {\n styleOverrides: {\n root: {\n borderRadius: borderRadius.md,\n },\n },\n },\n MuiChip: {\n styleOverrides: {\n root: {\n borderRadius: borderRadius.lg,\n fontWeight: 500,\n },\n },\n },\n MuiPaper: {\n styleOverrides: {\n root: {\n boxShadow: '0px 4px 20px rgba(0, 0, 0, 0.05)',\n border: '1px solid rgba(0, 0, 0, 0.05)',\n },\n },\n },\n MuiDrawer: {\n styleOverrides: {\n paper: {\n borderRight: '1px solid rgba(0, 0, 0, 0.05)',\n },\n },\n },\n MuiAlert: {\n styleOverrides: {\n root: {\n borderRadius: borderRadius.sm,\n },\n filled: {\n borderRadius: borderRadius.sm,\n },\n },\n },\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/theme/spacing.ts","../src/theme/surfaceVariants/webLight.ts","../src/theme/surfaceVariants/index.ts","../src/theme/index.ts","../src/theme/semantic.ts","../src/theme/components.ts"],"sourcesContent":["/**\n * Spacing and sizing tokens for the design system.\n *\n * Centralizes border-radius, component-specific sizing, and spacing\n * constants that were previously scattered across component files.\n */\n\nexport const borderRadius = {\n /** Small: alerts, compact elements */\n sm: 8,\n /** Medium: buttons, inputs, selects */\n md: 12,\n /** Large: chips, cards, global default */\n lg: 16,\n /** Extra large: hero surfaces, dialogs */\n xl: 20,\n /** Pill: fully rounded badges, on-gradient buttons */\n pill: 999,\n} as const;\n\nexport const componentSizing = {\n workflow: {\n nodeIconSize: 18,\n inspectorWidth: 320,\n },\n deployment: {\n entityIconSize: 16,\n chevronSize: 16,\n panelRadius: 12,\n },\n} as const;\n","/**\n * Surface variant: web-light.\n *\n * The marketplace + vault product palette. Both apps render on a light\n * surface; the older audit synthesis (which assumed marketplace was dark)\n * was wrong. There is no shipping dark variant today; that lands as part\n * of the dark-mode work (blocker `B5` in `DESIGN_SYSTEM_TODO.md`).\n *\n * This variant currently mirrors `webSurfaceTokens` verbatim. Future\n * work may diverge (e.g. a vault-specific accent override), at which\n * point a new named variant should be added rather than forking values\n * in app land.\n *\n * See `company-memory-bank/00-foundations/design-system.md` §4.\n */\n\nimport { webSurfaceTokens } from '../webSurfaceTokens';\n\nexport const webLight = webSurfaceTokens;\nexport type WebLightVariant = typeof webLight;\n","import { webLight } from './webLight';\n\n/**\n * Named surface variants. Consumers pick one variant per product surface\n * by importing the matching CSS layer (`@cere/cere-design-system/surfaces/<name>.css`)\n * AND optionally referencing the typed token bag here at the TS layer.\n *\n * Today there is only `webLight` (the shipped marketplace + vault\n * palette). A future `webDark` lands with the dark-mode work\n * (`DESIGN_SYSTEM_TODO.md` blocker `B5`).\n *\n * See `company-memory-bank/00-foundations/design-system.md` §4.\n */\nexport const surfaceVariants = { webLight } as const;\nexport type SurfaceVariant = keyof typeof surfaceVariants;\n\nexport { webLight };\nexport type { WebLightVariant } from './webLight';\n","/**\n * Design system theme barrel.\n *\n * Composes the MUI theme from token modules and re-exports everything\n * the public API needs. Internal structure:\n *\n * primitives.ts - Tier 1: raw color values (hue + shade)\n * semantic.ts - Tier 2: intent-based tokens\n * typography.ts - Font family and type scale\n * components.ts - MUI component style overrides\n * spacing.ts - Border radius and sizing constants\n */\n\nimport { createTheme, Theme } from '@mui/material/styles';\n// Side-effect: register custom Typography variants with MUI's type system.\nimport './typography-augment';\n\n// Token modules\nimport { primitives, deploymentEntityColors, deploymentStatusColors, workflowNodeColors, workflowConnectionColors, workflowChromeColors } from './primitives';\nimport { semantic } from './semantic';\nimport { typography } from './typography';\nimport { components } from './components';\nimport { borderRadius } from './spacing';\n\n// ---------------------------------------------------------------------------\n// Module augmentation: type-safe access to theme.palette.deployment/workflow\n// ---------------------------------------------------------------------------\ndeclare module '@mui/material/styles' {\n interface TypeBackground {\n selected: string;\n }\n interface Palette {\n deployment: {\n entity: typeof deploymentEntityColors;\n status: typeof deploymentStatusColors;\n };\n workflow: {\n node: typeof workflowNodeColors;\n connection: typeof workflowConnectionColors;\n chrome: typeof workflowChromeColors;\n };\n }\n interface PaletteOptions {\n deployment?: {\n entity?: Record<string, string>;\n status?: Record<string, string>;\n };\n workflow?: {\n node?: Partial<typeof workflowNodeColors>;\n connection?: Partial<typeof workflowConnectionColors>;\n chrome?: Partial<typeof workflowChromeColors>;\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Backwards-compatible `colors` object (same shape, derived from tokens)\n// ---------------------------------------------------------------------------\nconst colors = {\n primary: {\n main: semantic.action.primary,\n light: semantic.action.primary,\n dark: semantic.action.primaryHover,\n contrastText: semantic.text.contrast,\n },\n secondary: {\n main: primitives.neutral[600],\n light: primitives.neutral[900],\n dark: primitives.neutral[300],\n contrastText: semantic.text.contrast,\n },\n success: {\n main: semantic.feedback.success.main,\n light: semantic.feedback.success.light,\n dark: semantic.feedback.success.dark,\n contrastText: semantic.text.contrast,\n },\n error: {\n main: semantic.feedback.error.main,\n light: semantic.feedback.error.light,\n dark: semantic.feedback.error.dark,\n contrastText: semantic.text.contrast,\n },\n warning: {\n main: semantic.feedback.warning.main,\n light: semantic.feedback.warning.light,\n dark: semantic.feedback.warning.dark,\n contrastText: semantic.text.contrast,\n },\n tertiary: {\n main: semantic.feedback.warning.main,\n light: semantic.feedback.warning.light,\n dark: semantic.feedback.warning.dark,\n contrastText: primitives.nearBlack,\n },\n grey: primitives.grey,\n text: {\n primary: semantic.text.primary,\n secondary: semantic.text.secondary,\n disabled: semantic.text.disabled,\n },\n background: {\n default: semantic.surface.default,\n paper: semantic.surface.paper,\n selected: semantic.surface.selected,\n },\n};\n\n// ---------------------------------------------------------------------------\n// Theme composition\n// ---------------------------------------------------------------------------\nconst baseTheme = createTheme({\n cssVariables: true,\n palette: {\n mode: 'light',\n primary: colors.primary,\n secondary: colors.secondary,\n success: colors.success,\n error: colors.error,\n warning: colors.warning,\n grey: colors.grey,\n text: colors.text,\n background: colors.background,\n },\n typography,\n shape: {\n borderRadius: borderRadius.lg,\n },\n components,\n});\n\n// Extend palette with deployment dashboard and workflow tokens\nexport const theme: Theme = createTheme(baseTheme, {\n palette: {\n deployment: {\n entity: deploymentEntityColors,\n status: deploymentStatusColors,\n },\n workflow: {\n node: workflowNodeColors,\n connection: workflowConnectionColors,\n chrome: workflowChromeColors,\n },\n },\n});\n\n// ---------------------------------------------------------------------------\n// Public exports (preserve every name the old barrel exported)\n// ---------------------------------------------------------------------------\nexport { colors };\nexport { semantic, deploymentSurfaceTokens } from './semantic';\nexport {\n primitives,\n robPrimaryPalette,\n robPaletteExtended,\n deploymentEntityColors,\n deploymentStatusColors,\n workflowNodeColors,\n workflowConnectionColors,\n workflowChromeColors,\n deploymentSurface,\n} from './primitives';\nexport { borderRadius, componentSizing } from './spacing';\nexport { motion } from './motion';\nexport { webSurfaceTokens } from './webSurfaceTokens';\nexport type { WebSurfaceTokenKey } from './webSurfaceTokens';\nexport { surfaceVariants, webLight } from './surfaceVariants';\nexport type { SurfaceVariant, WebLightVariant } from './surfaceVariants';\n","/**\n * Tier 2: Semantic color tokens.\n *\n * Intent-based tokens that map primitives to UI roles. Components\n * should reference these (or theme.palette) instead of raw hex values.\n *\n * To change the color scheme: edit the mappings here. Zero component changes.\n */\n\nimport { primitives, deploymentSurface } from './primitives';\n\nexport const semantic = {\n action: {\n primary: primitives.violet[500],\n primaryHover: primitives.violet[600],\n disabled: primitives.grey[400],\n },\n surface: {\n default: primitives.white,\n paper: primitives.white,\n // Divergent near-violet #7B2CBF (rgba 123,44,191). NOT the brand violet\n // (#aa44f2). Kept distinct in Track A; collapse deferred to Track C.\n selected: 'rgba(123, 44, 191, 0.1)',\n hover: 'rgba(0, 0, 0, 0.04)',\n },\n text: {\n primary: primitives.nearBlack,\n secondary: primitives.neutral[600],\n disabled: primitives.neutral[900],\n contrast: primitives.white,\n },\n border: {\n default: primitives.grey[300],\n subtle: 'rgba(0, 0, 0, 0.05)',\n },\n feedback: {\n success: {\n main: primitives.green[500],\n light: primitives.green[400],\n dark: primitives.green[600],\n },\n error: {\n main: primitives.red[500],\n light: primitives.red[400],\n dark: primitives.red[600],\n },\n warning: {\n main: primitives.amber[500],\n light: primitives.amber[400],\n dark: primitives.amber[600],\n },\n },\n} as const;\n\n/**\n * Shared Figma surface/stroke tokens used across deployment dashboard\n * components. Referenced by semantic name rather than raw hex.\n */\nexport const deploymentSurfaceTokens = {\n /** Surface/high background (Figma #fefcff) */\n surfaceHigh: deploymentSurface.surfaceHigh,\n /** Stroke/Outside border (Figma #e6e6e6) */\n strokeOutside: deploymentSurface.strokeOutside,\n /** Default card border (Figma #cdcccd) */\n borderDefault: deploymentSurface.borderDefault,\n /** Primary text (Figma #1d1b20) */\n textPrimary: deploymentSurface.textPrimary,\n /** Secondary/muted text (Figma #818083) */\n textSecondary: deploymentSurface.textSecondary,\n /** Accent blue for workspace border, capacity bar, chevrons (Figma #5865f2) */\n accentBlue: deploymentSurface.accentBlue,\n /** Workspace card shadow */\n workspaceShadow: '0px 8px 12px rgba(26, 10, 124, 0.1)',\n /** Hover state for context menu items */\n hoverLight: deploymentSurface.hoverLight,\n /** Generic hover overlay (buttons, icon-buttons, rows) */\n hoverOverlay: 'rgba(0, 0, 0, 0.04)',\n /** Blue-50 highlight background for active menu items (Figma blue-50) */\n highlightBg: deploymentSurface.highlightBg,\n /** Blue-50 highlight background hover state */\n highlightBgHover: deploymentSurface.highlightBgHover,\n /** Blue-100 highlight border for active menu items (Figma blue-100) */\n highlightBorder: deploymentSurface.highlightBorder,\n /** Switch track enabled (Figma basic/green #53b96a) */\n switchGreen: deploymentSurface.switchGreen,\n /** Switch track disabled/off (Figma neutral track) */\n switchTrackOff: deploymentSurface.switchTrackOff,\n} as const;\n","/**\n * MUI component style overrides for the design system.\n *\n * Centralized overrides applied via createTheme({ components }).\n * Keeps the theme barrel focused on composition.\n */\n\nimport type { Components, Theme } from '@mui/material/styles';\nimport { borderRadius } from './spacing';\n\nexport const components: Components<Omit<Theme, 'components'>> = {\n MuiButton: {\n styleOverrides: {\n root: {\n textTransform: 'none',\n borderRadius: borderRadius.md,\n fontWeight: 600,\n padding: '8px 24px',\n boxShadow: 'none',\n '&:hover': {\n boxShadow: 'none',\n },\n },\n sizeSmall: {\n padding: '4px 12px',\n fontSize: '12px',\n },\n sizeMedium: {\n padding: '8px 24px',\n fontSize: '14px',\n },\n sizeLarge: {\n padding: '12px 24px',\n fontSize: '16px',\n },\n },\n },\n MuiTextField: {\n styleOverrides: {\n root: {\n '& .MuiOutlinedInput-root': {\n borderRadius: borderRadius.md,\n },\n },\n },\n },\n MuiSelect: {\n styleOverrides: {\n root: {\n borderRadius: borderRadius.md,\n },\n },\n },\n MuiChip: {\n styleOverrides: {\n root: {\n borderRadius: borderRadius.lg,\n fontWeight: 500,\n },\n },\n },\n MuiPaper: {\n styleOverrides: {\n root: {\n boxShadow: '0px 4px 20px rgba(0, 0, 0, 0.05)',\n border: '1px solid rgba(0, 0, 0, 0.05)',\n },\n },\n },\n MuiDrawer: {\n styleOverrides: {\n paper: {\n borderRight: '1px solid rgba(0, 0, 0, 0.05)',\n },\n },\n },\n MuiAlert: {\n styleOverrides: {\n root: {\n borderRadius: borderRadius.sm,\n },\n filled: {\n borderRadius: borderRadius.sm,\n },\n },\n },\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploymentSurfaceTokens
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-D7D25O6E.mjs";
|
|
4
4
|
|
|
5
5
|
// src/components/feedback/RoleBadge.tsx
|
|
6
6
|
import MuiChip from "@mui/material/Chip";
|
|
@@ -159,4 +159,4 @@ export {
|
|
|
159
159
|
RoleBadge,
|
|
160
160
|
IDBlock
|
|
161
161
|
};
|
|
162
|
-
//# sourceMappingURL=chunk-
|
|
162
|
+
//# sourceMappingURL=chunk-DRGMEIPT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/feedback/RoleBadge.tsx","../src/components/feedback/IDBlock.tsx"],"sourcesContent":["import React from 'react';\nimport MuiChip, { ChipProps as MuiChipProps } from '@mui/material/Chip';\nimport { styled } from '@mui/material/styles';\n\n/**\n * Color variants for the RoleBadge component\n */\nexport type RoleBadgeColor = 'primary' | 'secondary' | 'success' | 'error' | 'warning';\n\n/**\n * Size variants for the RoleBadge component\n */\nexport type RoleBadgeSize = 'small' | 'medium';\n\n/**\n * RoleBadge component props\n */\nexport interface RoleBadgeProps extends Omit<MuiChipProps, 'label' | 'variant' | 'color' | 'size'> {\n /**\n * The text content to display in the badge\n */\n label: string;\n /**\n * The color theme of the badge\n * @default 'primary'\n */\n color?: RoleBadgeColor;\n /**\n * The size of the badge\n * @default 'small'\n */\n size?: RoleBadgeSize;\n}\n\n/**\n * Styled MUI Chip with pill shape and outlined style\n * Matches Figma node 17-3595 specifications\n */\nconst StyledRoleBadge = styled(MuiChip)<MuiChipProps>(() => ({\n // Pill shape - 100px border radius\n borderRadius: '100px',\n // Typography specifications from Figma\n fontSize: '13px',\n fontWeight: 400,\n lineHeight: '18px',\n letterSpacing: '0.16px',\n // Padding specifications from Figma\n padding: '3px 4px',\n height: 'auto',\n // Outlined style (no background fill)\n '& .MuiChip-label': {\n padding: '0 8px',\n },\n}));\n\n/**\n * RoleBadge - Pill-shaped badge component for displaying roles or status labels\n *\n * A reusable badge component that extends MUI Chip with a pill-shaped outline style.\n * Designed for displaying user roles, status indicators, or categorization labels.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <RoleBadge label=\"Manager\" />\n *\n * // With color variants\n * <RoleBadge label=\"Admin\" color=\"error\" />\n * <RoleBadge label=\"Active\" color=\"success\" />\n *\n * // With size variants\n * <RoleBadge label=\"Owner\" size=\"medium\" />\n * ```\n *\n * @see Figma node 17-3595 for design specifications\n */\nexport const RoleBadge: React.FC<RoleBadgeProps> = ({\n label,\n color = 'primary',\n size = 'small',\n ...props\n}) => {\n if (!label || label.trim() === '') {\n return null;\n }\n\n return (\n <StyledRoleBadge\n label={label}\n variant=\"outlined\"\n color={color}\n size={size}\n {...props}\n />\n );\n};\n","import React, { useState } from 'react';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport IconButton from '@mui/material/IconButton';\nimport Snackbar from '@mui/material/Snackbar';\nimport Alert from '@mui/material/Alert';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport { styled } from '@mui/material/styles';\nimport type { AlertColor } from '@mui/material/Alert';\nimport { deploymentSurfaceTokens } from '../../theme';\n\n/**\n * IDBlock component props\n */\nexport interface IDBlockProps {\n /**\n * The identifier value to display and copy\n */\n id: string;\n /**\n * Label prefix text\n * @default 'ID'\n */\n label?: string;\n /**\n * Entity type for accessibility (used in aria-label)\n * @default 'entity'\n */\n entityType?: string;\n /**\n * Additional callback to execute after successful copy\n */\n onCopy?: () => void;\n}\n\n/**\n * Styled container for the ID block\n * Matches Figma node 17-3596 specifications\n */\nconst IDContainer = styled(Box)(() => ({\n display: 'inline-flex',\n alignItems: 'center',\n gap: '4px',\n padding: '8px 16px',\n backgroundColor: deploymentSurfaceTokens.surfaceHigh,\n border: `1px solid ${deploymentSurfaceTokens.strokeOutside}`,\n borderRadius: '8px',\n}));\n\n/**\n * IDBlock - Read-only identifier display with integrated copy-to-clipboard button\n *\n * A component that displays an identifier (ID, account number, etc.) with a copy button.\n * Provides user feedback via an inline Snackbar when copy succeeds or fails.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <IDBlock id=\"W1234567890\" />\n *\n * // With custom label\n * <IDBlock id=\"ACC-9876543\" label=\"Account ID\" entityType=\"account\" />\n *\n * // With callback\n * <IDBlock\n * id=\"DEPLOY-12345\"\n * label=\"Deployment ID\"\n * entityType=\"deployment\"\n * onCopy={() => console.log('ID copied')}\n * />\n * ```\n *\n * @see Figma node 17-3596 for design specifications\n */\nexport const IDBlock: React.FC<IDBlockProps> = ({\n id,\n label = 'ID',\n entityType = 'entity',\n onCopy,\n}) => {\n const [snackbar, setSnackbar] = useState<{ open: boolean; message: string; severity: AlertColor }>({\n open: false,\n message: '',\n severity: 'success',\n });\n\n if (!id || id.trim() === '') {\n return null;\n }\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(id);\n setSnackbar({ open: true, message: 'ID copied to clipboard', severity: 'success' });\n onCopy?.();\n } catch {\n setSnackbar({ open: true, message: 'Failed to copy ID', severity: 'error' });\n }\n };\n\n const handleSnackbarClose = () => {\n setSnackbar((prev) => ({ ...prev, open: false }));\n };\n\n return (\n <>\n <IDContainer>\n <Typography\n variant=\"body2\"\n sx={{\n fontSize: '13px',\n fontWeight: 500,\n color: deploymentSurfaceTokens.textSecondary,\n }}\n >\n {label}:\n </Typography>\n <Typography\n variant=\"body2\"\n sx={{\n fontSize: '13px',\n fontWeight: 500,\n color: deploymentSurfaceTokens.textPrimary,\n userSelect: 'all',\n }}\n >\n {id}\n </Typography>\n <IconButton\n onClick={handleCopy}\n size=\"small\"\n aria-label={`Copy ${entityType} ID ${id}`}\n sx={{\n padding: '4px',\n '&:hover': {\n backgroundColor: deploymentSurfaceTokens.hoverOverlay,\n },\n }}\n >\n <ContentCopyIcon\n sx={{\n fontSize: '16px',\n color: deploymentSurfaceTokens.textSecondary,\n }}\n />\n </IconButton>\n </IDContainer>\n <Snackbar\n open={snackbar.open}\n autoHideDuration={3000}\n onClose={handleSnackbarClose}\n anchorOrigin={{ vertical: 'top', horizontal: 'center' }}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbar.severity}>\n {snackbar.message}\n </Alert>\n </Snackbar>\n </>\n );\n};\n"],"mappings":"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","names":["styled","jsx","styled"]}
|