From e41d08d40c8dd7bd2aa5684f72202c03df039b93 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 11:32:24 +0000 Subject: [PATCH 1/4] Add JSON component conversion task list --- docs/JSON_COMPONENT_CONVERSION_TASKS.md | 95 +++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 docs/JSON_COMPONENT_CONVERSION_TASKS.md diff --git a/docs/JSON_COMPONENT_CONVERSION_TASKS.md b/docs/JSON_COMPONENT_CONVERSION_TASKS.md new file mode 100644 index 0000000..f312ed4 --- /dev/null +++ b/docs/JSON_COMPONENT_CONVERSION_TASKS.md @@ -0,0 +1,95 @@ +# JSON Component Conversion Tasks + +This task list captures the next steps for expanding JSON UI coverage, split between **component migrations** and **framework enablers**. + +## Component Migration Tasks (Planned → Supported) + +### Input Components +- [ ] **DatePicker** + - Add `DatePicker` to `ComponentType` in `src/types/json-ui.ts`. + - Register `DatePicker` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **FileUpload** + - Add `FileUpload` to `ComponentType` in `src/types/json-ui.ts`. + - Register `FileUpload` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. + +### Display Components +- [ ] **CircularProgress** + - Add `CircularProgress` to `ComponentType` in `src/types/json-ui.ts`. + - Register `CircularProgress` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **Divider** + - Add `Divider` to `ComponentType` in `src/types/json-ui.ts`. + - Register `Divider` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **ProgressBar** + - Add `ProgressBar` to `ComponentType` in `src/types/json-ui.ts`. + - Register `ProgressBar` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. + +### Navigation Components +- [ ] **Breadcrumb** + - Decide whether JSON should map to `BreadcrumbNav` (atoms) or `Breadcrumb` (molecules). + - Align props and bindings to a single JSON-friendly surface. + - Register a single `Breadcrumb` entry and set status to `supported` in `json-components-registry.json`. + +### Feedback Components +- [ ] **ErrorBadge** + - Add `ErrorBadge` to `ComponentType` in `src/types/json-ui.ts`. + - Register `ErrorBadge` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **Notification** + - Add `Notification` to `ComponentType` in `src/types/json-ui.ts`. + - Register `Notification` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **StatusIcon** + - Add `StatusIcon` to `ComponentType` in `src/types/json-ui.ts`. + - Register `StatusIcon` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. + +### Data Components +- [ ] **DataList** + - Add `DataList` to `ComponentType` in `src/types/json-ui.ts`. + - Register `DataList` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **DataTable** + - Add `DataTable` to `ComponentType` in `src/types/json-ui.ts`. + - Register `DataTable` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **MetricCard** + - Add `MetricCard` to `ComponentType` in `src/types/json-ui.ts`. + - Register `MetricCard` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. +- [ ] **Timeline** + - Add `Timeline` to `ComponentType` in `src/types/json-ui.ts`. + - Register `Timeline` in `src/lib/json-ui/component-registry.tsx`. + - Add metadata/defaults to `src/lib/component-definitions.ts`. + - Flip status to `supported` in `json-components-registry.json`. + +## Framework Enablers + +- [ ] **Event binding extensions** + - Expand event/action coverage to support richer interactions via JSON expressions. + - Confirm compatibility with existing `expression` and `valueTemplate` handling. +- [ ] **State binding system** + - Add support for stateful bindings needed by interactive components. + - Document and enforce which components require state binding. +- [ ] **JSON-friendly wrappers** + - Create wrapper components for hook-heavy/side-effect components. + - Register wrappers in the JSON registry instead of direct usage. +- [ ] **Registry normalization** + - Resolve duplicate component entries (e.g., multiple `Breadcrumb` variants) in `json-components-registry.json`. +- [ ] **Showcase schema coverage** + - Add JSON schema examples for each newly supported component to keep demos current. From 3fe02ed098b90f0d787f9b0d28c452ebd34efbd1 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 11:35:57 +0000 Subject: [PATCH 2/4] Add JSON UI support for data atoms --- json-components-registry.json | 12 +-- src/components/JSONUIShowcasePage.tsx | 6 ++ src/components/atoms/DataList.tsx | 23 ++++- src/lib/component-definitions.ts | 69 +++++++++++++ src/lib/json-ui/component-registry.ts | 14 ++- src/schemas/page-schemas.ts | 138 ++++++++++++++++++++++++++ src/types/json-ui.ts | 1 + 7 files changed, 251 insertions(+), 12 deletions(-) diff --git a/json-components-registry.json b/json-components-registry.json index bb68d7b..e3f8c9c 100644 --- a/json-components-registry.json +++ b/json-components-registry.json @@ -1219,7 +1219,7 @@ "category": "data", "canHaveChildren": false, "description": "Styled data list", - "status": "planned", + "status": "supported", "source": "atoms" }, { @@ -1238,7 +1238,7 @@ "category": "data", "canHaveChildren": false, "description": "Advanced data table with sorting and filtering", - "status": "planned", + "status": "supported", "source": "atoms" }, { @@ -1304,7 +1304,7 @@ "category": "data", "canHaveChildren": false, "description": "Metric display card", - "status": "planned", + "status": "supported", "source": "atoms" }, { @@ -1369,7 +1369,7 @@ "category": "data", "canHaveChildren": false, "description": "Timeline visualization", - "status": "planned", + "status": "supported", "source": "atoms" }, { @@ -2043,8 +2043,8 @@ ], "statistics": { "total": 219, - "supported": 150, - "planned": 14, + "supported": 154, + "planned": 10, "jsonCompatible": 14, "maybeJsonCompatible": 41, "byCategory": { diff --git a/src/components/JSONUIShowcasePage.tsx b/src/components/JSONUIShowcasePage.tsx index 2b92f00..1cd4c08 100644 --- a/src/components/JSONUIShowcasePage.tsx +++ b/src/components/JSONUIShowcasePage.tsx @@ -3,6 +3,7 @@ import { AtomicComponentDemo } from '@/components/AtomicComponentDemo' import { DashboardDemoPage } from '@/components/DashboardDemoPage' import { PageRenderer } from '@/lib/json-ui/page-renderer' import { hydrateSchema } from '@/schemas/schema-loader' +import { dataComponentsDemoSchema } from '@/schemas/page-schemas' import todoListJson from '@/schemas/todo-list.json' import newMoleculesShowcaseJson from '@/schemas/new-molecules-showcase.json' @@ -25,6 +26,7 @@ export function JSONUIShowcasePage() { Atomic Components New Molecules + Data Components JSON Dashboard JSON Todo List @@ -38,6 +40,10 @@ export function JSONUIShowcasePage() { + + + + diff --git a/src/components/atoms/DataList.tsx b/src/components/atoms/DataList.tsx index c12db88..109cb41 100644 --- a/src/components/atoms/DataList.tsx +++ b/src/components/atoms/DataList.tsx @@ -3,10 +3,11 @@ import { cn } from '@/lib/utils' export interface DataListProps { items: any[] - renderItem: (item: any, index: number) => ReactNode + renderItem?: (item: any, index: number) => ReactNode emptyMessage?: string className?: string itemClassName?: string + itemKey?: string } export function DataList({ @@ -15,6 +16,7 @@ export function DataList({ emptyMessage = 'No items', className, itemClassName, + itemKey, }: DataListProps) { if (items.length === 0) { return ( @@ -24,11 +26,28 @@ export function DataList({ ) } + const renderFallbackItem = (item: any) => { + if (itemKey && item && typeof item === 'object') { + const value = item[itemKey] + if (value !== undefined && value !== null) { + return typeof value === 'string' || typeof value === 'number' + ? value + : JSON.stringify(value) + } + } + + if (typeof item === 'string' || typeof item === 'number') { + return item + } + + return JSON.stringify(item) + } + return (
{items.map((item, index) => (
- {renderItem(item, index)} + {renderItem ? renderItem(item, index) : renderFallbackItem(item)}
))}
diff --git a/src/lib/component-definitions.ts b/src/lib/component-definitions.ts index 8093398..f5d9e36 100644 --- a/src/lib/component-definitions.ts +++ b/src/lib/component-definitions.ts @@ -264,6 +264,17 @@ export const componentDefinitions: ComponentDefinition[] = [ icon: 'List', defaultProps: { items: [], emptyMessage: 'No items' } }, + { + type: 'DataList', + label: 'Data List', + category: 'data', + icon: 'List', + defaultProps: { + items: ['Daily summary', 'New signups', 'Pending approvals'], + emptyMessage: 'No updates', + itemClassName: 'rounded-md border border-border bg-card/50 px-4 py-2' + } + }, { type: 'Table', label: 'Table', @@ -271,6 +282,25 @@ export const componentDefinitions: ComponentDefinition[] = [ icon: 'Table', defaultProps: { data: [], columns: [] } }, + { + type: 'DataTable', + label: 'Data Table', + category: 'data', + icon: 'Table', + defaultProps: { + columns: [ + { key: 'name', header: 'Name' }, + { key: 'status', header: 'Status' }, + { key: 'owner', header: 'Owner' }, + ], + data: [ + { name: 'Launch Plan', status: 'In Progress', owner: 'Avery' }, + { name: 'Design Review', status: 'Scheduled', owner: 'Jordan' }, + { name: 'QA Checklist', status: 'Done', owner: 'Riley' }, + ], + emptyMessage: 'No records available', + } + }, { type: 'KeyValue', label: 'Key Value', @@ -285,6 +315,45 @@ export const componentDefinitions: ComponentDefinition[] = [ icon: 'ChartBar', defaultProps: { title: 'Metric', value: '0' } }, + { + type: 'MetricCard', + label: 'Metric Card', + category: 'data', + icon: 'ChartBar', + defaultProps: { + label: 'Active Users', + value: '1,248', + trend: { value: 12.4, direction: 'up' }, + } + }, + { + type: 'Timeline', + label: 'Timeline', + category: 'data', + icon: 'Clock', + defaultProps: { + items: [ + { + title: 'Planning', + description: 'Finalize milestones', + timestamp: 'Mon 9:00 AM', + status: 'completed', + }, + { + title: 'Execution', + description: 'Kick off delivery', + timestamp: 'Tue 11:00 AM', + status: 'current', + }, + { + title: 'Review', + description: 'Collect feedback', + timestamp: 'Wed 3:00 PM', + status: 'pending', + }, + ], + } + }, // Custom Components { type: 'DataCard', diff --git a/src/lib/json-ui/component-registry.ts b/src/lib/json-ui/component-registry.ts index 3e53dfe..507a5d1 100644 --- a/src/lib/json-ui/component-registry.ts +++ b/src/lib/json-ui/component-registry.ts @@ -136,10 +136,16 @@ export const shadcnComponents: UIComponentRegistry = { AvatarImage, } -export const atomComponents: UIComponentRegistry = buildRegistryFromNames( - atomRegistryNames, - AtomComponents as Record> -) +export const atomComponents: UIComponentRegistry = { + ...buildRegistryFromNames( + atomRegistryNames, + AtomComponents as Record> + ), + DataList: (AtomComponents as Record>).DataList, + DataTable: (AtomComponents as Record>).DataTable, + MetricCard: (AtomComponents as Record>).MetricCard, + Timeline: (AtomComponents as Record>).Timeline, +} export const moleculeComponents: UIComponentRegistry = buildRegistryFromNames( moleculeRegistryNames, diff --git a/src/schemas/page-schemas.ts b/src/schemas/page-schemas.ts index 46ceb50..68299c8 100644 --- a/src/schemas/page-schemas.ts +++ b/src/schemas/page-schemas.ts @@ -73,3 +73,141 @@ export const stateBindingsDemoSchema: PageSchema = { }, ], } + +export const dataComponentsDemoSchema: PageSchema = { + id: 'data-components-demo', + name: 'Data Components Demo', + layout: { + type: 'single', + }, + dataSources: [ + { + id: 'metricCards', + type: 'static', + defaultValue: [ + { label: 'Active Users', value: 1248, trend: { value: 12.4, direction: 'up' } }, + { label: 'Churn Rate', value: '3.2%', trend: { value: 1.1, direction: 'down' } }, + { label: 'Net Revenue', value: '$48.3k', trend: { value: 6.8, direction: 'up' } }, + ], + }, + { + id: 'tableColumns', + type: 'static', + defaultValue: [ + { key: 'initiative', header: 'Initiative' }, + { key: 'owner', header: 'Owner' }, + { key: 'status', header: 'Status' }, + ], + }, + { + id: 'tableRows', + type: 'static', + defaultValue: [ + { initiative: 'Landing Page', owner: 'Avery', status: 'In Progress' }, + { initiative: 'Retention Emails', owner: 'Jordan', status: 'Review' }, + { initiative: 'Billing Update', owner: 'Riley', status: 'Done' }, + ], + }, + { + id: 'listItems', + type: 'static', + defaultValue: ['Prepare briefing deck', 'Confirm stakeholder approvals', 'Publish roadmap update'], + }, + { + id: 'timelineItems', + type: 'static', + defaultValue: [ + { + title: 'Kickoff', + description: 'Align on scope and milestones', + timestamp: 'Mon 9:00 AM', + status: 'completed', + }, + { + title: 'Execution', + description: 'Deliver initial workstream', + timestamp: 'Tue 11:00 AM', + status: 'current', + }, + { + title: 'Review', + description: 'Stakeholder walkthrough', + timestamp: 'Thu 3:00 PM', + status: 'pending', + }, + ], + }, + ], + components: [ + { + id: 'data-components-root', + type: 'div', + props: { + className: 'space-y-6 rounded-lg border border-border bg-card p-6', + }, + children: [ + { + id: 'data-components-title', + type: 'Heading', + props: { + className: 'text-xl font-semibold', + children: 'Data Components Showcase', + }, + }, + { + id: 'data-components-metrics-grid', + type: 'div', + props: { + className: 'grid gap-4 md:grid-cols-3', + }, + loop: { + source: 'metricCards', + itemVar: 'metricCard', + }, + children: [ + { + id: 'data-components-metric-card', + type: 'MetricCard', + bindings: { + label: { sourceType: 'bindings', source: 'metricCard', path: 'label' }, + value: { sourceType: 'bindings', source: 'metricCard', path: 'value' }, + trend: { sourceType: 'bindings', source: 'metricCard', path: 'trend' }, + }, + }, + ], + }, + { + id: 'data-components-table', + type: 'DataTable', + props: { + className: 'bg-background', + emptyMessage: 'No initiatives found', + }, + bindings: { + columns: { source: 'tableColumns', sourceType: 'data' }, + data: { source: 'tableRows', sourceType: 'data' }, + }, + }, + { + id: 'data-components-list', + type: 'DataList', + props: { + className: 'space-y-3', + itemClassName: 'rounded-md border border-border bg-card/50 px-4 py-2 text-sm', + emptyMessage: 'No action items', + }, + bindings: { + items: { source: 'listItems', sourceType: 'data' }, + }, + }, + { + id: 'data-components-timeline', + type: 'Timeline', + bindings: { + items: { source: 'timelineItems', sourceType: 'data' }, + }, + }, + ], + }, + ], +} diff --git a/src/types/json-ui.ts b/src/types/json-ui.ts index f3ce4c3..5bed643 100644 --- a/src/types/json-ui.ts +++ b/src/types/json-ui.ts @@ -7,6 +7,7 @@ export type ComponentType = | 'Link' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton' | 'Alert' | 'InfoBox' | 'EmptyState' | 'StatusBadge' | 'Table' | 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar' + | 'DataList' | 'DataTable' | 'MetricCard' | 'Timeline' | 'AppBranding' | 'LabelWithBadge' | 'EmptyEditorState' | 'LoadingFallback' | 'LoadingState' | 'NavigationGroupHeader' export type ActionType = From 0d82406e5f8ddb0d9b701574977c8c2e291de9d6 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 11:38:50 +0000 Subject: [PATCH 3/4] Add JSON UI support for feedback atoms --- json-components-registry.json | 6 +- src/components/JSONUIShowcasePage.tsx | 6 ++ src/lib/component-definitions.ts | 118 ++++++++++++++++++++++++++ src/schemas/page-schemas.ts | 114 +++++++++++++++++++++++++ src/types/json-ui.ts | 1 + 5 files changed, 242 insertions(+), 3 deletions(-) diff --git a/json-components-registry.json b/json-components-registry.json index bb68d7b..100f715 100644 --- a/json-components-registry.json +++ b/json-components-registry.json @@ -1088,7 +1088,7 @@ "category": "feedback", "canHaveChildren": false, "description": "Error state badge", - "status": "planned", + "status": "supported", "source": "atoms" }, { @@ -1164,7 +1164,7 @@ "category": "feedback", "canHaveChildren": true, "description": "Toast notification", - "status": "planned", + "status": "supported", "source": "atoms" }, { @@ -1201,7 +1201,7 @@ "category": "feedback", "canHaveChildren": false, "description": "Status indicator icon", - "status": "planned", + "status": "supported", "source": "atoms" }, { diff --git a/src/components/JSONUIShowcasePage.tsx b/src/components/JSONUIShowcasePage.tsx index 2b92f00..ad511da 100644 --- a/src/components/JSONUIShowcasePage.tsx +++ b/src/components/JSONUIShowcasePage.tsx @@ -3,6 +3,7 @@ import { AtomicComponentDemo } from '@/components/AtomicComponentDemo' import { DashboardDemoPage } from '@/components/DashboardDemoPage' import { PageRenderer } from '@/lib/json-ui/page-renderer' import { hydrateSchema } from '@/schemas/schema-loader' +import { feedbackAtomsDemoSchema } from '@/schemas/page-schemas' import todoListJson from '@/schemas/todo-list.json' import newMoleculesShowcaseJson from '@/schemas/new-molecules-showcase.json' @@ -24,6 +25,7 @@ export function JSONUIShowcasePage() { Atomic Components + Feedback Atoms New Molecules JSON Dashboard JSON Todo List @@ -34,6 +36,10 @@ export function JSONUIShowcasePage() { + + + + diff --git a/src/lib/component-definitions.ts b/src/lib/component-definitions.ts index 8093398..d9d8c71 100644 --- a/src/lib/component-definitions.ts +++ b/src/lib/component-definitions.ts @@ -7,6 +7,23 @@ export interface ComponentDefinition { icon: string defaultProps?: Record canHaveChildren?: boolean + props?: ComponentPropDefinition[] + events?: ComponentEventDefinition[] +} + +export interface ComponentPropDefinition { + name: string + type: string + description: string + required?: boolean + defaultValue?: string + options?: string[] + supportsBinding?: boolean +} + +export interface ComponentEventDefinition { + name: string + description: string } export const componentDefinitions: ComponentDefinition[] = [ @@ -256,6 +273,107 @@ export const componentDefinitions: ComponentDefinition[] = [ icon: 'Circle', defaultProps: { status: 'active', children: 'Active' } }, + { + type: 'ErrorBadge', + label: 'Error Badge', + category: 'feedback', + icon: 'WarningCircle', + defaultProps: { count: 3, variant: 'destructive', size: 'md' }, + props: [ + { + name: 'count', + type: 'number', + description: 'Number of errors to display. Hidden when set to 0.', + required: true, + supportsBinding: true, + }, + { + name: 'variant', + type: 'string', + description: 'Visual variant for the badge.', + defaultValue: 'destructive', + options: ['default', 'destructive'], + }, + { + name: 'size', + type: 'string', + description: 'Badge size.', + defaultValue: 'md', + options: ['sm', 'md'], + }, + ], + }, + { + type: 'Notification', + label: 'Notification', + category: 'feedback', + icon: 'Info', + defaultProps: { type: 'info', title: 'Notification', message: 'Details go here.' }, + props: [ + { + name: 'type', + type: 'string', + description: 'Notification style variant.', + required: true, + options: ['info', 'success', 'warning', 'error'], + }, + { + name: 'title', + type: 'string', + description: 'Primary notification title.', + required: true, + supportsBinding: true, + }, + { + name: 'message', + type: 'string', + description: 'Optional supporting message text.', + supportsBinding: true, + }, + { + name: 'className', + type: 'string', + description: 'Optional custom classes for spacing or layout tweaks.', + }, + ], + events: [ + { + name: 'onClose', + description: 'Fires when the close button is clicked. Bind to dismiss or trigger an action.', + }, + ], + }, + { + type: 'StatusIcon', + label: 'Status Icon', + category: 'feedback', + icon: 'CheckCircle', + defaultProps: { type: 'saved', size: 14, animate: false }, + props: [ + { + name: 'type', + type: 'string', + description: 'Status icon style.', + required: true, + supportsBinding: true, + options: ['saved', 'synced'], + }, + { + name: 'size', + type: 'number', + description: 'Icon size in pixels.', + defaultValue: '14', + supportsBinding: true, + }, + { + name: 'animate', + type: 'boolean', + description: 'Applies entry animation when true.', + defaultValue: 'false', + supportsBinding: true, + }, + ], + }, // Data Components { type: 'List', diff --git a/src/schemas/page-schemas.ts b/src/schemas/page-schemas.ts index 46ceb50..025fb26 100644 --- a/src/schemas/page-schemas.ts +++ b/src/schemas/page-schemas.ts @@ -73,3 +73,117 @@ export const stateBindingsDemoSchema: PageSchema = { }, ], } + +export const feedbackAtomsDemoSchema: PageSchema = { + id: 'feedback-atoms-demo', + name: 'Feedback Atoms Demo', + layout: { + type: 'single', + }, + dataSources: [ + { + id: 'errorCount', + type: 'static', + defaultValue: 3, + }, + { + id: 'showNotification', + type: 'static', + defaultValue: true, + }, + { + id: 'statusType', + type: 'static', + defaultValue: 'saved', + }, + ], + components: [ + { + id: 'feedback-atoms-root', + type: 'div', + props: { + className: 'space-y-6 rounded-lg border border-border bg-card p-6', + }, + children: [ + { + id: 'feedback-atoms-title', + type: 'Heading', + props: { + className: 'text-lg font-semibold', + children: 'Feedback Atoms', + }, + }, + { + id: 'feedback-atoms-row', + type: 'div', + props: { + className: 'flex flex-wrap items-center gap-6', + }, + children: [ + { + id: 'feedback-atoms-status-icon', + type: 'StatusIcon', + props: { + animate: true, + size: 18, + }, + bindings: { + type: { + source: 'statusType', + sourceType: 'data', + }, + }, + }, + { + id: 'feedback-atoms-badge-wrapper', + type: 'div', + props: { + className: 'relative h-10 w-10 rounded-full bg-muted', + }, + children: [ + { + id: 'feedback-atoms-error-badge', + type: 'ErrorBadge', + props: { + variant: 'destructive', + size: 'md', + }, + bindings: { + count: { + source: 'errorCount', + sourceType: 'data', + }, + }, + }, + ], + }, + ], + }, + { + id: 'feedback-atoms-notification', + type: 'Notification', + props: { + type: 'info', + title: 'Heads up!', + message: 'You have unsent changes ready to sync.', + }, + conditional: { + if: 'data.showNotification', + }, + events: { + onClose: { + actions: [ + { + id: 'dismiss-notification', + type: 'set-value', + target: 'showNotification', + value: false, + }, + ], + }, + }, + }, + ], + }, + ], +} diff --git a/src/types/json-ui.ts b/src/types/json-ui.ts index f3ce4c3..9b64f2e 100644 --- a/src/types/json-ui.ts +++ b/src/types/json-ui.ts @@ -6,6 +6,7 @@ export type ComponentType = | 'Text' | 'Heading' | 'Label' | 'List' | 'Grid' | 'Stack' | 'Flex' | 'Container' | 'Link' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton' | 'Alert' | 'InfoBox' | 'EmptyState' | 'StatusBadge' + | 'ErrorBadge' | 'Notification' | 'StatusIcon' | 'Table' | 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar' | 'AppBranding' | 'LabelWithBadge' | 'EmptyEditorState' | 'LoadingFallback' | 'LoadingState' | 'NavigationGroupHeader' From 64c3b5b12b43817bb5fb1ec2ee6887d0ef84223a Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 11:40:46 +0000 Subject: [PATCH 4/4] Convert page schemas to JSON --- src/components/JSONUIShowcasePage.tsx | 3 +- src/schemas/page-schemas.json | 212 +++++++++++++++++++++++++ src/schemas/page-schemas.ts | 213 -------------------------- 3 files changed, 214 insertions(+), 214 deletions(-) create mode 100644 src/schemas/page-schemas.json delete mode 100644 src/schemas/page-schemas.ts diff --git a/src/components/JSONUIShowcasePage.tsx b/src/components/JSONUIShowcasePage.tsx index 1cd4c08..e2aadbe 100644 --- a/src/components/JSONUIShowcasePage.tsx +++ b/src/components/JSONUIShowcasePage.tsx @@ -3,12 +3,13 @@ import { AtomicComponentDemo } from '@/components/AtomicComponentDemo' import { DashboardDemoPage } from '@/components/DashboardDemoPage' import { PageRenderer } from '@/lib/json-ui/page-renderer' import { hydrateSchema } from '@/schemas/schema-loader' -import { dataComponentsDemoSchema } from '@/schemas/page-schemas' +import pageSchemasJson from '@/schemas/page-schemas.json' import todoListJson from '@/schemas/todo-list.json' import newMoleculesShowcaseJson from '@/schemas/new-molecules-showcase.json' const todoListSchema = hydrateSchema(todoListJson) const newMoleculesShowcaseSchema = hydrateSchema(newMoleculesShowcaseJson) +const dataComponentsDemoSchema = hydrateSchema(pageSchemasJson.dataComponentsDemoSchema) export function JSONUIShowcasePage() { return ( diff --git a/src/schemas/page-schemas.json b/src/schemas/page-schemas.json new file mode 100644 index 0000000..0a38f9a --- /dev/null +++ b/src/schemas/page-schemas.json @@ -0,0 +1,212 @@ +{ + "stateBindingsDemoSchema": { + "id": "state-bindings-demo", + "name": "State & Bindings Demo", + "layout": { + "type": "single" + }, + "dataSources": [ + { + "id": "statusItems", + "type": "static", + "defaultValue": ["KV Ready", "Components Loaded", "Sync Enabled"] + } + ], + "components": [ + { + "id": "state-demo-root", + "type": "div", + "props": { + "className": "space-y-4 rounded-lg border border-border bg-card p-6" + }, + "children": [ + { + "id": "state-demo-title", + "type": "Heading", + "props": { + "className": "text-xl font-semibold", + "children": "Renderer State Binding Demo" + } + }, + { + "id": "state-demo-theme", + "type": "Text", + "props": { + "className": "text-sm text-muted-foreground" + }, + "bindings": { + "children": { + "sourceType": "state", + "source": "settings", + "path": "settings.theme" + } + } + }, + { + "id": "state-demo-list", + "type": "div", + "props": { + "className": "space-y-2" + }, + "loop": { + "source": "statusItems", + "itemVar": "statusItem" + }, + "children": [ + { + "id": "state-demo-list-item", + "type": "Text", + "props": { + "className": "text-sm" + }, + "bindings": { + "children": { + "sourceType": "bindings", + "source": "statusItem" + } + } + } + ] + } + ] + } + ] + }, + "dataComponentsDemoSchema": { + "id": "data-components-demo", + "name": "Data Components Demo", + "layout": { + "type": "single" + }, + "dataSources": [ + { + "id": "metricCards", + "type": "static", + "defaultValue": [ + { "label": "Active Users", "value": 1248, "trend": { "value": 12.4, "direction": "up" } }, + { "label": "Churn Rate", "value": "3.2%", "trend": { "value": 1.1, "direction": "down" } }, + { "label": "Net Revenue", "value": "$48.3k", "trend": { "value": 6.8, "direction": "up" } } + ] + }, + { + "id": "tableColumns", + "type": "static", + "defaultValue": [ + { "key": "initiative", "header": "Initiative" }, + { "key": "owner", "header": "Owner" }, + { "key": "status", "header": "Status" } + ] + }, + { + "id": "tableRows", + "type": "static", + "defaultValue": [ + { "initiative": "Landing Page", "owner": "Avery", "status": "In Progress" }, + { "initiative": "Retention Emails", "owner": "Jordan", "status": "Review" }, + { "initiative": "Billing Update", "owner": "Riley", "status": "Done" } + ] + }, + { + "id": "listItems", + "type": "static", + "defaultValue": ["Prepare briefing deck", "Confirm stakeholder approvals", "Publish roadmap update"] + }, + { + "id": "timelineItems", + "type": "static", + "defaultValue": [ + { + "title": "Kickoff", + "description": "Align on scope and milestones", + "timestamp": "Mon 9:00 AM", + "status": "completed" + }, + { + "title": "Execution", + "description": "Deliver initial workstream", + "timestamp": "Tue 11:00 AM", + "status": "current" + }, + { + "title": "Review", + "description": "Stakeholder walkthrough", + "timestamp": "Thu 3:00 PM", + "status": "pending" + } + ] + } + ], + "components": [ + { + "id": "data-components-root", + "type": "div", + "props": { + "className": "space-y-6 rounded-lg border border-border bg-card p-6" + }, + "children": [ + { + "id": "data-components-title", + "type": "Heading", + "props": { + "className": "text-xl font-semibold", + "children": "Data Components Showcase" + } + }, + { + "id": "data-components-metrics-grid", + "type": "div", + "props": { + "className": "grid gap-4 md:grid-cols-3" + }, + "loop": { + "source": "metricCards", + "itemVar": "metricCard" + }, + "children": [ + { + "id": "data-components-metric-card", + "type": "MetricCard", + "bindings": { + "label": { "sourceType": "bindings", "source": "metricCard", "path": "label" }, + "value": { "sourceType": "bindings", "source": "metricCard", "path": "value" }, + "trend": { "sourceType": "bindings", "source": "metricCard", "path": "trend" } + } + } + ] + }, + { + "id": "data-components-table", + "type": "DataTable", + "props": { + "className": "bg-background", + "emptyMessage": "No initiatives found" + }, + "bindings": { + "columns": { "source": "tableColumns", "sourceType": "data" }, + "data": { "source": "tableRows", "sourceType": "data" } + } + }, + { + "id": "data-components-list", + "type": "DataList", + "props": { + "className": "space-y-3", + "itemClassName": "rounded-md border border-border bg-card/50 px-4 py-2 text-sm", + "emptyMessage": "No action items" + }, + "bindings": { + "items": { "source": "listItems", "sourceType": "data" } + } + }, + { + "id": "data-components-timeline", + "type": "Timeline", + "bindings": { + "items": { "source": "timelineItems", "sourceType": "data" } + } + } + ] + } + ] + } +} diff --git a/src/schemas/page-schemas.ts b/src/schemas/page-schemas.ts deleted file mode 100644 index 68299c8..0000000 --- a/src/schemas/page-schemas.ts +++ /dev/null @@ -1,213 +0,0 @@ -import type { PageSchema } from '@/types/json-ui' - -export const stateBindingsDemoSchema: PageSchema = { - id: 'state-bindings-demo', - name: 'State & Bindings Demo', - layout: { - type: 'single', - }, - dataSources: [ - { - id: 'statusItems', - type: 'static', - defaultValue: ['KV Ready', 'Components Loaded', 'Sync Enabled'], - }, - ], - components: [ - { - id: 'state-demo-root', - type: 'div', - props: { - className: 'space-y-4 rounded-lg border border-border bg-card p-6', - }, - children: [ - { - id: 'state-demo-title', - type: 'Heading', - props: { - className: 'text-xl font-semibold', - children: 'Renderer State Binding Demo', - }, - }, - { - id: 'state-demo-theme', - type: 'Text', - props: { - className: 'text-sm text-muted-foreground', - }, - bindings: { - children: { - sourceType: 'state', - source: 'settings', - path: 'settings.theme', - }, - }, - }, - { - id: 'state-demo-list', - type: 'div', - props: { - className: 'space-y-2', - }, - loop: { - source: 'statusItems', - itemVar: 'statusItem', - }, - children: [ - { - id: 'state-demo-list-item', - type: 'Text', - props: { - className: 'text-sm', - }, - bindings: { - children: { - sourceType: 'bindings', - source: 'statusItem', - }, - }, - }, - ], - }, - ], - }, - ], -} - -export const dataComponentsDemoSchema: PageSchema = { - id: 'data-components-demo', - name: 'Data Components Demo', - layout: { - type: 'single', - }, - dataSources: [ - { - id: 'metricCards', - type: 'static', - defaultValue: [ - { label: 'Active Users', value: 1248, trend: { value: 12.4, direction: 'up' } }, - { label: 'Churn Rate', value: '3.2%', trend: { value: 1.1, direction: 'down' } }, - { label: 'Net Revenue', value: '$48.3k', trend: { value: 6.8, direction: 'up' } }, - ], - }, - { - id: 'tableColumns', - type: 'static', - defaultValue: [ - { key: 'initiative', header: 'Initiative' }, - { key: 'owner', header: 'Owner' }, - { key: 'status', header: 'Status' }, - ], - }, - { - id: 'tableRows', - type: 'static', - defaultValue: [ - { initiative: 'Landing Page', owner: 'Avery', status: 'In Progress' }, - { initiative: 'Retention Emails', owner: 'Jordan', status: 'Review' }, - { initiative: 'Billing Update', owner: 'Riley', status: 'Done' }, - ], - }, - { - id: 'listItems', - type: 'static', - defaultValue: ['Prepare briefing deck', 'Confirm stakeholder approvals', 'Publish roadmap update'], - }, - { - id: 'timelineItems', - type: 'static', - defaultValue: [ - { - title: 'Kickoff', - description: 'Align on scope and milestones', - timestamp: 'Mon 9:00 AM', - status: 'completed', - }, - { - title: 'Execution', - description: 'Deliver initial workstream', - timestamp: 'Tue 11:00 AM', - status: 'current', - }, - { - title: 'Review', - description: 'Stakeholder walkthrough', - timestamp: 'Thu 3:00 PM', - status: 'pending', - }, - ], - }, - ], - components: [ - { - id: 'data-components-root', - type: 'div', - props: { - className: 'space-y-6 rounded-lg border border-border bg-card p-6', - }, - children: [ - { - id: 'data-components-title', - type: 'Heading', - props: { - className: 'text-xl font-semibold', - children: 'Data Components Showcase', - }, - }, - { - id: 'data-components-metrics-grid', - type: 'div', - props: { - className: 'grid gap-4 md:grid-cols-3', - }, - loop: { - source: 'metricCards', - itemVar: 'metricCard', - }, - children: [ - { - id: 'data-components-metric-card', - type: 'MetricCard', - bindings: { - label: { sourceType: 'bindings', source: 'metricCard', path: 'label' }, - value: { sourceType: 'bindings', source: 'metricCard', path: 'value' }, - trend: { sourceType: 'bindings', source: 'metricCard', path: 'trend' }, - }, - }, - ], - }, - { - id: 'data-components-table', - type: 'DataTable', - props: { - className: 'bg-background', - emptyMessage: 'No initiatives found', - }, - bindings: { - columns: { source: 'tableColumns', sourceType: 'data' }, - data: { source: 'tableRows', sourceType: 'data' }, - }, - }, - { - id: 'data-components-list', - type: 'DataList', - props: { - className: 'space-y-3', - itemClassName: 'rounded-md border border-border bg-card/50 px-4 py-2 text-sm', - emptyMessage: 'No action items', - }, - bindings: { - items: { source: 'listItems', sourceType: 'data' }, - }, - }, - { - id: 'data-components-timeline', - type: 'Timeline', - bindings: { - items: { source: 'timelineItems', sourceType: 'data' }, - }, - }, - ], - }, - ], -}