@sckyzo/cosmos-charts 0.2.0 → 0.3.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.
Files changed (166) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +107 -22
  3. package/THIRD_PARTY_NOTICES.md +81 -0
  4. package/dist/BarChart.cjs +137 -0
  5. package/dist/BarChart.cjs.map +1 -0
  6. package/dist/BarChart.js +135 -0
  7. package/dist/BarChart.js.map +1 -0
  8. package/dist/BoxPlotChart.cjs +214 -0
  9. package/dist/BoxPlotChart.cjs.map +1 -0
  10. package/dist/BoxPlotChart.js +212 -0
  11. package/dist/BoxPlotChart.js.map +1 -0
  12. package/dist/BumpChart.cjs +328 -0
  13. package/dist/BumpChart.cjs.map +1 -0
  14. package/dist/BumpChart.js +326 -0
  15. package/dist/BumpChart.js.map +1 -0
  16. package/dist/CalendarChart.cjs +216 -0
  17. package/dist/CalendarChart.cjs.map +1 -0
  18. package/dist/CalendarChart.js +214 -0
  19. package/dist/CalendarChart.js.map +1 -0
  20. package/dist/DonutChart.cjs +122 -0
  21. package/dist/DonutChart.cjs.map +1 -0
  22. package/dist/DonutChart.js +120 -0
  23. package/dist/DonutChart.js.map +1 -0
  24. package/dist/FunnelChart.cjs +422 -0
  25. package/dist/FunnelChart.cjs.map +1 -0
  26. package/dist/FunnelChart.js +420 -0
  27. package/dist/FunnelChart.js.map +1 -0
  28. package/dist/GradientRadial.cjs +51 -0
  29. package/dist/GradientRadial.cjs.map +1 -0
  30. package/dist/GradientRadial.js +49 -0
  31. package/dist/GradientRadial.js.map +1 -0
  32. package/dist/HeatmapChart.cjs +146 -0
  33. package/dist/HeatmapChart.cjs.map +1 -0
  34. package/dist/HeatmapChart.js +144 -0
  35. package/dist/HeatmapChart.js.map +1 -0
  36. package/dist/LineAreaChart.cjs +98 -0
  37. package/dist/LineAreaChart.cjs.map +1 -0
  38. package/dist/LineAreaChart.js +96 -0
  39. package/dist/LineAreaChart.js.map +1 -0
  40. package/dist/MixedChart.cjs +195 -0
  41. package/dist/MixedChart.cjs.map +1 -0
  42. package/dist/MixedChart.js +193 -0
  43. package/dist/MixedChart.js.map +1 -0
  44. package/dist/RadarChart.cjs +109 -0
  45. package/dist/RadarChart.cjs.map +1 -0
  46. package/dist/RadarChart.js +107 -0
  47. package/dist/RadarChart.js.map +1 -0
  48. package/dist/RadialBarChart.cjs +99 -0
  49. package/dist/RadialBarChart.cjs.map +1 -0
  50. package/dist/RadialBarChart.js +97 -0
  51. package/dist/RadialBarChart.js.map +1 -0
  52. package/dist/RangeBarChart.cjs +218 -0
  53. package/dist/RangeBarChart.cjs.map +1 -0
  54. package/dist/RangeBarChart.js +216 -0
  55. package/dist/RangeBarChart.js.map +1 -0
  56. package/dist/RealtimeChart.cjs +173 -0
  57. package/dist/RealtimeChart.cjs.map +1 -0
  58. package/dist/RealtimeChart.js +171 -0
  59. package/dist/RealtimeChart.js.map +1 -0
  60. package/dist/ScatterChart.cjs +134 -0
  61. package/dist/ScatterChart.cjs.map +1 -0
  62. package/dist/ScatterChart.js +131 -0
  63. package/dist/ScatterChart.js.map +1 -0
  64. package/dist/SemiCircleGauge.cjs +142 -0
  65. package/dist/SemiCircleGauge.cjs.map +1 -0
  66. package/dist/SemiCircleGauge.js +140 -0
  67. package/dist/SemiCircleGauge.js.map +1 -0
  68. package/dist/Sparkline.cjs +117 -0
  69. package/dist/Sparkline.cjs.map +1 -0
  70. package/dist/Sparkline.js +115 -0
  71. package/dist/Sparkline.js.map +1 -0
  72. package/dist/StrokedGauge.cjs +94 -0
  73. package/dist/StrokedGauge.cjs.map +1 -0
  74. package/dist/StrokedGauge.js +92 -0
  75. package/dist/StrokedGauge.js.map +1 -0
  76. package/dist/TreemapChart.cjs +263 -0
  77. package/dist/TreemapChart.cjs.map +1 -0
  78. package/dist/TreemapChart.js +261 -0
  79. package/dist/TreemapChart.js.map +1 -0
  80. package/dist/WaterfallChart.cjs +235 -0
  81. package/dist/WaterfallChart.cjs.map +1 -0
  82. package/dist/WaterfallChart.js +233 -0
  83. package/dist/WaterfallChart.js.map +1 -0
  84. package/dist/WorldMap.cjs +2088 -0
  85. package/dist/WorldMap.cjs.map +1 -0
  86. package/dist/WorldMap.js +603 -0
  87. package/dist/WorldMap.js.map +1 -0
  88. package/dist/chunk-3N43QT36.js +60 -0
  89. package/dist/chunk-3N43QT36.js.map +1 -0
  90. package/dist/chunk-5C2RLJYZ.js +11 -0
  91. package/dist/chunk-5C2RLJYZ.js.map +1 -0
  92. package/dist/chunk-6ALKZLN2.js +127 -0
  93. package/dist/chunk-6ALKZLN2.js.map +1 -0
  94. package/dist/chunk-6BKLL7LZ.cjs +30 -0
  95. package/dist/chunk-6BKLL7LZ.cjs.map +1 -0
  96. package/dist/chunk-6NRRABPF.cjs +64 -0
  97. package/dist/chunk-6NRRABPF.cjs.map +1 -0
  98. package/dist/chunk-AAYHG7YK.cjs +30 -0
  99. package/dist/chunk-AAYHG7YK.cjs.map +1 -0
  100. package/dist/chunk-AOSO5QHL.js +19 -0
  101. package/dist/chunk-AOSO5QHL.js.map +1 -0
  102. package/dist/chunk-BFEDLXVW.js +12 -0
  103. package/dist/chunk-BFEDLXVW.js.map +1 -0
  104. package/dist/chunk-DBZQI4HM.cjs +14 -0
  105. package/dist/chunk-DBZQI4HM.cjs.map +1 -0
  106. package/dist/chunk-F2PMFYJ5.cjs +40 -0
  107. package/dist/chunk-F2PMFYJ5.cjs.map +1 -0
  108. package/dist/chunk-FUZW3H5X.js +38 -0
  109. package/dist/chunk-FUZW3H5X.js.map +1 -0
  110. package/dist/chunk-GDZLYYL2.js +27 -0
  111. package/dist/chunk-GDZLYYL2.js.map +1 -0
  112. package/dist/chunk-GVTMZYOM.cjs +30 -0
  113. package/dist/chunk-GVTMZYOM.cjs.map +1 -0
  114. package/dist/chunk-GZRMVE4X.cjs +131 -0
  115. package/dist/chunk-GZRMVE4X.cjs.map +1 -0
  116. package/dist/chunk-HMH6DI7U.js +27 -0
  117. package/dist/chunk-HMH6DI7U.js.map +1 -0
  118. package/dist/chunk-ICL5K2CW.js +280 -0
  119. package/dist/chunk-ICL5K2CW.js.map +1 -0
  120. package/dist/chunk-IW6EWB26.cjs +21 -0
  121. package/dist/chunk-IW6EWB26.cjs.map +1 -0
  122. package/dist/chunk-K3R7JGOW.cjs +18 -0
  123. package/dist/chunk-K3R7JGOW.cjs.map +1 -0
  124. package/dist/chunk-LT3UC65O.cjs +68 -0
  125. package/dist/chunk-LT3UC65O.cjs.map +1 -0
  126. package/dist/chunk-MN4CDVOS.cjs +63 -0
  127. package/dist/chunk-MN4CDVOS.cjs.map +1 -0
  128. package/dist/chunk-OCD6JIIX.js +23 -0
  129. package/dist/chunk-OCD6JIIX.js.map +1 -0
  130. package/dist/chunk-RILUG7JB.js +44 -0
  131. package/dist/chunk-RILUG7JB.js.map +1 -0
  132. package/dist/chunk-RLHGPHC7.cjs +51 -0
  133. package/dist/chunk-RLHGPHC7.cjs.map +1 -0
  134. package/dist/chunk-SGG7XKOY.js +58 -0
  135. package/dist/chunk-SGG7XKOY.js.map +1 -0
  136. package/dist/chunk-T3K6Q34U.cjs +82 -0
  137. package/dist/chunk-T3K6Q34U.cjs.map +1 -0
  138. package/dist/chunk-TPH5T3DA.cjs +282 -0
  139. package/dist/chunk-TPH5T3DA.cjs.map +1 -0
  140. package/dist/chunk-TYQWZR3S.cjs +13 -0
  141. package/dist/chunk-TYQWZR3S.cjs.map +1 -0
  142. package/dist/chunk-UATB2IRY.js +51 -0
  143. package/dist/chunk-UATB2IRY.js.map +1 -0
  144. package/dist/chunk-UJIV5PVI.js +13 -0
  145. package/dist/chunk-UJIV5PVI.js.map +1 -0
  146. package/dist/chunk-URNXLVSK.js +44 -0
  147. package/dist/chunk-URNXLVSK.js.map +1 -0
  148. package/dist/chunk-VIOSQN4Z.js +79 -0
  149. package/dist/chunk-VIOSQN4Z.js.map +1 -0
  150. package/dist/chunk-X3YZP5WF.cjs +46 -0
  151. package/dist/chunk-X3YZP5WF.cjs.map +1 -0
  152. package/dist/chunk-YWYF5CCJ.js +61 -0
  153. package/dist/chunk-YWYF5CCJ.js.map +1 -0
  154. package/dist/chunk-Z4LZFMDH.cjs +60 -0
  155. package/dist/chunk-Z4LZFMDH.cjs.map +1 -0
  156. package/dist/index.cjs +154 -1166
  157. package/dist/index.cjs.map +1 -1
  158. package/dist/index.d.cts +470 -80
  159. package/dist/index.d.ts +470 -80
  160. package/dist/index.js +23 -1144
  161. package/dist/index.js.map +1 -1
  162. package/dist/theme.cjs +88 -0
  163. package/dist/theme.cjs.map +1 -0
  164. package/dist/theme.js +84 -0
  165. package/dist/theme.js.map +1 -0
  166. package/package.json +23 -12
