Files
low-code-react-app-b/src/types/json-ui.ts

138 lines
3.9 KiB
TypeScript

export type ComponentType =
| 'div' | 'section' | 'article' | 'header' | 'footer' | 'main'
| 'Button' | 'Card' | 'CardHeader' | 'CardTitle' | 'CardDescription' | 'CardContent' | 'CardFooter'
| 'Input' | 'TextArea' | 'Textarea' | 'Select' | 'Checkbox' | 'Radio' | 'Switch' | 'Slider' | 'NumberInput'
| 'Badge' | 'Progress' | 'Separator' | 'Tabs' | 'TabsContent' | 'TabsList' | 'TabsTrigger' | 'Dialog'
| 'Text' | 'Heading' | 'Label' | 'List' | 'Grid' | 'Stack' | 'Flex' | 'Container'
| 'Link' | 'Breadcrumb' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton'
| 'Alert' | 'InfoBox' | 'EmptyState' | 'StatusBadge'
| 'ErrorBadge' | 'Notification' | 'StatusIcon'
| 'Table' | 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar'
| 'DataList' | 'DataTable' | 'MetricCard' | 'Timeline'
| 'AppBranding' | 'LabelWithBadge' | 'EmptyEditorState' | 'LoadingFallback' | 'LoadingState' | 'NavigationGroupHeader'
export type ActionType =
| 'create' | 'update' | 'delete' | 'navigate'
| 'show-toast' | 'open-dialog' | 'close-dialog'
| 'set-value' | 'toggle-value' | 'increment' | 'decrement'
| 'custom'
export type DataSourceType =
| 'kv' | 'computed' | 'static'
export type BindingSourceType =
| 'data' | 'bindings' | 'state'
export interface DataSource {
id: string
type: DataSourceType
key?: string
defaultValue?: any
compute?: (data: Record<string, any>) => any
dependencies?: string[]
}
export interface Action {
id: string
type: ActionType
target?: string
path?: string
value?: any
params?: Record<string, any>
// Legacy: function-based compute
compute?: ((data: Record<string, any>, event?: any) => any) | string
// New: JSON-friendly expression (e.g., "event.target.value", "data.fieldName")
expression?: string
// New: JSON template with dynamic values
valueTemplate?: Record<string, any>
message?: string
variant?: 'success' | 'error' | 'info' | 'warning'
}
export interface Binding {
source: string
sourceType?: BindingSourceType
path?: string
transform?: string | ((value: any) => any)
}
export interface EventHandler {
event: string
actions: Action[]
condition?: string | ((data: Record<string, any>) => boolean)
}
export interface JSONEventDefinition {
action?: string
actions?: Action[]
payload?: Record<string, any>
condition?: string | ((data: Record<string, any>) => boolean)
}
export type JSONEventMap = Record<string, JSONEventDefinition | JSONEventDefinition[] | string>
export interface Conditional {
if: string
then?: UIComponent | (UIComponent | string)[] | string
else?: UIComponent | (UIComponent | string)[] | string
}
export interface Loop {
source: string
itemVar: string
indexVar?: string
}
export interface UIComponent {
id: string
type: ComponentType
props?: Record<string, any>
className?: string
style?: Record<string, any>
bindings?: Record<string, Binding>
dataBinding?: string | Binding
events?: EventHandler[] | JSONEventMap
children?: UIComponent[] | string
condition?: Binding
conditional?: Conditional
loop?: Loop
}
export interface Layout {
type: 'single' | 'split' | 'tabs' | 'grid'
areas?: LayoutArea[]
columns?: number
gap?: number
}
export interface LayoutArea {
id: string
component: UIComponent
size?: number
}
export interface PageSchema {
id: string
name: string
layout: Layout
dataSources: DataSource[]
components: UIComponent[]
globalActions?: Action[]
}
export interface JSONUIContext {
data: Record<string, any>
updateData: (sourceId: string, value: any) => void
executeAction: (action: Action, event?: any) => Promise<void>
}
export interface ComponentRendererProps {
component: UIComponent
data: Record<string, unknown>
context?: Record<string, unknown>
state?: Record<string, unknown>
onEvent?: (componentId: string, handler: EventHandler, eventData: unknown) => void
}
export type ComponentSchema = UIComponent