feat: update json-components-registry with new components- Remove deprecated components from registry- Add new components: ComponentTreeEmptyState, ComponentTreeHeader, ComponentTreeNodes, ConditionalWrapper, DataSourceGroupSection, DataSourceIdField, DataSourceManagerHeader- Ensure all new components are categorized and marked as supported

This commit is contained in:
2026-01-20 00:51:26 +00:00
parent a4bf2ee5a6
commit f7683ff19b
71 changed files with 2667 additions and 591 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,10 @@
// Auto-generated - only exports existing TSX files
export { FlexLayout } from '@/lib/json-ui/json-components'
export { IconRenderer } from '@/lib/json-ui/json-components'
export { ConditionalWrapper } from '@/lib/json-ui/json-components'
export { DataCard } from '@/lib/json-ui/json-components'
export { Panel } from '@/lib/json-ui/json-components'
export { DynamicText } from '@/lib/json-ui/json-components'
export { GridLayout } from '@/lib/json-ui/json-components'
export { RepeatWrapper } from '@/lib/json-ui/json-components'

View File

@@ -0,0 +1,29 @@
{
"id": "component-tree-empty-state",
"props": {
"children": [
{
"props": {
"className": "w-12 h-12 mx-auto mb-4 opacity-50"
},
"type": "Icon"
},
{
"props": {
"className": "text-sm",
"text": "{componentTreeConfig.emptyState.title}"
},
"type": "Text"
},
{
"props": {
"className": "text-xs mt-1",
"text": "{componentTreeConfig.emptyState.description}"
},
"type": "Text"
}
],
"className": "p-8 text-center text-muted-foreground"
},
"type": "ComponentTreeEmptyState"
}

View File

@@ -0,0 +1,126 @@
{
"children": [
{
"children": [
{
"props": {
"icon": {
"source": "data.icon"
},
"subtitle": {
"source": "data.count > 1 ? data.config.subtitle.plural : data.config.subtitle.singular"
},
"title": {
"source": "data.config.title"
}
},
"type": "PanelHeader"
},
{
"else": null,
"if": "data.count > 0",
"then": {
"children": [
{
"children": [
{
"children": [
{
"children": [
{
"props": {
"size": 16
},
"type": "CaretDown"
}
],
"props": {
"className": "h-7 w-7 p-0",
"onClick": {
"source": "data.onExpandAll"
},
"size": "sm",
"variant": "ghost"
},
"type": "Button"
}
],
"type": "TooltipTrigger"
},
{
"children": [
{
"source": "data.config.tooltips.expandAll"
}
],
"type": "TooltipContent"
}
],
"type": "Tooltip"
},
{
"children": [
{
"children": [
{
"children": [
{
"props": {
"size": 16
},
"type": "CaretRight"
}
],
"props": {
"className": "h-7 w-7 p-0",
"onClick": {
"source": "data.onCollapseAll"
},
"size": "sm",
"variant": "ghost"
},
"type": "Button"
}
],
"type": "TooltipTrigger"
},
{
"children": [
{
"source": "data.config.tooltips.collapseAll"
}
],
"type": "TooltipContent"
}
],
"type": "Tooltip"
}
],
"props": {
"className": "flex gap-1"
},
"type": "div"
}
}
],
"props": {
"className": "flex items-center justify-between mb-2"
},
"type": "div"
}
],
"className": "p-4",
"id": "component-tree-header",
"props": {
"componentsCount": {
"source": "data.count"
},
"onCollapseAll": {
"source": "data.onCollapseAll"
},
"onExpandAll": {
"source": "data.onExpandAll"
}
},
"type": "ComponentTreeHeader"
}

View File

@@ -0,0 +1,104 @@
{
"children": [
{
"props": {
"component": {
"source": "data.component"
},
"depth": {
"source": "data.depth"
},
"dropPosition": {
"source": "data.dropPosition"
},
"hasChildren": {
"source": "data.hasChildren"
},
"isDraggedOver": {
"source": "data.isDraggedOver"
},
"isExpanded": {
"source": "data.isExpanded"
},
"isHovered": {
"source": "data.isHovered"
},
"isSelected": {
"source": "data.isSelected"
},
"onDragLeave": {
"source": "data.onDragLeave"
},
"onDragOver": {
"source": "data.onDragOver"
},
"onDragStart": {
"source": "data.onDragStart"
},
"onDrop": {
"source": "data.onDrop"
},
"onHover": {
"source": "data.onHover"
},
"onHoverEnd": {
"source": "data.onHoverEnd"
},
"onSelect": {
"source": "data.onSelect"
},
"onToggleExpand": {
"source": "data.onToggleExpand"
}
},
"type": "ComponentTreeNode"
}
],
"className": "component-tree-nodes",
"id": "component-tree-nodes",
"props": {
"components": {
"source": "data.components"
},
"draggedOverId": {
"source": "data.draggedOverId"
},
"dropPosition": {
"source": "data.dropPosition"
},
"expandedIds": {
"source": "data.expandedIds"
},
"hoveredId": {
"source": "data.hoveredId"
},
"onDragLeave": {
"source": "data.onDragLeave"
},
"onDragOver": {
"source": "data.onDragOver"
},
"onDragStart": {
"source": "data.onDragStart"
},
"onDrop": {
"source": "data.onDrop"
},
"onHover": {
"source": "data.onHover"
},
"onHoverEnd": {
"source": "data.onHoverEnd"
},
"onSelect": {
"source": "data.onSelect"
},
"onToggleExpand": {
"source": "data.onToggleExpand"
},
"selectedId": {
"source": "data.selectedId"
}
},
"type": "ComponentTreeNodes"
}

View File

