@misoto22/design 0.3.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -0
- package/bin/misoto22-design.mjs +205 -0
- package/dist/agent/Accordion.md +41 -0
- package/dist/agent/Alert.md +42 -0
- package/dist/agent/AppShell.md +40 -0
- package/dist/agent/AreaChart.md +68 -0
- package/dist/agent/Article.md +41 -0
- package/dist/agent/Avatar.md +32 -0
- package/dist/agent/Badge.md +40 -0
- package/dist/agent/BarChart.md +65 -0
- package/dist/agent/BarList.md +40 -0
- package/dist/agent/BigNumber.md +45 -0
- package/dist/agent/BoxPlot.md +58 -0
- package/dist/agent/Breadcrumb.md +32 -0
- package/dist/agent/BulletChart.md +48 -0
- package/dist/agent/Button.md +56 -0
- package/dist/agent/Calendar.md +42 -0
- package/dist/agent/Card.md +49 -0
- package/dist/agent/Checkbox.md +35 -0
- package/dist/agent/Collapsible.md +46 -0
- package/dist/agent/Combobox.md +50 -0
- package/dist/agent/Command.md +93 -0
- package/dist/agent/ComposedChart.md +57 -0
- package/dist/agent/ContextMenu.md +59 -0
- package/dist/agent/DatePicker.md +75 -0
- package/dist/agent/Diagram.md +46 -0
- package/dist/agent/Dialog.md +52 -0
- package/dist/agent/DropdownMenu.md +70 -0
- package/dist/agent/EmptyState.md +37 -0
- package/dist/agent/ErrorState.md +41 -0
- package/dist/agent/Facet.md +82 -0
- package/dist/agent/Field.md +37 -0
- package/dist/agent/FigureBand.md +37 -0
- package/dist/agent/FloatingIconButton.md +38 -0
- package/dist/agent/FunnelChart.md +52 -0
- package/dist/agent/Heatmap.md +53 -0
- package/dist/agent/Histogram.md +63 -0
- package/dist/agent/Input.md +30 -0
- package/dist/agent/Kbd.md +29 -0
- package/dist/agent/LineChart.md +60 -0
- package/dist/agent/LinkArrow.md +29 -0
- package/dist/agent/NativeSelect.md +40 -0
- package/dist/agent/NavItem.md +35 -0
- package/dist/agent/Pagination.md +43 -0
- package/dist/agent/PieChart.md +55 -0
- package/dist/agent/Popover.md +57 -0
- package/dist/agent/Progress.md +33 -0
- package/dist/agent/RadarChart.md +54 -0
- package/dist/agent/RadialChart.md +57 -0
- package/dist/agent/RadioGroup.md +44 -0
- package/dist/agent/SankeyChart.md +61 -0
- package/dist/agent/ScatterChart.md +54 -0
- package/dist/agent/ScrollArea.md +40 -0
- package/dist/agent/SearchableMenu.md +46 -0
- package/dist/agent/Select.md +75 -0
- package/dist/agent/Separator.md +35 -0
- package/dist/agent/Sheet.md +57 -0
- package/dist/agent/Skeleton.md +73 -0
- package/dist/agent/Slider.md +39 -0
- package/dist/agent/Sparkline.md +45 -0
- package/dist/agent/Spinner.md +39 -0
- package/dist/agent/StatusDot.md +36 -0
- package/dist/agent/StatusPill.md +28 -0
- package/dist/agent/Steps.md +44 -0
- package/dist/agent/Switch.md +29 -0
- package/dist/agent/Table.md +85 -0
- package/dist/agent/Tabs.md +48 -0
- package/dist/agent/Tag.md +35 -0
- package/dist/agent/Textarea.md +26 -0
- package/dist/agent/Toast.md +26 -0
- package/dist/agent/ToggleGroup.md +44 -0
- package/dist/agent/Tooltip.md +51 -0
- package/dist/agent/TreemapChart.md +52 -0
- package/dist/agent/WaterfallChart.md +62 -0
- package/dist/agent/catalog.json +1791 -0
- package/dist/agent/index.md +131 -0
- package/dist/article.css +393 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +191 -0
- package/dist/charts/AreaChart/AreaChart.js +480 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +179 -0
- package/dist/charts/BarChart/BarChart.js +591 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +57 -0
- package/dist/charts/BarList/BarList.js +71 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +56 -0
- package/dist/charts/BigNumber/BigNumber.js +31 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +495 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +162 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +171 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +101 -0
- package/dist/charts/FunnelChart/FunnelChart.js +147 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +78 -0
- package/dist/charts/Heatmap/Heatmap.js +108 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +165 -0
- package/dist/charts/Histogram/Histogram.js +350 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +167 -0
- package/dist/charts/LineChart/LineChart.js +486 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +128 -0
- package/dist/charts/PieChart/PieChart.js +309 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +123 -0
- package/dist/charts/RadarChart/RadarChart.js +299 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +124 -0
- package/dist/charts/RadialChart/RadialChart.js +257 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +137 -0
- package/dist/charts/SankeyChart/SankeyChart.js +501 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +128 -0
- package/dist/charts/ScatterChart/ScatterChart.js +269 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +93 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +93 -0
- package/dist/charts/TreemapChart/TreemapChart.js +118 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +319 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +41 -0
- package/dist/charts/index.js +128 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +134 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +13 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +103 -0
- package/dist/charts/lib/export.js +204 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +61 -0
- package/dist/charts/lib/figure.js +59 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +143 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +15 -1
- package/dist/components/AppShell/AppShell.js +8 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +51 -0
- package/dist/components/Article/Article.js +21 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/Button/Button.js +2 -2
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +1 -1
- package/dist/components/Calendar/Calendar.js +259 -24
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.d.ts +15 -1
- package/dist/components/Collapsible/Collapsible.js +18 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.js +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.js +7 -7
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js +2 -2
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/Diagram/Diagram.d.ts +81 -0
- package/dist/components/Diagram/Diagram.js +139 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.js +1 -1
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js +2 -2
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/FigureBand/FigureBand.js +41 -30
- package/dist/components/FigureBand/FigureBand.js.map +1 -1
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Select/Select.js +2 -2
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Sheet/Sheet.js +1 -1
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Slider/Slider.js +1 -1
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +55 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.js +1 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +1 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/useSelectionIndicator.js +14 -10
- package/dist/lib/useSelectionIndicator.js.map +1 -1
- package/dist/semantic.css +19 -0
- package/dist/styles.css +1 -1
- package/dist/themes.css +103 -7
- package/dist/tokens.css +193 -10
- package/dist/tokens.d.ts +25 -0
- package/dist/tokens.js +154 -8
- package/dist/tokens.json +154 -8
- package/package.json +45 -20
- package/skills/misoto22-design/SKILL.md +171 -0
- package/skills/misoto22-design/evals/claims.json +95 -0
- package/skills/misoto22-design/rules/a11y.md +115 -0
- package/skills/misoto22-design/rules/composition.md +108 -0
- package/skills/misoto22-design/rules/forms.md +128 -0
- package/skills/misoto22-design/rules/naming.md +155 -0
- package/skills/misoto22-design/rules/tokens.md +131 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
Fragment as Fragment2,
|
|
5
|
+
useCallback,
|
|
6
|
+
useDeferredValue,
|
|
7
|
+
useEffect,
|
|
8
|
+
useId,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef,
|
|
11
|
+
useState,
|
|
12
|
+
startTransition
|
|
13
|
+
} from "react";
|
|
14
|
+
import {
|
|
15
|
+
motion,
|
|
16
|
+
useMotionValue,
|
|
17
|
+
useMotionValueEvent,
|
|
18
|
+
useSpring,
|
|
19
|
+
useTransform
|
|
20
|
+
} from "motion/react";
|
|
21
|
+
import {
|
|
22
|
+
Area,
|
|
23
|
+
AreaChart,
|
|
24
|
+
Bar,
|
|
25
|
+
BarChart,
|
|
26
|
+
Line,
|
|
27
|
+
LineChart,
|
|
28
|
+
ResponsiveContainer
|
|
29
|
+
} from "recharts";
|
|
30
|
+
import { cn } from "../../lib/cn.js";
|
|
31
|
+
import { colorStops } from "./chart.js";
|
|
32
|
+
const Brush = () => null;
|
|
33
|
+
const SPRING = { stiffness: 300, damping: 35, mass: 0.8 };
|
|
34
|
+
function useBrushDrag({
|
|
35
|
+
range,
|
|
36
|
+
totalPoints,
|
|
37
|
+
containerRef,
|
|
38
|
+
commit
|
|
39
|
+
}) {
|
|
40
|
+
const drag = useRef(null);
|
|
41
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
42
|
+
const toIndexDelta = useCallback(
|
|
43
|
+
(px) => {
|
|
44
|
+
const width = containerRef.current?.getBoundingClientRect().width ?? 0;
|
|
45
|
+
if (!width || totalPoints <= 1) return 0;
|
|
46
|
+
return Math.round(px / width * (totalPoints - 1));
|
|
47
|
+
},
|
|
48
|
+
[containerRef, totalPoints]
|
|
49
|
+
);
|
|
50
|
+
const onPointerDown = useCallback(
|
|
51
|
+
(event, kind) => {
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
event.target.setPointerCapture(event.pointerId);
|
|
54
|
+
drag.current = { kind, originX: event.clientX, originRange: { ...range } };
|
|
55
|
+
setIsDragging(true);
|
|
56
|
+
},
|
|
57
|
+
[range]
|
|
58
|
+
);
|
|
59
|
+
const onPointerMove = useCallback(
|
|
60
|
+
(event) => {
|
|
61
|
+
const state = drag.current;
|
|
62
|
+
if (!state) return;
|
|
63
|
+
const delta = toIndexDelta(event.clientX - state.originX);
|
|
64
|
+
const origin = state.originRange;
|
|
65
|
+
if (state.kind === "start") {
|
|
66
|
+
commit({ startIndex: origin.startIndex + delta, endIndex: origin.endIndex }, "start");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (state.kind === "end") {
|
|
70
|
+
commit({ startIndex: origin.startIndex, endIndex: origin.endIndex + delta }, "end");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const span = origin.endIndex - origin.startIndex;
|
|
74
|
+
let start = origin.startIndex + delta;
|
|
75
|
+
let end = start + span;
|
|
76
|
+
if (start < 0) {
|
|
77
|
+
start = 0;
|
|
78
|
+
end = span;
|
|
79
|
+
}
|
|
80
|
+
if (end > totalPoints - 1) {
|
|
81
|
+
end = totalPoints - 1;
|
|
82
|
+
start = Math.max(0, end - span);
|
|
83
|
+
}
|
|
84
|
+
commit({ startIndex: start, endIndex: end }, "pan");
|
|
85
|
+
},
|
|
86
|
+
[commit, toIndexDelta, totalPoints]
|
|
87
|
+
);
|
|
88
|
+
const onPointerUp = useCallback((event) => {
|
|
89
|
+
;
|
|
90
|
+
event.target.releasePointerCapture(event.pointerId);
|
|
91
|
+
drag.current = null;
|
|
92
|
+
setIsDragging(false);
|
|
93
|
+
}, []);
|
|
94
|
+
const bind = useCallback(
|
|
95
|
+
(kind) => ({
|
|
96
|
+
onPointerDown: (event) => onPointerDown(event, kind),
|
|
97
|
+
onPointerMove,
|
|
98
|
+
onPointerUp
|
|
99
|
+
}),
|
|
100
|
+
[onPointerDown, onPointerMove, onPointerUp]
|
|
101
|
+
);
|
|
102
|
+
return { isDragging, bind };
|
|
103
|
+
}
|
|
104
|
+
function ChartBrush({
|
|
105
|
+
data,
|
|
106
|
+
config,
|
|
107
|
+
dataKeys,
|
|
108
|
+
xDataKey,
|
|
109
|
+
variant = "area",
|
|
110
|
+
height = 56,
|
|
111
|
+
className,
|
|
112
|
+
stacked = false,
|
|
113
|
+
strokeVariant = "solid",
|
|
114
|
+
connectNulls = false,
|
|
115
|
+
barRadius,
|
|
116
|
+
startIndex: controlledStart,
|
|
117
|
+
endIndex: controlledEnd,
|
|
118
|
+
defaultStartIndex = 0,
|
|
119
|
+
defaultEndIndex,
|
|
120
|
+
onChange,
|
|
121
|
+
formatLabel,
|
|
122
|
+
curveType = "monotone",
|
|
123
|
+
minSpan = 2,
|
|
124
|
+
showLabels = true,
|
|
125
|
+
label = "Visible range"
|
|
126
|
+
}) {
|
|
127
|
+
const containerRef = useRef(null);
|
|
128
|
+
const keys = useMemo(() => dataKeys ?? Object.keys(config), [dataKeys, config]);
|
|
129
|
+
const totalPoints = data.length;
|
|
130
|
+
const maxIndex = Math.max(0, totalPoints - 1);
|
|
131
|
+
const isControlled = controlledStart !== void 0 && controlledEnd !== void 0;
|
|
132
|
+
const [range, setRange] = useState(() => ({
|
|
133
|
+
startIndex: Math.max(0, Math.min(defaultStartIndex, maxIndex)),
|
|
134
|
+
endIndex: Math.max(0, Math.min(defaultEndIndex ?? maxIndex, maxIndex))
|
|
135
|
+
}));
|
|
136
|
+
const committed = useRef(range);
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
if (isControlled) return;
|
|
139
|
+
setRange((previous) => {
|
|
140
|
+
const adjusted = {
|
|
141
|
+
startIndex: Math.min(previous.startIndex, maxIndex),
|
|
142
|
+
endIndex: Math.min(previous.endIndex, maxIndex)
|
|
143
|
+
};
|
|
144
|
+
committed.current = adjusted;
|
|
145
|
+
return adjusted;
|
|
146
|
+
});
|
|
147
|
+
}, [isControlled, maxIndex]);
|
|
148
|
+
const clamp = useCallback(
|
|
149
|
+
(next, kind) => {
|
|
150
|
+
let startIndex = Math.max(0, Math.min(next.startIndex, maxIndex));
|
|
151
|
+
let endIndex = Math.max(0, Math.min(next.endIndex, maxIndex));
|
|
152
|
+
if (kind === "start") {
|
|
153
|
+
return { startIndex: Math.min(startIndex, Math.max(0, endIndex - minSpan)), endIndex };
|
|
154
|
+
}
|
|
155
|
+
if (kind === "end") {
|
|
156
|
+
return { startIndex, endIndex: Math.max(endIndex, Math.min(maxIndex, startIndex + minSpan)) };
|
|
157
|
+
}
|
|
158
|
+
if (endIndex - startIndex < minSpan) {
|
|
159
|
+
endIndex = Math.min(startIndex + minSpan, maxIndex);
|
|
160
|
+
if (endIndex - startIndex < minSpan) startIndex = Math.max(0, endIndex - minSpan);
|
|
161
|
+
}
|
|
162
|
+
return { startIndex, endIndex };
|
|
163
|
+
},
|
|
164
|
+
[maxIndex, minSpan]
|
|
165
|
+
);
|
|
166
|
+
const commit = useCallback(
|
|
167
|
+
(next, kind) => {
|
|
168
|
+
const clamped = clamp(next, kind);
|
|
169
|
+
const last = committed.current;
|
|
170
|
+
if (last.startIndex === clamped.startIndex && last.endIndex === clamped.endIndex) return;
|
|
171
|
+
committed.current = clamped;
|
|
172
|
+
setRange(clamped);
|
|
173
|
+
startTransition(() => onChange?.(clamped));
|
|
174
|
+
},
|
|
175
|
+
[clamp, onChange]
|
|
176
|
+
);
|
|
177
|
+
const { isDragging, bind } = useBrushDrag({ range, totalPoints, containerRef, commit });
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (!isControlled || isDragging) return;
|
|
180
|
+
const synced = { startIndex: controlledStart, endIndex: controlledEnd };
|
|
181
|
+
setRange(synced);
|
|
182
|
+
committed.current = synced;
|
|
183
|
+
}, [controlledEnd, controlledStart, isControlled, isDragging]);
|
|
184
|
+
const startPercent = maxIndex > 0 ? range.startIndex / maxIndex * 100 : 0;
|
|
185
|
+
const endPercent = maxIndex > 0 ? range.endIndex / maxIndex * 100 : 100;
|
|
186
|
+
const startTarget = useMotionValue(startPercent);
|
|
187
|
+
const endTarget = useMotionValue(endPercent);
|
|
188
|
+
if (startTarget.get() !== startPercent) startTarget.set(startPercent);
|
|
189
|
+
if (endTarget.get() !== endPercent) endTarget.set(endPercent);
|
|
190
|
+
const startSpring = useSpring(startTarget, SPRING);
|
|
191
|
+
const endSpring = useSpring(endTarget, SPRING);
|
|
192
|
+
const startEdge = useTransform(startSpring, (value) => `${value}%`);
|
|
193
|
+
const endEdge = useTransform(endSpring, (value) => `${value}%`);
|
|
194
|
+
const dimBefore = useTransform(startSpring, (value) => `${value}%`);
|
|
195
|
+
const dimAfter = useTransform(endSpring, (value) => `${Math.max(0, 100 - value)}%`);
|
|
196
|
+
const spanWidth = useMotionValue(`${Math.max(0, endPercent - startPercent)}%`);
|
|
197
|
+
const syncSpan = useCallback(() => {
|
|
198
|
+
spanWidth.set(`${Math.max(0, endSpring.get() - startSpring.get())}%`);
|
|
199
|
+
}, [endSpring, spanWidth, startSpring]);
|
|
200
|
+
useMotionValueEvent(startSpring, "change", syncSpan);
|
|
201
|
+
useMotionValueEvent(endSpring, "change", syncSpan);
|
|
202
|
+
const labelAt = useCallback(
|
|
203
|
+
(index) => {
|
|
204
|
+
if (!xDataKey) return String(index);
|
|
205
|
+
const value = data[index]?.[xDataKey];
|
|
206
|
+
return formatLabel ? formatLabel(value, index) : String(value ?? index);
|
|
207
|
+
},
|
|
208
|
+
[data, formatLabel, xDataKey]
|
|
209
|
+
);
|
|
210
|
+
const nudge = useCallback(
|
|
211
|
+
(kind, step) => {
|
|
212
|
+
const next = kind === "start" ? { startIndex: range.startIndex + step, endIndex: range.endIndex } : { startIndex: range.startIndex, endIndex: range.endIndex + step };
|
|
213
|
+
commit(next, kind);
|
|
214
|
+
},
|
|
215
|
+
[commit, range.endIndex, range.startIndex]
|
|
216
|
+
);
|
|
217
|
+
if (totalPoints === 0) return null;
|
|
218
|
+
return /* @__PURE__ */ jsxs(
|
|
219
|
+
"div",
|
|
220
|
+
{
|
|
221
|
+
ref: containerRef,
|
|
222
|
+
className: cn("group relative select-none", className),
|
|
223
|
+
style: { height },
|
|
224
|
+
children: [
|
|
225
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 overflow-hidden rounded-(--radius-sm)", children: /* @__PURE__ */ jsx(
|
|
226
|
+
BrushStrip,
|
|
227
|
+
{
|
|
228
|
+
data,
|
|
229
|
+
keys,
|
|
230
|
+
config,
|
|
231
|
+
variant,
|
|
232
|
+
curveType,
|
|
233
|
+
stacked,
|
|
234
|
+
strokeVariant,
|
|
235
|
+
connectNulls,
|
|
236
|
+
barRadius
|
|
237
|
+
}
|
|
238
|
+
) }),
|
|
239
|
+
/* @__PURE__ */ jsx(
|
|
240
|
+
motion.div,
|
|
241
|
+
{
|
|
242
|
+
"aria-hidden": true,
|
|
243
|
+
className: "pointer-events-none absolute inset-y-0 rounded-(--radius-sm) bg-(--chart-surface)/70 backdrop-blur-[2px]",
|
|
244
|
+
style: { left: 0, width: dimBefore }
|
|
245
|
+
}
|
|
246
|
+
),
|
|
247
|
+
/* @__PURE__ */ jsx(
|
|
248
|
+
motion.div,
|
|
249
|
+
{
|
|
250
|
+
"aria-hidden": true,
|
|
251
|
+
className: "pointer-events-none absolute inset-y-0 rounded-(--radius-sm) bg-(--chart-surface)/70 backdrop-blur-[2px]",
|
|
252
|
+
style: { right: 0, width: dimAfter }
|
|
253
|
+
}
|
|
254
|
+
),
|
|
255
|
+
/* @__PURE__ */ jsx(
|
|
256
|
+
motion.div,
|
|
257
|
+
{
|
|
258
|
+
"aria-hidden": true,
|
|
259
|
+
className: "absolute inset-y-0 cursor-grab touch-none rounded-(--radius-sm) border border-(--rule-2) active:cursor-grabbing",
|
|
260
|
+
style: { left: startEdge, width: spanWidth },
|
|
261
|
+
...bind("pan")
|
|
262
|
+
}
|
|
263
|
+
),
|
|
264
|
+
/* @__PURE__ */ jsx(
|
|
265
|
+
BrushHandle,
|
|
266
|
+
{
|
|
267
|
+
kind: "start",
|
|
268
|
+
edge: startEdge,
|
|
269
|
+
label,
|
|
270
|
+
valueLabel: labelAt(range.startIndex),
|
|
271
|
+
showLabel: showLabels,
|
|
272
|
+
index: range.startIndex,
|
|
273
|
+
max: maxIndex,
|
|
274
|
+
bind: bind("start"),
|
|
275
|
+
onNudge: nudge
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
/* @__PURE__ */ jsx(
|
|
279
|
+
BrushHandle,
|
|
280
|
+
{
|
|
281
|
+
kind: "end",
|
|
282
|
+
edge: endEdge,
|
|
283
|
+
label,
|
|
284
|
+
valueLabel: labelAt(range.endIndex),
|
|
285
|
+
showLabel: showLabels,
|
|
286
|
+
index: range.endIndex,
|
|
287
|
+
max: maxIndex,
|
|
288
|
+
bind: bind("end"),
|
|
289
|
+
onNudge: nudge
|
|
290
|
+
}
|
|
291
|
+
)
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
function BrushHandle({
|
|
297
|
+
kind,
|
|
298
|
+
edge,
|
|
299
|
+
label,
|
|
300
|
+
valueLabel,
|
|
301
|
+
showLabel,
|
|
302
|
+
index,
|
|
303
|
+
max,
|
|
304
|
+
bind,
|
|
305
|
+
onNudge
|
|
306
|
+
}) {
|
|
307
|
+
const isStart = kind === "start";
|
|
308
|
+
const onKeyDown = (event) => {
|
|
309
|
+
const steps = {
|
|
310
|
+
ArrowLeft: -1,
|
|
311
|
+
ArrowDown: -1,
|
|
312
|
+
ArrowRight: 1,
|
|
313
|
+
ArrowUp: 1,
|
|
314
|
+
PageDown: -5,
|
|
315
|
+
PageUp: 5
|
|
316
|
+
};
|
|
317
|
+
if (event.key === "Home") {
|
|
318
|
+
event.preventDefault();
|
|
319
|
+
onNudge(kind, -max);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (event.key === "End") {
|
|
323
|
+
event.preventDefault();
|
|
324
|
+
onNudge(kind, max);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const step = steps[event.key];
|
|
328
|
+
if (step === void 0) return;
|
|
329
|
+
event.preventDefault();
|
|
330
|
+
onNudge(kind, step);
|
|
331
|
+
};
|
|
332
|
+
return /* @__PURE__ */ jsxs(motion.div, { className: "absolute inset-y-0 z-(--z-rule)", style: { left: edge }, children: [
|
|
333
|
+
/* @__PURE__ */ jsx(
|
|
334
|
+
"div",
|
|
335
|
+
{
|
|
336
|
+
role: "slider",
|
|
337
|
+
tabIndex: 0,
|
|
338
|
+
"aria-label": `${label} \u2014 ${isStart ? "start" : "end"}`,
|
|
339
|
+
"aria-valuemin": 0,
|
|
340
|
+
"aria-valuemax": max,
|
|
341
|
+
"aria-valuenow": index,
|
|
342
|
+
"aria-valuetext": valueLabel,
|
|
343
|
+
onKeyDown,
|
|
344
|
+
className: cn(
|
|
345
|
+
"group/handle absolute inset-y-0 flex w-3 cursor-ew-resize touch-none items-center justify-center",
|
|
346
|
+
"after:absolute after:inset-y-0 after:w-11 after:content-['']"
|
|
347
|
+
),
|
|
348
|
+
style: { left: 0, transform: isStart ? void 0 : "translateX(-100%)" },
|
|
349
|
+
...bind,
|
|
350
|
+
children: /* @__PURE__ */ jsxs(
|
|
351
|
+
"span",
|
|
352
|
+
{
|
|
353
|
+
"aria-hidden": true,
|
|
354
|
+
className: "flex h-4 w-1.5 flex-col items-center justify-center gap-[2px] rounded-(--radius-sm) bg-(--ink-3-aa) transition-colors duration-(--duration-fast) group-hover/handle:bg-(--ink) group-focus-visible/handle:bg-(--ink)",
|
|
355
|
+
children: [
|
|
356
|
+
/* @__PURE__ */ jsx("span", { className: "size-[2px] rounded-(--radius-pill) bg-(--chart-surface)/70" }),
|
|
357
|
+
/* @__PURE__ */ jsx("span", { className: "size-[2px] rounded-(--radius-pill) bg-(--chart-surface)/70" }),
|
|
358
|
+
/* @__PURE__ */ jsx("span", { className: "size-[2px] rounded-(--radius-pill) bg-(--chart-surface)/70" })
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
}
|
|
363
|
+
),
|
|
364
|
+
showLabel && /* @__PURE__ */ jsx(
|
|
365
|
+
"span",
|
|
366
|
+
{
|
|
367
|
+
"aria-hidden": true,
|
|
368
|
+
className: "pointer-events-none absolute -bottom-3 -translate-y-1/2 rounded-[3px] bg-(--ink) px-1 py-px text-[8px] leading-tight font-medium whitespace-nowrap text-(--paper) opacity-0 transition-opacity duration-(--duration-fast) group-hover:opacity-100",
|
|
369
|
+
style: isStart ? { left: "0.375rem" } : { right: "0.375rem" },
|
|
370
|
+
children: valueLabel
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
] });
|
|
374
|
+
}
|
|
375
|
+
function BrushStrip({
|
|
376
|
+
data,
|
|
377
|
+
keys,
|
|
378
|
+
config,
|
|
379
|
+
variant,
|
|
380
|
+
curveType,
|
|
381
|
+
stacked,
|
|
382
|
+
strokeVariant,
|
|
383
|
+
connectNulls,
|
|
384
|
+
barRadius
|
|
385
|
+
}) {
|
|
386
|
+
const id = `brush-${useId().replace(/:/g, "")}`;
|
|
387
|
+
const series = useMemo(
|
|
388
|
+
() => Object.entries(config).filter(([key]) => keys.includes(key)).map(([dataKey, entry]) => ({ dataKey, stops: colorStops(entry) })),
|
|
389
|
+
[config, keys]
|
|
390
|
+
);
|
|
391
|
+
const dash = strokeVariant === "dashed" ? "4 4" : void 0;
|
|
392
|
+
const defs = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
393
|
+
variant === "area" && /* @__PURE__ */ jsxs("linearGradient", { id: `${id}-fade`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
394
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "white", stopOpacity: 0.15 }),
|
|
395
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "white", stopOpacity: 0 })
|
|
396
|
+
] }),
|
|
397
|
+
series.map(({ dataKey, stops }) => /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
398
|
+
/* @__PURE__ */ jsx("linearGradient", { id: `${id}-${dataKey}`, x1: "0", y1: "0", x2: "0", y2: "1", children: stops === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
399
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: `var(--color-${dataKey}-0)` }),
|
|
400
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: `var(--color-${dataKey}-0)` })
|
|
401
|
+
] }) : Array.from({ length: stops }, (_, index) => /* @__PURE__ */ jsx(
|
|
402
|
+
"stop",
|
|
403
|
+
{
|
|
404
|
+
offset: `${index / (stops - 1) * 100}%`,
|
|
405
|
+
stopColor: `var(--color-${dataKey}-${index}, var(--color-${dataKey}-0))`
|
|
406
|
+
},
|
|
407
|
+
index
|
|
408
|
+
)) }),
|
|
409
|
+
variant === "area" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
410
|
+
/* @__PURE__ */ jsx("mask", { id: `${id}-fill-mask-${dataKey}`, children: /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id}-fade)` }) }),
|
|
411
|
+
/* @__PURE__ */ jsx(
|
|
412
|
+
"pattern",
|
|
413
|
+
{
|
|
414
|
+
id: `${id}-fill-${dataKey}`,
|
|
415
|
+
patternUnits: "userSpaceOnUse",
|
|
416
|
+
width: "100%",
|
|
417
|
+
height: "100%",
|
|
418
|
+
children: /* @__PURE__ */ jsx(
|
|
419
|
+
"rect",
|
|
420
|
+
{
|
|
421
|
+
width: "100%",
|
|
422
|
+
height: "100%",
|
|
423
|
+
fill: `url(#${id}-${dataKey})`,
|
|
424
|
+
mask: `url(#${id}-fill-mask-${dataKey})`
|
|
425
|
+
}
|
|
426
|
+
)
|
|
427
|
+
}
|
|
428
|
+
)
|
|
429
|
+
] })
|
|
430
|
+
] }, dataKey))
|
|
431
|
+
] });
|
|
432
|
+
if (variant === "line") {
|
|
433
|
+
return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(LineChart, { data, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
|
|
434
|
+
/* @__PURE__ */ jsx("defs", { children: defs }),
|
|
435
|
+
keys.map((key) => /* @__PURE__ */ jsx(
|
|
436
|
+
Line,
|
|
437
|
+
{
|
|
438
|
+
type: curveType,
|
|
439
|
+
dataKey: key,
|
|
440
|
+
stroke: `url(#${id}-${key})`,
|
|
441
|
+
strokeWidth: 1,
|
|
442
|
+
strokeOpacity: 0.5,
|
|
443
|
+
strokeDasharray: dash,
|
|
444
|
+
connectNulls,
|
|
445
|
+
dot: false,
|
|
446
|
+
activeDot: false,
|
|
447
|
+
isAnimationActive: false
|
|
448
|
+
},
|
|
449
|
+
key
|
|
450
|
+
))
|
|
451
|
+
] }) });
|
|
452
|
+
}
|
|
453
|
+
if (variant === "bar") {
|
|
454
|
+
const radius = barRadius ?? 3;
|
|
455
|
+
return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
|
|
456
|
+
BarChart,
|
|
457
|
+
{
|
|
458
|
+
data,
|
|
459
|
+
margin: { top: 2, right: 0, bottom: 0, left: 0 },
|
|
460
|
+
barGap: 2,
|
|
461
|
+
barSize: 14,
|
|
462
|
+
children: [
|
|
463
|
+
/* @__PURE__ */ jsx("defs", { children: defs }),
|
|
464
|
+
keys.map((key) => /* @__PURE__ */ jsx(
|
|
465
|
+
Bar,
|
|
466
|
+
{
|
|
467
|
+
dataKey: key,
|
|
468
|
+
fill: `url(#${id}-${key})`,
|
|
469
|
+
fillOpacity: 0.35,
|
|
470
|
+
stackId: stacked ? "brush-stack" : void 0,
|
|
471
|
+
isAnimationActive: false,
|
|
472
|
+
radius: [radius, radius, radius, radius]
|
|
473
|
+
},
|
|
474
|
+
key
|
|
475
|
+
))
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
) });
|
|
479
|
+
}
|
|
480
|
+
return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(AreaChart, { data, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
|
|
481
|
+
/* @__PURE__ */ jsx("defs", { children: defs }),
|
|
482
|
+
keys.map((key) => /* @__PURE__ */ jsx(
|
|
483
|
+
Area,
|
|
484
|
+
{
|
|
485
|
+
type: curveType,
|
|
486
|
+
dataKey: key,
|
|
487
|
+
stroke: `url(#${id}-${key})`,
|
|
488
|
+
fill: `url(#${id}-fill-${key})`,
|
|
489
|
+
strokeWidth: 1,
|
|
490
|
+
strokeOpacity: 0.5,
|
|
491
|
+
strokeDasharray: dash,
|
|
492
|
+
connectNulls,
|
|
493
|
+
fillOpacity: 1,
|
|
494
|
+
stackId: stacked ? "brush-stack" : void 0,
|
|
495
|
+
dot: false,
|
|
496
|
+
activeDot: false,
|
|
497
|
+
isAnimationActive: false
|
|
498
|
+
},
|
|
499
|
+
key
|
|
500
|
+
))
|
|
501
|
+
] }) });
|
|
502
|
+
}
|
|
503
|
+
function useChartBrush({
|
|
504
|
+
data,
|
|
505
|
+
defaultStartIndex = 0,
|
|
506
|
+
defaultEndIndex
|
|
507
|
+
}) {
|
|
508
|
+
const [range, setRange] = useState({
|
|
509
|
+
startIndex: defaultStartIndex,
|
|
510
|
+
endIndex: defaultEndIndex ?? Math.max(0, data.length - 1)
|
|
511
|
+
});
|
|
512
|
+
const deferred = useDeferredValue(range);
|
|
513
|
+
useEffect(() => {
|
|
514
|
+
setRange({ startIndex: 0, endIndex: Math.max(0, data.length - 1) });
|
|
515
|
+
}, [data.length]);
|
|
516
|
+
const visibleData = useMemo(
|
|
517
|
+
() => data.slice(deferred.startIndex, deferred.endIndex + 1),
|
|
518
|
+
[data, deferred.endIndex, deferred.startIndex]
|
|
519
|
+
);
|
|
520
|
+
return {
|
|
521
|
+
range,
|
|
522
|
+
visibleData,
|
|
523
|
+
brushProps: {
|
|
524
|
+
startIndex: range.startIndex,
|
|
525
|
+
endIndex: range.endIndex,
|
|
526
|
+
onChange: setRange
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
export {
|
|
531
|
+
Brush,
|
|
532
|
+
ChartBrush,
|
|
533
|
+
useChartBrush
|
|
534
|
+
};
|
|
535
|
+
//# sourceMappingURL=brush.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/brush.tsx"],"sourcesContent":["'use client'\n\nimport {\n Fragment,\n useCallback,\n useDeferredValue,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n startTransition,\n type ComponentProps,\n type FC,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n} from 'react'\nimport {\n motion,\n useMotionValue,\n useMotionValueEvent,\n useSpring,\n useTransform,\n type MotionValue,\n} from 'motion/react'\nimport {\n Area,\n AreaChart,\n Bar,\n BarChart,\n Line,\n LineChart,\n ResponsiveContainer,\n} from 'recharts'\nimport { cn } from '../../lib/cn'\nimport { colorStops, type ChartConfig } from './chart'\n\n/** The slice of the data a brush has selected, as row indexes. */\nexport interface ChartBrushRange {\n startIndex: number\n endIndex: number\n}\n\n/** Which mark the miniature strip is drawn with. */\nexport type ChartBrushVariant = 'line' | 'area' | 'bar'\n\nexport interface BrushProps {\n /** Strip height in pixels. */\n height?: number\n /** Turns a row's x value into a handle label. */\n formatLabel?: (value: unknown, index: number) => string\n onChange?: (range: ChartBrushRange) => void\n}\n\n/**\n * Declares the zoom brush under a chart.\n *\n * Renders nothing itself — its PRESENCE among the chart's children turns the\n * footer on, and its props configure it. A marker rather than a `showBrush`\n * prop because the brush is composed like every other part, so a consumer does\n * not have to remember which knobs are children and which are props.\n */\nexport const Brush: FC<BrushProps> = () => null\n\n/** How firmly the handles catch up with the pointer. */\nconst SPRING = { stiffness: 300, damping: 35, mass: 0.8 }\n\ntype DragKind = 'start' | 'end' | 'pan'\n\ninterface DragState {\n kind: DragKind\n originX: number\n originRange: ChartBrushRange\n}\n\n/**\n * Pointer-capture dragging for the two handles and the selected span.\n *\n * `setPointerCapture` routes every subsequent move to the element that was\n * pressed, so mouse, touch and pen all work from one code path and there are no\n * window-level listeners to leak.\n */\nfunction useBrushDrag({\n range,\n totalPoints,\n containerRef,\n commit,\n}: {\n range: ChartBrushRange\n totalPoints: number\n containerRef: RefObject<HTMLDivElement | null>\n commit: (next: ChartBrushRange, kind?: DragKind) => void\n}) {\n const drag = useRef<DragState | null>(null)\n const [isDragging, setIsDragging] = useState(false)\n\n const toIndexDelta = useCallback(\n (px: number) => {\n const width = containerRef.current?.getBoundingClientRect().width ?? 0\n if (!width || totalPoints <= 1) return 0\n return Math.round((px / width) * (totalPoints - 1))\n },\n [containerRef, totalPoints],\n )\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent, kind: DragKind) => {\n event.preventDefault()\n ;(event.target as HTMLElement).setPointerCapture(event.pointerId)\n drag.current = { kind, originX: event.clientX, originRange: { ...range } }\n setIsDragging(true)\n },\n [range],\n )\n\n const onPointerMove = useCallback(\n (event: ReactPointerEvent) => {\n const state = drag.current\n if (!state) return\n\n const delta = toIndexDelta(event.clientX - state.originX)\n const origin = state.originRange\n\n if (state.kind === 'start') {\n commit({ startIndex: origin.startIndex + delta, endIndex: origin.endIndex }, 'start')\n return\n }\n if (state.kind === 'end') {\n commit({ startIndex: origin.startIndex, endIndex: origin.endIndex + delta }, 'end')\n return\n }\n\n const span = origin.endIndex - origin.startIndex\n let start = origin.startIndex + delta\n let end = start + span\n if (start < 0) {\n start = 0\n end = span\n }\n if (end > totalPoints - 1) {\n end = totalPoints - 1\n start = Math.max(0, end - span)\n }\n commit({ startIndex: start, endIndex: end }, 'pan')\n },\n [commit, toIndexDelta, totalPoints],\n )\n\n const onPointerUp = useCallback((event: ReactPointerEvent) => {\n ;(event.target as HTMLElement).releasePointerCapture(event.pointerId)\n drag.current = null\n setIsDragging(false)\n }, [])\n\n const bind = useCallback(\n (kind: DragKind) => ({\n onPointerDown: (event: ReactPointerEvent) => onPointerDown(event, kind),\n onPointerMove,\n onPointerUp,\n }),\n [onPointerDown, onPointerMove, onPointerUp],\n )\n\n return { isDragging, bind }\n}\n\nexport interface ChartBrushProps {\n /** The whole dataset. The strip always draws all of it. */\n data: Record<string, unknown>[]\n config: ChartConfig\n /** Which series the strip draws. Defaults to every key in the config. */\n dataKeys?: string[]\n /** The row field behind a handle's label. */\n xDataKey?: string\n variant?: ChartBrushVariant\n height?: number\n className?: string\n stacked?: boolean\n strokeVariant?: 'solid' | 'dashed'\n connectNulls?: boolean\n barRadius?: number\n startIndex?: number\n endIndex?: number\n defaultStartIndex?: number\n defaultEndIndex?: number\n onChange?: (range: ChartBrushRange) => void\n formatLabel?: (value: unknown, index: number) => string\n curveType?: ComponentProps<typeof Area>['type']\n /** The fewest rows that may stay selected. */\n minSpan?: number\n showLabels?: boolean\n /** Names the control for a screen reader. */\n label?: string\n}\n\n/**\n * The range selector under a chart: a miniature of the whole series, with a lit\n * window over the part the chart above is showing.\n *\n * Both handles are real `slider` controls — focusable, arrow-key driven, with\n * `aria-valuetext` reading out the row they sit on. The shape this was ported\n * from was pointer-only, which made zooming a chart something a keyboard user\n * could watch but not do.\n *\n * Position is written as inline style rather than as `start-`/`end-` classes on\n * purpose. The strip's axis is the DATA's, and Recharts lays a cartesian plot\n * out left-to-right in every writing direction — so mirroring the handles under\n * `dir=\"rtl\"` would put the \"earlier\" handle at the end of a chart that still\n * runs the other way.\n */\nexport function ChartBrush({\n data,\n config,\n dataKeys,\n xDataKey,\n variant = 'area',\n height = 56,\n className,\n stacked = false,\n strokeVariant = 'solid',\n connectNulls = false,\n barRadius,\n startIndex: controlledStart,\n endIndex: controlledEnd,\n defaultStartIndex = 0,\n defaultEndIndex,\n onChange,\n formatLabel,\n curveType = 'monotone',\n minSpan = 2,\n showLabels = true,\n label = 'Visible range',\n}: ChartBrushProps) {\n const containerRef = useRef<HTMLDivElement>(null)\n const keys = useMemo(() => dataKeys ?? Object.keys(config), [dataKeys, config])\n const totalPoints = data.length\n const maxIndex = Math.max(0, totalPoints - 1)\n\n const isControlled = controlledStart !== undefined && controlledEnd !== undefined\n\n const [range, setRange] = useState<ChartBrushRange>(() => ({\n startIndex: Math.max(0, Math.min(defaultStartIndex, maxIndex)),\n endIndex: Math.max(0, Math.min(defaultEndIndex ?? maxIndex, maxIndex)),\n }))\n\n const committed = useRef<ChartBrushRange>(range)\n\n useEffect(() => {\n if (isControlled) return\n setRange((previous) => {\n const adjusted = {\n startIndex: Math.min(previous.startIndex, maxIndex),\n endIndex: Math.min(previous.endIndex, maxIndex),\n }\n committed.current = adjusted\n return adjusted\n })\n }, [isControlled, maxIndex])\n\n const clamp = useCallback(\n (next: ChartBrushRange, kind?: DragKind): ChartBrushRange => {\n let startIndex = Math.max(0, Math.min(next.startIndex, maxIndex))\n let endIndex = Math.max(0, Math.min(next.endIndex, maxIndex))\n\n if (kind === 'start') {\n return { startIndex: Math.min(startIndex, Math.max(0, endIndex - minSpan)), endIndex }\n }\n if (kind === 'end') {\n return { startIndex, endIndex: Math.max(endIndex, Math.min(maxIndex, startIndex + minSpan)) }\n }\n if (endIndex - startIndex < minSpan) {\n endIndex = Math.min(startIndex + minSpan, maxIndex)\n if (endIndex - startIndex < minSpan) startIndex = Math.max(0, endIndex - minSpan)\n }\n return { startIndex, endIndex }\n },\n [maxIndex, minSpan],\n )\n\n const commit = useCallback(\n (next: ChartBrushRange, kind?: DragKind) => {\n const clamped = clamp(next, kind)\n const last = committed.current\n if (last.startIndex === clamped.startIndex && last.endIndex === clamped.endIndex) return\n\n committed.current = clamped\n setRange(clamped)\n // The handles have to keep up with the pointer; the chart above does not.\n // Deferring lets React drop intermediate slices during a fast drag.\n startTransition(() => onChange?.(clamped))\n },\n [clamp, onChange],\n )\n\n const { isDragging, bind } = useBrushDrag({ range, totalPoints, containerRef, commit })\n\n useEffect(() => {\n if (!isControlled || isDragging) return\n const synced = { startIndex: controlledStart, endIndex: controlledEnd }\n setRange(synced)\n committed.current = synced\n }, [controlledEnd, controlledStart, isControlled, isDragging])\n\n const startPercent = maxIndex > 0 ? (range.startIndex / maxIndex) * 100 : 0\n const endPercent = maxIndex > 0 ? (range.endIndex / maxIndex) * 100 : 100\n\n const startTarget = useMotionValue(startPercent)\n const endTarget = useMotionValue(endPercent)\n if (startTarget.get() !== startPercent) startTarget.set(startPercent)\n if (endTarget.get() !== endPercent) endTarget.set(endPercent)\n\n const startSpring = useSpring(startTarget, SPRING)\n const endSpring = useSpring(endTarget, SPRING)\n const startEdge = useTransform(startSpring, (value) => `${value}%`)\n const endEdge = useTransform(endSpring, (value) => `${value}%`)\n const dimBefore = useTransform(startSpring, (value) => `${value}%`)\n const dimAfter = useTransform(endSpring, (value) => `${Math.max(0, 100 - value)}%`)\n const spanWidth = useMotionValue(`${Math.max(0, endPercent - startPercent)}%`)\n\n const syncSpan = useCallback(() => {\n spanWidth.set(`${Math.max(0, endSpring.get() - startSpring.get())}%`)\n }, [endSpring, spanWidth, startSpring])\n\n useMotionValueEvent(startSpring, 'change', syncSpan)\n useMotionValueEvent(endSpring, 'change', syncSpan)\n\n const labelAt = useCallback(\n (index: number) => {\n if (!xDataKey) return String(index)\n const value = data[index]?.[xDataKey]\n return formatLabel ? formatLabel(value, index) : String(value ?? index)\n },\n [data, formatLabel, xDataKey],\n )\n\n const nudge = useCallback(\n (kind: 'start' | 'end', step: number) => {\n const next =\n kind === 'start'\n ? { startIndex: range.startIndex + step, endIndex: range.endIndex }\n : { startIndex: range.startIndex, endIndex: range.endIndex + step }\n commit(next, kind)\n },\n [commit, range.endIndex, range.startIndex],\n )\n\n if (totalPoints === 0) return null\n\n return (\n <div\n ref={containerRef}\n className={cn('group relative select-none', className)}\n style={{ height }}\n >\n <div className=\"absolute inset-0 overflow-hidden rounded-(--radius-sm)\">\n <BrushStrip\n data={data}\n keys={keys}\n config={config}\n variant={variant}\n curveType={curveType}\n stacked={stacked}\n strokeVariant={strokeVariant}\n connectNulls={connectNulls}\n barRadius={barRadius}\n />\n </div>\n\n {/* The two dimmed shoulders. A wash rather than an opacity change on the\n strip: dimming the strip itself would also dim the selected window. */}\n <motion.div\n aria-hidden\n className=\"pointer-events-none absolute inset-y-0 rounded-(--radius-sm) bg-(--chart-surface)/70 backdrop-blur-[2px]\"\n style={{ left: 0, width: dimBefore }}\n />\n <motion.div\n aria-hidden\n className=\"pointer-events-none absolute inset-y-0 rounded-(--radius-sm) bg-(--chart-surface)/70 backdrop-blur-[2px]\"\n style={{ right: 0, width: dimAfter }}\n />\n\n <motion.div\n aria-hidden\n className=\"absolute inset-y-0 cursor-grab touch-none rounded-(--radius-sm) border border-(--rule-2) active:cursor-grabbing\"\n style={{ left: startEdge, width: spanWidth }}\n {...bind('pan')}\n />\n\n <BrushHandle\n kind=\"start\"\n edge={startEdge}\n label={label}\n valueLabel={labelAt(range.startIndex)}\n showLabel={showLabels}\n index={range.startIndex}\n max={maxIndex}\n bind={bind('start')}\n onNudge={nudge}\n />\n <BrushHandle\n kind=\"end\"\n edge={endEdge}\n label={label}\n valueLabel={labelAt(range.endIndex)}\n showLabel={showLabels}\n index={range.endIndex}\n max={maxIndex}\n bind={bind('end')}\n onNudge={nudge}\n />\n </div>\n )\n}\n\n/**\n * One end of the window.\n *\n * A `slider` rather than a styled div: arrow keys step it, Home and End jump it\n * to the edges, and `aria-valuetext` says which row it is on rather than which\n * index — an index is not what the reader is choosing between.\n */\nfunction BrushHandle({\n kind,\n edge,\n label,\n valueLabel,\n showLabel,\n index,\n max,\n bind,\n onNudge,\n}: {\n kind: 'start' | 'end'\n edge: MotionValue<string>\n label: string\n valueLabel: string\n showLabel: boolean\n index: number\n max: number\n bind: {\n onPointerDown: (event: ReactPointerEvent) => void\n onPointerMove: (event: ReactPointerEvent) => void\n onPointerUp: (event: ReactPointerEvent) => void\n }\n onNudge: (kind: 'start' | 'end', step: number) => void\n}) {\n const isStart = kind === 'start'\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const steps: Record<string, number> = {\n ArrowLeft: -1,\n ArrowDown: -1,\n ArrowRight: 1,\n ArrowUp: 1,\n PageDown: -5,\n PageUp: 5,\n }\n if (event.key === 'Home') {\n event.preventDefault()\n onNudge(kind, -max)\n return\n }\n if (event.key === 'End') {\n event.preventDefault()\n onNudge(kind, max)\n return\n }\n const step = steps[event.key]\n if (step === undefined) return\n event.preventDefault()\n onNudge(kind, step)\n }\n\n return (\n <motion.div className=\"absolute inset-y-0 z-(--z-rule)\" style={{ left: edge }}>\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label={`${label} — ${isStart ? 'start' : 'end'}`}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={index}\n aria-valuetext={valueLabel}\n onKeyDown={onKeyDown}\n // The 44px hit target WCAG 2.5.5 asks for, as a pseudo-element so the\n // handle itself can stay 6px wide.\n className={cn(\n 'group/handle absolute inset-y-0 flex w-3 cursor-ew-resize touch-none items-center justify-center',\n \"after:absolute after:inset-y-0 after:w-11 after:content-['']\",\n )}\n // Physical, and deliberately so — see the note on ChartBrush. In a\n // class this would need an `rtl:` twin that would move the handle off\n // the edge it belongs to.\n style={{ left: 0, transform: isStart ? undefined : 'translateX(-100%)' }}\n {...bind}\n >\n <span\n aria-hidden\n className=\"flex h-4 w-1.5 flex-col items-center justify-center gap-[2px] rounded-(--radius-sm) bg-(--ink-3-aa) transition-colors duration-(--duration-fast) group-hover/handle:bg-(--ink) group-focus-visible/handle:bg-(--ink)\"\n >\n <span className=\"size-[2px] rounded-(--radius-pill) bg-(--chart-surface)/70\" />\n <span className=\"size-[2px] rounded-(--radius-pill) bg-(--chart-surface)/70\" />\n <span className=\"size-[2px] rounded-(--radius-pill) bg-(--chart-surface)/70\" />\n </span>\n </div>\n\n {showLabel && (\n <span\n aria-hidden\n className=\"pointer-events-none absolute -bottom-3 -translate-y-1/2 rounded-[3px] bg-(--ink) px-1 py-px text-[8px] leading-tight font-medium whitespace-nowrap text-(--paper) opacity-0 transition-opacity duration-(--duration-fast) group-hover:opacity-100\"\n style={isStart ? { left: '0.375rem' } : { right: '0.375rem' }}\n >\n {valueLabel}\n </span>\n )}\n </motion.div>\n )\n}\n\n/**\n * The miniature series behind the window.\n *\n * Its own gradients rather than the chart's: the strip is a second Recharts\n * tree, and an SVG paint reference cannot cross from one `<svg>` root into\n * another. The custom properties DO cross — they are inherited CSS — which is\n * why the strip needs no config of its own beyond the series list.\n */\nfunction BrushStrip({\n data,\n keys,\n config,\n variant,\n curveType,\n stacked,\n strokeVariant,\n connectNulls,\n barRadius,\n}: {\n data: Record<string, unknown>[]\n keys: string[]\n config: ChartConfig\n variant: ChartBrushVariant\n curveType: ComponentProps<typeof Area>['type']\n stacked: boolean\n strokeVariant: 'solid' | 'dashed'\n connectNulls: boolean\n barRadius?: number\n}) {\n const id = `brush-${useId().replace(/:/g, '')}`\n const series = useMemo(\n () =>\n Object.entries(config)\n .filter(([key]) => keys.includes(key))\n .map(([dataKey, entry]) => ({ dataKey, stops: colorStops(entry) })),\n [config, keys],\n )\n\n const dash = strokeVariant === 'dashed' ? '4 4' : undefined\n\n const defs = (\n <>\n {variant === 'area' && (\n <linearGradient id={`${id}-fade`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"white\" stopOpacity={0.15} />\n <stop offset=\"100%\" stopColor=\"white\" stopOpacity={0} />\n </linearGradient>\n )}\n {series.map(({ dataKey, stops }) => (\n <Fragment key={dataKey}>\n <linearGradient id={`${id}-${dataKey}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {stops === 1 ? (\n <>\n <stop offset=\"0%\" stopColor={`var(--color-${dataKey}-0)`} />\n <stop offset=\"100%\" stopColor={`var(--color-${dataKey}-0)`} />\n </>\n ) : (\n Array.from({ length: stops }, (_, index) => (\n <stop\n key={index}\n offset={`${(index / (stops - 1)) * 100}%`}\n stopColor={`var(--color-${dataKey}-${index}, var(--color-${dataKey}-0))`}\n />\n ))\n )}\n </linearGradient>\n {variant === 'area' && (\n <>\n <mask id={`${id}-fill-mask-${dataKey}`}>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${id}-fade)`} />\n </mask>\n <pattern\n id={`${id}-fill-${dataKey}`}\n patternUnits=\"userSpaceOnUse\"\n width=\"100%\"\n height=\"100%\"\n >\n <rect\n width=\"100%\"\n height=\"100%\"\n fill={`url(#${id}-${dataKey})`}\n mask={`url(#${id}-fill-mask-${dataKey})`}\n />\n </pattern>\n </>\n )}\n </Fragment>\n ))}\n </>\n )\n\n if (variant === 'line') {\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <LineChart data={data} margin={{ top: 4, right: 0, bottom: 0, left: 0 }}>\n <defs>{defs}</defs>\n {keys.map((key) => (\n <Line\n key={key}\n type={curveType}\n dataKey={key}\n stroke={`url(#${id}-${key})`}\n strokeWidth={1}\n strokeOpacity={0.5}\n strokeDasharray={dash}\n connectNulls={connectNulls}\n dot={false}\n activeDot={false}\n isAnimationActive={false}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n )\n }\n\n if (variant === 'bar') {\n const radius = barRadius ?? 3\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart\n data={data}\n margin={{ top: 2, right: 0, bottom: 0, left: 0 }}\n barGap={2}\n barSize={14}\n >\n <defs>{defs}</defs>\n {keys.map((key) => (\n <Bar\n key={key}\n dataKey={key}\n fill={`url(#${id}-${key})`}\n fillOpacity={0.35}\n stackId={stacked ? 'brush-stack' : undefined}\n isAnimationActive={false}\n radius={[radius, radius, radius, radius]}\n />\n ))}\n </BarChart>\n </ResponsiveContainer>\n )\n }\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={data} margin={{ top: 4, right: 0, bottom: 0, left: 0 }}>\n <defs>{defs}</defs>\n {keys.map((key) => (\n <Area\n key={key}\n type={curveType}\n dataKey={key}\n stroke={`url(#${id}-${key})`}\n fill={`url(#${id}-fill-${key})`}\n strokeWidth={1}\n strokeOpacity={0.5}\n strokeDasharray={dash}\n connectNulls={connectNulls}\n fillOpacity={1}\n stackId={stacked ? 'brush-stack' : undefined}\n dot={false}\n activeDot={false}\n isAnimationActive={false}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n )\n}\n\n/**\n * Holds the brush's range and hands back the rows the chart above should draw.\n *\n * The slicing runs on a deferred copy of the range: the handles move at pointer\n * cadence while the chart re-renders at whatever cadence it can manage, which\n * is what keeps a drag smooth over a few thousand rows.\n */\nexport function useChartBrush<TData extends Record<string, unknown>>({\n data,\n defaultStartIndex = 0,\n defaultEndIndex,\n}: {\n data: TData[]\n defaultStartIndex?: number\n defaultEndIndex?: number\n}) {\n const [range, setRange] = useState<ChartBrushRange>({\n startIndex: defaultStartIndex,\n endIndex: defaultEndIndex ?? Math.max(0, data.length - 1),\n })\n\n const deferred = useDeferredValue(range)\n\n useEffect(() => {\n setRange({ startIndex: 0, endIndex: Math.max(0, data.length - 1) })\n }, [data.length])\n\n const visibleData = useMemo(\n () => data.slice(deferred.startIndex, deferred.endIndex + 1),\n [data, deferred.endIndex, deferred.startIndex],\n )\n\n return {\n range,\n visibleData,\n brushProps: {\n startIndex: range.startIndex,\n endIndex: range.endIndex,\n onChange: setRange,\n },\n }\n}\n"],"mappings":"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","names":["Fragment"]}
|