feat: migrate SchemaEditor organisms to JSON

Completed migration of all 6 SchemaEditor organisms from TSX to JSON:
- SchemaEditorCanvas
- SchemaEditorLayout
- SchemaEditorPropertiesPanel
- SchemaEditorSidebar
- SchemaEditorStatusBar
- SchemaEditorToolbar

Changes:
- Created JSON definitions in src/components/json-definitions/
- Created TypeScript interfaces in src/lib/json-ui/interfaces/
- Exported from src/lib/json-ui/json-components.ts using createJsonComponent
- Updated src/components/organisms/index.ts to import from json-components
- Deleted 6 TSX files from src/components/organisms/
- Updated interfaces/index.ts to export new interface files

Build: ✓ passing
TSX files deleted: 6
JSON definitions created: 6
Interfaces created: 6

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 03:19:26 +00:00
parent 73c9aff67c
commit f954a6bf32
22 changed files with 440 additions and 382 deletions

View File

@@ -1,5 +1,5 @@
{
"timestamp": "2026-01-21T03:02:07.273Z",
"timestamp": "2026-01-21T03:13:44.395Z",
"issues": [
{
"severity": "warning",

View File

@@ -0,0 +1,26 @@
{
"id": "schema-editor-canvas",
"type": "div",
"props": {
"className": "flex-1 flex flex-col"
},
"children": [
{
"id": "canvas-renderer-container",
"type": "CanvasRenderer",
"bindings": {
"components": { "source": "components" },
"selectedId": { "source": "selectedId" },
"hoveredId": { "source": "hoveredId" },
"draggedOverId": { "source": "draggedOverId" },
"dropPosition": { "source": "dropPosition" },
"onSelect": { "source": "onSelect" },
"onHover": { "source": "onHover" },
"onHoverEnd": { "source": "onHoverEnd" },
"onDragOver": { "source": "onDragOver" },
"onDragLeave": { "source": "onDragLeave" },
"onDrop": { "source": "onDrop" }
}
}
]
}

View File

@@ -0,0 +1,74 @@
{
"id": "schema-editor-layout",
"type": "div",
"props": {
"className": "h-full flex flex-col bg-background"
},
"children": [
{
"id": "toolbar-section",
"type": "SchemaEditorToolbar",
"bindings": {
"onImport": { "source": "onImport" },
"onExport": { "source": "onExport" },
"onCopy": { "source": "onCopy" },
"onPreview": { "source": "onPreview" },
"onClear": { "source": "onClear" }
}
},
{
"id": "main-content",
"type": "div",
"props": {
"className": "flex-1 flex overflow-hidden"
},
"children": [
{
"id": "sidebar-section",
"type": "SchemaEditorSidebar",
"bindings": {
"onDragStart": { "source": "onComponentDragStart" }
}
},
{
"id": "canvas-section",
"type": "SchemaEditorCanvas",
"bindings": {
"components": { "source": "components" },
"selectedId": { "source": "selectedId" },
"hoveredId": { "source": "hoveredId" },
"draggedOverId": { "source": "draggedOverId" },
"dropPosition": { "source": "dropPosition" },
"onSelect": { "source": "onSelect" },
"onHover": { "source": "onHover" },
"onHoverEnd": { "source": "onHoverEnd" },
"onDragOver": { "source": "onDragOver" },
"onDragLeave": { "source": "onDragLeave" },
"onDrop": { "source": "onDrop" }
}
},
{
"id": "properties-section",
"type": "SchemaEditorPropertiesPanel",
"bindings": {
"components": { "source": "components" },
"selectedId": { "source": "selectedId" },
"hoveredId": { "source": "hoveredId" },
"draggedOverId": { "source": "draggedOverId" },
"dropPosition": { "source": "dropPosition" },
"selectedComponent": { "source": "selectedComponent" },
"onSelect": { "source": "onSelect" },
"onHover": { "source": "onHover" },
"onHoverEnd": { "source": "onHoverEnd" },
"onDragStart": { "source": "onTreeDragStart" },
"onDragOver": { "source": "onDragOver" },
"onDragLeave": { "source": "onDragLeave" },
"onDrop": { "source": "onDrop" },
"onUpdate": { "source": "onUpdate" },
"onDelete": { "source": "onDelete" }
}
}
]
}
]
}

View File

@@ -0,0 +1,60 @@
{
"id": "schema-editor-properties-panel",
"type": "div",
"props": {
"className": "w-80 border-l border-border bg-card overflow-y-auto"
},
"children": [
{
"id": "properties-content",
"type": "div",
"props": {
"className": "p-4 space-y-4"
},
"conditional": { "if": "selectedComponent" },
"children": [
{
"id": "component-id-display",
"type": "div",
"props": { "className": "space-y-2" },
"children": [
{
"type": "span",
"props": { "className": "text-sm font-medium" },
"bindings": { "children": "'Component ID'" }
},
{
"type": "div",
"props": { "className": "px-2 py-1 bg-muted rounded text-sm font-mono" },
"bindings": { "children": "selectedComponent?.id" }
}
]
},
{
"id": "component-type-display",
"type": "div",
"props": { "className": "space-y-2" },
"children": [
{
"type": "span",
"props": { "className": "text-sm font-medium" },
"bindings": { "children": "'Type'" }
},
{
"type": "div",
"props": { "className": "px-2 py-1 bg-muted rounded text-sm font-mono" },
"bindings": { "children": "selectedComponent?.type" }
}
]
}
]
},
{
"id": "no-selection-message",
"type": "div",
"props": { "className": "p-4 text-sm text-muted-foreground" },
"conditional": { "if": "!selectedComponent" },
"bindings": { "children": "'Select a component to edit its properties'" }
}
]
}

View File

@@ -0,0 +1,16 @@
{
"id": "schema-editor-sidebar",
"type": "div",
"props": {
"className": "w-64 border-r border-border bg-card"
},
"children": [
{
"id": "component-palette-container",
"type": "ComponentPalette",
"bindings": {
"onDragStart": { "source": "onDragStart" }
}
}
]
}

View File

@@ -0,0 +1,62 @@
{
"id": "schema-editor-status-bar",
"type": "div",
"props": {
"className": "border-t border-border px-4 py-2 bg-card flex items-center justify-between"
},
"bindings": {
"className": {
"source": "className",
"transform": "className ? `border-t border-border px-4 py-2 bg-card flex items-center justify-between ${className}` : 'border-t border-border px-4 py-2 bg-card flex items-center justify-between'"
}
},
"children": [
{
"id": "status-info",
"type": "div",
"props": { "className": "flex items-center gap-4 text-sm" },
"children": [
{
"id": "component-count",
"type": "span",
"props": { "className": "text-muted-foreground" },
"children": [
{
"type": "span",
"props": { "className": "font-medium text-foreground" },
"bindings": { "children": "componentCount" }
},
{
"type": "span",
"bindings": {
"children": {
"source": "componentCount",
"transform": "componentCount !== 1 ? ' components' : ' component'"
}
}
}
]
},
{
"id": "selected-type",
"type": "span",
"props": { "className": "text-muted-foreground" },
"conditional": { "if": "selectedComponentType" },
"bindings": {
"children": {
"source": "selectedComponentType",
"transform": "`Type: ${selectedComponentType}`"
}
}
},
{
"id": "unsaved-indicator",
"type": "span",
"props": { "className": "text-amber-600 font-medium" },
"conditional": { "if": "hasUnsavedChanges" },
"bindings": { "children": "'Unsaved changes'" }
}
]
}
]
}

View File

@@ -0,0 +1,98 @@
{
"id": "schema-editor-toolbar",
"type": "div",
"props": {
"className": "border-b border-border px-6 py-3 bg-card"
},
"children": [
{
"id": "toolbar-content",
"type": "div",
"props": { "className": "flex justify-between items-center" },
"children": [
{
"id": "toolbar-left",
"type": "div",
"props": { "className": "flex flex-col gap-1" },
"children": [
{
"id": "toolbar-title",
"type": "span",
"props": {
"className": "text-lg font-bold bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent"
},
"bindings": { "children": "'Schema Editor'" }
}
]
},
{
"id": "toolbar-actions",
"type": "div",
"props": { "className": "flex gap-2" },
"children": [
{
"id": "import-button",
"type": "Button",
"props": {
"variant": "outline",
"size": "sm"
},
"bindings": {
"onClick": { "source": "onImport" },
"children": "'Import'"
}
},
{
"id": "export-button",
"type": "Button",
"props": {
"variant": "outline",
"size": "sm"
},
"bindings": {
"onClick": { "source": "onExport" },
"children": "'Export'"
}
},
{
"id": "copy-button",
"type": "Button",
"props": {
"variant": "outline",
"size": "sm"
},
"bindings": {
"onClick": { "source": "onCopy" },
"children": "'Copy'"
}
},
{
"id": "preview-button",
"type": "Button",
"props": {
"variant": "outline",
"size": "sm"
},
"bindings": {
"onClick": { "source": "onPreview" },
"children": "'Preview'"
}
},
{
"id": "clear-button",
"type": "Button",
"props": {
"variant": "destructive",
"size": "sm"
},
"bindings": {
"onClick": { "source": "onClear" },
"children": "'Clear'"
}
}
]
}
]
}
]
}

View File

@@ -1,48 +0,0 @@
import { CanvasRenderer } from '@/components/molecules/CanvasRenderer'
import { UIComponent } from '@/types/json-ui'
interface SchemaEditorCanvasProps {
components: UIComponent[]
selectedId: string | null
hoveredId: string | null
draggedOverId: string | null
dropPosition: 'before' | 'after' | 'inside' | null
onSelect: (id: string | null) => void
onHover: (id: string | null) => void
onHoverEnd: () => void
onDragOver: (id: string, e: React.DragEvent) => void
onDragLeave: (e: React.DragEvent) => void
onDrop: (targetId: string, e: React.DragEvent) => void
}
export function SchemaEditorCanvas({
components,
selectedId,
hoveredId,
draggedOverId,
dropPosition,
onSelect,
onHover,
onHoverEnd,
onDragOver,
onDragLeave,
onDrop,
}: SchemaEditorCanvasProps) {
return (
<div className="flex-1 flex flex-col">
<CanvasRenderer
components={components}
selectedId={selectedId}
hoveredId={hoveredId}
draggedOverId={draggedOverId}
dropPosition={dropPosition}
onSelect={onSelect}
onHover={onHover}
onHoverEnd={onHoverEnd}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
/>
</div>
)
}

View File

@@ -1,102 +0,0 @@
import { UIComponent, PageSchema } from '@/types/json-ui'
import { ComponentDefinition } from '@/lib/component-definition-types'
import { SchemaEditorToolbar } from './SchemaEditorToolbar'
import { SchemaEditorSidebar } from './SchemaEditorSidebar'
import { SchemaEditorCanvas } from './SchemaEditorCanvas'
import { SchemaEditorPropertiesPanel } from './SchemaEditorPropertiesPanel'
interface SchemaEditorLayoutProps {
components: UIComponent[]
selectedId: string | null
hoveredId: string | null
draggedOverId: string | null
dropPosition: 'before' | 'after' | 'inside' | null
selectedComponent: UIComponent | null
onSelect: (id: string | null) => void
onHover: (id: string | null) => void
onHoverEnd: () => void
onComponentDragStart: (component: ComponentDefinition, e: React.DragEvent) => void
onTreeDragStart: (id: string, e: React.DragEvent) => void
onDragOver: (id: string, e: React.DragEvent) => void
onDragLeave: (e: React.DragEvent) => void
onDrop: (targetId: string, e: React.DragEvent) => void
onUpdate: (updates: Partial<UIComponent>) => void
onDelete: () => void
onImport: () => void
onExport: () => void
onCopy: () => void
onPreview: () => void
onClear: () => void
}
export function SchemaEditorLayout({
components,
selectedId,
hoveredId,
draggedOverId,
dropPosition,
selectedComponent,
onSelect,
onHover,
onHoverEnd,
onComponentDragStart,
onTreeDragStart,
onDragOver,
onDragLeave,
onDrop,
onUpdate,
onDelete,
onImport,
onExport,
onCopy,
onPreview,
onClear,
}: SchemaEditorLayoutProps) {
return (
<div className="h-full flex flex-col bg-background">
<SchemaEditorToolbar
onImport={onImport}
onExport={onExport}
onCopy={onCopy}
onPreview={onPreview}
onClear={onClear}
/>
<div className="flex-1 flex overflow-hidden">
<SchemaEditorSidebar onDragStart={onComponentDragStart} />
<SchemaEditorCanvas
components={components}
selectedId={selectedId}
hoveredId={hoveredId}
draggedOverId={draggedOverId}
dropPosition={dropPosition}
onSelect={onSelect}
onHover={onHover}
onHoverEnd={onHoverEnd}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
/>
<SchemaEditorPropertiesPanel
components={components}
selectedId={selectedId}
hoveredId={hoveredId}
draggedOverId={draggedOverId}
dropPosition={dropPosition}
selectedComponent={selectedComponent}
onSelect={onSelect}
onHover={onHover}
onHoverEnd={onHoverEnd}
onDragStart={onTreeDragStart}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
onUpdate={onUpdate}
onDelete={onDelete}
/>
</div>
</div>
)
}

View File

@@ -1,71 +0,0 @@
import { ComponentTree } from '@/components/molecules/ComponentTree'
import { PropertyEditor } from '@/components/molecules/PropertyEditor'
import { Separator, Stack } from '@/components/atoms'
import { UIComponent } from '@/types/json-ui'
interface SchemaEditorPropertiesPanelProps {
components: UIComponent[]
selectedId: string | null
hoveredId: string | null
draggedOverId: string | null
dropPosition: 'before' | 'after' | 'inside' | null
selectedComponent: UIComponent | null
onSelect: (id: string | null) => void
onHover: (id: string | null) => void
onHoverEnd: () => void
onDragStart: (id: string, e: React.DragEvent) => void
onDragOver: (id: string, e: React.DragEvent) => void
onDragLeave: (e: React.DragEvent) => void
onDrop: (targetId: string, e: React.DragEvent) => void
onUpdate: (updates: Partial<UIComponent>) => void
onDelete: () => void
}
export function SchemaEditorPropertiesPanel({
components,
selectedId,
hoveredId,
draggedOverId,
dropPosition,
selectedComponent,
onSelect,
onHover,
onHoverEnd,
onDragStart,
onDragOver,
onDragLeave,
onDrop,
onUpdate,
onDelete,
}: SchemaEditorPropertiesPanelProps) {
return (
<Stack direction="vertical" spacing="none" className="w-80 border-l border-border bg-card">
<div className="flex-1 overflow-hidden">
<ComponentTree
components={components}
selectedId={selectedId}
hoveredId={hoveredId}
draggedOverId={draggedOverId}
dropPosition={dropPosition}
onSelect={onSelect}
onHover={onHover}
onHoverEnd={onHoverEnd}
onDragStart={onDragStart}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
/>
</div>
<Separator />
<div className="flex-1 overflow-hidden">
<PropertyEditor
component={selectedComponent}
onUpdate={onUpdate}
onDelete={onDelete}
/>
</div>
</Stack>
)
}

View File

@@ -1,14 +0,0 @@
import { ComponentPalette } from '@/components/molecules/ComponentPalette'
import { ComponentDefinition } from '@/lib/component-definition-types'
interface SchemaEditorSidebarProps {
onDragStart: (component: ComponentDefinition, e: React.DragEvent) => void
}
export function SchemaEditorSidebar({ onDragStart }: SchemaEditorSidebarProps) {
return (
<div className="w-64 border-r border-border bg-card">
<ComponentPalette onDragStart={onDragStart} />
</div>
)
}

View File

@@ -1,50 +0,0 @@
import { cn } from '@/lib/utils'
import { Badge, Chip, Text, Flex } from '@/components/atoms'
interface SchemaEditorStatusBarProps {
componentCount: number
selectedComponentType?: string
hasUnsavedChanges?: boolean
className?: string
}
export function SchemaEditorStatusBar({
componentCount,
selectedComponentType,
hasUnsavedChanges = false,
className
}: SchemaEditorStatusBarProps) {
return (
<div className={cn(
"border-t border-border px-4 py-2 bg-card flex items-center justify-between",
className
)}>
<Flex align="center" gap="lg">
<Text variant="caption">
<span className="font-medium text-foreground">{componentCount}</span> component{componentCount !== 1 ? 's' : ''}
</Text>
{selectedComponentType && (
<Flex align="center" gap="sm">
<Text variant="caption">Selected:</Text>
<Chip
variant="default"
size="sm"
className="font-mono"
>
{selectedComponentType}
</Chip>
</Flex>
)}
</Flex>
<Flex align="center" gap="sm">
{hasUnsavedChanges && (
<Badge variant="outline" size="sm">
Unsaved changes
</Badge>
)}
</Flex>
</div>
)
}

View File

@@ -1,90 +0,0 @@
import {
Download,
Upload,
Play,
Trash,
Copy,
} from '@phosphor-icons/react'
import {
Heading,
TextGradient,
Text,
Separator,
Stack,
ActionButton,
Flex
} from '@/components/atoms'
interface SchemaEditorToolbarProps {
onImport: () => void
onExport: () => void
onCopy: () => void
onPreview: () => void
onClear: () => void
}
export function SchemaEditorToolbar({
onImport,
onExport,
onCopy,
onPreview,
onClear,
}: SchemaEditorToolbarProps) {
return (
<div className="border-b border-border px-6 py-3 bg-card">
<Flex justify="between" align="center">
<Stack direction="vertical" spacing="xs">
<TextGradient
from="primary"
to="accent"
className="text-2xl font-bold"
>
Schema Editor
</TextGradient>
<Text variant="muted">
Build JSON UI schemas with drag-and-drop
</Text>
</Stack>
<Flex align="center" gap="sm">
<ActionButton
icon={<Upload size={16} />}
label="Import"
onClick={onImport}
variant="outline"
size="sm"
/>
<ActionButton
icon={<Copy size={16} />}
label="Copy JSON"
onClick={onCopy}
variant="outline"
size="sm"
/>
<ActionButton
icon={<Download size={16} />}
label="Export"
onClick={onExport}
variant="outline"
size="sm"
/>
<Separator orientation="vertical" className="h-6" />
<ActionButton
icon={<Play size={16} />}
label="Preview"
onClick={onPreview}
variant="outline"
size="sm"
/>
<ActionButton
icon={<Trash size={16} />}
label="Clear"
onClick={onClear}
variant="destructive"
size="sm"
/>
</Flex>
</Flex>
</div>
)
}

View File

@@ -1,7 +1,2 @@
export { SchemaEditorLayout } from './SchemaEditorLayout'
export { SchemaEditorCanvas } from './SchemaEditorCanvas'
export { SchemaEditorPropertiesPanel } from './SchemaEditorPropertiesPanel'
export { SchemaEditorSidebar } from './SchemaEditorSidebar'
export { SchemaEditorStatusBar } from './SchemaEditorStatusBar'
export { SchemaEditorToolbar } from './SchemaEditorToolbar'
export { SchemaEditorLayout, SchemaEditorCanvas, SchemaEditorPropertiesPanel, SchemaEditorSidebar, SchemaEditorStatusBar, SchemaEditorToolbar } from '@/lib/json-ui/json-components'
export { JSONUIShowcase } from '../JSONUIShowcase'

View File

@@ -128,3 +128,9 @@ export * from './toolbar-actions'
export * from './app-header'
export * from './loading-screen'
export * from './sparkle'
export * from './schema-editor-canvas'
export * from './schema-editor-layout'
export * from './schema-editor-properties-panel'
export * from './schema-editor-sidebar'
export * from './schema-editor-status-bar'
export * from './schema-editor-toolbar'

View File

@@ -0,0 +1,15 @@
import { UIComponent } from '@/types/json-ui'
export interface SchemaEditorCanvasProps {
components: UIComponent[]
selectedId: string | null
hoveredId: string | null
draggedOverId: string | null
dropPosition: 'before' | 'after' | 'inside' | null
onSelect: (id: string | null) => void
onHover: (id: string | null) => void
onHoverEnd: () => void
onDragOver: (id: string, e: React.DragEvent) => void
onDragLeave: (e: React.DragEvent) => void
onDrop: (targetId: string, e: React.DragEvent) => void
}

View File

@@ -0,0 +1,26 @@
import { UIComponent } from '@/types/json-ui'
import { ComponentDefinition } from '@/lib/component-definition-types'
export interface SchemaEditorLayoutProps {
components: UIComponent[]
selectedId: string | null
hoveredId: string | null
draggedOverId: string | null
dropPosition: 'before' | 'after' | 'inside' | null
selectedComponent: UIComponent | null
onSelect: (id: string | null) => void
onHover: (id: string | null) => void
onHoverEnd: () => void
onComponentDragStart: (component: ComponentDefinition, e: React.DragEvent) => void
onTreeDragStart: (id: string, e: React.DragEvent) => void
onDragOver: (id: string, e: React.DragEvent) => void
onDragLeave: (e: React.DragEvent) => void
onDrop: (targetId: string, e: React.DragEvent) => void
onUpdate: (updates: Partial<UIComponent>) => void
onDelete: () => void
onImport: () => void
onExport: () => void
onCopy: () => void
onPreview: () => void
onClear: () => void
}

View File

@@ -0,0 +1,19 @@
import { UIComponent } from '@/types/json-ui'
export interface SchemaEditorPropertiesPanelProps {
components: UIComponent[]
selectedId: string | null
hoveredId: string | null
draggedOverId: string | null
dropPosition: 'before' | 'after' | 'inside' | null
selectedComponent: UIComponent | null
onSelect: (id: string | null) => void
onHover: (id: string | null) => void
onHoverEnd: () => void
onDragStart: (id: string, e: React.DragEvent) => void
onDragOver: (id: string, e: React.DragEvent) => void
onDragLeave: (e: React.DragEvent) => void
onDrop: (targetId: string, e: React.DragEvent) => void
onUpdate: (updates: Partial<UIComponent>) => void
onDelete: () => void
}

View File

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

View File

@@ -0,0 +1,6 @@
export interface SchemaEditorStatusBarProps {
componentCount: number
selectedComponentType?: string
hasUnsavedChanges?: boolean
className?: string
}

View File

@@ -0,0 +1,7 @@
export interface SchemaEditorToolbarProps {
onImport: () => void
onExport: () => void
onCopy: () => void
onPreview: () => void
onClear: () => void
}

View File

@@ -49,6 +49,12 @@ import type {
DataSourceManagerProps,
NavigationMenuProps,
TreeListPanelProps,
SchemaEditorCanvasProps,
SchemaEditorLayoutProps,
SchemaEditorPropertiesPanelProps,
SchemaEditorSidebarProps,
SchemaEditorStatusBarProps,
SchemaEditorToolbarProps,
ActionButtonProps,
ActionCardProps,
ActionIconProps,
@@ -265,6 +271,12 @@ import emptyCanvasStateDef from '@/components/json-definitions/empty-canvas-stat
import schemaCodeViewerDef from '@/components/json-definitions/schema-code-viewer.json'
import toolbarActionsDef from '@/components/json-definitions/toolbar-actions.json'
import appHeaderDef from '@/components/json-definitions/app-header.json'
import schemaEditorCanvasDef from '@/components/json-definitions/schema-editor-canvas.json'
import schemaEditorLayoutDef from '@/components/json-definitions/schema-editor-layout.json'
import schemaEditorPropertiesPanelDef from '@/components/json-definitions/schema-editor-properties-panel.json'
import schemaEditorSidebarDef from '@/components/json-definitions/schema-editor-sidebar.json'
import schemaEditorStatusBarDef from '@/components/json-definitions/schema-editor-status-bar.json'
import schemaEditorToolbarDef from '@/components/json-definitions/schema-editor-toolbar.json'
// Create pure JSON components (no hooks)
export const BindingIndicator = createJsonComponent<BindingIndicatorProps>(bindingIndicatorDef)
@@ -374,6 +386,12 @@ export const EmptyCanvasState = createJsonComponent<EmptyCanvasStateProps>(empty
export const SchemaCodeViewer = createJsonComponent<SchemaCodeViewerProps>(schemaCodeViewerDef)
export const ToolbarActions = createJsonComponent<ToolbarActionsProps>(toolbarActionsDef)
export const AppHeader = createJsonComponent<AppHeaderProps>(appHeaderDef)
export const SchemaEditorCanvas = createJsonComponent<SchemaEditorCanvasProps>(schemaEditorCanvasDef)
export const SchemaEditorLayout = createJsonComponent<SchemaEditorLayoutProps>(schemaEditorLayoutDef)
export const SchemaEditorPropertiesPanel = createJsonComponent<SchemaEditorPropertiesPanelProps>(schemaEditorPropertiesPanelDef)
export const SchemaEditorSidebar = createJsonComponent<SchemaEditorSidebarProps>(schemaEditorSidebarDef)
export const SchemaEditorStatusBar = createJsonComponent<SchemaEditorStatusBarProps>(schemaEditorStatusBarDef)
export const SchemaEditorToolbar = createJsonComponent<SchemaEditorToolbarProps>(schemaEditorToolbarDef)
// Create JSON components with hooks
export const SaveIndicator = createJsonComponentWithHooks<SaveIndicatorProps>(saveIndicatorDef, {