@@ -0,0 +1,51 @@
{
"bindings": {},
"children": [
{
"props": {
"text": "Conditional content"
},
"type": "Text"
}
],
"className": "optional-classes",
"conditional": {
"else": "renderFallback",
"if": "data.condition",
"then": "renderChildren"
},
"dataBinding": "data.somePath",
"events": [
{
"actions": [
{
"id": "yourActionId",
"type": "custom"
}
],
"event": "click"
}
],
"id": "conditional-wrapper",
"loop": {
"indexVar": "index",
"itemVar": "item",
"source": "data.childrenList"
},
"props": {
"children": {
"source": "data.children"
},
"className": {
"source": "data.className"
},
"condition": {
"source": "data.condition"
},
"fallback": {
"source": "data.fallback"
}
},
"style": {},
"type": "ConditionalWrapper"
}

View File

@@ -0,0 +1,20 @@
{
"bindings": {},
"children": [],
"className": "",
"conditional": null,
"dataBinding": null,
"events": [],
"id": "data-card",
"loop": null,
"props": {
"children": "",
"className": "",
"description": "",
"gradient": "",
"icon": "",
"title": ""
},
"style": {},
"type": "DataCard"
}

View File

@@ -0,0 +1,44 @@
{
"children": [
{
"children": [
{
"children": "Label",
"props": {},
"type": "text"
},
{
"children": " (0)",
"props": {},
"type": "text"
}
],
"props": {
"className": "text-sm font-semibold mb-3",
"icon": {}
},
"type": "IconText"
},
{
"children": [],
"props": {
"direction": "vertical",
"spacing": "sm"
},
"type": "Stack"
}
],
"className": "",
"dataBinding": "data.path",
"id": "data-source-group-section",
"props": {
"dataSources": [],
"getDependents": {},
"icon": {},
"label": "",
"onDelete": {},
"onEdit": {}
},
"style": {},
"type": "DataSourceGroupSection"
}

View File

@@ -0,0 +1,45 @@
{
"children": [
{
"props": {
"children": {
"source": "data.label"
}
},
"type": "Label"
},
{
"props": {
"className": "font-mono",
"onChange": {
"source": "data.onChange",
"transform": "(e) => onChange(e.target.value)"
},
"placeholder": {
"source": "data.placeholder"
},
"value": {
"source": "data.editingSource.id"
}
},
"type": "Input"
}
],
"className": "space-y-2",
"id": "data-source-id-field",
"props": {
"editingSource": {
"source": "data.editingSource"
},
"label": {
"source": "data.label"
},
"onChange": {
"source": "data.onChange"
},
"placeholder": {
"source": "data.placeholder"
}
},
"type": "DataSourceIdField"
}

View File

@@ -0,0 +1,29 @@
{
"className": "optional classes",
"events": [
{
"actions": [
{
"id": "addDataSource",
"type": "custom"
}
],
"event": "click"
}
],
"id": "data-source-manager-header",
"props": {
"copy": {
"addLabel": "string",
"description": "string",
"menu": {
"kv": "string",
"static": "string"
},
"title": "string"
},
"onAdd": "(type: DataSourceType) => void"
},
"style": {},
"type": "DataSourceManagerHeader"
}

View File

@@ -0,0 +1,149 @@
{
"children": [
{
"children": [
{
"children": [
{
"props": {
"copy": {
"addLabel": {
"source": "data.source.actions.add"
},
"description": {
"source": "data.source.header.description"
},
"menu": {
"source": "data.source.menu"
},
"title": {
"source": "data.source.header.title"
}
},
"onAdd": [
{
"actions": [
{
"id": "handleAddDataSource",
"type": "custom"
}
],
"event": "click"
}
]
},
"type": "DataSourceManagerHeader"
}
],
"type": "CardHeader"
},
{
"children": [
{
"conditional": {
"else": {
"children": [
{
"props": {
"dataSources": {
"source": "groupedSources.kv"
},
"getDependents": {
"source": "data.getDependents"
},
"icon": {
"source": "data.icon.Database"
},
"label": {
"source": "data.source.groups.kv"
},
"onDelete": {
"source": "data.handleDeleteSource"
},
"onEdit": {
"source": "data.handleEditSource"
}
},
"type": "DataSourceGroupSection"
},
{
"props": {
"dataSources": {
"source": "groupedSources.static"
},
"getDependents": {
"source": "data.getDependents"
},
"icon": {
"source": "data.icon.FileText"
},
"label": {
"source": "data.source.groups.static"
},
"onDelete": {
"source": "data.handleDeleteSource"
},
"onEdit": {
"source": "data.handleEditSource"
}
},
"type": "DataSourceGroupSection"
}
],
"props": {
"direction": "vertical",
"spacing": "xl"
},
"type": "Stack"
},
"if": "localSources.length === 0",
"then": {
"description": {
"source": "data.source.emptyState.description"
},
"icon": {
"source": "data.icon.Database"
},
"title": {
"source": "data.source.emptyState.title"
}
}
},
"type": "EmptyState"
}
],
"type": "CardContent"
}
],
"type": "Card"
},
{
"props": {
"dataSource": {
"source": "editingSource"
},
"onOpenChange": {
"source": "setDialogOpen"
},
"onSave": {
"source": "handleSaveSource"
},
"open": {
"source": "dialogOpen"
}
},
"type": "DataSourceEditorDialog"
}
],
"className": "space-y-6",
"id": "data-source-manager",
"props": {
"dataSources": {
"source": "data.path"
},
"onChange": {
"source": "data.onChange"
}
},
"type": "DataSourceManager"
}

View File

@@ -0,0 +1,30 @@
{
"bindings": {
"value": {
"path": "data.value",
"source": "data.value",
"transform": "optional js expression"
}
},
"className": "dynamic-text-class",
"events": [
{
"actions": [
{
"id": "exampleActionId",
"type": "custom"
}
],
"event": "click"
}
],
"id": "dynamic-text",
"props": {
"className": "optional-class",
"currency": "USD",
"format": "text",
"locale": "en-US",
"value": "data.value"
},
"type": "DynamicText"
}

View File

@@ -0,0 +1,20 @@
{
"bindings": {},
"children": "...",
"className": "optional classes",
"conditional": {},
"dataBinding": "data.path",
"events": [],
"id": "flex-layout",
"loop": {},
"props": {
"align": "start",
"className": "",
"direction": "row",
"gap": "md",
"justify": "start",
"wrap": false
},
"style": {},
"type": "FlexLayout"
}

