@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,501 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
Children,
|
|
5
|
+
createContext,
|
|
6
|
+
isValidElement,
|
|
7
|
+
useCallback,
|
|
8
|
+
useContext,
|
|
9
|
+
useId,
|
|
10
|
+
useMemo,
|
|
11
|
+
useState
|
|
12
|
+
} from "react";
|
|
13
|
+
import {
|
|
14
|
+
Layer,
|
|
15
|
+
Sankey as RechartsSankey
|
|
16
|
+
} from "recharts";
|
|
17
|
+
import { motion, useReducedMotion } from "motion/react";
|
|
18
|
+
import { ChartContainer, colorStops, cssName } from "../lib/chart.js";
|
|
19
|
+
import { ChartFigure } from "../lib/figure.js";
|
|
20
|
+
import { ChartBackground } from "../lib/background.js";
|
|
21
|
+
import { ChartTooltip, ChartTooltipContent } from "../lib/tooltip.js";
|
|
22
|
+
import { LoadingIndicator } from "../lib/loading.js";
|
|
23
|
+
import { ColorStops } from "../lib/paint.js";
|
|
24
|
+
const LOADING_PULSE = 2;
|
|
25
|
+
const SankeyChartContext = createContext(null);
|
|
26
|
+
function useSankeyChart() {
|
|
27
|
+
const context = useContext(SankeyChartContext);
|
|
28
|
+
if (!context) throw new Error("A sankey chart part must be rendered inside <SankeyChart>");
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
function SankeyChart({
|
|
32
|
+
data,
|
|
33
|
+
config,
|
|
34
|
+
title,
|
|
35
|
+
showTitle,
|
|
36
|
+
description,
|
|
37
|
+
children,
|
|
38
|
+
className,
|
|
39
|
+
sankeyProps,
|
|
40
|
+
nodeWidth = 10,
|
|
41
|
+
nodePadding = 10,
|
|
42
|
+
linkCurvature = 0.5,
|
|
43
|
+
iterations = 32,
|
|
44
|
+
sort = true,
|
|
45
|
+
align = "justify",
|
|
46
|
+
verticalAlign = "justify",
|
|
47
|
+
defaultSelectedNode = null,
|
|
48
|
+
onSelectionChange,
|
|
49
|
+
isLoading = false,
|
|
50
|
+
hideDataTable = false
|
|
51
|
+
}) {
|
|
52
|
+
const chartId = useId().replace(/:/g, "");
|
|
53
|
+
const [selectedNode, setSelectedNode] = useState(defaultSelectedNode);
|
|
54
|
+
const selectNode = useCallback(
|
|
55
|
+
(name) => {
|
|
56
|
+
setSelectedNode(name);
|
|
57
|
+
if (!onSelectionChange) return;
|
|
58
|
+
onSelectionChange(name === null ? null : { name, value: nodeValue(data, name) });
|
|
59
|
+
},
|
|
60
|
+
[data, onSelectionChange]
|
|
61
|
+
);
|
|
62
|
+
const context = useMemo(
|
|
63
|
+
() => ({ data, config, chartId, isLoading, selectedNode, selectNode }),
|
|
64
|
+
[chartId, config, data, isLoading, selectNode, selectedNode]
|
|
65
|
+
);
|
|
66
|
+
const flows = useMemo(
|
|
67
|
+
() => data.links.map((link) => ({
|
|
68
|
+
from: String(data.nodes[link.source]?.name ?? link.source),
|
|
69
|
+
to: String(data.nodes[link.target]?.name ?? link.target),
|
|
70
|
+
value: link.value
|
|
71
|
+
})),
|
|
72
|
+
[data]
|
|
73
|
+
);
|
|
74
|
+
return /* @__PURE__ */ jsx(SankeyChartContext.Provider, { value: context, children: /* @__PURE__ */ jsxs(
|
|
75
|
+
ChartFigure,
|
|
76
|
+
{
|
|
77
|
+
title,
|
|
78
|
+
showTitle,
|
|
79
|
+
description,
|
|
80
|
+
className,
|
|
81
|
+
table: hideDataTable ? false : {
|
|
82
|
+
rows: flows,
|
|
83
|
+
rowKey: "from",
|
|
84
|
+
columns: [
|
|
85
|
+
{ key: "to", label: "To" },
|
|
86
|
+
{ key: "value", label: "Value" }
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
children: [
|
|
90
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "relative aspect-video w-full", children: /* @__PURE__ */ jsx(
|
|
91
|
+
"svg",
|
|
92
|
+
{
|
|
93
|
+
viewBox: "0 0 500 250",
|
|
94
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
95
|
+
width: "100%",
|
|
96
|
+
height: "100%",
|
|
97
|
+
"aria-hidden": true,
|
|
98
|
+
className: "absolute inset-0 text-(--ink)",
|
|
99
|
+
children: /* @__PURE__ */ jsx(LoadingSankey, {})
|
|
100
|
+
}
|
|
101
|
+
) }) : /* @__PURE__ */ jsx(ChartContainer, { config, children: /* @__PURE__ */ jsxs(
|
|
102
|
+
RechartsSankey,
|
|
103
|
+
{
|
|
104
|
+
id: chartId,
|
|
105
|
+
data,
|
|
106
|
+
nodeWidth,
|
|
107
|
+
nodePadding,
|
|
108
|
+
linkCurvature,
|
|
109
|
+
iterations,
|
|
110
|
+
sort,
|
|
111
|
+
align,
|
|
112
|
+
verticalAlign,
|
|
113
|
+
...resolveRenderers(children),
|
|
114
|
+
...sankeyProps,
|
|
115
|
+
children: [
|
|
116
|
+
children,
|
|
117
|
+
/* @__PURE__ */ jsx("defs", { children: Object.entries(config).map(([key, series]) => /* @__PURE__ */ jsx(
|
|
118
|
+
"linearGradient",
|
|
119
|
+
{
|
|
120
|
+
id: `${chartId}-node-${cssName(key)}`,
|
|
121
|
+
x1: "0",
|
|
122
|
+
y1: "0",
|
|
123
|
+
x2: "0",
|
|
124
|
+
y2: "1",
|
|
125
|
+
children: /* @__PURE__ */ jsx(ColorStops, { dataKey: cssName(key), stops: colorStops(series) })
|
|
126
|
+
},
|
|
127
|
+
key
|
|
128
|
+
)) })
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
) }),
|
|
132
|
+
/* @__PURE__ */ jsx(LoadingIndicator, { isLoading })
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
) });
|
|
136
|
+
}
|
|
137
|
+
const Node = () => null;
|
|
138
|
+
const NodeLabel = () => null;
|
|
139
|
+
const Link = () => null;
|
|
140
|
+
function Tooltip({ variant, roundness, defaultIndex }) {
|
|
141
|
+
const { isLoading } = useSankeyChart();
|
|
142
|
+
if (isLoading) return null;
|
|
143
|
+
return /* @__PURE__ */ jsx(
|
|
144
|
+
ChartTooltip,
|
|
145
|
+
{
|
|
146
|
+
defaultIndex,
|
|
147
|
+
content: /* @__PURE__ */ jsx(ChartTooltipContent, { nameKey: "name", hideLabel: true, roundness, variant })
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
function Background({ variant = "dots" }) {
|
|
152
|
+
const { isLoading } = useSankeyChart();
|
|
153
|
+
if (isLoading) return null;
|
|
154
|
+
return /* @__PURE__ */ jsx(ChartBackground, { variant });
|
|
155
|
+
}
|
|
156
|
+
function nodeValue(data, name) {
|
|
157
|
+
const index = data.nodes.findIndex((node) => node.name === name);
|
|
158
|
+
if (index === -1) return 0;
|
|
159
|
+
const out = data.links.filter((link) => link.source === index).reduce((sum, link) => sum + link.value, 0);
|
|
160
|
+
const incoming = data.links.filter((link) => link.target === index).reduce((sum, link) => sum + link.value, 0);
|
|
161
|
+
return out > 0 ? out : incoming;
|
|
162
|
+
}
|
|
163
|
+
function resolveRenderers(children) {
|
|
164
|
+
let node = null;
|
|
165
|
+
let link = null;
|
|
166
|
+
Children.forEach(children, (child) => {
|
|
167
|
+
if (!isValidElement(child)) return;
|
|
168
|
+
if (child.type === Node) node = child.props;
|
|
169
|
+
if (child.type === Link) link = child.props;
|
|
170
|
+
});
|
|
171
|
+
return {
|
|
172
|
+
node: (props) => /* @__PURE__ */ jsx(SankeyNodeShape, { ...props, nodeSlot: node }),
|
|
173
|
+
link: (props) => /* @__PURE__ */ jsx(SankeyLinkShape, { ...props, linkSlot: link })
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function resolveNodeLabel(children) {
|
|
177
|
+
let label = null;
|
|
178
|
+
Children.forEach(children, (child) => {
|
|
179
|
+
if (isValidElement(child) && child.type === NodeLabel) {
|
|
180
|
+
label = child.props;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
return label;
|
|
184
|
+
}
|
|
185
|
+
function isConnected(data, selected, name) {
|
|
186
|
+
if (selected === null || selected === name) return true;
|
|
187
|
+
const selectedIndex = data.nodes.findIndex((node) => node.name === selected);
|
|
188
|
+
const nodeIndex = data.nodes.findIndex((node) => node.name === name);
|
|
189
|
+
return data.links.some(
|
|
190
|
+
(link) => link.source === selectedIndex && link.target === nodeIndex || link.source === nodeIndex && link.target === selectedIndex
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
function SankeyNodeShape({
|
|
194
|
+
x,
|
|
195
|
+
y,
|
|
196
|
+
width,
|
|
197
|
+
height,
|
|
198
|
+
payload,
|
|
199
|
+
nodeSlot
|
|
200
|
+
}) {
|
|
201
|
+
const { config, chartId, data, selectedNode, selectNode } = useSankeyChart();
|
|
202
|
+
const radius = nodeSlot?.radius ?? 0;
|
|
203
|
+
const isClickable = nodeSlot?.isClickable ?? false;
|
|
204
|
+
const label = resolveNodeLabel(nodeSlot?.children);
|
|
205
|
+
const name = payload.name;
|
|
206
|
+
const value = payload.value;
|
|
207
|
+
const icon = payload.icon;
|
|
208
|
+
const dimmed = isClickable && !isConnected(data, selectedNode, name);
|
|
209
|
+
const painted = name in config;
|
|
210
|
+
const text = config[name]?.label ?? name;
|
|
211
|
+
const format = label?.valueFormatter ?? ((n) => n.toLocaleString());
|
|
212
|
+
const showValues = label?.showValues ?? false;
|
|
213
|
+
const centreX = x + width / 2;
|
|
214
|
+
const centreY = showValues ? y + height / 2 - 8 : y + height / 2;
|
|
215
|
+
const valueY = y + height / 2 + 8;
|
|
216
|
+
const outsideX = x + width + 8;
|
|
217
|
+
const outsideY = y + height / 2;
|
|
218
|
+
return /* @__PURE__ */ jsxs(Layer, { children: [
|
|
219
|
+
/* @__PURE__ */ jsx(
|
|
220
|
+
"rect",
|
|
221
|
+
{
|
|
222
|
+
x,
|
|
223
|
+
y,
|
|
224
|
+
width,
|
|
225
|
+
height,
|
|
226
|
+
rx: radius,
|
|
227
|
+
ry: radius,
|
|
228
|
+
fill: painted ? `url(#${chartId}-node-${cssName(name)})` : "currentColor",
|
|
229
|
+
fillOpacity: dimmed ? 0.15 : 0.9,
|
|
230
|
+
className: "text-(--ink) transition-opacity duration-(--duration-base)",
|
|
231
|
+
style: isClickable ? { cursor: "pointer" } : void 0,
|
|
232
|
+
onClick: () => {
|
|
233
|
+
if (!isClickable) return;
|
|
234
|
+
selectNode(selectedNode === name ? null : name);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
label?.position === "inside" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
239
|
+
/* @__PURE__ */ jsx(
|
|
240
|
+
"rect",
|
|
241
|
+
{
|
|
242
|
+
x: x + 1,
|
|
243
|
+
y: y + 1,
|
|
244
|
+
width: width - 2,
|
|
245
|
+
height: height - 2,
|
|
246
|
+
rx: Math.max(0, radius - 1),
|
|
247
|
+
ry: Math.max(0, radius - 1),
|
|
248
|
+
opacity: dimmed ? 0.3 : 1,
|
|
249
|
+
className: "fill-(--chart-surface)/60 transition-opacity duration-(--duration-base)",
|
|
250
|
+
style: { pointerEvents: "none" }
|
|
251
|
+
}
|
|
252
|
+
),
|
|
253
|
+
icon && /* @__PURE__ */ jsx(
|
|
254
|
+
"foreignObject",
|
|
255
|
+
{
|
|
256
|
+
x: centreX - 8,
|
|
257
|
+
y: centreY - 30,
|
|
258
|
+
width: 16,
|
|
259
|
+
height: 16,
|
|
260
|
+
opacity: dimmed ? 0.3 : 1,
|
|
261
|
+
className: "transition-opacity duration-(--duration-base)",
|
|
262
|
+
style: { pointerEvents: "none" },
|
|
263
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center text-(--ink-2)", children: icon })
|
|
264
|
+
}
|
|
265
|
+
),
|
|
266
|
+
/* @__PURE__ */ jsx(
|
|
267
|
+
"text",
|
|
268
|
+
{
|
|
269
|
+
x: centreX,
|
|
270
|
+
y: icon ? centreY - 4 : centreY,
|
|
271
|
+
textAnchor: "middle",
|
|
272
|
+
dominantBaseline: "middle",
|
|
273
|
+
className: "fill-(--ink) text-[10px] font-medium transition-opacity duration-(--duration-base)",
|
|
274
|
+
opacity: dimmed ? 0.3 : 1,
|
|
275
|
+
style: { pointerEvents: "none" },
|
|
276
|
+
children: text
|
|
277
|
+
}
|
|
278
|
+
),
|
|
279
|
+
showValues && /* @__PURE__ */ jsx(
|
|
280
|
+
"text",
|
|
281
|
+
{
|
|
282
|
+
x: centreX,
|
|
283
|
+
y: valueY,
|
|
284
|
+
textAnchor: "middle",
|
|
285
|
+
dominantBaseline: "middle",
|
|
286
|
+
className: "fill-(--ink) font-mono text-xs font-medium tabular-nums transition-opacity duration-(--duration-base)",
|
|
287
|
+
opacity: dimmed ? 0.3 : 0.6,
|
|
288
|
+
style: { pointerEvents: "none" },
|
|
289
|
+
children: format(value)
|
|
290
|
+
}
|
|
291
|
+
)
|
|
292
|
+
] }),
|
|
293
|
+
label?.position === "outside" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
294
|
+
/* @__PURE__ */ jsx(
|
|
295
|
+
"text",
|
|
296
|
+
{
|
|
297
|
+
x: outsideX,
|
|
298
|
+
y: outsideY - (showValues ? 8 : 0),
|
|
299
|
+
textAnchor: "start",
|
|
300
|
+
dominantBaseline: "middle",
|
|
301
|
+
className: "fill-(--ink) text-xs",
|
|
302
|
+
style: { pointerEvents: "none" },
|
|
303
|
+
children: text
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
showValues && /* @__PURE__ */ jsx(
|
|
307
|
+
"text",
|
|
308
|
+
{
|
|
309
|
+
x: outsideX,
|
|
310
|
+
y: outsideY + 8,
|
|
311
|
+
textAnchor: "start",
|
|
312
|
+
dominantBaseline: "middle",
|
|
313
|
+
opacity: 0.5,
|
|
314
|
+
className: "fill-(--ink) font-mono text-xs tabular-nums",
|
|
315
|
+
style: { pointerEvents: "none" },
|
|
316
|
+
children: format(value)
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
] })
|
|
320
|
+
] });
|
|
321
|
+
}
|
|
322
|
+
function SankeyLinkShape({
|
|
323
|
+
sourceX,
|
|
324
|
+
targetX,
|
|
325
|
+
sourceY,
|
|
326
|
+
targetY,
|
|
327
|
+
sourceControlX,
|
|
328
|
+
targetControlX,
|
|
329
|
+
linkWidth,
|
|
330
|
+
index,
|
|
331
|
+
payload,
|
|
332
|
+
linkSlot
|
|
333
|
+
}) {
|
|
334
|
+
const { config, chartId, selectedNode } = useSankeyChart();
|
|
335
|
+
const variant = linkSlot?.variant ?? "gradient";
|
|
336
|
+
const verticalPadding = linkSlot?.verticalPadding ?? 0;
|
|
337
|
+
const sourceName = payload.source.name;
|
|
338
|
+
const targetName = payload.target.name;
|
|
339
|
+
const lit = selectedNode === null || selectedNode === sourceName || selectedNode === targetName;
|
|
340
|
+
const half = Math.max(1, linkWidth - verticalPadding) / 2;
|
|
341
|
+
const band = `M${sourceX},${sourceY - half}
|
|
342
|
+
C${sourceControlX},${sourceY - half} ${targetControlX},${targetY - half} ${targetX},${targetY - half}
|
|
343
|
+
L${targetX},${targetY + half}
|
|
344
|
+
C${targetControlX},${targetY + half} ${sourceControlX},${sourceY + half} ${sourceX},${sourceY + half}
|
|
345
|
+
Z`;
|
|
346
|
+
const sourceColor = sourceName in config ? `var(--color-${cssName(sourceName)}-0)` : "currentColor";
|
|
347
|
+
const targetColor = targetName in config ? `var(--color-${cssName(targetName)}-0)` : "currentColor";
|
|
348
|
+
return /* @__PURE__ */ jsxs(Layer, { className: "text-(--ink)", children: [
|
|
349
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
350
|
+
variant === "gradient" && /* @__PURE__ */ jsxs("linearGradient", { id: `${chartId}-link-${index}`, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
|
|
351
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: sourceColor, stopOpacity: 0.2 }),
|
|
352
|
+
/* @__PURE__ */ jsx("stop", { offset: "50%", stopColor: sourceColor, stopOpacity: 0.5 }),
|
|
353
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: targetColor, stopOpacity: 0.2 })
|
|
354
|
+
] }),
|
|
355
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: `${chartId}-link-edge-${index}`, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
|
|
356
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "var(--accent)", stopOpacity: 0 }),
|
|
357
|
+
/* @__PURE__ */ jsx("stop", { offset: "15%", stopColor: "var(--accent)", stopOpacity: 0.8 }),
|
|
358
|
+
/* @__PURE__ */ jsx("stop", { offset: "50%", stopColor: "var(--accent)", stopOpacity: 1 }),
|
|
359
|
+
/* @__PURE__ */ jsx("stop", { offset: "85%", stopColor: "var(--accent)", stopOpacity: 0.8 }),
|
|
360
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "var(--accent)", stopOpacity: 0 })
|
|
361
|
+
] })
|
|
362
|
+
] }),
|
|
363
|
+
/* @__PURE__ */ jsx(
|
|
364
|
+
"path",
|
|
365
|
+
{
|
|
366
|
+
d: band,
|
|
367
|
+
fill: linkFill(variant, chartId, index, config, sourceName, targetName),
|
|
368
|
+
fillOpacity: lit ? "calc(var(--chart-fill) * 2.6)" : "calc(var(--chart-fill) * 0.7)",
|
|
369
|
+
stroke: selectedNode !== null && lit ? `url(#${chartId}-link-edge-${index})` : "none",
|
|
370
|
+
strokeWidth: 1,
|
|
371
|
+
className: "transition-opacity duration-(--duration-base)"
|
|
372
|
+
}
|
|
373
|
+
)
|
|
374
|
+
] });
|
|
375
|
+
}
|
|
376
|
+
function linkFill(variant, chartId, index, config, sourceName, targetName) {
|
|
377
|
+
switch (variant) {
|
|
378
|
+
case "gradient":
|
|
379
|
+
return `url(#${chartId}-link-${index})`;
|
|
380
|
+
case "source":
|
|
381
|
+
return sourceName in config ? `url(#${chartId}-node-${cssName(sourceName)})` : "currentColor";
|
|
382
|
+
case "target":
|
|
383
|
+
return targetName in config ? `url(#${chartId}-node-${cssName(targetName)})` : "currentColor";
|
|
384
|
+
default:
|
|
385
|
+
return "currentColor";
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const SKELETON_NODES = [
|
|
389
|
+
{ x: 30, y: 25, width: 12, height: 65, delay: 0 },
|
|
390
|
+
{ x: 30, y: 110, width: 12, height: 50, delay: 0.3 },
|
|
391
|
+
{ x: 30, y: 180, width: 12, height: 45, delay: 0.15 },
|
|
392
|
+
{ x: 244, y: 20, width: 12, height: 55, delay: 0.45 },
|
|
393
|
+
{ x: 244, y: 95, width: 12, height: 75, delay: 0.6 },
|
|
394
|
+
{ x: 244, y: 190, width: 12, height: 40, delay: 0.25 },
|
|
395
|
+
{ x: 458, y: 35, width: 12, height: 80, delay: 0.5 },
|
|
396
|
+
{ x: 458, y: 135, width: 12, height: 90, delay: 0.1 }
|
|
397
|
+
];
|
|
398
|
+
const SKELETON_LINKS = [
|
|
399
|
+
{ from: 0, to: 3, width: 26, delay: 0.2 },
|
|
400
|
+
{ from: 0, to: 4, width: 18, delay: 0.7 },
|
|
401
|
+
{ from: 1, to: 4, width: 24, delay: 0.4 },
|
|
402
|
+
{ from: 1, to: 5, width: 12, delay: 0.9 },
|
|
403
|
+
{ from: 2, to: 4, width: 16, delay: 0.1 },
|
|
404
|
+
{ from: 2, to: 5, width: 14, delay: 0.55 },
|
|
405
|
+
{ from: 3, to: 6, width: 22, delay: 0.35 },
|
|
406
|
+
{ from: 3, to: 7, width: 18, delay: 0.8 },
|
|
407
|
+
{ from: 4, to: 6, width: 28, delay: 0.05 },
|
|
408
|
+
{ from: 4, to: 7, width: 32, delay: 0.65 },
|
|
409
|
+
{ from: 5, to: 7, width: 16, delay: 0.45 }
|
|
410
|
+
];
|
|
411
|
+
function skeletonPath(fromIndex, toIndex) {
|
|
412
|
+
const from = SKELETON_NODES[fromIndex];
|
|
413
|
+
const to = SKELETON_NODES[toIndex];
|
|
414
|
+
const startX = from.x + from.width;
|
|
415
|
+
const startY = from.y + from.height / 2;
|
|
416
|
+
const endX = to.x;
|
|
417
|
+
const endY = to.y + to.height / 2;
|
|
418
|
+
return `M${startX},${startY} C${startX + (endX - startX) * 0.4},${startY} ${startX + (endX - startX) * 0.6},${endY} ${endX},${endY}`;
|
|
419
|
+
}
|
|
420
|
+
function LoadingSankey() {
|
|
421
|
+
const reduceMotion = useReducedMotion();
|
|
422
|
+
if (reduceMotion) {
|
|
423
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
424
|
+
SKELETON_LINKS.map((link) => /* @__PURE__ */ jsx(
|
|
425
|
+
"path",
|
|
426
|
+
{
|
|
427
|
+
d: skeletonPath(link.from, link.to),
|
|
428
|
+
fill: "none",
|
|
429
|
+
stroke: "currentColor",
|
|
430
|
+
strokeWidth: link.width,
|
|
431
|
+
opacity: 0.09
|
|
432
|
+
},
|
|
433
|
+
`${link.from}-${link.to}`
|
|
434
|
+
)),
|
|
435
|
+
SKELETON_NODES.map((node) => /* @__PURE__ */ jsx(
|
|
436
|
+
"rect",
|
|
437
|
+
{
|
|
438
|
+
x: node.x,
|
|
439
|
+
y: node.y,
|
|
440
|
+
width: node.width,
|
|
441
|
+
height: node.height,
|
|
442
|
+
rx: 2,
|
|
443
|
+
fill: "currentColor",
|
|
444
|
+
opacity: 0.25
|
|
445
|
+
},
|
|
446
|
+
`${node.x}-${node.y}`
|
|
447
|
+
))
|
|
448
|
+
] });
|
|
449
|
+
}
|
|
450
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
451
|
+
SKELETON_LINKS.map((link, index) => /* @__PURE__ */ jsx(
|
|
452
|
+
motion.path,
|
|
453
|
+
{
|
|
454
|
+
d: skeletonPath(link.from, link.to),
|
|
455
|
+
fill: "none",
|
|
456
|
+
stroke: "currentColor",
|
|
457
|
+
strokeWidth: link.width,
|
|
458
|
+
initial: { opacity: 0.04 },
|
|
459
|
+
animate: { opacity: [0.04, 0.14, 0.04] },
|
|
460
|
+
transition: {
|
|
461
|
+
duration: LOADING_PULSE * (0.8 + index % 3 * 0.2),
|
|
462
|
+
delay: link.delay,
|
|
463
|
+
repeat: Infinity,
|
|
464
|
+
ease: "easeInOut"
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
`${link.from}-${link.to}`
|
|
468
|
+
)),
|
|
469
|
+
SKELETON_NODES.map((node, index) => /* @__PURE__ */ jsx(
|
|
470
|
+
motion.rect,
|
|
471
|
+
{
|
|
472
|
+
x: node.x,
|
|
473
|
+
y: node.y,
|
|
474
|
+
width: node.width,
|
|
475
|
+
height: node.height,
|
|
476
|
+
rx: 2,
|
|
477
|
+
fill: "currentColor",
|
|
478
|
+
initial: { opacity: 0.15 },
|
|
479
|
+
animate: { opacity: [0.15, 0.4, 0.15] },
|
|
480
|
+
transition: {
|
|
481
|
+
duration: LOADING_PULSE * (0.9 + index % 4 * 0.1),
|
|
482
|
+
delay: node.delay,
|
|
483
|
+
repeat: Infinity,
|
|
484
|
+
ease: "easeInOut"
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
`${node.x}-${node.y}`
|
|
488
|
+
))
|
|
489
|
+
] });
|
|
490
|
+
}
|
|
491
|
+
SankeyChart.Node = Node;
|
|
492
|
+
SankeyChart.NodeLabel = NodeLabel;
|
|
493
|
+
SankeyChart.Link = Link;
|
|
494
|
+
SankeyChart.Tooltip = Tooltip;
|
|
495
|
+
SankeyChart.Background = Background;
|
|
496
|
+
var SankeyChart_default = SankeyChart;
|
|
497
|
+
export {
|
|
498
|
+
SankeyChart,
|
|
499
|
+
SankeyChart_default as default
|
|
500
|
+
};
|
|
501
|
+
//# sourceMappingURL=SankeyChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/SankeyChart/SankeyChart.tsx"],"sourcesContent":["'use client'\n\nimport {\n Children,\n createContext,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useMemo,\n useState,\n type FC,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport {\n Layer,\n Sankey as RechartsSankey,\n type SankeyData,\n type SankeyLinkProps,\n type SankeyNodeProps,\n type SankeyProps,\n} from 'recharts'\nimport { motion, 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 { ChartTooltip, ChartTooltipContent } from '../lib/tooltip'\nimport { LoadingIndicator } from '../lib/loading'\nimport { ColorStops } from '../lib/paint'\nimport type { ChartTooltipSlotProps } from '../AreaChart/AreaChart'\n\n/** One full skeleton pulse, in seconds. */\nconst LOADING_PULSE = 2\n\n/**\n * How a flow band is coloured.\n *\n * `gradient` fades from the source's colour to the target's, which is the one\n * that actually reads as flow. `source` and `target` attribute the whole band\n * to one end — useful when the question is \"where did this come from\" rather\n * than \"what became of it\". `solid` gives up colour entirely and lets the\n * node rectangles carry identity.\n */\nexport type SankeyLinkVariant = 'gradient' | 'solid' | 'source' | 'target'\n\n/** Where a node's label sits. */\nexport type SankeyLabelPosition = 'inside' | 'outside'\n\ninterface SankeyChartContextValue {\n data: SankeyData\n config: ChartConfig\n chartId: string\n isLoading: boolean\n selectedNode: string | null\n selectNode: (name: string | null) => void\n}\n\nconst SankeyChartContext = createContext<SankeyChartContextValue | null>(null)\n\nfunction useSankeyChart(): SankeyChartContextValue {\n const context = useContext(SankeyChartContext)\n if (!context) throw new Error('A sankey chart part must be rendered inside <SankeyChart>')\n return context\n}\n\nexport interface SankeyChartProps {\n /** The nodes and the links between them, in Recharts' own shape. */\n data: SankeyData\n /** Node names → their label and paint. */\n config: ChartConfig\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 Sankey element. */\n sankeyProps?: Omit<SankeyProps, 'data'>\n /** How wide each node rectangle is, in pixels. */\n nodeWidth?: number\n /** Vertical gap between nodes in the same column, in pixels. */\n nodePadding?: number\n /** 0 draws straight links, 1 the fullest curve. */\n linkCurvature?: number\n /** Layout passes. More is tidier and slower. */\n iterations?: number\n /** Lets the layout reorder nodes for the fewest crossings. */\n sort?: boolean\n /** How nodes are placed along the flow axis. */\n align?: 'left' | 'justify'\n /** How nodes are distributed within a column. */\n verticalAlign?: 'justify' | 'top'\n /**\n * The node lit on first render. Selecting one dims every flow it does not\n * touch.\n */\n defaultSelectedNode?: 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 /**\n * Drops the hidden table view. Only correct when the page prints the data\n * itself.\n */\n hideDataTable?: boolean\n}\n\n/**\n * Where a quantity goes as it moves through stages — the shape for a funnel, a\n * budget, an energy or traffic breakdown.\n *\n * The only chart here whose data is a GRAPH rather than a table, so it takes\n * `{ nodes, links }` instead of rows, and the table view lists the flows rather\n * than the nodes.\n *\n * @example\n * <SankeyChart title=\"Traffic by source and outcome\" config={config} data={data}>\n * <SankeyChart.Node radius={2}>\n * <SankeyChart.NodeLabel position=\"outside\" showValues />\n * </SankeyChart.Node>\n * <SankeyChart.Link variant=\"gradient\" />\n * <SankeyChart.Tooltip />\n * </SankeyChart>\n */\nexport function SankeyChart({\n data,\n config,\n title,\n showTitle,\n description,\n children,\n className,\n sankeyProps,\n nodeWidth = 10,\n nodePadding = 10,\n linkCurvature = 0.5,\n iterations = 32,\n sort = true,\n align = 'justify',\n verticalAlign = 'justify',\n defaultSelectedNode = null,\n onSelectionChange,\n isLoading = false,\n hideDataTable = false,\n}: SankeyChartProps) {\n const chartId = useId().replace(/:/g, '')\n const [selectedNode, setSelectedNode] = useState<string | null>(defaultSelectedNode)\n\n const selectNode = useCallback(\n (name: string | null) => {\n setSelectedNode(name)\n if (!onSelectionChange) return\n onSelectionChange(name === null ? null : { name, value: nodeValue(data, name) })\n },\n [data, onSelectionChange],\n )\n\n const context = useMemo<SankeyChartContextValue>(\n () => ({ data, config, chartId, isLoading, selectedNode, selectNode }),\n [chartId, config, data, isLoading, selectNode, selectedNode],\n )\n\n // The flows, not the nodes: a link IS the fact a sankey states, and a table\n // of node totals would lose every \"from → to\" the diagram is drawn to show.\n const flows = useMemo(\n () =>\n data.links.map((link) => ({\n from: String(data.nodes[link.source]?.name ?? link.source),\n to: String(data.nodes[link.target]?.name ?? link.target),\n value: link.value,\n })),\n [data],\n )\n\n return (\n <SankeyChartContext.Provider value={context}>\n <ChartFigure\n title={title}\n showTitle={showTitle}\n description={description}\n className={className}\n table={\n hideDataTable\n ? false\n : {\n rows: flows,\n rowKey: 'from',\n columns: [\n { key: 'to', label: 'To' },\n { key: 'value', label: 'Value' },\n ],\n }\n }\n >\n {isLoading ? (\n <div className=\"relative aspect-video w-full\">\n <svg\n viewBox=\"0 0 500 250\"\n preserveAspectRatio=\"xMidYMid meet\"\n width=\"100%\"\n height=\"100%\"\n aria-hidden\n className=\"absolute inset-0 text-(--ink)\"\n >\n <LoadingSankey />\n </svg>\n </div>\n ) : (\n <ChartContainer config={config}>\n <RechartsSankey\n id={chartId}\n data={data}\n nodeWidth={nodeWidth}\n nodePadding={nodePadding}\n linkCurvature={linkCurvature}\n iterations={iterations}\n sort={sort}\n align={align}\n verticalAlign={verticalAlign}\n {...resolveRenderers(children)}\n {...sankeyProps}\n >\n {children}\n <defs>\n {Object.entries(config).map(([key, series]) => (\n <linearGradient\n key={key}\n id={`${chartId}-node-${cssName(key)}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <ColorStops dataKey={cssName(key)} stops={colorStops(series)} />\n </linearGradient>\n ))}\n </defs>\n </RechartsSankey>\n </ChartContainer>\n )}\n <LoadingIndicator isLoading={isLoading} />\n </ChartFigure>\n </SankeyChartContext.Provider>\n )\n}\n\nexport interface NodeProps {\n radius?: number\n isClickable?: boolean\n /** `<SankeyChart.NodeLabel>`. */\n children?: ReactNode\n}\n\n/** How the node rectangles render. A slot: the root reads it. */\nconst Node: FC<NodeProps> = () => null\n\nexport interface NodeLabelProps {\n position?: SankeyLabelPosition\n /** Prints each node's total flow under its name. */\n showValues?: boolean\n valueFormatter?: (value: number) => string\n}\n\n/** Labels for the nodes. A slot, composed inside `<Node>`. */\nconst NodeLabel: FC<NodeLabelProps> = () => null\n\nexport interface LinkProps {\n variant?: SankeyLinkVariant\n /** Thins each band where it meets a node, so neighbours stay separable. */\n verticalPadding?: number\n}\n\n/** How the flow bands render. A slot: the root reads it. */\nconst Link: FC<LinkProps> = () => null\n\n/** The hover panel. No heading: the node's own name is the row label. */\nfunction Tooltip({ variant, roundness, defaultIndex }: ChartTooltipSlotProps) {\n const { isLoading } = useSankeyChart()\n if (isLoading) return null\n\n return (\n <ChartTooltip\n defaultIndex={defaultIndex}\n content={\n <ChartTooltipContent nameKey=\"name\" hideLabel roundness={roundness} variant={variant} />\n }\n />\n )\n}\n\n/** The decorative plate behind the diagram. */\nfunction Background({ variant = 'dots' }: { variant?: ChartBackgroundVariant }) {\n const { isLoading } = useSankeyChart()\n if (isLoading) return null\n return <ChartBackground variant={variant} />\n}\n\n/** A node's total flow — outgoing, or incoming for a leaf. */\nfunction nodeValue(data: SankeyData, name: string): number {\n const index = data.nodes.findIndex((node) => node.name === name)\n if (index === -1) return 0\n\n const out = data.links\n .filter((link) => link.source === index)\n .reduce((sum, link) => sum + link.value, 0)\n const incoming = data.links\n .filter((link) => link.target === index)\n .reduce((sum, link) => sum + link.value, 0)\n\n return out > 0 ? out : incoming\n}\n\n/** Turns the composed `<Node>` and `<Link>` slots into Recharts renderers. */\nfunction resolveRenderers(children: ReactNode): Pick<SankeyProps, 'node' | 'link'> {\n let node: NodeProps | null = null\n let link: LinkProps | null = null\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return\n if (child.type === Node) node = (child as ReactElement<NodeProps>).props\n if (child.type === Link) link = (child as ReactElement<LinkProps>).props\n })\n\n return {\n node: (props: SankeyNodeProps) => <SankeyNodeShape {...props} nodeSlot={node} />,\n link: (props: SankeyLinkProps) => <SankeyLinkShape {...props} linkSlot={link} />,\n }\n}\n\n/** Reads the `<NodeLabel>` composed inside a `<Node>`, if any. */\nfunction resolveNodeLabel(children: ReactNode): NodeLabelProps | null {\n let label: NodeLabelProps | null = null\n\n Children.forEach(children, (child) => {\n if (isValidElement(child) && child.type === NodeLabel) {\n label = (child as ReactElement<NodeLabelProps>).props\n }\n })\n\n return label\n}\n\n/** Whether a node is the selected one, or one hop from it. */\nfunction isConnected(data: SankeyData, selected: string | null, name: string): boolean {\n if (selected === null || selected === name) return true\n\n const selectedIndex = data.nodes.findIndex((node) => node.name === selected)\n const nodeIndex = data.nodes.findIndex((node) => node.name === name)\n\n return data.links.some(\n (link) =>\n (link.source === selectedIndex && link.target === nodeIndex) ||\n (link.source === nodeIndex && link.target === selectedIndex),\n )\n}\n\n/** One node rectangle, with its label and value. */\nfunction SankeyNodeShape({\n x,\n y,\n width,\n height,\n payload,\n nodeSlot,\n}: SankeyNodeProps & { nodeSlot: NodeProps | null }) {\n const { config, chartId, data, selectedNode, selectNode } = useSankeyChart()\n\n const radius = nodeSlot?.radius ?? 0\n const isClickable = nodeSlot?.isClickable ?? false\n const label = resolveNodeLabel(nodeSlot?.children)\n\n const name = payload.name\n const value = payload.value\n const icon = (payload as { icon?: ReactNode }).icon\n\n const dimmed = isClickable && !isConnected(data, selectedNode, name)\n const painted = name in config\n const text = config[name]?.label ?? name\n\n const format = label?.valueFormatter ?? ((n: number) => n.toLocaleString())\n const showValues = label?.showValues ?? false\n\n const centreX = x + width / 2\n const centreY = showValues ? y + height / 2 - 8 : y + height / 2\n const valueY = y + height / 2 + 8\n const outsideX = x + width + 8\n const outsideY = y + height / 2\n\n return (\n <Layer>\n <rect\n x={x}\n y={y}\n width={width}\n height={height}\n rx={radius}\n ry={radius}\n fill={painted ? `url(#${chartId}-node-${cssName(name)})` : 'currentColor'}\n fillOpacity={dimmed ? 0.15 : 0.9}\n className=\"text-(--ink) transition-opacity duration-(--duration-base)\"\n style={isClickable ? { cursor: 'pointer' } : undefined}\n onClick={() => {\n if (!isClickable) return\n selectNode(selectedNode === name ? null : name)\n }}\n />\n {label?.position === 'inside' && (\n <>\n {/* A scrim inside the node, so the label reads against whatever the\n node's own gradient happens to be under it. */}\n <rect\n x={x + 1}\n y={y + 1}\n width={width - 2}\n height={height - 2}\n rx={Math.max(0, radius - 1)}\n ry={Math.max(0, radius - 1)}\n opacity={dimmed ? 0.3 : 1}\n className=\"fill-(--chart-surface)/60 transition-opacity duration-(--duration-base)\"\n style={{ pointerEvents: 'none' }}\n />\n {icon && (\n <foreignObject\n x={centreX - 8}\n y={centreY - 30}\n width={16}\n height={16}\n opacity={dimmed ? 0.3 : 1}\n className=\"transition-opacity duration-(--duration-base)\"\n style={{ pointerEvents: 'none' }}\n >\n <div className=\"flex items-center justify-center text-(--ink-2)\">{icon}</div>\n </foreignObject>\n )}\n <text\n x={centreX}\n y={icon ? centreY - 4 : centreY}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n className=\"fill-(--ink) text-[10px] font-medium transition-opacity duration-(--duration-base)\"\n opacity={dimmed ? 0.3 : 1}\n style={{ pointerEvents: 'none' }}\n >\n {text}\n </text>\n {showValues && (\n <text\n x={centreX}\n y={valueY}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n className=\"fill-(--ink) font-mono text-xs font-medium tabular-nums transition-opacity duration-(--duration-base)\"\n opacity={dimmed ? 0.3 : 0.6}\n style={{ pointerEvents: 'none' }}\n >\n {format(value)}\n </text>\n )}\n </>\n )}\n {label?.position === 'outside' && (\n <>\n <text\n x={outsideX}\n y={outsideY - (showValues ? 8 : 0)}\n textAnchor=\"start\"\n dominantBaseline=\"middle\"\n className=\"fill-(--ink) text-xs\"\n style={{ pointerEvents: 'none' }}\n >\n {text}\n </text>\n {showValues && (\n <text\n x={outsideX}\n y={outsideY + 8}\n textAnchor=\"start\"\n dominantBaseline=\"middle\"\n opacity={0.5}\n className=\"fill-(--ink) font-mono text-xs tabular-nums\"\n style={{ pointerEvents: 'none' }}\n >\n {format(value)}\n </text>\n )}\n </>\n )}\n </Layer>\n )\n}\n\n/** One flow band. */\nfunction SankeyLinkShape({\n sourceX,\n targetX,\n sourceY,\n targetY,\n sourceControlX,\n targetControlX,\n linkWidth,\n index,\n payload,\n linkSlot,\n}: SankeyLinkProps & { linkSlot: LinkProps | null }) {\n const { config, chartId, selectedNode } = useSankeyChart()\n\n const variant = linkSlot?.variant ?? 'gradient'\n const verticalPadding = linkSlot?.verticalPadding ?? 0\n\n const sourceName = payload.source.name\n const targetName = payload.target.name\n const lit =\n selectedNode === null || selectedNode === sourceName || selectedNode === targetName\n\n const half = Math.max(1, linkWidth - verticalPadding) / 2\n\n // Two mirrored cubics closed into a ribbon: the band has to be a filled shape\n // rather than a thick stroke, because its width changes along its length.\n const band = `M${sourceX},${sourceY - half}\n C${sourceControlX},${sourceY - half} ${targetControlX},${targetY - half} ${targetX},${targetY - half}\n L${targetX},${targetY + half}\n C${targetControlX},${targetY + half} ${sourceControlX},${sourceY + half} ${sourceX},${sourceY + half}\n Z`\n\n const sourceColor = sourceName in config ? `var(--color-${cssName(sourceName)}-0)` : 'currentColor'\n const targetColor = targetName in config ? `var(--color-${cssName(targetName)}-0)` : 'currentColor'\n\n return (\n <Layer className=\"text-(--ink)\">\n <defs>\n {variant === 'gradient' && (\n <linearGradient id={`${chartId}-link-${index}`} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stopColor={sourceColor} stopOpacity={0.2} />\n <stop offset=\"50%\" stopColor={sourceColor} stopOpacity={0.5} />\n <stop offset=\"100%\" stopColor={targetColor} stopOpacity={0.2} />\n </linearGradient>\n )}\n {/* The edge that traces a band connected to the selection. It fades out\n at both ends so it reads as a highlight rather than as an outline. */}\n <linearGradient id={`${chartId}-link-edge-${index}`} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stopColor=\"var(--accent)\" stopOpacity={0} />\n <stop offset=\"15%\" stopColor=\"var(--accent)\" stopOpacity={0.8} />\n <stop offset=\"50%\" stopColor=\"var(--accent)\" stopOpacity={1} />\n <stop offset=\"85%\" stopColor=\"var(--accent)\" stopOpacity={0.8} />\n <stop offset=\"100%\" stopColor=\"var(--accent)\" stopOpacity={0} />\n </linearGradient>\n </defs>\n <path\n d={band}\n fill={linkFill(variant, chartId, index, config, sourceName, targetName)}\n // Read from the ground rather than fixed: a band at 0.4 of ink over\n // paper reads; the same 0.4 of paper-white over near-black does not.\n fillOpacity={lit ? 'calc(var(--chart-fill) * 2.6)' : 'calc(var(--chart-fill) * 0.7)'}\n stroke={selectedNode !== null && lit ? `url(#${chartId}-link-edge-${index})` : 'none'}\n strokeWidth={1}\n className=\"transition-opacity duration-(--duration-base)\"\n />\n </Layer>\n )\n}\n\n/** The paint reference for a band, given its variant. */\nfunction linkFill(\n variant: SankeyLinkVariant,\n chartId: string,\n index: number,\n config: ChartConfig,\n sourceName: string,\n targetName: string,\n): string {\n switch (variant) {\n case 'gradient':\n return `url(#${chartId}-link-${index})`\n case 'source':\n return sourceName in config ? `url(#${chartId}-node-${cssName(sourceName)})` : 'currentColor'\n case 'target':\n return targetName in config ? `url(#${chartId}-node-${cssName(targetName)})` : 'currentColor'\n default:\n return 'currentColor'\n }\n}\n\n/** The skeleton's node columns. Fixed, so the shape reads as a sankey at once. */\nconst SKELETON_NODES = [\n { x: 30, y: 25, width: 12, height: 65, delay: 0 },\n { x: 30, y: 110, width: 12, height: 50, delay: 0.3 },\n { x: 30, y: 180, width: 12, height: 45, delay: 0.15 },\n { x: 244, y: 20, width: 12, height: 55, delay: 0.45 },\n { x: 244, y: 95, width: 12, height: 75, delay: 0.6 },\n { x: 244, y: 190, width: 12, height: 40, delay: 0.25 },\n { x: 458, y: 35, width: 12, height: 80, delay: 0.5 },\n { x: 458, y: 135, width: 12, height: 90, delay: 0.1 },\n]\n\nconst SKELETON_LINKS = [\n { from: 0, to: 3, width: 26, delay: 0.2 },\n { from: 0, to: 4, width: 18, delay: 0.7 },\n { from: 1, to: 4, width: 24, delay: 0.4 },\n { from: 1, to: 5, width: 12, delay: 0.9 },\n { from: 2, to: 4, width: 16, delay: 0.1 },\n { from: 2, to: 5, width: 14, delay: 0.55 },\n { from: 3, to: 6, width: 22, delay: 0.35 },\n { from: 3, to: 7, width: 18, delay: 0.8 },\n { from: 4, to: 6, width: 28, delay: 0.05 },\n { from: 4, to: 7, width: 32, delay: 0.65 },\n { from: 5, to: 7, width: 16, delay: 0.45 },\n]\n\n/** A bezier from one skeleton node's right edge to another's left. */\nfunction skeletonPath(fromIndex: number, toIndex: number): string {\n const from = SKELETON_NODES[fromIndex]!\n const to = SKELETON_NODES[toIndex]!\n const startX = from.x + from.width\n const startY = from.y + from.height / 2\n const endX = to.x\n const endY = to.y + to.height / 2\n return `M${startX},${startY} C${startX + (endX - startX) * 0.4},${startY} ${startX + (endX - startX) * 0.6},${endY} ${endX},${endY}`\n}\n\n/** The skeleton diagram: a fixed graph whose parts pulse out of phase. */\nfunction LoadingSankey() {\n const reduceMotion = useReducedMotion()\n\n if (reduceMotion) {\n return (\n <>\n {SKELETON_LINKS.map((link) => (\n <path\n key={`${link.from}-${link.to}`}\n d={skeletonPath(link.from, link.to)}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={link.width}\n opacity={0.09}\n />\n ))}\n {SKELETON_NODES.map((node) => (\n <rect\n key={`${node.x}-${node.y}`}\n x={node.x}\n y={node.y}\n width={node.width}\n height={node.height}\n rx={2}\n fill=\"currentColor\"\n opacity={0.25}\n />\n ))}\n </>\n )\n }\n\n return (\n <>\n {SKELETON_LINKS.map((link, index) => (\n <motion.path\n key={`${link.from}-${link.to}`}\n d={skeletonPath(link.from, link.to)}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={link.width}\n initial={{ opacity: 0.04 }}\n animate={{ opacity: [0.04, 0.14, 0.04] }}\n transition={{\n duration: LOADING_PULSE * (0.8 + (index % 3) * 0.2),\n delay: link.delay,\n repeat: Infinity,\n ease: 'easeInOut',\n }}\n />\n ))}\n {SKELETON_NODES.map((node, index) => (\n <motion.rect\n key={`${node.x}-${node.y}`}\n x={node.x}\n y={node.y}\n width={node.width}\n height={node.height}\n rx={2}\n fill=\"currentColor\"\n initial={{ opacity: 0.15 }}\n animate={{ opacity: [0.15, 0.4, 0.15] }}\n transition={{\n duration: LOADING_PULSE * (0.9 + (index % 4) * 0.1),\n delay: node.delay,\n repeat: Infinity,\n ease: 'easeInOut',\n }}\n />\n ))}\n </>\n )\n}\n\nSankeyChart.Node = Node\nSankeyChart.NodeLabel = NodeLabel\nSankeyChart.Link = Link\nSankeyChart.Tooltip = Tooltip\nSankeyChart.Background = Background\n\nexport default SankeyChart\n"],"mappings":"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","names":[]}
|