Merge branch 'main' into codex/identify-components-for-hooks-and-context

This commit is contained in:
2026-01-18 13:05:37 +00:00
committed by GitHub
31 changed files with 2691 additions and 373 deletions

View File

@@ -185,14 +185,20 @@
"label": "Progress Bar",
"category": "display",
"icon": "ChartBar",
"defaultProps": { "value": 65, "size": "md", "variant": "default", "showLabel": false }
"defaultProps": {
"value": 65,
"max": 100,
"size": "md",
"variant": "default",
"showLabel": false
}
},
{
"type": "CircularProgress",
"label": "Circular Progress",
"category": "display",
"icon": "CircleNotch",
"defaultProps": { "value": 65, "size": "md", "showLabel": true }
"defaultProps": { "value": 65, "max": 100, "size": "md", "showLabel": true }
},
{
"type": "Spinner",
@@ -220,7 +226,7 @@
"label": "Divider",
"category": "display",
"icon": "Minus",
"defaultProps": { "orientation": "horizontal", "decorative": true }
"defaultProps": { "orientation": "horizontal", "decorative": true, "className": "" }
},
{
"type": "Link",
@@ -574,5 +580,480 @@
"isExporting": false,
"isImporting": false
}
},
{
"type": "CodeExplanationDialog",
"label": "Code Explanation Dialog",
"category": "layout",
"icon": "Info",
"defaultProps": {
"open": false,
"fileName": "example.ts",
"explanation": "Explain this code...",
"isLoading": false
}
},
{
"type": "ComponentBindingDialog",
"label": "Component Binding Dialog",
"category": "layout",
"icon": "Link",
"defaultProps": {
"open": false,
"component": null,
"dataSources": []
}
},
{
"type": "DataSourceCard",
"label": "Data Source Card",
"category": "layout",
"icon": "Database",
"defaultProps": {
"dataSource": {
"id": "source",
"type": "static",
"defaultValue": ""
},
"dependents": []
}
},
{
"type": "DataSourceEditorDialog",
"label": "Data Source Editor Dialog",
"category": "layout",
"icon": "Database",
"defaultProps": {
"open": false,
"dataSource": null,
"allDataSources": []
}
},
{
"type": "TreeCard",
"label": "Tree Card",
"category": "layout",
"icon": "Tree",
"defaultProps": {
"tree": {
"id": "tree-1",
"name": "Main Tree",
"description": "Primary UI tree",
"rootNodes": [],
"createdAt": 0,
"updatedAt": 0
},
"isSelected": false,
"disableDelete": false
}
},
{
"type": "TreeFormDialog",
"label": "Tree Form Dialog",
"category": "layout",
"icon": "Tree",
"defaultProps": {
"open": false,
"title": "Create Tree",
"description": "Add a new component tree.",
"name": "",
"treeDescription": "",
"submitLabel": "Save"
}
},
{
"type": "ToolbarButton",
"label": "Toolbar Button",
"category": "input",
"icon": "Button",
"defaultProps": {
"label": "Action",
"variant": "outline",
"disabled": false
}
},
{
"type": "SchemaCodeViewer",
"label": "Schema Code Viewer",
"category": "display",
"icon": "Code",
"defaultProps": {
"components": [],
"schema": {}
}
},
{
"type": "FileTabs",
"label": "File Tabs",
"category": "navigation",
"icon": "Tabs",
"defaultProps": {
"files": [],
"activeFileId": null
}
},
{
"type": "NavigationItem",
"label": "Navigation Item",
"category": "navigation",
"icon": "List",
"defaultProps": {
"label": "Overview",
"isActive": false,
"badge": 0
}
},
{
"type": "NavigationMenu",
"label": "Navigation Menu",
"category": "navigation",
"icon": "Sidebar",
"defaultProps": {
"activeTab": "overview",
"featureToggles": {
"codeEditor": false,
"models": false,
"components": false,
"componentTrees": false,
"workflows": false,
"lambdas": false,
"styling": false,
"flaskApi": false,
"playwright": false,
"storybook": false,
"unitTests": false,
"errorRepair": false,
"documentation": false,
"sassStyles": false,
"faviconDesigner": false,
"ideaCloud": false,
"schemaEditor": false,
"dataBinding": false
},
"errorCount": 0
}
},
{
"type": "EmptyCanvasState",
"label": "Empty Canvas State",
"category": "feedback",
"icon": "FolderOpen",
"defaultProps": {}
},
{
"type": "SchemaEditorStatusBar",
"label": "Schema Editor Status Bar",
"category": "feedback",
"icon": "Info",
"defaultProps": {
"componentCount": 0,
"selectedComponentType": "",
"hasUnsavedChanges": false
}
},
{
"type": "DataSourceManager",
"label": "Data Source Manager",
"category": "data",
"icon": "Database",
"defaultProps": {
"dataSources": []
}
},
{
"type": "TreeListHeader",
"label": "Tree List Header",
"category": "data",
"icon": "Tree",
"defaultProps": {
"hasSelectedTree": false
}
},
{
"type": "TreeListPanel",
"label": "Tree List Panel",
"category": "data",
"icon": "Tree",
"defaultProps": {
"trees": [],
"selectedTreeId": null
}
},
{
"type": "AppHeader",
"label": "App Header",
"category": "custom",
"icon": "Layout",
"defaultProps": {
"activeTab": "overview",
"featureToggles": {
"codeEditor": false,
"models": false,
"components": false,
"componentTrees": false,
"workflows": false,
"lambdas": false,
"styling": false,
"flaskApi": false,
"playwright": false,
"storybook": false,
"unitTests": false,
"errorRepair": false,
"documentation": false,
"sassStyles": false,
"faviconDesigner": false,
"ideaCloud": false,
"schemaEditor": false,
"dataBinding": false
},
"errorCount": 0,
"lastSaved": null,
"currentProject": {
"name": "Demo Project",
"files": [],
"models": [],
"components": [],
"componentTrees": [],
"workflows": [],
"lambdas": [],
"theme": {
"variants": [
{
"id": "default",
"name": "Default",
"colors": {
"primary": "#4f46e5",
"secondary": "#64748b",
"accent": "#0ea5e9",
"muted": "#f1f5f9",
"background": "#ffffff",
"surface": "#ffffff",
"text": "#0f172a",
"textSecondary": "#475569",
"border": "#e2e8f0",
"customColors": {}
}
}
],
"activeVariantId": "default",
"fontFamily": "Inter",
"fontSize": {
"small": 12,
"medium": 14,
"large": 18
},
"spacing": 4,
"borderRadius": 8
}
}
}
},
{
"type": "BindingEditor",
"label": "Binding Editor",
"category": "custom",
"icon": "Link",
"defaultProps": {
"bindings": {},
"dataSources": [],
"availableProps": ["children", "value"]
}
},
{
"type": "CanvasRenderer",
"label": "Canvas Renderer",
"category": "custom",
"icon": "Layout",
"defaultProps": {
"components": [],
"selectedId": null,
"hoveredId": null,
"draggedOverId": null,
"dropPosition": null
}
},
{
"type": "ComponentPalette",
"label": "Component Palette",
"category": "custom",
"icon": "GridFour",
"defaultProps": {}
},
{
"type": "ComponentTree",
"label": "Component Tree",
"category": "custom",
"icon": "Tree",
"defaultProps": {
"components": [],
"selectedId": null,
"hoveredId": null,
"draggedOverId": null,
"dropPosition": null
}
},
{
"type": "EditorActions",
"label": "Editor Actions",
"category": "custom",
"icon": "Sparkle",
"defaultProps": {}
},
{
"type": "EditorToolbar",
"label": "Editor Toolbar",
"category": "custom",
"icon": "Toolbox",
"defaultProps": {
"openFiles": [],
"activeFileId": null,
"activeFile": null
}
},
{
"type": "JSONUIShowcase",
"label": "JSON UI Showcase",
"category": "custom",
"icon": "Code",
"defaultProps": {
"files": [],
"models": [],
"components": []
}
},
{
"type": "LazyInlineMonacoEditor",
"label": "Inline Monaco Editor",
"category": "custom",
"icon": "Code",
"defaultProps": {
"height": "300px",
"language": "typescript",
"value": "// Start typing..."
}
},
{
"type": "LazyMonacoEditor",
"label": "Monaco Editor",
"category": "custom",
"icon": "Code",
"defaultProps": {
"file": {
"id": "file-1",
"name": "App.tsx",
"path": "/App.tsx",
"content": "// Start typing...",
"language": "typescript"
}
}
},
{
"type": "MonacoEditorPanel",
"label": "Monaco Editor Panel",
"category": "custom",
"icon": "Code",
"defaultProps": {
"file": {
"id": "file-1",
"name": "App.tsx",
"path": "/App.tsx",
"content": "// Start typing...",
"language": "typescript"
}
}
},
{
"type": "PageHeaderContent",
"label": "Page Header Content",
"category": "custom",
"icon": "Heading",
"defaultProps": {
"title": "Page Title",
"description": "Page description"
}
},
{
"type": "PropertyEditor",
"label": "Property Editor",
"category": "custom",
"icon": "SlidersHorizontal",
"defaultProps": {
"component": null
}
},
{
"type": "SchemaEditorCanvas",
"label": "Schema Editor Canvas",
"category": "custom",
"icon": "Layout",
"defaultProps": {
"components": [],
"selectedId": null,
"hoveredId": null,
"draggedOverId": null,
"dropPosition": null
}
},
{
"type": "SchemaEditorLayout",
"label": "Schema Editor Layout",
"category": "custom",
"icon": "Layout",
"defaultProps": {
"components": [],
"selectedId": null,
"hoveredId": null,
"draggedOverId": null,
"dropPosition": null,
"selectedComponent": null
}
},
{
"type": "SchemaEditorPropertiesPanel",
"label": "Schema Editor Properties Panel",
"category": "custom",
"icon": "SlidersHorizontal",
"defaultProps": {
"components": [],
"selectedId": null,
"hoveredId": null,
"draggedOverId": null,
"dropPosition": null,
"selectedComponent": null
}
},
{
"type": "SchemaEditorSidebar",
"label": "Schema Editor Sidebar",
"category": "custom",
"icon": "Sidebar",
"defaultProps": {}
},
{
"type": "SchemaEditorToolbar",
"label": "Schema Editor Toolbar",
"category": "custom",
"icon": "Toolbox",
"defaultProps": {}
},
{
"type": "SearchBar",
"label": "Search Bar",
"category": "custom",
"icon": "MagnifyingGlass",
"defaultProps": {
"value": "",
"placeholder": "Search..."
}
},
{
"type": "ToolbarActions",
"label": "Toolbar Actions",
"category": "custom",
"icon": "Toolbox",
"defaultProps": {
"errorCount": 0,
"showErrorButton": false
}
}
]