View File

@@ -0,0 +1,18 @@
{
"children": "...",
"className": "",
"id": "grid-layout",
"props": {
"className": "",
"cols": {
"base": 1,
"lg": 1,
"md": 1,
"sm": 1,
"xl": 1
},
"gap": "md"
},
"style": {},
"type": "GridLayout"
}

View File

@@ -0,0 +1,32 @@
{
"bindings": {
"name": {
"path": "optional.iconPath",
"source": "data.iconName",
"transform": "optional js expression"
}
},
"children": "text",
"className": "optional classes",
"dataBinding": "data.iconName",
"events": [
{
"actions": [
{
"id": "iconClickAction",
"type": "custom"
}
],
"event": "click"
}
],
"id": "icon-renderer",
"props": {
"className": "string",
"name": "string",
"size": "number",
"weight": "'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone'"
},
"style": {},
"type": "IconRenderer"
}

View File

@@ -0,0 +1,33 @@
{
"children": [],
"className": "kv-source-fields",
"events": [],
"id": "kv-source-fields",
"props": {
"copy": {
"defaultLabel": {
"source": "data.copy.defaultLabel"
},
"defaultPlaceholder": {
"source": "data.copy.defaultPlaceholder"
},
"keyHelp": {
"source": "data.copy.keyHelp"
},
"keyLabel": {
"source": "data.copy.keyLabel"
},
"keyPlaceholder": {
"source": "data.copy.keyPlaceholder"
}
},
"editingSource": {
"source": "data.editingSource"
},
"onUpdateField": {
"source": "actions.onUpdateField"
}
},
"style": {},
"type": "KvSourceFields"
}

View File

@@ -0,0 +1,109 @@
{
"bindings": {},
"children": [
{
"children": [
{
"else": null,
"if": "title || description || actions",
"then": {
"children": [
{
"children": [
{
"else": null,
"if": "title",
"then": {
"children": "title",
"props": {
"className": "font-semibold text-lg"
},
"type": "h3"
}
},
{
"else": null,
"if": "description",
"then": {
"children": "description",
"props": {
"className": "text-sm text-muted-foreground"
},
"type": "p"
}
}
],
"props": {
"className": "space-y-1"
},
"type": "div"
},
{
"else": null,
"if": "actions",
"then": {
"children": "actions",
"type": "div"
}
}
],
"props": {
"className": "flex items-start justify-between p-4 border-b"
},
"type": "div"
}
},
{
"children": "children",
"props": {
"className": "p-4"
},
"type": "CardContent"
}
],
"props": {
"className": "border-border"
},
"type": "Card"
}
],
"className": "",
"conditional": {},
"dataBinding": "data.panel",
"events": {},
"id": "panel",
"loop": {},
"props": {
"actions": {
"optional": true,
"type": "ReactNode"
},
"children": {
"optional": false,
"type": "ReactNode"
},
"className": {
"optional": true,
"type": "string"
},
"description": {
"optional": true,
"type": "string"
},
"title": {
"optional": true,
"type": "string"
},
"variant": {
"enum": [
"default",
"bordered",
"elevated"
],
"optional": true,
"type": "string"
}
},
"style": {},
"type": "Panel"
}

View File

@@ -0,0 +1,53 @@
{
"children": [
{
"children": [
{
"props": {
"icon": {
"props": {
"className": "w-12 h-12"
},
"type": "Icon"
}
},
"type": "EmptyStateIcon"
},
{
"children": [
{
"props": {
"children": "{propertyEditorConfig.emptyState.title}",
"variant": "small"
},
"type": "Text"
},
{
"props": {
"children": "{propertyEditorConfig.emptyState.description}",
"variant": "caption"
},
"type": "Text"
}
],
"props": {
"align": "center",
"direction": "vertical",
"spacing": "xs"
},
"type": "Stack"
}
],
"props": {
"align": "center",
"direction": "vertical",
"spacing": "md"
},
"type": "Stack"
}
],
"className": "h-full flex flex-col items-center justify-center p-8",
"id": "property-editor-empty-state",
"props": {},
"type": "PropertyEditorEmptyState"
}

View File

@@ -0,0 +1,27 @@
{
"bindings": {},
"children": [],
"className": "optional classes",
"conditional": {},
"dataBinding": "data.path",
"events": [
{
"actions": [
{
"id": "deleteAction",
"type": "custom"
}
],
"event": "click"
}
],
"id": "property-editor-header",
"loop": {},
"props": {
"componentId": "string",
"componentLabel": "string",
"onDelete": "function"
},
"style": {},
"type": "PropertyEditorHeader"
}

View File

@@ -0,0 +1,49 @@
{
"children": [
{
"children": "{title}",
"props": {
"variant": "caption"
},
"type": "Text"
},
{
"children": {
"props": {
"label": "{field.label}",
"name": "{field.name}",
"onChange": "{onChange}",
"options": "{field.options}",
"type": "{field.type}",
"value": "{component.props?.[field.name]}"
},
"type": "PropertyEditorField"
},
"loop": {
"indexVar": "index",
"itemVar": "field",
"source": "fields"
}
}
],
"className": "optional classes",
"dataBinding": "data.propertyEditor",
"events": [
{
"actions": [
{
"id": "onChangeHandler",
"type": "custom"
}
],
"event": "change"
}
],
"id": "property-editor-section",
"props": {
"fields": [],
"title": ""
},
"style": {},
"type": "PropertyEditorSection"
}

View File

@@ -0,0 +1,37 @@
{
"children": [
{
"children": "emptyMessage",
"props": {
"className": "text-center text-muted-foreground text-sm p-4"
},
"type": "div"
},
{
"children": [
{
"children": "render(item, index)",
"props": {
"key": "index"
},
"type": "div"
}
],
"props": {
"className": "flex flex-col gapClasses[gap]"
},
"type": "div"
}
],
"className": "optional classes",
"id": "repeat-wrapper",
"props": {
"className": "",
"emptyMessage": "",
"gap": "md",
"items": [],
"render": "function(item, index) { return item; }"
},
"style": {},
"type": "RepeatWrapper"
}

