@misoto22/design 0.5.0 → 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/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 +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,93 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, ComponentProps } from 'react';
|
|
3
|
+
import { Treemap } from 'recharts';
|
|
4
|
+
import { ChartConfig } from '../lib/chart.js';
|
|
5
|
+
import { ChartTooltipSlotProps } from '../AreaChart/AreaChart.js';
|
|
6
|
+
import '../lib/empty.js';
|
|
7
|
+
import '../lib/values.js';
|
|
8
|
+
import '../lib/sonify-control.js';
|
|
9
|
+
import '../lib/sonify.js';
|
|
10
|
+
import '../lib/background.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 tile is painted.
|
|
24
|
+
*
|
|
25
|
+
* `ramp` walks the series ramp so siblings separate by lightness; `nested`
|
|
26
|
+
* darkens by DEPTH instead, which is the right encoding when the tree has more
|
|
27
|
+
* than one level and the question is "what is inside what".
|
|
28
|
+
*/
|
|
29
|
+
type TreemapVariant = 'ramp' | 'nested';
|
|
30
|
+
/** A node in the tree. Children make it a branch. */
|
|
31
|
+
interface TreemapNode {
|
|
32
|
+
name: string;
|
|
33
|
+
/** Leaf value. Omit on a branch — a branch is the sum of its children. */
|
|
34
|
+
size?: number;
|
|
35
|
+
children?: TreemapNode[];
|
|
36
|
+
[key: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
/** The raw Recharts Treemap props a consumer may still reach for. */
|
|
39
|
+
type TreemapExtras = Omit<ComponentProps<typeof Treemap>, 'data' | 'dataKey'>;
|
|
40
|
+
interface TreemapChartProps {
|
|
41
|
+
/** Tile names → their label and paint. Optional: the ramp covers unnamed tiles. */
|
|
42
|
+
config?: ChartConfig;
|
|
43
|
+
/** The tree. One level is a flat set of tiles; two is a nested treemap. */
|
|
44
|
+
data: TreemapNode[];
|
|
45
|
+
/**
|
|
46
|
+
* What the chart shows, in a sentence a reader could act on. Required, and
|
|
47
|
+
* announced to a screen reader even when it is not printed.
|
|
48
|
+
*/
|
|
49
|
+
title: string;
|
|
50
|
+
/** Prints the title above the plot instead of hiding it from sight. */
|
|
51
|
+
showTitle?: boolean;
|
|
52
|
+
/** A line under the title — the unit, the window, the caveat. */
|
|
53
|
+
description?: ReactNode;
|
|
54
|
+
/** Merged onto the figure, last, so a call site can size or space it. */
|
|
55
|
+
className?: string;
|
|
56
|
+
variant?: TreemapVariant;
|
|
57
|
+
/** The leaf field holding each tile's number. */
|
|
58
|
+
dataKey?: string;
|
|
59
|
+
/** How square the tiles are pushed to be. Recharts' own squarify parameter. */
|
|
60
|
+
aspectRatio?: number;
|
|
61
|
+
/** Prints each tile's name on it, where the tile is big enough to hold it. */
|
|
62
|
+
showLabels?: boolean;
|
|
63
|
+
/** The hover panel. */
|
|
64
|
+
children?: ReactNode;
|
|
65
|
+
chartProps?: TreemapExtras;
|
|
66
|
+
/** Drops the hidden table view. Only correct when the page prints the data itself. */
|
|
67
|
+
hideDataTable?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Part of a whole, when the whole has too many parts for a pie — and the parts
|
|
71
|
+
* nest.
|
|
72
|
+
*
|
|
73
|
+
* A treemap encodes value as AREA, which the eye reads worse than length but
|
|
74
|
+
* far better than angle, and it is the only form here that stays readable at
|
|
75
|
+
* fifty items. Two rules make it honest: no negative values (an area cannot be
|
|
76
|
+
* negative), and the tiles have to sum to something a reader recognises as the
|
|
77
|
+
* whole.
|
|
78
|
+
*
|
|
79
|
+
* Reach for `<BarChart>` when there are under a dozen items and the ranking
|
|
80
|
+
* matters — a bar's length is the more precise encoding, and a treemap's
|
|
81
|
+
* layout deliberately does not order its tiles by value alone.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* <TreemapChart title="Bundle size by package" data={packages} showLabels>
|
|
85
|
+
* <TreemapChart.Tooltip />
|
|
86
|
+
* </TreemapChart>
|
|
87
|
+
*/
|
|
88
|
+
declare function TreemapChart({ config, data, title, showTitle, description, className, variant, dataKey, aspectRatio, showLabels, children, chartProps, hideDataTable, }: TreemapChartProps): react.JSX.Element;
|
|
89
|
+
declare namespace TreemapChart {
|
|
90
|
+
var Tooltip: ({ variant, roundness }: ChartTooltipSlotProps) => react.JSX.Element;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { TreemapChart, type TreemapChartProps, type TreemapExtras, type TreemapNode, type TreemapVariant, TreemapChart as default };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { Treemap as RechartsTreemap } from "recharts";
|
|
5
|
+
import { ChartContainer, cssName } from "../lib/chart.js";
|
|
6
|
+
import { ChartFigure } from "../lib/figure.js";
|
|
7
|
+
import { ChartTooltip, ChartTooltipContent } from "../lib/tooltip.js";
|
|
8
|
+
function TreemapChart({
|
|
9
|
+
config = {},
|
|
10
|
+
data,
|
|
11
|
+
title,
|
|
12
|
+
showTitle,
|
|
13
|
+
description,
|
|
14
|
+
className,
|
|
15
|
+
variant = "ramp",
|
|
16
|
+
dataKey = "size",
|
|
17
|
+
aspectRatio = 4 / 3,
|
|
18
|
+
showLabels = true,
|
|
19
|
+
children,
|
|
20
|
+
chartProps,
|
|
21
|
+
hideDataTable = false
|
|
22
|
+
}) {
|
|
23
|
+
const chartId = useId().replace(/:/g, "");
|
|
24
|
+
const leaves = flatten(data);
|
|
25
|
+
return /* @__PURE__ */ jsx(
|
|
26
|
+
ChartFigure,
|
|
27
|
+
{
|
|
28
|
+
title,
|
|
29
|
+
showTitle,
|
|
30
|
+
description,
|
|
31
|
+
className,
|
|
32
|
+
table: hideDataTable ? false : {
|
|
33
|
+
rows: leaves,
|
|
34
|
+
rowKey: "path",
|
|
35
|
+
columns: [{ key: dataKey, label: "Value" }]
|
|
36
|
+
},
|
|
37
|
+
children: /* @__PURE__ */ jsx(ChartContainer, { config, children: /* @__PURE__ */ jsx(
|
|
38
|
+
RechartsTreemap,
|
|
39
|
+
{
|
|
40
|
+
data,
|
|
41
|
+
dataKey,
|
|
42
|
+
nameKey: "name",
|
|
43
|
+
aspectRatio,
|
|
44
|
+
isAnimationActive: false,
|
|
45
|
+
content: /* @__PURE__ */ jsx(TreemapTile, { chartId, variant, config, showLabels }),
|
|
46
|
+
...chartProps,
|
|
47
|
+
children
|
|
48
|
+
}
|
|
49
|
+
) })
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function flatten(nodes, prefix = "") {
|
|
54
|
+
return nodes.flatMap((node) => {
|
|
55
|
+
const path = prefix ? `${prefix} \u203A ${node.name}` : node.name;
|
|
56
|
+
if (node.children?.length) return flatten(node.children, path);
|
|
57
|
+
return [{ ...node, path }];
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function TreemapTile({
|
|
61
|
+
chartId,
|
|
62
|
+
variant,
|
|
63
|
+
config,
|
|
64
|
+
showLabels,
|
|
65
|
+
x = 0,
|
|
66
|
+
y = 0,
|
|
67
|
+
width = 0,
|
|
68
|
+
height = 0,
|
|
69
|
+
depth = 1,
|
|
70
|
+
index = 0,
|
|
71
|
+
name = ""
|
|
72
|
+
}) {
|
|
73
|
+
if (width <= 0 || height <= 0) return null;
|
|
74
|
+
const slot = variant === "nested" ? `var(--series-${Math.min(8, depth * 2)})` : name in config ? `var(--color-${cssName(name)}-0)` : `var(--series-${index % 8 + 1})`;
|
|
75
|
+
const roomForLabel = showLabels && width > 56 && height > 26;
|
|
76
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
"rect",
|
|
79
|
+
{
|
|
80
|
+
x,
|
|
81
|
+
y,
|
|
82
|
+
width,
|
|
83
|
+
height,
|
|
84
|
+
fill: slot,
|
|
85
|
+
stroke: "var(--chart-surface)",
|
|
86
|
+
strokeWidth: 2
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
roomForLabel && /* @__PURE__ */ jsx(
|
|
90
|
+
"text",
|
|
91
|
+
{
|
|
92
|
+
x: x + 8,
|
|
93
|
+
y: y + 18,
|
|
94
|
+
className: "fill-(--chart-surface) text-[11px] font-medium",
|
|
95
|
+
style: { pointerEvents: "none" },
|
|
96
|
+
children: name
|
|
97
|
+
}
|
|
98
|
+
),
|
|
99
|
+
/* @__PURE__ */ jsx("title", { children: name }),
|
|
100
|
+
/* @__PURE__ */ jsx("desc", { children: chartId })
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
function Tooltip({ variant, roundness }) {
|
|
104
|
+
return /* @__PURE__ */ jsx(
|
|
105
|
+
ChartTooltip,
|
|
106
|
+
{
|
|
107
|
+
cursor: false,
|
|
108
|
+
content: /* @__PURE__ */ jsx(ChartTooltipContent, { nameKey: "name", hideLabel: true, roundness, variant })
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
TreemapChart.Tooltip = Tooltip;
|
|
113
|
+
var TreemapChart_default = TreemapChart;
|
|
114
|
+
export {
|
|
115
|
+
TreemapChart,
|
|
116
|
+
TreemapChart_default as default
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=TreemapChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/TreemapChart/TreemapChart.tsx"],"sourcesContent":["'use client'\n\nimport { useId, type ComponentProps, type ReactNode } from 'react'\nimport { Treemap as RechartsTreemap } from 'recharts'\nimport { ChartContainer, cssName, type ChartConfig } from '../lib/chart'\nimport { ChartFigure } from '../lib/figure'\nimport { ChartTooltip, ChartTooltipContent } from '../lib/tooltip'\nimport type { ChartTooltipSlotProps } from '../AreaChart/AreaChart'\n\n/**\n * How a tile is painted.\n *\n * `ramp` walks the series ramp so siblings separate by lightness; `nested`\n * darkens by DEPTH instead, which is the right encoding when the tree has more\n * than one level and the question is \"what is inside what\".\n */\nexport type TreemapVariant = 'ramp' | 'nested'\n\n/** A node in the tree. Children make it a branch. */\nexport interface TreemapNode {\n name: string\n /** Leaf value. Omit on a branch — a branch is the sum of its children. */\n size?: number\n children?: TreemapNode[]\n [key: string]: unknown\n}\n\n/** The raw Recharts Treemap props a consumer may still reach for. */\nexport type TreemapExtras = Omit<ComponentProps<typeof RechartsTreemap>, 'data' | 'dataKey'>\n\nexport interface TreemapChartProps {\n /** Tile names → their label and paint. Optional: the ramp covers unnamed tiles. */\n config?: ChartConfig\n /** The tree. One level is a flat set of tiles; two is a nested treemap. */\n data: TreemapNode[]\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 /** Merged onto the figure, last, so a call site can size or space it. */\n className?: string\n variant?: TreemapVariant\n /** The leaf field holding each tile's number. */\n dataKey?: string\n /** How square the tiles are pushed to be. Recharts' own squarify parameter. */\n aspectRatio?: number\n /** Prints each tile's name on it, where the tile is big enough to hold it. */\n showLabels?: boolean\n /** The hover panel. */\n children?: ReactNode\n chartProps?: TreemapExtras\n /** Drops the hidden table view. Only correct when the page prints the data itself. */\n hideDataTable?: boolean\n}\n\n/**\n * Part of a whole, when the whole has too many parts for a pie — and the parts\n * nest.\n *\n * A treemap encodes value as AREA, which the eye reads worse than length but\n * far better than angle, and it is the only form here that stays readable at\n * fifty items. Two rules make it honest: no negative values (an area cannot be\n * negative), and the tiles have to sum to something a reader recognises as the\n * whole.\n *\n * Reach for `<BarChart>` when there are under a dozen items and the ranking\n * matters — a bar's length is the more precise encoding, and a treemap's\n * layout deliberately does not order its tiles by value alone.\n *\n * @example\n * <TreemapChart title=\"Bundle size by package\" data={packages} showLabels>\n * <TreemapChart.Tooltip />\n * </TreemapChart>\n */\nexport function TreemapChart({\n config = {},\n data,\n title,\n showTitle,\n description,\n className,\n variant = 'ramp',\n dataKey = 'size',\n aspectRatio = 4 / 3,\n showLabels = true,\n children,\n chartProps,\n hideDataTable = false,\n}: TreemapChartProps) {\n const chartId = useId().replace(/:/g, '')\n\n // Flattened for the table view, because a nested tree read aloud row by row\n // is not something anyone can follow — the leaves are the facts.\n const leaves = flatten(data)\n\n return (\n <ChartFigure\n title={title}\n showTitle={showTitle}\n description={description}\n className={className}\n table={\n hideDataTable\n ? false\n : {\n rows: leaves,\n rowKey: 'path',\n columns: [{ key: dataKey, label: 'Value' }],\n }\n }\n >\n <ChartContainer config={config}>\n <RechartsTreemap\n data={data}\n dataKey={dataKey}\n nameKey=\"name\"\n aspectRatio={aspectRatio}\n isAnimationActive={false}\n content={\n <TreemapTile chartId={chartId} variant={variant} config={config} showLabels={showLabels} />\n }\n {...chartProps}\n >\n {children}\n </RechartsTreemap>\n </ChartContainer>\n </ChartFigure>\n )\n}\n\n/** Every leaf, with the path that names it. */\nfunction flatten(nodes: TreemapNode[], prefix = ''): Record<string, unknown>[] {\n return nodes.flatMap((node) => {\n const path = prefix ? `${prefix} › ${node.name}` : node.name\n if (node.children?.length) return flatten(node.children, path)\n return [{ ...node, path }]\n })\n}\n\ninterface TileProps {\n chartId: string\n variant: TreemapVariant\n config: ChartConfig\n showLabels: boolean\n // Recharts hands the geometry in as loose props on the cloned element.\n x?: number\n y?: number\n width?: number\n height?: number\n depth?: number\n index?: number\n name?: string\n}\n\n/**\n * One tile.\n *\n * The gap between tiles is a surface-coloured stroke rather than a smaller\n * rect, so the tiles still tile — a treemap whose parts do not touch stops\n * reading as a partition of one whole.\n */\nfunction TreemapTile({\n chartId,\n variant,\n config,\n showLabels,\n x = 0,\n y = 0,\n width = 0,\n height = 0,\n depth = 1,\n index = 0,\n name = '',\n}: TileProps) {\n if (width <= 0 || height <= 0) return null\n\n const slot =\n variant === 'nested'\n ? `var(--series-${Math.min(8, depth * 2)})`\n : name in config\n ? `var(--color-${cssName(name)}-0)`\n : `var(--series-${(index % 8) + 1})`\n\n // Only label a tile with room for one. A clipped word is worse than none.\n const roomForLabel = showLabels && width > 56 && height > 26\n\n return (\n <g>\n <rect\n x={x}\n y={y}\n width={width}\n height={height}\n fill={slot}\n stroke=\"var(--chart-surface)\"\n strokeWidth={2}\n />\n {roomForLabel && (\n <text\n x={x + 8}\n y={y + 18}\n className=\"fill-(--chart-surface) text-[11px] font-medium\"\n style={{ pointerEvents: 'none' }}\n >\n {name}\n </text>\n )}\n {/* A hidden id so the tooltip can key off the same name the tile paints. */}\n <title>{name}</title>\n <desc>{chartId}</desc>\n </g>\n )\n}\n\n/** The hover panel. No heading: the tile's own name is the row label. */\nfunction Tooltip({ variant, roundness }: ChartTooltipSlotProps) {\n return (\n <ChartTooltip\n cursor={false}\n content={<ChartTooltipContent nameKey=\"name\" hideLabel roundness={roundness} variant={variant} />}\n />\n )\n}\n\nTreemapChart.Tooltip = Tooltip\n\nexport default TreemapChart\n"],"mappings":";AA4HY,cAoER,YApEQ;AA1HZ,SAAS,aAAkD;AAC3D,SAAS,WAAW,uBAAuB;AAC3C,SAAS,gBAAgB,eAAiC;AAC1D,SAAS,mBAAmB;AAC5B,SAAS,cAAc,2BAA2B;AAyE3C,SAAS,aAAa;AAAA,EAC3B,SAAS,CAAC;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc,IAAI;AAAA,EAClB,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,gBAAgB;AAClB,GAAsB;AACpB,QAAM,UAAU,MAAM,EAAE,QAAQ,MAAM,EAAE;AAIxC,QAAM,SAAS,QAAQ,IAAI;AAE3B,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OACE,gBACI,QACA;AAAA,QACE,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,CAAC,EAAE,KAAK,SAAS,OAAO,QAAQ,CAAC;AAAA,MAC5C;AAAA,MAGN,8BAAC,kBAAe,QACd;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,SAAQ;AAAA,UACR;AAAA,UACA,mBAAmB;AAAA,UACnB,SACE,oBAAC,eAAY,SAAkB,SAAkB,QAAgB,YAAwB;AAAA,UAE1F,GAAG;AAAA,UAEH;AAAA;AAAA,MACH,GACF;AAAA;AAAA,EACF;AAEJ;AAGA,SAAS,QAAQ,OAAsB,SAAS,IAA+B;AAC7E,SAAO,MAAM,QAAQ,CAAC,SAAS;AAC7B,UAAM,OAAO,SAAS,GAAG,MAAM,WAAM,KAAK,IAAI,KAAK,KAAK;AACxD,QAAI,KAAK,UAAU,OAAQ,QAAO,QAAQ,KAAK,UAAU,IAAI;AAC7D,WAAO,CAAC,EAAE,GAAG,MAAM,KAAK,CAAC;AAAA,EAC3B,CAAC;AACH;AAwBA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AACT,GAAc;AACZ,MAAI,SAAS,KAAK,UAAU,EAAG,QAAO;AAEtC,QAAM,OACJ,YAAY,WACR,gBAAgB,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC,MACtC,QAAQ,SACN,eAAe,QAAQ,IAAI,CAAC,QAC5B,gBAAiB,QAAQ,IAAK,CAAC;AAGvC,QAAM,eAAe,cAAc,QAAQ,MAAM,SAAS;AAE1D,SACE,qBAAC,OACC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,QAAO;AAAA,QACP,aAAa;AAAA;AAAA,IACf;AAAA,IACC,gBACC;AAAA,MAAC;AAAA;AAAA,QACC,GAAG,IAAI;AAAA,QACP,GAAG,IAAI;AAAA,QACP,WAAU;AAAA,QACV,OAAO,EAAE,eAAe,OAAO;AAAA,QAE9B;AAAA;AAAA,IACH;AAAA,IAGF,oBAAC,WAAO,gBAAK;AAAA,IACb,oBAAC,UAAM,mBAAQ;AAAA,KACjB;AAEJ;AAGA,SAAS,QAAQ,EAAE,SAAS,UAAU,GAA0B;AAC9D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ;AAAA,MACR,SAAS,oBAAC,uBAAoB,SAAQ,QAAO,WAAS,MAAC,WAAsB,SAAkB;AAAA;AAAA,EACjG;AAEJ;AAEA,aAAa,UAAU;AAEvB,IAAO,uBAAQ;","names":[]}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { ChartTooltipSlotProps } from '../AreaChart/AreaChart.js';
|
|
2
|
+
import { ChartXAxisProps, ChartYAxisProps } from '../BarChart/BarChart.js';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
5
|
+
import { Bar, BarChart, CartesianGrid } from 'recharts';
|
|
6
|
+
import { ChartConfig } from '../lib/chart.js';
|
|
7
|
+
import { ChartEmptyProps } from '../lib/empty.js';
|
|
8
|
+
import { ChartBackgroundVariant } from '../lib/background.js';
|
|
9
|
+
import { ReferenceLine, ReferenceBand, Annotation } from '../lib/annotations.js';
|
|
10
|
+
import '../lib/values.js';
|
|
11
|
+
import '../lib/sonify-control.js';
|
|
12
|
+
import '../lib/sonify.js';
|
|
13
|
+
import '../lib/brush.js';
|
|
14
|
+
import '../lib/toolbar.js';
|
|
15
|
+
import '../lib/zoom.js';
|
|
16
|
+
import '../lib/figure.js';
|
|
17
|
+
import '../lib/paint.js';
|
|
18
|
+
import '../lib/dot.js';
|
|
19
|
+
import '../lib/legend.js';
|
|
20
|
+
import '../lib/tooltip.js';
|
|
21
|
+
import 'recharts/types/component/DefaultTooltipContent';
|
|
22
|
+
|
|
23
|
+
/** How a step moves the running total. */
|
|
24
|
+
type WaterfallStepType = 'delta' | 'total';
|
|
25
|
+
/** Which way a bar goes, which is what its texture encodes. */
|
|
26
|
+
type WaterfallDirection = 'increase' | 'decrease' | 'total';
|
|
27
|
+
interface WaterfallStep {
|
|
28
|
+
/** The step's name on the category axis. Doubles as its key. */
|
|
29
|
+
name: string;
|
|
30
|
+
/**
|
|
31
|
+
* The signed change this step makes, or — on a `total` step — the absolute
|
|
32
|
+
* figure the running total is set to.
|
|
33
|
+
*
|
|
34
|
+
* Omit it on a `total` and the running total is used, which is the right
|
|
35
|
+
* default for the closing bar: an end total typed by hand can disagree with
|
|
36
|
+
* the deltas above it, and the chart would draw the disagreement without
|
|
37
|
+
* saying anything.
|
|
38
|
+
*/
|
|
39
|
+
value?: number;
|
|
40
|
+
/**
|
|
41
|
+
* `delta` (the default) adds `value` to the running total and floats the bar
|
|
42
|
+
* where that lands. `total` plants a bar on the baseline — an opening
|
|
43
|
+
* balance, a subtotal, a closing figure.
|
|
44
|
+
*/
|
|
45
|
+
type?: WaterfallStepType;
|
|
46
|
+
}
|
|
47
|
+
interface WaterfallChartProps {
|
|
48
|
+
/**
|
|
49
|
+
* The single series — its label and its paint. Only the FIRST entry is read;
|
|
50
|
+
* a waterfall has one quantity and as many bars as it has steps.
|
|
51
|
+
*/
|
|
52
|
+
config?: ChartConfig;
|
|
53
|
+
/**
|
|
54
|
+
* The steps, in the order they are applied. Order is the arithmetic: the
|
|
55
|
+
* chart does not sort, because a different order is a different total at
|
|
56
|
+
* every intermediate bar.
|
|
57
|
+
*/
|
|
58
|
+
data: WaterfallStep[];
|
|
59
|
+
/**
|
|
60
|
+
* What the chart shows, in a sentence a reader could act on. Required, and
|
|
61
|
+
* announced to a screen reader even when it is not printed.
|
|
62
|
+
*/
|
|
63
|
+
title: string;
|
|
64
|
+
/** Prints the title above the plot instead of hiding it from sight. */
|
|
65
|
+
showTitle?: boolean;
|
|
66
|
+
/** A line under the title — the unit, the window, the caveat. */
|
|
67
|
+
description?: ReactNode;
|
|
68
|
+
/** The composed parts — axes, grid, tooltip, and `<WaterfallChart.Bars>`. */
|
|
69
|
+
children: ReactNode;
|
|
70
|
+
/** Merged onto the figure, last, so a call site can size or space it. */
|
|
71
|
+
className?: string;
|
|
72
|
+
/** Escape hatch onto the raw Recharts chart element. */
|
|
73
|
+
chartProps?: ComponentProps<typeof BarChart>;
|
|
74
|
+
/** Formats every number the chart prints — ticks, labels, tooltip, table. */
|
|
75
|
+
formatValue?: (value: number) => string;
|
|
76
|
+
/** Drops the hidden table view. Only correct when the page prints the data itself. */
|
|
77
|
+
hideDataTable?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* What the chart shows when it has nothing to draw. `false` keeps the axes,
|
|
80
|
+
* for a chart whose emptiness is itself the reading.
|
|
81
|
+
*/
|
|
82
|
+
empty?: ChartEmptyProps | false;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* How a total got from one figure to another — an opening balance, the signed
|
|
86
|
+
* contributions that moved it, and where it closed.
|
|
87
|
+
*
|
|
88
|
+
* The form for "why did this change", which a pair of bars cannot answer and a
|
|
89
|
+
* pie chart answers wrongly, because contributions can be NEGATIVE and a slice
|
|
90
|
+
* cannot. Reach for `<BarChart>` when the parts do not have to add up to the
|
|
91
|
+
* gap between two totals, and for `<FunnelChart>` when the quantity only ever
|
|
92
|
+
* shrinks.
|
|
93
|
+
*
|
|
94
|
+
* **The connectors are the claim to be careful about.** They draw the steps as
|
|
95
|
+
* a sequence — this happened, then this — and most breakdowns are not
|
|
96
|
+
* sequential at all: churn and expansion in the same month are simultaneous,
|
|
97
|
+
* and the order they are listed in is an editorial choice. The arithmetic
|
|
98
|
+
* survives any order; the STORY does not, and a reader will take the leftmost
|
|
99
|
+
* bar as the first cause. Two related traps: the intermediate bars are floating
|
|
100
|
+
* lengths read against no baseline, so a small step high up the cascade is hard
|
|
101
|
+
* to compare with a large one near zero; and any step that is itself a net of
|
|
102
|
+
* two larger opposing movements is invisible as such. Where the order is
|
|
103
|
+
* arbitrary, say so in the `description`.
|
|
104
|
+
*
|
|
105
|
+
* Recharts earns its place for the axes, grid and tooltip. Each bar is a
|
|
106
|
+
* floating range — from the running total to the new one — with a custom shape
|
|
107
|
+
* over it, because Recharts has no waterfall mark and the connectors have to be
|
|
108
|
+
* drawn from the same geometry as the bars they join.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* <WaterfallChart title="Revenue bridge, FY25" data={steps}>
|
|
112
|
+
* <WaterfallChart.Grid />
|
|
113
|
+
* <WaterfallChart.XAxis />
|
|
114
|
+
* <WaterfallChart.YAxis label="AUD" />
|
|
115
|
+
* <WaterfallChart.Tooltip />
|
|
116
|
+
* <WaterfallChart.Bars showValues />
|
|
117
|
+
* </WaterfallChart>
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* const steps = [
|
|
121
|
+
* { name: 'FY24', value: 1200, type: 'total' as const },
|
|
122
|
+
* { name: 'New', value: 340 },
|
|
123
|
+
* { name: 'Churn', value: -180 },
|
|
124
|
+
* // No value: the closing bar is whatever the deltas add up to.
|
|
125
|
+
* { name: 'FY25', type: 'total' as const },
|
|
126
|
+
* ]
|
|
127
|
+
*/
|
|
128
|
+
declare function WaterfallChart({ config, data, title, showTitle, description, children, className, chartProps, formatValue, hideDataTable, empty, }: WaterfallChartProps): react.JSX.Element;
|
|
129
|
+
declare namespace WaterfallChart {
|
|
130
|
+
var Bars: ({ radius, connectors, showValues, barProps, }: WaterfallBarsProps) => react.JSX.Element;
|
|
131
|
+
var XAxis: ({ dataKey, tickLine, axisLine, tickMargin, minTickGap, label, ...rest }: ChartXAxisProps) => react.JSX.Element;
|
|
132
|
+
var YAxis: ({ tickLine, axisLine, tickMargin, width, label, tickFormatter, ...rest }: ChartYAxisProps) => react.JSX.Element;
|
|
133
|
+
var Grid: ({ strokeDasharray, vertical, ...rest }: ComponentProps<typeof CartesianGrid>) => react.JSX.Element;
|
|
134
|
+
var Tooltip: ({ variant, roundness, defaultIndex }: ChartTooltipSlotProps) => react.JSX.Element;
|
|
135
|
+
var Background: ({ variant }: {
|
|
136
|
+
variant: ChartBackgroundVariant;
|
|
137
|
+
}) => react.JSX.Element;
|
|
138
|
+
var ReferenceLine: typeof ReferenceLine;
|
|
139
|
+
var ReferenceBand: typeof ReferenceBand;
|
|
140
|
+
var Annotation: typeof Annotation;
|
|
141
|
+
}
|
|
142
|
+
interface WaterfallBarsProps {
|
|
143
|
+
/** The bars' corner. */
|
|
144
|
+
radius?: number;
|
|
145
|
+
/**
|
|
146
|
+
* Joins each bar's closing edge to where the next one starts.
|
|
147
|
+
*
|
|
148
|
+
* On by default: without them a waterfall is a row of bars floating at
|
|
149
|
+
* unrelated heights, and the cascade — which is the entire point of the form
|
|
150
|
+
* — has to be reconstructed by the reader.
|
|
151
|
+
*/
|
|
152
|
+
connectors?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Prints each step's signed change above or below its bar.
|
|
155
|
+
*
|
|
156
|
+
* Worth more here than on most charts: an intermediate bar has no baseline
|
|
157
|
+
* under it, so its length is the one thing a reader cannot get off the axis.
|
|
158
|
+
*/
|
|
159
|
+
showValues?: boolean;
|
|
160
|
+
/** Escape hatch onto the underlying Recharts bar. */
|
|
161
|
+
barProps?: ComponentProps<typeof Bar>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export { type WaterfallBarsProps, WaterfallChart, type WaterfallChartProps, type WaterfallDirection, type WaterfallStep, type WaterfallStepType, WaterfallChart as default };
|