mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 21:54:56 +00:00
feat: migrate ConflictIndicator to JSON
This commit is contained in:
26
src/components/json-definitions/conditional-wrapper.json
Normal file
26
src/components/json-definitions/conditional-wrapper.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "conditional-wrapper-container",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": "className",
|
||||
"transform": "data || ''"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "conditional-wrapper-content",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": ["condition", "children", "fallback"],
|
||||
"transform": "const condition = data[0]; const children = data[1]; const fallback = data[2]; return condition ? children : fallback"
|
||||
},
|
||||
"_if": {
|
||||
"source": ["condition", "fallback"],
|
||||
"transform": "const condition = data[0]; const fallback = data[1]; return condition || !!fallback"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,114 @@
|
||||
{
|
||||
"id": "conflict-indicator",
|
||||
"type": "div",
|
||||
"props": {
|
||||
"className": "conflict-indicator"
|
||||
"id": "conflict-indicator-wrapper",
|
||||
"type": "AnimatePresence",
|
||||
"conditional": {
|
||||
"if": "hasConflicts"
|
||||
},
|
||||
"children": []
|
||||
"children": [
|
||||
{
|
||||
"id": "conflict-indicator-motion",
|
||||
"type": "motion.div",
|
||||
"props": {
|
||||
"initial": { "opacity": 0, "x": -20 },
|
||||
"animate": { "opacity": 1, "x": 0 },
|
||||
"exit": { "opacity": 0, "x": -20 }
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "conflict-indicator-badge-compact",
|
||||
"type": "motion.button",
|
||||
"conditional": {
|
||||
"if": "variant === 'compact'"
|
||||
},
|
||||
"bindings": {
|
||||
"onClick": {
|
||||
"source": "onClick",
|
||||
"transform": "data || (() => {})"
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"className": "relative",
|
||||
"initial": { "scale": 0 },
|
||||
"animate": { "scale": 1 },
|
||||
"exit": { "scale": 0 }
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "conflict-icon-compact",
|
||||
"type": "Warning",
|
||||
"props": {
|
||||
"size": 20,
|
||||
"weight": "fill",
|
||||
"className": "text-destructive animate-pulse"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "conflict-count-badge",
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "stats.totalConflicts"
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"className": "absolute -top-1 -right-1 bg-destructive text-destructive-foreground text-[10px] font-bold rounded-full w-4 h-4 flex items-center justify-center"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "conflict-indicator-badge-full",
|
||||
"type": "Badge",
|
||||
"conditional": {
|
||||
"if": "variant !== 'compact'"
|
||||
},
|
||||
"bindings": {
|
||||
"onClick": {
|
||||
"source": "onClick",
|
||||
"transform": "data || (() => {})"
|
||||
}
|
||||
},
|
||||
"props": {
|
||||
"variant": "destructive",
|
||||
"className": "cursor-pointer hover:bg-destructive/90 transition-colors gap-1.5 animate-pulse"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "conflict-icon-full",
|
||||
"type": "Warning",
|
||||
"props": {
|
||||
"size": 14,
|
||||
"weight": "fill"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "conflict-label",
|
||||
"type": "span",
|
||||
"conditional": {
|
||||
"if": "showLabel"
|
||||
},
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "stats.totalConflicts",
|
||||
"transform": "data === 1 ? `${data} Conflict` : `${data} Conflicts`"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "conflict-count-only",
|
||||
"type": "span",
|
||||
"conditional": {
|
||||
"if": "!showLabel"
|
||||
},
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "stats.totalConflicts"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
82
src/components/json-definitions/data-card.json
Normal file
82
src/components/json-definitions/data-card.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"id": "data-card-container",
|
||||
"type": "Card",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": ["gradient", "className"],
|
||||
"transform": "const gradient = data[0]; const className = data[1] || ''; const gradientClass = gradient ? `bg-gradient-to-br ${gradient} border-primary/20` : ''; return `${gradientClass} ${className}`.trim()"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "data-card-header",
|
||||
"type": "CardHeader",
|
||||
"children": [
|
||||
{
|
||||
"id": "data-card-title",
|
||||
"type": "CardTitle",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'flex items-center gap-2'"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "data-card-icon",
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'text-primary'"
|
||||
},
|
||||
"children": {
|
||||
"source": "icon",
|
||||
"transform": "data"
|
||||
},
|
||||
"_if": {
|
||||
"source": "icon",
|
||||
"transform": "!!data"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "data-card-title-text",
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "title",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "data-card-description",
|
||||
"type": "CardDescription",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "description",
|
||||
"transform": "data"
|
||||
},
|
||||
"_if": {
|
||||
"source": "description",
|
||||
"transform": "!!data"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "data-card-content",
|
||||
"type": "CardContent",
|
||||
"children": [
|
||||
{
|
||||
"type": "slot",
|
||||
"source": "children"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
16
src/components/json-definitions/dynamic-text.json
Normal file
16
src/components/json-definitions/dynamic-text.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"id": "dynamic-text-container",
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"className": "className"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "dynamic-text-value",
|
||||
"type": "text",
|
||||
"bindings": {
|
||||
"content": "formattedValue"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
66
src/components/json-definitions/feature-toggle-settings.json
Normal file
66
src/components/json-definitions/feature-toggle-settings.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"id": "feature-toggle-settings",
|
||||
"type": "div",
|
||||
"className": "h-full p-6 bg-background",
|
||||
"children": [
|
||||
{
|
||||
"id": "feature-toggle-header",
|
||||
"type": "div",
|
||||
"className": "mb-6",
|
||||
"children": [
|
||||
{
|
||||
"id": "feature-toggle-title",
|
||||
"type": "h2",
|
||||
"className": "text-2xl font-bold mb-2",
|
||||
"children": "Feature Toggles"
|
||||
},
|
||||
{
|
||||
"id": "feature-toggle-description",
|
||||
"type": "p",
|
||||
"className": "text-muted-foreground",
|
||||
"children": [
|
||||
"Enable or disable features to customize your workspace. ",
|
||||
{
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "enabledCount",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
},
|
||||
" of ",
|
||||
{
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "totalCount",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
},
|
||||
" features enabled."
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "feature-toggle-scroll-area",
|
||||
"type": "ScrollArea",
|
||||
"className": "h-[calc(100vh-200px)]",
|
||||
"children": [
|
||||
{
|
||||
"id": "feature-toggle-grid",
|
||||
"type": "div",
|
||||
"className": "grid grid-cols-1 lg:grid-cols-2 gap-4 pr-4",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "items",
|
||||
"transform": "data.map((item, index) => ({ id: `feature-${item.key}`, key: item.key, item: item, index: index }))"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
src/components/json-definitions/flex-layout.json
Normal file
14
src/components/json-definitions/flex-layout.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "flex-layout",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": ["direction", "align", "justify", "wrap", "gap", "className"],
|
||||
"transform": "const [direction, align, justify, wrap, gap, customClass] = data; const directionClass = direction === 'column' ? 'flex-col' : 'flex-row'; const alignClasses = { start: 'items-start', center: 'items-center', end: 'items-end', stretch: 'items-stretch' }; const justifyClasses = { start: 'justify-start', center: 'justify-center', end: 'justify-end', between: 'justify-between', around: 'justify-around', evenly: 'justify-evenly' }; const gapClasses = { none: 'gap-0', xs: 'gap-1', sm: 'gap-2', md: 'gap-4', lg: 'gap-6', xl: 'gap-8' }; const wrapClass = wrap ? 'flex-wrap' : ''; const baseClasses = `flex ${directionClass} ${alignClasses[align || 'start']} ${justifyClasses[justify || 'start']} ${gapClasses[gap || 'md']} ${wrapClass} ${customClass || ''}`.trim(); return baseClasses.replace(/\\s+/g, ' ')"
|
||||
},
|
||||
"children": {
|
||||
"source": "children",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/components/json-definitions/grid-layout.json
Normal file
14
src/components/json-definitions/grid-layout.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "grid-layout",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": ["cols", "gap", "className"],
|
||||
"transform": "const [cols, gap, customClass] = data; const gapClasses = { none: 'gap-0', xs: 'gap-1', sm: 'gap-2', md: 'gap-4', lg: 'gap-6', xl: 'gap-8' }; const gridCols = []; const colsObj = cols || { base: 1 }; if (colsObj.base) gridCols.push(`grid-cols-${colsObj.base}`); if (colsObj.sm) gridCols.push(`sm:grid-cols-${colsObj.sm}`); if (colsObj.md) gridCols.push(`md:grid-cols-${colsObj.md}`); if (colsObj.lg) gridCols.push(`lg:grid-cols-${colsObj.lg}`); if (colsObj.xl) gridCols.push(`xl:grid-cols-${colsObj.xl}`); const baseClasses = `grid ${gapClasses[gap || 'md']} ${gridCols.join(' ')} ${customClass || ''}`.trim(); return baseClasses.replace(/\\s+/g, ' ')"
|
||||
},
|
||||
"children": {
|
||||
"source": "children",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/components/json-definitions/icon-renderer.json
Normal file
15
src/components/json-definitions/icon-renderer.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"id": "icon-renderer-container",
|
||||
"type": "span",
|
||||
"children": [
|
||||
{
|
||||
"id": "icon-renderer-icon",
|
||||
"type": "${name}",
|
||||
"bindings": {
|
||||
"size": "size",
|
||||
"weight": "weight",
|
||||
"className": "className"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
112
src/components/json-definitions/panel.json
Normal file
112
src/components/json-definitions/panel.json
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"id": "panel-card",
|
||||
"type": "Card",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": "variant",
|
||||
"transform": "const variantClasses = { default: 'border-border', bordered: 'border-2 border-primary/20', elevated: 'shadow-lg border-border' }; return variantClasses[data || 'default'] + (this.props.className ? ' ' + this.props.className : '')"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "panel-header",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": ["title", "description", "actions"],
|
||||
"transform": "const hasHeader = !!data[0] || !!data[1] || !!data[2]; return hasHeader ? 'flex items-start justify-between p-4 border-b' : ''"
|
||||
},
|
||||
"_if": {
|
||||
"source": ["title", "description", "actions"],
|
||||
"transform": "return !!data[0] || !!data[1] || !!data[2]"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "panel-header-content",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'space-y-1'"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "panel-title",
|
||||
"type": "h3",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'font-semibold text-lg'"
|
||||
},
|
||||
"children": {
|
||||
"source": "title",
|
||||
"transform": "data"
|
||||
},
|
||||
"_if": {
|
||||
"source": "title",
|
||||
"transform": "!!data"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "panel-description",
|
||||
"type": "p",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'text-sm text-muted-foreground'"
|
||||
},
|
||||
"children": {
|
||||
"source": "description",
|
||||
"transform": "data"
|
||||
},
|
||||
"_if": {
|
||||
"source": "description",
|
||||
"transform": "!!data"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "panel-actions",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "actions",
|
||||
"transform": "data"
|
||||
},
|
||||
"_if": {
|
||||
"source": "actions",
|
||||
"transform": "!!data"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "panel-content",
|
||||
"type": "CardContent",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'p-4'"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "panel-children",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "children",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
48
src/components/json-definitions/repeat-wrapper.json
Normal file
48
src/components/json-definitions/repeat-wrapper.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"id": "repeat-wrapper-container",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": ["gap", "className"],
|
||||
"transform": "const gap = data[0] || 'md'; const className = data[1] || ''; const gapClasses = { none: 'gap-0', xs: 'gap-1', sm: 'gap-2', md: 'gap-4', lg: 'gap-6', xl: 'gap-8' }; return `flex flex-col ${gapClasses[gap]} ${className}`.trim()"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "repeat-wrapper-empty",
|
||||
"type": "div",
|
||||
"bindings": {
|
||||
"className": {
|
||||
"source": null,
|
||||
"transform": "'text-center text-muted-foreground text-sm p-4'"
|
||||
},
|
||||
"children": {
|
||||
"source": "emptyMessage",
|
||||
"transform": "data"
|
||||
},
|
||||
"_if": {
|
||||
"source": ["items", "emptyMessage"],
|
||||
"transform": "(!data[0] || data[0].length === 0) && data[1]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "repeat-wrapper-items",
|
||||
"type": "RepeatLoop",
|
||||
"bindings": {
|
||||
"items": {
|
||||
"source": "items",
|
||||
"transform": "data"
|
||||
},
|
||||
"render": {
|
||||
"source": "render",
|
||||
"transform": "data"
|
||||
}
|
||||
},
|
||||
"_if": {
|
||||
"source": "items",
|
||||
"transform": "data && data.length > 0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -37,6 +37,8 @@ export * from './use-menu-state'
|
||||
export * from './use-file-upload'
|
||||
export * from './use-accordion'
|
||||
export * from './use-binding-editor'
|
||||
export * from './use-format-value'
|
||||
export * from './use-repeat-wrapper'
|
||||
export { useAppLayout } from './use-app-layout'
|
||||
export { useAppRouterLayout } from './use-app-router-layout'
|
||||
export { useNavigationMenu } from './use-navigation-menu'
|
||||
|
||||
49
src/hooks/use-format-value.ts
Normal file
49
src/hooks/use-format-value.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
export function useFormatValue(
|
||||
value: any,
|
||||
format: 'text' | 'number' | 'currency' | 'date' | 'time' | 'datetime' | 'boolean' = 'text',
|
||||
currency: string = 'USD',
|
||||
locale: string = 'en-US'
|
||||
): string {
|
||||
return useMemo(() => {
|
||||
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)
|
||||
}
|
||||
}, [value, format, currency, locale])
|
||||
}
|
||||
26
src/hooks/use-repeat-wrapper.ts
Normal file
26
src/hooks/use-repeat-wrapper.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
interface UseRepeatWrapperArgs {
|
||||
items: any[]
|
||||
render: (item: any, index: number) => React.ReactNode
|
||||
}
|
||||
|
||||
export function useRepeatWrapper({ items, render }: UseRepeatWrapperArgs) {
|
||||
const rendered = useMemo(() => {
|
||||
if (!items || items.length === 0) {
|
||||
return []
|
||||
}
|
||||
return items.map((item, index) => ({
|
||||
key: index,
|
||||
item,
|
||||
index,
|
||||
element: render(item, index)
|
||||
}))
|
||||
}, [items, render])
|
||||
|
||||
return {
|
||||
renderedItems: rendered,
|
||||
itemCount: items?.length || 0,
|
||||
isEmpty: !items || items.length === 0
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@ import { useMenuState } from '@/hooks/use-menu-state'
|
||||
import { useFileUpload } from '@/hooks/use-file-upload'
|
||||
import { useAccordion } from '@/hooks/use-accordion'
|
||||
import { useBindingEditor } from '@/hooks/use-binding-editor'
|
||||
import { useRepeatWrapper } from '@/hooks/use-repeat-wrapper'
|
||||
import { useAppLayout } from '@/hooks/use-app-layout'
|
||||
import { useAppRouterLayout } from '@/hooks/use-app-router-layout'
|
||||
import { useNavigationMenu } from '@/hooks/use-navigation-menu'
|
||||
import { useDataSourceManagerState } from '@/hooks/use-data-source-manager-state'
|
||||
import { useFormatValue } from '@/hooks/use-format-value'
|
||||
import { useConflictResolution } from '@/hooks/use-conflict-resolution'
|
||||
|
||||
export interface HookRegistry {
|
||||
[key: string]: (...args: any[]) => any
|
||||
@@ -41,10 +44,13 @@ export const hooksRegistry: HookRegistry = {
|
||||
useFileUpload,
|
||||
useAccordion,
|
||||
useBindingEditor,
|
||||
useRepeatWrapper,
|
||||
useAppLayout,
|
||||
useAppRouterLayout,
|
||||
useNavigationMenu,
|
||||
useDataSourceManagerState,
|
||||
useFormatValue,
|
||||
useConflictResolution,
|
||||
// Add more hooks here as needed
|
||||
}
|
||||
|
||||
|
||||
6
src/lib/json-ui/interfaces/conditional-wrapper.ts
Normal file
6
src/lib/json-ui/interfaces/conditional-wrapper.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface ConditionalWrapperProps {
|
||||
condition: boolean
|
||||
children: React.ReactNode
|
||||
fallback?: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* ConflictIndicatorProps - JSON definition interface
|
||||
* Indicator for conflicts
|
||||
*/
|
||||
export interface ConflictIndicatorProps {}
|
||||
export interface ConflictIndicatorProps {
|
||||
onClick?: () => void
|
||||
showLabel?: boolean
|
||||
variant?: 'badge' | 'compact'
|
||||
}
|
||||
|
||||
8
src/lib/json-ui/interfaces/data-card.ts
Normal file
8
src/lib/json-ui/interfaces/data-card.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface DataCardProps {
|
||||
title: string
|
||||
description?: string
|
||||
icon?: string
|
||||
gradient?: string
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
7
src/lib/json-ui/interfaces/dynamic-text.ts
Normal file
7
src/lib/json-ui/interfaces/dynamic-text.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface DynamicTextProps {
|
||||
value: any
|
||||
format?: 'text' | 'number' | 'currency' | 'date' | 'time' | 'datetime' | 'boolean'
|
||||
currency?: string
|
||||
locale?: string
|
||||
className?: string
|
||||
}
|
||||
6
src/lib/json-ui/interfaces/feature-toggle-settings.ts
Normal file
6
src/lib/json-ui/interfaces/feature-toggle-settings.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { FeatureToggles } from '@/types/project'
|
||||
|
||||
export interface FeatureToggleSettingsProps {
|
||||
features: FeatureToggles
|
||||
onFeaturesChange: (features: FeatureToggles) => void
|
||||
}
|
||||
9
src/lib/json-ui/interfaces/flex-layout.ts
Normal file
9
src/lib/json-ui/interfaces/flex-layout.ts
Normal 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
|
||||
}
|
||||
12
src/lib/json-ui/interfaces/grid-layout.ts
Normal file
12
src/lib/json-ui/interfaces/grid-layout.ts
Normal 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
|
||||
}
|
||||
6
src/lib/json-ui/interfaces/icon-renderer.ts
Normal file
6
src/lib/json-ui/interfaces/icon-renderer.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface IconRendererProps {
|
||||
name: string
|
||||
size?: number
|
||||
weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone'
|
||||
className?: string
|
||||
}
|
||||
@@ -34,6 +34,9 @@ export * from './menu'
|
||||
export * from './file-upload'
|
||||
export * from './accordion'
|
||||
export * from './binding-editor'
|
||||
export * from './icon-renderer'
|
||||
export * from './dynamic-text'
|
||||
export * from './repeat-wrapper'
|
||||
export * from './tree-list-panel'
|
||||
export * from './app-layout'
|
||||
export * from './app-router-layout'
|
||||
@@ -73,7 +76,9 @@ export * from './hover-card'
|
||||
export * from './icon'
|
||||
export * from './input-otp'
|
||||
export * from './label'
|
||||
export * from './conditional-wrapper'
|
||||
export * from './pagination'
|
||||
export * from './panel'
|
||||
export * from './progress'
|
||||
export * from './progress-bar'
|
||||
export * from './pulse'
|
||||
@@ -143,7 +148,9 @@ export * from './dot'
|
||||
export * from './empty-state'
|
||||
export * from './empty-state-icon'
|
||||
export * from './flex'
|
||||
export * from './flex-layout'
|
||||
export * from './grid'
|
||||
export * from './grid-layout'
|
||||
export * from './icon-button'
|
||||
export * from './icon-text'
|
||||
export * from './icon-wrapper'
|
||||
@@ -223,3 +230,4 @@ export * from './comprehensive-demo-page'
|
||||
export * from './template-explorer'
|
||||
export * from './project-manager'
|
||||
export * from './storage-settings-panel'
|
||||
export * from './feature-toggle-settings'
|
||||
|
||||
8
src/lib/json-ui/interfaces/panel.ts
Normal file
8
src/lib/json-ui/interfaces/panel.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface PanelProps {
|
||||
title?: string
|
||||
description?: string
|
||||
actions?: React.ReactNode
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
variant?: 'default' | 'bordered' | 'elevated'
|
||||
}
|
||||
7
src/lib/json-ui/interfaces/repeat-wrapper.ts
Normal file
7
src/lib/json-ui/interfaces/repeat-wrapper.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface RepeatWrapperProps {
|
||||
items: any[]
|
||||
render: (item: any, index: number) => React.ReactNode
|
||||
emptyMessage?: string
|
||||
className?: string
|
||||
gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
}
|
||||
@@ -34,14 +34,19 @@ import type {
|
||||
TreeCardProps,
|
||||
FilterInputProps,
|
||||
CopyButtonProps,
|
||||
ConditionalWrapperProps,
|
||||
InputProps,
|
||||
PasswordInputProps,
|
||||
ImageProps,
|
||||
DataCardProps,
|
||||
RepeatWrapperProps,
|
||||
PopoverProps,
|
||||
MenuProps,
|
||||
FileUploadProps,
|
||||
AccordionProps,
|
||||
BindingEditorProps,
|
||||
IconRendererProps,
|
||||
DynamicTextProps,
|
||||
AppLayoutProps,
|
||||
AppRouterLayoutProps,
|
||||
AppMainPanelProps,
|
||||
@@ -88,6 +93,7 @@ import type {
|
||||
InputOTPProps,
|
||||
LabelProps,
|
||||
PaginationProps,
|
||||
PanelProps,
|
||||
ProgressProps,
|
||||
ProgressBarProps,
|
||||
PulseProps,
|
||||
@@ -149,6 +155,8 @@ import type {
|
||||
DotProps,
|
||||
EmptyStateProps,
|
||||
EmptyStateIconProps,
|
||||
FlexLayoutProps,
|
||||
GridLayoutProps,
|
||||
FlexProps,
|
||||
GridProps,
|
||||
IconButtonProps,
|
||||
@@ -241,6 +249,7 @@ import type {
|
||||
TemplateExplorerProps,
|
||||
ProjectManagerProps,
|
||||
StorageSettingsPanelProps,
|
||||
FeatureToggleSettingsProps,
|
||||
} from './interfaces'
|
||||
|
||||
// Import JSON definitions
|
||||
@@ -270,14 +279,19 @@ import storageSettingsDef from '@/components/json-definitions/storage-settings.j
|
||||
import treeCardDef from '@/components/json-definitions/tree-card.json'
|
||||
import filterInputDef from '@/components/json-definitions/filter-input.json'
|
||||
import copyButtonDef from '@/components/json-definitions/copy-button.json'
|
||||
import conditionalWrapperDef from '@/components/json-definitions/conditional-wrapper.json'
|
||||
import inputDef from '@/components/json-definitions/input.json'
|
||||
import passwordInputDef from '@/components/json-definitions/password-input.json'
|
||||
import imageDef from '@/components/json-definitions/image.json'
|
||||
import dataCardDef from '@/components/json-definitions/data-card.json'
|
||||
import repeatWrapperDef from '@/components/json-definitions/repeat-wrapper.json'
|
||||
import popoverDef from '@/components/json-definitions/popover.json'
|
||||
import menuDef from '@/components/json-definitions/menu.json'
|
||||
import fileUploadDef from '@/components/json-definitions/file-upload.json'
|
||||
import accordionDef from '@/components/json-definitions/accordion.json'
|
||||
import bindingEditorDef from '@/components/json-definitions/binding-editor.json'
|
||||
import iconRendererDef from '@/components/json-definitions/icon-renderer.json'
|
||||
import dynamicTextDef from '@/components/json-definitions/dynamic-text.json'
|
||||
import appLayoutDef from '@/components/json-definitions/app-layout.json'
|
||||
import appRouterLayoutDef from '@/components/json-definitions/app-router-layout.json'
|
||||
import appMainPanelDef from '@/components/json-definitions/app-main-panel.json'
|
||||
@@ -318,6 +332,7 @@ import iconDef from '@/components/json-definitions/icon.json'
|
||||
import inputOtpDef from '@/components/json-definitions/input-otp.json'
|
||||
import labelDef from '@/components/json-definitions/label.json'
|
||||
import paginationDef from '@/components/json-definitions/pagination.json'
|
||||
import panelDef from '@/components/json-definitions/panel.json'
|
||||
import progressDef from '@/components/json-definitions/progress.json'
|
||||
import progressBarDef from '@/components/json-definitions/progress-bar.json'
|
||||
import pulseDef from '@/components/json-definitions/pulse.json'
|
||||
@@ -386,6 +401,8 @@ import dotDef from '@/components/json-definitions/dot.json'
|
||||
import emptyStateDef from '@/components/json-definitions/empty-state.json'
|
||||
import emptyStateIconDef from '@/components/json-definitions/empty-state-icon.json'
|
||||
import flexDef from '@/components/json-definitions/flex.json'
|
||||
import flexLayoutDef from '@/components/json-definitions/flex-layout.json'
|
||||
import gridLayoutDef from '@/components/json-definitions/grid-layout.json'
|
||||
import gridDef from '@/components/json-definitions/grid.json'
|
||||
import iconButtonDef from '@/components/json-definitions/icon-button.json'
|
||||
import iconTextDef from '@/components/json-definitions/icon-text.json'
|
||||
@@ -479,6 +496,7 @@ import comprehensiveDemoPageDef from '@/components/json-definitions/comprehensiv
|
||||
import templateExplorerDef from '@/components/json-definitions/template-explorer.json'
|
||||
import projectManagerDef from '@/components/json-definitions/project-manager.json'
|
||||
import storageSettingsPanelDef from '@/components/json-definitions/storage-settings-panel.json'
|
||||
import featureToggleSettingsDef from '@/components/json-definitions/feature-toggle-settings.json'
|
||||
|
||||
// Create pure JSON components (no hooks)
|
||||
export const BindingIndicator = createJsonComponent<BindingIndicatorProps>(bindingIndicatorDef)
|
||||
@@ -486,6 +504,7 @@ export const ButtonGroup = createJsonComponent<ButtonGroupProps>(buttonGroupDef)
|
||||
export const Chip = createJsonComponent<ChipProps>(chipDef)
|
||||
export const CircularProgress = createJsonComponent<CircularProgressProps>(circularProgressDef)
|
||||
export const Code = createJsonComponent<CodeProps>(codeDef)
|
||||
export const ConditionalWrapper = createJsonComponent<ConditionalWrapperProps>(conditionalWrapperDef)
|
||||
export const CommandPalette = createJsonComponent<CommandPaletteProps>(commandPaletteDef)
|
||||
export const CompletionCard = createJsonComponent<CompletionCardProps>(completionCardDef)
|
||||
export const ComponentPaletteItem = createJsonComponent<ComponentPaletteItemProps>(componentPaletteItemDef)
|
||||
@@ -535,6 +554,7 @@ export const Icon = createJsonComponent<IconProps>(iconDef)
|
||||
export const InputOTP = createJsonComponent<InputOTPProps>(inputOtpDef)
|
||||
export const Label = createJsonComponent<LabelProps>(labelDef)
|
||||
export const Pagination = createJsonComponent<PaginationProps>(paginationDef)
|
||||
export const Panel = createJsonComponent<PanelProps>(panelDef)
|
||||
export const Progress = createJsonComponent<ProgressProps>(progressDef)
|
||||
export const ProgressBar = createJsonComponent<ProgressBarProps>(progressBarDef)
|
||||
export const Pulse = createJsonComponent<PulseProps>(pulseDef)
|
||||
@@ -669,6 +689,19 @@ export const Image = createJsonComponentWithHooks<ImageProps>(imageDef, {
|
||||
}
|
||||
}
|
||||
})
|
||||
export const DataCard = createJsonComponent<DataCardProps>(dataCardDef)
|
||||
|
||||
export const RepeatWrapper = createJsonComponentWithHooks<RepeatWrapperProps>(repeatWrapperDef, {
|
||||
hooks: {
|
||||
repeatData: {
|
||||
hookName: "useRepeatWrapper",
|
||||
args: (props) => [{
|
||||
items: props.items,
|
||||
render: props.render
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const Popover = createJsonComponentWithHooks<PopoverProps>(popoverDef, {
|
||||
hooks: {
|
||||
@@ -715,6 +748,17 @@ export const BindingEditor = createJsonComponentWithHooks<BindingEditorProps>(bi
|
||||
}
|
||||
})
|
||||
|
||||
export const IconRenderer = createJsonComponent<IconRendererProps>(iconRendererDef)
|
||||
|
||||
export const DynamicText = createJsonComponentWithHooks<DynamicTextProps>(dynamicTextDef, {
|
||||
hooks: {
|
||||
formattedValue: {
|
||||
hookName: 'useFormatValue',
|
||||
args: (props) => [props.value, props.format, props.currency, props.locale]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const AppLayout = createJsonComponentWithHooks<AppLayoutProps>(appLayoutDef, {
|
||||
hooks: {
|
||||
hookData: {
|
||||
@@ -781,6 +825,8 @@ export const Dot = createJsonComponent<DotProps>(dotDef)
|
||||
export const EmptyState = createJsonComponent<EmptyStateProps>(emptyStateDef)
|
||||
export const EmptyStateIcon = createJsonComponent<EmptyStateIconProps>(emptyStateIconDef)
|
||||
export const Flex = createJsonComponent<FlexProps>(flexDef)
|
||||
export const FlexLayout = createJsonComponent<FlexLayoutProps>(flexLayoutDef)
|
||||
export const GridLayout = createJsonComponent<GridLayoutProps>(gridLayoutDef)
|
||||
export const Grid = createJsonComponent<GridProps>(gridDef)
|
||||
export const IconButton = createJsonComponent<IconButtonProps>(iconButtonDef)
|
||||
export const IconText = createJsonComponent<IconTextProps>(iconTextDef)
|
||||
@@ -839,7 +885,23 @@ export const PWAStatusBar = createJsonComponent<PWAStatusBarProps>(pwaStatusBarD
|
||||
export const PWAUpdatePrompt = createJsonComponent<PWAUpdatePromptProps>(pwaUpdatePromptDef)
|
||||
export const PWAInstallPrompt = createJsonComponent<PWAInstallPromptProps>(pwaInstallPromptDef)
|
||||
export const ConflictCard = createJsonComponent<ConflictCardProps>(conflictCardDef)
|
||||
export const ConflictIndicator = createJsonComponent<ConflictIndicatorProps>(conflictIndicatorDef)
|
||||
export const ConflictIndicator = createJsonComponentWithHooks<ConflictIndicatorProps>(
|
||||
conflictIndicatorDef,
|
||||
{
|
||||
hooks: {
|
||||
hasConflicts: {
|
||||
hookName: 'useConflictResolution',
|
||||
args: () => [],
|
||||
selector: (result) => result.hasConflicts
|
||||
},
|
||||
stats: {
|
||||
hookName: 'useConflictResolution',
|
||||
args: () => [],
|
||||
selector: (result) => result.stats
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
export const ErrorPanel = createJsonComponent<ErrorPanelProps>(errorPanelDef)
|
||||
export const PreviewDialog = createJsonComponent<PreviewDialogProps>(previewDialogDef)
|
||||
export const NotFoundPage = createJsonComponent<NotFoundPageProps>(notFoundPageDef)
|
||||
@@ -862,5 +924,6 @@ export const ComprehensiveDemoPage = createJsonComponent<ComprehensiveDemoPagePr
|
||||
export const TemplateExplorer = createJsonComponent<TemplateExplorerProps>(templateExplorerDef)
|
||||
export const ProjectManager = createJsonComponent<ProjectManagerProps>(projectManagerDef)
|
||||
export const StorageSettingsPanel = createJsonComponent<StorageSettingsPanelProps>(storageSettingsPanelDef)
|
||||
export const FeatureToggleSettings = createJsonComponent<FeatureToggleSettingsProps>(featureToggleSettingsDef)
|
||||
|
||||
// All components converted to pure JSON! 🎉
|
||||
|
||||
@@ -77,6 +77,7 @@ export const jsonUIComponentTypes = [
|
||||
"ComponentTreeNode",
|
||||
"ComponentTreeWrapper",
|
||||
"ConfirmButton",
|
||||
"ConditionalWrapper",
|
||||
"ConflictResolutionPage",
|
||||
"Container",
|
||||
"ContextMenu",
|
||||
@@ -97,6 +98,7 @@ export const jsonUIComponentTypes = [
|
||||
"Dialog",
|
||||
"Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,",
|
||||
"Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle",
|
||||
"DynamicText",
|
||||
"Divider",
|
||||
"DockerBuildDebugger",
|
||||
"DocumentationView",
|
||||
@@ -125,6 +127,7 @@ export const jsonUIComponentTypes = [
|
||||
"Filter",
|
||||
"FilterInput",
|
||||
"Flex",
|
||||
"FlexLayout",
|
||||
"Form",
|
||||
"Form as ShadcnForm,\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,",
|
||||
"FormField",
|
||||
@@ -132,6 +135,7 @@ export const jsonUIComponentTypes = [
|
||||
"GitHubBuildStatusWrapper",
|
||||
"GlowCard",
|
||||
"Grid",
|
||||
"GridLayout",
|
||||
"Heading",
|
||||
"Heart",
|
||||
"HelpCircle",
|
||||
@@ -140,6 +144,7 @@ export const jsonUIComponentTypes = [
|
||||
"HoverCard",
|
||||
"HoverCard as ShadcnHoverCard,\n HoverCardContent,\n HoverCardTrigger,",
|
||||
"Icon",
|
||||
"IconRenderer",
|
||||
"IconButton",
|
||||
"IconText",
|
||||
"IconWrapper",
|
||||
@@ -192,6 +197,7 @@ export const jsonUIComponentTypes = [
|
||||
"PageHeader",
|
||||
"PageHeaderContent",
|
||||
"Pagination",
|
||||
"Panel",
|
||||
"PanelHeader",
|
||||
"PasswordInput",
|
||||
"PersistenceDashboard",
|
||||
@@ -210,6 +216,7 @@ export const jsonUIComponentTypes = [
|
||||
"RadioGroup",
|
||||
"RangeSlider",
|
||||
"Rating",
|
||||
"RepeatWrapper",
|
||||
"RefreshCw",
|
||||
"Resizable",
|
||||
"ResponsiveGrid",
|
||||
|
||||
Reference in New Issue
Block a user