mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
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:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"timestamp": "2026-01-21T03:02:07.273Z",
|
||||
"timestamp": "2026-01-21T03:13:44.395Z",
|
||||
"issues": [
|
||||
{
|
||||
"severity": "warning",
|
||||
|
||||
26
src/components/json-definitions/schema-editor-canvas.json
Normal file
26
src/components/json-definitions/schema-editor-canvas.json
Normal 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" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
74
src/components/json-definitions/schema-editor-layout.json
Normal file
74
src/components/json-definitions/schema-editor-layout.json
Normal 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" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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'" }
|
||||
}
|
||||
]
|
||||
}
|
||||
16
src/components/json-definitions/schema-editor-sidebar.json
Normal file
16
src/components/json-definitions/schema-editor-sidebar.json
Normal 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" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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'" }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
98
src/components/json-definitions/schema-editor-toolbar.json
Normal file
98
src/components/json-definitions/schema-editor-toolbar.json
Normal 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'"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
15
src/lib/json-ui/interfaces/schema-editor-canvas.ts
Normal file
15
src/lib/json-ui/interfaces/schema-editor-canvas.ts
Normal 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
|
||||
}
|
||||
26
src/lib/json-ui/interfaces/schema-editor-layout.ts
Normal file
26
src/lib/json-ui/interfaces/schema-editor-layout.ts
Normal 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
|
||||
}
|
||||
19
src/lib/json-ui/interfaces/schema-editor-properties-panel.ts
Normal file
19
src/lib/json-ui/interfaces/schema-editor-properties-panel.ts
Normal 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
|
||||
}
|
||||
5
src/lib/json-ui/interfaces/schema-editor-sidebar.ts
Normal file
5
src/lib/json-ui/interfaces/schema-editor-sidebar.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { ComponentDefinition } from '@/lib/component-definition-types'
|
||||
|
||||
export interface SchemaEditorSidebarProps {
|
||||
onDragStart: (component: ComponentDefinition, e: React.DragEvent) => void
|
||||
}
|
||||
6
src/lib/json-ui/interfaces/schema-editor-status-bar.ts
Normal file
6
src/lib/json-ui/interfaces/schema-editor-status-bar.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface SchemaEditorStatusBarProps {
|
||||
componentCount: number
|
||||
selectedComponentType?: string
|
||||
hasUnsavedChanges?: boolean
|
||||
className?: string
|
||||
}
|
||||
7
src/lib/json-ui/interfaces/schema-editor-toolbar.ts
Normal file
7
src/lib/json-ui/interfaces/schema-editor-toolbar.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface SchemaEditorToolbarProps {
|
||||
onImport: () => void
|
||||
onExport: () => void
|
||||
onCopy: () => void
|
||||
onPreview: () => void
|
||||
onClear: () => void
|
||||
}
|
||||
@@ -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, {
|
||||
|
||||
Reference in New Issue
Block a user