@wallarm-org/design-system 4.0.0 → 4.1.0-rc-feat-WDS-192.1

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.
@@ -0,0 +1,30 @@
1
+ import { type FC, type HTMLAttributes, type ReactNode, type Ref } from 'react';
2
+ import { type TestableProps } from '../../../utils/testId.js';
3
+ export type MetricSparklineColor = 'brand' | 'positive' | 'negative' | 'neutral';
4
+ export interface MetricSparklinePoint {
5
+ /** The point's position on the period — a date (`Date`, timestamp, ISO string) or any label. */
6
+ x: Date | number | string;
7
+ value: number;
8
+ }
9
+ export interface MetricSparklineProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'>, TestableProps {
10
+ ref?: Ref<HTMLDivElement>;
11
+ /** The trend over the period, oldest first. */
12
+ data: MetricSparklinePoint[];
13
+ /**
14
+ * Line colour. Independent of the `MetricDelta` sentiment — set both. `brand` (default) ·
15
+ * `positive` (success) · `negative` (danger) · `neutral` (slate).
16
+ */
17
+ color?: MetricSparklineColor;
18
+ /** Series name on the hover popover row (Figma "Attribute"). */
19
+ label?: ReactNode;
20
+ /** Formats the hovered point's `x` for the popover. Defaults to `1 Jan, 2026` for dates. */
21
+ formatX?: (x: MetricSparklinePoint['x']) => ReactNode;
22
+ /** Formats the hovered value. Defaults to `toLocaleString('en-US')`. */
23
+ formatValue?: (value: number) => ReactNode;
24
+ }
25
+ /**
26
+ * The trend under a `Metric`: a 48px line + area spanning the card width, with a ruler and a
27
+ * date/value popover on hover. Compose it inside `Chart`, after `Metric` — the metric's bottom
28
+ * padding is the 8px gap, and the sparkline sits flush with the card's bottom edge.
29
+ */
30
+ export declare const MetricSparkline: FC<MetricSparklineProps>;
@@ -0,0 +1,365 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { c } from "react/compiler-runtime";
3
+ import { useEffect, useId, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+ import { cn } from "../../../utils/cn.js";
6
+ import { useTestId } from "../../../utils/testId.js";
7
+ import { useDateFormat } from "../../DateFormatProvider/useDateFormat.js";
8
+ import { ChartHoverCardRow } from "../internal/ChartHoverCard.js";
9
+ import { LineChartHoverPopover, LineChartHoverPopoverTimestamp } from "../LineChart/index.js";
10
+ import { LINE_CURSOR_DASHARRAY } from "../LineChart/constants.js";
11
+ import { formatChartDate } from "../lib/timeFormatters.js";
12
+ import { metricSparklineClasses, metricSparklinePlotClasses, metricSparklinePopoverClasses, metricSparklineRulerClasses } from "./classes.js";
13
+ const SPARKLINE_COLORS = {
14
+ brand: {
15
+ line: "var(--color-bg-fill-brand)",
16
+ area: "var(--color-bg-fill-brand)"
17
+ },
18
+ positive: {
19
+ line: "var(--color-bg-fill-success)",
20
+ area: "var(--color-bg-fill-success)"
21
+ },
22
+ negative: {
23
+ line: "var(--color-bg-fill-danger)",
24
+ area: "var(--color-bg-fill-danger)"
25
+ },
26
+ neutral: {
27
+ line: "var(--color-border-strong-primary)",
28
+ area: "var(--color-bg-strong-primary)"
29
+ }
30
+ };
31
+ const HEIGHT = 48;
32
+ const PAD_TOP = 4;
33
+ const PAD_BOTTOM = 8;
34
+ const STROKE_WIDTH = 1.5;
35
+ const POPOVER_OFFSET_X = 8;
36
+ const POPOVER_OFFSET_Y = 14;
37
+ const buildPaths = (values)=>{
38
+ const ys = 1 === values.length ? values.concat(values) : values;
39
+ const finite = ys.filter(Number.isFinite);
40
+ const min = Math.min(...finite);
41
+ const span = Math.max(...finite) - min;
42
+ const inner = HEIGHT - PAD_TOP - PAD_BOTTOM;
43
+ const toY = (v)=>0 === span ? PAD_TOP + inner / 2 : PAD_TOP + (1 - (v - min) / span) * inner;
44
+ const line = [];
45
+ const area = [];
46
+ let runEnd = -1;
47
+ ys.forEach((v, i)=>{
48
+ if (!Number.isFinite(v)) {
49
+ if (runEnd >= 0) area.push(`L${runEnd},${HEIGHT} Z`);
50
+ runEnd = -1;
51
+ return;
52
+ }
53
+ const y = toY(v);
54
+ line.push(`${runEnd < 0 ? "M" : "L"}${i},${y}`);
55
+ area.push(runEnd < 0 ? `M${i},${HEIGHT} L${i},${y}` : `L${i},${y}`);
56
+ runEnd = i;
57
+ });
58
+ if (runEnd >= 0) area.push(`L${runEnd},${HEIGHT} Z`);
59
+ return {
60
+ width: ys.length - 1,
61
+ line: line.join(" "),
62
+ area: area.join(" ")
63
+ };
64
+ };
65
+ const ISO_DATE = /^\d{4}-\d{2}-\d{2}/;
66
+ const MetricSparkline = (t0)=>{
67
+ const $ = c(61);
68
+ let className;
69
+ let data;
70
+ let formatValue;
71
+ let formatX;
72
+ let label;
73
+ let props;
74
+ let ref;
75
+ let t1;
76
+ let testIdProp;
77
+ if ($[0] !== t0) {
78
+ ({ data, color: t1, label, formatX, formatValue, className, ref, "data-testid": testIdProp, ...props } = t0);
79
+ $[0] = t0;
80
+ $[1] = className;
81
+ $[2] = data;
82
+ $[3] = formatValue;
83
+ $[4] = formatX;
84
+ $[5] = label;
85
+ $[6] = props;
86
+ $[7] = ref;
87
+ $[8] = t1;
88
+ $[9] = testIdProp;
89
+ } else {
90
+ className = $[1];
91
+ data = $[2];
92
+ formatValue = $[3];
93
+ formatX = $[4];
94
+ label = $[5];
95
+ props = $[6];
96
+ ref = $[7];
97
+ t1 = $[8];
98
+ testIdProp = $[9];
99
+ }
100
+ const color = void 0 === t1 ? "brand" : t1;
101
+ const testId = useTestId("sparkline", testIdProp);
102
+ const popoverTestId = testId ? `${testId}--popover` : void 0;
103
+ const { order } = useDateFormat();
104
+ const t2 = useId();
105
+ let t3;
106
+ if ($[10] !== t2) {
107
+ let t4;
108
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
109
+ t4 = /[^\w-]/g;
110
+ $[12] = t4;
111
+ } else t4 = $[12];
112
+ t3 = t2.replace(t4, "");
113
+ $[10] = t2;
114
+ $[11] = t3;
115
+ } else t3 = $[11];
116
+ const gradientId = `metric-sparkline-${t3}`;
117
+ const [hover, setHover] = useState(null);
118
+ const { line, area } = SPARKLINE_COLORS[color];
119
+ let t4;
120
+ if ($[13] !== data) {
121
+ t4 = data.length > 0 ? buildPaths(data.map(_temp)) : null;
122
+ $[13] = data;
123
+ $[14] = t4;
124
+ } else t4 = $[14];
125
+ const paths = t4;
126
+ const last = data.length - 1;
127
+ let t5;
128
+ if ($[15] !== last) {
129
+ t5 = (index)=>0 === last ? 0.5 : index / last;
130
+ $[15] = last;
131
+ $[16] = t5;
132
+ } else t5 = $[16];
133
+ const fractionOf = t5;
134
+ let t6;
135
+ if ($[17] !== last) {
136
+ t6 = (event)=>{
137
+ const rect = event.currentTarget.getBoundingClientRect();
138
+ if (last < 0 || 0 === rect.width) return;
139
+ const ratio = Math.min(Math.max((event.clientX - rect.left) / rect.width, 0), 1);
140
+ setHover({
141
+ index: Math.round(ratio * last),
142
+ left: rect.left,
143
+ top: rect.top,
144
+ width: rect.width
145
+ });
146
+ };
147
+ $[17] = last;
148
+ $[18] = t6;
149
+ } else t6 = $[18];
150
+ const handlePointerMove = t6;
151
+ let t7;
152
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
153
+ t7 = ()=>setHover(null);
154
+ $[19] = t7;
155
+ } else t7 = $[19];
156
+ const handlePointerLeave = t7;
157
+ const isHovering = null !== hover;
158
+ let t8;
159
+ let t9;
160
+ if ($[20] !== isHovering) {
161
+ t8 = ()=>{
162
+ if (!isHovering) return;
163
+ const clear = ()=>setHover(null);
164
+ window.addEventListener("scroll", clear, {
165
+ capture: true,
166
+ passive: true
167
+ });
168
+ window.addEventListener("resize", clear);
169
+ return ()=>{
170
+ window.removeEventListener("scroll", clear, {
171
+ capture: true
172
+ });
173
+ window.removeEventListener("resize", clear);
174
+ };
175
+ };
176
+ t9 = [
177
+ isHovering
178
+ ];
179
+ $[20] = isHovering;
180
+ $[21] = t8;
181
+ $[22] = t9;
182
+ } else {
183
+ t8 = $[21];
184
+ t9 = $[22];
185
+ }
186
+ useEffect(t8, t9);
187
+ const index_0 = hover && hover.index <= last ? hover.index : null;
188
+ const point = null === index_0 ? void 0 : data[index_0];
189
+ const fraction = null === index_0 ? 0 : fractionOf(index_0);
190
+ const flip = fraction > 0.5;
191
+ let t10;
192
+ if ($[23] !== formatX || $[24] !== order || $[25] !== point) {
193
+ t10 = point ? formatX ? formatX(point.x) : "string" != typeof point.x || ISO_DATE.test(point.x) ? formatChartDate(point.x, {
194
+ order,
195
+ withYear: true
196
+ }) || String(point.x) : point.x : null;
197
+ $[23] = formatX;
198
+ $[24] = order;
199
+ $[25] = point;
200
+ $[26] = t10;
201
+ } else t10 = $[26];
202
+ const formattedX = t10;
203
+ let t11;
204
+ if ($[27] !== className) {
205
+ t11 = cn(metricSparklineClasses, className);
206
+ $[27] = className;
207
+ $[28] = t11;
208
+ } else t11 = $[28];
209
+ const t12 = testId && `${testId}--plot`;
210
+ let t13;
211
+ if ($[29] !== area || $[30] !== gradientId || $[31] !== line || $[32] !== paths) {
212
+ t13 = paths && /*#__PURE__*/ jsxs("svg", {
213
+ className: "block size-full",
214
+ viewBox: `0 0 ${paths.width} ${HEIGHT}`,
215
+ preserveAspectRatio: "none",
216
+ children: [
217
+ /*#__PURE__*/ jsx("defs", {
218
+ children: /*#__PURE__*/ jsxs("linearGradient", {
219
+ id: gradientId,
220
+ x1: "0",
221
+ y1: "0",
222
+ x2: "0",
223
+ y2: "1",
224
+ children: [
225
+ /*#__PURE__*/ jsx("stop", {
226
+ offset: "0",
227
+ stopColor: area,
228
+ stopOpacity: 0.2
229
+ }),
230
+ /*#__PURE__*/ jsx("stop", {
231
+ offset: "1",
232
+ stopColor: area,
233
+ stopOpacity: 0
234
+ })
235
+ ]
236
+ })
237
+ }),
238
+ /*#__PURE__*/ jsx("path", {
239
+ d: paths.area,
240
+ fill: `url(#${gradientId})`
241
+ }),
242
+ /*#__PURE__*/ jsx("path", {
243
+ d: paths.line,
244
+ fill: "none",
245
+ stroke: line,
246
+ strokeWidth: STROKE_WIDTH,
247
+ strokeLinejoin: "round",
248
+ strokeLinecap: "round",
249
+ vectorEffect: "non-scaling-stroke"
250
+ })
251
+ ]
252
+ });
253
+ $[29] = area;
254
+ $[30] = gradientId;
255
+ $[31] = line;
256
+ $[32] = paths;
257
+ $[33] = t13;
258
+ } else t13 = $[33];
259
+ let t14;
260
+ if ($[34] !== fraction || $[35] !== point || $[36] !== testId) {
261
+ t14 = point && /*#__PURE__*/ jsx("svg", {
262
+ "data-slot": "metric-sparkline-ruler",
263
+ "data-testid": testId && `${testId}--ruler`,
264
+ className: metricSparklineRulerClasses,
265
+ style: {
266
+ left: `${100 * fraction}%`
267
+ },
268
+ children: /*#__PURE__*/ jsx("line", {
269
+ x1: "0.5",
270
+ x2: "0.5",
271
+ y1: "0",
272
+ y2: "100%",
273
+ stroke: "var(--color-border-strong-primary)",
274
+ strokeDasharray: LINE_CURSOR_DASHARRAY
275
+ })
276
+ });
277
+ $[34] = fraction;
278
+ $[35] = point;
279
+ $[36] = testId;
280
+ $[37] = t14;
281
+ } else t14 = $[37];
282
+ let t15;
283
+ if ($[38] !== handlePointerMove || $[39] !== t12 || $[40] !== t13 || $[41] !== t14) {
284
+ t15 = /*#__PURE__*/ jsxs("div", {
285
+ "data-slot": "metric-sparkline-plot",
286
+ "data-testid": t12,
287
+ "aria-hidden": "true",
288
+ className: metricSparklinePlotClasses,
289
+ onPointerMove: handlePointerMove,
290
+ onPointerLeave: handlePointerLeave,
291
+ children: [
292
+ t13,
293
+ t14
294
+ ]
295
+ });
296
+ $[38] = handlePointerMove;
297
+ $[39] = t12;
298
+ $[40] = t13;
299
+ $[41] = t14;
300
+ $[42] = t15;
301
+ } else t15 = $[42];
302
+ let t16;
303
+ if ($[43] !== flip || $[44] !== formatValue || $[45] !== formattedX || $[46] !== fraction || $[47] !== hover || $[48] !== label || $[49] !== line || $[50] !== point || $[51] !== popoverTestId) {
304
+ t16 = hover && point && /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx("div", {
305
+ className: cn(metricSparklinePopoverClasses, flip && "-translate-x-full"),
306
+ style: {
307
+ left: hover.left + fraction * hover.width + (flip ? -POPOVER_OFFSET_X : POPOVER_OFFSET_X),
308
+ top: hover.top + POPOVER_OFFSET_Y
309
+ },
310
+ children: /*#__PURE__*/ jsxs(LineChartHoverPopover, {
311
+ "data-testid": popoverTestId,
312
+ children: [
313
+ /*#__PURE__*/ jsx(LineChartHoverPopoverTimestamp, {
314
+ children: formattedX
315
+ }),
316
+ /*#__PURE__*/ jsx(ChartHoverCardRow, {
317
+ color: line,
318
+ label: label,
319
+ value: Number.isFinite(point.value) ? point.value : null,
320
+ formatValue: formatValue && ((v)=>"number" == typeof v ? formatValue(v) : "—")
321
+ })
322
+ ]
323
+ })
324
+ }), document.body);
325
+ $[43] = flip;
326
+ $[44] = formatValue;
327
+ $[45] = formattedX;
328
+ $[46] = fraction;
329
+ $[47] = hover;
330
+ $[48] = label;
331
+ $[49] = line;
332
+ $[50] = point;
333
+ $[51] = popoverTestId;
334
+ $[52] = t16;
335
+ } else t16 = $[52];
336
+ let t17;
337
+ if ($[53] !== color || $[54] !== props || $[55] !== ref || $[56] !== t11 || $[57] !== t15 || $[58] !== t16 || $[59] !== testId) {
338
+ t17 = /*#__PURE__*/ jsxs("div", {
339
+ ...props,
340
+ ref: ref,
341
+ "data-slot": "metric-sparkline",
342
+ "data-testid": testId,
343
+ "data-color": color,
344
+ className: t11,
345
+ children: [
346
+ t15,
347
+ t16
348
+ ]
349
+ });
350
+ $[53] = color;
351
+ $[54] = props;
352
+ $[55] = ref;
353
+ $[56] = t11;
354
+ $[57] = t15;
355
+ $[58] = t16;
356
+ $[59] = testId;
357
+ $[60] = t17;
358
+ } else t17 = $[60];
359
+ return t17;
360
+ };
361
+ MetricSparkline.displayName = "MetricSparkline";
362
+ function _temp(d) {
363
+ return d.value;
364
+ }
365
+ export { MetricSparkline };
@@ -6,3 +6,7 @@ export declare const metricTotalValueClasses = "font-sans-display text-lg font-m
6
6
  export declare const metricTotalWordClasses = "text-xs font-normal text-text-secondary";
