Skip to content

Commit 4406e9b

Browse files
Copilothotlong
andcommitted
feat(ui): add InterfaceSchema, RecordReviewConfig, content elements, and per-element data binding
Phase A: Interface Foundation (v3.2) — Airtable Interface Parity - Add InterfaceSchema as self-contained, shareable, multi-page application surface - Add RecordReviewConfigSchema for sequential record review/approval pages - Add content elements (element:text, element:number, element:image, element:divider) to PageComponentType - Add ElementDataSourceSchema for per-element data binding on PageComponentSchema - Add ElementTextPropsSchema, ElementNumberPropsSchema, ElementImagePropsSchema to component.zod.ts - Update ComponentPropsMap with new element types - Export new interface module from src/ui/index.ts - Add comprehensive tests (57 tests across all new schemas) Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 4430d13 commit 4406e9b

5 files changed

Lines changed: 979 additions & 2 deletions

File tree

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

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,45 @@ export const AIChatWindowProps = z.object({
128128
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),
129129
});
130130

131+
/**
132+
* ----------------------------------------------------------------------
133+
* 3. Content Element Components (Airtable Interface Parity)
134+
* ----------------------------------------------------------------------
135+
*/
136+
137+
export const ElementTextPropsSchema = z.object({
138+
content: z.string().describe('Text or Markdown content'),
139+
variant: z.enum(['heading', 'subheading', 'body', 'caption'])
140+
.optional().default('body').describe('Text style variant'),
141+
align: z.enum(['left', 'center', 'right'])
142+
.optional().default('left').describe('Text alignment'),
143+
/** ARIA accessibility */
144+
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),
145+
});
146+
147+
export const ElementNumberPropsSchema = z.object({
148+
object: z.string().describe('Source object'),
149+
field: z.string().optional().describe('Field to aggregate'),
150+
aggregate: z.enum(['count', 'sum', 'avg', 'min', 'max'])
151+
.describe('Aggregation function'),
152+
filter: z.any().optional().describe('Filter criteria'),
153+
format: z.enum(['number', 'currency', 'percent']).optional().describe('Number display format'),
154+
prefix: z.string().optional().describe('Prefix text (e.g. "$")'),
155+
suffix: z.string().optional().describe('Suffix text (e.g. "%")'),
156+
/** ARIA accessibility */
157+
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),
158+
});
159+
160+
export const ElementImagePropsSchema = z.object({
161+
src: z.string().describe('Image URL or attachment field'),
162+
alt: z.string().optional().describe('Alt text for accessibility'),
163+
fit: z.enum(['cover', 'contain', 'fill'])
164+
.optional().default('cover').describe('Image object-fit mode'),
165+
height: z.number().optional().describe('Fixed height in pixels'),
166+
/** ARIA accessibility */
167+
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),
168+
});
169+
131170
/**
132171
* ----------------------------------------------------------------------
133172
* Component Props Map
@@ -164,7 +203,13 @@ export const ComponentPropsMap = {
164203

165204
// AI
166205
'ai:chat_window': AIChatWindowProps,
167-
'ai:suggestion': z.object({ context: z.string().optional() })
206+
'ai:suggestion': z.object({ context: z.string().optional() }),
207+
208+
// Content Elements
209+
'element:text': ElementTextPropsSchema,
210+
'element:number': ElementNumberPropsSchema,
211+
'element:image': ElementImagePropsSchema,
212+
'element:divider': EmptyProps,
168213
} as const;
169214

170215
/**

packages/spec/src/ui/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ export * from './keyboard.zod';
2828
export * from './animation.zod';
2929
export * from './notification.zod';
3030
export * from './dnd.zod';
31+
export * from './interface.zod';

0 commit comments

Comments
 (0)