Merge pull request #171 from johndoe6345789/codex/extend-json-schema-for-component-registry

Make json-ui registry sources data-driven
This commit is contained in:
2026-01-18 17:57:31 +00:00
committed by GitHub
3 changed files with 553 additions and 26 deletions

View File

@@ -717,6 +717,348 @@
"status": "supported",
"source": "atoms"
},
{
"type": "ArrowLeft",
"name": "ArrowLeft",
"category": "display",
"canHaveChildren": false,
"description": "ArrowLeft icon",
"status": "supported",
"source": "icons"
},
{
"type": "ArrowRight",
"name": "ArrowRight",
"category": "display",
"canHaveChildren": false,
"description": "ArrowRight icon",
"status": "supported",
"source": "icons"
},
{
"type": "Check",
"name": "Check",
"category": "display",
"canHaveChildren": false,
"description": "Check icon",
"status": "supported",
"source": "icons"
},
{
"type": "X",
"name": "X",
"category": "display",
"canHaveChildren": false,
"description": "X icon",
"status": "supported",
"source": "icons"
},
{
"type": "Plus",
"name": "Plus",
"category": "display",
"canHaveChildren": false,
"description": "Plus icon",
"status": "supported",
"source": "icons"
},
{
"type": "Minus",
"name": "Minus",
"category": "display",
"canHaveChildren": false,
"description": "Minus icon",
"status": "supported",
"source": "icons"
},
{
"type": "Search",
"name": "Search",
"category": "display",
"canHaveChildren": false,
"description": "Search icon",
"status": "supported",
"source": "icons"
},
{
"type": "Filter",
"name": "Filter",
"category": "display",
"canHaveChildren": false,
"description": "Filter icon",
"status": "supported",
"source": "icons"
},
{
"type": "Download",
"name": "Download",
"category": "display",
"canHaveChildren": false,
"description": "Download icon",
"status": "supported",
"source": "icons"
},
{
"type": "Upload",
"name": "Upload",
"category": "display",
"canHaveChildren": false,
"description": "Upload icon",
"status": "supported",
"source": "icons"
},
{
"type": "Edit",
"name": "Edit",
"category": "display",
"canHaveChildren": false,
"description": "Edit icon",
"status": "supported",
"source": "icons"
},
{
"type": "Trash",
"name": "Trash",
"category": "display",
"canHaveChildren": false,
"description": "Trash icon",
"status": "supported",
"source": "icons"
},
{
"type": "Eye",
"name": "Eye",
"category": "display",
"canHaveChildren": false,
"description": "Eye icon",
"status": "supported",
"source": "icons"
},
{
"type": "EyeOff",
"name": "EyeOff",
"category": "display",
"canHaveChildren": false,
"description": "EyeOff icon",
"status": "supported",
"source": "icons"
},
{
"type": "ChevronUp",
"name": "ChevronUp",
"category": "display",
"canHaveChildren": false,
"description": "ChevronUp icon",
"status": "supported",
"source": "icons"
},
{
"type": "ChevronDown",
"name": "ChevronDown",
"category": "display",
"canHaveChildren": false,
"description": "ChevronDown icon",
"status": "supported",
"source": "icons"
},
{
"type": "ChevronLeft",
"name": "ChevronLeft",
"category": "display",
"canHaveChildren": false,
"description": "ChevronLeft icon",
"status": "supported",
"source": "icons"
},
{
"type": "ChevronRight",
"name": "ChevronRight",
"category": "display",
"canHaveChildren": false,
"description": "ChevronRight icon",
"status": "supported",
"source": "icons"
},
{
"type": "Settings",
"name": "Settings",
"category": "display",
"canHaveChildren": false,
"description": "Settings icon",
"status": "supported",
"source": "icons"
},
{
"type": "User",
"name": "User",
"category": "display",
"canHaveChildren": false,
"description": "User icon",
"status": "supported",
"source": "icons"
},
{
"type": "Bell",
"name": "Bell",
"category": "display",
"canHaveChildren": false,
"description": "Bell icon",
"status": "supported",
"source": "icons"
},
{
"type": "Mail",
"name": "Mail",
"category": "display",
"canHaveChildren": false,
"description": "Mail icon",
"status": "supported",
"source": "icons"
},
{
"type": "Calendar",
"name": "Calendar",
"category": "display",
"canHaveChildren": false,
"description": "Calendar icon",
"status": "supported",
"source": "icons"
},
{
"type": "Clock",
"name": "Clock",
"category": "display",
"canHaveChildren": false,
"description": "Clock icon",
"status": "supported",
"source": "icons"
},
{
"type": "Star",
"name": "Star",
"category": "display",
"canHaveChildren": false,
"description": "Star icon",
"status": "supported",
"source": "icons"
},
{
"type": "Heart",
"name": "Heart",
"category": "display",
"canHaveChildren": false,
"description": "Heart icon",
"status": "supported",
"source": "icons"
},
{
"type": "Share",
"name": "Share",
"category": "display",
"canHaveChildren": false,
"description": "Share icon",
"status": "supported",
"source": "icons"
},
{
"type": "Link",
"name": "Link",
"category": "display",
"canHaveChildren": false,
"description": "Link icon",
"status": "supported",
"source": "icons"
},
{
"type": "Copy",
"name": "Copy",
"category": "display",
"canHaveChildren": false,
"description": "Copy icon",
"status": "supported",
"source": "icons"
},
{
"type": "Save",
"name": "Save",
"category": "display",
"canHaveChildren": false,
"description": "Save icon",
"status": "supported",
"source": "icons"
},
{
"type": "RefreshCw",
"name": "RefreshCw",
"category": "display",
"canHaveChildren": false,
"description": "RefreshCw icon",
"status": "supported",
"source": "icons"
},
{
"type": "AlertCircle",
"name": "AlertCircle",
"category": "display",
"canHaveChildren": false,
"description": "AlertCircle icon",
"status": "supported",
"source": "icons"
},
{
"type": "Info",
"name": "Info",
"category": "display",
"canHaveChildren": false,
"description": "Info icon",
"status": "supported",
"source": "icons"
},
{
"type": "HelpCircle",
"name": "HelpCircle",
"category": "display",
"canHaveChildren": false,
"description": "HelpCircle icon",
"status": "supported",
"source": "icons"
},
{
"type": "Home",
"name": "Home",
"category": "display",
"canHaveChildren": false,
"description": "Home icon",
"status": "supported",
"source": "icons"
},
{
"type": "Menu",
"name": "Menu",
"category": "display",
"canHaveChildren": false,
"description": "Menu icon",
"status": "supported",
"source": "icons"
},
{
"type": "MoreVertical",
"name": "MoreVertical",
"category": "display",
"canHaveChildren": false,
"description": "MoreVertical icon",
"status": "supported",
"source": "icons"
},
{
"type": "MoreHorizontal",
"name": "MoreHorizontal",
"category": "display",
"canHaveChildren": false,
"description": "MoreHorizontal icon",
"status": "supported",
"source": "icons"
},
{
"type": "Breadcrumb",
"name": "Breadcrumb",
@@ -1926,25 +2268,27 @@
}
],
"statistics": {
"total": 222,
"supported": 209,
"total": 239,
"supported": 226,
"planned": 0,
"jsonCompatible": 13,
"jsonCompatible": 50,
"maybeJsonCompatible": 0,
"byCategory": {
"layout": 25,
"input": 34,
"display": 31,
"navigation": 15,
"feedback": 23,
"data": 25,
"custom": 69
"layout": 24,
"input": 26,
"display": 64,
"navigation": 12,
"feedback": 21,
"data": 27,
"custom": 65
},
"bySource": {
"atoms": 117,
"molecules": 40,
"organisms": 15,
"ui": 50
"molecules": 36,
"organisms": 13,
"ui": 25,
"wrappers": 10,
"icons": 38
}
}
}

