Generate JSON UI component types

This commit is contained in:
2026-01-18 18:46:02 +00:00
parent b34e45067d
commit b8dc6f38e6
6 changed files with 362 additions and 36 deletions

View File

@@ -13,6 +13,60 @@
"custom": "Custom domain-specific components"
},
"components": [
{
"type": "div",
"name": "div",
"category": "layout",
"canHaveChildren": true,
"description": "Generic block container",
"status": "supported",
"source": "primitive"
},
{
"type": "section",
"name": "section",
"category": "layout",
"canHaveChildren": true,
"description": "Semantic section container",
"status": "supported",
"source": "primitive"
},
{
"type": "article",
"name": "article",
"category": "layout",
"canHaveChildren": true,
"description": "Semantic article container",
"status": "supported",
"source": "primitive"
},
{
"type": "header",
"name": "header",
"category": "layout",
"canHaveChildren": true,
"description": "Semantic header container",
"status": "supported",
"source": "primitive"
},
{
"type": "footer",
"name": "footer",
"category": "layout",
"canHaveChildren": true,
"description": "Semantic footer container",
"status": "supported",
"source": "primitive"
},
{
"type": "main",
"name": "main",
"category": "layout",
"canHaveChildren": true,
"description": "Semantic main container",
"status": "supported",
"source": "primitive"
},
{
"type": "ActionCard",
"name": "ActionCard",

View File

@@ -6,7 +6,8 @@
"scripts": {
"dev": "vite",
"kill": "fuser -k 5000/tcp",
"prebuild": "mkdir -p /tmp/dist || true",
"predev": "npm run components:generate-types",
"prebuild": "npm run components:generate-types && mkdir -p /tmp/dist || true",
"build": "tsc -b --noCheck && vite build",
"lint": "eslint . --fix && npm run lint:schemas",
"lint:check": "eslint . && npm run lint:schemas",
@@ -24,6 +25,7 @@
"pages:generate": "node scripts/generate-page.js",
"schemas:validate": "tsx scripts/validate-json-schemas.ts",
"components:list": "node scripts/list-json-components.cjs",
"components:generate-types": "tsx scripts/generate-json-ui-component-types.ts",
"components:scan": "node scripts/scan-and-update-registry.cjs",
"components:validate": "node scripts/validate-supported-components.cjs"
},

View File

@@ -0,0 +1,50 @@
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
interface RegistryComponent {
type?: string
name?: string
export?: string
}
interface RegistryData {
components?: RegistryComponent[]
}
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const rootDir = path.resolve(__dirname, '..')
const registryPath = path.join(rootDir, 'json-components-registry.json')
const outputPath = path.join(rootDir, 'src/types/json-ui-component-types.ts')
const registryData = JSON.parse(fs.readFileSync(registryPath, 'utf8')) as RegistryData
const components = registryData.components ?? []
const seen = new Set<string>()
const componentTypes = components.flatMap((component) => {
const typeName = component.type ?? component.name ?? component.export
if (!typeName || typeof typeName !== 'string') {
throw new Error('Registry component is missing a valid type/name/export entry.')
}
if (seen.has(typeName)) {
return []
}
seen.add(typeName)
return [typeName]
})
const lines = [
'// This file is auto-generated by scripts/generate-json-ui-component-types.ts.',
'// Do not edit this file directly.',
'',
'export const jsonUIComponentTypes = [',
...componentTypes.map((typeName) => ` ${JSON.stringify(typeName)},`),
'] as const',
'',
'export type JSONUIComponentType = typeof jsonUIComponentTypes[number]',
'',
]
fs.writeFileSync(outputPath, `${lines.join('\n')}`)
console.log(`✅ Wrote ${componentTypes.length} component types to ${outputPath}`)

View File

@@ -4,7 +4,7 @@ const path = require('path')
const rootDir = path.resolve(__dirname, '..')
const registryPath = path.join(rootDir, 'json-components-registry.json')
const definitionsPath = path.join(rootDir, 'src/lib/component-definitions.json')
const componentTypesPath = path.join(rootDir, 'src/types/json-ui.ts')
const componentTypesPath = path.join(rootDir, 'src/types/json-ui-component-types.ts')
const uiRegistryPath = path.join(rootDir, 'src/lib/json-ui/component-registry.ts')
const atomIndexPath = path.join(rootDir, 'src/components/atoms/index.ts')
const moleculeIndexPath = path.join(rootDir, 'src/components/molecules/index.ts')
@@ -21,16 +21,10 @@ const componentDefinitions = readJson(definitionsPath)
const definitionTypes = new Set(componentDefinitions.map((def) => def.type))
const componentTypesContent = readText(componentTypesPath)
const componentTypesStart = componentTypesContent.indexOf('export type ComponentType')
const componentTypesEnd = componentTypesContent.indexOf('export type ActionType')
if (componentTypesStart === -1 || componentTypesEnd === -1) {
throw new Error('Unable to locate ComponentType union in src/types/json-ui.ts')
}
const componentTypesBlock = componentTypesContent.slice(componentTypesStart, componentTypesEnd)
const componentTypeSet = new Set()
const componentTypeRegex = /'([^']+)'/g
const componentTypeRegex = /"([^"]+)"/g
let match
while ((match = componentTypeRegex.exec(componentTypesBlock)) !== null) {
while ((match = componentTypeRegex.exec(componentTypesContent)) !== null) {
componentTypeSet.add(match[1])
}

View File

@@ -0,0 +1,249 @@
// This file is auto-generated by scripts/generate-json-ui-component-types.ts.
// Do not edit this file directly.
export const jsonUIComponentTypes = [
"div",
"section",
"article",
"header",
"footer",
"main",
"ActionCard",
"AlertDialog",
"Card",
"CodeExplanationDialog",
"CompletionCard",
"ComponentBindingDialog",
"ComponentBindingDialogWrapper",
"Container",
"DataSourceCard",
"DataSourceEditorDialog",
"DataSourceEditorDialogWrapper",
"Dialog",
"Drawer",
"Flex",
"GlowCard",
"Grid",
"HoverCard",
"Modal",
"ResponsiveGrid",
"Section",
"Stack",
"TipsCard",
"TreeCard",
"TreeFormDialog",
"ActionButton",
"Button",
"ButtonGroup",
"Checkbox",
"ConfirmButton",
"CopyButton",
"DatePicker",
"FileUpload",
"FilterInput",
"Form",
"IconButton",
"Input",
"InputOtp",
"NumberInput",
"PasswordInput",
"QuickActionButton",
"Radio",
"RadioGroup",
"RangeSlider",
"Select",
"Slider",
"Switch",
"TextArea",
"Toggle",
"ToggleGroup",
"ToolbarButton",
"ActionIcon",
"Avatar",
"AvatarGroup",
"Badge",
"CircularProgress",
"Code",
"Divider",
"FileIcon",
"Heading",
"HelperText",
"IconText",
"IconWrapper",
"Image",
"Label",
"Progress",
"ProgressBar",
"SchemaCodeViewer",
"Separator",
"Skeleton",
"Spinner",
"Tag",
"Text",
"Textarea",
"TextGradient",
"TextHighlight",
"TreeIcon",
"ArrowLeft",
"ArrowRight",
"Check",
"X",
"Plus",
"Minus",
"Search",
"Filter",
"Download",
"Upload",
"Edit",
"Trash",
"Eye",
"EyeOff",
"ChevronUp",
"ChevronDown",
"ChevronLeft",
"ChevronRight",
"Settings",
"User",
"Bell",
"Mail",
"Calendar",
"Clock",
"Star",
"Heart",
"Share",
"Link",
"Copy",
"Save",
"RefreshCw",
"AlertCircle",
"Info",
"HelpCircle",
"Home",
"Menu",
"MoreVertical",
"MoreHorizontal",
"Breadcrumb",
"ContextMenu",
"DropdownMenu",
"FileTabs",
"Menubar",
"NavigationGroupHeader",
"NavigationItem",
"NavigationMenu",
"TabIcon",
"Tabs",
"Alert",
"CountBadge",
"DataSourceBadge",
"EmptyCanvasState",
"EmptyEditorState",
"EmptyMessage",
"EmptyState",
"EmptyStateIcon",
"ErrorBadge",
"GitHubBuildStatus",
"GitHubBuildStatusWrapper",
"InfoBox",
"LabelWithBadge",
"LoadingFallback",
"LoadingSpinner",
"LoadingState",
"Notification",
"SchemaEditorStatusBar",
"SeedDataStatus",
"StatusBadge",
"StatusIcon",
"Chart",
"DataList",
"DataSourceManager",
"DataTable",
"KeyValue",
"LazyBarChart",
"LazyBarChartWrapper",
"LazyD3BarChart",
"LazyD3BarChartWrapper",
"LazyLineChart",
"LazyLineChartWrapper",
"List",
"ListItem",
"MetricCard",
"MetricDisplay",
"SeedDataManager",
"SeedDataManagerWrapper",
"StatCard",
"Table",
"TableHeader",
"TableBody",
"TableRow",
"TableCell",
"TableHead",
"Timeline",
"TreeListHeader",
"TreeListPanel",
"Accordion",
"ActionBar",
"AppBranding",
"AppHeader",
"AppLogo",
"AspectRatio",
"BindingEditor",
"BindingIndicator",
"CanvasRenderer",
"Carousel",
"Chip",
"Collapsible",
"ColorSwatch",
"Command",
"CommandPalette",
"ComponentPalette",
"ComponentPaletteItem",
"ComponentTree",
"ComponentTreeWrapper",
"ComponentTreeNode",
"DataCard",
"DetailRow",
"Dot",
"EditorActions",
"EditorToolbar",
"InfoPanel",
"JSONUIShowcase",
"Kbd",
"LazyInlineMonacoEditor",
"LazyMonacoEditor",
"LiveIndicator",
"MonacoEditorPanel",
"PageHeader",
"PageHeaderContent",
"Pagination",
"PanelHeader",
"Popover",
"PropertyEditor",
"PropertyEditorField",
"Pulse",
"Rating",
"Resizable",
"SaveIndicator",
"SaveIndicatorWrapper",
"SchemaEditorCanvas",
"SchemaEditorLayout",
"SchemaEditorPropertiesPanel",
"SchemaEditorSidebar",
"SchemaEditorToolbar",
"ScrollArea",
"SearchBar",
"SearchInput",
"Sheet",
"Sidebar",
"Sonner",
"Spacer",
"Sparkle",
"StepIndicator",
"Stepper",
"StorageSettings",
"StorageSettingsWrapper",
"Timestamp",
"ToolbarActions",
"Tooltip",
] as const
export type JSONUIComponentType = typeof jsonUIComponentTypes[number]

View File

@@ -1,29 +1,6 @@
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' | 'DatePicker' | 'FileUpload'
| 'Badge' | 'Progress' | 'Separator' | 'Tabs' | 'TabsContent' | 'TabsList' | 'TabsTrigger' | 'Dialog'
| 'Text' | 'Heading' | 'Label' | 'List' | 'ListItem' | 'Grid' | 'Stack' | 'Flex' | 'Container'
| 'Link' | 'Breadcrumb' | 'Image' | 'Avatar' | 'Code' | 'Tag' | 'Spinner' | 'Skeleton'
| 'CircularProgress' | 'Divider' | 'ProgressBar'
| 'Alert' | 'InfoBox' | 'EmptyState' | 'StatusBadge'
| 'ErrorBadge' | 'Notification' | 'StatusIcon'
| 'Table' | 'TableHeader' | 'TableBody' | 'TableRow' | 'TableCell' | 'TableHead'
| 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar'
| 'DataList' | 'DataTable' | 'MetricCard' | 'Timeline'
| 'LazyBarChart' | 'LazyLineChart' | 'LazyD3BarChart' | 'SeedDataManager'
| 'SaveIndicator' | 'StorageSettings'
| 'AppBranding' | 'LabelWithBadge' | 'NavigationGroupHeader' | 'EmptyEditorState' | 'LoadingFallback' | 'LoadingState'
| 'CodeExplanationDialog' | 'ComponentBindingDialog' | 'DataSourceCard' | 'DataSourceEditorDialog' | 'TreeCard' | 'TreeFormDialog'
| 'ToolbarButton'
| 'SchemaCodeViewer'
| 'FileTabs' | 'NavigationItem' | 'NavigationMenu'
| 'EmptyCanvasState' | 'SchemaEditorStatusBar'
| 'DataSourceManager' | 'TreeListHeader' | 'TreeListPanel'
| 'AppHeader' | 'BindingEditor' | 'CanvasRenderer' | 'ComponentPalette' | 'ComponentTree' | 'EditorActions'
| 'EditorToolbar' | 'JSONUIShowcase' | 'LazyInlineMonacoEditor' | 'LazyMonacoEditor' | 'MonacoEditorPanel'
| 'PageHeaderContent' | 'PropertyEditor' | 'SchemaEditorCanvas' | 'SchemaEditorLayout'
| 'SchemaEditorPropertiesPanel' | 'SchemaEditorSidebar' | 'SchemaEditorToolbar' | 'SearchBar' | 'ToolbarActions'
import type { JSONUIComponentType } from './json-ui-component-types'
export type ComponentType = JSONUIComponentType
export interface BreadcrumbItem {
label: string