View File

@@ -0,0 +1,28 @@
{
"children": [
{
"props": {
"children": "{label}"
},
"type": "Label"
},
{
"props": {
"className": "font-mono text-sm h-24",
"onChange": "handleChange",
"placeholder": "{placeholder}",
"value": "JSON.stringify(editingSource.defaultValue, null, 2)"
},
"type": "Textarea"
}
],
"className": "space-y-2",
"id": "static-source-fields",
"props": {
"editingSource": {},
"label": "",
"onUpdateField": null,
"placeholder": ""
},
"type": "StaticSourceFields"
}

View File

@@ -1,2 +1,11 @@
// Auto-generated - only exports existing TSX files
export { PropertyEditorHeader } from '@/lib/json-ui/json-components'
export { PropertyEditorEmptyState } from '@/lib/json-ui/json-components'
export { PropertyEditorSection } from '@/lib/json-ui/json-components'
export { KvSourceFields } from '@/lib/json-ui/json-components'
export { ComponentTreeEmptyState } from '@/lib/json-ui/json-components'
export { ComponentTreeNodes } from '@/lib/json-ui/json-components'
export { ComponentTreeHeader } from '@/lib/json-ui/json-components'
export { DataSourceIdField } from '@/lib/json-ui/json-components'
export { StaticSourceFields } from '@/lib/json-ui/json-components'

View File

@@ -1,2 +1,5 @@
// Auto-generated - only exports existing TSX files
export { DataSourceGroupSection } from '@/lib/json-ui/json-components'
export { DataSourceManager } from '@/lib/json-ui/json-components'
export { DataSourceManagerHeader } from '@/lib/json-ui/json-components'

View File

@@ -0,0 +1,17 @@
{
"type": "ConditionalWrapper",
"wrapperRequired": true,
"load": {
"path": "@/components/atoms/ConditionalWrapper",
"export": "ConditionalWrapper"
},
"props": {
"condition": true,
"children": "Child content here",
"fallback": "Fallback content here",
"className": ""
},
"metadata": {
"notes": "Contains conditional logic - needs wrapper"
}
}

View File

@@ -0,0 +1,14 @@
{
"type": "DataCard",
"jsonCompatible": true,
"wrapperRequired": false,
"props": {
"title": "",
"description": "",
"icon": "",
"gradient": "",
"children": "",
"className": ""
},
"metadata": {}
}

View File

@@ -0,0 +1,18 @@
{
"type": "DynamicText",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/atoms/DynamicText",
"export": "DynamicText"
},
"props": {
"value": "data.value",
"format": "text",
"currency": "USD",
"locale": "en-US"
},
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,5 @@
{
"type": "FlexLayout",
"props": {},
"jsonCompatible": true
}

View File

@@ -0,0 +1,16 @@
{
"type": "GridLayout",
"jsonCompatible": true,
"wrapperRequired": false,
"props": {
"cols": {
"base": 1,
"sm": 1,
"md": 1,
"lg": 1,
"xl": 1
},
"gap": "md",
"className": ""
}
}

View File

@@ -0,0 +1,11 @@
{
"type": "IconRenderer",
"jsonCompatible": true,
"wrapperRequired": false,
"props": {
"name": "default-icon-name",
"size": 24,
"weight": "duotone",
"className": "optional-class"
}
}

View File

@@ -0,0 +1,13 @@
{
"type": "Panel",
"jsonCompatible": true,
"wrapperRequired": false,
"props": {
"title": "",
"description": "",
"actions": null,
"children": "Content goes here",
"className": "",
"variant": "default"
}
}

View File

@@ -0,0 +1,4 @@
{
"type": "RepeatWrapper",
"props": {}
}

View File

@@ -0,0 +1,4 @@
{
"type": "ComponentTreeEmptyState",
"props": {}
}

View File

@@ -0,0 +1,23 @@
{
"type": "ComponentTreeHeader",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/molecules/ComponentTreeHeader",
"export": "ComponentTreeHeader"
},
"props": {
"componentsCount": {
"source": "data.count"
},
"onExpandAll": {
"source": "data.onExpandAll"
},
"onCollapseAll": {
"source": "data.onCollapseAll"
}
},
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,56 @@
{
"type": "ComponentTreeNodes",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/molecules/ComponentTreeNodes",
"export": "ComponentTreeNodes"
},
"props": {
"components": {
"source": "data.components"
},
"expandedIds": {
"source": "data.expandedIds"
},
"selectedId": {
"source": "data.selectedId"
},
"hoveredId": {
"source": "data.hoveredId"
},
"draggedOverId": {
"source": "data.draggedOverId"
},
"dropPosition": {
"source": "data.dropPosition"
},
"onSelect": {
"source": "data.onSelect"
},
"onHover": {
"source": "data.onHover"
},
"onHoverEnd": {
"source": "data.onHoverEnd"
},
"onDragStart": {
"source": "data.onDragStart"
},
"onDragOver": {
"source": "data.onDragOver"
},
"onDragLeave": {
"source": "data.onDragLeave"
},
"onDrop": {
"source": "data.onDrop"
},
"onToggleExpand": {
"source": "data.onToggleExpand"
}
},
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,26 @@
{
"type": "DataSourceIdField",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/molecules/DataSourceIdField",
"export": "DataSourceIdField"
},
"props": {
"label": {
"source": "data.label"
},
"placeholder": {
"source": "data.placeholder"
},
"editingSource": {
"source": "data.editingSource"
},
"onChange": {
"source": "data.onChange"
}
},
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,37 @@
{
"type": "KvSourceFields",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/molecules/KvSourceFields",
"export": "KvSourceFields"
},
"props": {
"editingSource": {
"source": "data.editingSource"
},
"copy": {
"keyLabel": {
"source": "data.copy.keyLabel"
},
"keyPlaceholder": {
"source": "data.copy.keyPlaceholder"
},
"keyHelp": {
"source": "data.copy.keyHelp"
},
"defaultLabel": {
"source": "data.copy.defaultLabel"
},
"defaultPlaceholder": {
"source": "data.copy.defaultPlaceholder"
}
},
"onUpdateField": {
"source": "actions.onUpdateField"
}
},
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,4 @@
{
"type": "PropertyEditorEmptyState",
"props": {}
}

