Skip to content

Commit 4f0d1ae

Browse files
committed
feat(schema): enhance chart and widget schemas with new properties and definitions
1 parent b5769f8 commit 4f0d1ae

4 files changed

Lines changed: 169 additions & 10 deletions

File tree

packages/spec/src/ui/chart.zod.ts

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,20 @@ export const ChartTypeSchema = z.enum([
1818
'column',
1919
'grouped-bar',
2020
'stacked-bar',
21+
'bi-polar-bar',
2122

2223
// Trend
2324
'line',
2425
'area',
2526
'stacked-area',
2627
'step-line',
28+
'spline',
2729

2830
// Distribution
2931
'pie',
3032
'donut',
3133
'funnel',
34+
'pyramid',
3235

3336
// Relationship
3437
'scatter',
@@ -38,22 +41,28 @@ export const ChartTypeSchema = z.enum([
3841
'treemap',
3942
'sunburst',
4043
'sankey',
44+
'word-cloud',
4145

4246
// Performance
4347
'gauge',
48+
'solid-gauge',
4449
'metric',
4550
'kpi',
51+
'bullet',
4652

4753
// Geo
4854
'choropleth',
4955
'bubble-map',
56+
'gl-map',
5057

5158
// Advanced
5259
'heatmap',
5360
'radar',
5461
'waterfall',
5562
'box-plot',
5663
'violin',
64+
'candlestick',
65+
'stock',
5766

5867
// Tabular
5968
'table',
@@ -62,17 +71,116 @@ export const ChartTypeSchema = z.enum([
6271

6372
export type ChartType = z.infer<typeof ChartTypeSchema>;
6473

74+
/**
75+
* Chart Axis Schema
76+
* Definition for X and Y axes
77+
*/
78+
export const ChartAxisSchema = z.object({
79+
/** Data field to map to this axis */
80+
field: z.string().describe('Data field key'),
81+
82+
/** Axis title */
83+
title: z.string().optional().describe('Axis display title'),
84+
85+
/** Value formatting (d3-format or similar) */
86+
format: z.string().optional().describe('Value format string (e.g., "$0,0.00")'),
87+
88+
/** Axis scale settings */
89+
min: z.number().optional().describe('Minimum value'),
90+
max: z.number().optional().describe('Maximum value'),
91+
stepSize: z.number().optional().describe('Step size for ticks'),
92+
93+
/** Appearance */
94+
showGridLines: z.boolean().default(true),
95+
position: z.enum(['left', 'right', 'top', 'bottom']).optional().describe('Axis position'),
96+
97+
/** Logarithmic scale */
98+
logarithmic: z.boolean().default(false),
99+
});
100+
101+
/**
102+
* Chart Series Schema
103+
* Defines a single data series in the chart
104+
*/
105+
export const ChartSeriesSchema = z.object({
106+
/** Field name for values */
107+
name: z.string().describe('Field name or series identifier'),
108+
109+
/** Display label */
110+
label: z.string().optional().describe('Series display label'),
111+
112+
/** Series type override (combo charts) */
113+
type: ChartTypeSchema.optional().describe('Override chart type for this series'),
114+
115+
/** Specific color */
116+
color: z.string().optional().describe('Series color (hex/rgb/token)'),
117+
118+
/** Stacking group */
119+
stack: z.string().optional().describe('Stack identifier to group series'),
120+
121+
/** Axis binding */
122+
yAxis: z.enum(['left', 'right']).default('left').describe('Bind to specific Y-Axis'),
123+
});
124+
125+
/**
126+
* Chart Annotation Schema
127+
* Static lines or regions to highlight data
128+
*/
129+
export const ChartAnnotationSchema = z.object({
130+
type: z.enum(['line', 'region']).default('line'),
131+
axis: z.enum(['x', 'y']).default('y'),
132+
value: z.union([z.number(), z.string()]).describe('Start value'),
133+
endValue: z.union([z.number(), z.string()]).optional().describe('End value for regions'),
134+
color: z.string().optional(),
135+
label: z.string().optional(),
136+
style: z.enum(['solid', 'dashed', 'dotted']).default('dashed'),
137+
});
138+
139+
/**
140+
* Chart Interaction Schema
141+
*/
142+
export const ChartInteractionSchema = z.object({
143+
tooltips: z.boolean().default(true),
144+
zoom: z.boolean().default(false),
145+
brush: z.boolean().default(false),
146+
clickAction: z.string().optional().describe('Action ID to trigger on click'),
147+
});
148+
65149
/**
66150
* Chart Configuration Base
67151
* Common configuration for all chart types
68152
*/
69153
export const ChartConfigSchema = z.object({
154+
/** Chart Type */
70155
type: ChartTypeSchema,
156+
157+
/** Titles */
71158
title: z.string().optional().describe('Chart title'),
72-
description: z.string().optional().describe('Chart description'),
73-
showLegend: z.boolean().optional().default(true).describe('Display legend'),
74-
showDataLabels: z.boolean().optional().default(false).describe('Display data labels on chart'),
75-
colors: z.array(z.string()).optional().describe('Custom color palette'),
159+
subtitle: z.string().optional().describe('Chart subtitle'),
160+
description: z.string().optional().describe('Accessibility description'),
161+
162+
/** Axes Mapping */
163+
xAxis: ChartAxisSchema.optional().describe('X-Axis configuration'),
164+
yAxis: z.array(ChartAxisSchema).optional().describe('Y-Axis configuration (support dual axis)'),
165+
166+
/** Series Configuration */
167+
series: z.array(ChartSeriesSchema).optional().describe('Defined series configuration'),
168+
169+
/** Appearance */
170+
colors: z.array(z.string()).optional().describe('Color palette'),
171+
height: z.number().optional().describe('Fixed height in pixels'),
172+
173+
/** Components */
174+
showLegend: z.boolean().default(true).describe('Display legend'),
175+
showDataLabels: z.boolean().default(false).describe('Display data labels'),
176+
177+
/** Annotations & Reference Lines */
178+
annotations: z.array(ChartAnnotationSchema).optional(),
179+
180+
/** Interactions */
181+
interaction: ChartInteractionSchema.optional(),
76182
});
77183

78184
export type ChartConfig = z.infer<typeof ChartConfigSchema>;
185+
export type ChartAxis = z.infer<typeof ChartAxisSchema>;
186+
export type ChartSeries = z.infer<typeof ChartSeriesSchema>;

packages/spec/src/ui/component.zod.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ export const PageCardProps = z.object({
3333
title: z.string().optional(),
3434
bordered: z.boolean().default(true),
3535
actions: z.array(z.string()).optional(),
36-
children: z.array(z.any()).describe('Card content')
36+
/** Slot for nested content in the Card body */
37+
body: z.array(z.any()).optional().describe('Card content components (slot)'),
38+
/** Slot for footer content */
39+
footer: z.array(z.any()).optional().describe('Card footer components (slot)'),
3740
});
3841

3942
/**

packages/spec/src/ui/page.zod.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,32 @@ export const PageComponentSchema = z.object({
4343
label: z.string().optional(),
4444
properties: z.record(z.string(), z.any()).describe('Component props passed to the widget. See component.zod.ts for schemas.'),
4545

46+
/**
47+
* Event Handlers
48+
* Map event names to Action expressions.
49+
* "onClick": "set_variable('userId', $event.id)"
50+
* "onRowSelect": "navigate_to('page_detail', { id: $event.id })"
51+
*/
52+
events: z.record(z.string(), z.string()).optional().describe('Event handlers map'),
53+
54+
/** Appearance */
55+
style: z.record(z.string(), z.string()).optional().describe('Inline styles or utility classes'),
56+
className: z.string().optional().describe('CSS class names'),
57+
4658
/** Visibility Rule */
4759
visibility: z.string().optional().describe('Visibility filter/formula')
4860
});
4961

62+
/**
63+
* Page Variable Schema
64+
* Defines local state for the page.
65+
*/
66+
export const PageVariableSchema = z.object({
67+
name: z.string().describe('Variable name'),
68+
type: z.enum(['string', 'number', 'boolean', 'object', 'array']).default('string'),
69+
defaultValue: z.any().optional(),
70+
});
71+
5072
/**
5173
* Page Schema
5274
* Defines a composition of components for a specific context (Record, Home, App).
@@ -74,6 +96,9 @@ export const PageSchema = z.object({
7496
/** Page Type */
7597
type: z.enum(['record', 'home', 'app', 'utility']).default('record'),
7698

99+
/** Page State Definitions */
100+
variables: z.array(PageVariableSchema).optional().describe('Local page state variables'),
101+
77102
/** Context */
78103
object: z.string().optional().describe('Bound object (for Record pages)'),
79104

packages/spec/src/ui/widget.zod.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,32 @@ export type WidgetProperty = z.infer<typeof WidgetPropertySchema>;
236236
* }
237237
* ```
238238
*/
239+
/**
240+
* Widget Source Schema
241+
* Defines how the widget code is loaded.
242+
*/
243+
export const WidgetSourceSchema = z.discriminatedUnion('type', [
244+
// NPM Registry (standard)
245+
z.object({
246+
type: z.literal('npm'),
247+
packageName: z.string().describe('NPM package name'),
248+
version: z.string().default('latest'),
249+
exportName: z.string().optional().describe('Named export (default: default)'),
250+
}),
251+
// Module Federation (Remote)
252+
z.object({
253+
type: z.literal('remote'),
254+
url: z.string().url().describe('Remote entry URL (.js)'),
255+
moduleName: z.string().describe('Exposed module name'),
256+
scope: z.string().describe('Remote scope name'),
257+
}),
258+
// Inline Code (Simple scripts)
259+
z.object({
260+
type: z.literal('inline'),
261+
code: z.string().describe('JavaScript code body'),
262+
}),
263+
]);
264+
239265
export const WidgetManifestSchema = z.object({
240266
/**
241267
* Widget identifier (snake_case)
@@ -300,12 +326,9 @@ export const WidgetManifestSchema = z.object({
300326

301327
/**
302328
* Widget implementation
303-
* URL to component or inline code
329+
* Defines how to load the widget code
304330
*/
305-
implementation: z.object({
306-
type: z.enum(['url', 'inline', 'module']).describe('Implementation type'),
307-
source: z.string().describe('Source URL, inline code, or module path'),
308-
}).optional().describe('Widget implementation'),
331+
implementation: WidgetSourceSchema.optional().describe('Widget implementation source'),
309332

310333
/**
311334
* Widget dependencies

0 commit comments

Comments
 (0)