@object-ui/plugin-charts 0.5.0 → 3.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 +7 -7
- package/CHANGELOG.md +34 -0
- package/dist/{AdvancedChartImpl-DcIHnCct.js → AdvancedChartImpl-BPJDgZhN.js} +429 -398
- package/dist/{ChartImpl-CU5lEzui.js → ChartImpl-C-IeuOgj.js} +2 -2
- package/dist/{index-DgxI83zT.js → index-B49zCCfG.js} +100 -84
- package/dist/index.js +1 -1
- package/dist/index.umd.cjs +12 -12
- package/dist/src/ObjectChart.stories.d.ts +24 -0
- package/package.json +8 -8
- package/src/AdvancedChartImpl.tsx +26 -4
- package/src/ChartImpl.tsx +2 -2
- package/src/ChartRenderer.tsx +2 -2
- package/src/ObjectChart.stories.tsx +104 -0
- package/src/ObjectChart.tsx +8 -3
- package/src/index.tsx +13 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: import('react').ForwardRefExoticComponent<Omit<{
|
|
5
|
+
schema: import('../../core/src').SchemaNode;
|
|
6
|
+
} & Record<string, any>, "ref"> & import('react').RefAttributes<any>>;
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: string;
|
|
9
|
+
};
|
|
10
|
+
tags: string[];
|
|
11
|
+
argTypes: {
|
|
12
|
+
schema: {
|
|
13
|
+
table: {
|
|
14
|
+
disable: true;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
export declare const Default: Story;
|
|
22
|
+
export declare const LineChart: Story;
|
|
23
|
+
export declare const PieChart: Story;
|
|
24
|
+
export declare const AreaChart: Story;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-charts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "3.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": "3.0.0",
|
|
29
|
+
"@object-ui/core": "3.0.0",
|
|
30
|
+
"@object-ui/react": "3.0.0",
|
|
31
|
+
"@object-ui/types": "3.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": "
|
|
39
|
-
"@types/react-dom": "
|
|
40
|
-
"@vitejs/plugin-react": "^5.1.
|
|
38
|
+
"@types/react": "19.2.13",
|
|
39
|
+
"@types/react-dom": "19.2.3",
|
|
40
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
41
41
|
"typescript": "^5.9.3",
|
|
42
42
|
"vite": "^7.3.1",
|
|
43
43
|
"vite-plugin-dts": "^4.5.4"
|
|
@@ -90,6 +90,14 @@ export default function AdvancedChartImpl({
|
|
|
90
90
|
series = [],
|
|
91
91
|
className = '',
|
|
92
92
|
}: AdvancedChartImplProps) {
|
|
93
|
+
const [isMobile, setIsMobile] = React.useState(false);
|
|
94
|
+
|
|
95
|
+
React.useEffect(() => {
|
|
96
|
+
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
97
|
+
checkMobile();
|
|
98
|
+
window.addEventListener('resize', checkMobile);
|
|
99
|
+
return () => window.removeEventListener('resize', checkMobile);
|
|
100
|
+
}, []);
|
|
93
101
|
const ChartComponent = {
|
|
94
102
|
bar: BarChart,
|
|
95
103
|
line: LineChart,
|
|
@@ -140,7 +148,10 @@ export default function AdvancedChartImpl({
|
|
|
140
148
|
return <Cell key={`cell-${index}`} fill={resolveColor(c)} />;
|
|
141
149
|
})}
|
|
142
150
|
</Pie>
|
|
143
|
-
<ChartLegend
|
|
151
|
+
<ChartLegend
|
|
152
|
+
content={<ChartLegendContent nameKey={xAxisKey} />}
|
|
153
|
+
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
154
|
+
/>
|
|
144
155
|
</PieChart>
|
|
145
156
|
</ChartContainer>
|
|
146
157
|
);
|
|
@@ -155,7 +166,10 @@ export default function AdvancedChartImpl({
|
|
|
155
166
|
<PolarAngleAxis dataKey={xAxisKey} />
|
|
156
167
|
<PolarRadiusAxis />
|
|
157
168
|
<ChartTooltip content={<ChartTooltipContent />} />
|
|
158
|
-
<ChartLegend
|
|
169
|
+
<ChartLegend
|
|
170
|
+
content={<ChartLegendContent />}
|
|
171
|
+
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
172
|
+
/>
|
|
159
173
|
{series.map((s: any) => {
|
|
160
174
|
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
|
|
161
175
|
return (
|
|
@@ -185,6 +199,7 @@ export default function AdvancedChartImpl({
|
|
|
185
199
|
name={String(config[xAxisKey]?.label || xAxisKey)}
|
|
186
200
|
tickLine={false}
|
|
187
201
|
axisLine={false}
|
|
202
|
+
interval={isMobile ? Math.ceil(data.length / 5) : 0}
|
|
188
203
|
/>
|
|
189
204
|
<YAxis
|
|
190
205
|
type="number"
|
|
@@ -195,7 +210,10 @@ export default function AdvancedChartImpl({
|
|
|
195
210
|
/>
|
|
196
211
|
<ZAxis type="number" range={[60, 400]} />
|
|
197
212
|
<ChartTooltip content={<ChartTooltipContent />} />
|
|
198
|
-
<ChartLegend
|
|
213
|
+
<ChartLegend
|
|
214
|
+
content={<ChartLegendContent />}
|
|
215
|
+
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
216
|
+
/>
|
|
199
217
|
{series.map((s: any, index: number) => {
|
|
200
218
|
const palette = getPalette();
|
|
201
219
|
const color = resolveColor(config[s.dataKey]?.color || palette[index % palette.length]);
|
|
@@ -222,10 +240,14 @@ export default function AdvancedChartImpl({
|
|
|
222
240
|
tickLine={false}
|
|
223
241
|
tickMargin={10}
|
|
224
242
|
axisLine={false}
|
|
243
|
+
interval={isMobile ? Math.ceil(data.length / 5) : 0}
|
|
225
244
|
tickFormatter={(value) => (value && typeof value === 'string') ? value.slice(0, 3) : value}
|
|
226
245
|
/>
|
|
227
246
|
<ChartTooltip content={<ChartTooltipContent />} />
|
|
228
|
-
<ChartLegend
|
|
247
|
+
<ChartLegend
|
|
248
|
+
content={<ChartLegendContent />}
|
|
249
|
+
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
|
|
250
|
+
/>
|
|
229
251
|
{series.map((s: any) => {
|
|
230
252
|
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
|
|
231
253
|
|
package/src/ChartImpl.tsx
CHANGED
|
@@ -31,9 +31,9 @@ export default function ChartImpl({
|
|
|
31
31
|
color = 'hsl(var(--primary))',
|
|
32
32
|
}: ChartImplProps) {
|
|
33
33
|
return (
|
|
34
|
-
<div className={`p-4 rounded-xl border border-border bg-card/40 backdrop-blur-sm shadow-lg shadow-background/5 ${className}`}>
|
|
34
|
+
<div className={`p-2 sm:p-3 md:p-4 rounded-xl border border-border bg-card/40 backdrop-blur-sm shadow-lg shadow-background/5 ${className}`}>
|
|
35
35
|
<ResponsiveContainer width="100%" height={height}>
|
|
36
|
-
<BarChart data={data} margin={{ top:
|
|
36
|
+
<BarChart data={data} margin={{ top: 10, right: 10, left: 10, bottom: 5 }}>
|
|
37
37
|
<defs>
|
|
38
38
|
<linearGradient id="barGradient" x1="0" y1="0" x2="0" y2="1">
|
|
39
39
|
<stop offset="0%" stopColor={color} stopOpacity={1} />
|
package/src/ChartRenderer.tsx
CHANGED
|
@@ -25,7 +25,7 @@ export interface ChartBarRendererProps {
|
|
|
25
25
|
*/
|
|
26
26
|
export const ChartBarRenderer: React.FC<ChartBarRendererProps> = ({ schema }) => {
|
|
27
27
|
return (
|
|
28
|
-
<Suspense fallback={<Skeleton className="w-full h-[400px]" />}>
|
|
28
|
+
<Suspense fallback={<Skeleton className="w-full h-48 sm:h-64 md:h-80 lg:h-[400px]" />}>
|
|
29
29
|
<LazyChart
|
|
30
30
|
data={schema.data}
|
|
31
31
|
dataKey={schema.dataKey}
|
|
@@ -98,7 +98,7 @@ export const ChartRenderer: React.FC<ChartRendererProps> = ({ schema }) => {
|
|
|
98
98
|
}, [schema]);
|
|
99
99
|
|
|
100
100
|
return (
|
|
101
|
-
<Suspense fallback={<Skeleton className="w-full h-[400px]" />}>
|
|
101
|
+
<Suspense fallback={<Skeleton className="w-full h-48 sm:h-64 md:h-80 lg:h-[400px]" />}>
|
|
102
102
|
<LazyAdvancedChart
|
|
103
103
|
chartType={props.chartType}
|
|
104
104
|
data={props.data}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { SchemaRenderer } from '@object-ui/react';
|
|
3
|
+
import type { BaseSchema } from '@object-ui/types';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Plugins/ObjectChart',
|
|
7
|
+
component: SchemaRenderer,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'padded',
|
|
10
|
+
},
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
argTypes: {
|
|
13
|
+
schema: { table: { disable: true } },
|
|
14
|
+
},
|
|
15
|
+
} satisfies Meta<any>;
|
|
16
|
+
|
|
17
|
+
export default meta;
|
|
18
|
+
type Story = StoryObj<typeof meta>;
|
|
19
|
+
|
|
20
|
+
const renderStory = (args: any) => <SchemaRenderer schema={args as unknown as BaseSchema} />;
|
|
21
|
+
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
render: renderStory,
|
|
24
|
+
args: {
|
|
25
|
+
type: 'chart',
|
|
26
|
+
chartType: 'bar',
|
|
27
|
+
data: [
|
|
28
|
+
{ month: 'Jan', revenue: 4200 },
|
|
29
|
+
{ month: 'Feb', revenue: 3800 },
|
|
30
|
+
{ month: 'Mar', revenue: 5100 },
|
|
31
|
+
{ month: 'Apr', revenue: 6300 },
|
|
32
|
+
{ month: 'May', revenue: 5800 },
|
|
33
|
+
{ month: 'Jun', revenue: 7200 },
|
|
34
|
+
],
|
|
35
|
+
xAxisKey: 'month',
|
|
36
|
+
series: [{ dataKey: 'revenue' }],
|
|
37
|
+
config: {
|
|
38
|
+
revenue: { label: 'Revenue', color: '#3b82f6' },
|
|
39
|
+
},
|
|
40
|
+
} as any,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const LineChart: Story = {
|
|
44
|
+
render: renderStory,
|
|
45
|
+
args: {
|
|
46
|
+
type: 'chart',
|
|
47
|
+
chartType: 'line',
|
|
48
|
+
data: [
|
|
49
|
+
{ month: 'Jan', users: 150, sessions: 520 },
|
|
50
|
+
{ month: 'Feb', users: 210, sessions: 680 },
|
|
51
|
+
{ month: 'Mar', users: 280, sessions: 910 },
|
|
52
|
+
{ month: 'Apr', users: 350, sessions: 1250 },
|
|
53
|
+
{ month: 'May', users: 430, sessions: 1600 },
|
|
54
|
+
{ month: 'Jun', users: 540, sessions: 2050 },
|
|
55
|
+
],
|
|
56
|
+
config: {
|
|
57
|
+
users: { label: 'Active Users', color: '#8b5cf6' },
|
|
58
|
+
sessions: { label: 'Sessions', color: '#ec4899' },
|
|
59
|
+
},
|
|
60
|
+
xAxisKey: 'month',
|
|
61
|
+
series: [{ dataKey: 'users' }, { dataKey: 'sessions' }],
|
|
62
|
+
} as any,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const PieChart: Story = {
|
|
66
|
+
render: renderStory,
|
|
67
|
+
args: {
|
|
68
|
+
type: 'pie-chart',
|
|
69
|
+
data: [
|
|
70
|
+
{ name: 'Desktop', value: 55 },
|
|
71
|
+
{ name: 'Mobile', value: 35 },
|
|
72
|
+
{ name: 'Tablet', value: 10 },
|
|
73
|
+
],
|
|
74
|
+
xAxisKey: 'name',
|
|
75
|
+
series: [{ dataKey: 'value' }],
|
|
76
|
+
config: {
|
|
77
|
+
Desktop: { label: 'Desktop', color: 'hsl(var(--chart-1))' },
|
|
78
|
+
Mobile: { label: 'Mobile', color: 'hsl(var(--chart-2))' },
|
|
79
|
+
Tablet: { label: 'Tablet', color: 'hsl(var(--chart-3))' },
|
|
80
|
+
},
|
|
81
|
+
} as any,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const AreaChart: Story = {
|
|
85
|
+
render: renderStory,
|
|
86
|
+
args: {
|
|
87
|
+
type: 'chart',
|
|
88
|
+
chartType: 'area',
|
|
89
|
+
data: [
|
|
90
|
+
{ date: 'Mon', traffic: 3200 },
|
|
91
|
+
{ date: 'Tue', traffic: 2800 },
|
|
92
|
+
{ date: 'Wed', traffic: 4100 },
|
|
93
|
+
{ date: 'Thu', traffic: 3600 },
|
|
94
|
+
{ date: 'Fri', traffic: 4800 },
|
|
95
|
+
{ date: 'Sat', traffic: 2900 },
|
|
96
|
+
{ date: 'Sun', traffic: 3400 },
|
|
97
|
+
],
|
|
98
|
+
config: {
|
|
99
|
+
traffic: { label: 'Page Views', color: '#06b6d4' },
|
|
100
|
+
},
|
|
101
|
+
xAxisKey: 'date',
|
|
102
|
+
series: [{ dataKey: 'traffic' }],
|
|
103
|
+
} as any,
|
|
104
|
+
};
|
package/src/ObjectChart.tsx
CHANGED
|
@@ -28,8 +28,8 @@ export const ObjectChart = (props: any) => {
|
|
|
28
28
|
if (Array.isArray(results)) {
|
|
29
29
|
data = results;
|
|
30
30
|
} else if (results && typeof results === 'object') {
|
|
31
|
-
if (Array.isArray((results as any).
|
|
32
|
-
data = (results as any).
|
|
31
|
+
if (Array.isArray((results as any).records)) {
|
|
32
|
+
data = (results as any).records;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -70,5 +70,10 @@ export const ObjectChart = (props: any) => {
|
|
|
70
70
|
ComponentRegistry.register('object-chart', ObjectChart, {
|
|
71
71
|
namespace: 'plugin-charts',
|
|
72
72
|
label: 'Object Chart',
|
|
73
|
-
category: 'view'
|
|
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
|
+
]
|
|
74
79
|
});
|
package/src/index.tsx
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { ComponentRegistry } from '@object-ui/core';
|
|
10
10
|
import { ChartBarRenderer, ChartRenderer } from './ChartRenderer';
|
|
11
|
-
import './ObjectChart';
|
|
11
|
+
import { ObjectChart } from './ObjectChart';
|
|
12
12
|
|
|
13
13
|
// Export types for external use
|
|
14
14
|
export type { BarChartSchema } from './types';
|
|
@@ -51,7 +51,18 @@ ComponentRegistry.register(
|
|
|
51
51
|
},
|
|
52
52
|
}
|
|
53
53
|
);
|
|
54
|
-
|
|
54
|
+
// Alias for generic view
|
|
55
|
+
ComponentRegistry.register('chart', ObjectChart, {
|
|
56
|
+
namespace: 'view',
|
|
57
|
+
category: 'view',
|
|
58
|
+
label: 'Chart',
|
|
59
|
+
inputs: [
|
|
60
|
+
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
|
|
61
|
+
{ name: 'type', type: 'string', label: 'Chart Type' },
|
|
62
|
+
{ name: 'categoryField', type: 'string', label: 'Category Field' },
|
|
63
|
+
{ name: 'valueField', type: 'string', label: 'Value Field' },
|
|
64
|
+
]
|
|
65
|
+
});
|
|
55
66
|
// Register the advanced chart component
|
|
56
67
|
ComponentRegistry.register(
|
|
57
68
|
'chart',
|