@object-ui/plugin-charts 3.1.5 → 3.3.1
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/CHANGELOG.md +28 -0
- package/README.md +24 -0
- package/dist/{AdvancedChartImpl-DmHTUUVD.js → AdvancedChartImpl-DxaZtNlE.js} +1214 -1206
- package/dist/{BarChart-XZkfLmcU.js → BarChart-BQS4sYHd.js} +3859 -3766
- package/dist/{ChartImpl-0VlpsMWG.js → ChartImpl-BaXisyXJ.js} +6 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +207 -63
- package/dist/index.umd.cjs +19 -19
- package/dist/{jsx-runtime-C8d0IhUE.js → jsx-runtime-Caia9pQX.js} +1 -1
- package/dist/packages/plugin-charts/src/ObjectChart.d.ts +31 -0
- package/package.json +34 -10
- package/.turbo/turbo-build.log +0 -26
- package/dist/src/ObjectChart.d.ts +0 -12
- package/examples/chart-examples.ts +0 -54
- package/src/AdvancedChartImpl.tsx +0 -309
- package/src/ChartContainerImpl.tsx +0 -353
- package/src/ChartImpl.tsx +0 -91
- package/src/ChartRenderer.tsx +0 -112
- package/src/ObjectChart.stories.tsx +0 -104
- package/src/ObjectChart.tsx +0 -145
- package/src/__tests__/ObjectChart.aggregation.test.ts +0 -166
- package/src/__tests__/ObjectChart.dataFetch.test.tsx +0 -303
- package/src/index.test.ts +0 -136
- package/src/index.tsx +0 -172
- package/src/types.ts +0 -68
- package/tsconfig.json +0 -17
- package/vite.config.ts +0 -61
- package/vitest.config.ts +0 -13
- package/vitest.setup.ts +0 -1
- /package/dist/{src → packages/plugin-charts/src}/AdvancedChartImpl.d.ts +0 -0
- /package/dist/{src → packages/plugin-charts/src}/ChartContainerImpl.d.ts +0 -0
- /package/dist/{src → packages/plugin-charts/src}/ChartImpl.d.ts +0 -0
- /package/dist/{src → packages/plugin-charts/src}/ChartRenderer.d.ts +0 -0
- /package/dist/{src → packages/plugin-charts/src}/ObjectChart.stories.d.ts +0 -0
- /package/dist/{src → packages/plugin-charts/src}/index.d.ts +0 -0
- /package/dist/{src → packages/plugin-charts/src}/types.d.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region \0rolldown/runtime.js
|
|
2
|
-
var e = Object.create, t = Object.defineProperty, n = Object.getOwnPropertyDescriptor, r = Object.getOwnPropertyNames, i = Object.getPrototypeOf, a = Object.prototype.hasOwnProperty, o = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), s = (e, n) => {
|
|
2
|
+
var e = Object.create, t = Object.defineProperty, n = Object.getOwnPropertyDescriptor, r = Object.getOwnPropertyNames, i = Object.getPrototypeOf, a = Object.prototype.hasOwnProperty, o = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), s = (e, n) => {
|
|
3
3
|
let r = {};
|
|
4
4
|
for (var i in e) t(r, i, {
|
|
5
5
|
get: e[i],
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Humanize a snake_case or kebab-case string into Title Case.
|
|
3
|
+
* Local implementation to avoid a dependency on @object-ui/fields.
|
|
4
|
+
*/
|
|
5
|
+
export declare function humanizeLabel(value: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Client-side aggregation for fetched records.
|
|
8
|
+
* Groups records by `groupBy` field and applies the aggregation function
|
|
9
|
+
* to the `field` values in each group.
|
|
10
|
+
*/
|
|
11
|
+
export declare function aggregateRecords(records: any[], aggregate: {
|
|
12
|
+
field: string;
|
|
13
|
+
function: string;
|
|
14
|
+
groupBy: string;
|
|
15
|
+
}): any[];
|
|
16
|
+
/**
|
|
17
|
+
* Resolve groupBy field values to human-readable labels using field metadata.
|
|
18
|
+
*
|
|
19
|
+
* - **select/picklist** fields: maps value→label via `field.options`.
|
|
20
|
+
* - **lookup/master_detail** fields: batch-fetches referenced records
|
|
21
|
+
* via `dataSource.find()` and maps id→name.
|
|
22
|
+
* - **fallback**: applies `humanizeLabel()` to convert snake_case/kebab-case
|
|
23
|
+
* values into Title Case.
|
|
24
|
+
*
|
|
25
|
+
* The resolved data is a new array with the groupBy key replaced by its label.
|
|
26
|
+
* This function is pure data-layer logic — the rendering layer does not need
|
|
27
|
+
* to perform any value→label conversion.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveGroupByLabels(data: any[], groupByField: string, objectSchema: any, dataSource?: any): Promise<any[]>;
|
|
30
|
+
export { extractRecords } from '../../core/src';
|
|
31
|
+
export declare const ObjectChart: (props: any) => import("react/jsx-runtime").JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-charts",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Chart components plugin for Object UI, powered by Recharts",
|
|
7
|
-
"homepage": "https://www.objectui.org",
|
|
7
|
+
"homepage": "https://www.objectui.org/docs/plugins/plugin-charts",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/objectstack-ai/objectui.git",
|
|
10
|
+
"url": "git+https://github.com/objectstack-ai/objectui.git",
|
|
11
11
|
"directory": "packages/plugin-charts"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
@@ -24,11 +24,12 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"@object-ui/
|
|
30
|
-
"@object-ui/
|
|
31
|
-
"@object-ui/
|
|
27
|
+
"lucide-react": "^1.8.0",
|
|
28
|
+
"recharts": "^3.8.1",
|
|
29
|
+
"@object-ui/components": "3.3.1",
|
|
30
|
+
"@object-ui/core": "3.3.1",
|
|
31
|
+
"@object-ui/react": "3.3.1",
|
|
32
|
+
"@object-ui/types": "3.3.1"
|
|
32
33
|
},
|
|
33
34
|
"peerDependencies": {
|
|
34
35
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -38,10 +39,33 @@
|
|
|
38
39
|
"@types/react": "19.2.14",
|
|
39
40
|
"@types/react-dom": "19.2.3",
|
|
40
41
|
"@vitejs/plugin-react": "^6.0.1",
|
|
41
|
-
"typescript": "^
|
|
42
|
-
"vite": "^8.0.
|
|
42
|
+
"typescript": "^6.0.3",
|
|
43
|
+
"vite": "^8.0.9",
|
|
43
44
|
"vite-plugin-dts": "^4.5.4"
|
|
44
45
|
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"objectui",
|
|
48
|
+
"sdui",
|
|
49
|
+
"schema-driven-ui",
|
|
50
|
+
"react",
|
|
51
|
+
"tailwind",
|
|
52
|
+
"shadcn",
|
|
53
|
+
"objectstack",
|
|
54
|
+
"plugin",
|
|
55
|
+
"charts",
|
|
56
|
+
"recharts",
|
|
57
|
+
"visualization"
|
|
58
|
+
],
|
|
59
|
+
"author": "ObjectStack Team <team@objectstack.ai>",
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
},
|
|
63
|
+
"files": [
|
|
64
|
+
"dist",
|
|
65
|
+
"README.md",
|
|
66
|
+
"CHANGELOG.md",
|
|
67
|
+
"LICENSE"
|
|
68
|
+
],
|
|
45
69
|
"scripts": {
|
|
46
70
|
"build": "vite build",
|
|
47
71
|
"test": "vitest run",
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @object-ui/plugin-charts@3.1.5 build /home/runner/work/objectui/objectui/packages/plugin-charts
|
|
3
|
-
> vite build
|
|
4
|
-
|
|
5
|
-
[36mvite v8.0.1 [32mbuilding client environment for production...[36m[39m
|
|
6
|
-
[2K
|
|
7
|
-
rendering chunks...
|
|
8
|
-
[32m
|
|
9
|
-
[36m[vite:dts][32m Start generate declaration files...[39m
|
|
10
|
-
[32m[36m[vite:dts][32m Declaration files built in 29474ms.
|
|
11
|
-
[39m
|
|
12
|
-
computing gzip size...
|
|
13
|
-
dist/ChartImpl-0VlpsMWG.js 3.70 kB │ gzip: 1.16 kB
|
|
14
|
-
[33m[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugin `vite:dts`. See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
15
|
-
[39m
|
|
16
|
-
dist/index.js 8.53 kB │ gzip: 2.53 kB
|
|
17
|
-
dist/jsx-runtime-C8d0IhUE.js 8.60 kB │ gzip: 3.13 kB
|
|
18
|
-
dist/AdvancedChartImpl-DmHTUUVD.js 120.71 kB │ gzip: 25.04 kB
|
|
19
|
-
dist/BarChart-XZkfLmcU.js 533.19 kB │ gzip: 130.61 kB
|
|
20
|
-
|
|
21
|
-
[2K
|
|
22
|
-
rendering chunks...
|
|
23
|
-
computing gzip size...
|
|
24
|
-
dist/index.umd.cjs 498.91 kB │ gzip: 143.06 kB
|
|
25
|
-
|
|
26
|
-
[32m✓ built in 34.99s[39m
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Client-side aggregation for fetched records.
|
|
3
|
-
* Groups records by `groupBy` field and applies the aggregation function
|
|
4
|
-
* to the `field` values in each group.
|
|
5
|
-
*/
|
|
6
|
-
export declare function aggregateRecords(records: any[], aggregate: {
|
|
7
|
-
field: string;
|
|
8
|
-
function: string;
|
|
9
|
-
groupBy: string;
|
|
10
|
-
}): any[];
|
|
11
|
-
export { extractRecords } from '../../core/src';
|
|
12
|
-
export declare const ObjectChart: (props: any) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Example: Using all new chart types
|
|
11
|
-
*
|
|
12
|
-
* This example demonstrates the new Pie, Donut, Radar, and Scatter chart types
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
export const pieChartExample = {
|
|
16
|
-
type: 'pie-chart',
|
|
17
|
-
data: [
|
|
18
|
-
{ name: 'Chrome', value: 65 },
|
|
19
|
-
{ name: 'Firefox', value: 20 },
|
|
20
|
-
{ name: 'Safari', value: 10 },
|
|
21
|
-
{ name: 'Edge', value: 5 },
|
|
22
|
-
],
|
|
23
|
-
xAxisKey: 'name',
|
|
24
|
-
series: [{ dataKey: 'value' }],
|
|
25
|
-
config: {
|
|
26
|
-
Chrome: { label: 'Chrome', color: 'hsl(var(--chart-1))' },
|
|
27
|
-
Firefox: { label: 'Firefox', color: 'hsl(var(--chart-2))' },
|
|
28
|
-
Safari: { label: 'Safari', color: 'hsl(var(--chart-3))' },
|
|
29
|
-
Edge: { label: 'Edge', color: 'hsl(var(--chart-4))' },
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const donutChartExample = {
|
|
34
|
-
type: 'donut-chart',
|
|
35
|
-
data: [
|
|
36
|
-
{ category: 'Electronics', revenue: 45000 },
|
|
37
|
-
{ category: 'Clothing', revenue: 32000 },
|
|
38
|
-
{ category: 'Food', revenue: 28000 },
|
|
39
|
-
{ category: 'Books', revenue: 15000 },
|
|
40
|
-
],
|
|
41
|
-
xAxisKey: 'category',
|
|
42
|
-
series: [{ dataKey: 'revenue' }]
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const radarChartExample = {
|
|
46
|
-
type: 'radar-chart',
|
|
47
|
-
data: [
|
|
48
|
-
{ skill: 'React', score: 90 },
|
|
49
|
-
{ skill: 'TypeScript', score: 85 },
|
|
50
|
-
{ skill: 'Node.js', score: 80 }
|
|
51
|
-
],
|
|
52
|
-
xAxisKey: 'skill',
|
|
53
|
-
series: [{ dataKey: 'score' }]
|
|
54
|
-
};
|
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import * as React from "react"
|
|
10
|
-
import {
|
|
11
|
-
Bar,
|
|
12
|
-
BarChart,
|
|
13
|
-
Line,
|
|
14
|
-
LineChart,
|
|
15
|
-
Area,
|
|
16
|
-
AreaChart,
|
|
17
|
-
Pie,
|
|
18
|
-
PieChart,
|
|
19
|
-
Radar,
|
|
20
|
-
RadarChart,
|
|
21
|
-
PolarGrid,
|
|
22
|
-
PolarAngleAxis,
|
|
23
|
-
PolarRadiusAxis,
|
|
24
|
-
Scatter,
|
|
25
|
-
ScatterChart,
|
|
26
|
-
ZAxis,
|
|
27
|
-
Cell,
|
|
28
|
-
XAxis,
|
|
29
|
-
YAxis,
|
|
30
|
-
CartesianGrid,
|
|
31
|
-
} from 'recharts';
|
|
32
|
-
import {
|
|
33
|
-
ChartContainer,
|
|
34
|
-
ChartTooltip,
|
|
35
|
-
ChartTooltipContent,
|
|
36
|
-
ChartLegend,
|
|
37
|
-
ChartLegendContent,
|
|
38
|
-
ChartConfig
|
|
39
|
-
} from './ChartContainerImpl';
|
|
40
|
-
|
|
41
|
-
// Default color fallback for chart series
|
|
42
|
-
const DEFAULT_CHART_COLOR = 'hsl(var(--primary))';
|
|
43
|
-
|
|
44
|
-
// Simple color map for Tailwind names (Mock - ideal would be computed styles)
|
|
45
|
-
const TW_COLORS: Record<string, string> = {
|
|
46
|
-
slate: '#64748b',
|
|
47
|
-
gray: '#6b7280',
|
|
48
|
-
zinc: '#71717a',
|
|
49
|
-
neutral: '#737373',
|
|
50
|
-
stone: '#78716c',
|
|
51
|
-
red: '#ef4444',
|
|
52
|
-
orange: '#f97316',
|
|
53
|
-
amber: '#f59e0b',
|
|
54
|
-
yellow: '#eab308',
|
|
55
|
-
lime: '#84cc16',
|
|
56
|
-
green: '#22c55e',
|
|
57
|
-
emerald: '#10b981',
|
|
58
|
-
teal: '#14b8a6',
|
|
59
|
-
cyan: '#06b6d4',
|
|
60
|
-
sky: '#0ea5e9',
|
|
61
|
-
blue: '#3b82f6',
|
|
62
|
-
indigo: '#6366f1',
|
|
63
|
-
violet: '#8b5cf6',
|
|
64
|
-
purple: '#a855f7',
|
|
65
|
-
fuchsia: '#d946ef',
|
|
66
|
-
pink: '#ec4899',
|
|
67
|
-
rose: '#f43f5e',
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const resolveColor = (color: string) => TW_COLORS[color] || color;
|
|
71
|
-
|
|
72
|
-
export interface AdvancedChartImplProps {
|
|
73
|
-
chartType?: 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'combo';
|
|
74
|
-
data?: Array<Record<string, any>>;
|
|
75
|
-
config?: ChartConfig;
|
|
76
|
-
xAxisKey?: string;
|
|
77
|
-
series?: Array<{ dataKey: string; chartType?: 'bar' | 'line' | 'area' }>;
|
|
78
|
-
className?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* AdvancedChartImpl - The heavy implementation that imports Recharts with full features
|
|
83
|
-
* This component is lazy-loaded to avoid including Recharts in the initial bundle
|
|
84
|
-
*/
|
|
85
|
-
export default function AdvancedChartImpl({
|
|
86
|
-
chartType = 'bar',
|
|
87
|
-
data: rawData = [],
|
|
88
|
-
config = {},
|
|
89
|
-
xAxisKey = 'name',
|
|
90
|
-
series = [],
|
|
91
|
-
className = '',
|
|
92
|
-
}: AdvancedChartImplProps) {
|
|
93
|
-
const data = Array.isArray(rawData) ? rawData : [];
|
|
94
|
-
const [isMobile, setIsMobile] = React.useState(false);
|
|
95
|
-
|
|
96
|
-
React.useEffect(() => {
|
|
97
|
-
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
98
|
-
checkMobile();
|
|
99
|
-
window.addEventListener('resize', checkMobile);
|
|
100
|
-
return () => window.removeEventListener('resize', checkMobile);
|
|
101
|
-
}, []);
|
|
102
|
-
const ChartComponent = {
|
|
103
|
-
bar: BarChart,
|
|
104
|
-
line: LineChart,
|
|
105
|
-
area: AreaChart,
|
|
106
|
-
pie: PieChart,
|
|
107
|
-
donut: PieChart,
|
|
108
|
-
radar: RadarChart,
|
|
109
|
-
scatter: ScatterChart,
|
|
110
|
-
combo: BarChart,
|
|
111
|
-
}[chartType] || BarChart;
|
|
112
|
-
|
|
113
|
-
console.log('📈 Rendering Chart:', { chartType, dataLength: data.length, config, series, xAxisKey });
|
|
114
|
-
|
|
115
|
-
// Helper function to get color palette
|
|
116
|
-
const getPalette = () => [
|
|
117
|
-
'hsl(var(--chart-1))',
|
|
118
|
-
'hsl(var(--chart-2))',
|
|
119
|
-
'hsl(var(--chart-3))',
|
|
120
|
-
'hsl(var(--chart-4))',
|
|
121
|
-
'hsl(var(--chart-5))'
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
// Pie and Donut charts
|
|
125
|
-
if (chartType === 'pie' || chartType === 'donut') {
|
|
126
|
-
const innerRadius = chartType === 'donut' ? 60 : 0;
|
|
127
|
-
return (
|
|
128
|
-
<ChartContainer config={config} className={className}>
|
|
129
|
-
<PieChart>
|
|
130
|
-
<ChartTooltip cursor={false} content={<ChartTooltipContent hideLabel />} />
|
|
131
|
-
<Pie
|
|
132
|
-
data={data}
|
|
133
|
-
dataKey={series[0]?.dataKey || 'value'}
|
|
134
|
-
nameKey={xAxisKey || 'name'}
|
|
135
|
-
innerRadius={innerRadius}
|
|
136
|
-
strokeWidth={5}
|
|
137
|
-
paddingAngle={2}
|
|
138
|
-
outerRadius={80}
|
|
139
|
-
>
|
|
140
|
-
{data.map((entry, index) => {
|
|
141
|
-
// 1. Try config by nameKey (category)
|
|
142
|
-
let c = config[entry[xAxisKey]]?.color;
|
|
143
|
-
|
|
144
|
-
// 2. Fallback to palette
|
|
145
|
-
if (!c) {
|
|
146
|
-
const palette = getPalette();
|
|
147
|
-
c = palette[index % palette.length];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return <Cell key={`cell-${index}`} fill={resolveColor(c)} />;
|
|
151
|
-
})}
|
|
152
|
-
</Pie>
|
|
153
|
-
<ChartLegend
|
|
154
|
-
content={<ChartLegendContent nameKey={xAxisKey} />}
|
|
155
|
-
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
156
|
-
/>
|
|
157
|
-
</PieChart>
|
|
158
|
-
</ChartContainer>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Radar chart
|
|
163
|
-
if (chartType === 'radar') {
|
|
164
|
-
return (
|
|
165
|
-
<ChartContainer config={config} className={className}>
|
|
166
|
-
<RadarChart data={data}>
|
|
167
|
-
<PolarGrid />
|
|
168
|
-
<PolarAngleAxis dataKey={xAxisKey} />
|
|
169
|
-
<PolarRadiusAxis />
|
|
170
|
-
<ChartTooltip content={<ChartTooltipContent />} />
|
|
171
|
-
<ChartLegend
|
|
172
|
-
content={<ChartLegendContent />}
|
|
173
|
-
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
174
|
-
/>
|
|
175
|
-
{series.map((s: any) => {
|
|
176
|
-
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
|
|
177
|
-
return (
|
|
178
|
-
<Radar
|
|
179
|
-
key={s.dataKey}
|
|
180
|
-
dataKey={s.dataKey}
|
|
181
|
-
stroke={color}
|
|
182
|
-
fill={color}
|
|
183
|
-
fillOpacity={0.6}
|
|
184
|
-
/>
|
|
185
|
-
);
|
|
186
|
-
})}
|
|
187
|
-
</RadarChart>
|
|
188
|
-
</ChartContainer>
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Scatter chart
|
|
193
|
-
if (chartType === 'scatter') {
|
|
194
|
-
return (
|
|
195
|
-
<ChartContainer config={config} className={className}>
|
|
196
|
-
<ScatterChart>
|
|
197
|
-
<CartesianGrid vertical={false} />
|
|
198
|
-
<XAxis
|
|
199
|
-
type="number"
|
|
200
|
-
dataKey={xAxisKey}
|
|
201
|
-
name={String(config[xAxisKey]?.label || xAxisKey)}
|
|
202
|
-
tickLine={false}
|
|
203
|
-
axisLine={false}
|
|
204
|
-
interval={isMobile ? Math.ceil(data.length / 5) : 0}
|
|
205
|
-
/>
|
|
206
|
-
<YAxis
|
|
207
|
-
type="number"
|
|
208
|
-
dataKey={series[0]?.dataKey || 'value'}
|
|
209
|
-
name={String(config[series[0]?.dataKey]?.label || series[0]?.dataKey)}
|
|
210
|
-
tickLine={false}
|
|
211
|
-
axisLine={false}
|
|
212
|
-
/>
|
|
213
|
-
<ZAxis type="number" range={[60, 400]} />
|
|
214
|
-
<ChartTooltip content={<ChartTooltipContent />} />
|
|
215
|
-
<ChartLegend
|
|
216
|
-
content={<ChartLegendContent />}
|
|
217
|
-
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
218
|
-
/>
|
|
219
|
-
{series.map((s: any, index: number) => {
|
|
220
|
-
const palette = getPalette();
|
|
221
|
-
const color = resolveColor(config[s.dataKey]?.color || palette[index % palette.length]);
|
|
222
|
-
return (
|
|
223
|
-
<Scatter
|
|
224
|
-
key={s.dataKey}
|
|
225
|
-
name={config[s.dataKey]?.label || s.dataKey}
|
|
226
|
-
data={data}
|
|
227
|
-
fill={color}
|
|
228
|
-
/>
|
|
229
|
-
);
|
|
230
|
-
})}
|
|
231
|
-
</ScatterChart>
|
|
232
|
-
</ChartContainer>
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Combo chart (mixed bar + line on same chart)
|
|
237
|
-
if (chartType === 'combo') {
|
|
238
|
-
return (
|
|
239
|
-
<ChartContainer config={config} className={className}>
|
|
240
|
-
<BarChart data={data}>
|
|
241
|
-
<CartesianGrid vertical={false} />
|
|
242
|
-
<XAxis
|
|
243
|
-
dataKey={xAxisKey}
|
|
244
|
-
tickLine={false}
|
|
245
|
-
tickMargin={10}
|
|
246
|
-
axisLine={false}
|
|
247
|
-
interval={isMobile ? Math.ceil(data.length / 5) : 0}
|
|
248
|
-
tickFormatter={(value) => (value && typeof value === 'string') ? value.slice(0, 3) : value}
|
|
249
|
-
/>
|
|
250
|
-
<YAxis yAxisId="left" tickLine={false} axisLine={false} />
|
|
251
|
-
<YAxis yAxisId="right" orientation="right" tickLine={false} axisLine={false} />
|
|
252
|
-
<ChartTooltip content={<ChartTooltipContent />} />
|
|
253
|
-
<ChartLegend
|
|
254
|
-
content={<ChartLegendContent />}
|
|
255
|
-
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
256
|
-
/>
|
|
257
|
-
{series.map((s: any, index: number) => {
|
|
258
|
-
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
|
|
259
|
-
const seriesType = s.chartType || (index === 0 ? 'bar' : 'line');
|
|
260
|
-
const yAxisId = seriesType === 'bar' ? 'left' : 'right';
|
|
261
|
-
|
|
262
|
-
if (seriesType === 'line') {
|
|
263
|
-
return <Line key={s.dataKey} yAxisId={yAxisId} type="monotone" dataKey={s.dataKey} stroke={color} strokeWidth={2} dot={false} />;
|
|
264
|
-
}
|
|
265
|
-
if (seriesType === 'area') {
|
|
266
|
-
return <Area key={s.dataKey} yAxisId={yAxisId} type="monotone" dataKey={s.dataKey} fill={color} stroke={color} fillOpacity={0.4} />;
|
|
267
|
-
}
|
|
268
|
-
return <Bar key={s.dataKey} yAxisId={yAxisId} dataKey={s.dataKey} fill={color} radius={4} />;
|
|
269
|
-
})}
|
|
270
|
-
</BarChart>
|
|
271
|
-
</ChartContainer>
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return (
|
|
276
|
-
<ChartContainer config={config} className={className}>
|
|
277
|
-
<ChartComponent data={data}>
|
|
278
|
-
<CartesianGrid vertical={false} />
|
|
279
|
-
<XAxis
|
|
280
|
-
dataKey={xAxisKey}
|
|
281
|
-
tickLine={false}
|
|
282
|
-
tickMargin={10}
|
|
283
|
-
axisLine={false}
|
|
284
|
-
interval={isMobile ? Math.ceil(data.length / 5) : 0}
|
|
285
|
-
tickFormatter={(value) => (value && typeof value === 'string') ? value.slice(0, 3) : value}
|
|
286
|
-
/>
|
|
287
|
-
<ChartTooltip content={<ChartTooltipContent />} />
|
|
288
|
-
<ChartLegend
|
|
289
|
-
content={<ChartLegendContent />}
|
|
290
|
-
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
291
|
-
/>
|
|
292
|
-
{series.map((s: any) => {
|
|
293
|
-
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
|
|
294
|
-
|
|
295
|
-
if (chartType === 'bar') {
|
|
296
|
-
return <Bar key={s.dataKey} dataKey={s.dataKey} fill={color} radius={4} />;
|
|
297
|
-
}
|
|
298
|
-
if (chartType === 'line') {
|
|
299
|
-
return <Line key={s.dataKey} type="monotone" dataKey={s.dataKey} stroke={color} strokeWidth={2} dot={false} />;
|
|
300
|
-
}
|
|
301
|
-
if (chartType === 'area') {
|
|
302
|
-
return <Area key={s.dataKey} type="monotone" dataKey={s.dataKey} fill={color} stroke={color} fillOpacity={0.4} />;
|
|
303
|
-
}
|
|
304
|
-
return null;
|
|
305
|
-
})}
|
|
306
|
-
</ChartComponent>
|
|
307
|
-
</ChartContainer>
|
|
308
|
-
);
|
|
309
|
-
}
|