diff --git a/json-components-registry.json b/json-components-registry.json index 575f4c0..0bfb080 100644 --- a/json-components-registry.json +++ b/json-components-registry.json @@ -1500,7 +1500,11 @@ "canHaveChildren": true, "description": "Chart component", "status": "supported", - "source": "ui" + "source": "ui", + "load": { + "path": "@/components/ui/chart/chart-container.tsx", + "export": "ChartContainer" + } }, { "type": "DataList", @@ -2047,7 +2051,11 @@ "description": "JSONUIShowcase organism component", "status": "supported", "source": "organisms", - "jsonCompatible": true + "jsonCompatible": true, + "load": { + "path": "@/components/JSONUIShowcase.tsx", + "export": "JSONUIShowcase" + } }, { "type": "Kbd", @@ -2104,7 +2112,11 @@ "canHaveChildren": true, "description": "PageHeader component", "status": "supported", - "source": "atoms" + "source": "atoms", + "load": { + "path": "@/components/atoms/PageHeader.tsx", + "export": "BasicPageHeader" + } }, { "type": "PageHeaderContent", @@ -2187,7 +2199,11 @@ "canHaveChildren": true, "description": "Resizable component", "status": "supported", - "source": "ui" + "source": "ui", + "load": { + "path": "@/components/ui/resizable.tsx", + "export": "ResizablePanelGroup" + } }, { "type": "SaveIndicator", @@ -2291,7 +2307,11 @@ "canHaveChildren": false, "description": "Search input with icon", "status": "supported", - "source": "atoms" + "source": "atoms", + "load": { + "path": "@/components/atoms/SearchInput.tsx", + "export": "BasicSearchInput" + } }, { "type": "Sheet", diff --git a/schemas/json-components-registry-schema.json b/schemas/json-components-registry-schema.json index 9b9d424..51e7642 100644 --- a/schemas/json-components-registry-schema.json +++ b/schemas/json-components-registry-schema.json @@ -76,6 +76,9 @@ "load": { "type": "object", "properties": { + "path": { + "type": "string" + }, "export": { "type": "string" } diff --git a/src/lib/json-ui/component-registry.ts b/src/lib/json-ui/component-registry.ts index d18b342..0d4b55c 100644 --- a/src/lib/json-ui/component-registry.ts +++ b/src/lib/json-ui/component-registry.ts @@ -1,7 +1,6 @@ import { ComponentType } from 'react' import * as PhosphorIcons from '@phosphor-icons/react' import jsonComponentsRegistry from '../../../json-components-registry.json' -import { JSONUIShowcase } from '@/components/JSONUIShowcase' export interface UIComponentRegistry { [key: string]: ComponentType @@ -17,6 +16,7 @@ interface JsonRegistryEntry { wrapperComponent?: string wrapperFor?: string load?: { + path?: string export?: string } deprecated?: DeprecatedComponentInfo @@ -94,6 +94,10 @@ const moleculeModules = import.meta.glob('@/components/molecules/*.tsx', { eager const organismModules = import.meta.glob('@/components/organisms/*.tsx', { eager: true }) const uiModules = import.meta.glob('@/components/ui/**/*.{ts,tsx}', { eager: true }) const wrapperModules = import.meta.glob('@/lib/json-ui/wrappers/*.tsx', { eager: true }) +const explicitModules = import.meta.glob( + ['@/components/**/*.tsx', '@/lib/json-ui/wrappers/**/*.tsx'], + { eager: true } +) const atomComponentMap = buildComponentMapFromModules(atomModules) const moleculeComponentMap = buildComponentMapFromModules(moleculeModules) @@ -102,28 +106,26 @@ const uiComponentMap = buildComponentMapFromModules(uiModules) const wrapperComponentMap = buildComponentMapFromModules(wrapperModules) const iconComponentMap = buildComponentMapFromExports(PhosphorIcons) -const sourceAliases: Record> = { - atoms: { - PageHeader: 'BasicPageHeader', - SearchInput: 'BasicSearchInput', - }, - molecules: {}, - organisms: {}, - ui: { - Chart: 'ChartContainer', - Resizable: 'ResizablePanelGroup', - }, - wrappers: {}, -} - -const explicitComponentAllowlist: Record> = { - JSONUIShowcase, +const resolveComponentFromExplicitPath = ( + entry: JsonRegistryEntry, + entryExportName: string +): ComponentType | undefined => { + if (!entry.load?.path) { + return undefined + } + const moduleExports = explicitModules[entry.load.path] + if (!moduleExports || typeof moduleExports !== 'object') { + return undefined + } + const explicitComponents = buildComponentMapFromExports( + moduleExports as Record + ) + return explicitComponents[entryExportName] } const buildRegistryFromEntries = ( source: string, - componentMap: Record>, - aliases: Record = {} + componentMap: Record> ): UIComponentRegistry => { return jsonRegistryEntries .filter((entry) => entry.source === source) @@ -133,11 +135,9 @@ const buildRegistryFromEntries = ( if (!entryKey || !entryExportName) { return registry } - const aliasName = aliases[entryKey] const component = - componentMap[entryExportName] ?? - (aliasName ? componentMap[aliasName] : undefined) ?? - explicitComponentAllowlist[entryKey] + resolveComponentFromExplicitPath(entry, entryExportName) ?? + componentMap[entryExportName] if (component) { registry[entryKey] = component } @@ -166,32 +166,27 @@ export const primitiveComponents: UIComponentRegistry = { export const shadcnComponents: UIComponentRegistry = buildRegistryFromEntries( 'ui', - uiComponentMap, - sourceAliases.ui + uiComponentMap ) export const atomComponents: UIComponentRegistry = buildRegistryFromEntries( 'atoms', - atomComponentMap, - sourceAliases.atoms + atomComponentMap ) export const moleculeComponents: UIComponentRegistry = buildRegistryFromEntries( 'molecules', - moleculeComponentMap, - sourceAliases.molecules + moleculeComponentMap ) export const organismComponents: UIComponentRegistry = buildRegistryFromEntries( 'organisms', - organismComponentMap, - sourceAliases.organisms + organismComponentMap ) export const jsonWrapperComponents: UIComponentRegistry = buildRegistryFromEntries( 'wrappers', - wrapperComponentMap, - sourceAliases.wrappers + wrapperComponentMap ) export const iconComponents: UIComponentRegistry = buildRegistryFromEntries(