+ "children": "## What is the Component Registry?\n\nThe component registry is a TypeScript object that maps component type names to their definitions. It tells UI Builder:\n\n- **How to render** the component in the editor\n- **What properties** it accepts and their types \n- **How to generate forms** for editing those properties\n- **Import paths** for code generation\n\n```tsx\nimport { ComponentRegistry } from '@/components/ui/ui-builder/types';\n\nconst myComponentRegistry: ComponentRegistry = {\n // Complex component with React component\n 'Button': {\n component: Button, // React component\n schema: z.object({...}), // Zod schema for props\n from: '@/components/ui/button' // Import path\n },\n // Primitive component (no React component needed)\n 'span': {\n schema: z.object({...}) // Just the schema\n }\n};\n```\n\n## Registry Structure\n\nEach registry entry can have these properties:\n\n### Required Properties\n- **`schema`**: Zod schema defining the component's props and their types\n- **`component`**: The React component (required for complex components)\n- **`from`**: Import path for code generation (required for complex components)\n\n### Optional Properties\n- **`isFromDefaultExport`**: Boolean, use default export in generated code\n- **`fieldOverrides`**: Object mapping prop names to custom form fields\n- **`defaultChildren`**: Array of ComponentLayer objects or string\n- **`defaultVariableBindings`**: Array of automatic variable bindings\n\n## Two Types of Components\n\n### Primitive Components\nHTML elements that don't need a React component:\n\n```tsx\nspan: {\n schema: z.object({\n className: z.string().optional(),\n children: z.any().optional(),\n })\n // No 'component' or 'from' needed\n}\n```\n\n### Complex Components\nCustom React components that need to be imported:\n\n```tsx\nButton: {\n component: Button,\n schema: z.object({\n className: z.string().optional(),\n children: z.any().optional(),\n variant: z.enum(['default', 'destructive']).default('default'),\n }),\n from: '@/components/ui/button'\n}\n```\n\n## Pre-built Component Definitions\n\nUI Builder includes example component definitions for testing and getting started:\n\n```tsx\nimport { primitiveComponentDefinitions } from '@/lib/ui-builder/registry/primitive-component-definitions';\nimport { complexComponentDefinitions } from '@/lib/ui-builder/registry/complex-component-definitions';\n\nconst componentRegistry: ComponentRegistry = {\n ...primitiveComponentDefinitions, // div, span, h1, h2, h3, p, ul, ol, li, img, iframe, a\n ...complexComponentDefinitions, // Button, Badge, Card, Icon, Flexbox, Grid, Markdown, etc.\n};\n```\n\n**Available Pre-built Components:**\n\n**Primitive Components:**\n- **Layout**: `div`, `span` \n- **Typography**: `h1`, `h2`, `h3`, `p`\n- **Lists**: `ul`, `ol`, `li`\n- **Media**: `img`, `iframe`\n- **Navigation**: `a` (links)\n\n**Complex Components:**\n- **Layout**: `Flexbox`, `Grid` \n- **Content**: `Markdown`, `CodePanel`\n- **UI Elements**: `Button`, `Badge`\n- **Advanced**: `Card`, `Icon`, `Accordion`\n\n## Simple Registry Example\n\nHere's a minimal registry with one custom component:\n\n```tsx\nimport { z } from 'zod';\nimport { Alert } from '@/components/ui/alert';\nimport { primitiveComponentDefinitions } from '@/lib/ui-builder/registry/primitive-component-definitions';\nimport { commonFieldOverrides } from '@/lib/ui-builder/registry/form-field-overrides';\n\nconst myComponentRegistry: ComponentRegistry = {\n // Include primitive components for basic HTML elements\n ...primitiveComponentDefinitions,\n \n // Add your custom component\n Alert: {\n component: Alert,\n schema: z.object({\n className: z.string().optional(),\n children: z.any().optional(),\n variant: z.enum(['default', 'destructive']).default('default'),\n }),\n from: '@/components/ui/alert',\n fieldOverrides: commonFieldOverrides()\n }\n};\n```\n\n## Component Dependencies\n\n**Important**: Make sure all component types referenced in your `defaultChildren` are included in your registry:\n\n```tsx\nconst componentRegistry: ComponentRegistry = {\n ...primitiveComponentDefinitions, // ← Includes 'span' needed below\n Button: {\n component: Button,\n schema: z.object({...}),\n from: '@/components/ui/button',\n // This Button references 'span' in defaultChildren\n defaultChildren: [{ \n id: 'btn-text',\n type: 'span', // ← Must be in registry\n name: 'Button Text',\n props: {},\n children: 'Click me'\n }]\n }\n};\n```\n\n## Schema Design Principles\n\nThe Zod schema is crucial as it drives the auto-generated form in the properties panel:\n\n```tsx\nschema: z.object({\n // Use .default() values for better UX\n title: z.string().default('Default Title'),\n \n // Use coerce for type conversion from strings\n count: z.coerce.number().default(1),\n \n // Boolean props become toggle switches\n disabled: z.boolean().optional(),\n \n // Enums become select dropdowns\n variant: z.enum(['default', 'destructive']).default('default'),\n \n // Special props need field overrides\n className: z.string().optional(),\n children: z.any().optional(),\n})\n```\n\n## Building Your Own Registry\n\n**For production applications**, you should create your own component registry with your specific components:\n\n```tsx\n// Your production registry\nconst productionRegistry: ComponentRegistry = {\n // Add only the components you need\n MyButton: { /* your button definition */ },\n MyCard: { /* your card definition */ },\n MyModal: { /* your modal definition */ },\n // Include primitives for basic HTML\n ...primitiveComponentDefinitions,\n};\n```\n\n**The pre-built registries are examples** to help you understand the system and test quickly, but you should replace them with your own component definitions that match your design system."
0 commit comments