@wallarm-org/design-system 0.35.0 → 0.36.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 (94) hide show
  1. package/dist/components/Attribute/AttributeActionsTarget.js +1 -1
  2. package/dist/components/Ip/IpList/IpListHorizontal.js +1 -1
  3. package/dist/components/OverflowList/OverflowList.js +1 -1
  4. package/dist/components/Popover/PopoverContent.js +1 -1
  5. package/dist/components/SimpleCharts/LineChart/LineChart.d.ts +70 -0
  6. package/dist/components/SimpleCharts/LineChart/LineChart.figma.d.ts +1 -0
  7. package/dist/components/SimpleCharts/LineChart/LineChart.figma.js +163 -0
  8. package/dist/components/SimpleCharts/LineChart/LineChart.js +136 -0
  9. package/dist/components/SimpleCharts/LineChart/LineChartBody.d.ts +12 -0
  10. package/dist/components/SimpleCharts/LineChart/LineChartBody.js +66 -0
  11. package/dist/components/SimpleCharts/LineChart/LineChartContext.d.ts +151 -0
  12. package/dist/components/SimpleCharts/LineChart/LineChartContext.js +16 -0
  13. package/dist/components/SimpleCharts/LineChart/LineChartEmpty.d.ts +15 -0
  14. package/dist/components/SimpleCharts/LineChart/LineChartEmpty.js +71 -0
  15. package/dist/components/SimpleCharts/LineChart/LineChartGrid.d.ts +19 -0
  16. package/dist/components/SimpleCharts/LineChart/LineChartGrid.js +17 -0
  17. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopover.d.ts +5 -0
  18. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopover.js +14 -0
  19. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopoverDot.d.ts +14 -0
  20. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopoverDot.js +20 -0
  21. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopoverRow.d.ts +12 -0
  22. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopoverRow.js +33 -0
  23. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopoverTimestamp.d.ts +5 -0
  24. package/dist/components/SimpleCharts/LineChart/LineChartHoverPopoverTimestamp.js +12 -0
  25. package/dist/components/SimpleCharts/LineChart/LineChartLegend.d.ts +15 -0
  26. package/dist/components/SimpleCharts/LineChart/LineChartLegend.js +19 -0
  27. package/dist/components/SimpleCharts/LineChart/LineChartLegendItem.d.ts +14 -0
  28. package/dist/components/SimpleCharts/LineChart/LineChartLegendItem.js +112 -0
  29. package/dist/components/SimpleCharts/LineChart/LineChartLine.d.ts +17 -0
  30. package/dist/components/SimpleCharts/LineChart/LineChartLine.js +57 -0
  31. package/dist/components/SimpleCharts/LineChart/LineChartTooltip.d.ts +31 -0
  32. package/dist/components/SimpleCharts/LineChart/LineChartTooltip.js +75 -0
  33. package/dist/components/SimpleCharts/LineChart/LineChartXAxis.d.ts +51 -0
  34. package/dist/components/SimpleCharts/LineChart/LineChartXAxis.js +34 -0
  35. package/dist/components/SimpleCharts/LineChart/LineChartYAxis.d.ts +24 -0
  36. package/dist/components/SimpleCharts/LineChart/LineChartYAxis.js +30 -0
  37. package/dist/components/SimpleCharts/LineChart/LineChartZoomBrush.d.ts +32 -0
  38. package/dist/components/SimpleCharts/LineChart/LineChartZoomBrush.js +104 -0
  39. package/dist/components/SimpleCharts/LineChart/LineChartZoomPopover.d.ts +5 -0
  40. package/dist/components/SimpleCharts/LineChart/LineChartZoomPopover.js +14 -0
  41. package/dist/components/SimpleCharts/LineChart/LineChartZoomPopoverConfirm.d.ts +5 -0
  42. package/dist/components/SimpleCharts/LineChart/LineChartZoomPopoverConfirm.js +14 -0
  43. package/dist/components/SimpleCharts/LineChart/LineChartZoomPopoverRange.d.ts +5 -0
  44. package/dist/components/SimpleCharts/LineChart/LineChartZoomPopoverRange.js +12 -0
  45. package/dist/components/SimpleCharts/LineChart/classes.d.ts +28 -0
  46. package/dist/components/SimpleCharts/LineChart/classes.js +95 -0
  47. package/dist/components/SimpleCharts/LineChart/constants.d.ts +25 -0
  48. package/dist/components/SimpleCharts/LineChart/constants.js +26 -0
  49. package/dist/components/SimpleCharts/LineChart/hooks/index.d.ts +5 -0
  50. package/dist/components/SimpleCharts/LineChart/hooks/index.js +6 -0
  51. package/dist/components/SimpleCharts/LineChart/hooks/useLineChartActiveKey.d.ts +33 -0
  52. package/dist/components/SimpleCharts/LineChart/hooks/useLineChartActiveKey.js +33 -0
  53. package/dist/components/SimpleCharts/LineChart/hooks/useLineChartDataWarnings.d.ts +18 -0
  54. package/dist/components/SimpleCharts/LineChart/hooks/useLineChartDataWarnings.js +47 -0
  55. package/dist/components/SimpleCharts/LineChart/hooks/useLineChartZoomState.d.ts +37 -0
  56. package/dist/components/SimpleCharts/LineChart/hooks/useLineChartZoomState.js +111 -0
  57. package/dist/components/SimpleCharts/LineChart/hooks/useZoomDragListeners.d.ts +16 -0
  58. package/dist/components/SimpleCharts/LineChart/hooks/useZoomDragListeners.js +27 -0
  59. package/dist/components/SimpleCharts/LineChart/hooks/useZoomPendingListeners.d.ts +21 -0
  60. package/dist/components/SimpleCharts/LineChart/hooks/useZoomPendingListeners.js +35 -0
  61. package/dist/components/SimpleCharts/LineChart/index.d.ts +19 -0
  62. package/dist/components/SimpleCharts/LineChart/index.js +19 -0
  63. package/dist/components/SimpleCharts/LineChart/lib/dropEdgeGridLines.d.ts +30 -0
  64. package/dist/components/SimpleCharts/LineChart/lib/dropEdgeGridLines.js +48 -0
  65. package/dist/components/SimpleCharts/LineChart/lib/formatRange.d.ts +9 -0
  66. package/dist/components/SimpleCharts/LineChart/lib/formatRange.js +7 -0
  67. package/dist/components/SimpleCharts/LineChart/lib/sampleData.d.ts +15 -0
  68. package/dist/components/SimpleCharts/LineChart/lib/sampleData.js +109 -0
  69. package/dist/components/SimpleCharts/LineChart/lib/tickHorizontalCoordinates.d.ts +15 -0
  70. package/dist/components/SimpleCharts/LineChart/lib/tickHorizontalCoordinates.js +13 -0
  71. package/dist/components/SimpleCharts/LineChart/lib/warn.d.ts +4 -0
  72. package/dist/components/SimpleCharts/LineChart/lib/warn.js +6 -0
  73. package/dist/components/SimpleCharts/PieChart/PieChartContext.js +5 -2
  74. package/dist/components/SimpleCharts/PieChart/constants.d.ts +1 -2
  75. package/dist/components/SimpleCharts/PieChart/constants.js +2 -15
  76. package/dist/components/SimpleCharts/hooks/index.d.ts +1 -0
  77. package/dist/components/SimpleCharts/hooks/index.js +2 -0
  78. package/dist/components/SimpleCharts/hooks/useChartTimeFormatters.d.ts +21 -0
  79. package/dist/components/SimpleCharts/hooks/useChartTimeFormatters.js +33 -0
  80. package/dist/components/SimpleCharts/index.d.ts +3 -0
  81. package/dist/components/SimpleCharts/index.js +4 -1
  82. package/dist/components/SimpleCharts/lib/chartPalette.d.ts +10 -0
  83. package/dist/components/SimpleCharts/lib/chartPalette.js +20 -0
  84. package/dist/components/SimpleCharts/lib/hoverSync.d.ts +9 -0
  85. package/dist/components/SimpleCharts/lib/hoverSync.js +5 -0
  86. package/dist/components/SimpleCharts/lib/index.d.ts +2 -0
  87. package/dist/components/SimpleCharts/lib/index.js +3 -0
  88. package/dist/components/SimpleCharts/lib/timeFormatters.d.ts +25 -0
  89. package/dist/components/SimpleCharts/lib/timeFormatters.js +57 -0
  90. package/dist/hooks/useOverflowItems.js +1 -1
  91. package/dist/metadata/components.json +3665 -2
  92. package/dist/utils/formatDateTime.d.ts +4 -0
  93. package/dist/utils/formatDateTime.js +1 -1
  94. package/package.json +1 -1
