Merge branch 'main' into codex/rename-component-definitions.ts-to-json

This commit is contained in:
2026-01-18 12:08:38 +00:00
committed by GitHub
23 changed files with 502 additions and 280 deletions

View File

@@ -92,8 +92,8 @@ Form inputs and interactive controls:
- `Switch` - Toggle switch
- `Slider` - Numeric range slider
- `NumberInput` - Numeric input with increment/decrement
- `DatePicker` - Date selection (planned)
- `FileUpload` - File upload control (planned)
- `DatePicker` - Date selection
- `FileUpload` - File upload control
### Display Components (16)
Presentation and visual elements:
@@ -110,9 +110,9 @@ Presentation and visual elements:
- `Spinner` - Loading spinner
- `Skeleton` - Loading placeholder
- `Separator` - Visual divider
- `CircularProgress` - Circular indicator (planned)
- `ProgressBar` - Linear progress (planned)
- `Divider` - Section divider (planned)
- `CircularProgress` - Circular indicator
- `ProgressBar` - Linear progress
- `Divider` - Section divider
### Navigation Components (3)
Navigation and routing:

View File

@@ -172,7 +172,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Date selection input",
"status": "planned"
"status": "supported"
},
{
"type": "FileUpload",
@@ -180,7 +180,7 @@
"category": "input",
"canHaveChildren": false,
"description": "File upload control",
"status": "planned"
"status": "supported"
},
{
"type": "Text",
@@ -268,7 +268,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Visual section divider",
"status": "planned"
"status": "supported"
},
{
"type": "Progress",
@@ -284,7 +284,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Linear progress bar",
"status": "planned"
"status": "supported"
},
{
"type": "CircularProgress",
@@ -292,7 +292,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Circular progress indicator",
"status": "planned"
"status": "supported"
},
{
"type": "Spinner",

View File

@@ -2,7 +2,7 @@
"$schema": "./schemas/json-components-registry-schema.json",
"version": "2.0.0",
"description": "Registry of all components in the application",
"lastUpdated": "2026-01-17T22:10:22.582Z",
"lastUpdated": "2026-01-18T12:05:00.000Z",
"categories": {
"layout": "Layout and container components",
"input": "Form inputs and interactive controls",
@@ -322,7 +322,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Date selection input",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -331,7 +331,7 @@
"category": "input",
"canHaveChildren": false,
"description": "File upload control",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -611,7 +611,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Circular progress indicator",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -629,7 +629,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Visual section divider",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -719,7 +719,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Linear progress bar",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -836,29 +836,10 @@
"name": "Breadcrumb",
"category": "navigation",
"canHaveChildren": false,
"description": "Navigation breadcrumb trail",
"status": "planned",
"description": "Navigation breadcrumb trail using the atoms/BreadcrumbNav JSON-safe items prop",
"status": "supported",
"source": "atoms"
},
{
"type": "Breadcrumb",
"name": "Breadcrumb",
"category": "navigation",
"canHaveChildren": false,
"description": "Navigation breadcrumb trail",
"status": "json-compatible",
"source": "molecules",
"jsonCompatible": true
},
{
"type": "Breadcrumb",
"name": "Breadcrumb",
"category": "navigation",
"canHaveChildren": false,
"description": "Navigation breadcrumb trail",
"status": "planned",
"source": "ui"
},
{
"type": "ContextMenu",
"name": "ContextMenu",
@@ -1088,7 +1069,7 @@
"category": "feedback",
"canHaveChildren": false,
"description": "Error state badge",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -1164,7 +1145,7 @@
"category": "feedback",
"canHaveChildren": true,
"description": "Toast notification",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -1201,7 +1182,7 @@
"category": "feedback",
"canHaveChildren": false,
"description": "Status indicator icon",
"status": "planned",
"status": "supported",
"source": "atoms"
},
{
@@ -2043,24 +2024,24 @@
],
"statistics": {
"total": 219,
"supported": 154,
"planned": 10,
"supported": 157,
"planned": 7,
"jsonCompatible": 14,
"maybeJsonCompatible": 41,
"byCategory": {
"layout": 25,
"input": 34,
"display": 31,
"navigation": 17,
"navigation": 15,
"feedback": 23,
"data": 20,
"custom": 69
},
"bySource": {
"atoms": 117,
"molecules": 41,
"molecules": 40,
"organisms": 15,
"ui": 46
"ui": 45
}
}
}

