{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form-builder",
  "title": "Formedible Form Builder",
  "description": "A visual drag-and-drop form builder component for creating forms with live preview and code generation. Includes field configurator, preview panel, and TypeScript code output.",
  "dependencies": [
    "react",
    "lucide-react",
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [
    "button",
    "input",
    "textarea",
    "select",
    "checkbox",
    "switch",
    "label",
    "card",
    "tabs",
    "accordion",
    "dialog",
    "popover",
    "progress",
    "radio-group",
    "slider",
    "badge",
    "alert",
    "skeleton"
  ],
  "files": [
    {
      "path": "src/components/formedible/builder/form-builder.tsx",
      "content": "\"use client\";\nimport React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Download, Upload } from \"lucide-react\";\nimport { BuilderProvider, useBuilderContext } from \"./BuilderContext\";\nimport { TabContainer } from \"./TabContainer\";\nimport { defaultTabs } from \"./default-tabs\";\nimport type { FormBuilderProps } from \"@/lib/formedible/builder-types\";\n\n// Internal FormBuilder component that uses context\nconst FormBuilderInternal: React.FC<{\n  tabs: FormBuilderProps[\"tabs\"];\n  defaultTab?: string;\n  onTabChange?: FormBuilderProps[\"onTabChange\"];\n  className?: string;\n}> = ({ \n  tabs = defaultTabs, \n  defaultTab = \"builder\",\n  onTabChange,\n  className\n}) => {\n  const { exportConfig, importConfig, submitConfig } = useBuilderContext();\n\n  return (\n    <div className=\"w-full min-h-[800px] flex flex-col bg-background\">\n      {/* Header */}\n      <div className=\"border-b bg-card\">\n        <div className=\"flex h-16 items-center px-6\">\n          <div className=\"flex items-center space-x-4\">\n            <h1 className=\"text-2xl font-bold\">Form Builder 2.0</h1>\n          </div>\n          <div className=\"ml-auto flex items-center space-x-4\">\n            <Button variant=\"secondary\" onClick={exportConfig}>\n              <Download className=\"h-4 w-4 mr-2\" />\n              Export\n            </Button>\n            <Button variant=\"secondary\" onClick={importConfig}>\n              <Upload className=\"h-4 w-4 mr-2\" />\n              Import\n            </Button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"flex-1 flex min-h-0\">\n        <div className=\"flex-1 flex flex-col\">\n          <TabContainer\n            tabs={tabs}\n            defaultTab={defaultTab}\n            onTabChange={onTabChange}\n            className={className}\n          />\n        </div>\n      </div>\n    </div>\n  );\n};\n\n// Main FormBuilder component with provider\nexport const FormBuilder: React.FC<FormBuilderProps> = ({\n  tabs = defaultTabs,\n  defaultTab = \"builder\",\n  enabledTabs,\n  onTabChange,\n  className,\n  initialData,\n  onSubmit,\n  isLoading,\n}) => {\n  // Filter tabs based on enabledTabs if provided\n  const finalTabs = enabledTabs \n    ? tabs.filter(tab => enabledTabs.includes(tab.id))\n    : tabs;\n\n  return (\n    <BuilderProvider \n      initialData={initialData}\n      onSubmit={onSubmit}\n      isLoading={isLoading}\n    >\n      <FormBuilderInternal\n        tabs={finalTabs}\n        defaultTab={defaultTab}\n        onTabChange={onTabChange}\n        className={className}\n      />\n    </BuilderProvider>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/form-builder.tsx"
    },
    {
      "path": "src/components/formedible/builder/field-configurator.tsx",
      "content": "\"use client\";\nimport React, { useRef } from \"react\";\nimport { useFormedible } from \"@/hooks/use-formedible\";\nimport { z } from \"zod\";\nimport { globalFieldStore, type FormField } from \"./field-store\";\n\n\n\ninterface FieldConfiguratorProps {\n  fieldId: string;\n  initialField: FormField;\n  availablePages?: number[];\n}\n\nexport const FieldConfigurator: React.FC<FieldConfiguratorProps> = ({\n  fieldId,\n  initialField,\n  availablePages = [1],\n}) => {\n  // Track the current field state without causing re-renders\n  const currentFieldRef = useRef<FormField>(initialField);\n  \n  // Update current field when props change\n  React.useEffect(() => {\n    currentFieldRef.current = initialField;\n  }, [fieldId, initialField]);\n  \n  // Use current field for configuration (this will update when field changes)\n  const currentField = currentFieldRef.current;\n  const needsOptions = ['select', 'radio', 'multiSelect'].includes(currentField.type);\n  const needsSliderConfig = currentField.type === 'slider';\n  const needsNumberConfig = currentField.type === 'number';\n  const needsDateConfig = currentField.type === 'date';\n  const needsFileConfig = currentField.type === 'file';\n  const needsTextareaConfig = currentField.type === 'textarea';\n  const needsPasswordConfig = currentField.type === 'password';\n  const needsEmailConfig = currentField.type === 'email';\n  const needsRatingConfig = currentField.type === 'rating';\n  const needsPhoneConfig = currentField.type === 'phone';\n  const needsColorConfig = currentField.type === 'colorPicker';\n  const needsMultiSelectConfig = currentField.type === 'multiSelect';\n\n  // SINGLE FORM WITH TABS CONFIGURATION - TanStack Form Best Practice Implementation\n  const configForm = useFormedible({\n    schema: z.object({\n      // Basic fields\n      label: z.string().min(1, \"Field label is required\"),\n      name: z.string().min(1, \"Field name is required\"),\n      placeholder: z.string().optional(),\n      description: z.string().optional(),\n      page: z.number().min(1),\n      group: z.string().optional(),\n      required: z.boolean().default(false),\n      \n      // Options\n      options: z.array(z.object({\n        value: z.string().min(1, \"Option value required\"),\n        label: z.string().min(1, \"Option label required\"),\n      })).optional(),\n      \n      // Field-specific configs\n      sliderConfig: z.object({\n        min: z.number().optional(),\n        max: z.number().optional(),\n        step: z.number().min(1).optional(),\n        showTooltip: z.boolean().default(false),\n        showValue: z.boolean().default(false),\n        orientation: z.enum([\"horizontal\", \"vertical\"]).default(\"horizontal\"),\n      }).optional(),\n      \n      numberConfig: z.object({\n        min: z.number().optional(),\n        max: z.number().optional(),\n        step: z.number().min(1).optional(),\n        precision: z.number().min(0).max(10).optional(),\n        allowNegative: z.boolean().default(true),\n        showSpinButtons: z.boolean().default(true),\n      }).optional(),\n      \n      dateConfig: z.object({\n        minDate: z.string().optional(),\n        maxDate: z.string().optional(),\n        format: z.enum([\"yyyy-MM-dd\", \"MM/dd/yyyy\", \"dd/MM/yyyy\", \"MMM dd, yyyy\"]).default(\"yyyy-MM-dd\"),\n        disablePast: z.boolean().default(false),\n        disableFuture: z.boolean().default(false),\n        disableWeekends: z.boolean().default(false),\n      }).optional(),\n      \n      multiSelectConfig: z.object({\n        placeholder: z.string().optional(),\n        searchable: z.boolean().default(false),\n        maxSelections: z.number().min(1).optional(),\n        creatable: z.boolean().default(false),\n      }).optional(),\n      \n      ratingConfig: z.object({\n        max: z.number().min(1).max(10).default(5),\n        allowHalf: z.boolean().default(false),\n        showValue: z.boolean().default(false),\n        icon: z.string().default(\"star\"),\n      }).optional(),\n      \n      phoneConfig: z.object({\n        defaultCountry: z.string().default(\"US\"),\n        format: z.enum([\"national\", \"international\"]).default(\"national\"),\n        placeholder: z.string().optional(),\n      }).optional(),\n      \n      colorConfig: z.object({\n        format: z.enum([\"hex\", \"rgb\", \"hsl\"]).default(\"hex\"),\n        presets: z.array(z.string()).optional(),\n      }).optional(),\n      \n      fileConfig: z.object({\n        accept: z.string().optional(),\n        multiple: z.boolean().default(false),\n        maxSize: z.number().min(1).optional(),\n        maxFiles: z.number().min(1).optional(),\n      }).optional(),\n      \n      textareaConfig: z.object({\n        rows: z.number().min(1).default(4),\n        cols: z.number().min(10).optional(),\n        resize: z.enum([\"none\", \"vertical\", \"horizontal\", \"both\"]).default(\"vertical\"),\n        maxLength: z.number().min(1).optional(),\n        showWordCount: z.boolean().default(false),\n      }).optional(),\n      \n      passwordConfig: z.object({\n        showToggle: z.boolean().default(true),\n        strengthMeter: z.boolean().default(false),\n        minStrength: z.number().min(1).max(4).default(1),\n        requireUppercase: z.boolean().default(false),\n        requireLowercase: z.boolean().default(false),\n        requireNumbers: z.boolean().default(false),\n        requireSymbols: z.boolean().default(false),\n        minLength: z.number().min(1).default(8),\n      }).optional(),\n      \n      emailConfig: z.object({\n        allowedDomains: z.string().optional(),\n        blockedDomains: z.string().optional(),\n        suggestions: z.string().optional(),\n        validateMX: z.boolean().default(false),\n      }).optional(),\n      \n      // Help and advanced\n      helpText: z.string().optional(),\n      helpTooltip: z.string().optional(),\n      helpPosition: z.enum([\"top\", \"bottom\", \"left\", \"right\"]).default(\"bottom\"),\n      helpLinkUrl: z.string().optional(),\n      helpLinkText: z.string().optional(),\n      \n      sectionTitle: z.string().optional(),\n      sectionDescription: z.string().optional(),\n      sectionCollapsible: z.boolean().default(false),\n      sectionDefaultExpanded: z.boolean().default(true),\n      \n      inlineValidationEnabled: z.boolean().default(false),\n      inlineValidationDebounceMs: z.number().min(0).default(300),\n      inlineValidationShowSuccess: z.boolean().default(false),\n      \n      validationMinLength: z.number().min(0).optional(),\n      validationMaxLength: z.number().min(1).optional(),\n      validationMin: z.number().optional(),\n      validationMax: z.number().optional(),\n      validationPattern: z.string().optional(),\n      validationIncludes: z.string().optional(),\n      validationStartsWith: z.string().optional(),\n      validationEndsWith: z.string().optional(),\n      validationEmail: z.boolean().default(false),\n      validationUrl: z.boolean().default(false),\n      validationUuid: z.boolean().default(false),\n      validationCustom: z.string().optional(),\n    }),\n    \n    fields: [\n      // BASIC TAB\n      { name: \"label\", type: \"text\", label: \"Field Label\", placeholder: \"Enter field label\", tab: \"basic\" },\n      { name: \"name\", type: \"text\", label: \"Field Name\", placeholder: \"Enter field name\", tab: \"basic\" },\n      { name: \"placeholder\", type: \"text\", label: \"Placeholder\", placeholder: \"Enter placeholder text\", tab: \"basic\" },\n      { name: \"description\", type: \"textarea\", label: \"Description\", placeholder: \"Enter field description\", tab: \"basic\" },\n      { \n        name: \"page\", \n        type: \"select\", \n        label: \"Page\",\n        options: availablePages.map(page => ({ value: page.toString(), label: `Page ${page}` })),\n        tab: \"basic\"\n      },\n      { name: \"group\", type: \"text\", label: \"Group (Optional)\", placeholder: \"Group name for organizing fields\", tab: \"basic\" },\n      { name: \"required\", type: \"checkbox\", label: \"Required field\", tab: \"basic\" },\n      \n      // OPTIONS TAB - only show if needed\n      ...(needsOptions ? [\n        { name: \"options\", type: \"array\", label: \"Field Options\", tab: \"options\" },\n      ] : []),\n      \n      // FIELD CONFIG TAB - show different configs based on field type\n      ...(needsSliderConfig ? [\n        { name: \"sliderConfig.min\", type: \"number\", label: \"Minimum Value\", tab: \"config\" },\n        { name: \"sliderConfig.max\", type: \"number\", label: \"Maximum Value\", tab: \"config\" },\n        { name: \"sliderConfig.step\", type: \"number\", label: \"Step\", tab: \"config\" },\n        { name: \"sliderConfig.orientation\", type: \"radio\", label: \"Orientation\", options: [\n          { value: \"horizontal\", label: \"Horizontal\" },\n          { value: \"vertical\", label: \"Vertical\" }\n        ], tab: \"config\" },\n        { name: \"sliderConfig.showTooltip\", type: \"switch\", label: \"Show tooltip\", tab: \"config\" },\n        { name: \"sliderConfig.showValue\", type: \"switch\", label: \"Show current value\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsNumberConfig ? [\n        { name: \"numberConfig.min\", type: \"number\", label: \"Minimum Value\", tab: \"config\" },\n        { name: \"numberConfig.max\", type: \"number\", label: \"Maximum Value\", tab: \"config\" },\n        { name: \"numberConfig.step\", type: \"number\", label: \"Step\", tab: \"config\" },\n        { name: \"numberConfig.precision\", type: \"number\", label: \"Precision (Decimal Places)\", tab: \"config\" },\n        { name: \"numberConfig.allowNegative\", type: \"switch\", label: \"Allow negative numbers\", tab: \"config\" },\n        { name: \"numberConfig.showSpinButtons\", type: \"switch\", label: \"Show spin buttons\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsDateConfig ? [\n        { name: \"dateConfig.minDate\", type: \"date\", label: \"Minimum Date\", tab: \"config\" },\n        { name: \"dateConfig.maxDate\", type: \"date\", label: \"Maximum Date\", tab: \"config\" },\n        { name: \"dateConfig.format\", type: \"select\", label: \"Date Format\", options: [\n          { value: \"yyyy-MM-dd\", label: \"YYYY-MM-DD\" },\n          { value: \"MM/dd/yyyy\", label: \"MM/DD/YYYY\" },\n          { value: \"dd/MM/yyyy\", label: \"DD/MM/YYYY\" },\n          { value: \"MMM dd, yyyy\", label: \"MMM DD, YYYY\" }\n        ], tab: \"config\" },\n        { name: \"dateConfig.disablePast\", type: \"switch\", label: \"Disable past dates\", tab: \"config\" },\n        { name: \"dateConfig.disableFuture\", type: \"switch\", label: \"Disable future dates\", tab: \"config\" },\n        { name: \"dateConfig.disableWeekends\", type: \"switch\", label: \"Disable weekends\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsMultiSelectConfig ? [\n        { name: \"multiSelectConfig.placeholder\", type: \"text\", label: \"Placeholder\", placeholder: \"Select options...\", tab: \"config\" },\n        { name: \"multiSelectConfig.maxSelections\", type: \"number\", label: \"Max Selections\", tab: \"config\" },\n        { name: \"multiSelectConfig.searchable\", type: \"switch\", label: \"Enable search\", tab: \"config\" },\n        { name: \"multiSelectConfig.creatable\", type: \"switch\", label: \"Allow creating new options\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsRatingConfig ? [\n        { name: \"ratingConfig.max\", type: \"number\", label: \"Maximum Rating\", tab: \"config\" },\n        { name: \"ratingConfig.allowHalf\", type: \"switch\", label: \"Allow half ratings\", tab: \"config\" },\n        { name: \"ratingConfig.showValue\", type: \"switch\", label: \"Show rating value\", tab: \"config\" },\n        { name: \"ratingConfig.icon\", type: \"select\", label: \"Icon Style\", options: [\n          { value: \"star\", label: \"⭐ Star\" },\n          { value: \"heart\", label: \"❤️ Heart\" },\n          { value: \"thumb\", label: \"👍 Thumb\" },\n          { value: \"circle\", label: \"⚫ Circle\" }\n        ], tab: \"config\" },\n      ] : []),\n      \n      ...(needsPhoneConfig ? [\n        { name: \"phoneConfig.defaultCountry\", type: \"text\", label: \"Default Country Code\", placeholder: \"US\", tab: \"config\" },\n        { name: \"phoneConfig.format\", type: \"radio\", label: \"Phone Format\", options: [\n          { value: \"national\", label: \"National (123) 456-7890\" },\n          { value: \"international\", label: \"International +1 123 456 7890\" }\n        ], tab: \"config\" },\n        { name: \"phoneConfig.placeholder\", type: \"text\", label: \"Placeholder\", placeholder: \"Enter phone number\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsColorConfig ? [\n        { name: \"colorConfig.format\", type: \"select\", label: \"Color Format\", options: [\n          { value: \"hex\", label: \"HEX (#ffffff)\" },\n          { value: \"rgb\", label: \"RGB (255, 255, 255)\" },\n          { value: \"hsl\", label: \"HSL (0, 0%, 100%)\" }\n        ], tab: \"config\" },\n        { name: \"colorConfig.presets\", type: \"array\", label: \"Color Presets\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsFileConfig ? [\n        { name: \"fileConfig.accept\", type: \"text\", label: \"Accepted File Types\", placeholder: \".pdf,.doc,.docx,image/*\", tab: \"config\" },\n        { name: \"fileConfig.multiple\", type: \"switch\", label: \"Allow multiple files\", tab: \"config\" },\n        { name: \"fileConfig.maxSize\", type: \"number\", label: \"Max File Size (MB)\", tab: \"config\" },\n        { name: \"fileConfig.maxFiles\", type: \"number\", label: \"Max Number of Files\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsTextareaConfig ? [\n        { name: \"textareaConfig.rows\", type: \"number\", label: \"Rows\", tab: \"config\" },\n        { name: \"textareaConfig.cols\", type: \"number\", label: \"Columns\", tab: \"config\" },\n        { name: \"textareaConfig.resize\", type: \"select\", label: \"Resize Behavior\", options: [\n          { value: \"none\", label: \"No resize\" },\n          { value: \"vertical\", label: \"Vertical only\" },\n          { value: \"horizontal\", label: \"Horizontal only\" },\n          { value: \"both\", label: \"Both directions\" }\n        ], tab: \"config\" },\n        { name: \"textareaConfig.maxLength\", type: \"number\", label: \"Maximum Length\", tab: \"config\" },\n        { name: \"textareaConfig.showWordCount\", type: \"switch\", label: \"Show word count\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsPasswordConfig ? [\n        { name: \"passwordConfig.showToggle\", type: \"switch\", label: \"Show/hide toggle button\", tab: \"config\" },\n        { name: \"passwordConfig.strengthMeter\", type: \"switch\", label: \"Show strength meter\", tab: \"config\" },\n        { name: \"passwordConfig.minStrength\", type: \"number\", label: \"Minimum Strength (1-4)\", tab: \"config\" },\n        { name: \"passwordConfig.minLength\", type: \"number\", label: \"Minimum Length\", tab: \"config\" },\n        { name: \"passwordConfig.requireUppercase\", type: \"switch\", label: \"Require uppercase letters\", tab: \"config\" },\n        { name: \"passwordConfig.requireLowercase\", type: \"switch\", label: \"Require lowercase letters\", tab: \"config\" },\n        { name: \"passwordConfig.requireNumbers\", type: \"switch\", label: \"Require numbers\", tab: \"config\" },\n        { name: \"passwordConfig.requireSymbols\", type: \"switch\", label: \"Require symbols\", tab: \"config\" },\n      ] : []),\n      \n      ...(needsEmailConfig ? [\n        { name: \"emailConfig.allowedDomains\", type: \"text\", label: \"Allowed Domains (comma-separated)\", placeholder: \"gmail.com, company.com\", tab: \"config\" },\n        { name: \"emailConfig.blockedDomains\", type: \"text\", label: \"Blocked Domains (comma-separated)\", placeholder: \"tempmail.com, throwaway.email\", tab: \"config\" },\n        { name: \"emailConfig.suggestions\", type: \"text\", label: \"Domain Suggestions (comma-separated)\", placeholder: \"gmail.com, yahoo.com, outlook.com\", tab: \"config\" },\n        { name: \"emailConfig.validateMX\", type: \"switch\", label: \"Validate MX records\", tab: \"config\" },\n      ] : []),\n      \n      // HELP TAB\n      { name: \"helpText\", type: \"textarea\", label: \"Help Text\", placeholder: \"Additional help text for users\", tab: \"help\" },\n      { name: \"helpTooltip\", type: \"text\", label: \"Tooltip\", placeholder: \"Short tooltip text\", tab: \"help\" },\n      { name: \"helpPosition\", type: \"select\", label: \"Help Position\", options: [\n        { value: \"top\", label: \"Top\" },\n        { value: \"bottom\", label: \"Bottom\" },\n        { value: \"left\", label: \"Left\" },\n        { value: \"right\", label: \"Right\" }\n      ], tab: \"help\" },\n      { name: \"helpLinkUrl\", type: \"text\", label: \"Help Link URL\", placeholder: \"https://example.com/help\", tab: \"help\" },\n      { name: \"helpLinkText\", type: \"text\", label: \"Help Link Text\", placeholder: \"Learn more\", tab: \"help\" },\n      \n      // SECTION TAB\n      { name: \"sectionTitle\", type: \"text\", label: \"Section Title\", placeholder: \"Section title\", tab: \"section\" },\n      { name: \"sectionDescription\", type: \"textarea\", label: \"Section Description\", placeholder: \"Section description\", tab: \"section\" },\n      { name: \"sectionCollapsible\", type: \"switch\", label: \"Collapsible section\", tab: \"section\" },\n      { name: \"sectionDefaultExpanded\", type: \"switch\", label: \"Expanded by default\", tab: \"section\" },\n      \n      // VALIDATION TAB\n      { name: \"inlineValidationEnabled\", type: \"switch\", label: \"Enable inline validation\", tab: \"validation\" },\n      { name: \"inlineValidationDebounceMs\", type: \"number\", label: \"Debounce (ms)\", tab: \"validation\" },\n      { name: \"inlineValidationShowSuccess\", type: \"switch\", label: \"Show success indicator\", tab: \"validation\" },\n      \n      { name: \"validationMinLength\", type: \"number\", label: \"Minimum Length\", tab: \"validation\" },\n      { name: \"validationMaxLength\", type: \"number\", label: \"Maximum Length\", tab: \"validation\" },\n      { name: \"validationMin\", type: \"number\", label: \"Minimum Value\", tab: \"validation\" },\n      { name: \"validationMax\", type: \"number\", label: \"Maximum Value\", tab: \"validation\" },\n      { name: \"validationPattern\", type: \"text\", label: \"Pattern (Regex)\", placeholder: \"e.g., ^[A-Za-z]+$\", tab: \"validation\" },\n      { name: \"validationIncludes\", type: \"text\", label: \"Must Include\", tab: \"validation\" },\n      { name: \"validationStartsWith\", type: \"text\", label: \"Must Start With\", tab: \"validation\" },\n      { name: \"validationEndsWith\", type: \"text\", label: \"Must End With\", tab: \"validation\" },\n      { name: \"validationEmail\", type: \"switch\", label: \"Validate email format\", tab: \"validation\" },\n      { name: \"validationUrl\", type: \"switch\", label: \"URL format\", tab: \"validation\" },\n      { name: \"validationUuid\", type: \"switch\", label: \"UUID format\", tab: \"validation\" },\n      { name: \"validationCustom\", type: \"textarea\", label: \"Custom Validation Message\", tab: \"validation\" },\n    ],\n    \n    // TABS CONFIGURATION\n    tabs: [\n      { id: \"basic\", label: \"Basic\" },\n      ...(needsOptions ? [{ id: \"options\", label: \"Options\" }] : []),\n      ...(needsSliderConfig || needsNumberConfig || needsDateConfig || needsMultiSelectConfig || needsRatingConfig || needsPhoneConfig || needsColorConfig || needsFileConfig || needsTextareaConfig || needsPasswordConfig || needsEmailConfig ? [{ id: \"config\", label: \"Config\" }] : []),\n      { id: \"help\", label: \"Help\" },\n      { id: \"section\", label: \"Section\" },\n      { id: \"validation\", label: \"Validation\" },\n    ],\n    \n    formOptions: {\n      defaultValues: {\n        label: initialField.label || \"\",\n        name: initialField.name || \"\",\n        placeholder: initialField.placeholder || \"\",\n        description: initialField.description || \"\",\n        page: initialField.page || 1,\n        group: initialField.group || \"\",\n        required: initialField.required || false,\n        options: initialField.options || [],\n        sliderConfig: initialField.sliderConfig || {},\n        numberConfig: initialField.numberConfig || {},\n        dateConfig: {\n          ...initialField.dateConfig,\n          format: (initialField.dateConfig?.format as \"yyyy-MM-dd\" | \"MM/dd/yyyy\" | \"dd/MM/yyyy\" | \"MMM dd, yyyy\") || \"yyyy-MM-dd\"\n        },\n        multiSelectConfig: initialField.multiSelectConfig || {},\n        ratingConfig: initialField.ratingConfig || {},\n        phoneConfig: initialField.phoneConfig || {},\n        colorConfig: initialField.colorConfig || {},\n        fileConfig: initialField.fileConfig || {},\n        textareaConfig: initialField.textareaConfig || {},\n        passwordConfig: initialField.passwordConfig || {},\n        emailConfig: {\n          allowedDomains: Array.isArray(initialField.emailConfig?.allowedDomains) \n            ? initialField.emailConfig.allowedDomains.join(', ') \n            : (initialField.emailConfig?.allowedDomains || \"\"),\n          blockedDomains: Array.isArray(initialField.emailConfig?.blockedDomains) \n            ? initialField.emailConfig.blockedDomains.join(', ') \n            : (initialField.emailConfig?.blockedDomains || \"\"),\n          suggestions: Array.isArray(initialField.emailConfig?.suggestions) \n            ? initialField.emailConfig.suggestions.join(', ') \n            : (initialField.emailConfig?.suggestions || \"\"),\n          validateMX: initialField.emailConfig?.validateMX || false,\n        },\n        helpText: initialField.help?.text || \"\",\n        helpTooltip: initialField.help?.tooltip || \"\",\n        helpPosition: initialField.help?.position || \"bottom\",\n        helpLinkUrl: initialField.help?.link?.url || \"\",\n        helpLinkText: initialField.help?.link?.text || \"\",\n        sectionTitle: initialField.section?.title || \"\",\n        sectionDescription: initialField.section?.description || \"\",\n        sectionCollapsible: initialField.section?.collapsible || false,\n        sectionDefaultExpanded: initialField.section?.defaultExpanded !== false,\n        inlineValidationEnabled: initialField.inlineValidation?.enabled || false,\n        inlineValidationDebounceMs: initialField.inlineValidation?.debounceMs || 300,\n        inlineValidationShowSuccess: initialField.inlineValidation?.showSuccess || false,\n        validationMinLength: initialField.validationConfig?.minLength,\n        validationMaxLength: initialField.validationConfig?.maxLength,\n        validationMin: initialField.validationConfig?.min,\n        validationMax: initialField.validationConfig?.max,\n        validationPattern: initialField.validationConfig?.pattern || \"\",\n        validationIncludes: initialField.validationConfig?.includes || \"\",\n        validationStartsWith: initialField.validationConfig?.startsWith || \"\",\n        validationEndsWith: initialField.validationConfig?.endsWith || \"\",\n        validationEmail: initialField.validationConfig?.email || false,\n        validationUrl: initialField.validationConfig?.url || false,\n        validationUuid: initialField.validationConfig?.uuid || false,\n        validationCustom: initialField.validationConfig?.custom || \"\",\n      },\n      \n      // DIRECT STORE UPDATE - NO PARENT RE-RENDERS!\n      onChange: ({ value }: { value: any }) => {\n        // console.log('=== FIELD CONFIGURATOR CHANGE ===');\n        // console.log('Field ID:', fieldId);\n        // console.log('Current field page:', currentFieldRef.current.page);\n        // console.log('Form value page:', value.page);\n        \n        // Preserve original page if form value is empty/undefined\n        const finalPage = value.page || currentFieldRef.current.page || 1;\n        // console.log('Will update to page:', finalPage);\n        \n        const updatedField: FormField = {\n          ...currentFieldRef.current,\n          label: value.label,\n          name: value.name,\n          placeholder: value.placeholder,\n          description: value.description,\n          page: finalPage,\n          group: value.group,\n          required: value.required,\n          options: value.options,\n          sliderConfig: value.sliderConfig,\n          numberConfig: value.numberConfig,\n          dateConfig: value.dateConfig,\n          multiSelectConfig: value.multiSelectConfig,\n          ratingConfig: value.ratingConfig,\n          phoneConfig: value.phoneConfig,\n          colorConfig: value.colorConfig,\n          fileConfig: value.fileConfig,\n          textareaConfig: value.textareaConfig,\n          passwordConfig: value.passwordConfig,\n          emailConfig: value.emailConfig ? {\n            allowedDomains: value.emailConfig.allowedDomains ? value.emailConfig.allowedDomains.split(',').map((d: string) => d.trim()).filter(Boolean) : undefined,\n            blockedDomains: value.emailConfig.blockedDomains ? value.emailConfig.blockedDomains.split(',').map((d: string) => d.trim()).filter(Boolean) : undefined,\n            suggestions: value.emailConfig.suggestions ? value.emailConfig.suggestions.split(',').map((d: string) => d.trim()).filter(Boolean) : undefined,\n            validateMX: value.emailConfig.validateMX,\n          } : undefined,\n          help: (value.helpText || value.helpTooltip || value.helpLinkUrl) ? {\n            text: value.helpText,\n            tooltip: value.helpTooltip,\n            position: value.helpPosition,\n            ...(value.helpLinkUrl && value.helpLinkText && { \n              link: { url: value.helpLinkUrl, text: value.helpLinkText } \n            })\n          } : undefined,\n          section: value.sectionTitle ? {\n            title: value.sectionTitle,\n            description: value.sectionDescription,\n            collapsible: value.sectionCollapsible,\n            defaultExpanded: value.sectionDefaultExpanded,\n          } : undefined,\n          inlineValidation: value.inlineValidationEnabled ? {\n            enabled: value.inlineValidationEnabled,\n            debounceMs: value.inlineValidationDebounceMs,\n            showSuccess: value.inlineValidationShowSuccess,\n          } : undefined,\n          validationConfig: (value.validationMinLength || value.validationMaxLength || value.validationMin || value.validationMax || value.validationPattern || value.validationIncludes || value.validationStartsWith || value.validationEndsWith || value.validationEmail || value.validationUrl || value.validationUuid || value.validationCustom) ? {\n            minLength: value.validationMinLength,\n            maxLength: value.validationMaxLength,\n            min: value.validationMin,\n            max: value.validationMax,\n            pattern: value.validationPattern,\n            includes: value.validationIncludes,\n            startsWith: value.validationStartsWith,\n            endsWith: value.validationEndsWith,\n            email: value.validationEmail,\n            url: value.validationUrl,\n            uuid: value.validationUuid,\n            custom: value.validationCustom,\n          } : undefined,\n        };\n        \n        // UPDATE FIELD STORE AND NOTIFY SUBSCRIBERS\n        currentFieldRef.current = updatedField;\n        globalFieldStore.updateField(fieldId, updatedField);\n        \n        // Notify field update subscribers immediately\n        globalFieldStore.notifyFieldUpdate(fieldId, updatedField);\n      },\n    },\n    \n    // NO SUBMIT BUTTON!\n    showSubmitButton: false,\n  });\n\n  // Reset form values when field changes\n  React.useEffect(() => {\n    configForm.form.reset();\n  }, [fieldId, configForm.form]);\n\n  return (\n    <div className=\"space-y-6 p-6\">\n      <div className=\"border-b pb-4\">\n        <h3 className=\"font-semibold text-lg\">Configure Field</h3>\n        <p className=\"text-sm text-muted-foreground\">\n          Configure the properties for this {initialField.type} field\n        </p>\n      </div>\n\n      {/* SINGLE FORMEDIBLE FORM WITH TABS - NO RE-RENDERS! */}\n      <configForm.Form />\n    </div>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/field-configurator.tsx"
    },
    {
      "path": "src/components/formedible/builder/form-preview.tsx",
      "content": "\"use client\";\n\nimport React, { useMemo } from 'react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { useFormedible } from '@/hooks/use-formedible';\nimport { cn } from '@/lib/utils';\nimport type { UseFormedibleOptions } from '@/lib/formedible/parser-types';\n\ninterface FormPreviewProps {\n  config: UseFormedibleOptions<Record<string, unknown>>;\n  className?: string;\n}\n\nexport const FormPreview: React.FC<FormPreviewProps> = ({\n  config,\n  className,\n}) => {\n  const fields = config.fields || [];\n\n  // Use the parsed config directly - no stupid rebuilding!\n  const formedibleConfig = useMemo(() => {\n    if (!config.fields || config.fields.length === 0) {\n      return {\n        fields: [],\n        formOptions: {\n          onSubmit: async () => {\n            alert('No fields to submit');\n          }\n        }\n      };\n    }\n\n    return {\n      ...config,  // Use the parsed config directly!\n      formOptions: {\n        onSubmit: async ({ value }: { value: Record<string, unknown> }) => {\n          console.log('Preview form submitted:', value);\n          \n          // Format the form data for display\n          const formatValue = (val: unknown): string => {\n            if (val === null || val === undefined) return 'null';\n            if (typeof val === 'boolean') return val.toString();\n            if (typeof val === 'number') return val.toString();\n            if (typeof val === 'string') return val;\n            if (Array.isArray(val)) {\n              return val.map(item => \n                typeof item === 'object' ? JSON.stringify(item) : String(item)\n              ).join(', ');\n            }\n            if (typeof val === 'object') {\n              return JSON.stringify(val, null, 2);\n            }\n            return String(val);\n          };\n\n          const formattedData = Object.entries(value).map(([key, val]) => \n            `${key}: ${formatValue(val)}`\n          ).join('\\n');\n          \n          alert(`Form submitted successfully!\\n\\n${formattedData}`);\n        }\n      }\n    };\n  }, [config]);\n\n  const formResult = useFormedible(formedibleConfig);\n\n  // Handle no form result or empty fields\n  if (!formResult || !formResult.Form || fields.length === 0) {\n    if (fields.length === 0) {\n      return (\n        <Card className={cn(\"bg-muted/30\", className)}>\n          <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n            <div className=\"text-4xl mb-4\">📝</div>\n            <h3 className=\"text-lg font-medium mb-2\">No Fields Added</h3>\n            <p className=\"text-muted-foreground\">\n              Add some fields from the sidebar to see your form preview\n            </p>\n          </CardContent>\n        </Card>\n      );\n    }\n    return (\n      <Card className={cn(\"bg-muted/30\", className)}>\n        <CardContent className=\"py-3\">\n          <div className=\"text-center text-muted-foreground\">\n            There was an error generating the form preview.\n          </div>\n        </CardContent>\n      </Card>\n    );\n  }\n\n  const { Form } = formResult;\n\n  return (\n    <Card className={cn(\"bg-muted/30\", className)}>\n      <CardHeader className=\"pb-2\">\n        <CardTitle className=\"flex items-center justify-between\">\n          <div>\n            <div>{config.title || 'Untitled Form'}</div>\n            {config.description && (\n              <div className=\"text-sm font-normal text-muted-foreground mt-1\">\n                {config.description}\n              </div>\n            )}\n          </div>\n          <div className=\"text-sm text-muted-foreground\">\n            {fields.length} field{fields.length !== 1 ? 's' : ''}\n            {(config.pages && config.pages.length > 1) && ` • ${config.pages.length} pages`}\n            {(config.tabs && config.tabs.length > 1) && ` • ${config.tabs.length} tabs`}\n          </div>\n        </CardTitle>\n      </CardHeader>\n      <CardContent className=\"pt-0\">\n        <div className=\"border-2 border-dashed border-muted-foreground/20 rounded-lg p-4 bg-background\">\n          <div className=\"text-xs text-muted-foreground mb-1 text-center\">\n            ✨ Live Preview - This form is fully functional!\n          </div>\n          <Form />\n        </div>\n      </CardContent>\n    </Card>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/form-preview.tsx"
    },
    {
      "path": "src/components/formedible/builder/code-generator.tsx",
      "content": "\"use client\";\nimport React, { useMemo } from \"react\";\nimport { CodeBlock } from \"@/components/ui/code-block\";\nimport type { FieldConfig } from \"@/lib/formedible/types\";\nimport { generateFormCode } from \"@/lib/formedible/code-generation\";\n\ninterface FormField extends FieldConfig {\n  id: string;\n  label: string; // Make label required for builder\n  help?: {\n    text?: string;\n    tooltip?: string;\n    position?: \"top\" | \"bottom\" | \"left\" | \"right\";\n    link?: { url: string; text: string };\n  };\n  inlineValidation?: {\n    enabled?: boolean;\n    debounceMs?: number;\n    showSuccess?: boolean;\n  };\n  options?: string[] | Array<{ value: string; label: string }> | ((values: Record<string, unknown>) => string[] | Array<{ value: string; label: string }>);\n  arrayConfig?: any;\n  datalist?: any;\n  multiSelectConfig?: any;\n  colorConfig?: any;\n  ratingConfig?: any;\n  phoneConfig?: any;\n}\n\ninterface CodeGeneratorProps {\n  formTitle: string;\n  formDescription: string;\n  fields: FormField[];\n  pages: Array<{ page: number; title: string; description?: string }>;\n  settings: {\n    submitLabel: string;\n    nextLabel: string;\n    previousLabel: string;\n    showProgress: boolean;\n  };\n}\n\nexport const CodeGenerator: React.FC<CodeGeneratorProps> = ({\n  formTitle,\n  formDescription,\n  fields,\n  pages,\n  settings,\n}) => {\n  const generatedCode = useMemo(() => {\n    const result = generateFormCode({\n      title: formTitle,\n      description: formDescription,\n      fields,\n      pages,\n      settings,\n    });\n    \n    return result.fullCode;\n  }, [formTitle, formDescription, fields, pages, settings]);\n\n  return (\n    <div className=\"space-y-6\">\n      <div>\n        <h2 className=\"text-2xl font-bold mb-2\">Generated Code</h2>\n        <p className=\"text-muted-foreground text-lg mb-6\">\n          Copy this code to use your form in your application\n        </p>\n      </div>\n      \n      {fields.length === 0 ? (\n        <div className=\"flex items-center justify-center h-64 border-2 border-dashed border-muted-foreground/25 rounded-lg\">\n          <div className=\"text-center\">\n            <h3 className=\"text-lg font-medium text-foreground mb-2\">No Fields Added</h3>\n            <p className=\"text-muted-foreground\">Add some fields to generate code</p>\n          </div>\n        </div>\n      ) : (\n        <CodeBlock\n          code={generatedCode}\n          language=\"tsx\"\n          title=\"MyForm.tsx\"\n          showCopyButton={true}\n          showLineNumbers={true}\n        />\n      )}\n    </div>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/code-generator.tsx"
    },
    {
      "path": "src/components/formedible/builder/field-store.ts",
      "content": "import type { FormField } from \"@/lib/formedible/builder-types\";\n\nconst FIELD_TYPES = [\n  { value: \"text\", label: \"Text Input\", icon: \"📝\" },\n  { value: \"email\", label: \"Email\", icon: \"📧\" },\n  { value: \"password\", label: \"Password\", icon: \"🔒\" },\n  { value: \"textarea\", label: \"Textarea\", icon: \"📄\" },\n  { value: \"number\", label: \"Number\", icon: \"🔢\" },\n  { value: \"select\", label: \"Select\", icon: \"📋\" },\n  { value: \"radio\", label: \"Radio Group\", icon: \"⚪\" },\n  { value: \"multiSelect\", label: \"Multi-Select\", icon: \"☑️\" },\n  { value: \"checkbox\", label: \"Checkbox\", icon: \"✅\" },\n  { value: \"switch\", label: \"Switch\", icon: \"🔘\" },\n  { value: \"date\", label: \"Date Picker\", icon: \"📅\" },\n  { value: \"slider\", label: \"Slider\", icon: \"🎚️\" },\n  { value: \"rating\", label: \"Rating\", icon: \"⭐\" },\n  { value: \"colorPicker\", label: \"Color Picker\", icon: \"🎨\" },\n  { value: \"phone\", label: \"Phone Number\", icon: \"📞\" },\n  { value: \"file\", label: \"File Upload\", icon: \"📎\" },\n  { value: \"array\", label: \"Array Field\", icon: \"📚\" },\n];\n\n// ISOLATED FIELD STORE - SEPARATE NOTIFICATIONS FOR STRUCTURE VS FIELD UPDATES\nclass FieldStore {\n  private fields: Record<string, FormField> = {};\n  private fieldOrder: string[] = [];\n  private structureListeners: Set<() => void> = new Set(); // For add/delete/reorder\n  private fieldUpdateCallbacks: Map<string, Set<(field: FormField) => void>> = new Map(); // Field-specific subscribers\n\n  addField(type: string, selectedPage?: number): string {\n    const id = `field_${Date.now()}`;\n    const newField: FormField = {\n      id,\n      name: `field_${Object.keys(this.fields).length + 1}`,\n      type,\n      label: `${FIELD_TYPES.find((t) => t.value === type)?.label || type} Field`,\n      required: false,\n      page: selectedPage || 1,\n    };\n    \n    this.fields[id] = newField;\n    this.fieldOrder.push(id);\n    this.notifyStructureListeners(); // Structure change\n    return id;\n  }\n\n  updateField(fieldId: string, updatedField: FormField): void {\n    this.fields[fieldId] = updatedField;\n    // DO NOT notify structure listeners - field updates should not cause parent re-renders!\n  }\n\n  // Notify specific field subscribers\n  notifyFieldUpdate(fieldId: string, field: FormField): void {\n    const subscribers = this.fieldUpdateCallbacks.get(fieldId);\n    if (subscribers) {\n      subscribers.forEach(callback => callback(field));\n    }\n  }\n\n  deleteField(fieldId: string): void {\n    delete this.fields[fieldId];\n    this.fieldOrder = this.fieldOrder.filter(id => id !== fieldId);\n    this.notifyStructureListeners(); // Structure change\n  }\n\n  duplicateField(fieldId: string): string | null {\n    const field = this.fields[fieldId];\n    if (field) {\n      const id = `field_${Date.now()}`;\n      const newField: FormField = {\n        ...field,\n        id,\n        name: `${field.name}_copy`,\n        label: `${field.label} (Copy)`,\n      };\n      this.fields[id] = newField;\n      this.fieldOrder.push(id);\n      this.notifyStructureListeners(); // Structure change\n      return id;\n    }\n    return null;\n  }\n\n  getField(fieldId: string): FormField | undefined {\n    return this.fields[fieldId];\n  }\n  \n  getAllFields(): FormField[] {\n    return this.fieldOrder.map(id => this.fields[id]).filter(Boolean);\n  }\n\n  getFieldsByPage(page: number): FormField[] {\n    return this.fieldOrder.map(id => this.fields[id]).filter(field => field && (field.page || 1) === page);\n  }\n\n  getFieldsByTab(tabId: string): FormField[] {\n    return this.fieldOrder.map(id => this.fields[id]).filter(field => field && field.tab === tabId);\n  }\n\n  // Subscribe to structure changes only (add/delete/reorder)\n  subscribe(listener: () => void): () => void {\n    this.structureListeners.add(listener);\n    return () => this.structureListeners.delete(listener);\n  }\n\n  // Subscribe to specific field updates\n  subscribeToFieldUpdates(fieldId: string, callback: (field: FormField) => void): () => void {\n    if (!this.fieldUpdateCallbacks.has(fieldId)) {\n      this.fieldUpdateCallbacks.set(fieldId, new Set());\n    }\n    this.fieldUpdateCallbacks.get(fieldId)!.add(callback);\n    \n    return () => {\n      const subscribers = this.fieldUpdateCallbacks.get(fieldId);\n      if (subscribers) {\n        subscribers.delete(callback);\n        if (subscribers.size === 0) {\n          this.fieldUpdateCallbacks.delete(fieldId);\n        }\n      }\n    };\n  }\n\n  private notifyStructureListeners(): void {\n    this.structureListeners.forEach(listener => listener());\n  }\n\n  // Import/Export methods\n  clear(): void {\n    this.fields = {};\n    this.fieldOrder = [];\n    this.notifyStructureListeners();\n  }\n\n  importFields(fields: any[]): void {\n    this.clear();\n    fields.forEach((field: any) => {\n      const newFieldId = this.addField(field.type, field.page || 1);\n      const newField: FormField = {\n        id: newFieldId,\n        name: field.name,\n        type: field.type,\n        label: field.label,\n        placeholder: field.placeholder,\n        description: field.description,\n        required: field.required || false,\n        page: field.page || 1,\n        group: field.group,\n        section: field.section,\n        help: field.help,\n        inlineValidation: field.inlineValidation,\n        options: field.options,\n        arrayConfig: field.arrayConfig,\n        datalist: field.datalist,\n        multiSelectConfig: field.multiSelectConfig,\n        colorConfig: field.colorConfig,\n        ratingConfig: field.ratingConfig,\n        phoneConfig: field.phoneConfig,\n        sliderConfig: field.sliderConfig,\n        numberConfig: field.numberConfig,\n        dateConfig: field.dateConfig,\n        fileConfig: field.fileConfig,\n        textareaConfig: field.textareaConfig,\n        passwordConfig: field.passwordConfig,\n        emailConfig: field.emailConfig,\n        validation: field.validation,\n      };\n      this.updateField(newFieldId, newField);\n    });\n  }\n}\n\n// Global field store instance\nexport const globalFieldStore = new FieldStore();\nexport type { FormField };",
      "type": "registry:lib",
      "target": "components/formedible/builder/field-store.ts"
    },
    {
      "path": "src/lib/formedible/builder-types.ts",
      "content": "import React from \"react\";\nimport { z } from \"zod\";\nimport type { FieldConfig, DynamicText, ObjectConfig, FieldHelpConfig, InlineValidationConfig, SectionConfig } from \"@/lib/formedible/types\";\n\n// Form Field Types - use proper FieldConfig from formedible with builder-specific additions\nexport interface FormField extends FieldConfig {\n  id: string; // Builder-specific ID for field management\n  label: string; // Make label required for builder\n}\n\n// Form Metadata Types\nexport interface FormPage {\n  page: number;\n  title: string;\n  description?: string;\n}\n\nexport interface FormTab {\n  id: string;\n  label: string;\n  description?: string;\n}\n\nexport interface FormSettings {\n  submitLabel: string;\n  nextLabel: string;\n  previousLabel: string;\n  showProgress: boolean;\n}\n\nexport interface FormMetadata {\n  title: string;\n  description: string;\n  pages: FormPage[];\n  tabs: FormTab[];\n  layoutType: \"pages\" | \"tabs\";\n  settings: FormSettings;\n}\n\n// Form Configuration\nexport interface FormConfig {\n  title: string;\n  description: string;\n  schema: z.ZodSchema<any>;\n  settings: FormSettings;\n  fields: FormField[];\n  pages?: FormPage[];\n  tabs?: FormTab[];\n  submitLabel?: string;\n  nextLabel?: string;\n  previousLabel?: string;\n  progress?: {\n    showSteps: boolean;\n    showPercentage: boolean;\n  };\n  formOptions: {\n    onSubmit: (data: { value: any }) => Promise<void> | void;\n  };\n}\n\n// Tab System Types\nexport interface TabContentProps {\n  // Form state and operations - NON-REACTIVE\n  getFormMetadata: () => FormMetadata;\n  onFormMetadataChange: (metadata: Partial<FormMetadata>) => void;\n  \n  // Field operations\n  selectedFieldId: string | null;\n  onSelectField: (fieldId: string | null) => void;\n  onAddField: (type: string) => void;\n  onDeleteField: (fieldId: string) => void;\n  onDuplicateField: (fieldId: string) => void;\n  \n  // UI state\n  selectedPageId: number | null;\n  selectedTabId: string | null;\n  setSelectedPageId: (pageId: number | null) => void;\n  setSelectedTabId: (tabId: string | null) => void;\n  editingPageId: number | null;\n  setEditingPageId: (pageId: number | null) => void;\n  editingTabId: string | null;\n  setEditingTabId: (tabId: string | null) => void;\n  previewMode: \"desktop\" | \"tablet\" | \"mobile\";\n  setPreviewMode: (mode: \"desktop\" | \"tablet\" | \"mobile\") => void;\n  \n  // Data access\n  getAllFields: () => FormField[];\n  getFieldsByPage: (page: number) => FormField[];\n  getFieldsByTab: (tabId: string) => FormField[];\n  getFormConfig: () => FormConfig;\n  \n  // Import/Export\n  exportConfig: () => void;\n  importConfig: () => void;\n}\n\nexport interface TabConfig {\n  id: string;\n  label: string;\n  icon?: React.ComponentType<{ className?: string }>;\n  component: React.ComponentType<TabContentProps>;\n  enabled?: boolean;\n  order?: number;\n}\n\n// Builder Context Type\nexport interface BuilderContextType extends TabContentProps {\n  // Additional context-specific methods can be added here\n  forceRerender: () => void;\n  // Submit functionality\n  submitConfig: () => void;\n  isLoading: boolean;\n}\n\n// Field Operations\nexport interface FieldOperations {\n  addField: (type: string, page?: number) => string;\n  deleteField: (fieldId: string) => void;\n  duplicateField: (fieldId: string) => string | null;\n  updateField: (fieldId: string, updates: Partial<FormField>) => void;\n  getField: (fieldId: string) => FormField | null;\n  getAllFields: () => FormField[];\n  getFieldsByPage: (page: number) => FormField[];\n  getFieldsByTab: (tabId: string) => FormField[];\n  importFields: (fields: Partial<FormField>[]) => void;\n  subscribe: (callback: () => void) => () => void;\n  subscribeToFieldUpdates: (fieldId: string, callback: (field: FormField) => void) => () => void;\n}\n\n// Component Props\nexport interface FormBuilderProps {\n  tabs?: TabConfig[];\n  defaultTab?: string;\n  enabledTabs?: string[];\n  onTabChange?: (tabId: string) => void;\n  className?: string;\n  initialData?: {\n    title: string;\n    description?: string;\n    config: string;\n  };\n  onSubmit?: (formData: {\n    title: string;\n    description?: string;\n    config: string;\n  }) => void;\n  isLoading?: boolean;\n}\n\nexport interface TabContainerProps {\n  tabs: TabConfig[];\n  defaultTab?: string;\n  onTabChange?: (tabId: string) => void;\n  className?: string;\n}\n\n// Field Type Definitions\nexport interface FieldType {\n  value: string;\n  label: string;\n  icon: string;\n}\n\nexport const FIELD_TYPES: FieldType[] = [\n  { value: \"text\", label: \"Text Input\", icon: \"📝\" },\n  { value: \"email\", label: \"Email\", icon: \"📧\" },\n  { value: \"password\", label: \"Password\", icon: \"🔒\" },\n  { value: \"textarea\", label: \"Textarea\", icon: \"📄\" },\n  { value: \"number\", label: \"Number\", icon: \"🔢\" },\n  { value: \"select\", label: \"Select\", icon: \"📋\" },\n  { value: \"radio\", label: \"Radio Group\", icon: \"⚪\" },\n  { value: \"multiSelect\", label: \"Multi-Select\", icon: \"☑️\" },\n  { value: \"checkbox\", label: \"Checkbox\", icon: \"✅\" },\n  { value: \"switch\", label: \"Switch\", icon: \"🔘\" },\n  { value: \"date\", label: \"Date Picker\", icon: \"📅\" },\n  { value: \"slider\", label: \"Slider\", icon: \"🎚️\" },\n  { value: \"rating\", label: \"Rating\", icon: \"⭐\" },\n  { value: \"colorPicker\", label: \"Color Picker\", icon: \"🎨\" },\n  { value: \"phone\", label: \"Phone Number\", icon: \"📞\" },\n  { value: \"file\", label: \"File Upload\", icon: \"📎\" },\n  { value: \"array\", label: \"Array Field\", icon: \"📚\" },\n];",
      "type": "registry:lib",
      "target": "lib/formedible/builder-types.ts"
    },
    {
      "path": "src/components/formedible/builder/BuilderContext.tsx",
      "content": "\"use client\";\nimport React, { createContext, useContext, useState, useRef, useCallback } from \"react\";\nimport { z } from \"zod\";\nimport { globalFieldStore } from \"./field-store\";\nimport type {\n  BuilderContextType,\n  FormMetadata,\n  FormField,\n  FormConfig,\n  TabContentProps,\n} from \"@/lib/formedible/builder-types\";\n\nconst BuilderContext = createContext<BuilderContextType | null>(null);\n\nexport const useBuilderContext = () => {\n  const context = useContext(BuilderContext);\n  if (!context) {\n    throw new Error(\"useBuilderContext must be used within a BuilderProvider\");\n  }\n  return context;\n};\n\ninterface BuilderProviderProps {\n  children: React.ReactNode;\n  initialMetadata?: Partial<FormMetadata>;\n  initialData?: {\n    title: string;\n    description?: string;\n    config: string;\n  };\n  onSubmit?: (formData: {\n    title: string;\n    description?: string;\n    config: string;\n  }) => void;\n  isLoading?: boolean;\n}\n\nexport const BuilderProvider: React.FC<BuilderProviderProps> = ({\n  children,\n  initialMetadata = {},\n  initialData,\n  onSubmit,\n  isLoading = false,\n}) => {\n  // Form metadata state (minimal, non-rerendering) - USING REF TO AVOID RE-RENDERS\n  const formMetaRef = useRef<FormMetadata>({\n    title: \"My Form\",\n    description: \"A form built with Formedible\",\n    pages: [{ page: 1, title: \"Page 1\", description: \"First page\" }],\n    tabs: [{ id: \"general\", label: \"General\", description: \"General information\" }],\n    layoutType: \"pages\",\n    settings: {\n      submitLabel: \"Submit\",\n      nextLabel: \"Next\",\n      previousLabel: \"Previous\",\n      showProgress: true,\n    },\n    ...initialMetadata,\n  });\n\n  // UI state (minimal, only for display)\n  const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null);\n  const [selectedPageId, setSelectedPageId] = useState<number | null>(null);\n  const [selectedTabId, setSelectedTabId] = useState<string | null>(null);\n  const [editingPageId, setEditingPageId] = useState<number | null>(null);\n  const [editingTabId, setEditingTabId] = useState<string | null>(null);\n  const [previewMode, setPreviewMode] = useState<\"desktop\" | \"tablet\" | \"mobile\">(\"desktop\");\n\n  // Force rerender for structure changes\n  const [, forceUpdateState] = useState({});\n  const forceRerender = useCallback(() => forceUpdateState({}), []);\n\n  // Subscribe to global field store changes\n  React.useEffect(() => {\n    const unsubscribe = globalFieldStore.subscribe(forceRerender);\n    return unsubscribe;\n  }, [forceRerender]);\n\n  // Load initial config once without rerenders\n  const [isInitialized, setIsInitialized] = useState(false);\n\n  React.useEffect(() => {\n    if (initialData && !isInitialized) {\n      // Update form metadata\n      formMetaRef.current.title = initialData.title;\n      formMetaRef.current.description = initialData.description || \"\";\n\n      // Parse and load config\n      try {\n        const config = JSON.parse(initialData.config);\n        if (config.fields) {\n          globalFieldStore.importFields(config.fields);\n        }\n        if (config.pages) {\n          formMetaRef.current.pages = config.pages;\n        }\n        if (config.tabs) {\n          formMetaRef.current.tabs = config.tabs;\n        }\n        if (config.layoutType) {\n          formMetaRef.current.layoutType = config.layoutType;\n        }\n        if (config.settings) {\n          formMetaRef.current.settings = {\n            ...formMetaRef.current.settings,\n            ...config.settings,\n          };\n        }\n      } catch (error) {\n        console.warn(\"Failed to parse initial config:\", error);\n      }\n\n      setIsInitialized(true);\n    }\n  }, [initialData, isInitialized]);\n\n  // Form metadata operations - DON'T TRIGGER RE-RENDERS\n  const onFormMetadataChange = useCallback((updates: Partial<FormMetadata>) => {\n    Object.assign(formMetaRef.current, updates);\n  }, []);\n\n  // Get current form metadata (non-reactive)\n  const getFormMetadata = useCallback(() => formMetaRef.current, []);\n\n  // Field operations\n  const onAddField = useCallback((type: string) => {\n    const newFieldId = globalFieldStore.addField(type, selectedPageId || 1);\n    const field = globalFieldStore.getField(newFieldId);\n    if (field && formMetaRef.current.layoutType === \"tabs\" && selectedTabId) {\n      globalFieldStore.updateField(newFieldId, { ...field, tab: selectedTabId });\n    }\n    setSelectedFieldId(newFieldId);\n  }, [selectedPageId, selectedTabId]);\n\n  const onSelectField = useCallback((fieldId: string | null) => {\n    setSelectedFieldId(fieldId);\n  }, []);\n\n  const onDeleteField = useCallback((fieldId: string) => {\n    globalFieldStore.deleteField(fieldId);\n    if (selectedFieldId === fieldId) {\n      setSelectedFieldId(null);\n    }\n  }, [selectedFieldId]);\n\n  const onDuplicateField = useCallback((fieldId: string) => {\n    const newFieldId = globalFieldStore.duplicateField(fieldId);\n    if (newFieldId) {\n      setSelectedFieldId(newFieldId);\n    }\n  }, []);\n\n  // Data access operations\n  const getAllFields = useCallback(() => globalFieldStore.getAllFields(), []);\n  const getFieldsByPage = useCallback((page: number) => globalFieldStore.getFieldsByPage(page), []);\n  const getFieldsByTab = useCallback((tabId: string) => globalFieldStore.getFieldsByTab(tabId), []);\n\n  // Generate form configuration\n  const getFormConfig = useCallback((): FormConfig => {\n    const currentFields = globalFieldStore.getAllFields();\n    const schemaFields: Record<string, any> = {};\n\n    currentFields.forEach((field) => {\n      let fieldSchema: any;\n\n      switch (field.type) {\n        case \"number\":\n        case \"slider\":\n        case \"rating\":\n          fieldSchema = z.number();\n          break;\n        case \"checkbox\":\n        case \"switch\":\n          fieldSchema = z.boolean();\n          break;\n        case \"date\":\n          fieldSchema = z.string();\n          break;\n        case \"multiSelect\":\n        case \"array\":\n          fieldSchema = z.array(z.string());\n          break;\n        case \"object\":\n          fieldSchema = z.object({});\n          break;\n        default:\n          fieldSchema = z.string();\n      }\n\n      if (field.required) {\n        if (field.type === \"number\" || field.type === \"slider\" || field.type === \"rating\") {\n          // For numbers, required means not null/undefined\n        } else if (field.type === \"checkbox\" || field.type === \"switch\") {\n          fieldSchema = fieldSchema.refine((val: boolean) => val === true, {\n            message: field.validationConfig?.customMessages?.required || `${field.label} is required`,\n          });\n        } else if (typeof fieldSchema.min === \"function\") {\n          fieldSchema = fieldSchema.min(1, field.validationConfig?.customMessages?.required || `${field.label} is required`);\n        }\n      } else {\n        fieldSchema = fieldSchema.optional();\n      }\n\n      schemaFields[field.name] = fieldSchema;\n    });\n\n    return {\n      title: formMetaRef.current.title,\n      description: formMetaRef.current.description,\n      schema: z.object(schemaFields),\n      settings: formMetaRef.current.settings,\n      fields: currentFields.map((field) => ({\n        id: field.id,\n        name: field.name,\n        type: field.type,\n        label: field.label,\n        placeholder: field.placeholder,\n        description: field.description,\n        page: field.page || 1,\n        tab: field.tab,\n        group: field.group,\n        section: field.section,\n        help: field.help,\n        inlineValidation: field.inlineValidation,\n        ...(field.options && { options: field.options }),\n        ...(field.arrayConfig && { arrayConfig: field.arrayConfig }),\n        ...(field.datalist && { datalist: field.datalist }),\n        ...(field.multiSelectConfig && { multiSelectConfig: field.multiSelectConfig }),\n        ...(field.colorConfig && { colorConfig: field.colorConfig }),\n        ...(field.ratingConfig && { ratingConfig: field.ratingConfig }),\n        ...(field.phoneConfig && { phoneConfig: field.phoneConfig }),\n      })),\n      pages: formMetaRef.current.layoutType === \"pages\" && formMetaRef.current.pages.length > 1 ? formMetaRef.current.pages : [],\n      tabs: formMetaRef.current.layoutType === \"tabs\" ? formMetaRef.current.tabs : undefined,\n      submitLabel: formMetaRef.current.settings.submitLabel,\n      nextLabel: formMetaRef.current.settings.nextLabel,\n      previousLabel: formMetaRef.current.settings.previousLabel,\n      progress: formMetaRef.current.settings.showProgress\n        ? { showSteps: true, showPercentage: true }\n        : undefined,\n      formOptions: {\n        onSubmit: async ({ value }: any) => {\n          console.log(\"Form submitted:\", value);\n          alert(\"Form submitted! Check console for values.\");\n        },\n      },\n    };\n  }, []);\n\n  // Export configuration\n  const exportConfig = useCallback(() => {\n    const formConfig = {\n      title: formMetaRef.current.title,\n      description: formMetaRef.current.description,\n      fields: globalFieldStore.getAllFields().map((field) => ({\n        name: field.name,\n        type: field.type,\n        label: field.label,\n        placeholder: field.placeholder,\n        description: field.description,\n        required: field.required,\n        page: field.page || 1,\n        tab: field.tab,\n        group: field.group,\n        section: field.section,\n        help: field.help,\n        inlineValidation: field.inlineValidation,\n        options: field.options,\n        arrayConfig: field.arrayConfig,\n        datalist: field.datalist,\n        multiSelectConfig: field.multiSelectConfig,\n        colorConfig: field.colorConfig,\n        ratingConfig: field.ratingConfig,\n        phoneConfig: field.phoneConfig,\n      })),\n      pages: formMetaRef.current.pages,\n      tabs: formMetaRef.current.tabs,\n      layoutType: formMetaRef.current.layoutType,\n      settings: formMetaRef.current.settings,\n    };\n\n    const blob = new Blob([JSON.stringify(formConfig, null, 2)], {\n      type: \"application/json\",\n    });\n    const url = URL.createObjectURL(blob);\n    const a = document.createElement(\"a\");\n    a.href = url;\n    a.download = `${formMetaRef.current.title.toLowerCase().replace(/\\s+/g, \"-\")}-form.json`;\n    a.click();\n    URL.revokeObjectURL(url);\n  }, []);\n\n  // Import configuration\n  const importConfig = useCallback(() => {\n    const input = document.createElement(\"input\");\n    input.type = \"file\";\n    input.accept = \".json\";\n    input.onchange = (e) => {\n      const file = (e.target as HTMLInputElement).files?.[0];\n      if (!file) return;\n\n      const reader = new FileReader();\n      reader.onload = (e) => {\n        try {\n          const config = JSON.parse(e.target?.result as string);\n          \n          // Import fields\n          globalFieldStore.importFields(config.fields || []);\n\n          // Update form config - DIRECT ASSIGNMENT TO AVOID RE-RENDERS\n          Object.assign(formMetaRef.current, {\n            title: config.title || \"Imported Form\",\n            description: config.description || \"Imported from JSON\",\n            pages: config.pages || [{ page: 1, title: \"Page 1\", description: \"\" }],\n            tabs: config.tabs || [{ id: \"general\", label: \"General\", description: \"General information\" }],\n            layoutType: config.layoutType || \"pages\",\n            settings: {\n              submitLabel: config.settings?.submitLabel || config.submitLabel || \"Submit\",\n              nextLabel: config.settings?.nextLabel || config.nextLabel || \"Next\",\n              previousLabel: config.settings?.previousLabel || config.previousLabel || \"Previous\",\n              showProgress: config.settings?.showProgress ?? (!!config.progress),\n            }\n          });\n          \n          setSelectedFieldId(null);\n          forceRerender();\n        } catch (error) {\n          alert(\"Error importing configuration. Please check the file format.\");\n          console.error(\"Import error:\", error);\n        }\n      };\n      reader.readAsText(file);\n    };\n    input.click();\n  }, [forceRerender]);\n\n  // Submit configuration to parent\n  const submitConfig = useCallback(() => {\n    if (onSubmit) {\n      const config = {\n        title: formMetaRef.current.title,\n        description: formMetaRef.current.description,\n        fields: globalFieldStore.getAllFields().map((field) => ({\n          name: field.name,\n          type: field.type,\n          label: field.label,\n          placeholder: field.placeholder,\n          description: field.description,\n          required: field.required,\n          page: field.page || 1,\n          tab: field.tab,\n          group: field.group,\n          section: field.section,\n          help: field.help,\n          inlineValidation: field.inlineValidation,\n          options: field.options,\n          arrayConfig: field.arrayConfig,\n          datalist: field.datalist,\n          multiSelectConfig: field.multiSelectConfig,\n          colorConfig: field.colorConfig,\n          ratingConfig: field.ratingConfig,\n          phoneConfig: field.phoneConfig,\n        })),\n        pages: formMetaRef.current.pages,\n        tabs: formMetaRef.current.tabs,\n        layoutType: formMetaRef.current.layoutType,\n        settings: formMetaRef.current.settings,\n      };\n      onSubmit({\n        title: config.title,\n        description: config.description,\n        config: JSON.stringify(config),\n      });\n    }\n  }, [onSubmit]);\n\n  // Add keyboard shortcut for save (Ctrl+S)\n  React.useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if ((e.ctrlKey || e.metaKey) && e.key === \"s\") {\n        e.preventDefault();\n        submitConfig();\n      }\n    };\n\n    document.addEventListener(\"keydown\", handleKeyDown);\n    return () => document.removeEventListener(\"keydown\", handleKeyDown);\n  }, [submitConfig]);\n\n  const contextValue: BuilderContextType = {\n    // Form metadata - NON-REACTIVE\n    getFormMetadata,\n    onFormMetadataChange,\n\n    // Field operations\n    selectedFieldId,\n    onSelectField,\n    onAddField,\n    onDeleteField,\n    onDuplicateField,\n\n    // UI state\n    selectedPageId,\n    selectedTabId,\n    setSelectedPageId,\n    setSelectedTabId,\n    editingPageId,\n    setEditingPageId,\n    editingTabId,\n    setEditingTabId,\n    previewMode,\n    setPreviewMode,\n\n    // Data access\n    getAllFields,\n    getFieldsByPage,\n    getFieldsByTab,\n    getFormConfig,\n\n    // Import/Export\n    exportConfig,\n    importConfig,\n\n    // Context-specific\n    forceRerender,\n    \n    // Submit functionality\n    submitConfig,\n    isLoading,\n  };\n\n  return (\n    <BuilderContext.Provider value={contextValue}>\n      {children}\n    </BuilderContext.Provider>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/BuilderContext.tsx"
    },
    {
      "path": "src/components/formedible/builder/TabContainer.tsx",
      "content": "\"use client\";\nimport React, { useState, useMemo } from \"react\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { cn } from \"@/lib/utils\";\nimport { useBuilderContext } from \"./BuilderContext\";\nimport type { TabConfig, TabContainerProps } from \"@/lib/formedible/builder-types\";\n\nexport const TabContainer: React.FC<TabContainerProps> = ({\n  tabs,\n  defaultTab,\n  onTabChange,\n  className,\n}) => {\n  const builderContext = useBuilderContext();\n  \n  // Filter and sort tabs\n  const activeTabs = useMemo(() => {\n    return tabs\n      .filter(tab => tab.enabled !== false)\n      .sort((a, b) => {\n        // Sort by order if provided, otherwise maintain array order\n        const orderA = a.order ?? 0;\n        const orderB = b.order ?? 0;\n        return orderA - orderB;\n      });\n  }, [tabs]);\n\n  // Determine initial active tab\n  const initialTab = useMemo(() => {\n    if (defaultTab && activeTabs.some(tab => tab.id === defaultTab)) {\n      return defaultTab;\n    }\n    return activeTabs.length > 0 ? activeTabs[0].id : \"\";\n  }, [defaultTab, activeTabs]);\n\n  const [activeTab, setActiveTab] = useState(initialTab);\n\n  const handleTabChange = (value: string) => {\n    setActiveTab(value);\n    onTabChange?.(value);\n  };\n\n  if (activeTabs.length === 0) {\n    return (\n      <div className=\"flex items-center justify-center h-64 border-2 border-dashed border-muted-foreground/25 rounded-lg\">\n        <div className=\"text-center\">\n          <h3 className=\"text-lg font-medium text-foreground mb-2\">No Tabs Available</h3>\n          <p className=\"text-muted-foreground\">No enabled tabs to display</p>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <Tabs \n      value={activeTab} \n      onValueChange={handleTabChange} \n      className={cn(\"flex-1 flex flex-col\", className)}\n    >\n      <TabsList className=\"w-full justify-start border-b rounded-none h-14 bg-card p-0\">\n        {activeTabs.map((tab) => {\n          const IconComponent = tab.icon;\n          return (\n            <TabsTrigger \n              key={tab.id} \n              value={tab.id} \n              className=\"flex items-center gap-2 h-full px-6\"\n            >\n              {IconComponent && <IconComponent className=\"h-4 w-4\" />}\n              {tab.label}\n            </TabsTrigger>\n          );\n        })}\n      </TabsList>\n\n      <div className=\"flex-1 min-h-0\">\n        {activeTabs.map((tab) => {\n          const TabComponent = tab.component;\n          return (\n            <TabsContent \n              key={tab.id} \n              value={tab.id} \n              className=\"h-full m-0\"\n            >\n              <TabComponent {...builderContext} />\n            </TabsContent>\n          );\n        })}\n      </div>\n    </Tabs>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/TabContainer.tsx"
    },
    {
      "path": "src/components/formedible/builder/default-tabs.ts",
      "content": "import { Settings, Eye, Code } from \"lucide-react\";\nimport { BuilderTabContent } from \"./tabs/BuilderTabContent\";\nimport { PreviewTabContent } from \"./tabs/PreviewTabContent\";\nimport { CodeTabContent } from \"./tabs/CodeTabContent\";\nimport type { TabConfig } from \"@/lib/formedible/builder-types\";\n\nexport const builderTab: TabConfig = {\n  id: \"builder\",\n  label: \"Builder\",\n  icon: Settings,\n  component: BuilderTabContent,\n  enabled: true,\n  order: 1,\n};\n\nexport const previewTab: TabConfig = {\n  id: \"preview\",\n  label: \"Preview\",\n  icon: Eye,\n  component: PreviewTabContent,\n  enabled: true,\n  order: 2,\n};\n\nexport const codeTab: TabConfig = {\n  id: \"code\",\n  label: \"Code\",\n  icon: Code,\n  component: CodeTabContent,\n  enabled: true,\n  order: 3,\n};\n\nexport const defaultTabs: TabConfig[] = [\n  builderTab,\n  previewTab,\n  codeTab,\n];\n\n// Helper functions for common tab configurations\nexport const getBuilderOnlyTabs = (): TabConfig[] => [builderTab];\n\nexport const getBuilderAndPreviewTabs = (): TabConfig[] => [builderTab, previewTab];\n\nexport const getBuilderAndCodeTabs = (): TabConfig[] => [builderTab, codeTab];\n\nexport const getPreviewAndCodeTabs = (): TabConfig[] => [previewTab, codeTab];\n\n// Factory function to create custom tab orders\nexport const createTabsWithOrder = (tabIds: string[]): TabConfig[] => {\n  const tabMap = new Map([\n    [\"builder\", builderTab],\n    [\"preview\", previewTab],\n    [\"code\", codeTab],\n  ]);\n\n  return tabIds\n    .map(id => tabMap.get(id))\n    .filter((tab): tab is TabConfig => tab !== undefined)\n    .map((tab, index) => ({ ...tab, order: index + 1 }));\n};\n\n// Factory function to disable specific tabs\nexport const createTabsWithDisabled = (disabledIds: string[]): TabConfig[] => {\n  return defaultTabs.map(tab => ({\n    ...tab,\n    enabled: !disabledIds.includes(tab.id),\n  }));\n};",
      "type": "registry:lib",
      "target": "components/formedible/builder/default-tabs.ts"
    },
    {
      "path": "src/components/formedible/builder/tabs/BuilderTabContent.tsx",
      "content": "\"use client\";\nimport React, { useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { cn } from \"@/lib/utils\";\nimport { Plus, Trash2, Copy, Edit, FileText, ChevronDown, ChevronUp } from \"lucide-react\";\nimport { FieldConfigurator } from \"../field-configurator\";\nimport { globalFieldStore } from \"../field-store\";\nimport type { TabContentProps, FormField } from \"@/lib/formedible/builder-types\";\nimport { FIELD_TYPES } from \"@/lib/formedible/builder-types\";\n\n// FieldList Component with grid layout (2 per row)\nconst FieldList: React.FC<{\n  fields: FormField[];\n  selectedFieldId: string | null;\n  onSelectField: (id: string | null) => void;\n  onDeleteField: (id: string) => void;\n  onDuplicateField: (id: string) => void;\n}> = ({ fields, selectedFieldId, onSelectField, onDeleteField, onDuplicateField }) => {\n  const [displayFields, setDisplayFields] = useState(fields);\n\n  // Subscribe to field updates for all visible fields\n  React.useEffect(() => {\n    const unsubscribers: (() => void)[] = [];\n\n    // Subscribe to each field's updates\n    fields.forEach(field => {\n      const unsubscribe = globalFieldStore.subscribeToFieldUpdates(field.id, (updatedField) => {\n        setDisplayFields(prevFields => \n          prevFields.map(f => f.id === updatedField.id ? updatedField : f)\n        );\n      });\n      unsubscribers.push(unsubscribe);\n    });\n\n    // Update display fields when fields prop changes\n    setDisplayFields(fields);\n\n    return () => {\n      unsubscribers.forEach(unsub => unsub());\n    };\n  }, [fields]);\n\n  return (\n    <div className=\"grid grid-cols-2 gap-4\">\n      {displayFields.map((field) => (\n      <div\n        key={field.id}\n        className={cn(\n          \"flex flex-col p-4 rounded-lg cursor-pointer transition-colors hover:shadow-md border bg-muted/30\",\n          selectedFieldId === field.id\n            ? \"border-primary bg-primary/5 ring-1 ring-primary/30\"\n            : \"border-border hover:bg-muted/50\"\n        )}\n        onClick={() => onSelectField(field.id)}\n      >\n        <div className=\"flex items-center space-x-3 mb-2\">\n          <span className=\"text-xl\">\n            {FIELD_TYPES.find((t) => t.value === field.type)?.icon || \"📝\"}\n          </span>\n          <div className=\"flex-1 min-w-0\">\n            <div className=\"font-medium truncate\">{field.label}</div>\n            <div className=\"text-sm text-muted-foreground truncate\">\n              {field.type} • {field.name}\n            </div>\n            <div className=\"text-xs text-muted-foreground\">\n              {field.tab ? `Tab ${field.tab}` : `Page ${field.page || 1}`}\n            </div>\n          </div>\n        </div>\n        <div className=\"flex items-center justify-end space-x-2 mt-auto\">\n          <Button\n            variant=\"ghost\"\n            size=\"sm\"\n            onClick={(e) => {\n              e.stopPropagation();\n              onDuplicateField(field.id);\n            }}\n          >\n            <Copy className=\"h-3 w-3\" />\n          </Button>\n          <Button\n            variant=\"ghost\"\n            size=\"sm\"\n            onClick={(e) => {\n              e.stopPropagation();\n              onDeleteField(field.id);\n            }}\n          >\n            <Trash2 className=\"h-3 w-3\" />\n          </Button>\n        </div>\n      </div>\n    ))}\n  </div>\n  );\n};\n\nFieldList.displayName = 'FieldList';\n\n// Collapsible Section Component\nconst CollapsibleSection: React.FC<{\n  title: string;\n  children: React.ReactNode;\n  defaultOpen?: boolean;\n  className?: string;\n}> = ({ title, children, defaultOpen = true, className }) => {\n  const [isOpen, setIsOpen] = useState(defaultOpen);\n\n  return (\n    <div className={cn(\"space-y-4\", className)}>\n      <div \n        className=\"flex items-center justify-between cursor-pointer py-2 hover:text-primary transition-colors border-b border-border\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <h3 className=\"text-xl font-semibold\">{title}</h3>\n        {isOpen ? (\n          <ChevronUp className=\"h-5 w-5\" />\n        ) : (\n          <ChevronDown className=\"h-5 w-5\" />\n        )}\n      </div>\n      {isOpen && (\n        <div className=\"space-y-4\">\n          {children}\n        </div>\n      )}\n      {/* Dashed separator line at bottom - only when open */}\n      {isOpen && (\n        <div className=\"flex justify-center\">\n          <div className=\"w-2/3 border-b border-dashed border-border/60\" />\n        </div>\n      )}\n    </div>\n  );\n};\n\n// FieldTypeSidebar Component\nconst FieldTypeSidebar: React.FC<{\n  onAddField: (type: string) => void;\n  selectedPage: number | null;\n  selectedTab: string | null;\n  layoutType: \"pages\" | \"tabs\";\n}> = ({ onAddField, selectedPage, selectedTab, layoutType }) => (\n  <div className=\"w-72 overflow-y-auto\">\n    <div className=\"p-6 bg-card border-r\">\n      <h3 className=\"font-semibold text-lg mb-6\">Field Types</h3>\n      {layoutType === \"pages\" && selectedPage && (\n        <div className=\"mb-4 p-3 bg-primary/10 rounded-lg\">\n          <p className=\"text-sm text-primary font-medium\">\n            Adding to Page {selectedPage}\n          </p>\n        </div>\n      )}\n      {layoutType === \"tabs\" && selectedTab && (\n        <div className=\"mb-4 p-3 bg-primary/10 rounded-lg\">\n          <p className=\"text-sm text-primary font-medium\">\n            Adding to Tab {selectedTab}\n          </p>\n        </div>\n      )}\n      <div className=\"grid grid-cols-1 gap-3\">\n        {FIELD_TYPES.map((fieldType) => (\n          <Button\n            key={fieldType.value}\n            variant=\"outline\"\n            size=\"default\"\n            className=\"justify-start h-auto p-4\"\n            onClick={() => onAddField(fieldType.value)}\n          >\n            <span className=\"mr-3 text-lg\">{fieldType.icon}</span>\n            <span>{fieldType.label}</span>\n          </Button>\n        ))}\n      </div>\n    </div>\n  </div>\n);\n\n// ConfiguratorPanel Component\nconst ConfiguratorPanel: React.FC<{\n  selectedFieldId: string | null;\n  availablePages: number[];\n}> = ({ selectedFieldId, availablePages }) => {\n  const [currentField, setCurrentField] = useState<FormField | null>(null);\n\n  // Update field data when selectedFieldId changes\n  React.useEffect(() => {\n    if (selectedFieldId) {\n      const field = globalFieldStore.getField(selectedFieldId);\n      setCurrentField(field || null);\n    } else {\n      setCurrentField(null);\n    }\n  }, [selectedFieldId]);\n\n  if (!selectedFieldId || !currentField) return null;\n\n  return (\n    <div className=\"w-96 overflow-y-auto min-h-0\">\n      <div className=\"bg-card border-l\">\n        <FieldConfigurator\n          fieldId={selectedFieldId}\n          initialField={currentField}\n          availablePages={availablePages}\n        />\n      </div>\n    </div>\n  );\n};\n\nexport const BuilderTabContent: React.FC<TabContentProps> = ({\n  getFormMetadata,\n  onFormMetadataChange,\n  selectedFieldId,\n  onSelectField,\n  onAddField,\n  onDeleteField,\n  onDuplicateField,\n  selectedPageId,\n  selectedTabId,\n  setSelectedPageId,\n  setSelectedTabId,\n  editingPageId,\n  setEditingPageId,\n  editingTabId,\n  setEditingTabId,\n  getAllFields,\n  getFieldsByPage,\n  getFieldsByTab,\n}) => {\n  // Get current form metadata when needed (non-reactive)\n  const formMetadata = getFormMetadata();\n  \n  // Get fields to show based on current selection\n  const allFields = getAllFields();\n  const fieldsToShow = formMetadata.layoutType === \"pages\" \n    ? (selectedPageId ? getFieldsByPage(selectedPageId) : allFields)\n    : (selectedTabId ? getFieldsByTab(selectedTabId) : allFields);\n\n  const availablePages = formMetadata.pages.map(p => p.page);\n\n  return (\n    <div className=\"h-full flex min-h-0\">\n      {/* Sidebar - Field Types */}\n      <FieldTypeSidebar \n        onAddField={onAddField} \n        selectedPage={selectedPageId} \n        selectedTab={selectedTabId}\n        layoutType={formMetadata.layoutType}\n      />\n\n      {/* Main Content */}\n      <div className=\"flex-1 p-4 overflow-y-auto min-h-0\">\n        <div className=\"mx-auto space-y-4\">\n          {/* Form Configuration */}\n          <CollapsibleSection title=\"Form Configuration\">\n            <div className=\"space-y-4\">\n              <div>\n                <Label htmlFor=\"form-title\">Form Title</Label>\n                <Input\n                  id=\"form-title\"\n                  defaultValue={formMetadata.title}\n                  onChange={(e) => onFormMetadataChange({ title: e.target.value })}\n                  placeholder=\"Enter form title\"\n                />\n              </div>\n              <div>\n                <Label htmlFor=\"form-description\">Description</Label>\n                <Textarea\n                  id=\"form-description\"\n                  defaultValue={formMetadata.description}\n                  onChange={(e) => onFormMetadataChange({ description: e.target.value })}\n                  placeholder=\"Enter form description\"\n                />\n              </div>\n              <div>\n                <Label htmlFor=\"layout-type\">Layout Type</Label>\n                <select\n                  id=\"layout-type\"\n                  defaultValue={formMetadata.layoutType}\n                  onChange={(e) => onFormMetadataChange({ layoutType: e.target.value as \"pages\" | \"tabs\" })}\n                  className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n                >\n                  <option value=\"pages\">Multi-Page Form</option>\n                  <option value=\"tabs\">Tabbed Form</option>\n                </select>\n              </div>\n            </div>\n          </CollapsibleSection>\n\n          {/* Form Settings */}\n          <CollapsibleSection title=\"Form Settings\">\n            <div className=\"space-y-4\">\n              <div>\n                <Label htmlFor=\"submit-label\">Submit Button Label</Label>\n                <Input\n                  id=\"submit-label\"\n                  defaultValue={formMetadata.settings.submitLabel}\n                  onChange={(e) => onFormMetadataChange({ \n                    settings: { ...formMetadata.settings, submitLabel: e.target.value } \n                  })}\n                  placeholder=\"Submit\"\n                />\n              </div>\n              <div>\n                <Label htmlFor=\"next-label\">Next Button Label</Label>\n                <Input\n                  id=\"next-label\"\n                  defaultValue={formMetadata.settings.nextLabel}\n                  onChange={(e) => onFormMetadataChange({ \n                    settings: { ...formMetadata.settings, nextLabel: e.target.value } \n                  })}\n                  placeholder=\"Next\"\n                />\n              </div>\n              <div>\n                <Label htmlFor=\"previous-label\">Previous Button Label</Label>\n                <Input\n                  id=\"previous-label\"\n                  defaultValue={formMetadata.settings.previousLabel}\n                  onChange={(e) => onFormMetadataChange({ \n                    settings: { ...formMetadata.settings, previousLabel: e.target.value } \n                  })}\n                  placeholder=\"Previous\"\n                />\n              </div>\n              <div className=\"flex items-center space-x-2\">\n                <Checkbox\n                  id=\"show-progress\"\n                  defaultChecked={formMetadata.settings.showProgress}\n                  onCheckedChange={(checked) => onFormMetadataChange({ \n                    settings: { ...formMetadata.settings, showProgress: !!checked } \n                  })}\n                />\n                <Label htmlFor=\"show-progress\">Show progress indicator</Label>\n              </div>\n            </div>\n          </CollapsibleSection>\n\n          {/* Page Management */}\n          {formMetadata.layoutType === \"pages\" && (\n            <CollapsibleSection \n              title={`Pages (${formMetadata.pages.length})`}\n              className=\"space-y-4\"\n            >\n              <div className=\"flex items-center justify-between mb-4\">\n                {selectedPageId && (\n                  <span className=\"text-sm text-primary\">\n                    Page {selectedPageId} selected\n                  </span>\n                )}\n                <Button\n                  onClick={() => {\n                    const newPageNumber = Math.max(...formMetadata.pages.map((p) => p.page)) + 1;\n                    const newPages = [...formMetadata.pages, {\n                      page: newPageNumber,\n                      title: `Page ${newPageNumber}`,\n                      description: \"\",\n                    }];\n                    onFormMetadataChange({ pages: newPages });\n                    setEditingPageId(newPageNumber);\n                  }}\n                >\n                  <Plus className=\"h-4 w-4 mr-2\" />\n                  Add Page\n                </Button>\n              </div>\n              <div className=\"grid grid-cols-3 gap-4\">\n                {formMetadata.pages.map((page) => (\n                  <div\n                    key={page.page}\n                    className={cn(\n                      \"border rounded-lg transition-all cursor-pointer bg-muted/30\",\n                      selectedPageId === page.page\n                        ? \"border-primary bg-primary/5 ring-1 ring-primary/30\"\n                        : \"border-border hover:bg-muted/50\",\n                      editingPageId === page.page && \"ring-2 ring-primary/20\"\n                    )}\n                    onClick={() => {\n                      if (editingPageId === page.page) return;\n                      setSelectedPageId(selectedPageId === page.page ? null : page.page);\n                    }}\n                  >\n                    {editingPageId === page.page ? (\n                      <div className=\"p-8 space-y-6\">\n                        <div>\n                          <Label>Page Title</Label>\n                          <Input\n                            defaultValue={page.title}\n                            onChange={(e) => {\n                              const updatedPages = formMetadata.pages.map(p => \n                                p.page === page.page ? { ...p, title: e.target.value } : p\n                              );\n                              onFormMetadataChange({ pages: updatedPages });\n                            }}\n                          />\n                        </div>\n                        <div>\n                          <Label>Description</Label>\n                          <Textarea\n                            defaultValue={page.description || \"\"}\n                            onChange={(e) => {\n                              const updatedPages = formMetadata.pages.map(p => \n                                p.page === page.page ? { ...p, description: e.target.value } : p\n                              );\n                              onFormMetadataChange({ pages: updatedPages });\n                            }}\n                          />\n                        </div>\n                        <div className=\"flex items-center gap-3\">\n                          <Button onClick={() => setEditingPageId(null)}>Done</Button>\n                          <Button variant=\"outline\" onClick={() => setEditingPageId(null)}>\n                            Cancel\n                          </Button>\n                        </div>\n                      </div>\n                    ) : (\n                      <div className=\"p-4\">\n                        <div className=\"flex items-start space-x-3 mb-3\">\n                          <FileText\n                            className={cn(\n                              \"h-5 w-5 mt-0.5\",\n                              selectedPageId === page.page\n                                ? \"text-primary\"\n                                : \"text-muted-foreground\"\n                            )}\n                          />\n                          <div className=\"flex-1 min-w-0\">\n                            <div\n                              className={cn(\n                                \"font-medium text-base truncate\",\n                                selectedPageId === page.page && \"text-primary\"\n                              )}\n                            >\n                              {page.title}\n                            </div>\n                            {page.description && (\n                              <div className=\"text-sm text-muted-foreground line-clamp-2\">{page.description}</div>\n                            )}\n                             <div className=\"text-xs text-muted-foreground mt-1\">\n                               {getFieldsByPage(page.page).length} fields\n                             </div>\n                          </div>\n                        </div>\n                        <div className=\"flex items-center justify-end space-x-1\">\n                          <Button\n                            variant=\"ghost\"\n                            size=\"sm\"\n                            onClick={(e) => {\n                              e.stopPropagation();\n                              setEditingPageId(page.page);\n                            }}\n                          >\n                            <Edit className=\"h-3 w-3\" />\n                          </Button>\n                          {formMetadata.pages.length > 1 && (\n                            <Button\n                              variant=\"ghost\"\n                              size=\"sm\"\n                              onClick={(e) => {\n                                e.stopPropagation();\n                                if (\n                                  confirm(\n                                    `Delete ${page.title}? Fields on this page will be moved to Page 1.`\n                                  )\n                                ) {\n                                  const updatedPages = formMetadata.pages\n                                    .filter((p) => p.page !== page.page)\n                                    .map((p, index) => ({ ...p, page: index + 1 }));\n                                  onFormMetadataChange({ pages: updatedPages });\n                                  if (selectedPageId === page.page) {\n                                    setSelectedPageId(null);\n                                  }\n                                }\n                              }}\n                            >\n                              <Trash2 className=\"h-3 w-3\" />\n                            </Button>\n                          )}\n                        </div>\n                      </div>\n                    )}\n                  </div>\n                ))}\n              </div>\n            </CollapsibleSection>\n          )}\n\n          {/* Tab Management */}\n          {formMetadata.layoutType === \"tabs\" && (\n            <CollapsibleSection \n              title={`Tabs (${formMetadata.tabs.length})`}\n              className=\"space-y-4\"\n            >\n              <div className=\"flex items-center justify-between mb-4\">\n                {selectedTabId && (\n                  <span className=\"text-sm text-primary\">\n                    Tab {selectedTabId} selected\n                  </span>\n                )}\n                <Button\n                  onClick={() => {\n                    const newTabId = `tab_${Date.now()}`;\n                    const newTabs = [...formMetadata.tabs, {\n                      id: newTabId,\n                      label: `Tab ${formMetadata.tabs.length + 1}`,\n                      description: \"\",\n                    }];\n                    onFormMetadataChange({ tabs: newTabs });\n                    setEditingTabId(newTabId);\n                  }}\n                >\n                  <Plus className=\"h-4 w-4 mr-2\" />\n                  Add Tab\n                </Button>\n              </div>\n              <div className=\"grid grid-cols-3 gap-4\">\n                  {formMetadata.tabs.map((tab) => (\n                    <div\n                      key={tab.id}\n                      className={cn(\n                        \"border rounded-lg transition-all cursor-pointer bg-muted/30\",\n                        selectedTabId === tab.id\n                          ? \"border-primary bg-primary/5 ring-1 ring-primary/30\"\n                          : \"border-border hover:bg-muted/50\",\n                        editingTabId === tab.id && \"ring-2 ring-primary/20\"\n                      )}\n                      onClick={() => {\n                        if (editingTabId === tab.id) return;\n                        setSelectedTabId(tab.id);\n                      }}\n                    >\n                      {editingTabId === tab.id ? (\n                        <div className=\"p-8 space-y-6\">\n                          <div>\n                            <Label>Tab Label</Label>\n                            <Input\n                              defaultValue={tab.label}\n                              onChange={(e) => {\n                                const updatedTabs = formMetadata.tabs.map(t => \n                                  t.id === tab.id ? { ...t, label: e.target.value } : t\n                                );\n                                onFormMetadataChange({ tabs: updatedTabs });\n                              }}\n                            />\n                          </div>\n                          <div>\n                            <Label>Description</Label>\n                            <Textarea\n                              defaultValue={tab.description || \"\"}\n                              onChange={(e) => {\n                                const updatedTabs = formMetadata.tabs.map(t => \n                                  t.id === tab.id ? { ...t, description: e.target.value } : t\n                                );\n                                onFormMetadataChange({ tabs: updatedTabs });\n                              }}\n                            />\n                          </div>\n                          <div className=\"flex items-center gap-3\">\n                            <Button onClick={() => setEditingTabId(null)}>Done</Button>\n                            <Button variant=\"outline\" onClick={() => setEditingTabId(null)}>\n                              Cancel\n                            </Button>\n                          </div>\n                        </div>\n                      ) : (\n                        <div className=\"flex items-center justify-between p-8\">\n                          <div className=\"flex items-center space-x-4\">\n                            <FileText\n                              className={cn(\n                                \"h-5 w-5\",\n                                selectedTabId === tab.id\n                                  ? \"text-primary\"\n                                  : \"text-muted-foreground\"\n                              )}\n                            />\n                            <div>\n                              <div\n                                className={cn(\n                                  \"font-medium text-lg\",\n                                  selectedTabId === tab.id && \"text-primary\"\n                                )}\n                              >\n                                {tab.label}\n                              </div>\n                              {tab.description && (\n                                <div className=\"text-muted-foreground\">{tab.description}</div>\n                              )}\n                               <div className=\"text-sm text-muted-foreground\">\n                                 {getFieldsByTab(tab.id).length} fields\n                               </div>\n                            </div>\n                          </div>\n                          <div className=\"flex items-center space-x-2\">\n                            <Button\n                              variant=\"ghost\"\n                              onClick={(e) => {\n                                e.stopPropagation();\n                                setEditingTabId(tab.id);\n                              }}\n                            >\n                              <Edit className=\"h-4 w-4\" />\n                            </Button>\n                            {formMetadata.tabs.length > 1 && (\n                              <Button\n                                variant=\"ghost\"\n                                onClick={(e) => {\n                                  e.stopPropagation();\n                                  if (\n                                    confirm(\n                                      `Delete ${tab.label}? Fields in this tab will be moved to the first tab.`\n                                    )\n                                  ) {\n                                    const updatedTabs = formMetadata.tabs.filter(t => t.id !== tab.id);\n                                    onFormMetadataChange({ tabs: updatedTabs });\n                                    if (selectedTabId === tab.id) {\n                                      setSelectedTabId(null);\n                                    }\n                                  }\n                                }}\n                              >\n                                <Trash2 className=\"h-4 w-4\" />\n                              </Button>\n                            )}\n                          </div>\n                        </div>\n                      )}\n                    </div>\n                  ))}\n              </div>\n            </CollapsibleSection>\n          )}\n\n          {/* Fields List */}\n          <CollapsibleSection \n            title={\n              formMetadata.layoutType === \"pages\" && selectedPageId \n                ? `${formMetadata.pages.find((p) => p.page === selectedPageId)?.title} Fields (${fieldsToShow.length})`\n                : formMetadata.layoutType === \"tabs\" && selectedTabId \n                ? `${formMetadata.tabs.find((t) => t.id === selectedTabId)?.label} Fields (${fieldsToShow.length})`\n                : `All Fields (${allFields.length})`\n            }\n            className=\"space-y-4\"\n          >\n            {(selectedPageId || selectedTabId) && (\n              <p className=\"text-sm text-muted-foreground\">\n                {formMetadata.layoutType === \"pages\" \n                  ? \"New fields will be added to this page. Click the page again to deselect.\"\n                  : \"New fields will be added to this tab. Click the tab again to deselect.\"}\n              </p>\n            )}\n            <div>\n              {fieldsToShow.length === 0 ? (\n                <div className=\"text-center py-12 text-muted-foreground\">\n                  <Plus className=\"h-12 w-12 mx-auto mb-4 opacity-50\" />\n                  <p className=\"text-lg\">\n                    {selectedPageId\n                      ? `No fields on this page yet. Add some from the sidebar!`\n                      : selectedTabId\n                      ? `No fields in this tab yet. Add some from the sidebar!`\n                      : `No fields yet. Add some from the sidebar!`}\n                  </p>\n                </div>\n              ) : (\n                <FieldList\n                  key={`${selectedPageId}-${selectedTabId}-${fieldsToShow.length}`}\n                  fields={fieldsToShow}\n                  selectedFieldId={selectedFieldId}\n                  onSelectField={onSelectField}\n                  onDeleteField={onDeleteField}\n                  onDuplicateField={onDuplicateField}\n                />\n              )}\n            </div>\n          </CollapsibleSection>\n        </div>\n      </div>\n\n      {/* Field Configuration Panel */}\n      <ConfiguratorPanel\n        selectedFieldId={selectedFieldId}\n        availablePages={availablePages}\n      />\n    </div>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/tabs/BuilderTabContent.tsx"
    },
    {
      "path": "src/components/formedible/builder/tabs/PreviewTabContent.tsx",
      "content": "\"use client\";\nimport React from \"react\";\nimport { PreviewControls } from \"../preview-controls\";\nimport type { TabContentProps } from \"@/lib/formedible/builder-types\";\n\nexport const PreviewTabContent: React.FC<TabContentProps> = ({\n  getFormConfig,\n}) => {\n  const formConfig = getFormConfig();\n  \n  return (\n    <div className=\"h-full m-0 p-8 overflow-y-auto min-h-0\">\n      <div className=\"max-w-6xl mx-auto\">\n        <div className=\"mb-8\">\n          <h2 className=\"text-2xl font-bold\">Live Preview</h2>\n          <p className=\"text-muted-foreground\">See how your form will look and behave</p>\n        </div>\n        \n        <PreviewControls\n          config={{\n            ...formConfig,\n            pages: formConfig.pages || []\n          }}\n          showModeSelector={false}\n          showDeviceSelector={true}\n        />\n      </div>\n    </div>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/tabs/PreviewTabContent.tsx"
    },
    {
      "path": "src/components/formedible/builder/tabs/CodeTabContent.tsx",
      "content": "\"use client\";\nimport React from \"react\";\nimport { CodeGenerator } from \"../code-generator\";\nimport type { TabContentProps } from \"@/lib/formedible/builder-types\";\n\nexport const CodeTabContent: React.FC<TabContentProps> = ({\n  getFormMetadata,\n  getAllFields,\n}) => {\n  // Get current form metadata and fields when rendering\n  const formMetadata = getFormMetadata();\n  const fields = getAllFields();\n\n  return (\n    <div className=\"h-full m-0 p-8 overflow-y-auto min-h-0\">\n      <div className=\"max-w-6xl mx-auto\">\n        <CodeGenerator\n          formTitle={formMetadata.title}\n          formDescription={formMetadata.description}\n          fields={fields}\n          pages={formMetadata.pages}\n          settings={formMetadata.settings}\n        />\n      </div>\n    </div>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/tabs/CodeTabContent.tsx"
    },
    {
      "path": "src/components/formedible/builder/preview-controls.tsx",
      "content": "\"use client\";\n\nimport React, { useState, useMemo } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { CodeBlock } from \"@/components/ui/code-block\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Monitor, Tablet, Smartphone, Code, Eye } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { FormPreview } from \"./form-preview\";\nimport { generateCodeFromParsedConfig } from \"@/lib/formedible/code-generation\";\nimport type { ParsedFormConfig } from \"@/lib/formedible/parser-types\";\n\nexport type PreviewMode = \"desktop\" | \"tablet\" | \"mobile\";\nexport type ViewMode = \"preview\" | \"code\";\n\ninterface PreviewControlsProps {\n  config: ParsedFormConfig;\n  code?: string; // Deprecated - now generated automatically\n  className?: string;\n  showModeSelector?: boolean;\n  showDeviceSelector?: boolean;\n  onFormSubmit?: (formData: Record<string, unknown>) => void;\n}\n\nexport const PreviewControls: React.FC<PreviewControlsProps> = ({\n  config,\n  code, // Deprecated but kept for compatibility\n  className,\n  showModeSelector = true,\n  showDeviceSelector = true,\n  onFormSubmit,\n}) => {\n  const [previewMode, setPreviewMode] = useState<PreviewMode>(\"desktop\");\n  const [viewMode, setViewMode] = useState<ViewMode>(\"preview\");\n\n  // Generate full React/TypeScript code from parsed config\n  const generatedCode = useMemo(() => {\n    try {\n      if (!config || !config.fields || config.fields.length === 0) {\n        return code || \"// No form configuration available\";\n      }\n      \n      const result = generateCodeFromParsedConfig(config);\n      return result.fullCode;\n    } catch (error) {\n      console.error('Failed to generate code:', error);\n      return code || \"// Error generating code\";\n    }\n  }, [config, code]);\n\n  const deviceModes: { mode: PreviewMode; icon: React.ReactNode; label: string }[] = [\n    { mode: \"desktop\", icon: <Monitor className=\"h-4 w-4\" />, label: \"Desktop\" },\n    { mode: \"tablet\", icon: <Tablet className=\"h-4 w-4\" />, label: \"Tablet\" },\n    { mode: \"mobile\", icon: <Smartphone className=\"h-4 w-4\" />, label: \"Mobile\" },\n  ];\n\n  const viewModes: { mode: ViewMode; icon: React.ReactNode; label: string }[] = [\n    { mode: \"preview\", icon: <Eye className=\"h-4 w-4\" />, label: \"Preview\" },\n    { mode: \"code\", icon: <Code className=\"h-4 w-4\" />, label: \"Code\" },\n  ];\n\n  return (\n    <Card className={cn(\"flex flex-col h-full !py-0 !gap-0\", className)}>\n      <CardHeader className=\"px-3 pt-1 pb-0\">\n        <div className=\"flex items-center justify-between\">\n          <CardTitle className=\"flex items-center gap-2\">\n            {viewMode === \"preview\" ? (\n              <Eye className=\"h-5 w-5\" />\n            ) : (\n              <Code className=\"h-5 w-5\" />\n            )}\n            {viewMode === \"preview\" ? \"\" : \"Generated Code\"}\n          </CardTitle>\n          \n          <div className=\"flex items-center gap-2\">\n            {/* View Mode Selector */}\n            {showModeSelector && (\n              <div className=\"flex rounded-md border\">\n                {viewModes.map(({ mode, icon, label }) => (\n                  <Button\n                    key={mode}\n                    variant={viewMode === mode ? \"default\" : \"ghost\"}\n                    size=\"sm\"\n                    onClick={() => setViewMode(mode)}\n                    className=\"h-8 px-3 rounded-none first:rounded-l-md last:rounded-r-md\"\n                  >\n                    {icon}\n                    <span className=\"ml-1 hidden sm:inline\">{label}</span>\n                  </Button>\n                ))}\n              </div>\n            )}\n            \n            {/* Device Mode Selector - only show in preview mode */}\n            {showDeviceSelector && viewMode === \"preview\" && (\n              <div className=\"flex rounded-md border\">\n                {deviceModes.map(({ mode, icon, label }) => (\n                  <Button\n                    key={mode}\n                    variant={previewMode === mode ? \"default\" : \"ghost\"}\n                    size=\"sm\"\n                    onClick={() => setPreviewMode(mode)}\n                    className=\"h-8 px-3 rounded-none first:rounded-l-md last:rounded-r-md\"\n                  >\n                    {icon}\n                    <span className=\"ml-1 hidden sm:inline\">{label}</span>\n                  </Button>\n                ))}\n              </div>\n            )}\n          </div>\n        </div>\n      </CardHeader>\n      \n      <CardContent className=\"flex-1 overflow-hidden px-3 pt-0\">\n        {viewMode === \"preview\" ? (\n          <div\n            className={cn(\n              \"h-full overflow-y-auto transition-all\",\n              previewMode === \"mobile\"\n                ? \"max-w-sm mx-auto\"\n                : previewMode === \"tablet\"\n                ? \"max-w-2xl mx-auto\"\n                : \"max-w-full\"\n            )}\n          >\n            <FormPreview config={config} />\n          </div>\n        ) : (\n          <div className=\"h-full overflow-y-auto\">\n            {generatedCode ? (\n              <CodeBlock\n                code={generatedCode}\n                language=\"tsx\"\n                showLineNumbers={true}\n                showCopyButton={true}\n                className=\"h-full\"\n                darkMode={true}\n                scrollable={true}\n                maxHeight=\"100%\"\n              />\n            ) : (\n              <div className=\"flex items-center justify-center h-full text-muted-foreground\">\n                No code available\n              </div>\n            )}\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  );\n};",
      "type": "registry:component",
      "target": "components/formedible/builder/preview-controls.tsx"
    },
    {
      "path": "src/lib/utils.ts",
      "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}",
      "type": "registry:lib",
      "target": "lib/utils.ts"
    },
    {
      "path": "src/components/ui/code-block.tsx",
      "content": "\"use client\";\n\nimport React, { useState, useEffect } from \"react\";\nimport { Highlight, themes } from \"prism-react-renderer\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport { Copy, Check } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\n/**\n * Unified CodeBlock component with syntax highlighting, copy functionality, and package manager tabs\n * \n * Features:\n * - Syntax highlighting using Prism.js with oneDark theme\n * - Floating copy button with animation feedback\n * - Optional line numbers\n * - Package manager tabs for installation commands (npx, pnpm, yarn, bunx)\n * - Optional title header\n * - Responsive design with proper overflow handling\n */\n\ninterface CodeBlockProps {\n  code: string;\n  language?: string;\n  showLineNumbers?: boolean;\n  showCopyButton?: boolean;\n  showPackageManagerTabs?: boolean;\n  className?: string;\n  title?: string;\n  darkMode?: boolean;\n  scrollable?: boolean;\n  maxHeight?: string;\n}\n\n// Copy Button Component\nconst CopyButton: React.FC<{ text: string; className?: string }> = ({\n  text,\n  className = \"\",\n}) => {\n  const [copied, setCopied] = useState(false);\n\n  const copyToClipboard = async () => {\n    try {\n      await navigator.clipboard.writeText(text);\n      setCopied(true);\n      toast.success(\"Copied to clipboard!\");\n      setTimeout(() => setCopied(false), 2000);\n    } catch (err) {\n      toast.error(\"Failed to copy\");\n    }\n  };\n\n  return (\n    <motion.button\n      onClick={copyToClipboard}\n      className={`relative inline-flex items-center justify-center p-2 rounded-md bg-muted/80 hover:bg-muted text-muted-foreground hover:text-foreground backdrop-blur-sm transition-colors shadow-lg ${className}`}\n      whileHover={{ scale: 1.05 }}\n      whileTap={{ scale: 0.95 }}\n    >\n      <AnimatePresence mode=\"wait\">\n        {copied ? (\n          <motion.div\n            key=\"check\"\n            initial={{ scale: 0 }}\n            animate={{ scale: 1 }}\n            exit={{ scale: 0 }}\n          >\n            <Check className=\"w-4 h-4 text-accent\" />\n          </motion.div>\n        ) : (\n          <motion.div\n            key=\"copy\"\n            initial={{ scale: 0 }}\n            animate={{ scale: 1 }}\n            exit={{ scale: 0 }}\n          >\n            <Copy className=\"w-4 h-4\" />\n          </motion.div>\n        )}\n      </AnimatePresence>\n    </motion.button>\n  );\n};\n\n// Function to load external CSS theme\nconst loadPrismTheme = (themeUrl: string, themeId: string) => {\n  // Remove existing theme if present\n  const existingLink = document.getElementById(themeId);\n  if (existingLink) {\n    existingLink.remove();\n  }\n  \n  // Add new theme\n  const link = document.createElement('link');\n  link.id = themeId;\n  link.rel = 'stylesheet';\n  link.href = themeUrl;\n  document.head.appendChild(link);\n};\n\n// Empty theme object to disable built-in styling and let external CSS take control\nconst emptyTheme = { plain: {}, styles: [] };\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({\n  code,\n  language = \"tsx\",\n  showLineNumbers = false,\n  showCopyButton = true,\n  showPackageManagerTabs = false,\n  className = \"\",\n  title,\n  darkMode = false,\n  scrollable = false,\n  maxHeight,\n}) => {\n  const [selectedPM, setSelectedPM] = useState(\"npx\");\n  \n  // Load appropriate Gruvbox theme based on darkMode prop\n  useEffect(() => {\n    if (darkMode) {\n      loadPrismTheme(\n        'https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-gruvbox-dark.min.css',\n        'prism-gruvbox-theme'\n      );\n    } else {\n      loadPrismTheme(\n        'https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-gruvbox-light.min.css',\n        'prism-gruvbox-theme'\n      );\n    }\n  }, [darkMode]);\n  \n  const packageManagers = {\n    npx: code,\n    pnpm: code.replace(\"npx shadcn@latest\", \"pnpm dlx shadcn@latest\"),\n    yarn: code.replace(\"npx shadcn@latest\", \"yarn dlx shadcn@latest\"),\n    bunx: code.replace(\"npx shadcn@latest\", \"bunx --bun shadcn@latest\"),\n  };\n\n  const currentCode = showPackageManagerTabs ? packageManagers[selectedPM as keyof typeof packageManagers] : code;\n\n  return (\n    <div className={`relative ${className}`}>\n      {title && (\n        <div className=\"bg-muted text-muted-foreground px-4 py-2 text-sm font-medium rounded-t-lg border-b\">\n          {title}\n        </div>\n      )}\n      \n      {showPackageManagerTabs && (\n        <div className=\"flex gap-1 mb-2\">\n          {Object.keys(packageManagers).map((pm) => (\n            <button\n              key={pm}\n              onClick={() => setSelectedPM(pm)}\n              className={`px-3 py-1 text-xs rounded-t-md transition-colors ${\n                selectedPM === pm\n                  ? \"bg-primary text-primary-foreground\"\n                  : \"bg-secondary text-secondary-foreground hover:bg-secondary/80\"\n              }`}\n            >\n              {pm}\n            </button>\n          ))}\n        </div>\n      )}\n      \n      <div className=\"relative group\">\n        <Highlight\n          theme={emptyTheme}\n          code={currentCode.trim()}\n          language={language as any}\n        >\n          {({ className: highlightClassName, style, tokens, getLineProps, getTokenProps }) => (\n            <pre \n              className={`${highlightClassName} p-4 rounded-lg font-mono text-sm overflow-x-auto ${\n                showPackageManagerTabs ? 'rounded-tl-none' : ''\n              } ${title ? 'rounded-t-none' : ''} ${\n                scrollable ? 'overflow-y-auto' : ''\n              }`}\n              style={{\n                ...style,\n                ...(scrollable && maxHeight && { maxHeight })\n              }}\n            >\n              {tokens.map((line, i) => (\n                <div key={i} {...getLineProps({ line })} className={showLineNumbers ? \"table-row\" : \"\"}>\n                  {showLineNumbers && (\n                     <span className=\"table-cell text-right pr-4 text-muted-foreground select-none text-xs\">                      {i + 1}\n                    </span>\n                  )}\n                  <span className={showLineNumbers ? \"table-cell\" : \"\"}>\n                    {line.map((token, key) => (\n                      <span key={key} {...getTokenProps({ token })} />\n                    ))}\n                  </span>\n                </div>\n              ))}\n            </pre>\n          )}\n        </Highlight>\n        \n        {showCopyButton && (\n          <div className=\"absolute top-3 right-3 opacity-0 group-hover:opacity-100 transition-opacity duration-200\">\n            <CopyButton text={currentCode} />\n          </div>\n        )}\n      </div>\n    </div>\n  );\n};",
      "type": "registry:component",
      "target": "components/ui/code-block.tsx"
    },
    {
      "path": "src/components/formedible/builder/form-preview-base.tsx",
      "content": "\"use client\";\n\nimport { useMemo } from \"react\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Alert, AlertDescription } from \"@/components/ui/alert\";\nimport { PreviewControls } from \"./preview-controls\";\nimport { FormedibleParser, type UseFormedibleOptions, type FieldConfig } from \"@/lib/formedible/formedible-parser\";\nimport { Eye, AlertCircle, FileText } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\n// Use formedible's UseFormedibleOptions directly - no more DRY violations!\n\nexport interface FormPreviewBaseProps {\n  formCode?: string;\n  isStreaming?: boolean;\n  onFormSubmit?: (formData: Record<string, unknown>) => void;\n  className?: string;\n  title?: string;\n  emptyStateMessage?: string;\n}\n\nexport function FormPreviewBase({ \n  formCode,\n  isStreaming = false, \n  onFormSubmit, \n  className,\n  title = \"Form Preview\",\n  emptyStateMessage = \"No form generated yet. The preview will appear here once a form is created.\"\n}: FormPreviewBaseProps) {\n  \n  const parsedConfig = useMemo<UseFormedibleOptions<Record<string, unknown>> | null>(() => {\n    if (!formCode) return null;\n    \n    try {\n      console.log('Attempting to parse form code:', {\n        codeLength: formCode.length,\n        codePreview: formCode.substring(0, 200) + '...'\n      });\n      \n      const parsed: UseFormedibleOptions<Record<string, unknown>> = FormedibleParser.parse(formCode);\n      \n      console.log('Successfully parsed form config:', {\n        fieldsCount: parsed.fields?.length || 0,\n        hasSchema: !!parsed.schema\n      });\n      \n      // Return the parsed config directly - no conversion needed!\n      return parsed;\n    } catch (error) {\n      console.error('Error parsing form configuration:', {\n        error: error instanceof Error ? error.message : String(error),\n        formCodePreview: formCode.substring(0, 500)\n      });\n      return null;\n    }\n  }, [formCode]);\n\n  if (!formCode && !isStreaming) {\n    return (\n      <Card className={cn(\"flex flex-col h-full\", className)}>\n        <CardContent className=\"flex-1 flex items-center justify-center\">\n          <div className=\"text-center text-muted-foreground\">\n            <FileText className=\"h-12 w-12 mb-4 opacity-50 mx-auto\" />\n            <h3 className=\"text-lg font-medium mb-2\">No Form Available</h3>\n            <p className=\"text-sm max-w-md\">\n              {emptyStateMessage}\n            </p>\n          </div>\n        </CardContent>\n      </Card>\n    );\n  }\n\n  return (\n    <Card className={cn(\"flex flex-col h-full\", className)}>\n      \n      <CardContent className={cn(\"flex-1 overflow-hidden\", title ? \"p-0\" : \"p-0\")}>\n        <div className=\"h-full\">\n          {isStreaming && !formCode && (\n            <div className=\"p-3\">\n              <Alert>\n                <AlertCircle className=\"h-4 w-4\" />\n                <AlertDescription>\n                  Form is being generated... Please wait for completion.\n                </AlertDescription>\n              </Alert>\n            </div>\n          )}\n          \n          {formCode && parsedConfig && (\n            <PreviewControls\n              config={parsedConfig}\n              code={formCode}\n              showModeSelector={true}\n              showDeviceSelector={true}\n              onFormSubmit={onFormSubmit}\n              className=\"border-0 h-full\"\n            />\n          )}\n\n          {formCode && !parsedConfig && (\n            <div className=\"p-3\">\n              <Alert variant=\"destructive\">\n                <AlertCircle className=\"h-4 w-4\" />\n                <AlertDescription>\n                  Failed to parse the form configuration. The form may have invalid syntax.\n                </AlertDescription>\n              </Alert>\n            </div>\n          )}\n        </div>\n      </CardContent>\n    </Card>\n  );\n}",
      "type": "registry:component",
      "target": "components/formedible/builder/form-preview-base.tsx"
    },
    {
      "path": "src/lib/formedible/code-generation.ts",
      "content": "\"use client\";\n\nimport type { FieldConfig, UseFormedibleOptions } from \"./types\";\nimport { resolveDynamicText } from \"./template-interpolation\";\n\nexport interface CodeGenerationOptions {\n  title?: string;\n  description?: string;\n  fields: FieldConfig[];\n  pages?: Array<{ page: number; title: string; description?: string }>;\n  settings?: {\n    submitLabel?: string;\n    nextLabel?: string;\n    previousLabel?: string;\n    showProgress?: boolean;\n  };\n  tabs?: Array<{ id: string; title: string; description?: string }>;\n}\n\nexport interface GeneratedCodeResult {\n  fullCode: string;\n  formConfig: string;\n  schemaCode: string;\n}\n\n/**\n * Generates complete React/TypeScript code for a formedible form\n */\nexport function generateFormCode(options: CodeGenerationOptions): GeneratedCodeResult {\n  const {\n    title = \"\",\n    description = \"\",\n    fields = [],\n    pages = [],\n    settings = {},\n    tabs = []\n  } = options;\n\n  if (fields.length === 0) {\n    const emptyCode = `import { useFormedible } from 'formedible';\nimport { z } from 'zod';\n\nexport const MyForm = () => {\n  const { Form } = useFormedible({\n    schema: z.object({}),\n    fields: [],\n    formOptions: {\n      onSubmit: async ({ value }) => {\n        console.log('Form submitted:', value);\n      },\n    },\n  });\n  \n  return <Form />;\n};`;\n\n    return {\n      fullCode: emptyCode,\n      formConfig: \"{}\",\n      schemaCode: \"z.object({})\"\n    };\n  }\n\n  // Build form configuration\n  const formConfig = {\n    ...(title && { title }),\n    ...(description && { description }),\n    schema: \"z.object(schemaFields)\",\n    fields: fields.map((field) => {\n      const mappedField: any = {\n        name: field.name,\n        type: field.type,\n        label: resolveDynamicText(field.label, {}) || field.label,\n        ...(field.page && { page: field.page }),\n        ...(field.tab && { tab: field.tab }),\n        ...(field.group && { group: field.group }),\n        ...(field.section && { section: field.section }),\n        ...(field.required && { required: field.required }),\n      };\n\n      // Add optional properties if they exist\n      if (field.placeholder) mappedField.placeholder = resolveDynamicText(field.placeholder, {}) || field.placeholder;\n      if (field.description) mappedField.description = resolveDynamicText(field.description, {}) || field.description;\n      if (field.help) mappedField.help = field.help;\n      if (field.inlineValidation) mappedField.inlineValidation = field.inlineValidation;\n      if (field.options) mappedField.options = field.options;\n      if (field.arrayConfig) mappedField.arrayConfig = field.arrayConfig;\n      if (field.objectConfig) mappedField.objectConfig = field.objectConfig;\n      if (field.datalist) mappedField.datalist = field.datalist;\n      if (field.multiSelectConfig) mappedField.multiSelectConfig = field.multiSelectConfig;\n      if (field.colorConfig) mappedField.colorConfig = field.colorConfig;\n      if (field.ratingConfig) mappedField.ratingConfig = field.ratingConfig;\n      if (field.phoneConfig) mappedField.phoneConfig = field.phoneConfig;\n      if (field.min !== undefined) mappedField.min = field.min;\n      if (field.max !== undefined) mappedField.max = field.max;\n      if (field.step !== undefined) mappedField.step = field.step;\n\n      return mappedField;\n    }),\n    ...(pages && pages.length > 1 && { pages }),\n    ...(tabs && tabs.length > 1 && { tabs }),\n    ...(settings.submitLabel && { submitLabel: settings.submitLabel }),\n    ...(settings.nextLabel && { nextLabel: settings.nextLabel }),\n    ...(settings.previousLabel && { previousLabel: settings.previousLabel }),\n    ...(settings.showProgress && {\n      progress: { showSteps: true, showPercentage: true }\n    }),\n    formOptions: {\n      onSubmit: \"async ({ value }) => {\\n      console.log('Form submitted:', value);\\n      // Handle form submission here\\n    }\",\n    },\n  };\n\n  // Generate schema fields\n  const schemaFieldsCode = fields.map((field) => {\n    let fieldSchema = \"\";\n    \n    switch (field.type) {\n      case \"number\":\n      case \"slider\":\n      case \"rating\":\n        fieldSchema = \"z.number()\";\n        break;\n      case \"checkbox\":\n      case \"switch\":\n        fieldSchema = \"z.boolean()\";\n        break;\n      case \"date\":\n        fieldSchema = \"z.string()\";\n        break;\n      case \"multiSelect\":\n      case \"array\":\n        fieldSchema = \"z.array(z.string())\";\n        break;\n      case \"object\":\n        fieldSchema = \"z.object({}).passthrough()\";\n        break;\n      default:\n        fieldSchema = \"z.string()\";\n    }\n\n    if (field.required) {\n      if (field.type === \"checkbox\" || field.type === \"switch\") {\n        fieldSchema = `${fieldSchema}.refine((val) => val === true, {\n    message: '${field.label || field.name} is required',\n  })`;\n      } else if (field.type !== \"number\" && field.type !== \"slider\" && field.type !== \"rating\") {\n        fieldSchema = `${fieldSchema}.min(1, '${field.label || field.name} is required')`;\n      }\n    } else {\n      fieldSchema = `${fieldSchema}.optional()`;\n    }\n\n    return `  ${field.name}: ${fieldSchema}`;\n  }).join(\",\\n\");\n\n  const configString = JSON.stringify(formConfig, null, 2)\n    .replace('\"z.object(schemaFields)\"', 'z.object(schemaFields)')\n    .replace('\"async ({ value }) => {\\\\n      console.log(\\'Form submitted:\\', value);\\\\n      // Handle form submission here\\\\n    }\"', \n      'async ({ value }) => {\\n      console.log(\\'Form submitted:\\', value);\\n      // Handle form submission here\\n    }');\n\n  const fullCode = `import { useFormedible } from 'formedible';\nimport { z } from 'zod';\n\nexport const MyForm = () => {\n  // Define the schema for form validation\n  const schemaFields = {\n${schemaFieldsCode}\n  };\n\n  const formConfig = ${configString};\n\n  const { Form } = useFormedible(formConfig);\n  \n  return <Form />;\n};`;\n\n  return {\n    fullCode,\n    formConfig: configString,\n    schemaCode: `z.object({\\n${schemaFieldsCode}\\n})`\n  };\n}\n\n/**\n * Generates code from a parsed formedible configuration (for AI builder)\n */\nexport function generateCodeFromParsedConfig(config: UseFormedibleOptions<any>): GeneratedCodeResult {\n  return generateFormCode({\n    title: config.title,\n    description: config.description,\n    fields: config.fields || [],\n    pages: config.pages?.map(page => ({\n      page: page.page,\n      title: page.title || `Page ${page.page}`,\n      description: page.description\n    })),\n    tabs: config.tabs?.map(tab => ({\n      id: tab.id,\n      title: tab.label || tab.id,\n      description: tab.description\n    })),\n    settings: {\n      submitLabel: config.submitLabel,\n      nextLabel: config.nextLabel,\n      previousLabel: config.previousLabel,\n      showProgress: !!config.progress,\n    }\n  });\n}",
      "type": "registry:lib",
      "target": "lib/formedible/code-generation.ts"
    }
  ],
  "type": "registry:block"
}