@@ -0,0 +1,37 @@
1
+ import type { LineChartDatum, LineChartZoomDragState, LineChartZoomPendingState, LineChartZoomRange } from '../LineChartContext';
2
+ interface UseLineChartZoomStateResult {
3
+ enabled: boolean;
4
+ drag: LineChartZoomDragState | null;
5
+ pending: LineChartZoomPendingState | null;
6
+ registerEnabled: () => () => void;
7
+ startDrag: (index: number, clientX: number, clientY: number) => void;
8
+ updateDrag: (index: number, clientX: number, clientY: number) => void;
9
+ endDrag: () => void;
10
+ cancelDrag: () => void;
11
+ confirmZoom: () => void;
12
+ cancelPending: () => void;
13
+ }
14
+ /**
15
+ * Two-phase zoom selection state machine.
16
+ *
17
+ * - `drag` is the live mouse-held selection — updated on every mousemove,
18
+ * torn down on Escape, promoted to `pending` on mouseup.
19
+ * - `pending` is the released-but-unconfirmed selection — renders the confirm
20
+ * popover. Commits via `confirmZoom` (fires `onZoomChange`) or dismisses via
21
+ * `cancelPending` (no emit).
22
+ *
23
+ * `enabledCount` (not a boolean) so multiple brush instances can't race when
24
+ * one unmounts while another remains. Window-level listeners are wired up by
25
+ * `useZoomDragListeners` so the popover keeps tracking when the cursor leaves
26
+ * the SVG and a mouseup outside the chart still releases into pending.
27
+ *
28
+ * Dataset changes invalidate cached indices on both `drag` and `pending`, so
29
+ * both reset whenever `data` or `xKey` flips — otherwise a stale range could
30
+ * be committed against a refreshed dataset.
31
+ */
32
+ export declare const useLineChartZoomState: ({ data, xKey, onZoomChange, }: {
33
+ data: LineChartDatum[];
34
+ xKey: string;
35
+ onZoomChange: ((range: LineChartZoomRange | null) => void) | undefined;
36
+ }) => UseLineChartZoomStateResult;
37
+ export {};
@@ -0,0 +1,111 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { useZoomDragListeners } from "./useZoomDragListeners.js";
3
+ const useLineChartZoomState = ({ data, xKey, onZoomChange })=>{
4
+ const [zoomEnabledCount, setZoomEnabledCount] = useState(0);
5
+ const [zoomDrag, setZoomDrag] = useState(null);
6
+ const [zoomPending, setZoomPending] = useState(null);
7
+ const registerEnabled = useCallback(()=>{
8
+ setZoomEnabledCount((n)=>n + 1);
9
+ return ()=>setZoomEnabledCount((n)=>n - 1);
10
+ }, []);
11
+ const startDrag = useCallback((index, clientX, clientY)=>{
12
+ setZoomPending(null);
13
+ setZoomDrag({
14
+ startIndex: index,
15
+ endIndex: index,
16
+ clientX,
17
+ clientY
18
+ });
19
+ }, []);
20
+ const updateDrag = useCallback((index, clientX, clientY)=>{
21
+ setZoomDrag((prev)=>{
22
+ if (!prev) return null;
23
+ if (prev.endIndex === index && prev.clientX === clientX && prev.clientY === clientY) return prev;
24
+ return {
25
+ startIndex: prev.startIndex,
26
+ endIndex: index,
27
+ clientX,
28
+ clientY
29
+ };
30
+ });
31
+ }, []);
32
+ const cancelDrag = useCallback(()=>{
33
+ setZoomDrag(null);
34
+ }, []);
35
+ const endDrag = useCallback(()=>{
36
+ setZoomDrag((currentDrag)=>{
37
+ if (!currentDrag) return null;
38
+ const lo = Math.min(currentDrag.startIndex, currentDrag.endIndex);
39
+ const hi = Math.max(currentDrag.startIndex, currentDrag.endIndex);
40
+ if (lo === hi) return null;
41
+ const fromDatum = data[lo];
42
+ const toDatum = data[hi];
43
+ const from = fromDatum?.[xKey];
44
+ const to = toDatum?.[xKey];
45
+ if (null != from && null != to) setZoomPending({
46
+ range: {
47
+ fromIndex: lo,
48
+ toIndex: hi,
49
+ from,
50
+ to
51
+ },
52
+ clientX: currentDrag.clientX,
53
+ clientY: currentDrag.clientY
54
+ });
55
+ return null;
56
+ });
57
+ }, [
58
+ data,
59
+ xKey
60
+ ]);
61
+ const confirmZoom = useCallback(()=>{
62
+ setZoomPending((currentPending)=>{
63
+ if (currentPending) onZoomChange?.(currentPending.range);
64
+ return null;
65
+ });
66
+ }, [
67
+ onZoomChange
68
+ ]);
69
+ const cancelPending = useCallback(()=>{
70
+ setZoomPending(null);
71
+ }, []);
72
+ useEffect(()=>{
73
+ setZoomDrag(null);
74
+ setZoomPending(null);
75
+ }, [
76
+ data,
77
+ xKey
78
+ ]);
79
+ const isZoomDragging = null !== zoomDrag;
80
+ const handleDragMove = useCallback((clientX, clientY)=>{
81
+ setZoomDrag((prev)=>{
82
+ if (!prev) return null;
83
+ if (prev.clientX === clientX && prev.clientY === clientY) return prev;
84
+ return {
85
+ ...prev,
86
+ clientX,
87
+ clientY
88
+ };
89
+ });
90
+ }, []);
91
+ const handleDragEscape = useCallback(()=>setZoomDrag(null), []);
92
+ useZoomDragListeners({
93
+ enabled: isZoomDragging,
94
+ onMove: handleDragMove,
95
+ onEnd: endDrag,
96
+ onEscape: handleDragEscape
97
+ });
98
+ return {
99
+ enabled: zoomEnabledCount > 0,
100
+ drag: zoomDrag,
101
+ pending: zoomPending,
102
+ registerEnabled,
103
+ startDrag,
104
+ updateDrag,
105
+ endDrag,
106
+ cancelDrag,
107
+ confirmZoom,
108
+ cancelPending
109
+ };
110
+ };
111
+ export { useLineChartZoomState };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Window-level drag follower. While `enabled` is `true` the chart's zoom drag
3
+ * is in progress: mousemove updates the cursor coordinates, mouseup releases
4
+ * into the pending state, Escape cancels outright. Listeners live on `window`
5
+ * rather than the chart body so the popover keeps tracking when the cursor
6
+ * leaves the SVG and a release outside the chart still commits.
7
+ *
8
+ * Pulled out of `<LineChart>` so the keyboard contract has a single source of
9
+ * truth that can be tested in isolation.
10
+ */
11
+ export declare const useZoomDragListeners: ({ enabled, onMove, onEnd, onEscape, }: {
12
+ enabled: boolean;
13
+ onMove: (clientX: number, clientY: number) => void;
14
+ onEnd: () => void;
15
+ onEscape: () => void;
16
+ }) => void;
@@ -0,0 +1,27 @@
1
+ import { useEffect } from "react";
2
+ const useZoomDragListeners = ({ enabled, onMove, onEnd, onEscape })=>{
3
+ useEffect(()=>{
4
+ if (!enabled) return;
5
+ const handleMove = (event)=>onMove(event.clientX, event.clientY);
6
+ const handleUp = ()=>onEnd();
7
+ const handleKey = (event)=>{
8
+ if ('Escape' !== event.key) return;
9
+ event.preventDefault();
10
+ onEscape();
11
+ };
12
+ window.addEventListener('mousemove', handleMove);
13
+ window.addEventListener('mouseup', handleUp);
14
+ window.addEventListener('keydown', handleKey);
15
+ return ()=>{
16
+ window.removeEventListener('mousemove', handleMove);
17
+ window.removeEventListener('mouseup', handleUp);
18
+ window.removeEventListener('keydown', handleKey);
19
+ };
20
+ }, [
21
+ enabled,
22
+ onMove,
23
+ onEnd,
24
+ onEscape
25
+ ]);
26
+ };
27
+ export { useZoomDragListeners };
@@ -0,0 +1,21 @@
1
+ import { type RefObject } from 'react';
2
+ /**
3
+ * Pending-phase listeners for the zoom confirm popover. Runs while `enabled`
4
+ * is `true` (i.e. a pending range exists):
5
+ *
6
+ * - Mousedown outside the popover dismisses the pending range. `mousedown`
7
+ * rather than `click` so a fresh drag (which starts on the chart body's
8
+ * `mousedown`) sees an already-cleared pending state.
9
+ * - Enter confirms, Escape cancels. Scope is gated to events whose target is
10
+ * inside `rootRef`, inside `popoverRef` (portalled), or ambient (focus on
11
+ * `<body>` / `<html>`). The ref-based scope is load-bearing: a generic
12
+ * `closest('[data-slot="line-chart"]')` selector would let sibling charts
13
+ * confirm a pending range that does not belong to them.
14
+ */
15
+ export declare const useZoomPendingListeners: ({ enabled, rootRef, popoverRef, onConfirm, onCancel, }: {
16
+ enabled: boolean;
17
+ rootRef: RefObject<HTMLElement | null> | undefined;
18
+ popoverRef: RefObject<HTMLElement | null>;
19
+ onConfirm?: () => void;
20
+ onCancel?: () => void;
21
+ }) => void;
@@ -0,0 +1,35 @@
1
+ import { useEffect } from "react";
2
+ const useZoomPendingListeners = ({ enabled, rootRef, popoverRef, onConfirm, onCancel })=>{
3
+ useEffect(()=>{
4
+ if (!enabled) return;
5
+ const handleMouseDown = (event)=>{
6
+ const target = event.target;
7
+ if (target instanceof Node && popoverRef.current?.contains(target)) return;
8
+ onCancel?.();
9
+ };
10
+ const handleKey = (event)=>{
11
+ if ('Enter' !== event.key && 'Escape' !== event.key) return;
12
+ const target = event.target;
13
+ const isAmbient = null === target || target === document.body || target === document.documentElement;
14
+ const isInPopover = target instanceof Node && (popoverRef.current?.contains(target) ?? false);
15
+ const isInOwningChart = target instanceof Node && (rootRef?.current?.contains(target) ?? false);
16
+ if (!isAmbient && !isInPopover && !isInOwningChart) return;
17
+ event.preventDefault();
18
+ if ('Enter' === event.key) onConfirm?.();
19
+ else onCancel?.();
20
+ };
21
+ window.addEventListener('mousedown', handleMouseDown);
22
+ window.addEventListener('keydown', handleKey);
23
+ return ()=>{
24
+ window.removeEventListener('mousedown', handleMouseDown);
25
+ window.removeEventListener('keydown', handleKey);
26
+ };
27
+ }, [
28
+ enabled,
29
+ rootRef,
30
+ popoverRef,
31
+ onConfirm,
32
+ onCancel
33
+ ]);
34
+ };
35
+ export { useZoomPendingListeners };
@@ -0,0 +1,19 @@
1
+ export { LineChart, type LineChartProps } from './LineChart';
2
+ export { LineChartBody, type LineChartBodyProps } from './LineChartBody';
3
+ export type { LineChartDatum, LineChartLegendOrientation, LineChartSeries, LineChartZoomRange, } from './LineChartContext';
4
+ export { LineChartEmpty, type LineChartEmptyProps } from './LineChartEmpty';
5
+ export { LineChartGrid, type LineChartGridProps } from './LineChartGrid';
6
+ export { LineChartHoverPopover, type LineChartHoverPopoverProps, } from './LineChartHoverPopover';
7
+ export { LineChartHoverPopoverDot, type LineChartHoverPopoverDotProps, } from './LineChartHoverPopoverDot';
8
+ export { LineChartHoverPopoverRow, type LineChartHoverPopoverRowProps, } from './LineChartHoverPopoverRow';
9
+ export { LineChartHoverPopoverTimestamp, type LineChartHoverPopoverTimestampProps, } from './LineChartHoverPopoverTimestamp';
10
+ export { LineChartLegend, type LineChartLegendProps } from './LineChartLegend';
11
+ export { LineChartLegendItem, type LineChartLegendItemProps, } from './LineChartLegendItem';
12
+ export { LineChartLine, type LineChartLineProps } from './LineChartLine';
13
+ export { LineChartTooltip, type LineChartTooltipProps, type LineChartTooltipRenderArgs, type LineChartTooltipRow, } from './LineChartTooltip';
14
+ export { LineChartXAxis, type LineChartXAxisDensity, type LineChartXAxisProps, } from './LineChartXAxis';
15
+ export { LineChartYAxis, type LineChartYAxisProps } from './LineChartYAxis';
16
+ export { LineChartZoomBrush, type LineChartZoomBrushProps, } from './LineChartZoomBrush';
17
+ export { LineChartZoomPopover, type LineChartZoomPopoverProps, } from './LineChartZoomPopover';
18
+ export { LineChartZoomPopoverConfirm, type LineChartZoomPopoverConfirmProps, } from './LineChartZoomPopoverConfirm';
19
+ export { LineChartZoomPopoverRange, type LineChartZoomPopoverRangeProps, } from './LineChartZoomPopoverRange';
@@ -0,0 +1,19 @@
1
+ import { LineChart } from "./LineChart.js";
2
+ import { LineChartBody } from "./LineChartBody.js";
3
+ import { LineChartEmpty } from "./LineChartEmpty.js";
4
+ import { LineChartGrid } from "./LineChartGrid.js";
5
+ import { LineChartHoverPopover } from "./LineChartHoverPopover.js";
6
+ import { LineChartHoverPopoverDot } from "./LineChartHoverPopoverDot.js";
7
+ import { LineChartHoverPopoverRow } from "./LineChartHoverPopoverRow.js";
8
+ import { LineChartHoverPopoverTimestamp } from "./LineChartHoverPopoverTimestamp.js";
9
+ import { LineChartLegend } from "./LineChartLegend.js";
10
+ import { LineChartLegendItem } from "./LineChartLegendItem.js";
11
+ import { LineChartLine } from "./LineChartLine.js";
12
+ import { LineChartTooltip } from "./LineChartTooltip.js";
13
+ import { LineChartXAxis } from "./LineChartXAxis.js";
14
+ import { LineChartYAxis } from "./LineChartYAxis.js";
15
+ import { LineChartZoomBrush } from "./LineChartZoomBrush.js";
16
+ import { LineChartZoomPopover } from "./LineChartZoomPopover.js";
17
+ import { LineChartZoomPopoverConfirm } from "./LineChartZoomPopoverConfirm.js";
18
+ import { LineChartZoomPopoverRange } from "./LineChartZoomPopoverRange.js";
19
+ export { LineChart, LineChartBody, LineChartEmpty, LineChartGrid, LineChartHoverPopover, LineChartHoverPopoverDot, LineChartHoverPopoverRow, LineChartHoverPopoverTimestamp, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis, LineChartZoomBrush, LineChartZoomPopover, LineChartZoomPopoverConfirm, LineChartZoomPopoverRange };
@@ -0,0 +1,30 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { GridLineTypeFunctionProps } from 'recharts/types/cartesian/CartesianGrid';
3
+ interface DropEdgeGridLinesOptions {
4
+ /** Keep the topmost horizontal grid line unconditionally. */
5
+ keepTop?: boolean;
6
+ /** Keep the bottommost horizontal grid line unconditionally. */
7
+ keepBottom?: boolean;
8
+ }
9
+ /**
10
+ * `<CartesianGrid horizontal>` render function that conditionally omits the
11
+ * topmost and bottommost horizontal grid lines.
12
+ *
13
+ * - **Top** — implements the Figma "no top x-line" rule (anatomy node
14
+ * `7533-3334`). Dropped only when the gap from the chart's top edge to the
15
+ * topmost grid line is less than {@link TOP_LINE_GAP_THRESHOLD} of one
16
+ * tick-to-tick spacing; above that ratio the gap reads as deliberate
17
+ * whitespace and the line stays (useful for axes whose nice-tick max sits
18
+ * well below the data max).
19
+ * - **Bottom** — dropped unconditionally so the solid X-axis line owns the
20
+ * bottom rail (otherwise the dashed grid line and the solid axis line stack
21
+ * on top of each other and read as a double line).
22
+ *
23
+ * Either drop can be suppressed via `keepTop` / `keepBottom` (e.g. when the
24
+ * caller hides the X-axis line and wants the grid to draw the bottom rail).
25
+ *
26
+ * Returning an empty `<g/>` (rather than `null`) keeps the type contract:
27
+ * `GridLineType`'s function form requires a `ReactElement<SVGElement>`.
28
+ */
29
+ export declare const dropEdgeGridLines: ({ keepTop, keepBottom, }?: DropEdgeGridLinesOptions) => (props: GridLineTypeFunctionProps) => ReactElement<SVGElement>;
30
+ export {};
@@ -0,0 +1,48 @@
1
+ import { createElement } from "react";
2
+ const TOP_LINE_GAP_THRESHOLD = 0.5;
3
+ const collectTickYs = (yAxis)=>{
4
+ const { scale } = yAxis;
5
+ const tickValues = yAxis.niceTicks ?? yAxis.ticks;
6
+ if (!scale || !tickValues?.length) return [];
7
+ const ys = [];
8
+ for (const tick of tickValues){
9
+ const y = scale.map(tick);
10
+ if ('number' == typeof y) ys.push(y);
11
+ }
12
+ ys.sort((a, b)=>a - b);
13
+ return ys;
14
+ };
15
+ const asSvgElement = (el)=>el;
16
+ const dropEdgeGridLines = ({ keepTop = false, keepBottom = false } = {})=>{
17
+ let cachedYs = null;
18
+ let cachedAxis = null;
19
+ return (props)=>{
20
+ const { offset, x1, x2, y1, y2, key, index: _index, yAxis, ...rest } = props;
21
+ const line = asSvgElement(createElement('line', {
22
+ ...rest,
23
+ x1,
24
+ x2,
25
+ y1,
26
+ y2
27
+ }));
28
+ if ('number' != typeof y1 || !yAxis) return line;
29
+ if (cachedAxis !== yAxis) {
30
+ cachedAxis = yAxis;
31
+ cachedYs = collectTickYs(yAxis);
32
+ }
33
+ const ys = cachedYs;
34
+ const [topY, secondY] = ys;
35
+ const bottomY = ys[ys.length - 1];
36
+ if (void 0 === topY || void 0 === secondY || void 0 === bottomY) return line;
37
+ const spacing = secondY - topY;
38
+ if (!keepBottom && Math.abs(y1 - bottomY) < 0.5) return asSvgElement(createElement('g', {
39
+ key
40
+ }));
41
+ if (keepTop || spacing <= 0 || Math.abs(y1 - topY) >= 0.5) return line;
42
+ if (topY - offset.top < spacing * TOP_LINE_GAP_THRESHOLD) return asSvgElement(createElement('g', {
43
+ key
44
+ }));
45
+ return line;
46
+ };
47
+ };
48
+ export { dropEdgeGridLines };
@@ -0,0 +1,9 @@
1
+ import type { LineChartZoomRange } from '../LineChartContext';
2
+ /**
3
+ * Default range text for the zoom popover. Renders as `from → to` using the
4
+ * shared {@link formatChartDateTime} helper for numeric (timestamp) X values,
5
+ * which respects the app-level `order` / `hourCycle` defaults from the
6
+ * `DateFormatProvider`. Falls back to `String(value)` for non-numeric X values.
7
+ * Consumers override via the `formatRange` prop on `<LineChartZoomBrush>`.
8
+ */
9
+ export declare const formatRange: (range: LineChartZoomRange) => string;
@@ -0,0 +1,7 @@
1
+ import { formatChartDateTime } from "../../lib/timeFormatters.js";
2
+ const formatRange = (range)=>{
3
+ const from = formatChartDateTime(range.from) || String(range.from);
4
+ const to = formatChartDateTime(range.to) || String(range.to);
5
+ return `${from} → ${to}`;
6
+ };
7
+ export { formatRange };
@@ -0,0 +1,15 @@
1
+ import type { LineChartDatum, LineChartSeries } from '../LineChartContext';
2
+ export declare const genHourly: (count: number, seed?: number) => LineChartDatum[];
3
+ export declare const genDaily: (count: number) => LineChartDatum[];
4
+ export declare const singleSeries: LineChartSeries[];
5
+ export declare const multiSeries: LineChartSeries[];
6
+ export declare const dashedSeries: LineChartSeries[];
7
+ export declare const customColorSeries: LineChartSeries[];
8
+ export declare const hourlyData24: LineChartDatum[];
9
+ export declare const hourlyDataA: LineChartDatum[];
10
+ export declare const hourlyDataB: LineChartDatum[];
11
+ export declare const dailyData60: LineChartDatum[];
12
+ export declare const hourlyData1000: LineChartDatum[];
13
+ export declare const singlePointData: LineChartDatum[];
14
+ export declare const dataWithErrorGaps: LineChartDatum[];
15
+ export declare const unitsByKey: Record<string, string>;
@@ -0,0 +1,109 @@
1
+ const jitter = (i, seed, salt)=>{
2
+ const v = 43758.5453 * Math.sin((i + seed) * salt);
3
+ return v - Math.floor(v);
4
+ };
5
+ const genHourly = (count, seed = 1)=>{
6
+ const start = Date.UTC(2025, 0, 1, 0, 0, 0);
7
+ const out = [];
8
+ for(let i = 0; i < count; i++){
9
+ const t = start + 60 * i * 60000;
10
+ const requests = Math.round(120 + 30 * Math.sin((i + seed) / 4) + (jitter(i, seed, 12.9898) - 0.5) * 80);
11
+ const errors = Math.round(24 + 10 * Math.cos((i + seed) / 5) + (jitter(i, seed, 78.233) - 0.5) * 32);
12
+ const latency = Math.round(80 + 14 * Math.sin((i + seed) / 6) + (jitter(i, seed, 39.346) - 0.5) * 40);
13
+ out.push({
14
+ timestamp: t,
15
+ requests,
16
+ errors,
17
+ latency
18
+ });
19
+ }
20
+ return out;
21
+ };
22
+ const genDaily = (count)=>{
23
+ const start = Date.UTC(2024, 0, 1, 0, 0, 0);
24
+ const out = [];
25
+ for(let i = 0; i < count; i++){
26
+ const t = start + 24 * i * 3600000;
27
+ const requests = Math.round(1000 + 400 * Math.sin(i / 9) + i % 13 * 12);
28
+ const errors = Math.round(80 + 30 * Math.cos(i / 11) + i % 7 * 3);
29
+ out.push({
30
+ timestamp: t,
31
+ requests,
32
+ errors
33
+ });
34
+ }
35
+ return out;
36
+ };
37
+ const singleSeries = [
38
+ {
39
+ key: 'requests',
40
+ label: 'Requests',
41
+ color: 'brand'
42
+ }
43
+ ];
44
+ const multiSeries = [
45
+ {
46
+ key: 'requests',
47
+ label: 'Requests',
48
+ color: 'brand'
49
+ },
50
+ {
51
+ key: 'errors',
52
+ label: 'Errors',
53
+ color: 'red'
54
+ },
55
+ {
56
+ key: 'latency',
57
+ label: 'Latency',
58
+ color: 'blue'
59
+ }
60
+ ];
61
+ const dashedSeries = [
62
+ {
63
+ key: 'requests',
64
+ label: 'Requests',
65
+ color: 'brand'
66
+ },
67
+ {
68
+ key: 'errors',
69
+ label: 'Errors (target)',
70
+ color: 'red',
71
+ variant: 'dashed'
72
+ }
73
+ ];
74
+ const customColorSeries = [
75
+ {
76
+ key: 'requests',
77
+ label: 'Requests',
78
+ color: 'var(--color-violet-500)'
79
+ },
80
+ {
81
+ key: 'errors',
82
+ label: 'Errors',
83
+ color: 'var(--color-emerald-500)'
84
+ }
85
+ ];
86
+ const hourlyData24 = genHourly(24);
87
+ const hourlyDataA = genHourly(24, 1);
88
+ const hourlyDataB = genHourly(24, 7);
89
+ const dailyData60 = genDaily(60);
90
+ const hourlyData1000 = genHourly(1000);
91
+ const singlePointData = [
92
+ {
93
+ timestamp: Date.UTC(2025, 0, 1, 12, 0, 0),
94
+ requests: 142
95
+ }
96
+ ];
97
+ const dataWithErrorGaps = hourlyData24.map((d, i)=>{
98
+ if (i >= 6 && i <= 8 || i >= 15 && i <= 16) return {
99
+ ...d,
100
+ errors: null
101
+ };
102
+ return d;
103
+ });
104
+ const unitsByKey = {
105
+ requests: ' req',
106
+ errors: ' err',
107
+ latency: ' ms'
108
+ };
109
+ export { customColorSeries, dailyData60, dashedSeries, dataWithErrorGaps, genDaily, genHourly, hourlyData1000, hourlyData24, hourlyDataA, hourlyDataB, multiSeries, singlePointData, singleSeries, unitsByKey };
@@ -0,0 +1,15 @@
1
+ import type { HorizontalCoordinatesGenerator } from 'recharts/types/cartesian/CartesianGrid';
2
+ /**
3
+ * `<CartesianGrid horizontalCoordinatesGenerator>` that emits one grid line
4
+ * per Y-axis tick.
5
+ *
6
+ * The recharts v3 default skips some ticks (notably the second-from-top) and
7
+ * folds the topmost grid line onto the plot's top edge instead of placing it
8
+ * at the topmost tick. That breaks the one-line-per-label visual contract:
9
+ * a label can appear with no corresponding grid line.
10
+ *
11
+ * Using `yAxis.niceTicks ?? yAxis.ticks` and mapping each through the axis
12
+ * scale produces a grid line at every rendered tick value. `dropEdgeGridLines`
13
+ * then handles top/bottom culling against the resulting coordinates.
14
+ */
15
+ export declare const tickHorizontalCoordinates: HorizontalCoordinatesGenerator;
@@ -0,0 +1,13 @@
1
+ const tickHorizontalCoordinates = ({ yAxis })=>{
2
+ if (!yAxis) return [];
3
+ const { scale } = yAxis;
4
+ const tickValues = yAxis.niceTicks ?? yAxis.ticks;
5
+ if (!scale || !tickValues?.length) return [];
6
+ const coords = [];
7
+ for (const tick of tickValues){
8
+ const y = scale.map(tick);
9
+ if ('number' == typeof y && Number.isFinite(y)) coords.push(y);
10
+ }
11
+ return coords;
12
+ };
13
+ export { tickHorizontalCoordinates };
@@ -0,0 +1,4 @@
1
+ type WarnFn = (...args: unknown[]) => void;
2
+ export declare const warnLineChart: WarnFn;
3
+ export declare const warnLineChartLine: WarnFn;
4
+ export {};
@@ -0,0 +1,6 @@
1
+ const PROD = ()=>{};
2
+ const DEV = console.warn;
3
+ const make = (component)=>'production' === process.env.NODE_ENV ? PROD : DEV.bind(console, `[${component}]`);
4
+ const warnLineChart = make('LineChart');
5
+ const warnLineChartLine = make('LineChartLine');
6
+ export { warnLineChart, warnLineChartLine };
@@ -1,7 +1,10 @@
1
1
  import { createContext } from "react";