7
7
  export declare const metricCaptionClasses = "text-xs text-text-secondary";
8
8
  export declare const metricSkeletonLineClasses = "w-full py-4";
9
+ export declare const metricSparklineClasses = "mt-auto w-full px-px";
10
+ export declare const metricSparklinePlotClasses = "relative h-48";
11
+ export declare const metricSparklineRulerClasses = "pointer-events-none absolute top-0 h-full w-px -translate-x-1/2 overflow-visible";
12
+ export declare const metricSparklinePopoverClasses = "pointer-events-none fixed z-(--tooltip-z-index)";
@@ -6,4 +6,8 @@ const metricTotalValueClasses = 'font-sans-display text-lg font-medium text-text
6
6
  const metricTotalWordClasses = 'text-xs font-normal text-text-secondary';
7
7
  const metricCaptionClasses = 'text-xs text-text-secondary';
8
8
  const metricSkeletonLineClasses = 'w-full py-4';
9
- export { metricCaptionClasses, metricHeaderClasses, metricRootClasses, metricSkeletonLineClasses, metricTotalClasses, metricTotalValueClasses, metricTotalWordClasses, metricValueClasses };
9
+ const metricSparklineClasses = 'mt-auto w-full px-px';
10
+ const metricSparklinePlotClasses = 'relative h-48';
11
+ const metricSparklineRulerClasses = 'pointer-events-none absolute top-0 h-full w-px -translate-x-1/2 overflow-visible';
12
+ const metricSparklinePopoverClasses = 'pointer-events-none fixed z-(--tooltip-z-index)';
13
+ export { metricCaptionClasses, metricHeaderClasses, metricRootClasses, metricSkeletonLineClasses, metricSparklineClasses, metricSparklinePlotClasses, metricSparklinePopoverClasses, metricSparklineRulerClasses, metricTotalClasses, metricTotalValueClasses, metricTotalWordClasses, metricValueClasses };
@@ -3,5 +3,6 @@ export { MetricCaption, type MetricCaptionProps } from './MetricCaption.js';
3
3
  export { MetricDelta, type MetricDeltaProps } from './MetricDelta.js';