View File

@@ -0,0 +1 @@
{ "type": "PropertyEditorHeader", "props": { "componentId": "", "componentLabel": "", "onDelete": null } }

View File

@@ -0,0 +1,57 @@
{
"type": "PropertyEditorSection",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/molecules/PropertyEditorSection",
"export": "PropertyEditorSection"
},
"props": {
"title": "",
"fields": []
},
"className": "optional classes",
"style": {},
"dataBinding": "data.propertyEditor",
"events": [
{
"event": "change",
"actions": [
{
"id": "onChangeHandler",
"type": "custom"
}
]
}
],
"children": [
{
"type": "Text",
"props": {
"variant": "caption"
},
"children": "{title}"
},
{
"loop": {
"source": "fields",
"itemVar": "field",
"indexVar": "index"
},
"children": {
"type": "PropertyEditorField",
"props": {
"label": "{field.label}",
"name": "{field.name}",
"value": "{component.props?.[field.name]}",
"type": "{field.type}",
"options": "{field.options}",
"onChange": "{onChange}"
}
}
}
],
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,18 @@
{
"type": "StaticSourceFields",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {
"path": "@/components/molecules/StaticSourceFields",
"export": "StaticSourceFields"
},
"props": {
"editingSource": {},
"label": "",
"placeholder": "",
"onUpdateField": null
},
"metadata": {
"notes": "Contains hooks - needs wrapper"
}
}

View File

@@ -0,0 +1,4 @@
{
"type": "DataSourceGroupSection",
"props": {}
}

View File

@@ -0,0 +1,15 @@
{
"type": "DataSourceManagerHeader",
"props": {
"copy": {
"title": "Header Title",
"description": "Header Description",
"addLabel": "Add Data Source",
"menu": {
"kv": "KV Data Source",
"static": "Static Data Source"
}
},
"onAdd": "function reference"
}
}

View File

@@ -38,3 +38,51 @@ export * from './use-file-upload'
export * from './use-accordion'
export * from './use-binding-editor'
export * from './use-navigation-menu'
export * from './use-app-navigation'
export * from './use-project-export'
export * from './use-dynamic-text'
export * from './use-project-state'
export * from './use-save-indicator'
export * from './use-conflict-resolution-page'
export * from './use-redux-component-trees'
export * from './use-persistence-dashboard'
export * from './use-active-selection'
export * from './use-dialog-state'
export * from './use-app-shortcuts'
export * from './use-component-tree-builder'
export * from './use-app-project'
export * from './use-pwa'
export * from './use-file-operations'
export * from './use-project-manager'
export * from './use-schema-loader'
export * from './use-mobile'
export * from './use-app-bootstrap'
export * from './use-unified-storage'
export * from './use-d3-bar-chart'
export * from './use-redux-files'
export * from './use-static-source-fields'
export * from './use-keyboard-shortcuts'
export * from './use-component-binding-dialog'
export * from './use-project-manager-dialogs'
export * from './use-conflict-resolution'
export * from './use-last-saved'
export * from './use-component-tree-expansion'
export * from './use-tab-navigation'
export * from './use-template-explorer-actions'
export * from './use-redux-sync'
export * from './use-storage-backend-info'
export * from './use-component-tree-loader'
export * from './use-ai-operations'
export * from './use-github-build-status'
export * from './use-data-source-editor'
export * from './use-file-filters'
export * from './use-indexed-db'
export * from './use-project-loader'
export * from './use-router-navigation'
export * from './use-storage'
export * from './use-component-tree-nodes'
export * from './use-auto-repair'
export * from './use-code-explanation'
export * from './use-component-tree'
export * from './use-data-source-manager'
export * from './use-persistence'

View File

@@ -0,0 +1,19 @@
import { useState, useEffect } from 'react';
export const useComponentTreeNodes = (initialExpandedIds: Set<string>) => {
const [expandedIds, setExpandedIds] = useState(initialExpandedIds);
const toggleExpand = (id: string) => {
setExpandedIds((prev) => {
const newIds = new Set(prev);
if (newIds.has(id)) {
newIds.delete(id);
} else {
newIds.add(id);
}
return newIds;
});
};
return { expandedIds, toggleExpand };
};

View File

@@ -0,0 +1 @@
import { useState } from 'react'; import { DataSource } from '@/types/json-ui'; export function useDataSourceManager(initialDataSources: DataSource[]) { /* logic */ }

View File

@@ -0,0 +1,42 @@
import { useState, useEffect } from 'react';
export const useDynamicText = (value: any, format: string, currency: string, locale: string) => {
const [formattedValue, setFormattedValue] = useState('');
useEffect(() => {
const formatValue = () => {
if (value === null || value === undefined) return '';
switch (format) {
case 'number':
return typeof value === 'number' ? value.toLocaleString(locale) : value;
case 'currency':
return typeof value === 'number' ? new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value) : value;
case 'date':
try {
return new Date(value).toLocaleDateString(locale);
} catch {
return value;
}
case 'time':
try {
return new Date(value).toLocaleTimeString(locale);
} catch {
return value;
}
case 'datetime':
try {
return new Date(value).toLocaleString(locale);
} catch {
return value;
}
case 'boolean':
return value ? 'Yes' : 'No';
default:
return String(value);
}
};
setFormattedValue(formatValue());
}, [value, format, currency, locale]);
return formattedValue;
};

View File