View File

@@ -0,0 +1,102 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Components Registry",
"type": "object",
"required": ["version", "description", "components"],
"properties": {
"$schema": {
"type": "string"
},
"version": {
"type": "string"
},
"description": {
"type": "string"
},
"lastUpdated": {
"type": "string"
},
"categories": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"components": {
"type": "array",
"items": {
"type": "object",
"required": [
"type",
"name",
"category",
"canHaveChildren",
"description",
"status",
"source"
],
"properties": {
"type": {
"type": "string"
},
"name": {
"type": "string"
},
"export": {
"type": "string"
},
"category": {
"type": "string"
},
"canHaveChildren": {
"type": "boolean"
},
"description": {
"type": "string"
},
"status": {
"type": "string"
},
"source": {
"type": "string",
"enum": ["atoms", "molecules", "organisms", "ui", "wrappers", "icons"]
},
"jsonCompatible": {
"type": "boolean"
},
"wrapperRequired": {
"type": "boolean"
},
"wrapperComponent": {
"type": "string"
},
"wrapperFor": {
"type": "string"
},
"deprecated": {
"type": "object",
"properties": {
"replacedBy": {
"type": "string"
},
"message": {
"type": "string"
}
},
"additionalProperties": false
},
"metadata": {
"type": "object",
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"statistics": {
"type": "object",
"additionalProperties": true
}
},
"additionalProperties": true
}

View File

@@ -1,27 +1,47 @@
import { ComponentType } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { InputOtp } from '@/components/ui/input-otp'
import { Textarea } from '@/components/ui/textarea'
import { Label } from '@/components/ui/label'
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Separator } from '@/components/ui/separator'
import { Alert as ShadcnAlert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { AlertDialog } from '@/components/ui/alert-dialog'
import { AspectRatio } from '@/components/ui/aspect-ratio'
import { Carousel } from '@/components/ui/carousel'
import { ChartContainer as Chart } from '@/components/ui/chart'
import { Collapsible } from '@/components/ui/collapsible'
import { Command } from '@/components/ui/command'
import { Switch } from '@/components/ui/switch'
import { Checkbox } from '@/components/ui/checkbox'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { DropdownMenu } from '@/components/ui/dropdown-menu'
import { Menubar } from '@/components/ui/menubar'
import { NavigationMenu } from '@/components/ui/navigation-menu'
import { Table as ShadcnTable, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Skeleton as ShadcnSkeleton } from '@/components/ui/skeleton'
import { Progress } from '@/components/ui/progress'
import { Pagination } from '@/components/ui/pagination'
import { ResizablePanelGroup as Resizable } from '@/components/ui/resizable'
import { Sheet } from '@/components/ui/sheet'
import { Sidebar } from '@/components/ui/sidebar'
import { Toaster as Sonner } from '@/components/ui/sonner'
import { ToggleGroup } from '@/components/ui/toggle-group'
import { Avatar as ShadcnAvatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { CircularProgress, Divider, ProgressBar } from '@/components/atoms'
import * as AtomComponents from '@/components/atoms'
import * as MoleculeComponents from '@/components/molecules'
import * as OrganismComponents from '@/components/organisms'
import {
ComponentBindingDialogWrapper,
ComponentTreeWrapper,
DataSourceEditorDialogWrapper,
GitHubBuildStatusWrapper,
LazyBarChartWrapper,
LazyD3BarChartWrapper,
LazyLineChartWrapper,
@@ -49,6 +69,9 @@ interface JsonRegistryEntry {
export?: string
source?: string
status?: string
wrapperRequired?: boolean
wrapperComponent?: string
wrapperFor?: string
deprecated?: DeprecatedComponentInfo
}
@@ -63,6 +86,9 @@ export interface DeprecatedComponentInfo {
const jsonRegistry = jsonComponentsRegistry as JsonComponentRegistry
const getRegistryEntryName = (entry: JsonRegistryEntry): string | undefined =>
entry.export ?? entry.name ?? entry.type
const buildRegistryFromNames = (
names: string[],
components: Record<string, ComponentType<any>>
@@ -77,10 +103,18 @@ const buildRegistryFromNames = (
}
const jsonRegistryEntries = jsonRegistry.components ?? []
const registryEntryByType = new Map(
jsonRegistryEntries
.map((entry) => {
const entryName = getRegistryEntryName(entry)
return entryName ? [entryName, entry] : null
})
.filter((entry): entry is [string, JsonRegistryEntry] => Boolean(entry))
)
const atomComponentMap = AtomComponents as Record<string, ComponentType<any>>
const deprecatedComponentInfo = jsonRegistryEntries.reduce<Record<string, DeprecatedComponentInfo>>(
(acc, entry) => {
const entryName = entry.export ?? entry.name ?? entry.type
const entryName = getRegistryEntryName(entry)
if (!entryName) {
return acc
}
@@ -93,15 +127,27 @@ const deprecatedComponentInfo = jsonRegistryEntries.reduce<Record<string, Deprec
)
const atomRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'atoms')
.map((entry) => entry.export ?? entry.name ?? entry.type)
.map((entry) => getRegistryEntryName(entry))
.filter((name): name is string => Boolean(name))
const moleculeRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'molecules')
.map((entry) => entry.export ?? entry.name ?? entry.type)
.map((entry) => getRegistryEntryName(entry))
.filter((name): name is string => Boolean(name))
const organismRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'organisms')
.map((entry) => entry.export ?? entry.name ?? entry.type)
.map((entry) => getRegistryEntryName(entry))
.filter((name): name is string => Boolean(name))
const shadcnRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'ui')
.map((entry) => getRegistryEntryName(entry))
.filter((name): name is string => Boolean(name))
const wrapperRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'wrappers')
.map((entry) => getRegistryEntryName(entry))
.filter((name): name is string => Boolean(name))
const iconRegistryNames = jsonRegistryEntries
.filter((entry) => entry.source === 'icons')
.map((entry) => getRegistryEntryName(entry))
.filter((name): name is string => Boolean(name))
export const primitiveComponents: UIComponentRegistry = {
@@ -123,9 +169,17 @@ export const primitiveComponents: UIComponentRegistry = {
nav: 'nav' as any,
}
export const shadcnComponents: UIComponentRegistry = {
const shadcnComponentMap: Record<string, ComponentType<any>> = {
AlertDialog,
AspectRatio,
Button,
Carousel,
Chart,
Collapsible,
Command,
DropdownMenu,
Input,
InputOtp,
Textarea,
Label,
Card,
@@ -164,13 +218,26 @@ export const shadcnComponents: UIComponentRegistry = {
DialogFooter,
DialogHeader,
DialogTitle,
Menubar,
NavigationMenu,
Skeleton: ShadcnSkeleton,
Pagination,
Progress,
Resizable,
Sheet,
Sidebar,
Sonner,
ToggleGroup,
Avatar: ShadcnAvatar,
AvatarFallback,
AvatarImage,
}
export const shadcnComponents: UIComponentRegistry = buildRegistryFromNames(
shadcnRegistryNames,
shadcnComponentMap
)
export const atomComponents: UIComponentRegistry = {
...buildRegistryFromNames(
atomRegistryNames,
@@ -208,16 +275,25 @@ export const organismComponents: UIComponentRegistry = buildRegistryFromNames(
OrganismComponents as Record<string, ComponentType<any>>
)
export const jsonWrapperComponents: UIComponentRegistry = {
SaveIndicator: SaveIndicatorWrapper,
LazyBarChart: LazyBarChartWrapper,
LazyLineChart: LazyLineChartWrapper,
LazyD3BarChart: LazyD3BarChartWrapper,
SeedDataManager: SeedDataManagerWrapper,
StorageSettings: StorageSettingsWrapper,
const wrapperComponentMap: Record<string, ComponentType<any>> = {
ComponentBindingDialogWrapper,
ComponentTreeWrapper,
DataSourceEditorDialogWrapper,
GitHubBuildStatusWrapper,
SaveIndicatorWrapper,
LazyBarChartWrapper,
LazyLineChartWrapper,
LazyD3BarChartWrapper,
SeedDataManagerWrapper,
StorageSettingsWrapper,
}
export const iconComponents: UIComponentRegistry = {
export const jsonWrapperComponents: UIComponentRegistry = buildRegistryFromNames(
wrapperRegistryNames,
wrapperComponentMap
)
const iconComponentMap: Record<string, ComponentType<any>> = {
ArrowLeft,
ArrowRight,
Check,
@@ -258,6 +334,11 @@ export const iconComponents: UIComponentRegistry = {
MoreHorizontal: DotsThree,
}
export const iconComponents: UIComponentRegistry = buildRegistryFromNames(
iconRegistryNames,
iconComponentMap
)
export const uiComponentRegistry: UIComponentRegistry = {
...primitiveComponents,
...shadcnComponents,