@misoto22/design 0.5.0 → 0.6.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.
- 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 +1863 -0
- package/dist/agent/index.md +131 -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/semantic.css +19 -0
- package/dist/styles.css +1 -1
- package/dist/themes.css +50 -0
- package/dist/tokens.css +118 -0
- package/dist/tokens.d.ts +17 -0
- package/dist/tokens.js +101 -0
- package/dist/tokens.json +101 -0
- package/package.json +26 -4
- package/skills/misoto22-design/SKILL.md +209 -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,257 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useCallback,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useId,
|
|
9
|
+
useMemo,
|
|
10
|
+
useState
|
|
11
|
+
} from "react";
|
|
12
|
+
import {
|
|
13
|
+
PolarAngleAxis,
|
|
14
|
+
RadialBar as RechartsRadialBar,
|
|
15
|
+
RadialBarChart as RechartsRadialBarChart,
|
|
16
|
+
Sector
|
|
17
|
+
} from "recharts";
|
|
18
|
+
import { useReducedMotion } from "motion/react";
|
|
19
|
+
import { ChartContainer, colorStops, cssName } from "../lib/chart.js";
|
|
20
|
+
import { ChartFigure } from "../lib/figure.js";
|
|
21
|
+
import { ChartBackground } from "../lib/background.js";
|
|
22
|
+
import { ChartLegend, ChartLegendContent } from "../lib/legend.js";
|
|
23
|
+
import { ChartTooltip, ChartTooltipContent } from "../lib/tooltip.js";
|
|
24
|
+
import { LoadingIndicator } from "../lib/loading.js";
|
|
25
|
+
import { ColorStops } from "../lib/paint.js";
|
|
26
|
+
const CORNER_RADIUS = 5;
|
|
27
|
+
const BAR_SIZE = 14;
|
|
28
|
+
const LOADING_BARS = 5;
|
|
29
|
+
const LOADING_CYCLE = 1500;
|
|
30
|
+
const ARC = {
|
|
31
|
+
// Starting at 90° and running to -270° draws the ring clockwise from noon,
|
|
32
|
+
// which is the direction a reader expects a total to fill in.
|
|
33
|
+
full: { startAngle: 90, endAngle: -270, cx: "50%", cy: "50%" },
|
|
34
|
+
semi: { startAngle: 180, endAngle: 0, cx: "50%", cy: "70%" }
|
|
35
|
+
};
|
|
36
|
+
const RadialChartContext = createContext(null);
|
|
37
|
+
function useRadialChart() {
|
|
38
|
+
const context = useContext(RadialChartContext);
|
|
39
|
+
if (!context) throw new Error("A radial chart part must be rendered inside <RadialChart>");
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
42
|
+
function RadialChart({
|
|
43
|
+
config,
|
|
44
|
+
data,
|
|
45
|
+
nameKey,
|
|
46
|
+
title,
|
|
47
|
+
showTitle,
|
|
48
|
+
description,
|
|
49
|
+
children,
|
|
50
|
+
className,
|
|
51
|
+
chartProps,
|
|
52
|
+
variant = "full",
|
|
53
|
+
max,
|
|
54
|
+
innerRadius = "30%",
|
|
55
|
+
outerRadius = "100%",
|
|
56
|
+
defaultSelectedBar = null,
|
|
57
|
+
onSelectionChange,
|
|
58
|
+
isLoading = false,
|
|
59
|
+
valueKey,
|
|
60
|
+
hideDataTable = false
|
|
61
|
+
}) {
|
|
62
|
+
const chartId = useId().replace(/:/g, "");
|
|
63
|
+
const [selectedBar, setSelectedBar] = useState(defaultSelectedBar);
|
|
64
|
+
const loadingData = useLoadingBars(isLoading);
|
|
65
|
+
const arc = ARC[variant];
|
|
66
|
+
const selectBar = useCallback(
|
|
67
|
+
(name, value) => {
|
|
68
|
+
setSelectedBar(name);
|
|
69
|
+
onSelectionChange?.(name === null ? null : { name, value: value ?? 0 });
|
|
70
|
+
},
|
|
71
|
+
[onSelectionChange]
|
|
72
|
+
);
|
|
73
|
+
const painted = useMemo(
|
|
74
|
+
() => data.map((row) => ({
|
|
75
|
+
...row,
|
|
76
|
+
fill: `url(#${chartId}-colors-${cssName(String(row[nameKey]))})`
|
|
77
|
+
})),
|
|
78
|
+
[chartId, data, nameKey]
|
|
79
|
+
);
|
|
80
|
+
const context = useMemo(
|
|
81
|
+
() => ({ config, nameKey, isLoading, selectedBar, selectBar }),
|
|
82
|
+
[config, isLoading, nameKey, selectBar, selectedBar]
|
|
83
|
+
);
|
|
84
|
+
return /* @__PURE__ */ jsx(RadialChartContext.Provider, { value: context, children: /* @__PURE__ */ jsxs(
|
|
85
|
+
ChartFigure,
|
|
86
|
+
{
|
|
87
|
+
title,
|
|
88
|
+
showTitle,
|
|
89
|
+
description,
|
|
90
|
+
className,
|
|
91
|
+
table: hideDataTable || !valueKey ? false : { rows: data, rowKey: nameKey, columns: [{ key: valueKey, label: "Value" }] },
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ jsx(ChartContainer, { config, children: /* @__PURE__ */ jsxs(
|
|
94
|
+
RechartsRadialBarChart,
|
|
95
|
+
{
|
|
96
|
+
id: chartId,
|
|
97
|
+
data: isLoading ? loadingData : painted,
|
|
98
|
+
innerRadius,
|
|
99
|
+
outerRadius,
|
|
100
|
+
startAngle: arc.startAngle,
|
|
101
|
+
endAngle: arc.endAngle,
|
|
102
|
+
cx: arc.cx,
|
|
103
|
+
cy: arc.cy,
|
|
104
|
+
...chartProps,
|
|
105
|
+
children: [
|
|
106
|
+
max != null && max > 0 && /* @__PURE__ */ jsx(PolarAngleAxis, { type: "number", domain: [0, max], tick: false, axisLine: false }),
|
|
107
|
+
children,
|
|
108
|
+
isLoading && /* @__PURE__ */ jsx(LoadingRadialBar, {}),
|
|
109
|
+
/* @__PURE__ */ jsx("defs", { children: Object.entries(config).map(([key, series]) => /* @__PURE__ */ jsx(
|
|
110
|
+
"linearGradient",
|
|
111
|
+
{
|
|
112
|
+
id: `${chartId}-colors-${cssName(key)}`,
|
|
113
|
+
x1: "0",
|
|
114
|
+
y1: "0",
|
|
115
|
+
x2: "1",
|
|
116
|
+
y2: "1",
|
|
117
|
+
children: /* @__PURE__ */ jsx(ColorStops, { dataKey: cssName(key), stops: colorStops(series) })
|
|
118
|
+
},
|
|
119
|
+
key
|
|
120
|
+
)) })
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
) }),
|
|
124
|
+
/* @__PURE__ */ jsx(LoadingIndicator, { isLoading })
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
) });
|
|
128
|
+
}
|
|
129
|
+
function RadialBar({
|
|
130
|
+
dataKey,
|
|
131
|
+
cornerRadius = CORNER_RADIUS,
|
|
132
|
+
barSize = BAR_SIZE,
|
|
133
|
+
showTrack = true,
|
|
134
|
+
isClickable = false,
|
|
135
|
+
radialBarProps
|
|
136
|
+
}) {
|
|
137
|
+
const { nameKey, isLoading, selectedBar, selectBar } = useRadialChart();
|
|
138
|
+
if (isLoading) return null;
|
|
139
|
+
return /* @__PURE__ */ jsx(
|
|
140
|
+
RechartsRadialBar,
|
|
141
|
+
{
|
|
142
|
+
dataKey,
|
|
143
|
+
cornerRadius,
|
|
144
|
+
barSize,
|
|
145
|
+
background: showTrack,
|
|
146
|
+
style: isClickable ? { cursor: "pointer" } : void 0,
|
|
147
|
+
onClick: (payload, index) => {
|
|
148
|
+
if (!isClickable) return;
|
|
149
|
+
const row = payload;
|
|
150
|
+
const name = row?.[nameKey] ?? String(index);
|
|
151
|
+
selectBar(selectedBar === name ? null : name, Number(row?.[dataKey] ?? 0));
|
|
152
|
+
},
|
|
153
|
+
shape: (props) => {
|
|
154
|
+
const name = props[nameKey];
|
|
155
|
+
const isSelected = selectedBar === null || selectedBar === name;
|
|
156
|
+
return /* @__PURE__ */ jsx(
|
|
157
|
+
Sector,
|
|
158
|
+
{
|
|
159
|
+
...props,
|
|
160
|
+
opacity: isClickable && !isSelected ? 0.15 : 1,
|
|
161
|
+
className: "transition-opacity duration-(--duration-base)"
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
},
|
|
165
|
+
...radialBarProps
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
function Tooltip({ variant, roundness, defaultIndex }) {
|
|
170
|
+
const { nameKey, isLoading } = useRadialChart();
|
|
171
|
+
if (isLoading) return null;
|
|
172
|
+
return /* @__PURE__ */ jsx(
|
|
173
|
+
ChartTooltip,
|
|
174
|
+
{
|
|
175
|
+
defaultIndex,
|
|
176
|
+
cursor: false,
|
|
177
|
+
content: /* @__PURE__ */ jsx(ChartTooltipContent, { nameKey, hideLabel: true, roundness, variant })
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
function Legend({
|
|
182
|
+
variant,
|
|
183
|
+
align = "center",
|
|
184
|
+
verticalAlign = "bottom",
|
|
185
|
+
isClickable = false
|
|
186
|
+
}) {
|
|
187
|
+
const { nameKey, isLoading, selectedBar, selectBar } = useRadialChart();
|
|
188
|
+
if (isLoading) return null;
|
|
189
|
+
return /* @__PURE__ */ jsx(
|
|
190
|
+
ChartLegend,
|
|
191
|
+
{
|
|
192
|
+
verticalAlign,
|
|
193
|
+
align,
|
|
194
|
+
content: /* @__PURE__ */ jsx(
|
|
195
|
+
ChartLegendContent,
|
|
196
|
+
{
|
|
197
|
+
selected: selectedBar,
|
|
198
|
+
onSelectChange: selectBar,
|
|
199
|
+
isClickable,
|
|
200
|
+
nameKey,
|
|
201
|
+
variant
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
function Background({ variant = "dots" }) {
|
|
208
|
+
const { isLoading } = useRadialChart();
|
|
209
|
+
if (isLoading) return null;
|
|
210
|
+
return /* @__PURE__ */ jsx(ChartBackground, { variant });
|
|
211
|
+
}
|
|
212
|
+
function sweep(index, cycle) {
|
|
213
|
+
const x = Math.sin(index * 53.9 + cycle * 173.1) * 13759.3;
|
|
214
|
+
return 40 + (x - Math.floor(x)) * 60;
|
|
215
|
+
}
|
|
216
|
+
function useLoadingBars(isLoading) {
|
|
217
|
+
const [cycle, setCycle] = useState(0);
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
if (!isLoading) return;
|
|
220
|
+
const timer = setInterval(() => setCycle((previous) => previous + 1), LOADING_CYCLE);
|
|
221
|
+
return () => clearInterval(timer);
|
|
222
|
+
}, [isLoading]);
|
|
223
|
+
return useMemo(
|
|
224
|
+
() => Array.from({ length: LOADING_BARS }, (_, index) => ({
|
|
225
|
+
name: `loading-${index}`,
|
|
226
|
+
value: sweep(index, cycle)
|
|
227
|
+
})),
|
|
228
|
+
[cycle]
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
function LoadingRadialBar() {
|
|
232
|
+
const reduceMotion = useReducedMotion();
|
|
233
|
+
return /* @__PURE__ */ jsx(
|
|
234
|
+
RechartsRadialBar,
|
|
235
|
+
{
|
|
236
|
+
dataKey: "value",
|
|
237
|
+
cornerRadius: CORNER_RADIUS,
|
|
238
|
+
barSize: BAR_SIZE,
|
|
239
|
+
background: true,
|
|
240
|
+
className: "text-(--ink)",
|
|
241
|
+
isAnimationActive: !reduceMotion,
|
|
242
|
+
animationDuration: LOADING_CYCLE,
|
|
243
|
+
animationEasing: "ease-in-out",
|
|
244
|
+
shape: (props) => /* @__PURE__ */ jsx(Sector, { ...props, fill: "currentColor", fillOpacity: 0.25 })
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
RadialChart.RadialBar = RadialBar;
|
|
249
|
+
RadialChart.Tooltip = Tooltip;
|
|
250
|
+
RadialChart.Legend = Legend;
|
|
251
|
+
RadialChart.Background = Background;
|
|
252
|
+
var RadialChart_default = RadialChart;
|
|
253
|
+
export {
|
|
254
|
+
RadialChart,
|
|
255
|
+
RadialChart_default as default
|
|
256
|
+
};
|
|
257
|
+
//# sourceMappingURL=RadialChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/RadialChart/RadialChart.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useState,\n type ComponentProps,\n type ReactNode,\n} from 'react'\nimport {\n PolarAngleAxis,\n RadialBar as RechartsRadialBar,\n RadialBarChart as RechartsRadialBarChart,\n Sector,\n} from 'recharts'\nimport type { SectorProps } from 'recharts'\nimport type { TypedDataKey } from 'recharts/types/util/typedDataKey'\nimport { useReducedMotion } from 'motion/react'\nimport { ChartContainer, colorStops, cssName, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { ChartBackground, type ChartBackgroundVariant } from '../lib/background'\nimport { ChartLegend, ChartLegendContent } from '../lib/legend'\nimport { ChartTooltip, ChartTooltipContent } from '../lib/tooltip'\nimport { LoadingIndicator } from '../lib/loading'\nimport { ColorStops } from '../lib/paint'\nimport type { ChartLegendSlotProps, ChartTooltipSlotProps } from '../AreaChart/AreaChart'\n\nconst CORNER_RADIUS = 5\nconst BAR_SIZE = 14\nconst LOADING_BARS = 5\n\n/** One skeleton morph, in milliseconds. */\nconst LOADING_CYCLE = 1500\n\n/**\n * The arc the bars are drawn on.\n *\n * `full` is a ring; `semi` is the half-circle a gauge wants, with the centre\n * dropped so the arc sits in the middle of its own box rather than at the top.\n */\nexport type RadialVariant = 'full' | 'semi'\n\n/** The angles and centre each arc shape needs. */\nconst ARC: Record<RadialVariant, { startAngle: number; endAngle: number; cx: string; cy: string }> =\n {\n // Starting at 90° and running to -270° draws the ring clockwise from noon,\n // which is the direction a reader expects a total to fill in.\n full: { startAngle: 90, endAngle: -270, cx: '50%', cy: '50%' },\n semi: { startAngle: 180, endAngle: 0, cx: '50%', cy: '70%' },\n }\n\ninterface RadialChartContextValue {\n config: ChartConfig\n nameKey: string\n isLoading: boolean\n selectedBar: string | null\n selectBar: (name: string | null, value?: number) => void\n}\n\nconst RadialChartContext = createContext<RadialChartContextValue | null>(null)\n\nfunction useRadialChart(): RadialChartContextValue {\n const context = useContext(RadialChartContext)\n if (!context) throw new Error('A radial chart part must be rendered inside <RadialChart>')\n return context\n}\n\nexport interface RadialChartProps<TData extends Record<string, unknown>> {\n /** Bar names → their label and paint. Keys must match the `nameKey` values. */\n config: ChartConfig\n /** The rows the chart draws. One entry per point, bar or category. */\n data: TData[]\n /** The row field naming each bar. */\n nameKey: keyof TData & string\n /**\n * What the chart shows, in a sentence a reader could act on. Required, and\n * announced to a screen reader even when it is not printed.\n */\n title: string\n /** Prints the title above the plot instead of hiding it from sight. */\n showTitle?: boolean\n /** A line under the title — the unit, the window, the caveat. */\n description?: ReactNode\n /**\n * The composed parts — axes, grid, tooltip, legend, and the marks\n * themselves.\n */\n children: ReactNode\n /** Merged onto the figure, last, so a call site can size or space it. */\n className?: string\n /** Escape hatch onto the raw Recharts chart element. */\n chartProps?: ComponentProps<typeof RechartsRadialBarChart>\n /** The arc shape — a full ring, or the half circle a gauge wants. */\n variant?: RadialVariant\n /**\n * What a full sweep is worth.\n *\n * Without it the scale comes from the data, so the largest bar always fills\n * the arc — which is right for a comparison and wrong for a gauge. Set it\n * (typically 100) whenever a single value has to read against a fixed total,\n * or \"62%\" and \"98%\" will look identical.\n */\n max?: number\n /** Where the arc starts, from the centre. */\n innerRadius?: number | string\n /** Where the arc ends. */\n outerRadius?: number | string\n /** The bar lit on first render. */\n defaultSelectedBar?: string | null\n /** Fires when the selection changes, and with null when it is cleared. */\n onSelectionChange?: (selection: { name: string; value: number } | null) => void\n /**\n * Swaps the marks for an animated skeleton, keeping the measured height so\n * the page does not jump when the data lands.\n */\n isLoading?: boolean\n /** The row field holding each bar's number. Used by the table view. */\n valueKey?: keyof TData & string\n /**\n * Drops the hidden table view. Only correct when the page prints the data\n * itself.\n */\n hideDataTable?: boolean\n}\n\n/**\n * Values on an arc — a gauge, or a small set of totals against one scale.\n *\n * The caveat worth knowing before reaching for it: a radial bar's LENGTH is its\n * value, but its RADIUS is not, so an inner bar and an outer bar of the same\n * value are drawn different lengths. That makes it a poor comparison and a good\n * single-value gauge; past about four bars, a `<BarChart>` is the honest choice.\n *\n * @example\n * <RadialChart title=\"Storage used\" config={config} data={data} nameKey=\"tier\" max={100}>\n * <RadialChart.RadialBar dataKey=\"used\" />\n * <RadialChart.Tooltip />\n * </RadialChart>\n */\nexport function RadialChart<TData extends Record<string, unknown>>({\n config,\n data,\n nameKey,\n title,\n showTitle,\n description,\n children,\n className,\n chartProps,\n variant = 'full',\n max,\n innerRadius = '30%',\n outerRadius = '100%',\n defaultSelectedBar = null,\n onSelectionChange,\n isLoading = false,\n valueKey,\n hideDataTable = false,\n}: RadialChartProps<TData>) {\n const chartId = useId().replace(/:/g, '')\n const [selectedBar, setSelectedBar] = useState<string | null>(defaultSelectedBar)\n const loadingData = useLoadingBars(isLoading)\n const arc = ARC[variant]\n\n const selectBar = useCallback(\n (name: string | null, value?: number) => {\n setSelectedBar(name)\n onSelectionChange?.(name === null ? null : { name, value: value ?? 0 })\n },\n [onSelectionChange],\n )\n\n const painted = useMemo(\n () =>\n data.map((row) => ({\n ...row,\n fill: `url(#${chartId}-colors-${cssName(String(row[nameKey]))})`,\n })),\n [chartId, data, nameKey],\n )\n\n const context = useMemo<RadialChartContextValue>(\n () => ({ config, nameKey, isLoading, selectedBar, selectBar }),\n [config, isLoading, nameKey, selectBar, selectedBar],\n )\n\n return (\n <RadialChartContext.Provider value={context}>\n <ChartFigure\n title={title}\n showTitle={showTitle}\n description={description}\n className={className}\n table={\n hideDataTable || !valueKey\n ? false\n : { rows: data, rowKey: nameKey, columns: [{ key: valueKey, label: 'Value' }] }\n }\n >\n <ChartContainer config={config}>\n <RechartsRadialBarChart\n id={chartId}\n data={isLoading ? loadingData : painted}\n innerRadius={innerRadius}\n outerRadius={outerRadius}\n startAngle={arc.startAngle}\n endAngle={arc.endAngle}\n cx={arc.cx}\n cy={arc.cy}\n {...chartProps}\n >\n {max != null && max > 0 && (\n <PolarAngleAxis type=\"number\" domain={[0, max]} tick={false} axisLine={false} />\n )}\n {children}\n {isLoading && <LoadingRadialBar />}\n <defs>\n {Object.entries(config).map(([key, series]) => (\n <linearGradient\n key={key}\n id={`${chartId}-colors-${cssName(key)}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"1\"\n y2=\"1\"\n >\n <ColorStops dataKey={cssName(key)} stops={colorStops(series)} />\n </linearGradient>\n ))}\n </defs>\n </RechartsRadialBarChart>\n </ChartContainer>\n <LoadingIndicator isLoading={isLoading} />\n </ChartFigure>\n </RadialChartContext.Provider>\n )\n}\n\nexport interface RadialBarProps {\n /** The row field holding each bar's number. */\n dataKey: string\n cornerRadius?: number\n /** How thick each arc is, in pixels. */\n barSize?: number\n /** Draws the unfilled remainder behind each bar. Required reading for a gauge. */\n showTrack?: boolean\n isClickable?: boolean\n radialBarProps?: Omit<ComponentProps<typeof RechartsRadialBar>, 'dataKey'>\n}\n\n/** The arcs. One per row. */\nfunction RadialBar({\n dataKey,\n cornerRadius = CORNER_RADIUS,\n barSize = BAR_SIZE,\n showTrack = true,\n isClickable = false,\n radialBarProps,\n}: RadialBarProps) {\n const { nameKey, isLoading, selectedBar, selectBar } = useRadialChart()\n\n if (isLoading) return null\n\n return (\n <RechartsRadialBar\n dataKey={dataKey as TypedDataKey<Record<string, unknown>>}\n cornerRadius={cornerRadius}\n barSize={barSize}\n background={showTrack}\n style={isClickable ? { cursor: 'pointer' } : undefined}\n onClick={(payload, index) => {\n if (!isClickable) return\n const row = payload as Record<string, unknown>\n const name = (row?.[nameKey] as string | undefined) ?? String(index)\n selectBar(selectedBar === name ? null : name, Number(row?.[dataKey] ?? 0))\n }}\n shape={(props: SectorProps) => {\n const name = (props as unknown as Record<string, unknown>)[nameKey] as string\n const isSelected = selectedBar === null || selectedBar === name\n\n return (\n <Sector\n {...props}\n opacity={isClickable && !isSelected ? 0.15 : 1}\n className=\"transition-opacity duration-(--duration-base)\"\n />\n )\n }}\n {...radialBarProps}\n />\n )\n}\n\n/** The hover panel. No heading: the bar's own name is the row label. */\nfunction Tooltip({ variant, roundness, defaultIndex }: ChartTooltipSlotProps) {\n const { nameKey, isLoading } = useRadialChart()\n if (isLoading) return null\n\n return (\n <ChartTooltip\n defaultIndex={defaultIndex}\n cursor={false}\n content={\n <ChartTooltipContent nameKey={nameKey} hideLabel roundness={roundness} variant={variant} />\n }\n />\n )\n}\n\n/** The key. Under the arc and centred — nothing else names the bars. */\nfunction Legend({\n variant,\n align = 'center',\n verticalAlign = 'bottom',\n isClickable = false,\n}: ChartLegendSlotProps) {\n const { nameKey, isLoading, selectedBar, selectBar } = useRadialChart()\n if (isLoading) return null\n\n return (\n <ChartLegend\n verticalAlign={verticalAlign}\n align={align}\n content={\n <ChartLegendContent\n selected={selectedBar}\n onSelectChange={selectBar}\n isClickable={isClickable}\n nameKey={nameKey}\n variant={variant}\n />\n }\n />\n )\n}\n\n/** The decorative plate behind the arc. */\nfunction Background({ variant = 'dots' }: { variant?: ChartBackgroundVariant }) {\n const { isLoading } = useRadialChart()\n if (isLoading) return null\n return <ChartBackground variant={variant} />\n}\n\n/** A deterministic bar length, so the server and the client agree. */\nfunction sweep(index: number, cycle: number): number {\n const x = Math.sin(index * 53.9 + cycle * 173.1) * 13_759.3\n return 40 + (x - Math.floor(x)) * 60\n}\n\n/** The skeleton's arcs, re-rolled once per cycle. */\nfunction useLoadingBars(isLoading: boolean) {\n const [cycle, setCycle] = useState(0)\n\n useEffect(() => {\n if (!isLoading) return\n const timer = setInterval(() => setCycle((previous) => previous + 1), LOADING_CYCLE)\n return () => clearInterval(timer)\n }, [isLoading])\n\n return useMemo(\n () =>\n Array.from({ length: LOADING_BARS }, (_, index) => ({\n name: `loading-${index}`,\n value: sweep(index, cycle),\n })),\n [cycle],\n )\n}\n\n/** The skeleton arcs, morphing while the data is in flight. */\nfunction LoadingRadialBar() {\n const reduceMotion = useReducedMotion()\n\n return (\n <RechartsRadialBar\n dataKey=\"value\"\n cornerRadius={CORNER_RADIUS}\n barSize={BAR_SIZE}\n background\n className=\"text-(--ink)\"\n isAnimationActive={!reduceMotion}\n animationDuration={LOADING_CYCLE}\n animationEasing=\"ease-in-out\"\n shape={(props: SectorProps) => <Sector {...props} fill=\"currentColor\" fillOpacity={0.25} />}\n />\n )\n}\n\nRadialChart.RadialBar = RadialBar\nRadialChart.Tooltip = Tooltip\nRadialChart.Legend = Legend\nRadialChart.Background = Background\n\nexport default RadialChart\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, FC } from 'react';
|
|
3
|
+
import { SankeyData, SankeyProps } from 'recharts';
|
|
4
|
+
import { ChartConfig } from '../lib/chart.js';
|
|
5
|
+
import { ChartBackgroundVariant } from '../lib/background.js';
|
|
6
|
+
import { ChartTooltipSlotProps } from '../AreaChart/AreaChart.js';
|
|
7
|
+
import '../lib/empty.js';
|
|
8
|
+
import '../lib/values.js';
|
|
9
|
+
import '../lib/sonify-control.js';
|
|
10
|
+
import '../lib/sonify.js';
|
|
11
|
+
import '../lib/brush.js';
|
|
12
|
+
import '../lib/toolbar.js';
|
|
13
|
+
import '../lib/zoom.js';
|
|
14
|
+
import '../lib/figure.js';
|
|
15
|
+
import '../lib/paint.js';
|
|
16
|
+
import '../lib/dot.js';
|
|
17
|
+
import '../lib/legend.js';
|
|
18
|
+
import '../lib/tooltip.js';
|
|
19
|
+
import 'recharts/types/component/DefaultTooltipContent';
|
|
20
|
+
import '../lib/annotations.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* How a flow band is coloured.
|
|
24
|
+
*
|
|
25
|
+
* `gradient` fades from the source's colour to the target's, which is the one
|
|
26
|
+
* that actually reads as flow. `source` and `target` attribute the whole band
|
|
27
|
+
* to one end — useful when the question is "where did this come from" rather
|
|
28
|
+
* than "what became of it". `solid` gives up colour entirely and lets the
|
|
29
|
+
* node rectangles carry identity.
|
|
30
|
+
*/
|
|
31
|
+
type SankeyLinkVariant = 'gradient' | 'solid' | 'source' | 'target';
|
|
32
|
+
/** Where a node's label sits. */
|
|
33
|
+
type SankeyLabelPosition = 'inside' | 'outside';
|
|
34
|
+
interface SankeyChartProps {
|
|
35
|
+
/** The nodes and the links between them, in Recharts' own shape. */
|
|
36
|
+
data: SankeyData;
|
|
37
|
+
/** Node names → their label and paint. */
|
|
38
|
+
config: ChartConfig;
|
|
39
|
+
/**
|
|
40
|
+
* What the chart shows, in a sentence a reader could act on. Required, and
|
|
41
|
+
* announced to a screen reader even when it is not printed.
|
|
42
|
+
*/
|
|
43
|
+
title: string;
|
|
44
|
+
/** Prints the title above the plot instead of hiding it from sight. */
|
|
45
|
+
showTitle?: boolean;
|
|
46
|
+
/** A line under the title — the unit, the window, the caveat. */
|
|
47
|
+
description?: ReactNode;
|
|
48
|
+
/**
|
|
49
|
+
* The composed parts — axes, grid, tooltip, legend, and the marks
|
|
50
|
+
* themselves.
|
|
51
|
+
*/
|
|
52
|
+
children: ReactNode;
|
|
53
|
+
/** Merged onto the figure, last, so a call site can size or space it. */
|
|
54
|
+
className?: string;
|
|
55
|
+
/** Escape hatch onto the raw Recharts Sankey element. */
|
|
56
|
+
sankeyProps?: Omit<SankeyProps, 'data'>;
|
|
57
|
+
/** How wide each node rectangle is, in pixels. */
|
|
58
|
+
nodeWidth?: number;
|
|
59
|
+
/** Vertical gap between nodes in the same column, in pixels. */
|
|
60
|
+
nodePadding?: number;
|
|
61
|
+
/** 0 draws straight links, 1 the fullest curve. */
|
|
62
|
+
linkCurvature?: number;
|
|
63
|
+
/** Layout passes. More is tidier and slower. */
|
|
64
|
+
iterations?: number;
|
|
65
|
+
/** Lets the layout reorder nodes for the fewest crossings. */
|
|
66
|
+
sort?: boolean;
|
|
67
|
+
/** How nodes are placed along the flow axis. */
|
|
68
|
+
align?: 'left' | 'justify';
|
|
69
|
+
/** How nodes are distributed within a column. */
|
|
70
|
+
verticalAlign?: 'justify' | 'top';
|
|
71
|
+
/**
|
|
72
|
+
* The node lit on first render. Selecting one dims every flow it does not
|
|
73
|
+
* touch.
|
|
74
|
+
*/
|
|
75
|
+
defaultSelectedNode?: string | null;
|
|
76
|
+
/** Fires when the selection changes, and with null when it is cleared. */
|
|
77
|
+
onSelectionChange?: (selection: {
|
|
78
|
+
name: string;
|
|
79
|
+
value: number;
|
|
80
|
+
} | null) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Swaps the marks for an animated skeleton, keeping the measured height so
|
|
83
|
+
* the page does not jump when the data lands.
|
|
84
|
+
*/
|
|
85
|
+
isLoading?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Drops the hidden table view. Only correct when the page prints the data
|
|
88
|
+
* itself.
|
|
89
|
+
*/
|
|
90
|
+
hideDataTable?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Where a quantity goes as it moves through stages — the shape for a funnel, a
|
|
94
|
+
* budget, an energy or traffic breakdown.
|
|
95
|
+
*
|
|
96
|
+
* The only chart here whose data is a GRAPH rather than a table, so it takes
|
|
97
|
+
* `{ nodes, links }` instead of rows, and the table view lists the flows rather
|
|
98
|
+
* than the nodes.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* <SankeyChart title="Traffic by source and outcome" config={config} data={data}>
|
|
102
|
+
* <SankeyChart.Node radius={2}>
|
|
103
|
+
* <SankeyChart.NodeLabel position="outside" showValues />
|
|
104
|
+
* </SankeyChart.Node>
|
|
105
|
+
* <SankeyChart.Link variant="gradient" />
|
|
106
|
+
* <SankeyChart.Tooltip />
|
|
107
|
+
* </SankeyChart>
|
|
108
|
+
*/
|
|
109
|
+
declare function SankeyChart({ data, config, title, showTitle, description, children, className, sankeyProps, nodeWidth, nodePadding, linkCurvature, iterations, sort, align, verticalAlign, defaultSelectedNode, onSelectionChange, isLoading, hideDataTable, }: SankeyChartProps): react.JSX.Element;
|
|
110
|
+
declare namespace SankeyChart {
|
|
111
|
+
var Node: FC<NodeProps>;
|
|
112
|
+
var NodeLabel: FC<NodeLabelProps>;
|
|
113
|
+
var Link: FC<LinkProps>;
|
|
114
|
+
var Tooltip: ({ variant, roundness, defaultIndex }: ChartTooltipSlotProps) => react.JSX.Element | null;
|
|
115
|
+
var Background: ({ variant }: {
|
|
116
|
+
variant?: ChartBackgroundVariant;
|
|
117
|
+
}) => react.JSX.Element | null;
|
|
118
|
+
}
|
|
119
|
+
interface NodeProps {
|
|
120
|
+
radius?: number;
|
|
121
|
+
isClickable?: boolean;
|
|
122
|
+
/** `<SankeyChart.NodeLabel>`. */
|
|
123
|
+
children?: ReactNode;
|
|
124
|
+
}
|
|
125
|
+
interface NodeLabelProps {
|
|
126
|
+
position?: SankeyLabelPosition;
|
|
127
|
+
/** Prints each node's total flow under its name. */
|
|
128
|
+
showValues?: boolean;
|
|
129
|
+
valueFormatter?: (value: number) => string;
|
|
130
|
+
}
|
|
131
|
+
interface LinkProps {
|
|
132
|
+
variant?: SankeyLinkVariant;
|
|
133
|
+
/** Thins each band where it meets a node, so neighbours stay separable. */
|
|
134
|
+
verticalPadding?: number;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { type LinkProps, type NodeLabelProps, type NodeProps, SankeyChart, type SankeyChartProps, type SankeyLabelPosition, type SankeyLinkVariant, SankeyChart as default };
|