4
4
  export { MetricHeader, type MetricHeaderProps } from './MetricHeader.js';
5
5
  export { MetricSkeleton, type MetricSkeletonProps } from './MetricSkeleton.js';
6
+ export { MetricSparkline, type MetricSparklineColor, type MetricSparklinePoint, type MetricSparklineProps, } from './MetricSparkline.js';
6
7
  export { MetricTotal, type MetricTotalConnector, type MetricTotalProps } from './MetricTotal.js';
7
8
  export { MetricValue, type MetricValueProps } from './MetricValue.js';
@@ -3,5 +3,6 @@ export { MetricCaption } from "./MetricCaption.js";
3
3
  export { MetricDelta } from "./MetricDelta.js";
4
4
  export { MetricHeader } from "./MetricHeader.js";
5
5
  export { MetricSkeleton } from "./MetricSkeleton.js";
6
+ export { MetricSparkline } from "./MetricSparkline.js";
6
7
  export { MetricTotal } from "./MetricTotal.js";
7
8
  export { MetricValue } from "./MetricValue.js";
@@ -5,6 +5,6 @@ export { HorizontalBarStack, type HorizontalBarStackDatum, type HorizontalBarSta
5
5
  export { type ChartTimeFormatters, useChartTimeFormatters } from './hooks/index.js';
6
6
  export { LineChart, LineChartBody, type LineChartBodyProps, type LineChartDatum, LineChartEmpty, type LineChartEmptyProps, LineChartGrid, type LineChartGridProps, LineChartHoverPopover, LineChartHoverPopoverDot, type LineChartHoverPopoverDotProps, type LineChartHoverPopoverProps, LineChartHoverPopoverRow, type LineChartHoverPopoverRowProps, LineChartHoverPopoverTimestamp, type LineChartHoverPopoverTimestampProps, LineChartLegend, LineChartLegendItem, type LineChartLegendItemProps, type LineChartLegendOrientation, type LineChartLegendProps, LineChartLine, type LineChartLineProps, type LineChartProps, type LineChartSeries, LineChartTooltip, type LineChartTooltipProps, type LineChartTooltipRenderArgs, LineChartXAxis, type LineChartXAxisProps, LineChartYAxis, type LineChartYAxisProps, LineChartZoomBrush, type LineChartZoomBrushProps, LineChartZoomPopover, LineChartZoomPopoverConfirm, type LineChartZoomPopoverConfirmProps, type LineChartZoomPopoverProps, LineChartZoomPopoverRange, type LineChartZoomPopoverRangeProps, type LineChartZoomRange, } from './LineChart/index.js';
7
7
  export { type ChartHourCycle, type ChartTimeFormatterOptions, type ChartTimeOrder, formatChartDate, formatChartDateTime, formatChartHour, formatChartTimezone, withTimezoneChip, } from './lib/index.js';
8
- export { Metric, MetricCaption, type MetricCaptionProps, MetricDelta, type MetricDeltaProps, MetricHeader, type MetricHeaderProps, type MetricProps, MetricSkeleton, type MetricSkeletonProps, MetricTotal, type MetricTotalConnector, type MetricTotalProps, MetricValue, type MetricValueProps, } from './Metric/index.js';
8
+ export { Metric, MetricCaption, type MetricCaptionProps, MetricDelta, type MetricDeltaProps, MetricHeader, type MetricHeaderProps, type MetricProps, MetricSkeleton, type MetricSkeletonProps, MetricSparkline, type MetricSparklineColor, type MetricSparklinePoint, type MetricSparklineProps, MetricTotal, type MetricTotalConnector, type MetricTotalProps, MetricValue, type MetricValueProps, } from './Metric/index.js';
9
9
  export { LegendDot, type LegendDotProps, PieChart, PieChartCenter, PieChartCenterLabel, type PieChartCenterLabelPluralRules, type PieChartCenterLabelProps, type PieChartCenterProps, PieChartCenterValue, type PieChartCenterValueProps, type PieChartDatum, PieChartDonut, type PieChartDonutProps, PieChartLegend, PieChartLegendItem, type PieChartLegendItemProps, PieChartLegendPercent, type PieChartLegendPercentProps, type PieChartLegendPercentVariant, type PieChartLegendProps, PieChartLegendValue, type PieChartLegendValueProps, type PieChartProps, PieChartSkeleton, type PieChartSkeletonProps, } from './PieChart/index.js';
10
10
  export type { ChartColor } from './types.js';
@@ -5,5 +5,5 @@ export { HorizontalBarStack, HorizontalBarStackSkeleton } from "./HorizontalBarS
5
5
  export { useChartTimeFormatters } from "./hooks/index.js";
6
6
  export { LineChart, LineChartBody, LineChartEmpty, LineChartGrid, LineChartHoverPopover, LineChartHoverPopoverDot, LineChartHoverPopoverRow, LineChartHoverPopoverTimestamp, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis, LineChartZoomBrush, LineChartZoomPopover, LineChartZoomPopoverConfirm, LineChartZoomPopoverRange } from "./LineChart/index.js";
7
7
  export { formatChartDate, formatChartDateTime, formatChartHour, formatChartTimezone, withTimezoneChip } from "./lib/index.js";
8
- export { Metric, MetricCaption, MetricDelta, MetricHeader, MetricSkeleton, MetricTotal, MetricValue } from "./Metric/index.js";
8
+ export { Metric, MetricCaption, MetricDelta, MetricHeader, MetricSkeleton, MetricSparkline, MetricTotal, MetricValue } from "./Metric/index.js";
9
9
  export { LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue, PieChartSkeleton } from "./PieChart/index.js";
@@ -10,9 +10,13 @@ export interface ChartTimeFormatterOptions {
10
10
  export declare const formatChartHour: (value: unknown, options?: {
11
11
  hourCycle?: ChartHourCycle;
12
12
  }) => string;
13
- /** `24 Jan` (day-first) / `Jan 24` (month-first). Year is omitted — axis space is precious. */
13
+ /**
14
+ * `24 Jan` (day-first) / `Jan 24` (month-first). Year is omitted by default — axis space is
15
+ * precious; `withYear` gives `24 Jan, 2026` / `Jan 24, 2026` for popovers.
16
+ */
14
17
  export declare const formatChartDate: (value: unknown, options?: {
15
18
  order?: ChartTimeOrder;
19
+ withYear?: boolean;
16
20
  }) => string;
17
21
  /** Combined `24 Jan 14:32`. Respects both `order` and `hourCycle`. */
18
22
  export declare const formatChartDateTime: (value: unknown, options?: ChartTimeFormatterOptions) => string;
@@ -1,10 +1,11 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { format, isValid } from "date-fns";
2
+ import { format, isValid, parseISO } from "date-fns";
3
3
  import { formatTimezone } from "../../../utils/formatDateTime.js";
4
+ const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
4
5
  const toDate = (value)=>{
5
6
  if (value instanceof Date) return isValid(value) ? value : null;
6
7
  if ('number' == typeof value || 'string' == typeof value) {
7
- const d = new Date(value);
8
+ const d = 'string' == typeof value && DATE_ONLY.test(value) ? parseISO(value) : new Date(value);
8
9
  return isValid(d) ? d : null;
9
10
  }
10
11
  return null;
@@ -25,7 +26,7 @@ const formatChartHour = (value, options = {})=>{
25
26
  const formatChartDate = (value, options = {})=>{
26
27
  const date = toDate(value);
27
28
  if (!date) return '';
28
- return format(date, datePattern(options.order ?? 'day-first', false));
29
+ return format(date, datePattern(options.order ?? 'day-first', options.withYear ?? false));
29
30
  };
30
31
  const formatChartDateTime = (value, options = {})=>{
31
32
  const date = toDate(value);
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "3.4.0",
3
- "generatedAt": "2026-10-22T11:42:57.295Z",
2
+ "version": "4.0.0",
3
+ "generatedAt": "2026-10-22T12:30:52.881Z",
4
4
  "components": [
5
5
  {
6
6
  "name": "Accordion",
@@ -103713,6 +103713,312 @@
103713
103713
  }
103714
103714
  ]
103715
103715
  },
103716
+ {
103717
+ "name": "MetricSparkline",
103718
+ "props": [
103719
+ {
103720
+ "name": "data",
103721
+ "type": "MetricSparklinePoint[]",
103722
+ "required": true,
103723
+ "description": "The trend over the period, oldest first."
103724
+ },
103725
+ {
103726
+ "name": "color",
103727
+ "type": "MetricSparklineColor | undefined",
103728
+ "required": false,
103729
+ "description": "Line colour. Independent of the `MetricDelta` sentiment — set both. `brand` (default) ·\n`positive` (success) · `negative` (danger) · `neutral` (slate).",
103730
+ "defaultValue": "brand"
103731
+ },
103732
+ {
103733
+ "name": "label",
103734
+ "type": "ReactNode",
103735
+ "required": false,
103736
+ "description": "Series name on the hover popover row (Figma \"Attribute\")."
103737
+ },
103738
+ {
103739
+ "name": "formatX",
103740
+ "type": "((x: string | number | Date) => ReactNode) | undefined",
103741
+ "required": false,
103742
+ "description": "Formats the hovered point's `x` for the popover. Defaults to `1 Jan, 2026` for dates."
103743
+ },
103744
+ {
103745
+ "name": "formatValue",
103746
+ "type": "((value: number) => ReactNode) | undefined",
103747
+ "required": false,
103748
+ "description": "Formats the hovered value. Defaults to `toLocaleString('en-US')`."
103749
+ },
103750
+ {
103751
+ "name": "defaultChecked",
103752
+ "type": "boolean | undefined",
103753
+ "required": false
103754
+ },
103755
+ {
103756
+ "name": "defaultValue",
103757
+ "type": "string | number | readonly string[] | undefined",
103758
+ "required": false
103759
+ },
103760
+ {
103761
+ "name": "suppressContentEditableWarning",
103762
+ "type": "boolean | undefined",
103763
+ "required": false
103764
+ },
103765
+ {
103766
+ "name": "suppressHydrationWarning",
103767
+ "type": "boolean | undefined",
103768
+ "required": false
103769
+ },
103770
+ {
103771
+ "name": "accessKey",
103772
+ "type": "string | undefined",
103773
+ "required": false
103774
+ },
103775
+ {
103776
+ "name": "autoCapitalize",
103777
+ "type": "\"off\" | \"none\" | \"on\" | \"sentences\" | \"words\" | \"characters\" | (string & {}) | undefined",
103778
+ "required": false
103779
+ },
103780
+ {
103781
+ "name": "autoFocus",
103782
+ "type": "boolean | undefined",
103783
+ "required": false
103784
+ },
103785
+ {
103786
+ "name": "contentEditable",
103787
+ "type": "Booleanish | \"inherit\" | \"plaintext-only\" | undefined",
103788
+ "required": false
103789
+ },
103790
+ {
103791
+ "name": "contextMenu",
103792
+ "type": "string | undefined",
103793
+ "required": false
103794
+ },
103795
+ {
103796
+ "name": "dir",
103797
+ "type": "string | undefined",
103798
+ "required": false
103799
+ },
103800
+ {
103801
+ "name": "draggable",
103802
+ "type": "Booleanish | undefined",
103803
+ "required": false
103804
+ },
103805
+ {
103806
+ "name": "enterKeyHint",
103807
+ "type": "\"enter\" | \"done\" | \"go\" | \"next\" | \"previous\" | \"search\" | \"send\" | undefined",
103808
+ "required": false
103809
+ },
103810
+ {
103811
+ "name": "hidden",
103812
+ "type": "boolean | undefined",
103813
+ "required": false
103814
+ },
103815
+ {
103816
+ "name": "id",
103817
+ "type": "string | undefined",
103818
+ "required": false
103819
+ },
103820
+ {
103821
+ "name": "lang",
103822
+ "type": "string | undefined",
103823
+ "required": false
103824
+ },
103825
+ {
103826
+ "name": "nonce",
103827
+ "type": "string | undefined",
103828
+ "required": false
103829
+ },
103830
+ {
103831
+ "name": "slot",
103832
+ "type": "string | undefined",
103833
+ "required": false
103834
+ },
103835
+ {
103836
+ "name": "spellCheck",
103837
+ "type": "Booleanish | undefined",
103838
+ "required": false
103839
+ },
103840
+ {
103841
+ "name": "tabIndex",
103842
+ "type": "number | undefined",
103843
+ "required": false
103844
+ },
103845
+ {
103846
+ "name": "title",
103847
+ "type": "string | undefined",
103848
+ "required": false
103849
+ },
103850
+ {
103851
+ "name": "translate",
103852
+ "type": "\"yes\" | \"no\" | undefined",
103853
+ "required": false
103854
+ },
103855
+ {
103856
+ "name": "radioGroup",
103857
+ "type": "string | undefined",
103858
+ "required": false
103859
+ },
103860
+ {
103861
+ "name": "role",
103862
+ "type": "AriaRole | undefined",
103863
+ "required": false
103864
+ },
103865
+ {
103866
+ "name": "about",
103867
+ "type": "string | undefined",
103868
+ "required": false
103869
+ },
103870
+ {
103871
+ "name": "content",
103872
+ "type": "string | undefined",
103873
+ "required": false
103874
+ },
103875
+ {
103876
+ "name": "datatype",
103877
+ "type": "string | undefined",
103878
+ "required": false
103879
+ },
103880
+ {
103881
+ "name": "inlist",
103882
+ "type": "any",
103883
+ "required": false
103884
+ },
103885
+ {
103886
+ "name": "prefix",
103887
+ "type": "string | undefined",
103888
+ "required": false
103889
+ },
103890
+ {
103891
+ "name": "property",
103892
+ "type": "string | undefined",
103893
+ "required": false
103894
+ },
103895
+ {
103896
+ "name": "rel",
103897
+ "type": "string | undefined",
103898
+ "required": false
103899
+ },
103900
+ {
103901
+ "name": "resource",
103902
+ "type": "string | undefined",
103903
+ "required": false
103904
+ },
103905
+ {
103906
+ "name": "rev",
103907
+ "type": "string | undefined",
103908
+ "required": false
103909
+ },
103910
+ {
103911
+ "name": "typeof",
103912
+ "type": "string | undefined",
103913
+ "required": false
103914
+ },
103915
+ {
103916
+ "name": "vocab",
103917
+ "type": "string | undefined",
103918
+ "required": false
103919
+ },
103920
+ {
103921
+ "name": "autoCorrect",
103922
+ "type": "string | undefined",
103923
+ "required": false
103924
+ },
103925
+ {
103926
+ "name": "autoSave",
103927
+ "type": "string | undefined",
103928
+ "required": false
103929
+ },
103930
+ {
103931
+ "name": "itemProp",
103932
+ "type": "string | undefined",
103933
+ "required": false
103934
+ },
103935
+ {
103936
+ "name": "itemScope",
103937
+ "type": "boolean | undefined",
103938
+ "required": false
103939
+ },
103940
+ {
103941
+ "name": "itemType",
103942
+ "type": "string | undefined",
103943
+ "required": false
103944
+ },
103945
+ {
103946
+ "name": "itemID",
103947
+ "type": "string | undefined",
103948
+ "required": false
103949
+ },
103950
+ {
103951
+ "name": "itemRef",
103952
+ "type": "string | undefined",
103953
+ "required": false
103954
+ },
103955
+ {
103956
+ "name": "results",
103957
+ "type": "number | undefined",
103958
+ "required": false
103959
+ },
103960
+ {
103961
+ "name": "security",
103962
+ "type": "string | undefined",
103963
+ "required": false
103964
+ },
103965
+ {
103966
+ "name": "unselectable",
103967
+ "type": "\"off\" | \"on\" | undefined",
103968
+ "required": false
103969
+ },
103970
+ {
103971
+ "name": "popover",
103972
+ "type": "\"\" | \"auto\" | \"manual\" | \"hint\" | undefined",
103973
+ "required": false
103974
+ },
103975
+ {
103976
+ "name": "popoverTargetAction",
103977
+ "type": "\"toggle\" | \"show\" | \"hide\" | undefined",
103978
+ "required": false
103979
+ },
103980
+ {
103981
+ "name": "popoverTarget",
103982
+ "type": "string | undefined",
103983
+ "required": false
103984
+ },
103985
+ {
103986
+ "name": "inert",
103987
+ "type": "boolean | undefined",
103988
+ "required": false,
103989
+ "description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert}"
103990
+ },
103991
+ {
103992
+ "name": "inputMode",
103993
+ "type": "\"none\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined",
103994
+ "required": false,
103995
+ "description": "Hints at the type of data that might be entered by the user while editing the element or its contents"
103996
+ },
103997
+ {
103998
+ "name": "is",
103999
+ "type": "string | undefined",
104000
+ "required": false,
104001
+ "description": "Specify that a standard HTML element should behave like a defined custom built-in element"
104002
+ },
104003
+ {
104004
+ "name": "exportparts",
104005
+ "type": "string | undefined",
104006
+ "required": false,
104007
+ "description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts}"
104008
+ },
104009
+ {
104010
+ "name": "part",
104011
+ "type": "string | undefined",
104012
+ "required": false,
104013
+ "description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/part}"
104014
+ },
104015
+ {
104016
+ "name": "data-testid",
104017
+ "type": "string | undefined",
104018
+ "required": false
104019
+ }
104020
+ ]
104021
+ },
103716
104022
  {
103717
104023
  "name": "MetricTotal",
103718
104024
  "props": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wallarm-org/design-system",
3
- "version": "4.0.0",
3
+ "version": "4.1.0-rc-feat-WDS-192.1",
4
4
  "description": "Core design system library with React components and Storybook documentation",
5
5
  "publishConfig": {
6
6
  "access": "public",