2
+ import { makeIsHoverSyncTarget } from "../lib/hoverSync.js";
2
3
  const EMPTY_SELECTION = new Set();
3
- const HOVER_SYNC_SELECTOR = '[data-slot="pie-chart-legend-item"], [data-slot="pie-chart-slice"]';
4
- const isHoverSyncTarget = (target)=>target instanceof Element && null !== target.closest(HOVER_SYNC_SELECTOR);
4
+ const isHoverSyncTarget = makeIsHoverSyncTarget([
5
+ 'pie-chart-legend-item',
6
+ 'pie-chart-slice'
7
+ ]);
5
8
  const PieChartDataContext = createContext(null);
6
9
  const PieChartActiveContext = createContext({
7
10
  activeName: null
@@ -1,4 +1,4 @@
1
- import type { ChartColor } from '../types';
1
+ export { CHART_PALETTE_FILL as PIE_SLICE_FILL } from '../lib/chartPalette';
2
2
  export declare const PIE_DONUT_SIZE = 120;
3
3
  export declare const PIE_DONUT_OUTER_RADIUS = 60;
4
4
  export declare const PIE_DONUT_INNER_RADIUS = 48;
@@ -6,4 +6,3 @@ export declare const PIE_DONUT_CORNER_RADIUS = 2;
6
6
  export declare const PIE_DONUT_PADDING_ANGLE = 2;
7
7
  export declare const PIE_DONUT_ANIMATION_DURATION = 400;
8
8
  export declare const PIE_DONUT_ANIMATION_BEGIN = 0;
9
- export declare const PIE_SLICE_FILL: Record<ChartColor, string>;
@@ -1,3 +1,4 @@
1
+ import { CHART_PALETTE_FILL } from "../lib/chartPalette.js";
1
2
  const PIE_DONUT_SIZE = 120;
2
3
  const PIE_DONUT_OUTER_RADIUS = 60;
3
4
  const PIE_DONUT_INNER_RADIUS = 48;
@@ -5,18 +6,4 @@ const PIE_DONUT_CORNER_RADIUS = 2;
5
6
  const PIE_DONUT_PADDING_ANGLE = 2;
6
7
  const PIE_DONUT_ANIMATION_DURATION = 400;
7
8
  const PIE_DONUT_ANIMATION_BEGIN = 0;
8
- const PIE_SLICE_FILL = {
9
- brand: 'var(--color-w-orange-500)',
10
- blue: 'var(--color-blue-500)',
11
- green: 'var(--color-green-500)',
12
- red: 'var(--color-red-500)',
13
- amber: 'var(--color-amber-500)',
14
- purple: 'var(--color-purple-500)',
15
- slate: 'var(--color-badge-slate-dark-alt)',
16
- teal: 'var(--color-teal-500)',
17
- cyan: 'var(--color-cyan-500)',
18
- indigo: 'var(--color-indigo-500)',
19
- pink: 'var(--color-pink-500)',
20
- rose: 'var(--color-rose-500)'
21
- };
22
- export { PIE_DONUT_ANIMATION_BEGIN, PIE_DONUT_ANIMATION_DURATION, PIE_DONUT_CORNER_RADIUS, PIE_DONUT_INNER_RADIUS, PIE_DONUT_OUTER_RADIUS, PIE_DONUT_PADDING_ANGLE, PIE_DONUT_SIZE, PIE_SLICE_FILL };
9
+ export { PIE_DONUT_ANIMATION_BEGIN, PIE_DONUT_ANIMATION_DURATION, PIE_DONUT_CORNER_RADIUS, PIE_DONUT_INNER_RADIUS, PIE_DONUT_OUTER_RADIUS, PIE_DONUT_PADDING_ANGLE, PIE_DONUT_SIZE, CHART_PALETTE_FILL as PIE_SLICE_FILL };
@@ -0,0 +1 @@
1
+ export { type ChartTimeFormatters, useChartTimeFormatters, } from './useChartTimeFormatters';
@@ -0,0 +1,2 @@
1
+ import { useChartTimeFormatters } from "./useChartTimeFormatters.js";
2
+ export { useChartTimeFormatters };
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface ChartTimeFormatters {
3
+ formatHour: (value: unknown) => string;
4
+ formatDate: (value: unknown) => string;
5
+ formatDateTime: (value: unknown) => string;
6
+ formatTimezone: (value: unknown) => string;
7
+ formatHourWithTimezone: (value: unknown) => ReactNode;
8
+ formatDateWithTimezone: (value: unknown) => ReactNode;
9
+ formatDateTimeWithTimezone: (value: unknown) => ReactNode;
10
+ /** `from → to` using `formatDate`. Suitable for `<LineChartZoomBrush formatRange>`. */
11
+ formatDateRange: (range: {
12
+ from: unknown;
13
+ to: unknown;
14
+ }) => string;
15
+ }
16
+ /**
17
+ * Memoised bundle of chart time formatters bound to `DateFormatProvider`
18
+ * settings. Falls back to `day-first` + `hourCycle: 24` when no provider is
19
+ * mounted (mirrors `useDateFormat`).
20
+ */
21
+ export declare const useChartTimeFormatters: () => ChartTimeFormatters;