@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,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Legend as RechartsLegend } from "recharts";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { colorStops, cssName, seriesFromPayload, useChart } from "./chart.js";
|
|
6
|
+
const ALIGN = {
|
|
7
|
+
left: "justify-start",
|
|
8
|
+
center: "justify-center",
|
|
9
|
+
right: "justify-end"
|
|
10
|
+
};
|
|
11
|
+
function ChartLegendContent({
|
|
12
|
+
className,
|
|
13
|
+
hideIcon = false,
|
|
14
|
+
nameKey,
|
|
15
|
+
payload,
|
|
16
|
+
verticalAlign,
|
|
17
|
+
align = "right",
|
|
18
|
+
selected,
|
|
19
|
+
onSelectChange,
|
|
20
|
+
isClickable,
|
|
21
|
+
variant = "rounded-square"
|
|
22
|
+
}) {
|
|
23
|
+
const { config } = useChart();
|
|
24
|
+
if (!payload?.length) return null;
|
|
25
|
+
return /* @__PURE__ */ jsx(
|
|
26
|
+
"ul",
|
|
27
|
+
{
|
|
28
|
+
className: cn(
|
|
29
|
+
"m-0 flex list-none items-center gap-4 p-0 select-none",
|
|
30
|
+
ALIGN[align],
|
|
31
|
+
verticalAlign === "top" ? "pb-4" : "pt-4",
|
|
32
|
+
className
|
|
33
|
+
),
|
|
34
|
+
children: payload.filter((item) => item.type !== "none").map((item) => {
|
|
35
|
+
const named = nameKey && item.payload ? item.payload[nameKey] : void 0;
|
|
36
|
+
const key = `${named ?? item.value ?? item.dataKey ?? "value"}`;
|
|
37
|
+
const series = seriesFromPayload(config, item, key);
|
|
38
|
+
const isLit = selected === null || selected === void 0 || selected === key;
|
|
39
|
+
const stops = series ? colorStops(series) : 1;
|
|
40
|
+
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
+
series?.icon && !hideIcon ? /* @__PURE__ */ jsx(series.icon, {}) : /* @__PURE__ */ jsx(LegendSwatch, { variant, seriesKey: key, stops }),
|
|
42
|
+
series?.label ?? key
|
|
43
|
+
] });
|
|
44
|
+
const shared = cn(
|
|
45
|
+
"flex items-center gap-1.5 text-(--ink-2) transition-opacity duration-(--duration-fast) [&>svg]:size-3 [&>svg]:text-(--ink-3-aa)",
|
|
46
|
+
!isLit && "opacity-30"
|
|
47
|
+
);
|
|
48
|
+
return /* @__PURE__ */ jsx("li", { children: isClickable ? /* @__PURE__ */ jsx(
|
|
49
|
+
"button",
|
|
50
|
+
{
|
|
51
|
+
type: "button",
|
|
52
|
+
"aria-pressed": selected === key,
|
|
53
|
+
onClick: () => onSelectChange?.(selected === key ? null : key),
|
|
54
|
+
className: cn(
|
|
55
|
+
shared,
|
|
56
|
+
"cursor-pointer rounded-(--radius-sm) hover:text-(--ink)"
|
|
57
|
+
),
|
|
58
|
+
children: body
|
|
59
|
+
}
|
|
60
|
+
) : /* @__PURE__ */ jsx("span", { className: shared, children: body }) }, key);
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function LegendSwatch({
|
|
66
|
+
variant,
|
|
67
|
+
seriesKey,
|
|
68
|
+
stops
|
|
69
|
+
}) {
|
|
70
|
+
const fill = paintStyle(seriesKey, stops);
|
|
71
|
+
const outline = { ...fill, ...MASK };
|
|
72
|
+
switch (variant) {
|
|
73
|
+
case "square":
|
|
74
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2 shrink-0", style: fill });
|
|
75
|
+
case "circle":
|
|
76
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2 shrink-0 rounded-(--radius-pill)", style: fill });
|
|
77
|
+
case "circle-outline":
|
|
78
|
+
return /* @__PURE__ */ jsx(
|
|
79
|
+
"span",
|
|
80
|
+
{
|
|
81
|
+
"aria-hidden": true,
|
|
82
|
+
className: "size-2.5 shrink-0 rounded-(--radius-pill) p-[1.5px]",
|
|
83
|
+
style: outline
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
case "vertical-bar":
|
|
87
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-3 w-1 shrink-0 rounded-[2px]", style: fill });
|
|
88
|
+
case "horizontal-bar":
|
|
89
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-1 w-3 shrink-0 rounded-[2px]", style: fill });
|
|
90
|
+
case "rounded-square-outline":
|
|
91
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2.5 shrink-0 rounded-[3px] p-[1.5px]", style: outline });
|
|
92
|
+
case "rounded-square":
|
|
93
|
+
default:
|
|
94
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-2 shrink-0 rounded-[2px]", style: fill });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const MASK = {
|
|
98
|
+
WebkitMask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
|
|
99
|
+
WebkitMaskComposite: "xor",
|
|
100
|
+
mask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
|
|
101
|
+
maskComposite: "exclude"
|
|
102
|
+
};
|
|
103
|
+
function paintStyle(seriesKey, stops) {
|
|
104
|
+
const name = cssName(seriesKey);
|
|
105
|
+
if (stops <= 1) return { backgroundColor: `var(--color-${name}-0)` };
|
|
106
|
+
const gradient = Array.from({ length: stops }, (_, index) => {
|
|
107
|
+
const offset = index / (stops - 1) * 100;
|
|
108
|
+
return `var(--color-${name}-${index}) ${offset}%`;
|
|
109
|
+
}).join(", ");
|
|
110
|
+
return { background: `linear-gradient(to right, ${gradient})` };
|
|
111
|
+
}
|
|
112
|
+
const ChartLegend = RechartsLegend;
|
|
113
|
+
export {
|
|
114
|
+
ChartLegend,
|
|
115
|
+
ChartLegendContent
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=legend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/legend.tsx"],"sourcesContent":["'use client'\n\nimport type { CSSProperties } from 'react'\nimport { Legend as RechartsLegend } from 'recharts'\nimport type { DefaultLegendContentProps } from 'recharts'\nimport { cn } from '../../lib/cn'\nimport { colorStops, cssName, seriesFromPayload, useChart } from './chart'\n\n/**\n * The shape of a legend's series mark.\n *\n * Seven, because the mark is doing more work here than in a chromatic system:\n * with the monochrome ramp, a bar-shaped swatch beside a bar chart and a\n * dot-shaped one beside a scatter is often the fastest way a reader ties the\n * key to the plot.\n */\nexport type ChartLegendVariant =\n | 'square'\n | 'circle'\n | 'circle-outline'\n | 'rounded-square'\n | 'rounded-square-outline'\n | 'vertical-bar'\n | 'horizontal-bar'\n\n/** Where the legend sits along the inline axis. Recharts' own vocabulary. */\nexport type ChartLegendAlign = 'left' | 'center' | 'right'\n\nconst ALIGN: Record<ChartLegendAlign, string> = {\n left: 'justify-start',\n center: 'justify-center',\n right: 'justify-end',\n}\n\nexport interface ChartLegendContentProps extends DefaultLegendContentProps {\n className?: string\n /** Suppresses a config `icon`, falling back to the shape swatch. */\n hideIcon?: boolean\n /** The row field holding a series name, when it is not the `dataKey`. */\n nameKey?: string\n /** The chart's selected series, or null when the whole plot is lit. */\n selected?: string | null\n /** Makes each entry a control that toggles its series. */\n isClickable?: boolean\n onSelectChange?: (selected: string | null) => void\n variant?: ChartLegendVariant\n}\n\n/**\n * The key to a plot's series.\n *\n * Required above one series and not decorative: the monochrome ramp separates\n * two series by a step of grey and a texture, and neither is self-describing.\n * The chroma palette does not change that — three of its light steps sit below\n * 3:1 on paper, and the legend is the documented relief.\n *\n * When `isClickable` is set each entry is a real `<button>` with `aria-pressed`\n * rather than a `<div>` with a click handler. That is the difference between a\n * filter a keyboard can reach and one it cannot, and it is why the entry is not\n * simply styled to look pressable.\n */\nexport function ChartLegendContent({\n className,\n hideIcon = false,\n nameKey,\n payload,\n verticalAlign,\n align = 'right',\n selected,\n onSelectChange,\n isClickable,\n variant = 'rounded-square',\n}: ChartLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) return null\n\n return (\n <ul\n className={cn(\n 'm-0 flex list-none items-center gap-4 p-0 select-none',\n ALIGN[align],\n verticalAlign === 'top' ? 'pb-4' : 'pt-4',\n className,\n )}\n >\n {payload\n .filter((item) => item.type !== 'none')\n .map((item) => {\n const named =\n nameKey && item.payload ? (item.payload as Record<string, unknown>)[nameKey] : undefined\n const key = `${named ?? item.value ?? item.dataKey ?? 'value'}`\n const series = seriesFromPayload(config, item, key)\n const isLit = selected === null || selected === undefined || selected === key\n const stops = series ? colorStops(series) : 1\n\n const body = (\n <>\n {series?.icon && !hideIcon ? (\n <series.icon />\n ) : (\n <LegendSwatch variant={variant} seriesKey={key} stops={stops} />\n )}\n {series?.label ?? key}\n </>\n )\n\n const shared = cn(\n 'flex items-center gap-1.5 text-(--ink-2) transition-opacity duration-(--duration-fast) [&>svg]:size-3 [&>svg]:text-(--ink-3-aa)',\n !isLit && 'opacity-30',\n )\n\n return (\n <li key={key}>\n {isClickable ? (\n <button\n type=\"button\"\n aria-pressed={selected === key}\n onClick={() => onSelectChange?.(selected === key ? null : key)}\n className={cn(\n shared,\n 'cursor-pointer rounded-(--radius-sm) hover:text-(--ink)',\n )}\n >\n {body}\n </button>\n ) : (\n <span className={shared}>{body}</span>\n )}\n </li>\n )\n })}\n </ul>\n )\n}\n\n/**\n * The swatch itself. Each variant is its own branch rather than a size lookup,\n * because the outline forms are built differently from the filled ones and a\n * shared branch would have to carry both.\n */\nfunction LegendSwatch({\n variant,\n seriesKey,\n stops,\n}: {\n variant: ChartLegendVariant\n seriesKey: string\n stops: number\n}) {\n const fill = paintStyle(seriesKey, stops)\n const outline = { ...fill, ...MASK }\n\n switch (variant) {\n case 'square':\n return <span aria-hidden className=\"size-2 shrink-0\" style={fill} />\n case 'circle':\n return <span aria-hidden className=\"size-2 shrink-0 rounded-(--radius-pill)\" style={fill} />\n case 'circle-outline':\n return (\n <span\n aria-hidden\n className=\"size-2.5 shrink-0 rounded-(--radius-pill) p-[1.5px]\"\n style={outline}\n />\n )\n case 'vertical-bar':\n return <span aria-hidden className=\"h-3 w-1 shrink-0 rounded-[2px]\" style={fill} />\n case 'horizontal-bar':\n return <span aria-hidden className=\"h-1 w-3 shrink-0 rounded-[2px]\" style={fill} />\n case 'rounded-square-outline':\n return <span aria-hidden className=\"size-2.5 shrink-0 rounded-[3px] p-[1.5px]\" style={outline} />\n case 'rounded-square':\n default:\n return <span aria-hidden className=\"size-2 shrink-0 rounded-[2px]\" style={fill} />\n }\n}\n\n/**\n * Punches the middle out of a filled swatch, leaving its border.\n *\n * `border-color` cannot take a gradient, and a swatch whose series is painted\n * with several stops has to show them. Two masks composited with `exclude`\n * leave only the padding box — which follows the border radius, which a border\n * approximated with an inset box-shadow would not.\n */\nconst MASK: CSSProperties = {\n WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n WebkitMaskComposite: 'xor',\n mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n maskComposite: 'exclude',\n}\n\n/** A swatch's paint: the series colour, or its gradient across the swatch. */\nfunction paintStyle(seriesKey: string, stops: number): CSSProperties {\n const name = cssName(seriesKey)\n if (stops <= 1) return { backgroundColor: `var(--color-${name}-0)` }\n\n const gradient = Array.from({ length: stops }, (_, index) => {\n const offset = (index / (stops - 1)) * 100\n return `var(--color-${name}-${index}) ${offset}%`\n }).join(', ')\n\n return { background: `linear-gradient(to right, ${gradient})` }\n}\n\nexport const ChartLegend = RechartsLegend\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
/** The key the skeleton series is drawn from. Never a real series name. */
|
|
4
|
+
declare const LOADING_KEY = "loading";
|
|
5
|
+
/** Rows for the skeleton plot: one field, values inside a plausible band. */
|
|
6
|
+
declare function loadingRows(points?: number, salt?: number, min?: number, max?: number): {
|
|
7
|
+
loading: number;
|
|
8
|
+
}[];
|
|
9
|
+
/**
|
|
10
|
+
* The skeleton's rows, re-rolled each time the shimmer leaves the plot.
|
|
11
|
+
*
|
|
12
|
+
* The swap is driven by the shimmer's own position rather than by a timer: an
|
|
13
|
+
* interval drifts against the animation and eventually re-rolls the data in
|
|
14
|
+
* full view, which reads as the chart glitching rather than as it loading.
|
|
15
|
+
*/
|
|
16
|
+
declare function useLoadingRows(isLoading: boolean, points?: number): {
|
|
17
|
+
rows: {
|
|
18
|
+
loading: number;
|
|
19
|
+
}[];
|
|
20
|
+
onShimmerExit: () => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The badge over a loading plot.
|
|
24
|
+
*
|
|
25
|
+
* Sits above the skeleton rather than replacing it, so the chart keeps its
|
|
26
|
+
* measured height and the page does not jump when the data lands.
|
|
27
|
+
*/
|
|
28
|
+
declare function LoadingIndicator({ isLoading }: {
|
|
29
|
+
isLoading: boolean;
|
|
30
|
+
}): react.JSX.Element | null;
|
|
31
|
+
/**
|
|
32
|
+
* The travelling mask that makes the skeleton read as "working" rather than as
|
|
33
|
+
* "broken".
|
|
34
|
+
*
|
|
35
|
+
* The plot is normalised to 0–1 and the pattern is three times that wide, so
|
|
36
|
+
* the highlight has a full plot-width of runway on each side. `onShimmerExit`
|
|
37
|
+
* fires as it crosses the far edge — off-screen — which is where the rows are
|
|
38
|
+
* re-rolled, so the loop has no visible seam.
|
|
39
|
+
*
|
|
40
|
+
* With `prefers-reduced-motion` the whole travelling layer is dropped for a
|
|
41
|
+
* flat wash: the skeleton still says "not yet", without anything moving.
|
|
42
|
+
*/
|
|
43
|
+
declare function LoadingShimmer({ id, onShimmerExit }: {
|
|
44
|
+
id: string;
|
|
45
|
+
onShimmerExit: () => void;
|
|
46
|
+
}): react.JSX.Element;
|
|
47
|
+
|
|
48
|
+
export { LOADING_KEY, LoadingIndicator, LoadingShimmer, loadingRows, useLoadingRows };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { motion, useReducedMotion } from "motion/react";
|
|
5
|
+
const LOADING_KEY = "loading";
|
|
6
|
+
const SHIMMER_SECONDS = 2;
|
|
7
|
+
function noise(index, salt) {
|
|
8
|
+
const x = Math.sin(index * 127.1 + salt * 311.7) * 43758.5453;
|
|
9
|
+
return x - Math.floor(x);
|
|
10
|
+
}
|
|
11
|
+
function loadingRows(points = 14, salt = 0, min = 0, max = 70) {
|
|
12
|
+
return Array.from({ length: points }, (_, index) => ({
|
|
13
|
+
[LOADING_KEY]: Math.floor(noise(index, salt) * (max - min)) + min
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
function useLoadingRows(isLoading, points = 14) {
|
|
17
|
+
const [salt, setSalt] = useState(0);
|
|
18
|
+
const onShimmerExit = useCallback(() => {
|
|
19
|
+
if (isLoading) setSalt((previous) => previous + 1);
|
|
20
|
+
}, [isLoading]);
|
|
21
|
+
const rows = useMemo(() => loadingRows(points, salt), [points, salt]);
|
|
22
|
+
return { rows, onShimmerExit };
|
|
23
|
+
}
|
|
24
|
+
function LoadingIndicator({ isLoading }) {
|
|
25
|
+
if (!isLoading) return null;
|
|
26
|
+
return /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-(--z-rule) flex items-center justify-center", children: /* @__PURE__ */ jsxs(
|
|
27
|
+
"output",
|
|
28
|
+
{
|
|
29
|
+
className: "flex items-center gap-2 rounded-(--radius) border border-(--rule) bg-(--chart-surface) px-2.5 py-1 mono-meta text-(--ink-2)",
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
"span",
|
|
33
|
+
{
|
|
34
|
+
"aria-hidden": true,
|
|
35
|
+
"data-m22-animated": true,
|
|
36
|
+
className: "size-3 rounded-(--radius-pill) border border-(--rule-2) border-t-(--ink) motion-safe:animate-[m22-spin_0.8s_linear_infinite]"
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
"Loading"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
) });
|
|
43
|
+
}
|
|
44
|
+
function shimmerStops(steps = 17, min = 0.05, max = 0.9) {
|
|
45
|
+
return Array.from({ length: steps }, (_, index) => {
|
|
46
|
+
const t = index / (steps - 1);
|
|
47
|
+
const eased = Math.sin(t * Math.PI) ** 2;
|
|
48
|
+
return {
|
|
49
|
+
offset: `${Math.round(t * 100)}%`,
|
|
50
|
+
opacity: Number((min + eased * (max - min)).toFixed(3))
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function LoadingShimmer({ id, onShimmerExit }) {
|
|
55
|
+
const reduceMotion = useReducedMotion();
|
|
56
|
+
const stops = shimmerStops();
|
|
57
|
+
const lastX = useRef(-1);
|
|
58
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
59
|
+
/* @__PURE__ */ jsx("linearGradient", { id: `${id}-loading-gradient`, x1: "0", y1: "0", x2: "1", y2: "0", children: stops.map(({ offset, opacity }) => /* @__PURE__ */ jsx("stop", { offset, stopColor: "white", stopOpacity: opacity }, offset)) }),
|
|
60
|
+
/* @__PURE__ */ jsx("mask", { id: `${id}-loading-mask`, maskUnits: "userSpaceOnUse", children: reduceMotion ? /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: "white", fillOpacity: 0.55 }) : /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id}-loading-pattern)` }) }),
|
|
61
|
+
!reduceMotion && /* @__PURE__ */ jsx(
|
|
62
|
+
"pattern",
|
|
63
|
+
{
|
|
64
|
+
id: `${id}-loading-pattern`,
|
|
65
|
+
patternUnits: "objectBoundingBox",
|
|
66
|
+
patternContentUnits: "objectBoundingBox",
|
|
67
|
+
patternTransform: "rotate(25)",
|
|
68
|
+
width: 3,
|
|
69
|
+
height: "1",
|
|
70
|
+
x: "0",
|
|
71
|
+
y: "0",
|
|
72
|
+
children: /* @__PURE__ */ jsx(
|
|
73
|
+
motion.rect,
|
|
74
|
+
{
|
|
75
|
+
y: "0",
|
|
76
|
+
width: "1",
|
|
77
|
+
height: "1",
|
|
78
|
+
fill: `url(#${id}-loading-gradient)`,
|
|
79
|
+
initial: { x: -1 },
|
|
80
|
+
animate: { x: 2 },
|
|
81
|
+
transition: {
|
|
82
|
+
duration: SHIMMER_SECONDS,
|
|
83
|
+
ease: "linear",
|
|
84
|
+
repeat: Infinity,
|
|
85
|
+
repeatType: "loop"
|
|
86
|
+
},
|
|
87
|
+
onUpdate: (latest) => {
|
|
88
|
+
const x = typeof latest.x === "number" ? latest.x : -1;
|
|
89
|
+
if (x >= 1 && lastX.current < 1) onShimmerExit();
|
|
90
|
+
lastX.current = x;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
] });
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
LOADING_KEY,
|
|
100
|
+
LoadingIndicator,
|
|
101
|
+
LoadingShimmer,
|
|
102
|
+
loadingRows,
|
|
103
|
+
useLoadingRows
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=loading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/charts/lib/loading.tsx"],"sourcesContent":["'use client'\n\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport { motion, useReducedMotion } from 'motion/react'\n\n/** The key the skeleton series is drawn from. Never a real series name. */\nexport const LOADING_KEY = 'loading'\n\n/** One shimmer pass, in seconds. */\nconst SHIMMER_SECONDS = 2\n\n/**\n * A deterministic pseudo-random sequence, seeded by index.\n *\n * The shape this was ported from called `Math.random()` inside a `useMemo`,\n * which runs during render — so the server rendered one skeleton, the client\n * rendered a different one, and React logged a hydration mismatch for every\n * chart on the page. A hash of the index gives the same jagged, un-patterned\n * silhouette on both sides of the wire, which is the only property the\n * skeleton actually needs from randomness.\n */\nfunction noise(index: number, salt: number): number {\n const x = Math.sin(index * 127.1 + salt * 311.7) * 43758.5453\n return x - Math.floor(x)\n}\n\n/** Rows for the skeleton plot: one field, values inside a plausible band. */\nexport function loadingRows(points = 14, salt = 0, min = 0, max = 70) {\n return Array.from({ length: points }, (_, index) => ({\n [LOADING_KEY]: Math.floor(noise(index, salt) * (max - min)) + min,\n }))\n}\n\n/**\n * The skeleton's rows, re-rolled each time the shimmer leaves the plot.\n *\n * The swap is driven by the shimmer's own position rather than by a timer: an\n * interval drifts against the animation and eventually re-rolls the data in\n * full view, which reads as the chart glitching rather than as it loading.\n */\nexport function useLoadingRows(isLoading: boolean, points = 14) {\n const [salt, setSalt] = useState(0)\n\n const onShimmerExit = useCallback(() => {\n if (isLoading) setSalt((previous) => previous + 1)\n }, [isLoading])\n\n const rows = useMemo(() => loadingRows(points, salt), [points, salt])\n\n return { rows, onShimmerExit }\n}\n\n/**\n * The badge over a loading plot.\n *\n * Sits above the skeleton rather than replacing it, so the chart keeps its\n * measured height and the page does not jump when the data lands.\n */\nexport function LoadingIndicator({ isLoading }: { isLoading: boolean }) {\n if (!isLoading) return null\n\n return (\n <div className=\"pointer-events-none absolute inset-0 z-(--z-rule) flex items-center justify-center\">\n <output\n className=\"flex items-center gap-2 rounded-(--radius) border border-(--rule) bg-(--chart-surface) px-2.5 py-1 mono-meta text-(--ink-2)\"\n >\n <span\n aria-hidden\n data-m22-animated\n className=\"size-3 rounded-(--radius-pill) border border-(--rule-2) border-t-(--ink) motion-safe:animate-[m22-spin_0.8s_linear_infinite]\"\n />\n Loading\n </output>\n </div>\n )\n}\n\n/** Bell-curve opacity stops, so the shimmer has no hard edge at either end. */\nfunction shimmerStops(steps = 17, min = 0.05, max = 0.9) {\n return Array.from({ length: steps }, (_, index) => {\n const t = index / (steps - 1)\n const eased = Math.sin(t * Math.PI) ** 2\n return {\n offset: `${Math.round(t * 100)}%`,\n opacity: Number((min + eased * (max - min)).toFixed(3)),\n }\n })\n}\n\n/**\n * The travelling mask that makes the skeleton read as \"working\" rather than as\n * \"broken\".\n *\n * The plot is normalised to 0–1 and the pattern is three times that wide, so\n * the highlight has a full plot-width of runway on each side. `onShimmerExit`\n * fires as it crosses the far edge — off-screen — which is where the rows are\n * re-rolled, so the loop has no visible seam.\n *\n * With `prefers-reduced-motion` the whole travelling layer is dropped for a\n * flat wash: the skeleton still says \"not yet\", without anything moving.\n */\nexport function LoadingShimmer({ id, onShimmerExit }: { id: string; onShimmerExit: () => void }) {\n const reduceMotion = useReducedMotion()\n const stops = shimmerStops()\n const lastX = useRef(-1)\n\n return (\n <>\n <linearGradient id={`${id}-loading-gradient`} x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">\n {stops.map(({ offset, opacity }) => (\n <stop key={offset} offset={offset} stopColor=\"white\" stopOpacity={opacity} />\n ))}\n </linearGradient>\n <mask id={`${id}-loading-mask`} maskUnits=\"userSpaceOnUse\">\n {reduceMotion ? (\n <rect width=\"100%\" height=\"100%\" fill=\"white\" fillOpacity={0.55} />\n ) : (\n <rect width=\"100%\" height=\"100%\" fill={`url(#${id}-loading-pattern)`} />\n )}\n </mask>\n {!reduceMotion && (\n <pattern\n id={`${id}-loading-pattern`}\n patternUnits=\"objectBoundingBox\"\n patternContentUnits=\"objectBoundingBox\"\n patternTransform=\"rotate(25)\"\n width={3}\n height=\"1\"\n x=\"0\"\n y=\"0\"\n >\n <motion.rect\n y=\"0\"\n width=\"1\"\n height=\"1\"\n fill={`url(#${id}-loading-gradient)`}\n initial={{ x: -1 }}\n animate={{ x: 2 }}\n transition={{\n duration: SHIMMER_SECONDS,\n ease: 'linear',\n repeat: Infinity,\n repeatType: 'loop',\n }}\n onUpdate={(latest) => {\n const x = typeof latest.x === 'number' ? latest.x : -1\n if (x >= 1 && lastX.current < 1) onShimmerExit()\n lastX.current = x\n }}\n />\n </pattern>\n )}\n </>\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ChartConfig } from './chart.js';
|
|
3
|
+
import 'recharts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The intro wipe's direction, shared by every mark that has one.
|
|
7
|
+
*
|
|
8
|
+
* Named for the DATA rather than for the screen. `forward` runs from the first
|
|
9
|
+
* row to the last, `reverse` the other way — which is the thing the author
|
|
10
|
+
* actually means, and stays true in a right-to-left document, where a cartesian
|
|
11
|
+
* plot is still drawn first-row-first.
|
|
12
|
+
*
|
|
13
|
+
* `"none"` opts out, and is also what a device with the OS reduce-motion
|
|
14
|
+
* preference falls back to: a reveal is a per-frame animated SVG mask, the
|
|
15
|
+
* heaviest thing in the package and the least welcome to a reader who has
|
|
16
|
+
* asked for stillness.
|
|
17
|
+
*/
|
|
18
|
+
type ChartRevealType = 'none' | 'forward' | 'reverse' | 'center-out' | 'edges-in';
|
|
19
|
+
/** A reveal that actually plays. */
|
|
20
|
+
type ChartRevealDirection = Exclude<ChartRevealType, 'none'>;
|
|
21
|
+
/** The intro wipe, in seconds. */
|
|
22
|
+
declare const REVEAL_DURATION = 1;
|
|
23
|
+
/**
|
|
24
|
+
* The wipe's curve. Not `--ease`: the system's easing is tuned for a control
|
|
25
|
+
* moving a few pixels, and over a full plot width it arrives too abruptly.
|
|
26
|
+
* A long, flat tail is what makes a line read as being drawn.
|
|
27
|
+
*/
|
|
28
|
+
declare const REVEAL_EASE: [number, number, number, number];
|
|
29
|
+
/**
|
|
30
|
+
* The mask that draws a line or an area in.
|
|
31
|
+
*
|
|
32
|
+
* One mask covers the mark's fill, its stroke AND its resting dots, so the
|
|
33
|
+
* three arrive together. Drawn separately — which is what Recharts' own
|
|
34
|
+
* animation does — the dots pop in before the line reaches them.
|
|
35
|
+
*
|
|
36
|
+
* Both `maskUnits` and `maskContentUnits` are user space so every masked
|
|
37
|
+
* element shares one coordinate system and the wipe edge lands at the same x
|
|
38
|
+
* on each of them.
|
|
39
|
+
*/
|
|
40
|
+
declare function RevealMask({ id, type }: {
|
|
41
|
+
id: string;
|
|
42
|
+
type: ChartRevealDirection;
|
|
43
|
+
}): react.JSX.Element;
|
|
44
|
+
interface PaintProps {
|
|
45
|
+
/** The owning mark's id, which scopes every definition below. */
|
|
46
|
+
id: string;
|
|
47
|
+
/** The series being painted. */
|
|
48
|
+
dataKey: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The one gradient everything else is masked out of.
|
|
52
|
+
*
|
|
53
|
+
* Every fill variant, every stroke and every dot in a chart paints from this,
|
|
54
|
+
* which is what makes a series a single visual object rather than a set of
|
|
55
|
+
* elements that happen to share a colour. A series with one colour still gets a
|
|
56
|
+
* two-stop gradient: it keeps the paint reference identical across variants, so
|
|
57
|
+
* switching a series from one colour to three changes no other code.
|
|
58
|
+
*/
|
|
59
|
+
declare function SeriesGradient({ id, dataKey, config, direction, gradientUnits, }: PaintProps & {
|
|
60
|
+
config: ChartConfig;
|
|
61
|
+
/** Horizontal reads along the axis; vertical reads up the mark. */
|
|
62
|
+
direction?: 'horizontal' | 'vertical';
|
|
63
|
+
gradientUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
|
|
64
|
+
}): react.JSX.Element;
|
|
65
|
+
/**
|
|
66
|
+
* The stops themselves, so a variant can build its own gradient from them.
|
|
67
|
+
*
|
|
68
|
+
* `opacities` ramps the stops independently of their colour — a radar's fill
|
|
69
|
+
* fades from its centre outward without needing a second gradient to mask it.
|
|
70
|
+
*/
|
|
71
|
+
declare function ColorStops({ dataKey, stops, opacities, }: {
|
|
72
|
+
dataKey: string;
|
|
73
|
+
stops: number;
|
|
74
|
+
opacities?: number[];
|
|
75
|
+
}): react.JSX.Element;
|
|
76
|
+
/** Solid at the top, dissolving toward the axis. The default. */
|
|
77
|
+
declare function AreaGradientFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
78
|
+
/** The same fade, run the other way — heavier where it meets the axis. */
|
|
79
|
+
declare function AreaGradientReverseFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
80
|
+
/** One flat wash, no fade. Reads as a band rather than as a slope. */
|
|
81
|
+
declare function AreaSolidFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
82
|
+
/** A field of dots. The lightest texture, and the one that stacks best. */
|
|
83
|
+
declare function AreaDottedFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
84
|
+
/** Diagonal rule lines, 45°. */
|
|
85
|
+
declare function AreaLinesFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
86
|
+
/** Wide soft-edged stripes at 20°. The heaviest of the six. */
|
|
87
|
+
declare function AreaHatchedFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
88
|
+
/**
|
|
89
|
+
* What a series looks like when another one is selected.
|
|
90
|
+
*
|
|
91
|
+
* A thin diagonal rule rather than a lower opacity: opacity alone makes a
|
|
92
|
+
* series faint, and a faint area on a white ground is still an area. The
|
|
93
|
+
* texture change is what makes it read as "not this one".
|
|
94
|
+
*/
|
|
95
|
+
declare function UnselectedFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
96
|
+
/** 45° stripes over a faint ground. */
|
|
97
|
+
declare function BarHatchedFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
98
|
+
/**
|
|
99
|
+
* Stripes with nothing behind them — the projected, not-yet-real part of a
|
|
100
|
+
* series. Used by the last bar when `buffer` is set.
|
|
101
|
+
*/
|
|
102
|
+
declare function BarBufferFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
103
|
+
/**
|
|
104
|
+
* A bar split down its own middle, one half at full weight.
|
|
105
|
+
*
|
|
106
|
+
* Everything here is in object-bounding-box units so the split lands at each
|
|
107
|
+
* bar's centre rather than at the plot's — in user space a narrow bar at the
|
|
108
|
+
* right of the chart would be entirely on one side of the seam.
|
|
109
|
+
*/
|
|
110
|
+
declare function BarDuotoneFill({ id, dataKey, config, reverse, }: PaintProps & {
|
|
111
|
+
config: ChartConfig;
|
|
112
|
+
reverse?: boolean;
|
|
113
|
+
}): react.JSX.Element;
|
|
114
|
+
/** Solid at the top of the bar, dissolving toward the baseline. */
|
|
115
|
+
declare function BarGradientFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
116
|
+
/**
|
|
117
|
+
* A faint body under a solid cap, drawn by the bar shape itself.
|
|
118
|
+
*
|
|
119
|
+
* The variant that survives density best: at twenty bars a solid block becomes
|
|
120
|
+
* a wall, and a 2px cap over a wash still reads as twenty distinct values.
|
|
121
|
+
*/
|
|
122
|
+
declare function BarStrippedFill({ id, dataKey }: PaintProps): react.JSX.Element;
|
|
123
|
+
/**
|
|
124
|
+
* The halo behind a highlighted mark.
|
|
125
|
+
*
|
|
126
|
+
* The one blur in the package, and it is a filter on a MARK rather than a
|
|
127
|
+
* box-shadow under a panel — law 2 bans the second, not the first. It exists
|
|
128
|
+
* because a monochrome chart has no "brighter" to reach for when one series has
|
|
129
|
+
* to be the point of the figure.
|
|
130
|
+
*
|
|
131
|
+
* A line needs a wider, stronger halo than a bar: a 0.8px stroke has almost no
|
|
132
|
+
* area to bleed from, where a bar has its whole face.
|
|
133
|
+
*/
|
|
134
|
+
declare function GlowFilter({ id, dataKey, spread, intensity, }: PaintProps & {
|
|
135
|
+
/** Blur radius, in user units. */
|
|
136
|
+
spread?: number;
|
|
137
|
+
/** Alpha multiplier on the blurred copy. Above 1 saturates it. */
|
|
138
|
+
intensity?: number;
|
|
139
|
+
}): react.JSX.Element;
|
|
140
|
+
/**
|
|
141
|
+
* A dashed stroke that crawls along its own path.
|
|
142
|
+
*
|
|
143
|
+
* SMIL rather than CSS, because the two attributes have to stay in lockstep and
|
|
144
|
+
* a CSS animation on `stroke-dasharray` is not interpolated the same way in
|
|
145
|
+
* every engine. It is composed as a CHILD of the mark, so a caller that does
|
|
146
|
+
* not ask for it pays nothing — and `keyframes.css`'s reduced-motion rule
|
|
147
|
+
* cannot reach SMIL, which is why the call sites gate it on `useReducedMotion`
|
|
148
|
+
* instead.
|
|
149
|
+
*/
|
|
150
|
+
declare function AnimatedDashedStroke({ dash }: {
|
|
151
|
+
dash?: number;
|
|
152
|
+
}): react.JSX.Element;
|
|
153
|
+
|
|
154
|
+
export { AnimatedDashedStroke, AreaDottedFill, AreaGradientFill, AreaGradientReverseFill, AreaHatchedFill, AreaLinesFill, AreaSolidFill, BarBufferFill, BarDuotoneFill, BarGradientFill, BarHatchedFill, BarStrippedFill, type ChartRevealDirection, type ChartRevealType, ColorStops, GlowFilter, type PaintProps, REVEAL_DURATION, REVEAL_EASE, RevealMask, SeriesGradient, UnselectedFill };
|