@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.
@@ -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.5.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.5.0",
29
- "@object-ui/core": "0.5.0",
30
- "@object-ui/react": "0.5.0",
31
- "@object-ui/types": "0.5.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": "^19.2.10",
39
- "@types/react-dom": "^19.2.3",
40
- "@vitejs/plugin-react": "^5.1.3",
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 content={<ChartLegendContent nameKey={xAxisKey} />} />
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 content={<ChartLegendContent />} />
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 content={<ChartLegendContent />} />
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 content={<ChartLegendContent />} />
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: 20, right: 30, left: 20, bottom: 5 }}>
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} />
@@ -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
+ };
@@ -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).value)) {
32
- data = (results as any).value;
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'; // Import for side-effects (registration of object-chart)
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',