View File

@@ -78,6 +78,16 @@ export function JSONUIPage({ jsonConfig }: JSONUIPageProps) {
updateDataField('formData', action.params.field, event)
}
break
case 'update-date':
if (action.params?.field) {
updateDataField('formData', action.params.field, event)
}
break
case 'update-files':
if (action.params?.field) {
updateDataField('formData', action.params.field, event)
}
break
case 'submit-form':
toast.success('Form submitted!')
console.log('Form data:', dataMap.formData)

View File

@@ -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 (
@@ -25,6 +26,7 @@ export function JSONUIShowcasePage() {
</div>
<TabsList className="w-full justify-start">
<TabsTrigger value="atomic">Atomic Components</TabsTrigger>
<TabsTrigger value="feedback">Feedback Atoms</TabsTrigger>
<TabsTrigger value="molecules">New Molecules</TabsTrigger>
<TabsTrigger value="data-components">Data Components</TabsTrigger>
<TabsTrigger value="dashboard">JSON Dashboard</TabsTrigger>
@@ -36,6 +38,10 @@ export function JSONUIShowcasePage() {
<TabsContent value="atomic" className="h-full m-0 data-[state=active]:block">
<AtomicComponentDemo />
</TabsContent>
<TabsContent value="feedback" className="h-full m-0 data-[state=active]:block">
<PageRenderer schema={feedbackAtomsDemoSchema} />
</TabsContent>
<TabsContent value="molecules" className="h-full m-0 data-[state=active]:block">
<PageRenderer schema={newMoleculesShowcaseSchema} />

View File

@@ -17,19 +17,19 @@ export function BreadcrumbNav({ items, className }: BreadcrumbNavProps) {
<nav aria-label="Breadcrumb" className={cn('flex items-center gap-2', className)}>
{items.map((item, index) => {
const isLast = index === items.length - 1
const linkClassName = cn(
'text-sm transition-colors',
isLast ? 'text-foreground font-medium' : 'text-muted-foreground hover:text-foreground'
)
return (
<div key={index} className="flex items-center gap-2">
{item.href || item.onClick ? (
<button
onClick={item.onClick}
className={cn(
'text-sm transition-colors',
isLast
? 'text-foreground font-medium'
: 'text-muted-foreground hover:text-foreground'
)}
>
{item.href ? (
<a href={item.href} onClick={item.onClick} className={linkClassName}>
{item.label}
</a>
) : item.onClick ? (
<button onClick={item.onClick} className={linkClassName}>
{item.label}
</button>
) : (
@@ -49,3 +49,5 @@ export function BreadcrumbNav({ items, className }: BreadcrumbNavProps) {
</nav>
)
}
export const Breadcrumb = BreadcrumbNav

View File

@@ -1,4 +1,4 @@
import { ComponentDefinition } from '@/lib/component-definitions-utils'
import { ComponentDefinition } from '@/lib/component-definition-types'
import { Card } from '@/components/ui/card'
import * as Icons from '@phosphor-icons/react'
import { cn } from '@/lib/utils'

View File

@@ -1,5 +1,5 @@
import { UIComponent } from '@/types/json-ui'
import { getComponentDef } from '@/lib/component-definitions-utils'
import { getComponentDef } from '@/lib/component-definition-utils'
import { cn } from '@/lib/utils'
import * as Icons from '@phosphor-icons/react'

View File

@@ -54,7 +54,7 @@ export { Timestamp } from './Timestamp'
export { ScrollArea } from './ScrollArea'
export { Tag } from './Tag'
export { BreadcrumbNav } from './Breadcrumb'
export { Breadcrumb, BreadcrumbNav } from './Breadcrumb'
export { IconText } from './IconText'
export { TextArea } from './TextArea'
export { Input } from './Input'
@@ -118,4 +118,3 @@ export { MetricDisplay } from './MetricDisplay'
export { KeyValue } from './KeyValue'
export { EmptyMessage } from './EmptyMessage'
export { StepIndicator } from './StepIndicator'

View File

@@ -1,6 +1,6 @@
import { UIComponent } from '@/types/json-ui'
import { getUIComponent } from '@/lib/json-ui/component-registry'
import { getComponentDef } from '@/lib/component-definitions-utils'
import { getComponentDef } from '@/lib/component-definition-utils'
import { cn } from '@/lib/utils'
import { createElement, ReactNode } from 'react'

View File

@@ -1,4 +1,5 @@
import { ComponentDefinition, getCategoryComponents } from '@/lib/component-definitions-utils'
import { ComponentDefinition } from '@/lib/component-definition-types'
import { getCategoryComponents } from '@/lib/component-definition-utils'
import { ComponentPaletteItem } from '@/components/atoms/ComponentPaletteItem'
import { PanelHeader, Stack } from '@/components/atoms'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'

View File

@@ -1,7 +1,7 @@
import { UIComponent } from '@/types/json-ui'
import { ScrollArea } from '@/components/ui/scroll-area'
import { Separator } from '@/components/ui/separator'
import { getComponentDef } from '@/lib/component-definitions-utils'
import { getComponentDef } from '@/lib/component-definition-utils'
import { PropertyEditorEmptyState } from '@/components/molecules/property-editor/PropertyEditorEmptyState'
import { propertyEditorConfig } from '@/components/molecules/property-editor/propertyEditorConfig'
import { PropertyEditorHeader } from '@/components/molecules/property-editor/PropertyEditorHeader'

View File

@@ -1,5 +1,5 @@
import { UIComponent, PageSchema } from '@/types/json-ui'
import { ComponentDefinition } from '@/lib/component-definitions-utils'
import { ComponentDefinition } from '@/lib/component-definition-types'
import { SchemaEditorToolbar } from './SchemaEditorToolbar'
import { SchemaEditorSidebar } from './SchemaEditorSidebar'
import { SchemaEditorCanvas } from './SchemaEditorCanvas'

View File

@@ -1,5 +1,5 @@
import { ComponentPalette } from '@/components/molecules/ComponentPalette'
import { ComponentDefinition } from '@/lib/component-definitions-utils'
import { ComponentDefinition } from '@/lib/component-definition-types'
interface SchemaEditorSidebarProps {
onDragStart: (component: ComponentDefinition, e: React.DragEvent) => void

View File

@@ -2,7 +2,7 @@ import { useSchemaEditor } from '@/hooks/ui/use-schema-editor'
import { useDragDrop } from '@/hooks/ui/use-drag-drop'
import { useJsonExport } from '@/hooks/ui/use-json-export'
import { SchemaEditorLayout } from '@/components/organisms'
import { ComponentDefinition } from '@/lib/component-definitions-utils'
import { ComponentDefinition } from '@/lib/component-definition-types'
import { UIComponent, PageSchema } from '@/types/json-ui'
import { toast } from 'sonner'
import { schemaEditorConfig } from '@/components/schema-editor/schemaEditorConfig'

View File

@@ -130,6 +130,37 @@
}
]
},
{
"id": "birthdate-field",
"type": "div",
"className": "space-y-2",
"children": [
{
"id": "birthdate-label",
"type": "Label",
"props": {
"htmlFor": "birthDate"
},
"children": "Birth date"
},
{
"id": "birthdate-input",
"type": "DatePicker",
"props": {
"placeholder": "Select a date"
},
"dataBinding": "formData.birthDate",
"events": {
"onChange": {
"action": "update-date",
"payload": {
"field": "birthDate"
}
}
}
}
]
},
{
"id": "bio-field",
"type": "div",
@@ -159,6 +190,36 @@
}
]
},
{
"id": "resume-field",
"type": "div",
"className": "space-y-2",
"children": [
{
"id": "resume-label",
"type": "Label",
"props": {
"htmlFor": "resume"
},
"children": "Resume"
},
{
"id": "resume-upload",
"type": "FileUpload",
"props": {
"accept": ".pdf,.doc,.docx"
},
"events": {
"onFilesSelected": {
"action": "update-files",
"payload": {
"field": "resumeFiles"
}
}
}
}
]
},
{
"id": "subscribe-field",
"type": "div",
@@ -234,6 +295,8 @@
"email": "",
"password": "",
"bio": "",
"birthDate": null,
"resumeFiles": [],
"subscribe": false
}
}

View File

@@ -0,0 +1,27 @@
import { ComponentType } from '@/types/json-ui'
export interface ComponentDefinition {
type: ComponentType
label: string
category: 'layout' | 'input' | 'display' | 'navigation' | 'feedback' | 'data' | 'custom'
icon: string
defaultProps?: Record<string, any>
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
}

View File

@@ -0,0 +1,13 @@
import componentDefinitionsData from '@/lib/component-definitions.json'
import { ComponentDefinition } from '@/lib/component-definition-types'
import { ComponentType } from '@/types/json-ui'
export const componentDefinitions = componentDefinitionsData as ComponentDefinition[]
export function getCategoryComponents(category: string): ComponentDefinition[] {
return componentDefinitions.filter(c => c.category === category)
}
export function getComponentDef(type: ComponentType): ComponentDefinition | undefined {
return componentDefinitions.find(c => c.type === type)
}

View File

@@ -209,6 +209,19 @@
"canHaveChildren": true,
"defaultProps": { "href": "#", "children": "Link" }
},
{
"type": "Breadcrumb",
"label": "Breadcrumb",
"category": "navigation",
"icon": "CaretRight",
"canHaveChildren": false,
"defaultProps": {
"items": [
{ "label": "Home", "href": "/" },
{ "label": "Current" }
]
}
},
{
"type": "Alert",
"label": "Alert",
@@ -240,6 +253,107 @@
"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
}
]
},
{
"type": "List",
"label": "List",

View File

@@ -147,6 +147,11 @@ export const atomComponents: UIComponentRegistry = {
Timeline: (AtomComponents as Record<string, ComponentType<any>>).Timeline,
}
const breadcrumbComponent = AtomComponents.Breadcrumb ?? AtomComponents.BreadcrumbNav
if (breadcrumbComponent) {
atomComponents.Breadcrumb = breadcrumbComponent as ComponentType<any>
}
export const moleculeComponents: UIComponentRegistry = buildRegistryFromNames(
moleculeRegistryNames,
MoleculeComponents as Record<string, ComponentType<any>>

View File

@@ -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" }
}
}
]
}
]
}
}