@@ -0,0 +1,14 @@
import { useCallback } from 'react';
export const useStaticSourceFields = (onUpdateField) => {
const handleChange = useCallback((e) => {
try {
const parsed = JSON.parse(e.target.value);
onUpdateField('defaultValue', parsed);
} catch (err) {
// Invalid JSON, don't update
}
}, [onUpdateField]);
return { handleChange };
};

View File

@@ -2,6 +2,51 @@
* Hook Registry for JSON Components
* Allows JSON components to use custom React hooks
*/
import { useProjectExport } from '@/hooks/use-project-export'
import { useRoutePreload } from '@/hooks/use-route-preload'
import { useDynamicText } from '@/hooks/use-dynamic-text'
import { useProjectState } from '@/hooks/use-project-state'
import { useConflictResolutionPage } from '@/hooks/use-conflict-resolution-page'
import { useReduxComponentTrees } from '@/hooks/use-redux-component-trees'
import { usePersistenceDashboard } from '@/hooks/use-persistence-dashboard'
import { useActiveSelection } from '@/hooks/use-active-selection'
import { useDialogState } from '@/hooks/use-dialog-state'
import { useComponentTreeBuilder } from '@/hooks/use-component-tree-builder'
import { usePWA } from '@/hooks/use-pwa'
import { useFileOperations } from '@/hooks/use-file-operations'
import { useProjectManager } from '@/hooks/use-project-manager'
import { useSchemaLoader } from '@/hooks/use-schema-loader'
import { useIsMobile } from '@/hooks/use-mobile'
import { useAppBootstrap } from '@/hooks/use-app-bootstrap'
import { useUnifiedStorage } from '@/hooks/use-unified-storage'
import { useKV } from '@/hooks/use-kv'
import { useReduxFiles } from '@/hooks/use-redux-files'
import { useStaticSourceFields } from '@/hooks/use-static-source-fields'
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
import { useComponentBindingDialog } from '@/hooks/use-component-binding-dialog'
import { useProjectManagerDialogs } from '@/hooks/use-project-manager-dialogs'
import { useThemeConfig } from '@/hooks/use-theme-config'
import { useConflictResolution } from '@/hooks/use-conflict-resolution'
import { useLastSaved } from '@/hooks/use-last-saved'
import { useComponentTreeExpansion } from '@/hooks/use-component-tree-expansion'
import { useTabNavigation } from '@/hooks/use-tab-navigation'
import { useTemplateExplorerActions } from '@/hooks/use-template-explorer-actions'
import { useReduxSync } from '@/hooks/use-redux-sync'
import { useNavigationHistory } from '@/hooks/use-navigation-history'
import { useComponentTreeLoader } from '@/hooks/use-component-tree-loader'
import { useAIOperations } from '@/hooks/use-ai-operations'
import { useGithubBuildStatus } from '@/hooks/use-github-build-status'
import { useDataSourceEditor } from '@/hooks/use-data-source-editor'
import { useFileFilters } from '@/hooks/use-file-filters'
import { useIndexedDB } from '@/hooks/use-indexed-db'
import { useProjectLoader } from '@/hooks/use-project-loader'
import { useRouterNavigation } from '@/hooks/use-router-navigation'
import { useStorage } from '@/hooks/use-storage'
import { useComponentTreeNodes } from '@/hooks/use-component-tree-nodes'
import { useAutoRepair } from '@/hooks/use-auto-repair'
import { useCodeExplanation } from '@/hooks/use-code-explanation'
import { useDataSourceManager } from '@/hooks/use-data-source-manager'
import { usePersistence } from '@/hooks/use-persistence'
import { useSaveIndicator } from '@/hooks/use-save-indicator'
import { useComponentTree } from '@/hooks/use-component-tree'
import { useStorageBackendInfo } from '@/hooks/use-storage-backend-info'
@@ -39,6 +84,51 @@ export const hooksRegistry: HookRegistry = {
useAccordion,
useBindingEditor,
useNavigationMenu,
useProjectExport,
useRoutePreload,
useDynamicText,
useProjectState,
useConflictResolutionPage,
useReduxComponentTrees,
usePersistenceDashboard,
useActiveSelection,
useDialogState,
useComponentTreeBuilder,
usePWA,
useFileOperations,
useProjectManager,
useSchemaLoader,
useIsMobile,
useAppBootstrap,
useUnifiedStorage,
useKV,
useReduxFiles,
useStaticSourceFields,
useKeyboardShortcuts,
useComponentBindingDialog,
useProjectManagerDialogs,
useThemeConfig,
useConflictResolution,
useLastSaved,
useComponentTreeExpansion,
useTabNavigation,
useTemplateExplorerActions,
useReduxSync,
useNavigationHistory,
useComponentTreeLoader,
useAIOperations,
useGithubBuildStatus,
useDataSourceEditor,
useFileFilters,
useIndexedDB,
useProjectLoader,
useRouterNavigation,
useStorage,
useComponentTreeNodes,
useAutoRepair,
useCodeExplanation,
useDataSourceManager,
usePersistence,
// Add more hooks here as needed
}

View File

@@ -0,0 +1 @@
export interface ComponentTreeEmptyStateProps { }

View File

@@ -0,0 +1,5 @@
export interface ComponentTreeHeaderProps {
componentsCount: number;
onExpandAll: () => void;
onCollapseAll: () => void;
}

View File

@@ -0,0 +1,17 @@
export interface ComponentTreeNodesProps {
components: UIComponent[];
depth?: number;
expandedIds: Set<string>;
selectedId: string | null;
hoveredId: string | null;
draggedOverId: string | null;
dropPosition: 'before' | 'after' | 'inside' | null;
onSelect: (id: string) => void;
onHover: (id: string) => void;
onHoverEnd: () => void;
onDragStart: (id: string, e: React.DragEvent) => void;
onDragOver: (id: string, e: React.DragEvent) => void;
onDragLeave: (e: React.DragEvent) => void;
onDrop: (id: string, e: React.DragEvent) => void;
onToggleExpand: (id: string) => void;
}

View File

@@ -0,0 +1,6 @@
export interface ConditionalWrapperProps {
condition: boolean;
children: React.ReactNode;
fallback?: React.ReactNode;
className?: string;
}

