mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-25 14:14:57 +00:00
Merge branch 'main' into codex/rename-component-definitions.ts-to-json
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
27
src/lib/component-definition-types.ts
Normal file
27
src/lib/component-definition-types.ts
Normal 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
|
||||
}
|
||||
13
src/lib/component-definition-utils.ts
Normal file
13
src/lib/component-definition-utils.ts
Normal 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)
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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>>
|
||||
|
||||
212
src/schemas/page-schemas.json
Normal file
212
src/schemas/page-schemas.json
Normal 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" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user