View File

@@ -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' },
},
},
],
},
],
}

View File

@@ -2,10 +2,12 @@ export type ComponentType =
| 'div' | 'section' | 'article' | 'header' | 'footer' | 'main'
| 'Button' | 'Card' | 'CardHeader' | 'CardTitle' | 'CardDescription' | 'CardContent' | 'CardFooter'
| 'Input' | 'TextArea' | 'Textarea' | 'Select' | 'Checkbox' | 'Radio' | 'Switch' | 'Slider' | 'NumberInput'
| 'DatePicker' | 'FileUpload'
| 'Badge' | 'Progress' | 'Separator' | 'Tabs' | 'TabsContent' | 'TabsList' | 'TabsTrigger' | 'Dialog'
| 'Text' | 'Heading' | 'Label' | 'List' | 'Grid' | 'Stack' | 'Flex' | 'Container'
| 'Link' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton'
| 'Link' | 'Breadcrumb' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton'
| 'Alert' | 'InfoBox' | 'EmptyState' | 'StatusBadge'
| 'ErrorBadge' | 'Notification' | 'StatusIcon'
| 'Table' | 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar'
| 'DataList' | 'DataTable' | 'MetricCard' | 'Timeline'
| 'AppBranding' | 'LabelWithBadge' | 'EmptyEditorState' | 'LoadingFallback' | 'LoadingState' | 'NavigationGroupHeader'