@chakra-ui/charts 3.15.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/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/cjs/bar-list/bar-list.cjs +162 -0
- package/dist/cjs/bar-list/index.cjs +16 -0
- package/dist/cjs/bar-list/namespace.cjs +14 -0
- package/dist/cjs/bar-segment/bar-segment.cjs +215 -0
- package/dist/cjs/bar-segment/index.cjs +16 -0
- package/dist/cjs/bar-segment/namespace.cjs +14 -0
- package/dist/cjs/chart/chart.cjs +275 -0
- package/dist/cjs/chart/index.cjs +14 -0
- package/dist/cjs/chart/namespace.cjs +12 -0
- package/dist/cjs/index.cjs +36 -0
- package/dist/cjs/use-chart.cjs +130 -0
- package/dist/esm/bar-list/bar-list.js +135 -0
- package/dist/esm/bar-list/index.js +4 -0
- package/dist/esm/bar-list/namespace.js +2 -0
- package/dist/esm/bar-segment/bar-segment.js +187 -0
- package/dist/esm/bar-segment/index.js +4 -0
- package/dist/esm/bar-segment/namespace.js +2 -0
- package/dist/esm/chart/chart.js +251 -0
- package/dist/esm/chart/index.js +4 -0
- package/dist/esm/chart/namespace.js +2 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/use-chart.js +108 -0
- package/dist/types/bar-list/bar-list.d.ts +40 -0
- package/dist/types/bar-list/index.d.ts +3 -0
- package/dist/types/bar-list/namespace.d.ts +2 -0
- package/dist/types/bar-segment/bar-segment.d.ts +42 -0
- package/dist/types/bar-segment/index.d.ts +3 -0
- package/dist/types/bar-segment/namespace.d.ts +2 -0
- package/dist/types/chart/chart.d.ts +44 -0
- package/dist/types/chart/index.d.ts +3 -0
- package/dist/types/chart/namespace.d.ts +2 -0
- package/dist/types/index.d.mts +5 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/use-chart.d.ts +54 -0
- package/package.json +64 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import { Stack, HStack, Box, Flex, Span, FormatNumber, ColorSwatch, Text } from '@chakra-ui/react';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
const ChartContext = React.createContext({});
|
|
8
|
+
function BarSegmentRoot(props) {
|
|
9
|
+
const { chart, barSize = "10", children, ...rest } = props;
|
|
10
|
+
return /* @__PURE__ */ jsx(Stack, { gap: "4", ...rest, css: { "--bar-size": chart.size(barSize) }, children: /* @__PURE__ */ jsx(ChartContext.Provider, { value: chart, children }) });
|
|
11
|
+
}
|
|
12
|
+
const BarSegmentContent = React.forwardRef(
|
|
13
|
+
function BarSegmentContent2(props, ref) {
|
|
14
|
+
const chart = React.useContext(ChartContext);
|
|
15
|
+
return /* @__PURE__ */ jsx(
|
|
16
|
+
Stack,
|
|
17
|
+
{
|
|
18
|
+
w: "full",
|
|
19
|
+
gap: "1",
|
|
20
|
+
ref,
|
|
21
|
+
onMouseLeave: () => chart.setHighlightedSeries(null),
|
|
22
|
+
...props
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
function BarSegmentLabel(props) {
|
|
28
|
+
const chart = React.useContext(ChartContext);
|
|
29
|
+
const getPercent = (value) => chart.getValuePercent("value", value);
|
|
30
|
+
return /* @__PURE__ */ jsx(HStack, { ...props, children: chart.data.map((item) => /* @__PURE__ */ jsx(
|
|
31
|
+
HStack,
|
|
32
|
+
{
|
|
33
|
+
flexShrink: "0",
|
|
34
|
+
textStyle: "sm",
|
|
35
|
+
fontWeight: "medium",
|
|
36
|
+
lineClamp: 1,
|
|
37
|
+
style: {
|
|
38
|
+
["--bar-percent"]: `${getPercent(item.value)}%`
|
|
39
|
+
},
|
|
40
|
+
flex: "var(--bar-percent)",
|
|
41
|
+
children: item.name
|
|
42
|
+
},
|
|
43
|
+
item.name
|
|
44
|
+
)) });
|
|
45
|
+
}
|
|
46
|
+
function BarSegmentBar(props) {
|
|
47
|
+
const { showTooltip, children, ...rest } = props;
|
|
48
|
+
const chart = React.useContext(ChartContext);
|
|
49
|
+
const getPercent = (value) => chart.getValuePercent("value", value);
|
|
50
|
+
return /* @__PURE__ */ jsxs(HStack, { pos: "relative", gap: "1", ...rest, children: [
|
|
51
|
+
chart.data.map((item) => /* @__PURE__ */ jsx(
|
|
52
|
+
Box,
|
|
53
|
+
{
|
|
54
|
+
pos: "relative",
|
|
55
|
+
flexShrink: "0",
|
|
56
|
+
flex: "var(--bar-percent)",
|
|
57
|
+
height: "var(--bar-size)",
|
|
58
|
+
bg: item.color,
|
|
59
|
+
rounded: "l1",
|
|
60
|
+
onMouseMove: () => {
|
|
61
|
+
if (!showTooltip) return;
|
|
62
|
+
chart.setHighlightedSeries(item.name);
|
|
63
|
+
},
|
|
64
|
+
style: {
|
|
65
|
+
["--bar-percent"]: `${getPercent(item.value)}%`
|
|
66
|
+
},
|
|
67
|
+
children: showTooltip && /* @__PURE__ */ jsx(BarSegmentTooltip, { payload: item })
|
|
68
|
+
},
|
|
69
|
+
item.name
|
|
70
|
+
)),
|
|
71
|
+
children
|
|
72
|
+
] });
|
|
73
|
+
}
|
|
74
|
+
function BarSegmentReference(props) {
|
|
75
|
+
const { value, label } = props;
|
|
76
|
+
const chart = React.useContext(ChartContext);
|
|
77
|
+
const getPercent = (value2) => chart.getValuePercent("value", value2);
|
|
78
|
+
return /* @__PURE__ */ jsx(
|
|
79
|
+
Box,
|
|
80
|
+
{
|
|
81
|
+
h: label ? "150%" : "100%",
|
|
82
|
+
pos: "absolute",
|
|
83
|
+
insetStart: `var(--bar-percent)`,
|
|
84
|
+
bottom: "0",
|
|
85
|
+
style: { ["--bar-percent"]: `${getPercent(value)}%` },
|
|
86
|
+
children: /* @__PURE__ */ jsxs(Flex, { gap: "2", h: "full", children: [
|
|
87
|
+
/* @__PURE__ */ jsx(
|
|
88
|
+
Span,
|
|
89
|
+
{
|
|
90
|
+
w: "2px",
|
|
91
|
+
h: "100%",
|
|
92
|
+
bg: "bg.inverted",
|
|
93
|
+
outline: "2px solid {colors.bg}"
|
|
94
|
+
}
|
|
95
|
+
),
|
|
96
|
+
label && /* @__PURE__ */ jsx(Span, { fontWeight: "medium", textStyle: "xs", pos: "relative", top: "-4px", children: label })
|
|
97
|
+
] })
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
function BarSegmentValue(props) {
|
|
102
|
+
const chart = React.useContext(ChartContext);
|
|
103
|
+
const getPercent = (value) => chart.getValuePercent("value", value);
|
|
104
|
+
return /* @__PURE__ */ jsx(HStack, { ...props, children: chart.data.map((item) => /* @__PURE__ */ jsx(
|
|
105
|
+
HStack,
|
|
106
|
+
{
|
|
107
|
+
textStyle: "sm",
|
|
108
|
+
fontWeight: "medium",
|
|
109
|
+
flexShrink: "0",
|
|
110
|
+
style: {
|
|
111
|
+
["--bar-percent"]: `${getPercent(item.value)}%`
|
|
112
|
+
},
|
|
113
|
+
flex: "var(--bar-percent)",
|
|
114
|
+
children: /* @__PURE__ */ jsx(
|
|
115
|
+
FormatNumber,
|
|
116
|
+
{
|
|
117
|
+
value: item.value,
|
|
118
|
+
notation: "compact",
|
|
119
|
+
maximumFractionDigits: 2
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
},
|
|
123
|
+
item.name
|
|
124
|
+
)) });
|
|
125
|
+
}
|
|
126
|
+
function BarSegmentLegend(props) {
|
|
127
|
+
const { showPercent, showValue, valueFormatter, ...rest } = props;
|
|
128
|
+
const chart = React.useContext(ChartContext);
|
|
129
|
+
const formatter = valueFormatter || chart.formatNumber({ maximumFractionDigits: 2 });
|
|
130
|
+
return /* @__PURE__ */ jsx(HStack, { wrap: "wrap", gap: "4", textStyle: "sm", ...rest, children: chart.data.map((item) => /* @__PURE__ */ jsxs(HStack, { children: [
|
|
131
|
+
/* @__PURE__ */ jsx(
|
|
132
|
+
ColorSwatch,
|
|
133
|
+
{
|
|
134
|
+
value: chart.color(item.color),
|
|
135
|
+
boxSize: "0.82em",
|
|
136
|
+
rounded: "full"
|
|
137
|
+
}
|
|
138
|
+
),
|
|
139
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "1.5", children: [
|
|
140
|
+
/* @__PURE__ */ jsx(Text, { children: item.name }),
|
|
141
|
+
showValue && /* @__PURE__ */ jsx(Span, { fontWeight: "medium", children: formatter(item.value) }),
|
|
142
|
+
showPercent && /* @__PURE__ */ jsxs(Span, { color: "fg.muted", children: [
|
|
143
|
+
chart.getValuePercent("value", item.value).toFixed(0),
|
|
144
|
+
"%"
|
|
145
|
+
] })
|
|
146
|
+
] })
|
|
147
|
+
] }, item.name)) });
|
|
148
|
+
}
|
|
149
|
+
function BarSegmentTooltip(props) {
|
|
150
|
+
const { payload } = props;
|
|
151
|
+
const chart = React.useContext(ChartContext);
|
|
152
|
+
if (!payload || chart.highlightedSeries !== payload.name) return null;
|
|
153
|
+
const item = chart.data.find((d) => d.name === payload.name);
|
|
154
|
+
if (!item) return null;
|
|
155
|
+
const formatter = chart.formatNumber({ maximumFractionDigits: 2 });
|
|
156
|
+
return /* @__PURE__ */ jsxs(
|
|
157
|
+
HStack,
|
|
158
|
+
{
|
|
159
|
+
pos: "absolute",
|
|
160
|
+
top: "-4",
|
|
161
|
+
right: "4",
|
|
162
|
+
bg: "bg.panel",
|
|
163
|
+
textStyle: "xs",
|
|
164
|
+
zIndex: "1",
|
|
165
|
+
px: "2.5",
|
|
166
|
+
py: "1",
|
|
167
|
+
gap: "1.5",
|
|
168
|
+
rounded: "l2",
|
|
169
|
+
shadow: "md",
|
|
170
|
+
...props,
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ jsx(
|
|
173
|
+
ColorSwatch,
|
|
174
|
+
{
|
|
175
|
+
value: chart.color(item.color),
|
|
176
|
+
boxSize: "0.82em",
|
|
177
|
+
rounded: "full"
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
/* @__PURE__ */ jsx(Span, { children: item.name }),
|
|
181
|
+
/* @__PURE__ */ jsx(Span, { fontFamily: "mono", fontWeight: "medium", children: formatter(item.value) })
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { BarSegmentBar, BarSegmentContent, BarSegmentLabel, BarSegmentLegend, BarSegmentReference, BarSegmentRoot, BarSegmentTooltip, BarSegmentValue };
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { defineStyle, Box, Stack, Text, Flex, HStack, ColorSwatch, Span, Separator } from '@chakra-ui/react';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { useMemo } from 'react';
|
|
7
|
+
import { ResponsiveContainer } from 'recharts';
|
|
8
|
+
import { getProp } from '../use-chart.js';
|
|
9
|
+
|
|
10
|
+
const ChartContext = React.createContext({});
|
|
11
|
+
const useChartContext = () => React.useContext(ChartContext);
|
|
12
|
+
const baseCss = defineStyle({
|
|
13
|
+
width: "100%",
|
|
14
|
+
[`& :where(${[
|
|
15
|
+
".recharts-cartesian-axis-tick-value",
|
|
16
|
+
".recharts-polar-angle-axis-tick-value",
|
|
17
|
+
".recharts-polar-radius-axis-tick-value",
|
|
18
|
+
".recharts-pie-label-text"
|
|
19
|
+
].join(", ")})`]: {
|
|
20
|
+
fill: "fg.muted"
|
|
21
|
+
},
|
|
22
|
+
"& .recharts-cartesian-axis .recharts-label": {
|
|
23
|
+
fill: "fg",
|
|
24
|
+
fontWeight: "medium"
|
|
25
|
+
},
|
|
26
|
+
"& *": {
|
|
27
|
+
outline: "none"
|
|
28
|
+
},
|
|
29
|
+
"& svg": {
|
|
30
|
+
overflow: "visible"
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const ChartRoot = React.forwardRef(
|
|
34
|
+
function ChartRoot2(props, ref) {
|
|
35
|
+
const { children, css, chart, ...rest } = props;
|
|
36
|
+
return /* @__PURE__ */ jsx(ChartContext.Provider, { value: chart, children: /* @__PURE__ */ jsx(
|
|
37
|
+
Box,
|
|
38
|
+
{
|
|
39
|
+
ref,
|
|
40
|
+
aspectRatio: "landscape",
|
|
41
|
+
textStyle: "xs",
|
|
42
|
+
css: [baseCss, css],
|
|
43
|
+
...rest,
|
|
44
|
+
children: /* @__PURE__ */ jsx(ResponsiveContainer, { children })
|
|
45
|
+
}
|
|
46
|
+
) });
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
const ChartGradient = React.forwardRef(function ChartGradient2(props, ref) {
|
|
50
|
+
const chart = useChartContext();
|
|
51
|
+
const { id, fillOpacity, stops } = props;
|
|
52
|
+
return /* @__PURE__ */ jsx("linearGradient", { id, x1: "0", y1: "0", x2: "0", y2: "1", ref, children: stops.map((stop, index) => /* @__PURE__ */ jsx(
|
|
53
|
+
"stop",
|
|
54
|
+
{
|
|
55
|
+
offset: stop.offset,
|
|
56
|
+
stopColor: chart.color(stop.color),
|
|
57
|
+
stopOpacity: stop.opacity ?? fillOpacity
|
|
58
|
+
},
|
|
59
|
+
index
|
|
60
|
+
)) });
|
|
61
|
+
});
|
|
62
|
+
const hAlignMap = {
|
|
63
|
+
left: "flex-start",
|
|
64
|
+
center: "center",
|
|
65
|
+
right: "flex-end"
|
|
66
|
+
};
|
|
67
|
+
function ChartLegend(props) {
|
|
68
|
+
const {
|
|
69
|
+
payload,
|
|
70
|
+
verticalAlign = "bottom",
|
|
71
|
+
align = "center",
|
|
72
|
+
title,
|
|
73
|
+
orientation,
|
|
74
|
+
nameKey,
|
|
75
|
+
spacing = "2.5"
|
|
76
|
+
} = props;
|
|
77
|
+
const chart = useChartContext();
|
|
78
|
+
const filteredPayload = payload?.filter(
|
|
79
|
+
(item) => item.color !== "none" || item.type !== "none"
|
|
80
|
+
);
|
|
81
|
+
if (!filteredPayload?.length) return null;
|
|
82
|
+
const spacingValue = typeof spacing === "number" ? `${spacing}px` : chart.spacing(spacing);
|
|
83
|
+
return /* @__PURE__ */ jsxs(
|
|
84
|
+
Stack,
|
|
85
|
+
{
|
|
86
|
+
gap: "1.5",
|
|
87
|
+
align: hAlignMap[align],
|
|
88
|
+
pt: verticalAlign === "bottom" ? "3" : void 0,
|
|
89
|
+
pb: verticalAlign === "top" ? "3" : void 0,
|
|
90
|
+
children: [
|
|
91
|
+
title && /* @__PURE__ */ jsx(Text, { fontWeight: "medium", children: title }),
|
|
92
|
+
/* @__PURE__ */ jsx(
|
|
93
|
+
Flex,
|
|
94
|
+
{
|
|
95
|
+
"data-orientation": orientation,
|
|
96
|
+
gap: spacingValue,
|
|
97
|
+
direction: { _horizontal: "row", _vertical: "column" },
|
|
98
|
+
align: { _horizontal: "center", _vertical: "flex-start" },
|
|
99
|
+
flexWrap: "wrap",
|
|
100
|
+
children: filteredPayload.map((item, index) => {
|
|
101
|
+
const config = chart.getSeries(item);
|
|
102
|
+
const name = getProp(item.payload, nameKey);
|
|
103
|
+
return /* @__PURE__ */ jsxs(HStack, { gap: "1", _icon: { boxSize: "3" }, children: [
|
|
104
|
+
config?.icon || /* @__PURE__ */ jsx(
|
|
105
|
+
ColorSwatch,
|
|
106
|
+
{
|
|
107
|
+
boxSize: "2.5",
|
|
108
|
+
rounded: "full",
|
|
109
|
+
value: chart.color(config?.color)
|
|
110
|
+
}
|
|
111
|
+
),
|
|
112
|
+
/* @__PURE__ */ jsx(Span, { color: "fg.muted", children: name || config?.label })
|
|
113
|
+
] }, index);
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function ChartTooltip(props) {
|
|
122
|
+
const {
|
|
123
|
+
payload: payloadProp,
|
|
124
|
+
label,
|
|
125
|
+
labelFormatter,
|
|
126
|
+
hideLabel,
|
|
127
|
+
hideIndicator,
|
|
128
|
+
hideSeriesLabel,
|
|
129
|
+
showTotal,
|
|
130
|
+
fitContent,
|
|
131
|
+
nameKey,
|
|
132
|
+
render
|
|
133
|
+
} = props;
|
|
134
|
+
const chart = useChartContext();
|
|
135
|
+
const payload = payloadProp?.filter(
|
|
136
|
+
(item) => item.color !== "none" || item.type !== "none"
|
|
137
|
+
);
|
|
138
|
+
const total = useMemo(() => chart.getPayloadTotal(payload), [payload, chart]);
|
|
139
|
+
const tooltipLabel = React.useMemo(() => {
|
|
140
|
+
const item = payload?.[0];
|
|
141
|
+
const itemLabel = `${getProp(item?.payload, nameKey) || label || item?.dataKey || "value"}`;
|
|
142
|
+
return labelFormatter?.(itemLabel, payload ?? []) ?? itemLabel;
|
|
143
|
+
}, [payload, labelFormatter, label, nameKey]);
|
|
144
|
+
if (!payload?.length) return null;
|
|
145
|
+
return /* @__PURE__ */ jsxs(
|
|
146
|
+
Stack,
|
|
147
|
+
{
|
|
148
|
+
minW: fitContent ? void 0 : "8rem",
|
|
149
|
+
gap: "1",
|
|
150
|
+
rounded: "l2",
|
|
151
|
+
bg: "bg.panel",
|
|
152
|
+
px: "2.5",
|
|
153
|
+
py: "1",
|
|
154
|
+
textStyle: "xs",
|
|
155
|
+
shadow: "md",
|
|
156
|
+
children: [
|
|
157
|
+
!hideLabel && /* @__PURE__ */ jsx(Text, { fontWeight: "medium", children: tooltipLabel }),
|
|
158
|
+
/* @__PURE__ */ jsx(Box, { children: payload.map((item, index) => {
|
|
159
|
+
const config = chart.getSeries(item);
|
|
160
|
+
if (render) return render(item.payload);
|
|
161
|
+
return /* @__PURE__ */ jsxs(
|
|
162
|
+
Flex,
|
|
163
|
+
{
|
|
164
|
+
gap: "1.5",
|
|
165
|
+
wrap: "wrap",
|
|
166
|
+
align: "center",
|
|
167
|
+
_icon: { boxSize: "2.5" },
|
|
168
|
+
children: [
|
|
169
|
+
config?.icon,
|
|
170
|
+
config?.color && !config?.icon && !hideIndicator && /* @__PURE__ */ jsx(
|
|
171
|
+
ColorSwatch,
|
|
172
|
+
{
|
|
173
|
+
rounded: "full",
|
|
174
|
+
boxSize: "2",
|
|
175
|
+
value: chart.color(config.color)
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "space-between", flex: "1", children: [
|
|
179
|
+
!hideSeriesLabel && /* @__PURE__ */ jsx(Span, { color: "fg.muted", children: `${config?.label || item.name}` }),
|
|
180
|
+
item.value && /* @__PURE__ */ jsx(
|
|
181
|
+
Text,
|
|
182
|
+
{
|
|
183
|
+
fontFamily: "mono",
|
|
184
|
+
fontWeight: "medium",
|
|
185
|
+
fontVariantNumeric: "tabular-nums",
|
|
186
|
+
children: item.value.toLocaleString()
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
] })
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
index
|
|
193
|
+
);
|
|
194
|
+
}) }),
|
|
195
|
+
showTotal && total != null && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
196
|
+
/* @__PURE__ */ jsx(Separator, { mt: "1" }),
|
|
197
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "1", justify: "space-between", pb: "1", children: [
|
|
198
|
+
/* @__PURE__ */ jsx(Span, { color: "fg.muted", children: "Total" }),
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
Text,
|
|
201
|
+
{
|
|
202
|
+
fontFamily: "mono",
|
|
203
|
+
fontWeight: "medium",
|
|
204
|
+
fontVariantNumeric: "tabular-nums",
|
|
205
|
+
children: total.toLocaleString()
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
] })
|
|
209
|
+
] })
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
const isPolarViewBox = (viewBox) => "cx" in viewBox && "cy" in viewBox;
|
|
215
|
+
function ChartRadialText(props) {
|
|
216
|
+
const { viewBox, title, description, gap = 24 } = props;
|
|
217
|
+
const chart = useChartContext();
|
|
218
|
+
if (!viewBox || !isPolarViewBox(viewBox)) return null;
|
|
219
|
+
return /* @__PURE__ */ jsxs(
|
|
220
|
+
"text",
|
|
221
|
+
{
|
|
222
|
+
x: viewBox.cx,
|
|
223
|
+
y: viewBox.cy,
|
|
224
|
+
textAnchor: "middle",
|
|
225
|
+
dominantBaseline: "middle",
|
|
226
|
+
fill: chart.color("fg"),
|
|
227
|
+
children: [
|
|
228
|
+
/* @__PURE__ */ jsx(
|
|
229
|
+
"tspan",
|
|
230
|
+
{
|
|
231
|
+
x: viewBox.cx,
|
|
232
|
+
y: viewBox.cy,
|
|
233
|
+
style: { fontSize: "2rem", fontWeight: 600 },
|
|
234
|
+
children: title
|
|
235
|
+
}
|
|
236
|
+
),
|
|
237
|
+
/* @__PURE__ */ jsx(
|
|
238
|
+
"tspan",
|
|
239
|
+
{
|
|
240
|
+
x: viewBox.cx,
|
|
241
|
+
y: (viewBox.cy || 0) + gap,
|
|
242
|
+
style: { fill: chart.color("fg.muted") },
|
|
243
|
+
children: description
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
]
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export { ChartGradient, ChartLegend, ChartRadialText, ChartRoot, ChartTooltip };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
export { useChart } from './use-chart.js';
|
|
3
|
+
export { ChartGradient, ChartLegend, ChartRadialText, ChartRoot, ChartTooltip } from './chart/chart.js';
|
|
4
|
+
import * as namespace from './chart/namespace.js';
|
|
5
|
+
export { namespace as Chart };
|
|
6
|
+
export { BarListBar, BarListContent, BarListLabel, BarListRoot, BarListTitle, BarListTooltip, BarListValue } from './bar-list/bar-list.js';
|
|
7
|
+
import * as namespace$1 from './bar-list/namespace.js';
|
|
8
|
+
export { namespace$1 as BarList };
|
|
9
|
+
export { BarSegmentBar, BarSegmentContent, BarSegmentLabel, BarSegmentLegend, BarSegmentReference, BarSegmentRoot, BarSegmentValue } from './bar-segment/bar-segment.js';
|
|
10
|
+
import * as namespace$2 from './bar-segment/namespace.js';
|
|
11
|
+
export { namespace$2 as BarSegment };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
import { useLocaleContext, useChakraContext } from '@chakra-ui/react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
function useChart(props) {
|
|
7
|
+
const { data, series = [], sort } = props;
|
|
8
|
+
const id = React.useId();
|
|
9
|
+
const [selectedSeries, setSelectedSeries] = React.useState(
|
|
10
|
+
null
|
|
11
|
+
);
|
|
12
|
+
const [highlightedSeries, setHighlightedSeries] = React.useState(null);
|
|
13
|
+
const env = useLocaleContext();
|
|
14
|
+
const sys = useChakraContext();
|
|
15
|
+
const color = (key2) => sys.token(`colors.${key2}`, key2);
|
|
16
|
+
const size = (key2) => sys.token(`sizes.${key2}`, key2);
|
|
17
|
+
const spacing = (key2) => sys.token(`spacing.${key2}`, key2);
|
|
18
|
+
const key = (prop) => prop ?? "value";
|
|
19
|
+
const formatNumber = React.useCallback(
|
|
20
|
+
(options) => {
|
|
21
|
+
const formatter = new Intl.NumberFormat(env.locale, options);
|
|
22
|
+
return (value) => formatter.format(value);
|
|
23
|
+
},
|
|
24
|
+
[env.locale]
|
|
25
|
+
);
|
|
26
|
+
const formatDate = React.useCallback(
|
|
27
|
+
(options) => {
|
|
28
|
+
return (value) => new Date(value).toLocaleDateString(env.locale, options);
|
|
29
|
+
},
|
|
30
|
+
[env.locale]
|
|
31
|
+
);
|
|
32
|
+
const getSeries = (item) => {
|
|
33
|
+
if (!isObject(item)) return;
|
|
34
|
+
const result = series.find((s) => {
|
|
35
|
+
return s.name === item.name || s.name === getProp(item.payload, "name") || s.name === item.dataKey || s.name === getProp(item.payload, "dataKey");
|
|
36
|
+
}) || { color: void 0 };
|
|
37
|
+
result.color || (result.color = getProp(item.payload, "color"));
|
|
38
|
+
result.label || (result.label = result.name?.toLocaleString() || getProp(item.payload, "name"));
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
const getTotal = (key2) => {
|
|
42
|
+
return data.reduce((acc, d) => acc + Number(d[key2]), 0);
|
|
43
|
+
};
|
|
44
|
+
function getPayloadTotal(payload) {
|
|
45
|
+
return payload?.reduce((acc, item) => {
|
|
46
|
+
if (!item.value) return acc;
|
|
47
|
+
const num = Number(item.value);
|
|
48
|
+
const value = Number.isNaN(num) ? 0 : num;
|
|
49
|
+
return acc + value;
|
|
50
|
+
}, 0);
|
|
51
|
+
}
|
|
52
|
+
function getMin(key2) {
|
|
53
|
+
return Math.min(...data.map((d) => Number(d[key2])));
|
|
54
|
+
}
|
|
55
|
+
function getMax(key2) {
|
|
56
|
+
return Math.max(...data.map((d) => Number(d[key2])));
|
|
57
|
+
}
|
|
58
|
+
function getValuePercent(key2, value, domain) {
|
|
59
|
+
const min = getMin(key2);
|
|
60
|
+
const max = getMax(key2);
|
|
61
|
+
if (domain) {
|
|
62
|
+
const d = typeof domain === "function" ? domain({ min, max }) : domain;
|
|
63
|
+
return (value - d[0]) / (d[1] - d[0]) * 100;
|
|
64
|
+
}
|
|
65
|
+
return value / getTotal(key2) * 100;
|
|
66
|
+
}
|
|
67
|
+
const sortedData = React.useMemo(() => {
|
|
68
|
+
if (!sort) return data;
|
|
69
|
+
return data.sort((a, b) => {
|
|
70
|
+
const aValue = Number(a[sort.by]);
|
|
71
|
+
const bValue = Number(b[sort.by]);
|
|
72
|
+
return sort.direction === "desc" ? bValue - aValue : aValue - bValue;
|
|
73
|
+
});
|
|
74
|
+
}, [data, sort]);
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
key,
|
|
78
|
+
// series
|
|
79
|
+
data: sortedData,
|
|
80
|
+
series,
|
|
81
|
+
getSeries,
|
|
82
|
+
// token functions
|
|
83
|
+
color,
|
|
84
|
+
size,
|
|
85
|
+
spacing,
|
|
86
|
+
// formatters
|
|
87
|
+
formatNumber,
|
|
88
|
+
formatDate,
|
|
89
|
+
// state
|
|
90
|
+
selectedSeries,
|
|
91
|
+
setSelectedSeries,
|
|
92
|
+
highlightedSeries,
|
|
93
|
+
setHighlightedSeries,
|
|
94
|
+
// value functions
|
|
95
|
+
getTotal,
|
|
96
|
+
getMin,
|
|
97
|
+
getMax,
|
|
98
|
+
getPayloadTotal,
|
|
99
|
+
getValuePercent
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const isObject = (value) => typeof value === "object" && value !== null;
|
|
103
|
+
function getProp(item, key) {
|
|
104
|
+
if (!key || !isObject(item)) return;
|
|
105
|
+
return Reflect.get(item, key);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { getProp, useChart };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AbsoluteCenterProps, FlexProps, StackProps, Tokens } from "@chakra-ui/react";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { type UseChartReturn } from "../use-chart";
|
|
4
|
+
export interface BarListData {
|
|
5
|
+
name: string;
|
|
6
|
+
value: number;
|
|
7
|
+
href?: string;
|
|
8
|
+
}
|
|
9
|
+
interface ChartProps {
|
|
10
|
+
chart: UseChartReturn<BarListData>;
|
|
11
|
+
}
|
|
12
|
+
export interface BarListRootProps extends StackProps, ChartProps {
|
|
13
|
+
barSize?: Tokens["sizes"];
|
|
14
|
+
}
|
|
15
|
+
export declare function BarListRoot(props: BarListRootProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare const BarListTitle: (props: StackProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare const BarListContent: (props: FlexProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export interface BarListTooltipProps extends AbsoluteCenterProps {
|
|
19
|
+
payload: BarListData;
|
|
20
|
+
labelFormatter?: (value: number) => React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
export declare function BarListTooltip(props: BarListTooltipProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export interface BarListBarProps extends StackProps {
|
|
24
|
+
showTooltip?: boolean;
|
|
25
|
+
label?: (props: {
|
|
26
|
+
payload: BarListData;
|
|
27
|
+
index: number;
|
|
28
|
+
}) => React.ReactNode;
|
|
29
|
+
}
|
|
30
|
+
export declare function BarListBar(props: BarListBarProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export interface BarListValueProps extends StackProps {
|
|
32
|
+
valueFormatter?: (value: number) => React.ReactNode;
|
|
33
|
+
}
|
|
34
|
+
export declare function BarListValue(props: BarListValueProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
export interface BarListLabelProps extends Omit<StackProps, "title"> {
|
|
36
|
+
title: React.ReactNode;
|
|
37
|
+
titleAlignment?: StackProps["textAlign"];
|
|
38
|
+
}
|
|
39
|
+
export declare function BarListLabel(props: BarListLabelProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { BarListBar, BarListContent, BarListRoot, BarListValue, BarListTitle, BarListLabel, BarListTooltip, } from "./bar-list";
|
|
2
|
+
export type { BarListData, BarListBarProps, BarListRootProps, BarListValueProps, BarListLabelProps, BarListTooltipProps, } from "./bar-list";
|
|
3
|
+
export * as BarList from "./namespace";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { BarListContent as Content, BarListRoot as Root, BarListValue as Value, BarListBar as Bar, BarListTitle as Title, BarListLabel as Label, BarListTooltip as Tooltip, } from "./bar-list";
|
|
2
|
+
export type { BarListData as Data, BarListBarProps as BarProps, BarListRootProps as RootProps, BarListValueProps as ValueProps, BarListLabelProps as LabelProps, BarListTooltipProps as TooltipProps, } from "./bar-list";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { StackProps, Tokens } from "@chakra-ui/react";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import type { UseChartReturn } from "../use-chart";
|
|
4
|
+
export interface BarSegmentData {
|
|
5
|
+
name: string;
|
|
6
|
+
value: number;
|
|
7
|
+
color: string;
|
|
8
|
+
}
|
|
9
|
+
interface ChartProps {
|
|
10
|
+
chart: UseChartReturn<BarSegmentData>;
|
|
11
|
+
}
|
|
12
|
+
export interface BarSegmentRootProps extends StackProps, ChartProps {
|
|
13
|
+
barSize?: Tokens["sizes"];
|
|
14
|
+
}
|
|
15
|
+
export declare function BarSegmentRoot(props: BarSegmentRootProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare const BarSegmentContent: React.ForwardRefExoticComponent<StackProps & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
export interface BarSegmentLabelProps extends StackProps {
|
|
18
|
+
}
|
|
19
|
+
export declare function BarSegmentLabel(props: BarSegmentLabelProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export interface BarSegmentBarProps extends StackProps {
|
|
21
|
+
showTooltip?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function BarSegmentBar(props: BarSegmentBarProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export interface BarSegmentReferenceProps {
|
|
25
|
+
value: number;
|
|
26
|
+
label?: React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
export declare function BarSegmentReference(props: BarSegmentReferenceProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export interface BarSegmentValueProps extends StackProps {
|
|
30
|
+
}
|
|
31
|
+
export declare function BarSegmentValue(props: BarSegmentValueProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export interface BarSegmentLegendProps extends StackProps {
|
|
33
|
+
showPercent?: boolean;
|
|
34
|
+
showValue?: boolean;
|
|
35
|
+
valueFormatter?: (value: number) => string;
|
|
36
|
+
}
|
|
37
|
+
export declare function BarSegmentLegend(props: BarSegmentLegendProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export interface BarSegmentTooltipProps {
|
|
39
|
+
payload: BarSegmentData;
|
|
40
|
+
}
|
|
41
|
+
export declare function BarSegmentTooltip(props: BarSegmentTooltipProps): import("react/jsx-runtime").JSX.Element | null;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { BarSegmentBar, BarSegmentContent, BarSegmentLabel, BarSegmentRoot, BarSegmentValue, BarSegmentLegend, BarSegmentReference, } from "./bar-segment";
|
|
2
|
+
export type { BarSegmentData, BarSegmentLegendProps, BarSegmentRootProps, BarSegmentValueProps, BarSegmentReferenceProps, BarSegmentBarProps, BarSegmentLabelProps, BarSegmentTooltipProps, } from "./bar-segment";
|
|
3
|
+
export * as BarSegment from "./namespace";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { BarSegmentBar as Bar, BarSegmentContent as Content, BarSegmentLabel as Label, BarSegmentRoot as Root, BarSegmentValue as Value, BarSegmentLegend as Legend, BarSegmentReference as Reference, } from "./bar-segment";
|
|
2
|
+
export type { BarSegmentData as Data, BarSegmentLegendProps as LegendProps, BarSegmentRootProps as RootProps, BarSegmentValueProps as ValueProps, BarSegmentReferenceProps as ReferenceProps, BarSegmentBarProps as BarProps, BarSegmentLabelProps as LabelProps, BarSegmentTooltipProps as TooltipProps, } from "./bar-segment";
|