View File

@@ -0,0 +1,8 @@
export interface DataCardProps {
title: string;
description?: string;
icon?: string;
gradient?: string;
children: ReactNode;
className?: string;
}

View File

@@ -0,0 +1,8 @@
export interface DataSourceGroupSectionProps {
icon: ReactNode;
label: string;
dataSources: DataSource[];
getDependents: (id: string) => string[];
onEdit: (id: string) => void;
onDelete: (id: string) => void;
}

View File

@@ -0,0 +1,6 @@
export interface DataSourceIdFieldProps {
editingSource: DataSource;
label: string;
placeholder: string;
onChange: (value: string) => void;
}

View File

@@ -0,0 +1,14 @@
interface DataSourceManagerHeaderCopy {
title: string;
description: string;
addLabel: string;
menu: {
kv: string;
static: string;
};
}
interface DataSourceManagerHeaderProps {
copy: DataSourceManagerHeaderCopy;
onAdd: (type: DataSourceType) => void;
}

View File

@@ -0,0 +1 @@
export interface DataSourceManagerProps { dataSources: DataSource[]; onChange: (dataSources: DataSource[]) => void; }

View File

@@ -0,0 +1,7 @@
export interface DynamicTextProps {
value: any;
format?: 'text' | 'number' | 'currency' | 'date' | 'time' | 'datetime' | 'boolean';
currency?: string;
locale?: string;
className?: string;
}

View File

@@ -0,0 +1,9 @@
export interface FlexLayoutProps {
children: React.ReactNode;
direction?: 'row' | 'column';
align?: 'start' | 'center' | 'end' | 'stretch';
justify?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
wrap?: boolean;
gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
className?: string;
}

View File

@@ -0,0 +1,12 @@
export interface GridLayoutProps {
children: React.ReactNode;
cols?: {
base?: number;
sm?: number;
md?: number;
lg?: number;
xl?: number;
};
gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
className?: string;
}

View File

