|
| 1 | +# Architecture: ObjectStack Spec Integration |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This document explains how ObjectUI integrates with `@objectstack/spec` (v0.1.1) as the foundational protocol for all UI components. |
| 6 | + |
| 7 | +## The Inheritance Chain |
| 8 | + |
| 9 | +``` |
| 10 | +@objectstack/spec (v0.1.1) ← The "Highest Law" - Universal Protocol |
| 11 | + ↓ |
| 12 | +UIComponent ← Base interface for all UI components |
| 13 | + ↓ |
| 14 | +BaseSchema (@object-ui/types) ← ObjectUI-specific extensions |
| 15 | + ↓ |
| 16 | +Specific Schemas ← Component implementations |
| 17 | + ↓ |
| 18 | +Component Renderers ← UI implementations |
| 19 | +``` |
| 20 | + |
| 21 | +### 1. UIComponent (@objectstack/spec) |
| 22 | + |
| 23 | +The foundational interface that defines the core protocol for schema-driven UI: |
| 24 | + |
| 25 | +```typescript |
| 26 | +interface UIComponent { |
| 27 | + type: string; // Component type discriminator |
| 28 | + id?: string; // Unique identifier |
| 29 | + props?: Record<string, any>; // Component-specific properties |
| 30 | + children?: SchemaNode | SchemaNode[]; // Child content |
| 31 | + [key: string]: any; // Extensibility |
| 32 | +} |
| 33 | +``` |
| 34 | + |
| 35 | +**Why this is the "highest law":** |
| 36 | +- Defines the universal contract for all UI components |
| 37 | +- Ensures interoperability across the ObjectStack ecosystem |
| 38 | +- Provides the type discriminator pattern |
| 39 | +- Enables JSON serialization |
| 40 | + |
| 41 | +### 2. BaseSchema (@object-ui/types) |
| 42 | + |
| 43 | +Extends `UIComponent` with ObjectUI-specific rendering logic: |
| 44 | + |
| 45 | +```typescript |
| 46 | +interface BaseSchema extends UIComponent { |
| 47 | + // Inherited from UIComponent |
| 48 | + type: string; |
| 49 | + id?: string; |
| 50 | + children?: SchemaNode | SchemaNode[]; |
| 51 | + |
| 52 | + // ObjectUI extensions |
| 53 | + className?: string; // Tailwind CSS classes |
| 54 | + visible?: boolean; // Static visibility |
| 55 | + visibleOn?: string; // Dynamic visibility (expression) |
| 56 | + hidden?: boolean; // Static hiding |
| 57 | + hiddenOn?: string; // Dynamic hiding (expression) |
| 58 | + disabled?: boolean; // Static disabled state |
| 59 | + disabledOn?: string; // Dynamic disabled state (expression) |
| 60 | + |
| 61 | + // Additional ObjectUI properties |
| 62 | + name?: string; |
| 63 | + label?: string; |
| 64 | + description?: string; |
| 65 | + placeholder?: string; |
| 66 | + style?: Record<string, string | number>; |
| 67 | + data?: any; |
| 68 | + body?: SchemaNode | SchemaNode[]; |
| 69 | + testId?: string; |
| 70 | + ariaLabel?: string; |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +### 3. Specific Schemas (e.g., ChartSchema) |
| 75 | + |
| 76 | +Component-specific interfaces that extend `BaseSchema`: |
| 77 | + |
| 78 | +```typescript |
| 79 | +interface ChartSchema extends BaseSchema { |
| 80 | + type: 'chart'; // Type discriminator |
| 81 | + chartType: ChartType; // Chart-specific property |
| 82 | + title?: string; |
| 83 | + description?: string; |
| 84 | + categories?: string[]; |
| 85 | + series: ChartSeries[]; |
| 86 | + height?: string | number; |
| 87 | + showLegend?: boolean; |
| 88 | + showGrid?: boolean; |
| 89 | + animate?: boolean; |
| 90 | + config?: Record<string, any>; |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +## Data Display Components |
| 95 | + |
| 96 | +The following components are defined in `@object-ui/types/data-display`: |
| 97 | + |
| 98 | +| Type | Component | Schema Interface | Key Properties | |
| 99 | +|------|-----------|-----------------|----------------| |
| 100 | +| `alert` | Alert | `AlertSchema` | title, description, variant, icon, dismissible | |
| 101 | +| `statistic` | Metric Card | `StatisticSchema` | label, value, trend, description, icon | |
| 102 | +| `badge` | Badge | `BadgeSchema` | label, variant, icon | |
| 103 | +| `avatar` | Avatar | `AvatarSchema` | src, alt, fallback, size, shape | |
| 104 | +| `list` | List | `ListSchema` | items, ordered, dividers | |
| 105 | +| `table` | Basic Table | `TableSchema` | columns, data, caption, hoverable | |
| 106 | +| `data-table` | Data Grid | `DataTableSchema` | pagination, searchable, rowActions, selectable | |
| 107 | +| `chart` | Chart | `ChartSchema` | chartType, series, categories, showLegend | |
| 108 | +| `timeline` | Timeline | `TimelineSchema` | events, orientation, position | |
| 109 | +| `tree-view` | Tree View | `TreeViewSchema` | data, multiSelect, showLines | |
| 110 | +| `markdown` | Markdown | `MarkdownSchema` | content, sanitize | |
| 111 | +| `html` | Raw HTML | `HtmlSchema` | html | |
| 112 | + |
| 113 | +## Usage Examples |
| 114 | + |
| 115 | +### 1. Simple Component (Compliant with UIComponent) |
| 116 | + |
| 117 | +```json |
| 118 | +{ |
| 119 | + "type": "badge", |
| 120 | + "id": "status-badge", |
| 121 | + "label": "New", |
| 122 | + "variant": "default" |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +### 2. Component with ObjectUI Extensions |
| 127 | + |
| 128 | +```json |
| 129 | +{ |
| 130 | + "type": "alert", |
| 131 | + "id": "welcome-alert", |
| 132 | + "title": "Welcome!", |
| 133 | + "description": "Thank you for using ObjectUI", |
| 134 | + "variant": "default", |
| 135 | + "icon": "info", |
| 136 | + "dismissible": true, |
| 137 | + "visibleOn": "${user.isNewUser}", |
| 138 | + "className": "mb-4" |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +### 3. Complex Component with Children |
| 143 | + |
| 144 | +```json |
| 145 | +{ |
| 146 | + "type": "flex", |
| 147 | + "id": "user-profile", |
| 148 | + "props": { |
| 149 | + "direction": "col", |
| 150 | + "gap": 4 |
| 151 | + }, |
| 152 | + "children": [ |
| 153 | + { |
| 154 | + "type": "avatar", |
| 155 | + "src": "https://github.com/shadcn.png", |
| 156 | + "fallback": "JD", |
| 157 | + "size": "lg" |
| 158 | + }, |
| 159 | + { |
| 160 | + "type": "statistic", |
| 161 | + "label": "Followers", |
| 162 | + "value": "1,234", |
| 163 | + "trend": "up" |
| 164 | + }, |
| 165 | + { |
| 166 | + "type": "badge", |
| 167 | + "label": "Pro Member", |
| 168 | + "variant": "default" |
| 169 | + } |
| 170 | + ] |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +### 4. Data Display with Chart |
| 175 | + |
| 176 | +```json |
| 177 | +{ |
| 178 | + "type": "chart", |
| 179 | + "id": "sales-chart", |
| 180 | + "chartType": "bar", |
| 181 | + "title": "Monthly Sales", |
| 182 | + "categories": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], |
| 183 | + "series": [ |
| 184 | + { |
| 185 | + "name": "Revenue", |
| 186 | + "data": [12000, 15000, 18000, 14000, 22000, 25000], |
| 187 | + "color": "#3b82f6" |
| 188 | + } |
| 189 | + ], |
| 190 | + "showLegend": true, |
| 191 | + "height": 400 |
| 192 | +} |
| 193 | +``` |
| 194 | + |
| 195 | +## Protocol Compliance Rules |
| 196 | + |
| 197 | +When creating or using components: |
| 198 | + |
| 199 | +1. ✅ **MUST** extend from `UIComponent` (directly or indirectly via `BaseSchema`) |
| 200 | +2. ✅ **MUST** include a `type` field (the discriminator) |
| 201 | +3. ✅ **MUST** use the correct type value from the component registry |
| 202 | +4. ✅ **SHOULD** place component-specific properties at the top level (not in props) |
| 203 | +5. ✅ **SHOULD** use `props` for standard HTML attributes (role, aria-*, data-*) |
| 204 | +6. ✅ **SHOULD** support `children` for composable components |
| 205 | +7. ✅ **SHOULD** support `id` for unique identification |
| 206 | +8. ✅ **MAY** use ObjectUI extensions (className, visibleOn, etc.) |
| 207 | + |
| 208 | +### Property Placement Guide |
| 209 | + |
| 210 | +**Component-specific properties** → Top level: |
| 211 | +```json |
| 212 | +{ |
| 213 | + "type": "alert", |
| 214 | + "title": "Welcome", // ✅ Component-specific |
| 215 | + "variant": "default", // ✅ Component-specific |
| 216 | + "dismissible": true // ✅ Component-specific |
| 217 | +} |
| 218 | +``` |
| 219 | + |
| 220 | +**Standard HTML/ARIA attributes** → props object: |
| 221 | +```json |
| 222 | +{ |
| 223 | + "type": "alert", |
| 224 | + "title": "Welcome", |
| 225 | + "props": { |
| 226 | + "role": "alert", // ✅ HTML attribute |
| 227 | + "aria-live": "polite", // ✅ ARIA attribute |
| 228 | + "data-testid": "alert" // ✅ Data attribute |
| 229 | + } |
| 230 | +} |
| 231 | +``` |
| 232 | + |
| 233 | +## Related Packages |
| 234 | + |
| 235 | +- **[@objectstack/spec](../../packages/objectstack-spec)** - Universal UI component specification |
| 236 | +- **[@object-ui/types](../../packages/types)** - ObjectUI protocol extensions |
| 237 | +- **[@object-ui/core](../../packages/core)** - Schema validation and expression engine |
| 238 | +- **[@object-ui/react](../../packages/react)** - React renderer |
| 239 | +- **[@object-ui/components](../../packages/components)** - Shadcn/Tailwind implementation |
| 240 | + |
| 241 | +## References |
| 242 | + |
| 243 | +- [ObjectStack Spec README](../../packages/objectstack-spec/README.md) |
| 244 | +- [Object UI Types README](../../packages/types/README.md) |
| 245 | +- [Data Display Examples](../../packages/types/examples/data-display-examples.json) |
0 commit comments