@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.
Files changed (36) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +24 -0
  3. package/dist/{AdvancedChartImpl-DmHTUUVD.js → AdvancedChartImpl-DxaZtNlE.js} +1214 -1206
  4. package/dist/{BarChart-XZkfLmcU.js → BarChart-BQS4sYHd.js} +3859 -3766
  5. package/dist/{ChartImpl-0VlpsMWG.js → ChartImpl-BaXisyXJ.js} +6 -6
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js +207 -63
  8. package/dist/index.umd.cjs +19 -19
  9. package/dist/{jsx-runtime-C8d0IhUE.js → jsx-runtime-Caia9pQX.js} +1 -1
  10. package/dist/packages/plugin-charts/src/ObjectChart.d.ts +31 -0
  11. package/package.json +34 -10
  12. package/.turbo/turbo-build.log +0 -26
  13. package/dist/src/ObjectChart.d.ts +0 -12
  14. package/examples/chart-examples.ts +0 -54
  15. package/src/AdvancedChartImpl.tsx +0 -309
  16. package/src/ChartContainerImpl.tsx +0 -353
  17. package/src/ChartImpl.tsx +0 -91
  18. package/src/ChartRenderer.tsx +0 -112
  19. package/src/ObjectChart.stories.tsx +0 -104
  20. package/src/ObjectChart.tsx +0 -145
  21. package/src/__tests__/ObjectChart.aggregation.test.ts +0 -166
  22. package/src/__tests__/ObjectChart.dataFetch.test.tsx +0 -303
  23. package/src/index.test.ts +0 -136
  24. package/src/index.tsx +0 -172
  25. package/src/types.ts +0 -68
  26. package/tsconfig.json +0 -17
  27. package/vite.config.ts +0 -61
  28. package/vitest.config.ts +0 -13
  29. package/vitest.setup.ts +0 -1
  30. /package/dist/{src → packages/plugin-charts/src}/AdvancedChartImpl.d.ts +0 -0
  31. /package/dist/{src → packages/plugin-charts/src}/ChartContainerImpl.d.ts +0 -0
  32. /package/dist/{src → packages/plugin-charts/src}/ChartImpl.d.ts +0 -0
  33. /package/dist/{src → packages/plugin-charts/src}/ChartRenderer.d.ts +0 -0
  34. /package/dist/{src → packages/plugin-charts/src}/ObjectChart.stories.d.ts +0 -0
  35. /package/dist/{src → packages/plugin-charts/src}/index.d.ts +0 -0
  36. /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.5",
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
- "recharts": "^3.8.0",
28
- "@object-ui/components": "3.1.5",
29
- "@object-ui/core": "3.1.5",
30
- "@object-ui/react": "3.1.5",
31
- "@object-ui/types": "3.1.5"
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": "^5.9.3",
42
- "vite": "^8.0.1",
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",
@@ -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
- vite v8.0.1 building client environment for production...
6
- 
7
- rendering chunks...
8
- 
9
- [vite:dts] Start generate declaration files...
10
- [vite:dts] Declaration files built in 29474ms.
11
- 
12
- computing gzip size...
13
- dist/ChartImpl-0VlpsMWG.js 3.70 kB │ gzip: 1.16 kB
14
- [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugin `vite:dts`. See https://rolldown.rs/options/checks#plugintimings for more details.
15
- 
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
- 
22
- rendering chunks...
23
- computing gzip size...
24
- dist/index.umd.cjs 498.91 kB │ gzip: 143.06 kB
25
-
26
- ✓ built in 34.99s
@@ -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
- }