Migrate 20+ components to JSON UI system - now 46 supported

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-17 21:54:51 +00:00
parent b20dc11773
commit 58437b9770
4 changed files with 260 additions and 33 deletions

View File

@@ -83,7 +83,7 @@
"category": "layout",
"canHaveChildren": true,
"description": "Flexible box layout container",
"status": "planned"
"status": "supported"
},
{
"type": "Stack",
@@ -91,7 +91,7 @@
"category": "layout",
"canHaveChildren": true,
"description": "Vertical or horizontal stack layout",
"status": "planned"
"status": "supported"
},
{
"type": "Container",
@@ -99,7 +99,7 @@
"category": "layout",
"canHaveChildren": true,
"description": "Centered container with max-width",
"status": "planned"
"status": "supported"
},
{
"type": "Button",
@@ -123,7 +123,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Multi-line text input",
"status": "planned"
"status": "supported"
},
{
"type": "Select",
@@ -147,7 +147,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Radio button selection",
"status": "planned"
"status": "supported"
},
{
"type": "Switch",
@@ -163,7 +163,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Numeric range slider",
"status": "planned"
"status": "supported"
},
{
"type": "NumberInput",
@@ -171,7 +171,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Numeric input with increment/decrement",
"status": "planned"
"status": "supported"
},
{
"type": "DatePicker",
@@ -227,7 +227,7 @@
"category": "display",
"canHaveChildren": true,
"description": "Removable tag or chip",
"status": "planned"
"status": "supported"
},
{
"type": "Code",
@@ -235,7 +235,7 @@
"category": "display",
"canHaveChildren": true,
"description": "Inline or block code display",
"status": "planned"
"status": "supported"
},
{
"type": "Image",
@@ -243,7 +243,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Image element with loading states",
"status": "planned"
"status": "supported"
},
{
"type": "Avatar",
@@ -251,7 +251,7 @@
"category": "display",
"canHaveChildren": false,
"description": "User avatar image",
"status": "planned"
"status": "supported"
},
{
"type": "Icon",
@@ -307,7 +307,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Loading spinner",
"status": "planned"
"status": "supported"
},
{
"type": "Skeleton",
@@ -315,7 +315,7 @@
"category": "display",
"canHaveChildren": false,
"description": "Loading skeleton placeholder",
"status": "planned"
"status": "supported"
},
{
"type": "Link",
@@ -323,7 +323,7 @@
"category": "navigation",
"canHaveChildren": true,
"description": "Hyperlink element",
"status": "planned"
"status": "supported"
},
{
"type": "Breadcrumb",
@@ -348,7 +348,7 @@
"category": "feedback",
"canHaveChildren": true,
"description": "Alert notification message",
"status": "planned"
"status": "supported"
},
{
"type": "InfoBox",
@@ -356,7 +356,7 @@
"category": "feedback",
"canHaveChildren": true,
"description": "Information box with icon",
"status": "planned"
"status": "supported"
},
{
"type": "Notification",
@@ -388,7 +388,7 @@
"category": "feedback",
"canHaveChildren": true,
"description": "Empty state placeholder",
"status": "planned"
"status": "supported"
},
{
"type": "ErrorBadge",
@@ -420,7 +420,7 @@
"category": "data",
"canHaveChildren": false,
"description": "Data table",
"status": "planned"
"status": "supported"
},
{
"type": "DataTable",
@@ -436,7 +436,7 @@
"category": "data",
"canHaveChildren": false,
"description": "Key-value pair display",
"status": "planned"
"status": "supported"
},
{
"type": "Timeline",
@@ -452,7 +452,7 @@
"category": "data",
"canHaveChildren": false,
"description": "Statistic card display",
"status": "planned"
"status": "supported"
},
{
"type": "MetricCard",
@@ -496,13 +496,13 @@
}
],
"statistics": {
"total": 68,
"supported": 23,
"planned": 45,
"total": 60,
"supported": 43,
"planned": 17,
"byCategory": {
"layout": 11,
"layout": 12,
"input": 11,
"display": 17,
"display": 16,
"navigation": 3,
"feedback": 7,
"data": 8,

View File

@@ -3,13 +3,14 @@ import { ComponentType } from '@/types/json-ui'
export interface ComponentDefinition {
type: ComponentType
label: string
category: 'layout' | 'input' | 'display' | 'custom'
category: 'layout' | 'input' | 'display' | 'navigation' | 'feedback' | 'data' | 'custom'
icon: string
defaultProps?: Record<string, any>
canHaveChildren?: boolean
}
export const componentDefinitions: ComponentDefinition[] = [
// Layout Components
{
type: 'div',
label: 'Container',
@@ -34,6 +35,30 @@ export const componentDefinitions: ComponentDefinition[] = [
canHaveChildren: true,
defaultProps: { columns: 2, gap: 4 }
},
{
type: 'Stack',
label: 'Stack',
category: 'layout',
icon: 'Stack',
canHaveChildren: true,
defaultProps: { direction: 'vertical', gap: 2 }
},
{
type: 'Flex',
label: 'Flex',
category: 'layout',
icon: 'ArrowsOutLineHorizontal',
canHaveChildren: true,
defaultProps: { direction: 'row', gap: 2 }
},
{
type: 'Container',
label: 'Container',
category: 'layout',
icon: 'Rectangle',
canHaveChildren: true,
defaultProps: { maxWidth: 'lg' }
},
{
type: 'Card',
label: 'Card',
@@ -42,11 +67,13 @@ export const componentDefinitions: ComponentDefinition[] = [
canHaveChildren: true,
defaultProps: { className: 'p-4' }
},
// Input Components
{
type: 'Button',
label: 'Button',
category: 'input',
icon: 'Circle',
canHaveChildren: true,
defaultProps: { children: 'Click me', variant: 'default' }
},
{
@@ -56,6 +83,13 @@ export const componentDefinitions: ComponentDefinition[] = [
icon: 'TextT',
defaultProps: { placeholder: 'Enter text...' }
},
{
type: 'TextArea',
label: 'TextArea',
category: 'input',
icon: 'TextAlignLeft',
defaultProps: { placeholder: 'Enter text...', rows: 4 }
},
{
type: 'Select',
label: 'Select',
@@ -70,6 +104,13 @@ export const componentDefinitions: ComponentDefinition[] = [
icon: 'CheckSquare',
defaultProps: {}
},
{
type: 'Radio',
label: 'Radio',
category: 'input',
icon: 'Circle',
defaultProps: {}
},
{
type: 'Switch',
label: 'Switch',
@@ -77,11 +118,27 @@ export const componentDefinitions: ComponentDefinition[] = [
icon: 'ToggleLeft',
defaultProps: {}
},
{
type: 'Slider',
label: 'Slider',
category: 'input',
icon: 'SlidersHorizontal',
defaultProps: { min: 0, max: 100, value: 50 }
},
{
type: 'NumberInput',
label: 'Number Input',
category: 'input',
icon: 'NumberCircleOne',
defaultProps: { placeholder: '0', min: 0 }
},
// Display Components
{
type: 'Heading',
label: 'Heading',
category: 'display',
icon: 'TextHOne',
canHaveChildren: true,
defaultProps: { level: 1, children: 'Heading' }
},
{
@@ -89,6 +146,7 @@ export const componentDefinitions: ComponentDefinition[] = [
label: 'Text',
category: 'display',
icon: 'Paragraph',
canHaveChildren: true,
defaultProps: { children: 'Text content' }
},
{
@@ -96,8 +154,39 @@ export const componentDefinitions: ComponentDefinition[] = [
label: 'Badge',
category: 'display',
icon: 'Tag',
canHaveChildren: true,
defaultProps: { children: 'Badge', variant: 'default' }
},
{
type: 'Tag',
label: 'Tag',
category: 'display',
icon: 'Tag',
canHaveChildren: true,
defaultProps: { children: 'Tag' }
},
{
type: 'Code',
label: 'Code',
category: 'display',
icon: 'Code',
canHaveChildren: true,
defaultProps: { children: 'code' }
},
{
type: 'Image',
label: 'Image',
category: 'display',
icon: 'Image',
defaultProps: { src: '', alt: 'Image' }
},
{
type: 'Avatar',
label: 'Avatar',
category: 'display',
icon: 'UserCircle',
defaultProps: { src: '', alt: 'Avatar' }
},
{
type: 'Progress',
label: 'Progress',
@@ -105,6 +194,20 @@ export const componentDefinitions: ComponentDefinition[] = [
icon: 'CircleNotch',
defaultProps: { value: 50 }
},
{
type: 'Spinner',
label: 'Spinner',
category: 'display',
icon: 'CircleNotch',
defaultProps: { size: 'md' }
},
{
type: 'Skeleton',
label: 'Skeleton',
category: 'display',
icon: 'Rectangle',
defaultProps: { className: 'h-4 w-full' }
},
{
type: 'Separator',
label: 'Separator',
@@ -112,6 +215,77 @@ export const componentDefinitions: ComponentDefinition[] = [
icon: 'Minus',
defaultProps: {}
},
// Navigation Components
{
type: 'Link',
label: 'Link',
category: 'navigation',
icon: 'Link',
canHaveChildren: true,
defaultProps: { href: '#', children: 'Link' }
},
// Feedback Components
{
type: 'Alert',
label: 'Alert',
category: 'feedback',
icon: 'Info',
canHaveChildren: true,
defaultProps: { variant: 'info', children: 'Alert message' }
},
{
type: 'InfoBox',
label: 'Info Box',
category: 'feedback',
icon: 'Info',
canHaveChildren: true,
defaultProps: { type: 'info', children: 'Information' }
},
{
type: 'EmptyState',
label: 'Empty State',
category: 'feedback',
icon: 'FolderOpen',
canHaveChildren: true,
defaultProps: { message: 'No items found' }
},
{
type: 'StatusBadge',
label: 'Status Badge',
category: 'feedback',
icon: 'Circle',
defaultProps: { status: 'active', children: 'Active' }
},
// Data Components
{
type: 'List',
label: 'List',
category: 'data',
icon: 'List',
defaultProps: { items: [], emptyMessage: 'No items' }
},
{
type: 'Table',
label: 'Table',
category: 'data',
icon: 'Table',
defaultProps: { data: [], columns: [] }
},
{
type: 'KeyValue',
label: 'Key Value',
category: 'data',
icon: 'Equals',
defaultProps: { label: 'Key', value: 'Value' }
},
{
type: 'StatCard',
label: 'Stat Card',
category: 'data',
icon: 'ChartBar',
defaultProps: { title: 'Metric', value: '0' }
},
// Custom Components
{
type: 'DataCard',
label: 'Data Card',
@@ -127,11 +301,12 @@ export const componentDefinitions: ComponentDefinition[] = [
defaultProps: { placeholder: 'Search...' }
},
{
type: 'StatusBadge',
label: 'Status Badge',
type: 'ActionBar',
label: 'Action Bar',
category: 'custom',
icon: 'Circle',
defaultProps: { status: 'active', children: 'Active' }
icon: 'Toolbox',
canHaveChildren: true,
defaultProps: { actions: [] }
},
]

View File

@@ -12,8 +12,28 @@ import { Separator } from '@/components/ui/separator'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Heading } from '@/components/atoms/Heading'
import { Text } from '@/components/atoms/Text'
import { TextArea } from '@/components/atoms/TextArea'
import { List } from '@/components/atoms/List'
import { Grid } from '@/components/atoms/Grid'
import { Stack } from '@/components/atoms/Stack'
import { Flex } from '@/components/atoms/Flex'
import { Container } from '@/components/atoms/Container'
import { Link } from '@/components/atoms/Link'
import { Image } from '@/components/atoms/Image'
import { Avatar } from '@/components/atoms/Avatar'
import { Code } from '@/components/atoms/Code'
import { Tag } from '@/components/atoms/Tag'
import { Spinner } from '@/components/atoms/Spinner'
import { Skeleton } from '@/components/atoms/Skeleton'
import { Slider } from '@/components/atoms/Slider'
import { NumberInput } from '@/components/atoms/NumberInput'
import { Radio } from '@/components/atoms/Radio'
import { Alert } from '@/components/atoms/Alert'
import { InfoBox } from '@/components/atoms/InfoBox'
import { EmptyState } from '@/components/atoms/EmptyState'
import { Table } from '@/components/atoms/Table'
import { KeyValue } from '@/components/atoms/KeyValue'
import { StatCard } from '@/components/atoms/StatCard'
import { StatusBadge } from '@/components/atoms/StatusBadge'
import { DataCard } from '@/components/molecules/DataCard'
import { SearchInput } from '@/components/molecules/SearchInput'
@@ -29,10 +49,15 @@ export const componentRegistry: Record<ComponentType, any> = {
'Button': Button,
'Card': Card,
'Input': Input,
'TextArea': TextArea,
'Select': Select,
'Checkbox': Checkbox,
'Radio': Radio,
'Switch': Switch,
'Slider': Slider,
'NumberInput': NumberInput,
'Badge': Badge,
'Tag': Tag,
'Progress': Progress,
'Separator': Separator,
'Tabs': Tabs,
@@ -40,8 +65,27 @@ export const componentRegistry: Record<ComponentType, any> = {
'Text': Text,
'Heading': Heading,
'Label': Label,
'Link': Link,
'Image': Image,
'Avatar': Avatar,
'Code': Code,
'Spinner': Spinner,
'Skeleton': Skeleton,
'List': List,
'Grid': Grid,
'Stack': Stack,
'Flex': Flex,
'Container': Container,
'Alert': Alert,
'InfoBox': InfoBox,
'EmptyState': EmptyState,
'StatusBadge': StatusBadge,
'Table': Table,
'KeyValue': KeyValue,
'StatCard': StatCard,
'DataCard': DataCard,
'SearchInput': SearchInput,
'ActionBar': ActionBar,
}
export const cardSubComponents = {
@@ -63,6 +107,12 @@ export const customComponents = {
'DataCard': DataCard,
'SearchInput': SearchInput,
'ActionBar': ActionBar,
'StatCard': StatCard,
'KeyValue': KeyValue,
'Table': Table,
'Alert': Alert,
'InfoBox': InfoBox,
'EmptyState': EmptyState,
}
export function getComponent(type: ComponentType | string): any {

View File

@@ -3,10 +3,12 @@ import { ReactNode } from 'react'
export type ComponentType =
| 'div' | 'section' | 'article' | 'header' | 'footer' | 'main'
| 'Button' | 'Card' | 'CardHeader' | 'CardTitle' | 'CardDescription' | 'CardContent' | 'CardFooter'
| 'Input' | 'Select' | 'Checkbox' | 'Switch'
| 'Input' | 'TextArea' | 'Select' | 'Checkbox' | 'Radio' | 'Switch' | 'Slider' | 'NumberInput'
| 'Badge' | 'Progress' | 'Separator' | 'Tabs' | 'Dialog'
| 'Text' | 'Heading' | 'Label' | 'List' | 'Grid'
| 'StatusBadge' | 'DataCard' | 'SearchInput' | 'ActionBar'
| 'Text' | 'Heading' | 'Label' | 'List' | 'Grid' | 'Stack' | 'Flex' | 'Container'
| 'Link' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton'
| 'Alert' | 'InfoBox' | 'EmptyState' | 'StatusBadge'
| 'Table' | 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar'
export type ActionType =
| 'create' | 'update' | 'delete' | 'navigate'