@object-ui/plugin-charts 0.3.1 → 2.0.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/.turbo/turbo-build.log +20 -0
- package/CHANGELOG.md +14 -0
- package/dist/AdvancedChartImpl-DFmeUY4Q.js +4529 -0
- package/dist/{BarChart-RKJxvg5Y.js → BarChart-C_I0OFbj.js} +6033 -5763
- package/dist/ChartImpl-B5LY4On3.js +79 -0
- package/dist/index-DSBO2Kdy.js +494 -0
- package/dist/index.js +5 -6
- package/dist/index.umd.cjs +22 -22
- package/dist/src/AdvancedChartImpl.d.ts +1 -1
- package/dist/src/ChartRenderer.d.ts +35 -0
- package/dist/src/ObjectChart.d.ts +1 -0
- package/dist/src/index.d.ts +5 -39
- package/dist/src/types.d.ts +1 -1
- package/examples/chart-examples.ts +54 -0
- package/package.json +7 -7
- package/src/AdvancedChartImpl.tsx +94 -18
- package/src/ChartRenderer.tsx +112 -0
- package/src/ObjectChart.tsx +79 -0
- package/src/index.test.ts +1 -1
- package/src/index.tsx +82 -121
- package/src/registration.test.tsx +22 -0
- package/vite.config.ts +13 -0
- package/vitest.config.ts +13 -0
- package/vitest.setup.ts +1 -0
- package/dist/AdvancedChartImpl-DJcN3TPx.js +0 -2530
- package/dist/ChartImpl-CE1UGkNR.js +0 -275
- package/dist/index-CTfEtwhn.js +0 -387
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChartConfig } from './ChartContainerImpl';
|
|
2
2
|
export interface AdvancedChartImplProps {
|
|
3
|
-
chartType?: 'bar' | 'line' | 'area' | 'pie';
|
|
3
|
+
chartType?: 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter';
|
|
4
4
|
data?: Array<Record<string, any>>;
|
|
5
5
|
config?: ChartConfig;
|
|
6
6
|
xAxisKey?: string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface ChartBarRendererProps {
|
|
3
|
+
schema: {
|
|
4
|
+
type: string;
|
|
5
|
+
id?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
data?: Array<Record<string, any>>;
|
|
8
|
+
dataKey?: string;
|
|
9
|
+
xAxisKey?: string;
|
|
10
|
+
height?: number;
|
|
11
|
+
color?: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ChartBarRenderer - The public API for the bar chart component
|
|
16
|
+
*/
|
|
17
|
+
export declare const ChartBarRenderer: React.FC<ChartBarRendererProps>;
|
|
18
|
+
export interface ChartRendererProps {
|
|
19
|
+
schema: {
|
|
20
|
+
type: string;
|
|
21
|
+
id?: string;
|
|
22
|
+
className?: string;
|
|
23
|
+
chartType?: 'bar' | 'line' | 'area';
|
|
24
|
+
data?: Array<Record<string, any>>;
|
|
25
|
+
config?: Record<string, any>;
|
|
26
|
+
xAxisKey?: string;
|
|
27
|
+
series?: Array<{
|
|
28
|
+
dataKey: string;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* ChartRenderer - The public API for the advanced chart component
|
|
34
|
+
*/
|
|
35
|
+
export declare const ChartRenderer: React.FC<ChartRendererProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ObjectChart: (props: any) => import("react/jsx-runtime").JSX.Element;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,42 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChartBarRenderer, ChartRenderer } from './ChartRenderer';
|
|
2
2
|
export type { BarChartSchema } from './types';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
type: string;
|
|
6
|
-
id?: string;
|
|
7
|
-
className?: string;
|
|
8
|
-
data?: Array<Record<string, any>>;
|
|
9
|
-
dataKey?: string;
|
|
10
|
-
xAxisKey?: string;
|
|
11
|
-
height?: number;
|
|
12
|
-
color?: string;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* ChartBarRenderer - The public API for the bar chart component
|
|
17
|
-
* This wrapper handles lazy loading internally using React.Suspense
|
|
18
|
-
*/
|
|
19
|
-
export declare const ChartBarRenderer: React.FC<ChartBarRendererProps>;
|
|
20
|
-
export interface ChartRendererProps {
|
|
21
|
-
schema: {
|
|
22
|
-
type: string;
|
|
23
|
-
id?: string;
|
|
24
|
-
className?: string;
|
|
25
|
-
chartType?: 'bar' | 'line' | 'area';
|
|
26
|
-
data?: Array<Record<string, any>>;
|
|
27
|
-
config?: Record<string, any>;
|
|
28
|
-
xAxisKey?: string;
|
|
29
|
-
series?: Array<{
|
|
30
|
-
dataKey: string;
|
|
31
|
-
}>;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* ChartRenderer - The public API for the advanced chart component
|
|
36
|
-
* Supports multiple chart types (bar, line, area) with full configuration
|
|
37
|
-
*/
|
|
38
|
-
export declare const ChartRenderer: React.FC<ChartRendererProps>;
|
|
3
|
+
export { ChartBarRenderer, ChartRenderer };
|
|
4
|
+
export { ObjectChart } from './ObjectChart';
|
|
39
5
|
export declare const chartComponents: {
|
|
40
|
-
'bar-chart':
|
|
41
|
-
chart:
|
|
6
|
+
'bar-chart': import('react').FC<import('./ChartRenderer').ChartBarRendererProps>;
|
|
7
|
+
chart: import('react').FC<import('./ChartRenderer').ChartRendererProps>;
|
|
42
8
|
};
|
package/dist/src/types.d.ts
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-charts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Chart components plugin for Object UI, powered by Recharts",
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"recharts": "^3.7.0",
|
|
28
|
-
"@object-ui/components": "0.
|
|
29
|
-
"@object-ui/core": "0.
|
|
30
|
-
"@object-ui/react": "0.
|
|
31
|
-
"@object-ui/types": "0.
|
|
28
|
+
"@object-ui/components": "2.0.0",
|
|
29
|
+
"@object-ui/core": "2.0.0",
|
|
30
|
+
"@object-ui/react": "2.0.0",
|
|
31
|
+
"@object-ui/types": "2.0.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": "^18.0.0 || ^19.0.0",
|
|
35
35
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@types/react": "^19.2.
|
|
38
|
+
"@types/react": "^19.2.13",
|
|
39
39
|
"@types/react-dom": "^19.2.3",
|
|
40
|
-
"@vitejs/plugin-react": "^
|
|
40
|
+
"@vitejs/plugin-react": "^5.1.3",
|
|
41
41
|
"typescript": "^5.9.3",
|
|
42
42
|
"vite": "^7.3.1",
|
|
43
43
|
"vite-plugin-dts": "^4.5.4"
|
|
@@ -16,6 +16,14 @@ import {
|
|
|
16
16
|
AreaChart,
|
|
17
17
|
Pie,
|
|
18
18
|
PieChart,
|
|
19
|
+
Radar,
|
|
20
|
+
RadarChart,
|
|
21
|
+
PolarGrid,
|
|
22
|
+
PolarAngleAxis,
|
|
23
|
+
PolarRadiusAxis,
|
|
24
|
+
Scatter,
|
|
25
|
+
ScatterChart,
|
|
26
|
+
ZAxis,
|
|
19
27
|
Cell,
|
|
20
28
|
XAxis,
|
|
21
29
|
YAxis,
|
|
@@ -62,7 +70,7 @@ const TW_COLORS: Record<string, string> = {
|
|
|
62
70
|
const resolveColor = (color: string) => TW_COLORS[color] || color;
|
|
63
71
|
|
|
64
72
|
export interface AdvancedChartImplProps {
|
|
65
|
-
chartType?: 'bar' | 'line' | 'area' | 'pie';
|
|
73
|
+
chartType?: 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter';
|
|
66
74
|
data?: Array<Record<string, any>>;
|
|
67
75
|
config?: ChartConfig;
|
|
68
76
|
xAxisKey?: string;
|
|
@@ -87,11 +95,25 @@ export default function AdvancedChartImpl({
|
|
|
87
95
|
line: LineChart,
|
|
88
96
|
area: AreaChart,
|
|
89
97
|
pie: PieChart,
|
|
98
|
+
donut: PieChart,
|
|
99
|
+
radar: RadarChart,
|
|
100
|
+
scatter: ScatterChart,
|
|
90
101
|
}[chartType] || BarChart;
|
|
91
102
|
|
|
92
103
|
console.log('📈 Rendering Chart:', { chartType, dataLength: data.length, config, series, xAxisKey });
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
// Helper function to get color palette
|
|
106
|
+
const getPalette = () => [
|
|
107
|
+
'hsl(var(--chart-1))',
|
|
108
|
+
'hsl(var(--chart-2))',
|
|
109
|
+
'hsl(var(--chart-3))',
|
|
110
|
+
'hsl(var(--chart-4))',
|
|
111
|
+
'hsl(var(--chart-5))'
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
// Pie and Donut charts
|
|
115
|
+
if (chartType === 'pie' || chartType === 'donut') {
|
|
116
|
+
const innerRadius = chartType === 'donut' ? 60 : 0;
|
|
95
117
|
return (
|
|
96
118
|
<ChartContainer config={config} className={className}>
|
|
97
119
|
<PieChart>
|
|
@@ -100,7 +122,7 @@ export default function AdvancedChartImpl({
|
|
|
100
122
|
data={data}
|
|
101
123
|
dataKey={series[0]?.dataKey || 'value'}
|
|
102
124
|
nameKey={xAxisKey || 'name'}
|
|
103
|
-
innerRadius={
|
|
125
|
+
innerRadius={innerRadius}
|
|
104
126
|
strokeWidth={5}
|
|
105
127
|
paddingAngle={2}
|
|
106
128
|
outerRadius={80}
|
|
@@ -109,22 +131,9 @@ export default function AdvancedChartImpl({
|
|
|
109
131
|
// 1. Try config by nameKey (category)
|
|
110
132
|
let c = config[entry[xAxisKey]]?.color;
|
|
111
133
|
|
|
112
|
-
// 2.
|
|
134
|
+
// 2. Fallback to palette
|
|
113
135
|
if (!c) {
|
|
114
|
-
|
|
115
|
-
// Actually my adapter logic in index.tsx was: config[seriesKey].color = colors[idx]
|
|
116
|
-
// But here we are iterating DATA items, not SERIES.
|
|
117
|
-
// So we need a cycling palette.
|
|
118
|
-
// Let's assume the user didn't provide per-category config here, so we cycle default colors.
|
|
119
|
-
const palette = [
|
|
120
|
-
'hsl(var(--chart-1))',
|
|
121
|
-
'hsl(var(--chart-2))',
|
|
122
|
-
'hsl(var(--chart-3))',
|
|
123
|
-
'hsl(var(--chart-4))',
|
|
124
|
-
'hsl(var(--chart-5))'
|
|
125
|
-
];
|
|
126
|
-
// Check if we can get colors from the first series config?
|
|
127
|
-
// No, let's just use the palette or resolveColor from entry if provided in data.
|
|
136
|
+
const palette = getPalette();
|
|
128
137
|
c = palette[index % palette.length];
|
|
129
138
|
}
|
|
130
139
|
|
|
@@ -137,6 +146,73 @@ export default function AdvancedChartImpl({
|
|
|
137
146
|
);
|
|
138
147
|
}
|
|
139
148
|
|
|
149
|
+
// Radar chart
|
|
150
|
+
if (chartType === 'radar') {
|
|
151
|
+
return (
|
|
152
|
+
<ChartContainer config={config} className={className}>
|
|
153
|
+
<RadarChart data={data}>
|
|
154
|
+
<PolarGrid />
|
|
155
|
+
<PolarAngleAxis dataKey={xAxisKey} />
|
|
156
|
+
<PolarRadiusAxis />
|
|
157
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
158
|
+
<ChartLegend content={<ChartLegendContent />} />
|
|
159
|
+
{series.map((s: any) => {
|
|
160
|
+
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
|
|
161
|
+
return (
|
|
162
|
+
<Radar
|
|
163
|
+
key={s.dataKey}
|
|
164
|
+
dataKey={s.dataKey}
|
|
165
|
+
stroke={color}
|
|
166
|
+
fill={color}
|
|
167
|
+
fillOpacity={0.6}
|
|
168
|
+
/>
|
|
169
|
+
);
|
|
170
|
+
})}
|
|
171
|
+
</RadarChart>
|
|
172
|
+
</ChartContainer>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Scatter chart
|
|
177
|
+
if (chartType === 'scatter') {
|
|
178
|
+
return (
|
|
179
|
+
<ChartContainer config={config} className={className}>
|
|
180
|
+
<ScatterChart>
|
|
181
|
+
<CartesianGrid vertical={false} />
|
|
182
|
+
<XAxis
|
|
183
|
+
type="number"
|
|
184
|
+
dataKey={xAxisKey}
|
|
185
|
+
name={String(config[xAxisKey]?.label || xAxisKey)}
|
|
186
|
+
tickLine={false}
|
|
187
|
+
axisLine={false}
|
|
188
|
+
/>
|
|
189
|
+
<YAxis
|
|
190
|
+
type="number"
|
|
191
|
+
dataKey={series[0]?.dataKey || 'value'}
|
|
192
|
+
name={String(config[series[0]?.dataKey]?.label || series[0]?.dataKey)}
|
|
193
|
+
tickLine={false}
|
|
194
|
+
axisLine={false}
|
|
195
|
+
/>
|
|
196
|
+
<ZAxis type="number" range={[60, 400]} />
|
|
197
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
198
|
+
<ChartLegend content={<ChartLegendContent />} />
|
|
199
|
+
{series.map((s: any, index: number) => {
|
|
200
|
+
const palette = getPalette();
|
|
201
|
+
const color = resolveColor(config[s.dataKey]?.color || palette[index % palette.length]);
|
|
202
|
+
return (
|
|
203
|
+
<Scatter
|
|
204
|
+
key={s.dataKey}
|
|
205
|
+
name={config[s.dataKey]?.label || s.dataKey}
|
|
206
|
+
data={data}
|
|
207
|
+
fill={color}
|
|
208
|
+
/>
|
|
209
|
+
);
|
|
210
|
+
})}
|
|
211
|
+
</ScatterChart>
|
|
212
|
+
</ChartContainer>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
140
216
|
return (
|
|
141
217
|
<ChartContainer config={config} className={className}>
|
|
142
218
|
<ChartComponent data={data}>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { Suspense } from 'react';
|
|
3
|
+
import { Skeleton } from '@object-ui/components';
|
|
4
|
+
import type { ChartConfig } from './ChartContainerImpl';
|
|
5
|
+
|
|
6
|
+
// 🚀 Lazy load the implementation files
|
|
7
|
+
const LazyChart = React.lazy(() => import('./ChartImpl'));
|
|
8
|
+
const LazyAdvancedChart = React.lazy(() => import('./AdvancedChartImpl'));
|
|
9
|
+
|
|
10
|
+
export interface ChartBarRendererProps {
|
|
11
|
+
schema: {
|
|
12
|
+
type: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
data?: Array<Record<string, any>>;
|
|
16
|
+
dataKey?: string;
|
|
17
|
+
xAxisKey?: string;
|
|
18
|
+
height?: number;
|
|
19
|
+
color?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* ChartBarRenderer - The public API for the bar chart component
|
|
25
|
+
*/
|
|
26
|
+
export const ChartBarRenderer: React.FC<ChartBarRendererProps> = ({ schema }) => {
|
|
27
|
+
return (
|
|
28
|
+
<Suspense fallback={<Skeleton className="w-full h-[400px]" />}>
|
|
29
|
+
<LazyChart
|
|
30
|
+
data={schema.data}
|
|
31
|
+
dataKey={schema.dataKey}
|
|
32
|
+
xAxisKey={schema.xAxisKey}
|
|
33
|
+
height={schema.height}
|
|
34
|
+
className={schema.className}
|
|
35
|
+
color={schema.color}
|
|
36
|
+
/>
|
|
37
|
+
</Suspense>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export interface ChartRendererProps {
|
|
42
|
+
schema: {
|
|
43
|
+
type: string;
|
|
44
|
+
id?: string;
|
|
45
|
+
className?: string;
|
|
46
|
+
chartType?: 'bar' | 'line' | 'area';
|
|
47
|
+
data?: Array<Record<string, any>>;
|
|
48
|
+
config?: Record<string, any>;
|
|
49
|
+
xAxisKey?: string;
|
|
50
|
+
series?: Array<{ dataKey: string }>;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* ChartRenderer - The public API for the advanced chart component
|
|
56
|
+
*/
|
|
57
|
+
export const ChartRenderer: React.FC<ChartRendererProps> = ({ schema }) => {
|
|
58
|
+
// ⚡️ Adapter: Normalize JSON schema to Recharts Props
|
|
59
|
+
const props = React.useMemo(() => {
|
|
60
|
+
// 1. Defaults
|
|
61
|
+
let series = schema.series;
|
|
62
|
+
let xAxisKey = schema.xAxisKey;
|
|
63
|
+
let config = schema.config;
|
|
64
|
+
|
|
65
|
+
// 2. Adapt Tremor/Simple format (categories -> series, index -> xAxisKey)
|
|
66
|
+
if (!xAxisKey) {
|
|
67
|
+
if ((schema as any).index) xAxisKey = (schema as any).index;
|
|
68
|
+
else if ((schema as any).category) xAxisKey = (schema as any).category; // Support Pie/Donut category
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!series) {
|
|
72
|
+
if ((schema as any).categories) {
|
|
73
|
+
series = (schema as any).categories.map((cat: string) => ({ dataKey: cat }));
|
|
74
|
+
} else if ((schema as any).value) {
|
|
75
|
+
// Single value adapter (for Pie/Simple charts)
|
|
76
|
+
series = [{ dataKey: (schema as any).value }];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 3. Auto-generate config/colors if missing
|
|
81
|
+
if (!config && series) {
|
|
82
|
+
const colors = (schema as any).colors || ['hsl(var(--chart-1))', 'hsl(var(--chart-2))', 'hsl(var(--chart-3))'];
|
|
83
|
+
const newConfig: ChartConfig = {};
|
|
84
|
+
series.forEach((s: any, idx: number) => {
|
|
85
|
+
newConfig[s.dataKey] = { label: s.dataKey, color: colors[idx % colors.length] };
|
|
86
|
+
});
|
|
87
|
+
config = newConfig;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
chartType: schema.chartType,
|
|
92
|
+
data: schema.data,
|
|
93
|
+
config,
|
|
94
|
+
xAxisKey,
|
|
95
|
+
series,
|
|
96
|
+
className: schema.className
|
|
97
|
+
};
|
|
98
|
+
}, [schema]);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Suspense fallback={<Skeleton className="w-full h-[400px]" />}>
|
|
102
|
+
<LazyAdvancedChart
|
|
103
|
+
chartType={props.chartType}
|
|
104
|
+
data={props.data}
|
|
105
|
+
config={props.config}
|
|
106
|
+
xAxisKey={props.xAxisKey}
|
|
107
|
+
series={props.series}
|
|
108
|
+
className={props.className}
|
|
109
|
+
/>
|
|
110
|
+
</Suspense>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { useState, useEffect } from 'react';
|
|
3
|
+
import { useDataScope, useSchemaContext } from '@object-ui/react';
|
|
4
|
+
import { ChartRenderer } from './ChartRenderer';
|
|
5
|
+
import { ComponentRegistry } from '@object-ui/core';
|
|
6
|
+
|
|
7
|
+
export const ObjectChart = (props: any) => {
|
|
8
|
+
const { schema } = props;
|
|
9
|
+
const context = useSchemaContext();
|
|
10
|
+
const dataSource = props.dataSource || context.dataSource;
|
|
11
|
+
const boundData = useDataScope(schema.bind);
|
|
12
|
+
|
|
13
|
+
const [fetchedData, setFetchedData] = useState<any[]>([]);
|
|
14
|
+
const [loading, setLoading] = useState(false);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
let isMounted = true;
|
|
18
|
+
const fetchData = async () => {
|
|
19
|
+
if (!dataSource || !schema.objectName) return;
|
|
20
|
+
if (isMounted) setLoading(true);
|
|
21
|
+
try {
|
|
22
|
+
// Apply filtering?
|
|
23
|
+
const results = await dataSource.find(schema.objectName, {
|
|
24
|
+
$filter: schema.filter
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let data: any[] = [];
|
|
28
|
+
if (Array.isArray(results)) {
|
|
29
|
+
data = results;
|
|
30
|
+
} else if (results && typeof results === 'object') {
|
|
31
|
+
if (Array.isArray((results as any).value)) {
|
|
32
|
+
data = (results as any).value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (isMounted) {
|
|
37
|
+
setFetchedData(data);
|
|
38
|
+
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error('[ObjectChart] Fetch error:', e);
|
|
41
|
+
} finally {
|
|
42
|
+
if (isMounted) setLoading(false);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
if (schema.objectName && !boundData && !schema.data) {
|
|
47
|
+
fetchData();
|
|
48
|
+
}
|
|
49
|
+
return () => { isMounted = false; };
|
|
50
|
+
}, [schema.objectName, dataSource, boundData, schema.data, schema.filter]);
|
|
51
|
+
|
|
52
|
+
const finalData = boundData || schema.data || fetchedData || [];
|
|
53
|
+
|
|
54
|
+
// Merge data if not provided in schema
|
|
55
|
+
const finalSchema = {
|
|
56
|
+
...schema,
|
|
57
|
+
data: finalData
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (loading && finalData.length === 0) {
|
|
61
|
+
// Return skeleton or loading state?
|
|
62
|
+
// ChartRenderer has suspense/skeleton handling but needs to be triggered.
|
|
63
|
+
// We pass empty data but it might render empty chart.
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return <ChartRenderer {...props} schema={finalSchema} />;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Register it
|
|
70
|
+
ComponentRegistry.register('object-chart', ObjectChart, {
|
|
71
|
+
namespace: 'plugin-charts',
|
|
72
|
+
label: 'Object Chart',
|
|
73
|
+
category: 'view',
|
|
74
|
+
inputs: [
|
|
75
|
+
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
|
|
76
|
+
{ name: 'data', type: 'array', label: 'Data', description: 'Optional static data' },
|
|
77
|
+
{ name: 'filter', type: 'array', label: 'Filter' },
|
|
78
|
+
]
|
|
79
|
+
});
|
package/src/index.test.ts
CHANGED