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