@@ -0,0 +1,216 @@
1
+ "use client";
2
+ import { useCategoryKeys } from './chunk-FUZW3H5X.js';
3
+ import { referenceMarks } from './chunk-SGG7XKOY.js';
4
+ import { useHiddenSeries, legendProps, ChartLegend } from './chunk-6ALKZLN2.js';
5
+ import { ANIMATION } from './chunk-5C2RLJYZ.js';
6
+ import { useAxis, xAxisTitle, yAxisTitle } from './chunk-RILUG7JB.js';
7
+ import { TooltipCard } from './chunk-VIOSQN4Z.js';
8
+ import { hasNoData, seriesKey } from './chunk-UJIV5PVI.js';
9
+ import { ChartEmpty, frameProps } from './chunk-3N43QT36.js';
10
+ import { GRID, BORDER, seriesColor } from './chunk-UATB2IRY.js';
11
+ import { BarChart, CartesianGrid, XAxis, YAxis, Legend, Tooltip, Bar } from 'recharts';
12
+ import { jsx, jsxs } from 'react/jsx-runtime';
13
+
14
+ var UTC_DATE_TIME = new Intl.DateTimeFormat("en-GB", {
15
+ day: "2-digit",
16
+ month: "short",
17
+ hour: "2-digit",
18
+ minute: "2-digit",
19
+ hourCycle: "h23",
20
+ timeZone: "UTC"
21
+ });
22
+ var UTC_DAY = new Intl.DateTimeFormat("en-GB", {
23
+ day: "2-digit",
24
+ month: "short",
25
+ timeZone: "UTC"
26
+ });
27
+ var UTC_TIME = new Intl.DateTimeFormat("en-GB", {
28
+ hour: "2-digit",
29
+ minute: "2-digit",
30
+ hourCycle: "h23",
31
+ timeZone: "UTC"
32
+ });
33
+ var defaultFormatDate = (timestamp) => UTC_DATE_TIME.format(timestamp);
34
+ var HOUR = 36e5;
35
+ var DAY = 24 * HOUR;
36
+ var STEPS = [HOUR, 2 * HOUR, 3 * HOUR, 6 * HOUR, 12 * HOUR, DAY, 2 * DAY, 7 * DAY, 30 * DAY];
37
+ var timeTicks = (min, max) => {
38
+ const step = STEPS.find((s) => (max - min) / s <= 8) ?? STEPS[STEPS.length - 1];
39
+ const first = Math.floor(min / step) * step;
40
+ const last = Math.max(Math.ceil(max / step) * step, first + step);
41
+ return Array.from({ length: Math.round((last - first) / step) + 1 }, (_, i) => first + i * step);
42
+ };
43
+ var tickLabel = (timestamp) => timestamp % DAY === 0 ? UTC_DAY.format(timestamp) : UTC_TIME.format(timestamp);
44
+ var GROUP_KEY = "all";
45
+ var rangesShape = (key, colors, visible) => (props) => {
46
+ const { x, y, width, height } = props;
47
+ const row = props.payload;
48
+ const bounds = row[key];
49
+ if (!bounds) return null;
50
+ const [low, high] = bounds;
51
+ const span = high - low || 1;
52
+ const lane = Math.abs(height);
53
+ const top = Math.min(y, y + height);
54
+ return /* @__PURE__ */ jsx("g", { children: row.ranges.filter((r) => visible(r.series) && (key === GROUP_KEY || key === seriesKey(r.series))).map((r, i) => /* @__PURE__ */ jsx(
55
+ "rect",
56
+ {
57
+ x: x + (r.start - low) / span * width,
58
+ y: top,
59
+ width: Math.max((r.end - r.start) / span * width, 2),
60
+ height: lane,
61
+ rx: 3,
62
+ fill: colors(r.series)
63
+ },
64
+ i
65
+ )) });
66
+ };
67
+ var SeriesLegend = ({
68
+ entries,
69
+ hidden,
70
+ onToggle,
71
+ column
72
+ }) => /* @__PURE__ */ jsx(ChartLegend, { payload: entries, hidden, onToggle, column });
73
+ var RangeBarChart = ({
74
+ series,
75
+ groupRows = false,
76
+ colors,
77
+ formatDate = defaultFormatDate,
78
+ xTitle,
79
+ yTitle,
80
+ referenceLines,
81
+ referenceBands,
82
+ showLegend,
83
+ legendPosition = "top",
84
+ emptyMessage = "No data",
85
+ ariaLabel,
86
+ children,
87
+ height = 320,
88
+ width
89
+ }) => {
90
+ const hidden = useHiddenSeries();
91
+ const axis = useAxis();
92
+ const categoryKeys = useCategoryKeys("vertical");
93
+ const name = ariaLabel ?? `Range chart: ${series.map((s) => s.name).join(", ")}`;
94
+ if (hasNoData(series)) {
95
+ return /* @__PURE__ */ jsx(ChartEmpty, { message: emptyMessage, ariaLabel: name, height, width });
96
+ }
97
+ const categories = [...new Set(series.flatMap((s) => s.data.map((p) => p.x)))];
98
+ const all = series.flatMap((s) => s.data.flatMap((p) => p.y));
99
+ const ticks = timeTicks(Math.min(...all), Math.max(...all));
100
+ const color = (index) => seriesColor(index, colors);
101
+ const visible = (index) => !hidden.hidden.has(seriesKey(index));
102
+ const rows = categories.map((category) => {
103
+ const ranges = series.flatMap(
104
+ (s, index) => s.data.filter((p) => p.x === category).map((p) => ({ series: index, start: p.y[0], end: p.y[1] }))
105
+ );
106
+ const bounds = (of) => of.length > 0 ? [Math.min(...of.map((r) => r.start)), Math.max(...of.map((r) => r.end))] : void 0;
107
+ return {
108
+ category,
109
+ ranges,
110
+ [GROUP_KEY]: bounds(ranges),
111
+ ...Object.fromEntries(
112
+ series.map((_, index) => [
113
+ seriesKey(index),
114
+ bounds(ranges.filter((r) => r.series === index))
115
+ ])
116
+ )
117
+ };
118
+ });
119
+ const tooltip = ({ active, payload, label }) => {
120
+ const row = payload?.[0]?.payload;
121
+ if (!active || !row) return null;
122
+ return /* @__PURE__ */ jsx(
123
+ TooltipCard,
124
+ {
125
+ title: label,
126
+ rows: row.ranges.filter((r) => visible(r.series)).map((r) => ({
127
+ name: series[r.series].name,
128
+ value: `${formatDate(r.start)} \u2013 ${formatDate(r.end)}`,
129
+ color: color(r.series)
130
+ }))
131
+ }
132
+ );
133
+ };
134
+ return /* @__PURE__ */ jsxs(
135
+ BarChart,
136
+ {
137
+ ref: categoryKeys,
138
+ ...frameProps({ height, width, ariaLabel: name }),
139
+ data: rows,
140
+ layout: "vertical",
141
+ margin: { top: 4, right: 16, bottom: 0, left: 0 },
142
+ barGap: 2,
143
+ barCategoryGap: "20%",
144
+ children: [
145
+ /* @__PURE__ */ jsx(CartesianGrid, { stroke: GRID, strokeDasharray: "4 4" }),
146
+ /* @__PURE__ */ jsx(
147
+ XAxis,
148
+ {
149
+ type: "number",
150
+ domain: [ticks[0], ticks[ticks.length - 1]],
151
+ ticks,
152
+ tickFormatter: tickLabel,
153
+ ...axis,
154
+ ...xAxisTitle(xTitle)
155
+ }
156
+ ),
157
+ /* @__PURE__ */ jsx(YAxis, { type: "category", dataKey: "category", width: "auto", ...axis, ...yAxisTitle(yTitle) }),
158
+ (showLegend ?? series.length > 1) && /* @__PURE__ */ jsx(
159
+ Legend,
160
+ {
161
+ ...legendProps(legendPosition, hidden),
162
+ content: /* @__PURE__ */ jsx(
163
+ SeriesLegend,
164
+ {
165
+ entries: series.map((s, index) => ({
166
+ value: s.name,
167
+ type: "circle",
168
+ color: color(index),
169
+ dataKey: seriesKey(index)
170
+ })),
171
+ hidden: hidden.hidden,
172
+ onToggle: hidden.toggle,
173
+ column: legendPosition === "left" || legendPosition === "right"
174
+ }
175
+ )
176
+ }
177
+ ),
178
+ /* @__PURE__ */ jsx(
179
+ Tooltip,
180
+ {
181
+ content: tooltip,
182
+ cursor: { fill: BORDER, fillOpacity: 0.35, radius: 8 },
183
+ animationDuration: 150
184
+ }
185
+ ),
186
+ groupRows ? /* @__PURE__ */ jsx(
187
+ Bar,
188
+ {
189
+ name: "Ranges",
190
+ dataKey: GROUP_KEY,
191
+ maxBarSize: 32,
192
+ shape: rangesShape(GROUP_KEY, color, visible),
193
+ ...ANIMATION
194
+ }
195
+ ) : series.map((s, index) => /* @__PURE__ */ jsx(
196
+ Bar,
197
+ {
198
+ name: s.name,
199
+ dataKey: seriesKey(index),
200
+ maxBarSize: 28,
201
+ shape: rangesShape(seriesKey(index), color, visible),
202
+ hide: !visible(index),
203
+ ...ANIMATION
204
+ },
205
+ seriesKey(index)
206
+ )),
207
+ referenceMarks({ referenceLines, referenceBands, axis: "x" }),
208
+ children
209
+ ]
210
+ }
211
+ );
212
+ };
213
+
214
+ export { RangeBarChart };
215
+ //# sourceMappingURL=RangeBarChart.js.map
216
+ //# sourceMappingURL=RangeBarChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/RangeBarChart.tsx"],"names":[],"mappings":"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","file":"RangeBarChart.js","sourcesContent":["import type { ComponentProps } from 'react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Tooltip,\n XAxis,\n YAxis,\n type BarShapeProps,\n type LegendPayload,\n type TooltipContentProps,\n} from 'recharts';\nimport { ANIMATION } from './core/animation';\nimport { useAxis, xAxisTitle, yAxisTitle } from './core/axes';\nimport { useCategoryKeys } from './core/categoryKeys';\nimport { TooltipCard } from './core/ChartTooltip';\nimport { ChartLegend, legendProps, useHiddenSeries } from './core/ChartLegend';\nimport { BORDER, GRID, seriesColor } from './core/colors';\nimport { hasNoData, seriesKey } from './core/data';\nimport { ChartEmpty, frameProps } from './core/frame';\nimport { referenceMarks } from './core/reference';\nimport type {\n ChartAxisTitleProps,\n ChartEmptyProps,\n ChartLegendProps,\n ChartProps,\n ChartReferenceProps,\n} from './types';\n\nexport type RangeBarPoint = {\n /** Row label: the service, rack or host the range belongs to. */\n x: string;\n /** Start and end, as timestamps in milliseconds. */\n y: [number, number];\n};\n\nexport type RangeBarChartProps = ChartProps &\n ChartEmptyProps &\n ChartLegendProps &\n ChartAxisTitleProps &\n ChartReferenceProps & {\n /** One series per kind of range (maintenance, deploy, incident…), drawn on a time axis. */\n series: { name: string; data: RangeBarPoint[] }[];\n /** Draw every series of a row on one lane, instead of one lane per series. */\n groupRows?: boolean;\n /** Override the default Cosmos palette. */\n colors?: string[];\n /** Format the start and end times in the tooltip. Default: `14 Oct, 02:00`, in UTC like the axis. */\n formatDate?: (timestamp: number) => string;\n /** Show the legend (auto-true when 2+ series). */\n showLegend?: boolean;\n };\n\n// The axis labels are UTC, so the default tooltip is too.\nconst UTC_DATE_TIME = new Intl.DateTimeFormat('en-GB', {\n day: '2-digit',\n month: 'short',\n hour: '2-digit',\n minute: '2-digit',\n hourCycle: 'h23',\n timeZone: 'UTC',\n});\nconst UTC_DAY = new Intl.DateTimeFormat('en-GB', {\n day: '2-digit',\n month: 'short',\n timeZone: 'UTC',\n});\nconst UTC_TIME = new Intl.DateTimeFormat('en-GB', {\n hour: '2-digit',\n minute: '2-digit',\n hourCycle: 'h23',\n timeZone: 'UTC',\n});\n\nconst defaultFormatDate = (timestamp: number) => UTC_DATE_TIME.format(timestamp);\n\nconst HOUR = 3_600_000;\nconst DAY = 24 * HOUR;\nconst STEPS = [HOUR, 2 * HOUR, 3 * HOUR, 6 * HOUR, 12 * HOUR, DAY, 2 * DAY, 7 * DAY, 30 * DAY];\n\n/** Round UTC ticks that cover `[min, max]`: the first step that leaves at most eight of them. */\nconst timeTicks = (min: number, max: number) => {\n const step = STEPS.find((s) => (max - min) / s <= 8) ?? STEPS[STEPS.length - 1];\n const first = Math.floor(min / step) * step;\n const last = Math.max(Math.ceil(max / step) * step, first + step);\n return Array.from({ length: Math.round((last - first) / step) + 1 }, (_, i) => first + i * step);\n};\n\n/** A tick label: the day at midnight, the time otherwise. */\nconst tickLabel = (timestamp: number) =>\n timestamp % DAY === 0 ? UTC_DAY.format(timestamp) : UTC_TIME.format(timestamp);\n\ntype Range = { series: number; start: number; end: number };\ntype Row = { category: string; ranges: Range[] } & Record<string, unknown>;\n\nconst GROUP_KEY = 'all';\n\n// A bar's value is the span from the first start to the last end of what it\n// draws in a row, so Recharts sizes and places it; the ranges inside are drawn\n// by the shape, at the same scale.\nconst rangesShape =\n (key: string, colors: (series: number) => string, visible: (series: number) => boolean) =>\n (props: BarShapeProps) => {\n const { x, y, width, height } = props;\n const row = props.payload as Row;\n const bounds = row[key] as [number, number] | undefined;\n if (!bounds) return null;\n const [low, high] = bounds;\n const span = high - low || 1;\n const lane = Math.abs(height);\n const top = Math.min(y, y + height);\n return (\n <g>\n {row.ranges\n .filter((r) => visible(r.series) && (key === GROUP_KEY || key === seriesKey(r.series)))\n .map((r, i) => (\n <rect\n key={i}\n x={x + ((r.start - low) / span) * width}\n y={top}\n width={Math.max(((r.end - r.start) / span) * width, 2)}\n height={lane}\n rx={3}\n fill={colors(r.series)}\n />\n ))}\n </g>\n );\n };\n\n// One legend entry per series, whichever way the bars are drawn: Recharts' own\n// entries (one per bar) are left aside.\nconst SeriesLegend = ({\n entries,\n hidden,\n onToggle,\n column,\n}: { entries: LegendPayload[] } & Omit<ComponentProps<typeof ChartLegend>, 'payload'>) => (\n <ChartLegend payload={entries} hidden={hidden} onToggle={onToggle} column={column} />\n);\n\nexport const RangeBarChart = ({\n series,\n groupRows = false,\n colors,\n formatDate = defaultFormatDate,\n xTitle,\n yTitle,\n referenceLines,\n referenceBands,\n showLegend,\n legendPosition = 'top',\n emptyMessage = 'No data',\n ariaLabel,\n children,\n height = 320,\n width,\n}: RangeBarChartProps) => {\n const hidden = useHiddenSeries();\n const axis = useAxis();\n // Recharts names the layout after the axis the categories sit on.\n const categoryKeys = useCategoryKeys('vertical');\n const name = ariaLabel ?? `Range chart: ${series.map((s) => s.name).join(', ')}`;\n if (hasNoData(series)) {\n return <ChartEmpty message={emptyMessage} ariaLabel={name} height={height} width={width} />;\n }\n\n const categories = [...new Set(series.flatMap((s) => s.data.map((p) => p.x)))];\n const all = series.flatMap((s) => s.data.flatMap((p) => p.y));\n const ticks = timeTicks(Math.min(...all), Math.max(...all));\n const color = (index: number) => seriesColor(index, colors);\n const visible = (index: number) => !hidden.hidden.has(seriesKey(index));\n\n const rows: Row[] = categories.map((category) => {\n const ranges = series.flatMap((s, index) =>\n s.data\n .filter((p) => p.x === category)\n .map((p) => ({ series: index, start: p.y[0], end: p.y[1] }))\n );\n const bounds = (of: Range[]) =>\n of.length > 0\n ? ([Math.min(...of.map((r) => r.start)), Math.max(...of.map((r) => r.end))] as const)\n : undefined;\n return {\n category,\n ranges,\n [GROUP_KEY]: bounds(ranges),\n ...Object.fromEntries(\n series.map((_, index) => [\n seriesKey(index),\n bounds(ranges.filter((r) => r.series === index)),\n ])\n ),\n };\n });\n\n const tooltip = ({ active, payload, label }: Partial<TooltipContentProps>) => {\n const row = payload?.[0]?.payload as Row | undefined;\n if (!active || !row) return null;\n return (\n <TooltipCard\n title={label}\n rows={row.ranges\n .filter((r) => visible(r.series))\n .map((r) => ({\n name: series[r.series].name,\n value: `${formatDate(r.start)} – ${formatDate(r.end)}`,\n color: color(r.series),\n }))}\n />\n );\n };\n\n return (\n <BarChart\n ref={categoryKeys}\n {...frameProps({ height, width, ariaLabel: name })}\n data={rows}\n layout=\"vertical\"\n margin={{ top: 4, right: 16, bottom: 0, left: 0 }}\n barGap={2}\n barCategoryGap=\"20%\"\n >\n {/* Time runs left to right: vertical grid lines, plus a line between rows. */}\n <CartesianGrid stroke={GRID} strokeDasharray=\"4 4\" />\n <XAxis\n type=\"number\"\n domain={[ticks[0], ticks[ticks.length - 1]]}\n ticks={ticks}\n tickFormatter={tickLabel}\n {...axis}\n {...xAxisTitle(xTitle)}\n />\n <YAxis type=\"category\" dataKey=\"category\" width=\"auto\" {...axis} {...yAxisTitle(yTitle)} />\n {(showLegend ?? series.length > 1) && (\n <Legend\n {...legendProps(legendPosition, hidden)}\n content={\n <SeriesLegend\n entries={series.map((s, index) => ({\n value: s.name,\n type: 'circle',\n color: color(index),\n dataKey: seriesKey(index),\n }))}\n hidden={hidden.hidden}\n onToggle={hidden.toggle}\n column={legendPosition === 'left' || legendPosition === 'right'}\n />\n }\n />\n )}\n <Tooltip\n content={tooltip}\n cursor={{ fill: BORDER, fillOpacity: 0.35, radius: 8 }}\n animationDuration={150}\n />\n {groupRows ? (\n <Bar\n name=\"Ranges\"\n dataKey={GROUP_KEY}\n maxBarSize={32}\n shape={rangesShape(GROUP_KEY, color, visible)}\n {...ANIMATION}\n />\n ) : (\n series.map((s, index) => (\n <Bar\n key={seriesKey(index)}\n name={s.name}\n dataKey={seriesKey(index)}\n maxBarSize={28}\n shape={rangesShape(seriesKey(index), color, visible)}\n hide={!visible(index)}\n {...ANIMATION}\n />\n ))\n )}\n {referenceMarks({ referenceLines, referenceBands, axis: 'x' })}\n {children}\n </BarChart>\n );\n};\n"]}
@@ -0,0 +1,173 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var chunkRLHGPHC7_cjs = require('./chunk-RLHGPHC7.cjs');
5
+ var chunkT3K6Q34U_cjs = require('./chunk-T3K6Q34U.cjs');
6
+ var chunk6NRRABPF_cjs = require('./chunk-6NRRABPF.cjs');
7
+ var chunkLT3UC65O_cjs = require('./chunk-LT3UC65O.cjs');
8
+ var react = require('react');
9
+ var recharts = require('recharts');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
+
12
+ var CLOCK = new Intl.DateTimeFormat("en-GB", {
13
+ hour: "2-digit",
14
+ minute: "2-digit",
15
+ second: "2-digit",
16
+ hourCycle: "h23"
17
+ });
18
+ var clock = (timestamp) => CLOCK.format(timestamp);
19
+ var Threshold = ({ y, label, color }) => /* @__PURE__ */ jsxRuntime.jsx(
20
+ recharts.ReferenceLine,
21
+ {
22
+ y,
23
+ stroke: color,
24
+ strokeWidth: 1.5,
25
+ strokeDasharray: "6 4",
26
+ label: label === "" ? void 0 : {
27
+ value: label,
28
+ position: "insideTopRight",
29
+ offset: 4,
30
+ // Text on the card, whatever the status color: it reads on every theme.
31
+ fill: chunkLT3UC65O_cjs.TEXT,
32
+ style: { fill: chunkLT3UC65O_cjs.TEXT, fontSize: chunkRLHGPHC7_cjs.TEXT_SIZE, fontWeight: 600 }
33
+ }
34
+ }
35
+ );
36
+ var createDefaultGenerator = () => {
37
+ let last = 50;
38
+ return () => {
39
+ last += (Math.random() - 0.5) * 8;
40
+ last = Math.max(20, Math.min(95, last));
41
+ return Math.round(last);
42
+ };
43
+ };
44
+ var RealtimeChart = ({
45
+ generator,
46
+ intervalMs = 2e3,
47
+ windowSize = 30,
48
+ min = 0,
49
+ max = 100,
50
+ warnThreshold = 70,
51
+ critThreshold = 85,
52
+ warnLabel = "WARN",
53
+ critLabel = "CRIT",
54
+ showTimeAxis = false,
55
+ xTitle,
56
+ yTitle,
57
+ formatValue,
58
+ ariaLabel,
59
+ children,
60
+ height = 240,
61
+ width
62
+ }) => {
63
+ const axis = chunkRLHGPHC7_cjs.useAxis();
64
+ const [defaultGenerator] = react.useState(createDefaultGenerator);
65
+ const generate = generator ?? defaultGenerator;
66
+ const [mountedAt] = react.useState(Date.now);
67
+ const [samples, setSamples] = react.useState(
68
+ () => Array.from({ length: windowSize }, (_, index) => ({
69
+ time: mountedAt - (windowSize - 1 - index) * intervalMs,
70
+ value: generate()
71
+ }))
72
+ );
73
+ const [sizedFor, setSizedFor] = react.useState(windowSize);
74
+ if (sizedFor !== windowSize) {
75
+ setSizedFor(windowSize);
76
+ const missing = windowSize - samples.length;
77
+ const oldest = samples[0]?.time ?? mountedAt;
78
+ setSamples(
79
+ missing <= 0 ? samples.slice(samples.length - windowSize) : [
80
+ ...Array.from({ length: missing }, (_, index) => ({
81
+ time: oldest - (missing - index) * intervalMs,
82
+ value: generate()
83
+ })),
84
+ ...samples
85
+ ]
86
+ );
87
+ }
88
+ react.useEffect(() => {
89
+ const id = setInterval(() => {
90
+ setSamples((current) => [...current.slice(1), { time: Date.now(), value: generate() }]);
91
+ }, intervalMs);
92
+ return () => clearInterval(id);
93
+ }, [generate, intervalMs]);
94
+ const format = formatValue ?? String;
95
+ const tooltip = ({ active, payload }) => {
96
+ const sample = payload?.[0]?.payload;
97
+ if (!active || !sample) return null;
98
+ return /* @__PURE__ */ jsxRuntime.jsx(
99
+ chunkT3K6Q34U_cjs.TooltipCard,
100
+ {
101
+ title: showTimeAxis ? clock(sample.time) : void 0,
102
+ rows: [{ name: "value", value: format(sample.value), color: chunkLT3UC65O_cjs.SERIES[0] }]
103
+ }
104
+ );
105
+ };
106
+ return /* @__PURE__ */ jsxRuntime.jsxs(
107
+ recharts.LineChart,
108
+ {
109
+ ...chunk6NRRABPF_cjs.frameProps({
110
+ height,
111
+ width,
112
+ ariaLabel: ariaLabel ?? "Live values, newest on the right"
113
+ }),
114
+ data: samples,
115
+ margin: { top: 4, right: 12, bottom: 0, left: 0 },
116
+ children: [
117
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { ...chunkRLHGPHC7_cjs.GRID_PROPS }),
118
+ /* @__PURE__ */ jsxRuntime.jsx(
119
+ recharts.XAxis,
120
+ {
121
+ dataKey: "time",
122
+ type: "number",
123
+ domain: ["dataMin", "dataMax"],
124
+ hide: !showTimeAxis,
125
+ tickFormatter: clock,
126
+ ...axis,
127
+ ...showTimeAxis ? chunkRLHGPHC7_cjs.xAxisTitle(xTitle) : {}
128
+ }
129
+ ),
130
+ /* @__PURE__ */ jsxRuntime.jsx(
131
+ recharts.YAxis,
132
+ {
133
+ domain: [min, max],
134
+ allowDataOverflow: true,
135
+ interval: 0,
136
+ width: "auto",
137
+ tickFormatter: formatValue,
138
+ ...axis,
139
+ ...chunkRLHGPHC7_cjs.yAxisTitle(yTitle)
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsxRuntime.jsx(Threshold, { y: warnThreshold, label: warnLabel, color: chunkLT3UC65O_cjs.STATUS_WARN }),
143
+ /* @__PURE__ */ jsxRuntime.jsx(Threshold, { y: critThreshold, label: critLabel, color: chunkLT3UC65O_cjs.STATUS_CRIT }),
144
+ /* @__PURE__ */ jsxRuntime.jsx(
145
+ recharts.Tooltip,
146
+ {
147
+ content: tooltip,
148
+ cursor: { stroke: chunkLT3UC65O_cjs.BORDER, strokeDasharray: "4 4" },
149
+ animationDuration: 0
150
+ }
151
+ ),
152
+ /* @__PURE__ */ jsxRuntime.jsx(
153
+ recharts.Line,
154
+ {
155
+ name: "value",
156
+ dataKey: "value",
157
+ type: "monotone",
158
+ stroke: chunkLT3UC65O_cjs.SERIES[0],
159
+ strokeWidth: 2,
160
+ dot: false,
161
+ activeDot: { r: 5, fill: chunkLT3UC65O_cjs.PANEL, stroke: chunkLT3UC65O_cjs.SERIES[0], strokeWidth: 2.5 },
162
+ isAnimationActive: false
163
+ }
164
+ ),
165
+ children
166
+ ]
167
+ }
168
+ );
169
+ };
170
+
171
+ exports.RealtimeChart = RealtimeChart;
172
+ //# sourceMappingURL=RealtimeChart.cjs.map
173
+ //# sourceMappingURL=RealtimeChart.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/RealtimeChart.tsx"],"names":["jsx","ReferenceLine","TEXT","TEXT_SIZE","useAxis","useState","useEffect","TooltipCard","SERIES","jsxs","LineChart","frameProps","CartesianGrid","GRID_PROPS","XAxis","xAxisTitle","YAxis","yAxisTitle","STATUS_WARN","STATUS_CRIT","Tooltip","BORDER","Line","PANEL"],"mappings":"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","file":"RealtimeChart.cjs","sourcesContent":["import { useEffect, useState } from 'react';\nimport {\n CartesianGrid,\n Line,\n LineChart,\n ReferenceLine,\n Tooltip,\n XAxis,\n YAxis,\n type TooltipContentProps,\n} from 'recharts';\nimport { GRID_PROPS, TEXT_SIZE, useAxis, xAxisTitle, yAxisTitle } from './core/axes';\nimport { TooltipCard } from './core/ChartTooltip';\nimport { BORDER, PANEL, SERIES, STATUS_CRIT, STATUS_WARN, TEXT } from './core/colors';\nimport { frameProps } from './core/frame';\nimport type { ChartAxisTitleProps, ChartProps } from './types';\n\nexport type RealtimeChartProps = ChartProps &\n ChartAxisTitleProps & {\n /** Sample generator — defaults to a noisy walk between 30 and 80. */\n generator?: () => number;\n /** Interval in ms — defaults to 2000. */\n intervalMs?: number;\n windowSize?: number;\n /** Bottom of the y axis. Default 0. */\n min?: number;\n /** Top of the y axis, above `min`. Default 100. */\n max?: number;\n warnThreshold?: number;\n critThreshold?: number;\n /** Text of the warning threshold's label. Default `WARN`; an empty string draws the line alone. */\n warnLabel?: string;\n /** Text of the critical threshold's label. Default `CRIT`; an empty string draws the line alone. */\n critLabel?: string;\n /**\n * Label the x axis with the time of each sample (`14:03:25`, in local time), and the\n * tooltip with it, and `xTitle` has an axis to name. Default off: no x axis.\n */\n showTimeAxis?: boolean;\n /** Format the y-axis labels and the tooltip values. */\n formatValue?: (value: number) => string;\n };\n\ntype Sample = { time: number; value: number };\n\n// The time axis reads as a clock.\nconst CLOCK = new Intl.DateTimeFormat('en-GB', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hourCycle: 'h23',\n});\nconst clock = (timestamp: number) => CLOCK.format(timestamp);\n\n/** A threshold: a line in its status color, and a label on it unless `label` is empty. */\nconst Threshold = ({ y, label, color }: { y: number; label: string; color: string }) => (\n <ReferenceLine\n y={y}\n stroke={color}\n strokeWidth={1.5}\n strokeDasharray=\"6 4\"\n label={\n label === ''\n ? undefined\n : {\n value: label,\n position: 'insideTopRight',\n offset: 4,\n // Text on the card, whatever the status color: it reads on every theme.\n fill: TEXT,\n style: { fill: TEXT, fontSize: TEXT_SIZE, fontWeight: 600 },\n }\n }\n />\n);\n\n// One walk per chart: a module-level one made every instance continue the last.\nconst createDefaultGenerator = () => {\n let last = 50;\n return () => {\n last += (Math.random() - 0.5) * 8;\n last = Math.max(20, Math.min(95, last));\n return Math.round(last);\n };\n};\n\nexport const RealtimeChart = ({\n generator,\n intervalMs = 2000,\n windowSize = 30,\n min = 0,\n max = 100,\n warnThreshold = 70,\n critThreshold = 85,\n warnLabel = 'WARN',\n critLabel = 'CRIT',\n showTimeAxis = false,\n xTitle,\n yTitle,\n formatValue,\n ariaLabel,\n children,\n height = 240,\n width,\n}: RealtimeChartProps) => {\n const axis = useAxis();\n const [defaultGenerator] = useState(createDefaultGenerator);\n const generate = generator ?? defaultGenerator;\n // Each sample with the time it was taken, for the time axis. A window that\n // starts full is dated as if it had been filled at the sampling pace.\n const [mountedAt] = useState(Date.now);\n const [samples, setSamples] = useState<Sample[]>(() =>\n Array.from({ length: windowSize }, (_, index) => ({\n time: mountedAt - (windowSize - 1 - index) * intervalMs,\n value: generate(),\n }))\n );\n\n // A new windowSize trims the oldest samples or prepends new ones. Adjusted\n // while rendering, which React redoes at once without painting the old window.\n const [sizedFor, setSizedFor] = useState(windowSize);\n if (sizedFor !== windowSize) {\n setSizedFor(windowSize);\n const missing = windowSize - samples.length;\n const oldest = samples[0]?.time ?? mountedAt;\n setSamples(\n missing <= 0\n ? samples.slice(samples.length - windowSize)\n : [\n ...Array.from({ length: missing }, (_, index) => ({\n time: oldest - (missing - index) * intervalMs,\n value: generate(),\n })),\n ...samples,\n ]\n );\n }\n\n useEffect(() => {\n const id = setInterval(() => {\n setSamples((current) => [...current.slice(1), { time: Date.now(), value: generate() }]);\n }, intervalMs);\n return () => clearInterval(id);\n }, [generate, intervalMs]);\n\n const format = formatValue ?? String;\n\n // The card of the sample under the pointer, with its time when the axis shows it.\n const tooltip = ({ active, payload }: Partial<TooltipContentProps>) => {\n const sample = payload?.[0]?.payload as Sample | undefined;\n if (!active || !sample) return null;\n return (\n <TooltipCard\n title={showTimeAxis ? clock(sample.time) : undefined}\n rows={[{ name: 'value', value: format(sample.value), color: SERIES[0] }]}\n />\n );\n };\n\n return (\n <LineChart\n {...frameProps({\n height,\n width,\n ariaLabel: ariaLabel ?? 'Live values, newest on the right',\n })}\n data={samples}\n margin={{ top: 4, right: 12, bottom: 0, left: 0 }}\n >\n <CartesianGrid {...GRID_PROPS} />\n {/* The samples are not on a scale of their own unless the axis is the clock. */}\n <XAxis\n dataKey=\"time\"\n type=\"number\"\n domain={['dataMin', 'dataMax']}\n hide={!showTimeAxis}\n tickFormatter={clock}\n {...axis}\n {...(showTimeAxis ? xAxisTitle(xTitle) : {})}\n />\n <YAxis\n domain={[min, max]}\n allowDataOverflow\n // The bottom tick is `min`: keep it.\n interval={0}\n width=\"auto\"\n tickFormatter={formatValue}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n <Threshold y={warnThreshold} label={warnLabel} color={STATUS_WARN} />\n <Threshold y={critThreshold} label={critLabel} color={STATUS_CRIT} />\n <Tooltip\n content={tooltip}\n cursor={{ stroke: BORDER, strokeDasharray: '4 4' }}\n animationDuration={0}\n />\n <Line\n name=\"value\"\n dataKey=\"value\"\n type=\"monotone\"\n stroke={SERIES[0]}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 5, fill: PANEL, stroke: SERIES[0], strokeWidth: 2.5 }}\n // A new sample moves the window: no animation, so the line redraws steadily.\n isAnimationActive={false}\n />\n {children}\n </LineChart>\n );\n};\n"]}
@@ -0,0 +1,171 @@
1
+ "use client";
2
+ import { useAxis, GRID_PROPS, xAxisTitle, yAxisTitle, TEXT_SIZE } from './chunk-RILUG7JB.js';
3
+ import { TooltipCard } from './chunk-VIOSQN4Z.js';
4
+ import { frameProps } from './chunk-3N43QT36.js';
5
+ import { STATUS_WARN, STATUS_CRIT, BORDER, SERIES, PANEL, TEXT } from './chunk-UATB2IRY.js';
6
+ import { useState, useEffect } from 'react';
7
+ import { LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Line, ReferenceLine } from 'recharts';
8
+ import { jsxs, jsx } from 'react/jsx-runtime';
9
+
10
+ var CLOCK = new Intl.DateTimeFormat("en-GB", {
11
+ hour: "2-digit",
12
+ minute: "2-digit",
13
+ second: "2-digit",
14
+ hourCycle: "h23"
15
+ });
16
+ var clock = (timestamp) => CLOCK.format(timestamp);
17
+ var Threshold = ({ y, label, color }) => /* @__PURE__ */ jsx(
18
+ ReferenceLine,
19
+ {
20
+ y,
21
+ stroke: color,
22
+ strokeWidth: 1.5,
23
+ strokeDasharray: "6 4",
24
+ label: label === "" ? void 0 : {
25
+ value: label,
26
+ position: "insideTopRight",
27
+ offset: 4,
28
+ // Text on the card, whatever the status color: it reads on every theme.
29
+ fill: TEXT,
30
+ style: { fill: TEXT, fontSize: TEXT_SIZE, fontWeight: 600 }
31
+ }
32
+ }
33
+ );
34
+ var createDefaultGenerator = () => {
35
+ let last = 50;
36
+ return () => {
37
+ last += (Math.random() - 0.5) * 8;
38
+ last = Math.max(20, Math.min(95, last));
39
+ return Math.round(last);
40
+ };
41
+ };
42
+ var RealtimeChart = ({
43
+ generator,
44
+ intervalMs = 2e3,
45
+ windowSize = 30,
46
+ min = 0,
47
+ max = 100,
48
+ warnThreshold = 70,
49
+ critThreshold = 85,
50
+ warnLabel = "WARN",
51
+ critLabel = "CRIT",
52
+ showTimeAxis = false,
53
+ xTitle,
54
+ yTitle,
55
+ formatValue,
56
+ ariaLabel,
57
+ children,
58
+ height = 240,
59
+ width
60
+ }) => {
61
+ const axis = useAxis();
62
+ const [defaultGenerator] = useState(createDefaultGenerator);
63
+ const generate = generator ?? defaultGenerator;
64
+ const [mountedAt] = useState(Date.now);
65
+ const [samples, setSamples] = useState(
66
+ () => Array.from({ length: windowSize }, (_, index) => ({
67
+ time: mountedAt - (windowSize - 1 - index) * intervalMs,
68
+ value: generate()
69
+ }))
70
+ );
71
+ const [sizedFor, setSizedFor] = useState(windowSize);
72
+ if (sizedFor !== windowSize) {
73
+ setSizedFor(windowSize);
74
+ const missing = windowSize - samples.length;
75
+ const oldest = samples[0]?.time ?? mountedAt;
76
+ setSamples(
77
+ missing <= 0 ? samples.slice(samples.length - windowSize) : [
78
+ ...Array.from({ length: missing }, (_, index) => ({
79
+ time: oldest - (missing - index) * intervalMs,
80
+ value: generate()
81
+ })),
82
+ ...samples
83
+ ]
84
+ );
85
+ }
86
+ useEffect(() => {
87
+ const id = setInterval(() => {
88
+ setSamples((current) => [...current.slice(1), { time: Date.now(), value: generate() }]);
89
+ }, intervalMs);
90
+ return () => clearInterval(id);
91
+ }, [generate, intervalMs]);
92
+ const format = formatValue ?? String;
93
+ const tooltip = ({ active, payload }) => {
94
+ const sample = payload?.[0]?.payload;
95
+ if (!active || !sample) return null;
96
+ return /* @__PURE__ */ jsx(
97
+ TooltipCard,
98
+ {
99
+ title: showTimeAxis ? clock(sample.time) : void 0,
100
+ rows: [{ name: "value", value: format(sample.value), color: SERIES[0] }]
101
+ }
102
+ );
103
+ };
104
+ return /* @__PURE__ */ jsxs(
105
+ LineChart,
106
+ {
107
+ ...frameProps({
108
+ height,
109
+ width,
110
+ ariaLabel: ariaLabel ?? "Live values, newest on the right"
111
+ }),
112
+ data: samples,
113
+ margin: { top: 4, right: 12, bottom: 0, left: 0 },
114
+ children: [
115
+ /* @__PURE__ */ jsx(CartesianGrid, { ...GRID_PROPS }),
116
+ /* @__PURE__ */ jsx(
117
+ XAxis,
118
+ {
119
+ dataKey: "time",
120
+ type: "number",
121
+ domain: ["dataMin", "dataMax"],
122
+ hide: !showTimeAxis,
123
+ tickFormatter: clock,
124
+ ...axis,
125
+ ...showTimeAxis ? xAxisTitle(xTitle) : {}
126
+ }
127
+ ),
128
+ /* @__PURE__ */ jsx(
129
+ YAxis,
130
+ {
131
+ domain: [min, max],
132
+ allowDataOverflow: true,
133
+ interval: 0,
134
+ width: "auto",
135
+ tickFormatter: formatValue,
136
+ ...axis,
137
+ ...yAxisTitle(yTitle)
138
+ }
139
+ ),
140
+ /* @__PURE__ */ jsx(Threshold, { y: warnThreshold, label: warnLabel, color: STATUS_WARN }),
141
+ /* @__PURE__ */ jsx(Threshold, { y: critThreshold, label: critLabel, color: STATUS_CRIT }),
142
+ /* @__PURE__ */ jsx(
143
+ Tooltip,
144
+ {
145
+ content: tooltip,
146
+ cursor: { stroke: BORDER, strokeDasharray: "4 4" },
147
+ animationDuration: 0
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsx(
151
+ Line,
152
+ {
153
+ name: "value",
154
+ dataKey: "value",
155
+ type: "monotone",
156
+ stroke: SERIES[0],
157
+ strokeWidth: 2,
158
+ dot: false,
159
+ activeDot: { r: 5, fill: PANEL, stroke: SERIES[0], strokeWidth: 2.5 },
160
+ isAnimationActive: false
161
+ }
162
+ ),
163
+ children
164
+ ]
165
+ }
166
+ );
167
+ };
168
+
169
+ export { RealtimeChart };
170
+ //# sourceMappingURL=RealtimeChart.js.map
171
+ //# sourceMappingURL=RealtimeChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/RealtimeChart.tsx"],"names":[],"mappings":"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","file":"RealtimeChart.js","sourcesContent":["import { useEffect, useState } from 'react';\nimport {\n CartesianGrid,\n Line,\n LineChart,\n ReferenceLine,\n Tooltip,\n XAxis,\n YAxis,\n type TooltipContentProps,\n} from 'recharts';\nimport { GRID_PROPS, TEXT_SIZE, useAxis, xAxisTitle, yAxisTitle } from './core/axes';\nimport { TooltipCard } from './core/ChartTooltip';\nimport { BORDER, PANEL, SERIES, STATUS_CRIT, STATUS_WARN, TEXT } from './core/colors';\nimport { frameProps } from './core/frame';\nimport type { ChartAxisTitleProps, ChartProps } from './types';\n\nexport type RealtimeChartProps = ChartProps &\n ChartAxisTitleProps & {\n /** Sample generator — defaults to a noisy walk between 30 and 80. */\n generator?: () => number;\n /** Interval in ms — defaults to 2000. */\n intervalMs?: number;\n windowSize?: number;\n /** Bottom of the y axis. Default 0. */\n min?: number;\n /** Top of the y axis, above `min`. Default 100. */\n max?: number;\n warnThreshold?: number;\n critThreshold?: number;\n /** Text of the warning threshold's label. Default `WARN`; an empty string draws the line alone. */\n warnLabel?: string;\n /** Text of the critical threshold's label. Default `CRIT`; an empty string draws the line alone. */\n critLabel?: string;\n /**\n * Label the x axis with the time of each sample (`14:03:25`, in local time), and the\n * tooltip with it, and `xTitle` has an axis to name. Default off: no x axis.\n */\n showTimeAxis?: boolean;\n /** Format the y-axis labels and the tooltip values. */\n formatValue?: (value: number) => string;\n };\n\ntype Sample = { time: number; value: number };\n\n// The time axis reads as a clock.\nconst CLOCK = new Intl.DateTimeFormat('en-GB', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hourCycle: 'h23',\n});\nconst clock = (timestamp: number) => CLOCK.format(timestamp);\n\n/** A threshold: a line in its status color, and a label on it unless `label` is empty. */\nconst Threshold = ({ y, label, color }: { y: number; label: string; color: string }) => (\n <ReferenceLine\n y={y}\n stroke={color}\n strokeWidth={1.5}\n strokeDasharray=\"6 4\"\n label={\n label === ''\n ? undefined\n : {\n value: label,\n position: 'insideTopRight',\n offset: 4,\n // Text on the card, whatever the status color: it reads on every theme.\n fill: TEXT,\n style: { fill: TEXT, fontSize: TEXT_SIZE, fontWeight: 600 },\n }\n }\n />\n);\n\n// One walk per chart: a module-level one made every instance continue the last.\nconst createDefaultGenerator = () => {\n let last = 50;\n return () => {\n last += (Math.random() - 0.5) * 8;\n last = Math.max(20, Math.min(95, last));\n return Math.round(last);\n };\n};\n\nexport const RealtimeChart = ({\n generator,\n intervalMs = 2000,\n windowSize = 30,\n min = 0,\n max = 100,\n warnThreshold = 70,\n critThreshold = 85,\n warnLabel = 'WARN',\n critLabel = 'CRIT',\n showTimeAxis = false,\n xTitle,\n yTitle,\n formatValue,\n ariaLabel,\n children,\n height = 240,\n width,\n}: RealtimeChartProps) => {\n const axis = useAxis();\n const [defaultGenerator] = useState(createDefaultGenerator);\n const generate = generator ?? defaultGenerator;\n // Each sample with the time it was taken, for the time axis. A window that\n // starts full is dated as if it had been filled at the sampling pace.\n const [mountedAt] = useState(Date.now);\n const [samples, setSamples] = useState<Sample[]>(() =>\n Array.from({ length: windowSize }, (_, index) => ({\n time: mountedAt - (windowSize - 1 - index) * intervalMs,\n value: generate(),\n }))\n );\n\n // A new windowSize trims the oldest samples or prepends new ones. Adjusted\n // while rendering, which React redoes at once without painting the old window.\n const [sizedFor, setSizedFor] = useState(windowSize);\n if (sizedFor !== windowSize) {\n setSizedFor(windowSize);\n const missing = windowSize - samples.length;\n const oldest = samples[0]?.time ?? mountedAt;\n setSamples(\n missing <= 0\n ? samples.slice(samples.length - windowSize)\n : [\n ...Array.from({ length: missing }, (_, index) => ({\n time: oldest - (missing - index) * intervalMs,\n value: generate(),\n })),\n ...samples,\n ]\n );\n }\n\n useEffect(() => {\n const id = setInterval(() => {\n setSamples((current) => [...current.slice(1), { time: Date.now(), value: generate() }]);\n }, intervalMs);\n return () => clearInterval(id);\n }, [generate, intervalMs]);\n\n const format = formatValue ?? String;\n\n // The card of the sample under the pointer, with its time when the axis shows it.\n const tooltip = ({ active, payload }: Partial<TooltipContentProps>) => {\n const sample = payload?.[0]?.payload as Sample | undefined;\n if (!active || !sample) return null;\n return (\n <TooltipCard\n title={showTimeAxis ? clock(sample.time) : undefined}\n rows={[{ name: 'value', value: format(sample.value), color: SERIES[0] }]}\n />\n );\n };\n\n return (\n <LineChart\n {...frameProps({\n height,\n width,\n ariaLabel: ariaLabel ?? 'Live values, newest on the right',\n })}\n data={samples}\n margin={{ top: 4, right: 12, bottom: 0, left: 0 }}\n >\n <CartesianGrid {...GRID_PROPS} />\n {/* The samples are not on a scale of their own unless the axis is the clock. */}\n <XAxis\n dataKey=\"time\"\n type=\"number\"\n domain={['dataMin', 'dataMax']}\n hide={!showTimeAxis}\n tickFormatter={clock}\n {...axis}\n {...(showTimeAxis ? xAxisTitle(xTitle) : {})}\n />\n <YAxis\n domain={[min, max]}\n allowDataOverflow\n // The bottom tick is `min`: keep it.\n interval={0}\n width=\"auto\"\n tickFormatter={formatValue}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n <Threshold y={warnThreshold} label={warnLabel} color={STATUS_WARN} />\n <Threshold y={critThreshold} label={critLabel} color={STATUS_CRIT} />\n <Tooltip\n content={tooltip}\n cursor={{ stroke: BORDER, strokeDasharray: '4 4' }}\n animationDuration={0}\n />\n <Line\n name=\"value\"\n dataKey=\"value\"\n type=\"monotone\"\n stroke={SERIES[0]}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 5, fill: PANEL, stroke: SERIES[0], strokeWidth: 2.5 }}\n // A new sample moves the window: no animation, so the line redraws steadily.\n isAnimationActive={false}\n />\n {children}\n </LineChart>\n );\n};\n"]}