@@ -0,0 +1 @@
export interface IconRendererProps { name: string; size?: number; weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone'; className?: string; }

View File

@@ -59,3 +59,84 @@ export * from './detail-row'
export * from './key-value'
export * from './status-icon'
export * from './progress-bar'
export * from './loading-fallback'
export * from './navigation-item'
export * from './page-header-content'
export * from './save-indicator'
export * from './lazy-bar-chart'
export * from './lazy-line-chart'
export * from './lazy-d3-bar-chart'
export * from './seed-data-manager'
export * from './storage-settings'
export * from './github-build-status'
export * from './component-binding-dialog'
export * from './data-source-editor-dialog'
export * from './component-tree'
export * from './tree-card'
export * from './filter-input'
export * from './copy-button'
export * from './input'
export * from './password-input'
export * from './image'
export * from './popover'
export * from './menu'
export * from './file-upload'
export * from './accordion'
export * from './binding-editor'
export * from './navigation-menu'
export * from './text-gradient'
export * from './error-badge'
export * from './app-logo'
export * from './dot'
export * from './spacer'
export * from './live-indicator'
export * from './action-icon'
export * from './divider'
export * from './kbd'
export * from './helper-text'
export * from './code'
export * from './info-box'
export * from './alert'
export * from './badge'
export * from './pulse'
export * from './metric-display'
export * from './separator'
export * from './text'
export * from './heading'
export * from './container'
export * from './stack'
export * from './label'
export * from './link'
export * from './chip'
export * from './tag'
export * from './spinner'
export * from './icon-wrapper'
export * from './icon-text'
export * from './empty-message'
export * from './skeleton'
export * from './loading-spinner'
export * from './count-badge'
export * from './detail-row'
export * from './key-value'
export * from './status-icon'
export * from './progress-bar'
export * from './property-editor-header'
export * from './property-editor-empty-state'
export * from './property-editor-section'
export * from './kv-source-fields'
export * from './component-tree-empty-state'
export * from './component-tree-nodes'
export * from './component-tree-header'
export * from './data-source-id-field'
export * from './static-source-fields'
export * from './flex-layout'
export * from './icon-renderer'
export * from './conditional-wrapper'
export * from './data-card'
export * from './panel'
export * from './dynamic-text'
export * from './grid-layout'
export * from './repeat-wrapper'
export * from './data-source-group-section'
export * from './data-source-manager'
export * from './data-source-manager-header'

View File

@@ -0,0 +1,5 @@
export interface KvSourceFieldsProps {
editingSource: DataSource;
copy: KvSourceFieldsCopy;
onUpdateField: <K extends keyof DataSource>(field: K, value: DataSource[K]) => void;
}

View File

@@ -0,0 +1,8 @@
export interface PanelProps {
title?: string;
description?: string;
actions?: React.ReactNode;
children: React.ReactNode;
className?: string;
variant?: 'default' | 'bordered' | 'elevated';
}

View File

@@ -0,0 +1 @@
export interface PropertyEditorEmptyStateProps {}

View File

@@ -0,0 +1 @@
export interface PropertyEditorHeaderProps { componentId: string; componentLabel: string; onDelete: () => void; }

View File

@@ -0,0 +1,6 @@
export interface PropertyEditorSectionProps {
title: string;
fields: PropertyEditorFieldDefinition[];
component: UIComponent;
onChange: (key: string, value: unknown) => void;
}

View File

@@ -0,0 +1 @@
export interface RepeatWrapperProps { items: any[]; render: (item: any, index: number) => React.ReactNode; emptyMessage?: string; className?: string; gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; }

View File

@@ -0,0 +1,6 @@
export interface StaticSourceFieldsProps {
editingSource: DataSource;
label: string;
placeholder: string;
onUpdateField: <K extends keyof DataSource>(field: K, value: DataSource[K]) => void;
};

View File

@@ -6,6 +6,7 @@
import { createJsonComponent } from './create-json-component'
import { createJsonComponentWithHooks } from './create-json-component-with-hooks'
import type {
LoadingFallbackProps,
NavigationItemProps,
PageHeaderContentProps,
@@ -67,6 +68,26 @@ import type {
KeyValueProps,
StatusIconProps,
ProgressBarProps,
PropertyEditorHeaderProps,
PropertyEditorEmptyStateProps,
PropertyEditorSectionProps,
KvSourceFieldsProps,
ComponentTreeEmptyStateProps,
ComponentTreeNodesProps,
ComponentTreeHeaderProps,
DataSourceIdFieldProps,
StaticSourceFieldsProps,
FlexLayoutProps,
IconRendererProps,
ConditionalWrapperProps,
DataCardProps,
PanelProps,
DynamicTextProps,
GridLayoutProps,
RepeatWrapperProps,
DataSourceGroupSectionProps,
DataSourceManagerProps,
DataSourceManagerHeaderProps,
} from './interfaces'
// Import JSON definitions
@@ -129,6 +150,26 @@ import detailRowDef from '@/components/json-definitions/detail-row.json'
import keyValueDef from '@/components/json-definitions/key-value.json'
import statusIconDef from '@/components/json-definitions/status-icon.json'
import progressBarDef from '@/components/json-definitions/progress-bar.json'
import propertyEditorHeaderDef from '@/components/json-definitions/property-editor-header.json'
import propertyEditorEmptyStateDef from '@/components/json-definitions/property-editor-empty-state.json'
import propertyEditorSectionDef from '@/components/json-definitions/property-editor-section.json'
import kvSourceFieldsDef from '@/components/json-definitions/kv-source-fields.json'
import componentTreeEmptyStateDef from '@/components/json-definitions/component-tree-empty-state.json'
import componentTreeNodesDef from '@/components/json-definitions/component-tree-nodes.json'
import componentTreeHeaderDef from '@/components/json-definitions/component-tree-header.json'
import dataSourceIdFieldDef from '@/components/json-definitions/data-source-id-field.json'
import staticSourceFieldsDef from '@/components/json-definitions/static-source-fields.json'
import flexLayoutDef from '@/components/json-definitions/flex-layout.json'
import iconRendererDef from '@/components/json-definitions/icon-renderer.json'
import conditionalWrapperDef from '@/components/json-definitions/conditional-wrapper.json'
import dataCardDef from '@/components/json-definitions/data-card.json'
import panelDef from '@/components/json-definitions/panel.json'
import dynamicTextDef from '@/components/json-definitions/dynamic-text.json'
import gridLayoutDef from '@/components/json-definitions/grid-layout.json'
import repeatWrapperDef from '@/components/json-definitions/repeat-wrapper.json'
import dataSourceGroupSectionDef from '@/components/json-definitions/data-source-group-section.json'
import dataSourceManagerDef from '@/components/json-definitions/data-source-manager.json'
import dataSourceManagerHeaderDef from '@/components/json-definitions/data-source-manager-header.json'
// Create pure JSON components (no hooks)
export const LoadingFallback = createJsonComponent<LoadingFallbackProps>(loadingFallbackDef)
@@ -312,3 +353,44 @@ export const StatusIcon = createJsonComponent<StatusIconProps>(statusIconDef)
export const ProgressBar = createJsonComponent<ProgressBarProps>(progressBarDef)
// All components converted to pure JSON! 🎉
export const PropertyEditorHeader = createJsonComponent<PropertyEditorHeaderProps>(propertyEditorHeaderDef)
export const PropertyEditorEmptyState = createJsonComponent<PropertyEditorEmptyStateProps>(propertyEditorEmptyStateDef)
export const PropertyEditorSection = createJsonComponent<PropertyEditorSectionProps>(propertyEditorSectionDef)
export const KvSourceFields = createJsonComponent<KvSourceFieldsProps>(kvSourceFieldsDef)
export const ComponentTreeEmptyState = createJsonComponent<ComponentTreeEmptyStateProps>(componentTreeEmptyStateDef)
export const ComponentTreeNodes = createJsonComponentWithHooks<ComponentTreeNodesProps>(componentTreeNodesDef, {
hooks: {
data: {
hookName: "useComponentTreeNodes",
args: (props) => [props.expandedIds]
}
}
})
export const ComponentTreeHeader = createJsonComponent<ComponentTreeHeaderProps>(componentTreeHeaderDef)
export const DataSourceIdField = createJsonComponent<DataSourceIdFieldProps>(dataSourceIdFieldDef)
export const StaticSourceFields = createJsonComponentWithHooks<StaticSourceFieldsProps>(staticSourceFieldsDef, {
hooks: {
handleChange: {
hookName: 'useStaticSourceFields',
args: (props) => [props.onUpdateField]
}
}
});
export const FlexLayout = createJsonComponent<FlexLayoutProps>(flexLayoutDef)
export const IconRenderer = createJsonComponent<IconRendererProps>(iconRendererDef)
export const ConditionalWrapper = createJsonComponent<ConditionalWrapperProps>(conditionalWrapperDef);
export const DataCard = createJsonComponent<DataCardProps>(dataCardDef)
export const Panel = createJsonComponent<PanelProps>(panelDef)
export const DynamicText = createJsonComponentWithHooks<DynamicTextProps>(dynamicTextDef, {
hooks: {
data: {
hookName: 'useDynamicText',
args: (props) => [props.value, props.format, props.currency, props.locale]
}
}
});
export const GridLayout = createJsonComponent<GridLayoutProps>(gridLayoutDef);
export const RepeatWrapper = createJsonComponent<RepeatWrapperProps>(repeatWrapperDef)
export const DataSourceGroupSection = createJsonComponent<DataSourceGroupSectionProps>(dataSourceGroupSectionDef)
export const DataSourceManager = createJsonComponentWithHooks<DataSourceManagerProps>(dataSourceManagerDef, { hooks: { hookData: { hookName: 'useDataSourceManager', args: (props) => [props.dataSources] } } })
export const DataSourceManagerHeader = createJsonComponent<DataSourceManagerHeaderProps>(dataSourceManagerHeaderDef)