View File

@@ -17,9 +17,19 @@ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, D
import { Skeleton as ShadcnSkeleton } from '@/components/ui/skeleton'
import { Progress } from '@/components/ui/progress'
import { Avatar as ShadcnAvatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { CircularProgress, Divider, ProgressBar } from '@/components/atoms'
import * as AtomComponents from '@/components/atoms'
import * as MoleculeComponents from '@/components/molecules'
import * as WrapperComponents from '@/lib/json-ui/wrappers'
import * as OrganismComponents from '@/components/organisms'
import {
BreadcrumbWrapper,
LazyBarChartWrapper,
LazyD3BarChartWrapper,
LazyLineChartWrapper,
SaveIndicatorWrapper,
SeedDataManagerWrapper,
StorageSettingsWrapper,
} from '@/lib/json-ui/wrappers'
import jsonComponentsRegistry from '../../../json-components-registry.json'
import {
ArrowLeft, ArrowRight, Check, X, Plus, Minus, MagnifyingGlass,
@@ -39,14 +49,19 @@ interface JsonRegistryEntry {
type?: string
export?: string
source?: string
wrapperRequired?: boolean
wrapperComponent?: string
status?: string
deprecated?: DeprecatedComponentInfo
}
interface JsonComponentRegistry {
components?: JsonRegistryEntry[]
}
export interface DeprecatedComponentInfo {
replacedBy?: string
message?: string
}
const jsonRegistry = jsonComponentsRegistry as JsonComponentRegistry
const buildRegistryFromNames = (
@@ -63,6 +78,19 @@ const buildRegistryFromNames = (
}
const jsonRegistryEntries = jsonRegistry.components ?? []
const deprecatedComponentInfo = jsonRegistryEntries.reduce<Record<string, DeprecatedComponentInfo>>(
(acc, entry) => {
const entryName = entry.export ?? entry.name ?? entry.type
if (!entryName) {
return acc
}
if (entry.status === 'deprecated' || entry.deprecated) {
acc[entryName] = entry.deprecated ?? {}
}
return acc
},
{}
)
const atomRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'atoms')
.map((entry) => entry.export ?? entry.name ?? entry.type)
@@ -71,20 +99,11 @@ const moleculeRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'molecules')
.map((entry) => entry.export ?? entry.name ?? entry.type)
.filter((name): name is string => Boolean(name))
const wrapperRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'wrappers')
const organismRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'organisms')
.map((entry) => entry.export ?? entry.name ?? entry.type)
.filter((name): name is string => Boolean(name))
const registryEntryByType = new Map<string, JsonRegistryEntry>(
jsonRegistryEntries
.map((entry) => {
const key = entry.type ?? entry.name ?? entry.export
return key ? [key, entry] : null
})
.filter((entry): entry is [string, JsonRegistryEntry] => Boolean(entry))
)
export const primitiveComponents: UIComponentRegistry = {
div: 'div' as any,
span: 'span' as any,
@@ -157,6 +176,9 @@ export const atomComponents: UIComponentRegistry = {
atomRegistryNames,
AtomComponents as Record<string, ComponentType<any>>
),
CircularProgress,
Divider,
ProgressBar,
DataList: (AtomComponents as Record<string, ComponentType<any>>).DataList,
DataTable: (AtomComponents as Record<string, ComponentType<any>>).DataTable,
MetricCard: (AtomComponents as Record<string, ComponentType<any>>).MetricCard,
@@ -173,11 +195,21 @@ export const moleculeComponents: UIComponentRegistry = buildRegistryFromNames(
MoleculeComponents as Record<string, ComponentType<any>>
)
export const jsonWrapperComponents: UIComponentRegistry = buildRegistryFromNames(
wrapperRegistryNames,
WrapperComponents as Record<string, ComponentType<any>>
export const organismComponents: UIComponentRegistry = buildRegistryFromNames(
organismRegistryNames,
OrganismComponents as Record<string, ComponentType<any>>
)
export const jsonWrapperComponents: UIComponentRegistry = {
Breadcrumb: BreadcrumbWrapper,
SaveIndicator: SaveIndicatorWrapper,
LazyBarChart: LazyBarChartWrapper,
LazyLineChart: LazyLineChartWrapper,
LazyD3BarChart: LazyD3BarChartWrapper,
SeedDataManager: SeedDataManagerWrapper,
StorageSettings: StorageSettingsWrapper,
}
export const iconComponents: UIComponentRegistry = {
ArrowLeft,
ArrowRight,
@@ -224,6 +256,7 @@ export const uiComponentRegistry: UIComponentRegistry = {
...shadcnComponents,
...atomComponents,
...moleculeComponents,
...organismComponents,
...jsonWrapperComponents,
...iconComponents,
}
@@ -247,3 +280,7 @@ export function getUIComponent(type: string): ComponentType<any> | string | null
export function hasComponent(type: string): boolean {
return Boolean(resolveWrapperComponent(type) ?? uiComponentRegistry[type])
}
export function getDeprecatedComponentInfo(type: string): DeprecatedComponentInfo | null {
return deprecatedComponentInfo[type] ?? null
}

View File

@@ -2,6 +2,7 @@ import { createElement, type ComponentType, type ReactNode } from 'react'
import { cn } from '@/lib/utils'
import { Component as ComponentSchema, Layout } from '@/schemas/ui-schema'
import { useDataBinding, useEventHandlers, useComponentRegistry } from '@/hooks/ui'
import { getDeprecatedComponentInfo } from '@/lib/json-ui/component-registry'
interface SchemaRendererProps {
schema: ComponentSchema
@@ -15,6 +16,26 @@ interface LayoutRendererProps {
children: ReactNode
}
const warnedDeprecatedComponents = new Set<string>()
const warnDeprecatedComponent = (schema: ComponentSchema) => {
const deprecatedInfo = getDeprecatedComponentInfo(schema.type)
if (!deprecatedInfo || warnedDeprecatedComponents.has(schema.type)) {
return
}
const idSuffix = schema.id ? ` (id: ${schema.id})` : ''
const replacementHint = deprecatedInfo.replacedBy
? ` Replace with "${deprecatedInfo.replacedBy}".`
: ''
const extraMessage = deprecatedInfo.message ? ` ${deprecatedInfo.message}` : ''
console.warn(
`[SchemaRenderer] Deprecated component "${schema.type}" detected in schema${idSuffix}.${replacementHint}${extraMessage}`
)
warnedDeprecatedComponents.add(schema.type)
}
function LayoutRenderer({ layout, children }: LayoutRendererProps) {
const getLayoutClasses = () => {
const classes: string[] = []
@@ -85,6 +106,8 @@ export function SchemaRenderer({ schema, data, functions = {}, componentRegistry
)
}
warnDeprecatedComponent(schema)
const props = resolveProps(schema.props || {})
const events = resolveEvents(schema.events)
const combinedProps = { ...props, ...events }