{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form-builder",
  "title": "FormBuilder",
  "description": "Visual drag-and-drop form builder primitives for BuzzForm v2.",
  "dependencies": [
    "@buildnbuzz/form-core",
    "@buildnbuzz/form-react",
    "@buildnbuzz/form-builder-core",
    "@buildnbuzz/form-builder-react",
    "@dnd-kit/core",
    "@dnd-kit/sortable",
    "@dnd-kit/utilities",
    "fumadocs-ui",
    "zustand"
  ],
  "registryDependencies": [
    "@buzzform/all",
    "alert",
    "badge",
    "button",
    "card",
    "checkbox",
    "collapsible",
    "dialog",
    "empty",
    "field",
    "input",
    "scroll-area",
    "select",
    "separator",
    "sheet",
    "sidebar",
    "sonner",
    "spinner",
    "switch",
    "tabs",
    "textarea",
    "tooltip"
  ],
  "files": [
    {
      "path": "registry/shadcn/builder/canvas/canvas-toolbar.tsx",
      "content": "\"use client\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n  TooltipProvider,\n} from \"@/components/ui/tooltip\";\nimport { cn } from \"@/lib/utils\";\nimport { useBuilderStore, useUndoRedo } from \"@buildnbuzz/form-builder-react\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\n\n/**\n * Floating canvas toolbar at bottom-center of the canvas area.\n * Provides undo/redo, mode toggle, viewport switching, and zoom controls.\n */\nexport function CanvasToolbar() {\n  const viewport = useBuilderStore((state) => state.viewport);\n  const setViewport = useBuilderStore((state) => state.setViewport);\n  const zoom = useBuilderStore((state) => state.zoom);\n  const setZoom = useBuilderStore((state) => state.setZoom);\n  const mode = useBuilderStore((state) => state.mode);\n  const setMode = useBuilderStore((state) => state.setMode);\n  const { undo, redo, canUndo, canRedo } = useUndoRedo();\n\n  const isPreview = mode === \"preview\";\n\n  return (\n    <div className=\"absolute bottom-6 left-1/2 -translate-x-1/2 z-20 flex items-center gap-1 p-1.5 rounded-full border border-border/50 bg-card/80 backdrop-blur-xl shadow-xl shadow-black/5 supports-backdrop-filter:bg-card/40\">\n      <TooltipProvider delay={0}>\n        {/* Undo/Redo */}\n        <div className=\"flex items-center gap-0.5\">\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  onClick={() => undo()}\n                  disabled={!canUndo}\n                  className={cn(\n                    \"h-8 w-8 rounded-full text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                    !canUndo && \"opacity-50 cursor-not-allowed\",\n                  )}\n                >\n                  <IconPlaceholder\n                    lucide=\"Undo\"\n                    hugeicons=\"UndoIcon\"\n                    tabler=\"IconArrowBackUp\"\n                    phosphor=\"ArrowCounterClockwise\"\n                    remixicon=\"RiArrowGoBackLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              <p className=\"text-xs font-medium\">Undo</p>\n              <p className=\"text-[10px] text-muted-foreground\">Ctrl+Z</p>\n            </TooltipContent>\n          </Tooltip>\n\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  onClick={() => redo()}\n                  disabled={!canRedo}\n                  className={cn(\n                    \"h-8 w-8 rounded-full text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                    !canRedo && \"opacity-50 cursor-not-allowed\",\n                  )}\n                >\n                  <IconPlaceholder\n                    lucide=\"Redo\"\n                    hugeicons=\"RedoIcon\"\n                    tabler=\"IconArrowForwardUp\"\n                    phosphor=\"ArrowClockwise\"\n                    remixicon=\"RiArrowGoForwardLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              <p className=\"text-xs font-medium\">Redo</p>\n              <p className=\"text-[10px] text-muted-foreground\">Ctrl+Shift+Z</p>\n            </TooltipContent>\n          </Tooltip>\n        </div>\n\n        <div className=\"mx-1.5 h-6 w-px bg-border/50\" />\n\n        {/* Mode Toggle */}\n        <Tooltip>\n          <TooltipTrigger\n            render={\n              <Button\n                variant={isPreview ? \"default\" : \"ghost\"}\n                size=\"icon\"\n                onClick={() => setMode(isPreview ? \"edit\" : \"preview\")}\n                className={cn(\n                  \"h-8 w-8 rounded-full\",\n                  !isPreview &&\n                    \"text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                )}\n              >\n                {isPreview ? (\n                  <IconPlaceholder\n                    lucide=\"Pencil\"\n                    hugeicons=\"PencilEdit01Icon\"\n                    tabler=\"IconPencil\"\n                    phosphor=\"Pencil\"\n                    remixicon=\"RiPencilLine\"\n                    size={16}\n                  />\n                ) : (\n                  <IconPlaceholder\n                    lucide=\"Eye\"\n                    hugeicons=\"ViewIcon\"\n                    tabler=\"IconEye\"\n                    phosphor=\"Eye\"\n                    remixicon=\"RiEyeLine\"\n                    size={16}\n                  />\n                )}\n              </Button>\n            }\n          />\n          <TooltipContent side=\"top\" sideOffset={8}>\n            <p className=\"text-xs font-medium\">\n              {isPreview ? \"Back to Edit Mode\" : \"Preview Form\"}\n            </p>\n          </TooltipContent>\n        </Tooltip>\n\n        <div className=\"mx-1.5 h-6 w-px bg-border/50\" />\n\n        {/* Viewport Toggles */}\n        <div className=\"flex items-center gap-0.5\">\n          {/* Desktop */}\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant={viewport === \"desktop\" ? \"default\" : \"ghost\"}\n                  size=\"icon\"\n                  onClick={() => setViewport(\"desktop\")}\n                  className={cn(\n                    \"h-8 w-8 rounded-full\",\n                    viewport !== \"desktop\" &&\n                      \"text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                  )}\n                >\n                  <IconPlaceholder\n                    lucide=\"Monitor\"\n                    hugeicons=\"ComputerIcon\"\n                    tabler=\"IconDeviceDesktop\"\n                    phosphor=\"Monitor\"\n                    remixicon=\"RiComputerLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              <p className=\"text-xs font-medium\">Desktop (100%)</p>\n            </TooltipContent>\n          </Tooltip>\n\n          {/* Tablet */}\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant={viewport === \"tablet\" ? \"default\" : \"ghost\"}\n                  size=\"icon\"\n                  onClick={() => setViewport(\"tablet\")}\n                  className={cn(\n                    \"h-8 w-8 rounded-full\",\n                    viewport !== \"tablet\" &&\n                      \"text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                  )}\n                >\n                  <IconPlaceholder\n                    lucide=\"Tablet\"\n                    hugeicons=\"Tablet01Icon\"\n                    tabler=\"IconDeviceTablet\"\n                    phosphor=\"DeviceTabletIcon\"\n                    remixicon=\"RiTabletLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              <p className=\"text-xs font-medium\">Tablet (768px)</p>\n            </TooltipContent>\n          </Tooltip>\n\n          {/* Mobile */}\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant={viewport === \"mobile\" ? \"default\" : \"ghost\"}\n                  size=\"icon\"\n                  onClick={() => setViewport(\"mobile\")}\n                  className={cn(\n                    \"h-8 w-8 rounded-full\",\n                    viewport !== \"mobile\" &&\n                      \"text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                  )}\n                >\n                  <IconPlaceholder\n                    lucide=\"Smartphone\"\n                    hugeicons=\"SmartPhone01Icon\"\n                    tabler=\"IconDeviceMobile\"\n                    phosphor=\"DeviceMobile\"\n                    remixicon=\"RiSmartphoneLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              <p className=\"text-xs font-medium\">Mobile (375px)</p>\n            </TooltipContent>\n          </Tooltip>\n        </div>\n\n        <div className=\"mx-1.5 h-6 w-px bg-border/50\" />\n\n        {/* Zoom Controls */}\n        <div className=\"flex items-center gap-0.5\">\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  className=\"h-8 w-8 rounded-full text-muted-foreground hover:text-foreground hover:bg-muted/50\"\n                  onClick={() => setZoom(zoom - 0.1)}\n                >\n                  <IconPlaceholder\n                    lucide=\"Minus\"\n                    hugeicons=\"MinusSignIcon\"\n                    tabler=\"IconMinus\"\n                    phosphor=\"Minus\"\n                    remixicon=\"RiSubtractLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              Zoom Out\n            </TooltipContent>\n          </Tooltip>\n\n          <div className=\"flex items-center justify-center min-w-12 px-1 text-xs font-semibold tabular-nums text-muted-foreground select-none\">\n            {Math.round(zoom * 100)}%\n          </div>\n\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  className=\"h-8 w-8 rounded-full text-muted-foreground hover:text-foreground hover:bg-muted/50\"\n                  onClick={() => setZoom(zoom + 0.1)}\n                >\n                  <IconPlaceholder\n                    lucide=\"Plus\"\n                    hugeicons=\"Add01Icon\"\n                    tabler=\"IconPlus\"\n                    phosphor=\"Plus\"\n                    remixicon=\"RiAddLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              Zoom In\n            </TooltipContent>\n          </Tooltip>\n\n          {/* Reset Zoom */}\n          <div className=\"mx-1 h-4 w-px bg-border/50\" />\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  disabled={Math.round(zoom * 100) === 90}\n                  className={cn(\n                    \"h-8 w-8 rounded-full text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n                    Math.round(zoom * 100) === 90 &&\n                      \"opacity-50 cursor-not-allowed\",\n                  )}\n                  onClick={() => setZoom(0.9)}\n                >\n                  <IconPlaceholder\n                    lucide=\"RotateCcw\"\n                    hugeicons=\"ArrowTurnBackwardIcon\"\n                    tabler=\"IconRefresh\"\n                    phosphor=\"ArrowCounterClockwise\"\n                    remixicon=\"RiRefreshLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent side=\"top\" sideOffset={8}>\n              Reset Zoom\n            </TooltipContent>\n          </Tooltip>\n        </div>\n      </TooltipProvider>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/canvas/canvas-toolbar.tsx"
    },
    {
      "path": "registry/shadcn/builder/drag-overlay.tsx",
      "content": "\"use client\";\n\nimport {\n  useBuilderStore,\n  useBuilderContext,\n} from \"@buildnbuzz/form-builder-react\";\nimport { FieldIcon } from \"./field-icon\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Rich drag overlay item that provides visual feedback during DnD.\n * Matches legacy DragOverlayItem but integrates with the new registry pattern.\n */\nexport function DragOverlayItem({\n  activeId,\n  activeData,\n}: {\n  activeId: string;\n  activeData: Record<string, unknown>;\n}) {\n  const { registry } = useBuilderContext();\n  const node = useBuilderStore((s) => s.nodes[activeId]);\n\n  const data = activeData as Record<string, unknown>;\n  const isFromSidebar = data?.from === \"sidebar\";\n  const type = (isFromSidebar ? data?.type : node?.field?.type) as\n    | string\n    | undefined;\n  const entry = type ? registry[type] : null;\n\n  const label =\n    entry?.sidebar?.label ?? (typeof type === \"string\" ? type : \"Field\");\n\n  // Get field name for existing fields\n  let fieldName: string | undefined;\n  if (!isFromSidebar && node && \"name\" in node.field) {\n    fieldName = node.field.name;\n  }\n\n  return (\n    <div\n      className={cn(\n        \"bg-card/95 backdrop-blur-md border-2 shadow-2xl rounded-xl p-3 min-w-[20rem] cursor-grabbing\",\n        \"animate-in fade-in-0 zoom-in-95 duration-150\",\n        isFromSidebar\n          ? \"border-primary/50 shadow-primary/10\"\n          : \"border-border shadow-black/10\",\n      )}\n    >\n      <div className=\"flex items-center gap-3\">\n        {/* Icon container */}\n        <div\n          className={cn(\n            \"p-2.5 rounded-lg flex items-center justify-center\",\n            isFromSidebar\n              ? \"bg-primary/15 text-primary\"\n              : \"bg-muted text-foreground\",\n          )}\n        >\n          {type ? (\n            <FieldIcon type={type} size={20} />\n          ) : (\n            <FieldIcon type=\"text\" size={20} />\n          )}\n        </div>\n\n        {/* Text content */}\n        <div className=\"flex-1 min-w-0 text-left\">\n          <div className=\"text-sm font-semibold text-foreground truncate\">\n            {isFromSidebar ? `New ${label}` : (fieldName ?? label)}\n          </div>\n          <div className=\"text-xs text-muted-foreground flex items-center gap-1.5 whitespace-nowrap\">\n            <FieldIcon\n              type={isFromSidebar ? \"plus\" : \"move\"}\n              size={12}\n            />\n            <div className=\"flex items-center gap-1\">\n              {isFromSidebar ? (\n                <>\n                  Adding new, press\n                  <kbd className=\"inline-flex items-center rounded border border-border bg-muted px-1.5 py-0.5 text-[10px] font-medium text-foreground/80\">\n                    Esc\n                  </kbd>\n                  to cancel\n                </>\n              ) : (\n                \"Moving field\"\n              )}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/drag-overlay.tsx"
    },
    {
      "path": "registry/shadcn/builder/export-sheet.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { DynamicCodeBlock } from \"fumadocs-ui/components/dynamic-codeblock\";\nimport { toast } from \"sonner\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport {\n  Sheet,\n  SheetContent,\n  SheetDescription,\n  SheetHeader,\n  SheetTitle,\n  SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport {\n  generateComponentCode,\n  nodesToFields,\n  toSafeFileName,\n} from \"@buildnbuzz/form-builder-core\";\nimport {\n  useBuilderStore,\n  downloadTextFile,\n} from \"@buildnbuzz/form-builder-react\";\n\nconst starterCommand =\n  \"npx shadcn@latest add https://form.buildnbuzz.com/r/all.json\";\n\nexport function ExportSheet() {\n  const [open, setOpen] = React.useState(false);\n\n  const nodes = useBuilderStore((state) => state.nodes);\n  const rootIds = useBuilderStore((state) => state.rootIds);\n  const formName = useBuilderStore((state) => state.formName);\n  const outputConfig = useBuilderStore((state) => state.outputConfig);\n\n  const componentCode = React.useMemo(() => {\n    if (!open) return \"\";\n    return generateComponentCode(nodes, rootIds, formName, outputConfig);\n  }, [open, nodes, rootIds, formName, outputConfig]);\n\n  const schemaJson = React.useMemo(() => {\n    if (!open) return \"\";\n    const fields = nodesToFields(nodes, rootIds);\n    const schema = {\n      title: formName || \"BuzzForm Export\",\n      fields,\n    };\n    return JSON.stringify(schema, null, 2);\n  }, [open, nodes, rootIds, formName]);\n\n  const downloadSchema = React.useCallback(() => {\n    if (!schemaJson) return;\n    const fileName = `${toSafeFileName(formName)}.json`;\n    downloadTextFile(schemaJson, fileName, \"application/json\");\n    toast.success(\"BuzzForm schema exported\");\n  }, [schemaJson, formName]);\n\n  const downloadCode = React.useCallback(() => {\n    if (!componentCode) return;\n    const fileName = `${toSafeFileName(formName)}.tsx`;\n    downloadTextFile(componentCode, fileName, \"text/plain;charset=utf-8\");\n    toast.success(\"Component code exported\");\n  }, [componentCode, formName]);\n\n  const copyToClipboard = React.useCallback((text: string, label: string) => {\n    navigator.clipboard.writeText(text);\n    toast.success(`${label} copied to clipboard`);\n  }, []);\n\n  return (\n    <Sheet open={open} onOpenChange={setOpen}>\n      <SheetTrigger\n        render={\n          <Button variant=\"outline\" className=\"gap-2\">\n            <IconPlaceholder\n              hugeicons=\"FileExportIcon\"\n              lucide=\"FileDown\"\n              tabler=\"IconFileExport\"\n              phosphor=\"FileArrowDown\"\n              remixicon=\"RiFileDownloadLine\"\n              size={16}\n              strokeWidth={2}\n            />\n            Export\n          </Button>\n        }\n      />\n\n      <SheetContent\n        side=\"right\"\n        className=\"w-full p-0 gap-0 data-[side=right]:w-[min(96vw,1120px)] data-[side=right]:sm:max-w-280\"\n      >\n        <SheetHeader className=\"border-b pr-12\">\n          <SheetTitle>Export Form</SheetTitle>\n          <SheetDescription>\n            Export production-ready TSX or portable BuzzForm schema JSON.\n          </SheetDescription>\n        </SheetHeader>\n\n        <Tabs\n          defaultValue=\"tsx\"\n          className=\"flex h-full min-h-0 flex-1 flex-col p-4\"\n        >\n          <TabsList variant=\"line\" className=\"w-full\">\n            <TabsTrigger value=\"tsx\" className=\"gap-1.5\">\n              <IconPlaceholder\n                hugeicons=\"SourceCodeIcon\"\n                lucide=\"Code\"\n                tabler=\"IconCode\"\n                phosphor=\"Code\"\n                remixicon=\"RiCodeLine\"\n                size={16}\n                strokeWidth={2}\n              />\n              App Code\n              <Badge variant=\"outline\">.tsx</Badge>\n            </TabsTrigger>\n            <TabsTrigger value=\"schema\" className=\"gap-1.5\">\n              <IconPlaceholder\n                hugeicons=\"File02Icon\"\n                lucide=\"File\"\n                tabler=\"IconFile\"\n                phosphor=\"File\"\n                remixicon=\"RiFileCodeLine\"\n                size={16}\n                strokeWidth={2}\n              />\n              BuzzForm Schema\n              <Badge variant=\"outline\">.json</Badge>\n            </TabsTrigger>\n          </TabsList>\n\n          <TabsContent value=\"tsx\" className=\"min-h-0 flex-1 overflow-hidden\">\n            <ScrollArea className=\"h-full px-4 py-2\">\n              <div className=\"space-y-3 p-1\">\n                <div className=\"rounded-lg border bg-muted/30 p-3\">\n                  <div className=\"mb-3 flex items-center gap-2 text-sm font-medium\">\n                    <IconPlaceholder\n                      hugeicons=\"SourceCodeIcon\"\n                      lucide=\"Code\"\n                      tabler=\"IconCode\"\n                      phosphor=\"Code\"\n                      remixicon=\"RiCodeLine\"\n                      size={16}\n                      strokeWidth={1.8}\n                      className=\"text-muted-foreground\"\n                    />\n                    Required setup\n                  </div>\n                  <div className=\"[&_figure]:my-0!\">\n                    <DynamicCodeBlock lang=\"bash\" code={starterCommand} />\n                  </div>\n                  <div className=\"mt-3 flex flex-wrap items-center gap-2\">\n                    <Button\n                      type=\"button\"\n                      variant=\"outline\"\n                      size=\"sm\"\n                      onClick={downloadCode}\n                    >\n                      <IconPlaceholder\n                        hugeicons=\"Download01Icon\"\n                        lucide=\"Download\"\n                        tabler=\"IconDownload\"\n                        phosphor=\"DownloadSimple\"\n                        remixicon=\"RiDownload2Line\"\n                        size={16}\n                        strokeWidth={2}\n                      />\n                      Download TSX File\n                    </Button>\n                    <Button\n                      type=\"button\"\n                      variant=\"ghost\"\n                      size=\"sm\"\n                      onClick={() => copyToClipboard(componentCode, \"App code\")}\n                    >\n                      <IconPlaceholder\n                        hugeicons=\"Copy01Icon\"\n                        lucide=\"Copy\"\n                        tabler=\"IconCopy\"\n                        phosphor=\"Copy\"\n                        remixicon=\"RiFileCopyLine\"\n                        size={16}\n                        strokeWidth={2}\n                      />\n                      Copy Code\n                    </Button>\n                  </div>\n                </div>\n\n                <div className=\"[&_figure]:my-0!\">\n                  <DynamicCodeBlock lang=\"tsx\" code={componentCode} />\n                </div>\n              </div>\n            </ScrollArea>\n          </TabsContent>\n\n          <TabsContent\n            value=\"schema\"\n            className=\"min-h-0 flex-1 overflow-hidden\"\n          >\n            <ScrollArea className=\"h-full px-4 py-2\">\n              <div className=\"space-y-3 p-1\">\n                <div className=\"rounded-lg border bg-muted/30 p-3\">\n                  <div className=\"mb-3 flex items-center gap-2 text-sm font-medium\">\n                    <IconPlaceholder\n                      hugeicons=\"File02Icon\"\n                      lucide=\"File\"\n                      tabler=\"IconFile\"\n                      phosphor=\"File\"\n                      remixicon=\"RiFileCodeLine\"\n                      size={16}\n                      strokeWidth={1.8}\n                      className=\"text-muted-foreground\"\n                    />\n                    BuzzForm schema\n                  </div>\n                  <p className=\"text-sm text-muted-foreground\">\n                    Pure schema JSON for copy/paste import and runtime form\n                    generation.\n                  </p>\n                  <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n                    <Button\n                      type=\"button\"\n                      variant=\"outline\"\n                      size=\"sm\"\n                      onClick={downloadSchema}\n                    >\n                      <IconPlaceholder\n                        hugeicons=\"Download01Icon\"\n                        lucide=\"Download\"\n                        tabler=\"IconDownload\"\n                        phosphor=\"DownloadSimple\"\n                        remixicon=\"RiDownload2Line\"\n                        size={16}\n                        strokeWidth={2}\n                      />\n                      Download BuzzForm Schema\n                    </Button>\n                    <Button\n                      type=\"button\"\n                      variant=\"ghost\"\n                      size=\"sm\"\n                      onClick={() => copyToClipboard(schemaJson, \"Schema JSON\")}\n                    >\n                      <IconPlaceholder\n                        hugeicons=\"Copy01Icon\"\n                        lucide=\"Copy\"\n                        tabler=\"IconCopy\"\n                        phosphor=\"Copy\"\n                        remixicon=\"RiFileCopyLine\"\n                        size={16}\n                        strokeWidth={2}\n                      />\n                      Copy JSON\n                    </Button>\n                  </div>\n                </div>\n\n                <div className=\"[&_figure]:my-0!\">\n                  <DynamicCodeBlock lang=\"json\" code={schemaJson} />\n                </div>\n              </div>\n            </ScrollArea>\n          </TabsContent>\n        </Tabs>\n      </SheetContent>\n    </Sheet>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/export-sheet.tsx"
    },
    {
      "path": "registry/shadcn/builder/expression-builder/expression-checkbox.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport { useDataField } from \"@buildnbuzz/form-react\";\nimport type { ExpressionGroup } from \"@buildnbuzz/form-builder-core\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { Button } from \"@/components/ui/button\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport {\n  Field,\n  FieldContent,\n  FieldDescription,\n  FieldError,\n  FieldGroup,\n  FieldLabel,\n} from \"@/components/ui/field\";\nimport { cn } from \"@/lib/utils\";\nimport { ExpressionBuilder } from \"./index\";\n\ntype ExpressionValue = boolean | undefined | ExpressionGroup;\n\nfunction isExpressionGroup(value: unknown): value is ExpressionGroup {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    (value as ExpressionGroup).type === \"group\"\n  );\n}\n\n/**\n * Dual-mode property widget for boolean/expression fields.\n *\n * - Static mode: renders a Checkbox or Switch (per `field.type`) with a ⚡ button.\n * - Expression mode: renders an \"Expression active\" badge with Edit and Clear buttons.\n *\n * Toggling ⚡ opens the ExpressionBuilder dialog. Saving stores an ExpressionGroup.\n * Clearing reverts to `false` (static boolean).\n */\nexport function ExpressionCheckbox() {\n  const {\n    field,\n    fieldApi,\n    isDisabled,\n    isReadOnly,\n    isRequired,\n    label,\n    description,\n    errors,\n    isInvalid,\n    descriptionId,\n    errorId,\n    ariaDescribedBy,\n    handleBlur,\n    handleChange,\n  } = useDataField();\n\n  const value = fieldApi.state.value as ExpressionValue;\n  const disabled = isDisabled || isReadOnly;\n  const isExpression = isExpressionGroup(value);\n  const boolValue = isExpression ? false : ((value as boolean | undefined) ?? false);\n  const fieldType = (field as { type?: string }).type;\n  \n  const ui = (\n    field as {\n      ui?: {\n        alignment?: \"start\" | \"end\" | \"between\";\n        autoFocus?: boolean;\n        className?: string;\n        expressionMode?: \"default\" | \"only\" | \"none\";\n      };\n    }\n  ).ui;\n  const alignment = ui?.alignment ?? \"between\";\n  const expressionMode = ui?.expressionMode ?? \"default\";\n\n  const handleSave = (group: ExpressionGroup) => handleChange(group);\n  const handleClear = () => handleChange(expressionMode === \"only\" ? undefined : false);\n\n  // 1. The active expression node (replaces the input)\n  const activeControlNode = (\n    <div\n      className={cn(\n        \"flex shrink-0 items-center justify-center border border-amber-500/50 bg-amber-500/10 text-amber-600 dark:text-amber-500\",\n        fieldType === \"switch\" ? \"h-5 w-9 rounded-full\" : \"h-4 w-4 mt-0.5 rounded-sm\"\n      )}\n    >\n      <IconPlaceholder\n        lucide=\"Zap\"\n        hugeicons=\"Lightning\"\n        tabler=\"IconBolt\"\n        phosphor=\"Lightning\"\n        remixicon=\"RiFlashlightLine\"\n        size={fieldType === \"switch\" ? 12 : 10}\n        className=\"fill-amber-500/20\"\n      />\n    </div>\n  );\n\n  const expressionBar = isExpression ? (\n    <div className=\"mt-2 flex items-center justify-between rounded-md border border-amber-500/30 bg-amber-500/5 px-2 py-1 shadow-sm\">\n      <div className=\"flex items-center gap-1.5 text-xs font-medium text-amber-600 dark:text-amber-500\">\n        <IconPlaceholder\n          lucide=\"Zap\"\n          hugeicons=\"Lightning\"\n          tabler=\"IconBolt\"\n          phosphor=\"Lightning\"\n          remixicon=\"RiFlashlightLine\"\n          size={14}\n          className=\"fill-amber-500/20\"\n        />\n        Dynamic Expression\n      </div>\n      <div className=\"flex items-center gap-0.5\">\n        <ExpressionBuilder\n          initialValue={value as ExpressionGroup}\n          onSave={handleSave}\n          trigger={\n            <Button\n              variant=\"ghost\"\n              size=\"icon-sm\"\n              className=\"h-6 w-6 text-amber-600/70 hover:bg-amber-500/10 hover:text-amber-600 dark:text-amber-500/70 dark:hover:text-amber-500\"\n            >\n              <IconPlaceholder\n                lucide=\"Pencil\"\n                hugeicons=\"PencilEdit01Icon\"\n                tabler=\"IconPencil\"\n                phosphor=\"PencilSimple\"\n                remixicon=\"RiPencilLine\"\n                size={12}\n              />\n            </Button>\n          }\n        />\n        <Button\n          variant=\"ghost\"\n          size=\"icon-sm\"\n          className=\"h-6 w-6 text-amber-600/70 hover:bg-destructive/10 hover:text-destructive dark:text-amber-500/70 dark:hover:text-destructive\"\n          onClick={handleClear}\n          disabled={disabled}\n        >\n          <IconPlaceholder\n            lucide=\"X\"\n            hugeicons=\"Cancel01Icon\"\n            tabler=\"IconX\"\n            phosphor=\"X\"\n            remixicon=\"RiCloseLine\"\n            size={12}\n          />\n        </Button>\n      </div>\n    </div>\n  ) : expressionMode === \"only\" && !isExpression ? (\n    <div className=\"mt-2\">\n      <ExpressionBuilder\n        initialValue={undefined}\n        onSave={handleSave}\n        trigger={\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"h-7 w-full gap-1.5 border-dashed text-xs text-muted-foreground hover:border-amber-500/50 hover:bg-amber-500/5 hover:text-amber-500\"\n          >\n            <IconPlaceholder\n              lucide=\"Zap\"\n              hugeicons=\"Lightning\"\n              tabler=\"IconBolt\"\n              phosphor=\"Lightning\"\n              remixicon=\"RiFlashlightLine\"\n              size={14}\n            />\n            Set Expression\n          </Button>\n        }\n      />\n    </div>\n  ) : null;\n\n  // 2. The static control node\n  const switchNode = (\n    <Switch\n      id={fieldApi.name}\n      checked={boolValue}\n      onCheckedChange={(checked) => {\n        handleChange(checked);\n        handleBlur();\n      }}\n      disabled={disabled}\n      aria-invalid={isInvalid}\n      aria-describedby={ariaDescribedBy}\n      aria-readonly={isReadOnly}\n      autoFocus={ui?.autoFocus}\n      size=\"sm\"\n    />\n  );\n\n  const checkboxNode = (\n    <Checkbox\n      id={fieldApi.name}\n      checked={boolValue}\n      onCheckedChange={(checked) => {\n        handleChange(!!checked);\n        handleBlur();\n      }}\n      disabled={disabled}\n      aria-invalid={isInvalid}\n      aria-describedby={ariaDescribedBy}\n      aria-readonly={isReadOnly}\n      autoFocus={ui?.autoFocus}\n    />\n  );\n\n  const emptyControlNode = (\n    <div\n      className={cn(\n        \"flex shrink-0 items-center justify-center text-muted-foreground/30\",\n        fieldType === \"switch\" ? \"h-5 w-9\" : \"h-4 w-4 mt-0.5\"\n      )}\n    >\n      <IconPlaceholder\n        lucide=\"Zap\"\n        hugeicons=\"Lightning\"\n        tabler=\"IconBolt\"\n        phosphor=\"Lightning\"\n        remixicon=\"RiFlashlightLine\"\n        size={fieldType === \"switch\" ? 12 : 10}\n      />\n    </div>\n  );\n\n  const controlNode = isExpression\n    ? activeControlNode\n    : expressionMode === \"only\"\n      ? emptyControlNode\n      : fieldType === \"switch\"\n        ? switchNode\n        : checkboxNode;\n\n  // 3. The content element (label, description, error, expression bar)\n  const isSwitchBetween = fieldType === \"switch\" && alignment === \"between\";\n  const contentElement = (\n    <FieldContent className={isSwitchBetween ? \"flex-1\" : undefined}>\n      {label && (\n        <FieldLabel\n          htmlFor={fieldApi.name}\n          className={cn(\n            \"cursor-pointer m-0 font-normal\",\n            isSwitchBetween ? \"flex-none gap-1 items-baseline\" : \"inline\"\n          )}\n        >\n          {isSwitchBetween && isRequired && <span className=\"text-destructive\">*</span>}\n          {label}\n          {!isSwitchBetween && isRequired && <span className=\"text-destructive\">&nbsp;*</span>}\n        </FieldLabel>\n      )}\n      {description && !isInvalid && (\n        <FieldDescription id={descriptionId}>{description}</FieldDescription>\n      )}\n      {isInvalid && <FieldError id={errorId} errors={errors} />}\n      {expressionBar}\n    </FieldContent>\n  );\n\n  // 4. Assemble the layout\n  return (\n    <FieldGroup data-field={fieldApi.name} className={cn(\"group/expr\", ui?.className)}>\n      <div className=\"flex items-start gap-2 w-full\">\n        <Field\n          orientation=\"horizontal\"\n          className={cn(\"flex-1\", isSwitchBetween && \"w-full justify-between\")}\n          data-invalid={isInvalid}\n          data-disabled={disabled}\n        >\n          {fieldType === \"switch\" ? (\n            alignment === \"start\" ? (\n              <>\n                {controlNode}\n                {contentElement}\n              </>\n            ) : (\n              <>\n                {contentElement}\n                {controlNode}\n              </>\n            )\n          ) : (\n            // Default Checkbox layout\n            <>\n              {controlNode}\n              {contentElement}\n            </>\n          )}\n        </Field>\n\n        {/* Lightning bolt trigger (only visible when static mode and default mode) */}\n        {!isExpression && expressionMode === \"default\" && (\n          <ExpressionBuilder\n            initialValue={undefined}\n            onSave={handleSave}\n            trigger={\n              <Button\n                variant=\"ghost\"\n                size=\"icon-sm\"\n                className=\"h-6 w-6 shrink-0 opacity-0 transition-all hover:bg-amber-500/10 hover:text-amber-500 focus-visible:opacity-100 group-hover/expr:opacity-100 dark:text-muted-foreground\"\n                disabled={disabled}\n              >\n                <IconPlaceholder\n                  lucide=\"Zap\"\n                  hugeicons=\"Lightning\"\n                  tabler=\"IconBolt\"\n                  phosphor=\"Lightning\"\n                  remixicon=\"RiFlashlightLine\"\n                  size={14}\n                />\n              </Button>\n            }\n          />\n        )}\n      </div>\n    </FieldGroup>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/expression-builder/expression-checkbox.tsx"
    },
    {
      "path": "registry/shadcn/builder/expression-builder/expression-group.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport type { StoreApi } from \"zustand\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport {\n  Empty,\n  EmptyHeader,\n  EmptyTitle,\n  EmptyDescription,\n  EmptyMedia,\n} from \"@/components/ui/empty\";\nimport {\n  SortableContext,\n  verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { type ExpressionGroup } from \"@buildnbuzz/form-builder-core\";\nimport { type ExpressionStoreState } from \"@buildnbuzz/form-builder-react\";\nimport { Card, CardContent, CardFooter } from \"@/components/ui/card\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { SortableItem } from \"./sortable-item\";\nimport { ExpressionRuleItem } from \"./expression-rule\";\n\ninterface ExpressionGroupItemProps {\n  group: ExpressionGroup;\n  parentId?: string;\n  isRoot?: boolean;\n  store: StoreApi<ExpressionStoreState>;\n}\n\nexport function ExpressionGroupItem({\n  group,\n  parentId,\n  isRoot = false,\n  store,\n}: ExpressionGroupItemProps) {\n  const [isOpen, setIsOpen] = React.useState(true);\n  const {\n    updateGroupOperator,\n    removeNode,\n    addRule,\n    addGroup,\n    duplicateGroup,\n  } = store.getState();\n\n  const headerContent = (\n    <div\n      className={cn(\n        \"flex flex-col sm:flex-row items-start sm:items-center gap-2 p-1.5 transition-all relative\",\n        isRoot\n          ? \"rounded-xl\"\n          : cn(\n              \"bg-muted/50 cursor-pointer group/header hover:bg-muted/80 rounded-t-xl\",\n              isOpen ? \"rounded-b-none\" : \"rounded-b-xl\"\n            )\n      )}\n    >\n      {!isRoot && (\n        <div className=\"flex items-center justify-center w-6 h-6 shrink-0 text-muted-foreground mr-1\">\n          {isOpen ? (\n            <IconPlaceholder\n              lucide=\"ChevronDown\"\n              hugeicons=\"ArrowDown01Icon\"\n              tabler=\"IconChevronDown\"\n              phosphor=\"CaretDown\"\n              remixicon=\"RiArrowDownSLine\"\n              size={18}\n            />\n          ) : (\n            <IconPlaceholder\n              lucide=\"ChevronRight\"\n              hugeicons=\"ArrowRight01Icon\"\n              tabler=\"IconChevronRight\"\n              phosphor=\"CaretRight\"\n              remixicon=\"RiArrowRightSLine\"\n              size={18}\n            />\n          )}\n        </div>\n      )}\n\n      <div onClick={(e) => e.stopPropagation()}>\n        <Select\n          value={group.logicalOperator}\n          onValueChange={(val: unknown) => {\n            if (val) updateGroupOperator(group.id, val as \"AND\" | \"OR\");\n          }}\n        >\n          <SelectTrigger className=\"w-26.25 text-xs font-medium bg-muted border-none\">\n            <SelectValue>\n              {group.logicalOperator === \"AND\" ? \"Match ALL\" : \"Match ANY\"}\n            </SelectValue>\n          </SelectTrigger>\n          <SelectContent\n            alignItemWithTrigger={false}\n            align=\"start\"\n            sideOffset={4}\n          >\n            <SelectItem value=\"AND\">Match ALL</SelectItem>\n            <SelectItem value=\"OR\">Match ANY</SelectItem>\n          </SelectContent>\n        </Select>\n      </div>\n\n      <span className=\"text-sm font-medium text-muted-foreground\">\n        {isRoot ? \"of the following:\" : \"Expression Group\"}\n      </span>\n\n      {!isRoot && parentId && (\n        <div\n          className=\"absolute -top-3 right-4 flex items-center bg-card border shadow-sm rounded-md px-1 py-0.5 opacity-0 group-hover/header:opacity-100 transition-all z-30 scale-95 group-hover/header:scale-100\"\n          onClick={(e) => e.stopPropagation()}\n        >\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon-lg\"\n                  className=\"h-7 w-7 text-muted-foreground hover:text-primary\"\n                  onClick={(e) => {\n                    e.stopPropagation();\n                    duplicateGroup(parentId, group.id);\n                  }}\n                >\n                  <IconPlaceholder\n                    lucide=\"Copy\"\n                    hugeicons=\"Copy01Icon\"\n                    tabler=\"IconCopy\"\n                    phosphor=\"Copy\"\n                    remixicon=\"RiFileCopyLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent>Duplicate Expression Group</TooltipContent>\n          </Tooltip>\n\n          <div className=\"w-px h-4 bg-border mx-0.5\" />\n\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  className=\"h-7 w-7 text-muted-foreground hover:text-destructive\"\n                  onClick={(e) => {\n                    e.stopPropagation();\n                    removeNode(parentId, group.id);\n                  }}\n                >\n                  <IconPlaceholder\n                    lucide=\"Trash2\"\n                    hugeicons=\"Delete01Icon\"\n                    tabler=\"IconTrash\"\n                    phosphor=\"Trash\"\n                    remixicon=\"RiDeleteBinLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent>Delete Expression Group</TooltipContent>\n          </Tooltip>\n        </div>\n      )}\n    </div>\n  );\n\n  const mainContent =\n    group.children.length === 0 ? (\n      <Empty className={isRoot ? \"h-full min-h-75\" : \"h-auto py-8\"}>\n        <EmptyHeader>\n          <EmptyMedia variant=\"icon\">\n            <IconPlaceholder\n              lucide=\"Layers\"\n              hugeicons=\"Layers01Icon\"\n              tabler=\"IconLayersIntersect\"\n              phosphor=\"Stack\"\n              remixicon=\"RiStackLine\"\n            />\n          </EmptyMedia>\n          <EmptyTitle>No rules added</EmptyTitle>\n          <EmptyDescription>\n            Click the buttons below to add rules\n          </EmptyDescription>\n        </EmptyHeader>\n      </Empty>\n    ) : (\n      <SortableContext\n        id={group.id}\n        items={group.children.map((c) => c.id)}\n        strategy={verticalListSortingStrategy}\n      >\n        <div className=\"flex flex-col gap-3\">\n          {group.children.map((child) => (\n            <SortableItem key={child.id} id={child.id}>\n              {child.type === \"group\" ? (\n                <ExpressionGroupItem\n                  group={child}\n                  parentId={group.id}\n                  store={store}\n                />\n              ) : (\n                <ExpressionRuleItem\n                  rule={child}\n                  parentId={group.id}\n                  store={store}\n                />\n              )}\n            </SortableItem>\n          ))}\n        </div>\n      </SortableContext>\n    );\n\n  const footerActions = (\n    <div className=\"flex items-center gap-2\">\n      <Button\n        variant=\"outline\"\n        size=\"sm\"\n        className=\"h-8 text-xs\"\n        onClick={() => addRule(group.id)}\n      >\n        <span className=\"mr-1 flex items-center justify-center\">\n          <IconPlaceholder\n            lucide=\"Plus\"\n            hugeicons=\"PlusSignIcon\"\n            tabler=\"IconPlus\"\n            phosphor=\"Plus\"\n            remixicon=\"RiAddLine\"\n            size={14}\n          />\n        </span>\n        Add Rule\n      </Button>\n      <Button\n        variant=\"outline\"\n        size=\"sm\"\n        className=\"h-8 text-xs\"\n        onClick={() => addGroup(group.id)}\n      >\n        <span className=\"mr-1 flex items-center justify-center\">\n          <IconPlaceholder\n            lucide=\"FolderPlus\"\n            hugeicons=\"FolderAddIcon\"\n            tabler=\"IconFolderPlus\"\n            phosphor=\"FolderPlus\"\n            remixicon=\"RiFolderAddLine\"\n            size={14}\n          />\n        </span>\n        Add Group\n      </Button>\n    </div>\n  );\n\n  if (isRoot) {\n    return (\n      <div className=\"flex flex-col flex-1 min-h-0 h-full\">\n        <div className=\"shrink-0 px-6 pt-0 pb-0\">{headerContent}</div>\n        <ScrollArea className=\"flex-1 h-full min-h-0\">\n          <div className=\"px-6 pt-4 pb-2\">{mainContent}</div>\n        </ScrollArea>\n        <div className=\"shrink-0 px-6 pt-2 pb-0\">{footerActions}</div>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"overflow-visible w-full\">\n      <Card\n        size=\"sm\"\n        className=\"gap-0 py-0 data-[size=sm]:py-0 ring-1 ring-border shadow-sm border-none bg-card overflow-visible\"\n      >\n        <Collapsible open={isOpen} onOpenChange={setIsOpen} className=\"w-full\">\n          <CollapsibleTrigger\n            nativeButton={false}\n            render={headerContent}\n            className=\"w-full\"\n          />\n          <CollapsibleContent>\n            <CardContent className=\"pt-2 pb-0\">{mainContent}</CardContent>\n            <CardFooter className=\"bg-transparent border-none px-4 py-2\">\n              {footerActions}\n            </CardFooter>\n          </CollapsibleContent>\n        </Collapsible>\n      </Card>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/expression-builder/expression-group.tsx"
    },
    {
      "path": "registry/shadcn/builder/expression-builder/expression-rule.tsx",
      "content": "\"use client\";\n\nimport type { StoreApi } from \"zustand\";\nimport {\n  type ExpressionRule,\n  type ExpressionOperator,\n  EXPRESSION_OPERATORS,\n  getFieldTypeCategory,\n  getOperatorsForFieldType,\n} from \"@buildnbuzz/form-builder-core\";\nimport {\n  useAvailableFields,\n  type ExpressionStoreState,\n} from \"@buildnbuzz/form-builder-react\";\n\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\n\ninterface ExpressionRuleItemProps {\n  rule: ExpressionRule;\n  parentId: string;\n  store: StoreApi<ExpressionStoreState>;\n}\n\nexport function ExpressionRuleItem({\n  rule,\n  parentId,\n  store,\n}: ExpressionRuleItemProps) {\n  const availableFields = useAvailableFields();\n\n  const selectedField = availableFields.find((f) => f.id === rule.fieldId);\n  const fieldCategory = getFieldTypeCategory(selectedField?.type);\n  const applicableOperators = getOperatorsForFieldType(selectedField?.type);\n\n  const selectedOperator = EXPRESSION_OPERATORS.find(\n    (op) => op.value === rule.operator,\n  );\n  const requiresValue = selectedOperator?.requiresValue ?? true;\n\n  const selectedValueField = availableFields.find((f) => f.id === rule.value);\n\n  const { updateRule, removeNode, duplicateRule } = store.getState();\n\n  const handleFieldChange = (newFieldId: string) => {\n    const newField = availableFields.find((f) => f.id === newFieldId);\n    const newCategory = getFieldTypeCategory(newField?.type);\n    const newOps = getOperatorsForFieldType(newField?.type);\n\n    // Reset operator if not applicable to new field type\n    const currentOpApplicable = newOps.some((op) => op.value === rule.operator);\n    const newOperator = currentOpApplicable ? rule.operator : \"equals\";\n\n    // Reset value for type changes\n    let newValue = rule.value;\n    if (newCategory === \"boolean\") {\n      newValue = \"true\";\n    } else if (newCategory !== fieldCategory) {\n      newValue = \"\";\n    }\n\n    updateRule(parentId, rule.id, {\n      fieldId: newFieldId,\n      operator: newOperator,\n      value: newValue,\n      valueType: newCategory === \"boolean\" ? \"custom\" : rule.valueType,\n    });\n  };\n\n  // Render value input based on field type category\n  const renderValueInput = () => {\n    if (!requiresValue) return null;\n\n    // Field reference mode\n    if (rule.valueType !== \"custom\") {\n      return (\n        <div className=\"flex items-center gap-2 w-full sm:flex-1\">\n          <Tooltip>\n            <TooltipTrigger\n              render={\n                <Button\n                  variant=\"outline\"\n                  size=\"icon-lg\"\n                  className=\"shrink-0 text-muted-foreground\"\n                  onClick={() =>\n                    updateRule(parentId, rule.id, {\n                      valueType: \"custom\",\n                      value: selectedField?.options?.[0]?.value ?? \"\",\n                    })\n                  }\n                >\n                  <IconPlaceholder\n                    lucide=\"Link\"\n                    hugeicons=\"LinkSquare02Icon\"\n                    tabler=\"IconLink\"\n                    phosphor=\"Link\"\n                    remixicon=\"RiLinksLine\"\n                    size={16}\n                  />\n                </Button>\n              }\n            />\n            <TooltipContent>Use Custom Value</TooltipContent>\n          </Tooltip>\n          <Select\n            value={rule.value}\n            onValueChange={(val: unknown) => {\n              if (val)\n                updateRule(parentId, rule.id, {\n                  value: val as string,\n                });\n            }}\n          >\n            <SelectTrigger className=\"w-full h-9!\">\n              <SelectValue>{selectedValueField?.label}</SelectValue>\n            </SelectTrigger>\n            <SelectContent\n              alignItemWithTrigger={false}\n              align=\"start\"\n              sideOffset={4}\n            >\n              {availableFields\n                .filter((f) => f.id !== rule.fieldId)\n                .map((field) => (\n                  <SelectItem key={field.id} value={field.id}>\n                    {field.label}\n                  </SelectItem>\n                ))}\n            </SelectContent>\n          </Select>\n        </div>\n      );\n    }\n\n    const fieldRefButton = (\n      <Tooltip>\n        <TooltipTrigger\n          render={\n            <Button\n              variant=\"outline\"\n              size=\"icon-lg\"\n              className=\"shrink-0 text-muted-foreground\"\n              onClick={() =>\n                updateRule(parentId, rule.id, {\n                  valueType: \"field\",\n                  value: \"\",\n                })\n              }\n            >\n              <IconPlaceholder\n                lucide=\"Type\"\n                hugeicons=\"TextIcon\"\n                tabler=\"IconLetterCase\"\n                phosphor=\"TextT\"\n                remixicon=\"RiText\"\n                size={16}\n              />\n            </Button>\n          }\n        />\n        <TooltipContent>Use Field Reference</TooltipContent>\n      </Tooltip>\n    );\n\n    // Fields with options (boolean, select, radio, checkbox-group): render Select dropdown\n    if (selectedField?.options && selectedField.options.length > 0) {\n      const matchedOption = selectedField.options.find(\n        (o) => o.value === rule.value,\n      );\n      return (\n        <div className=\"flex items-center gap-2 w-full sm:flex-1\">\n          {fieldRefButton}\n          <Select\n            value={rule.value}\n            onValueChange={(val: unknown) => {\n              if (val) updateRule(parentId, rule.id, { value: val as string });\n            }}\n          >\n            <SelectTrigger className=\"w-full h-9!\">\n              <SelectValue>{matchedOption?.label ?? rule.value}</SelectValue>\n            </SelectTrigger>\n            <SelectContent\n              alignItemWithTrigger={false}\n              align=\"start\"\n              sideOffset={4}\n            >\n              {selectedField.options.map((opt) => (\n                <SelectItem key={opt.value} value={opt.value}>\n                  {opt.label}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n        </div>\n      );\n    }\n\n    // Number fields: render number input\n    if (fieldCategory === \"number\") {\n      return (\n        <div className=\"flex items-center gap-2 w-full sm:flex-1\">\n          {fieldRefButton}\n          <Input\n            type=\"number\"\n            placeholder=\"Enter number...\"\n            className=\"h-9 w-full\"\n            value={rule.value}\n            onChange={(e) =>\n              updateRule(parentId, rule.id, { value: e.target.value })\n            }\n          />\n        </div>\n      );\n    }\n\n    // Default: text input\n    return (\n      <div className=\"flex items-center gap-2 w-full sm:flex-1\">\n        {fieldRefButton}\n        <Input\n          placeholder=\"Enter value...\"\n          className=\"h-9 w-full\"\n          value={rule.value}\n          onChange={(e) =>\n            updateRule(parentId, rule.id, { value: e.target.value })\n          }\n        />\n      </div>\n    );\n  };\n\n  return (\n    <div className=\"flex flex-col sm:flex-row items-start sm:items-center gap-2 bg-card p-2 rounded-lg border shadow-sm transition-all group/rule w-full relative\">\n      <Select\n        value={rule.fieldId}\n        onValueChange={(val: unknown) => {\n          if (val) handleFieldChange(val as string);\n        }}\n      >\n        <SelectTrigger className=\"w-full sm:w-50 h-9!\">\n          <SelectValue>{selectedField?.label}</SelectValue>\n        </SelectTrigger>\n        <SelectContent\n          alignItemWithTrigger={false}\n          align=\"start\"\n          sideOffset={4}\n        >\n          {availableFields.map((field) => (\n            <SelectItem key={field.id} value={field.id}>\n              {field.label}\n            </SelectItem>\n          ))}\n        </SelectContent>\n      </Select>\n\n      <Select\n        value={rule.operator}\n        onValueChange={(val: unknown) => {\n          if (val)\n            updateRule(parentId, rule.id, {\n              operator: val as ExpressionOperator,\n            });\n        }}\n      >\n        <SelectTrigger className=\"w-full sm:w-40 h-9!\">\n          <SelectValue>{selectedOperator?.label}</SelectValue>\n        </SelectTrigger>\n        <SelectContent\n          alignItemWithTrigger={false}\n          align=\"start\"\n          sideOffset={4}\n        >\n          {applicableOperators.map((op) => (\n            <SelectItem key={op.value} value={op.value}>\n              {op.label}\n            </SelectItem>\n          ))}\n        </SelectContent>\n      </Select>\n\n      {renderValueInput()}\n\n      <div className=\"absolute -top-3 right-4 flex items-center bg-card border shadow-sm rounded-md px-1 py-0.5 opacity-0 group-hover/rule:opacity-100 transition-all z-50 scale-95 group-hover/rule:scale-100\">\n        <Tooltip>\n          <TooltipTrigger\n            render={\n              <Button\n                variant=\"ghost\"\n                size=\"icon-lg\"\n                className=\"text-muted-foreground hover:text-primary h-7 w-7\"\n                onClick={() => duplicateRule(parentId, rule.id)}\n              >\n                <IconPlaceholder\n                  lucide=\"Copy\"\n                  hugeicons=\"Copy01Icon\"\n                  tabler=\"IconCopy\"\n                  phosphor=\"Copy\"\n                  remixicon=\"RiFileCopyLine\"\n                  size={16}\n                />\n              </Button>\n            }\n          />\n          <TooltipContent>Duplicate Rule</TooltipContent>\n        </Tooltip>\n\n        <div className=\"w-px h-4 bg-border mx-0.5\" />\n\n        <Tooltip>\n          <TooltipTrigger\n            render={\n              <Button\n                variant=\"ghost\"\n                size=\"icon\"\n                className=\"text-muted-foreground hover:text-destructive h-7 w-7\"\n                onClick={() => removeNode(parentId, rule.id)}\n              >\n                <IconPlaceholder\n                  lucide=\"Trash2\"\n                  hugeicons=\"Delete01Icon\"\n                  tabler=\"IconTrash\"\n                  phosphor=\"Trash\"\n                  remixicon=\"RiDeleteBinLine\"\n                  size={16}\n                />\n              </Button>\n            }\n          />\n          <TooltipContent>Delete Rule</TooltipContent>\n        </Tooltip>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/expression-builder/expression-rule.tsx"
    },
    {
      "path": "registry/shadcn/builder/expression-builder/index.tsx",
      "content": "\"use client\";\n\nimport React, { useState } from \"react\";\nimport { DndContext, closestCorners } from \"@dnd-kit/core\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Button } from \"@/components/ui/button\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\n\nimport type { ExpressionGroup } from \"@buildnbuzz/form-builder-core\";\nimport {\n  useExpressionStore,\n  useExpressionDnd,\n} from \"@buildnbuzz/form-builder-react\";\n\nimport { ExpressionGroupItem } from \"./expression-group\";\n\nexport { ExpressionGroupItem } from \"./expression-group\";\nexport { ExpressionRuleItem } from \"./expression-rule\";\nexport { SortableItem } from \"./sortable-item\";\n\nexport interface ExpressionBuilderProps {\n  initialValue?: ExpressionGroup;\n  onSave: (group: ExpressionGroup) => void;\n  trigger?: React.ReactElement;\n}\n\nexport function ExpressionBuilder({\n  initialValue,\n  onSave,\n  trigger,\n}: ExpressionBuilderProps) {\n  const [open, setOpen] = useState(false);\n\n  const { store, rootGroup } = useExpressionStore(initialValue, open);\n  const { sensors, handleDragOver, handleDragEnd } = useExpressionDnd(store);\n\n  const handleSave = () => {\n    onSave(store.getState().rootGroup);\n    setOpen(false);\n  };\n\n  return (\n    <Dialog open={open} onOpenChange={setOpen}>\n      <DialogTrigger\n        render={\n          trigger || (\n            <Button variant=\"outline\">\n              <span className=\"mr-2 flex items-center justify-center\">\n                <IconPlaceholder\n                  lucide=\"Settings\"\n                  hugeicons=\"Settings01Icon\"\n                  tabler=\"IconSettings\"\n                  phosphor=\"Gear\"\n                  remixicon=\"RiSettings4Line\"\n                  size={16}\n                />\n              </span>\n              Expression Logic\n            </Button>\n          )\n        }\n      />\n      <DialogContent className=\"sm:max-w-4xl md:max-w-5xl lg:max-w-6xl w-[95vw] h-[80vh] flex flex-col p-0 overflow-hidden bg-background/80\">\n        <DialogHeader className=\"p-6 pb-4 bg-card border-b shrink-0 flex flex-row items-start gap-4 space-y-0 text-left\">\n          <div className=\"text-primary flex items-center justify-center p-2 rounded-xl bg-primary/10\">\n            <IconPlaceholder\n              lucide=\"Settings\"\n              hugeicons=\"Settings01Icon\"\n              tabler=\"IconSettings\"\n              phosphor=\"Gear\"\n              remixicon=\"RiSettings4Line\"\n              size={24}\n            />\n          </div>\n          <div className=\"flex flex-col gap-1\">\n            <DialogTitle>Expression Builder</DialogTitle>\n            <DialogDescription>\n              Define the logical expression for this property.\n            </DialogDescription>\n          </div>\n        </DialogHeader>\n\n        <div className=\"flex-1 flex flex-col min-h-0\">\n          <DndContext\n            sensors={sensors}\n            collisionDetection={closestCorners}\n            onDragOver={handleDragOver}\n            onDragEnd={handleDragEnd}\n          >\n            <ExpressionGroupItem\n              group={rootGroup}\n              isRoot={true}\n              store={store}\n            />\n          </DndContext>\n        </div>\n\n        <DialogFooter className=\"border-t shrink-0 m-0 rounded-none\">\n          <Button variant=\"outline\" onClick={() => setOpen(false)}>\n            Cancel\n          </Button>\n          <Button\n            onClick={handleSave}\n            className=\"bg-primary hover:bg-primary/90 text-primary-foreground\"\n          >\n            Save Expression\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/expression-builder/index.tsx"
    },
    {
      "path": "registry/shadcn/builder/expression-builder/sortable-item.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\n\ninterface SortableItemProps {\n  id: string;\n  children: React.ReactNode;\n}\n\nexport function SortableItem({ id, children }: SortableItemProps) {\n  const {\n    attributes,\n    listeners,\n    setNodeRef,\n    transform,\n    transition,\n    isDragging,\n  } = useSortable({ id });\n\n  const style = {\n    transform: CSS.Transform.toString(transform),\n    transition,\n    opacity: isDragging ? 0.5 : 1,\n  };\n\n  return (\n    <div\n      ref={setNodeRef}\n      style={style}\n      className=\"flex items-start gap-2 relative group/item\"\n    >\n      <div\n        {...attributes}\n        {...listeners}\n        className=\"mt-2 cursor-grab active:cursor-grabbing text-muted-foreground/50 hover:text-muted-foreground opacity-0 group-hover/item:opacity-100 transition-opacity\"\n      >\n        <IconPlaceholder\n          lucide=\"GripVertical\"\n          hugeicons=\"DragDropVerticalIcon\"\n          tabler=\"IconGripVertical\"\n          phosphor=\"DotsSixVertical\"\n          remixicon=\"RiDragMove2Line\"\n          size={20}\n        />\n      </div>\n      <div className=\"flex-1 min-w-0\">{children}</div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/expression-builder/sortable-item.tsx"
    },
    {
      "path": "registry/shadcn/builder/field-icon.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\n\ninterface FieldIconProps extends React.ComponentProps<\"svg\"> {\n  type: string;\n  size?: number;\n}\n\n/**\n * A statically-analyzable icon picker for the form builder.\n *\n * IMPORTANT: We use a switch statement with literal string props for IconPlaceholder\n * so that the shadcn CLI transformer can identify and replace these with the\n * user's local icon library components during installation.\n */\nexport const FieldIcon = ({ type, size = 16, ...props }: FieldIconProps) => {\n  switch (type) {\n    case \"text\":\n      return (\n        <IconPlaceholder\n          lucide=\"Type\"\n          hugeicons=\"TextIcon\"\n          tabler=\"IconLetterCase\"\n          phosphor=\"TextT\"\n          remixicon=\"RiText\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"email\":\n      return (\n        <IconPlaceholder\n          lucide=\"Mail\"\n          hugeicons=\"Mail01Icon\"\n          tabler=\"IconMail\"\n          phosphor=\"Envelope\"\n          remixicon=\"RiMailLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"password\":\n      return (\n        <IconPlaceholder\n          lucide=\"Lock\"\n          hugeicons=\"SecurityPasswordIcon\"\n          tabler=\"IconLock\"\n          phosphor=\"LockSimple\"\n          remixicon=\"RiLockPasswordLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"textarea\":\n      return (\n        <IconPlaceholder\n          lucide=\"AlignLeft\"\n          hugeicons=\"TextAlignLeftIcon\"\n          tabler=\"IconAlignLeft\"\n          phosphor=\"TextAlignLeft\"\n          remixicon=\"RiAlignLeft\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"number\":\n      return (\n        <IconPlaceholder\n          lucide=\"Binary\"\n          hugeicons=\"GridIcon\"\n          tabler=\"IconHash\"\n          phosphor=\"Hash\"\n          remixicon=\"RiNumber7\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"checkbox\":\n      return (\n        <IconPlaceholder\n          lucide=\"CheckSquare\"\n          hugeicons=\"CheckmarkSquare02Icon\"\n          tabler=\"IconCheck\"\n          phosphor=\"Check\"\n          remixicon=\"RiCheckLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"switch\":\n      return (\n        <IconPlaceholder\n          lucide=\"ToggleRight\"\n          hugeicons=\"ToggleOnIcon\"\n          tabler=\"IconToggleRight\"\n          phosphor=\"ToggleRight\"\n          remixicon=\"RiToggleLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"select\":\n      return (\n        <IconPlaceholder\n          lucide=\"ChevronDown\"\n          hugeicons=\"ArrowDown01Icon\"\n          tabler=\"IconChevronDown\"\n          phosphor=\"CaretDown\"\n          remixicon=\"RiArrowDownSLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"radio\":\n      return (\n        <IconPlaceholder\n          lucide=\"CircleDot\"\n          hugeicons=\"CircleIcon\"\n          tabler=\"IconCircleDot\"\n          phosphor=\"CircleDashed\"\n          remixicon=\"RiRadioButtonLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"date\":\n      return (\n        <IconPlaceholder\n          lucide=\"Calendar\"\n          hugeicons=\"Calendar03Icon\"\n          tabler=\"IconCalendar\"\n          phosphor=\"Calendar\"\n          remixicon=\"RiCalendarLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"tags\":\n      return (\n        <IconPlaceholder\n          lucide=\"Tag\"\n          hugeicons=\"Tag01Icon\"\n          tabler=\"IconTag\"\n          phosphor=\"Tag\"\n          remixicon=\"RiPriceTagLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"group\":\n      return (\n        <IconPlaceholder\n          lucide=\"Folder\"\n          hugeicons=\"FolderIcon\"\n          tabler=\"IconFolder\"\n          phosphor=\"Folder\"\n          remixicon=\"RiFolderLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"array\":\n      return (\n        <IconPlaceholder\n          lucide=\"Layers\"\n          hugeicons=\"Menu01Icon\"\n          tabler=\"IconLayersIntersect\"\n          phosphor=\"Stack\"\n          remixicon=\"RiStackLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"row\":\n      return (\n        <IconPlaceholder\n          lucide=\"Columns\"\n          hugeicons=\"RowInsertIcon\"\n          tabler=\"IconColumns\"\n          phosphor=\"Columns\"\n          remixicon=\"RiLayoutColumnLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"tabs\":\n      return (\n        <IconPlaceholder\n          lucide=\"PanelTop\"\n          hugeicons=\"Layout01Icon\"\n          tabler=\"IconBrowser\"\n          phosphor=\"Browser\"\n          remixicon=\"RiWindowLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"collapsible\":\n      return (\n        <IconPlaceholder\n          lucide=\"ChevronsDownUp\"\n          hugeicons=\"ArrowShrink02Icon\"\n          tabler=\"IconChevronDownLeft\"\n          phosphor=\"CaretDoubleDown\"\n          remixicon=\"RiArrowDownDoubleLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"upload\":\n      return (\n        <IconPlaceholder\n          lucide=\"UploadCloud\"\n          hugeicons=\"Upload01Icon\"\n          tabler=\"IconUpload\"\n          phosphor=\"UploadSimple\"\n          remixicon=\"RiUploadCloud2Line\"\n          size={size}\n          {...props}\n        />\n      );\n\n\n    // Contextual icons\n    case \"plus\":\n      return (\n        <IconPlaceholder\n          lucide=\"Plus\"\n          hugeicons=\"Add01Icon\"\n          tabler=\"IconPlus\"\n          phosphor=\"Plus\"\n          remixicon=\"RiAddLine\"\n          size={size}\n          {...props}\n        />\n      );\n    case \"move\":\n      return (\n        <IconPlaceholder\n          lucide=\"Move\"\n          hugeicons=\"Move01Icon\"\n          tabler=\"IconArrowsMove\"\n          phosphor=\"ArrowsOutCardinal\"\n          remixicon=\"RiDragMove2Line\"\n          size={size}\n          {...props}\n        />\n      );\n\n    default:\n      return (\n        <IconPlaceholder\n          lucide=\"Circle\"\n          hugeicons=\"CircleIcon\"\n          tabler=\"IconCircle\"\n          phosphor=\"Circle\"\n          remixicon=\"RiCircleLine\"\n          size={size}\n          {...props}\n        />\n      );\n  }\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/field-icon.tsx"
    },
    {
      "path": "registry/shadcn/builder/field-sidebar.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport {\n  BuilderSidebar,\n  DraggableSidebarItem,\n} from \"@buildnbuzz/form-builder-react\";\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarGroup,\n  SidebarGroupContent,\n  SidebarGroupLabel,\n  SidebarMenu,\n  SidebarMenuItem,\n  SidebarMenuButton,\n} from \"@/components/ui/sidebar\";\nimport { FieldIcon } from \"./field-icon\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Visual field palette for the form builder.\n * Grouped by category and draggable into the canvas.\n */\nexport const FieldSidebar = () => {\n  return (\n    <Sidebar className=\"h-full bg-background\" collapsible=\"none\">\n      <SidebarContent>\n        <BuilderSidebar\n          render={({ groups }) => (\n            <>\n              {Object.entries(groups).map(([category, items]) => (\n                <SidebarGroup key={category}>\n                  <SidebarGroupLabel>\n                    {category}\n                  </SidebarGroupLabel>\n                  <SidebarGroupContent>\n                    <SidebarMenu>\n                      {items.map((item) => (\n                        <DraggableSidebarItem\n                          key={item.type}\n                          type={item.type}\n                          render={({\n                            setNodeRef,\n                            attributes,\n                            listeners,\n                            isDragging,\n                          }) => {\n                            const disabled = item.disabled;\n\n                            return (\n                              <SidebarMenuItem key={item.type}>\n                                <SidebarMenuButton\n                                  ref={setNodeRef}\n                                  {...listeners}\n                                  {...attributes}\n                                  className={cn(\n                                    \"cursor-grab group relative\",\n                                    disabled && \"cursor-not-allowed opacity-50\",\n                                    isDragging && \"opacity-40 bg-muted/50\",\n                                  )}\n                                  // disabled={disabled} // DraggableSidebarItem handles disabled state\n                                >\n                                  <FieldIcon type={item.type} size={16} />\n                                  <span>{item.label}</span>\n                                  {disabled && (\n                                    <Badge\n                                      variant=\"outline\"\n                                      className=\"ml-auto text-[10px] h-5 px-1.5 py-0 bg-transparent text-muted-foreground border-muted-foreground/40\"\n                                    >\n                                      Coming Soon\n                                    </Badge>\n                                  )}\n                                </SidebarMenuButton>\n                              </SidebarMenuItem>\n                            );\n                          }}\n                        />\n                      ))}\n                    </SidebarMenu>\n                  </SidebarGroupContent>\n                </SidebarGroup>\n              ))}\n            </>\n          )}\n        />\n      </SidebarContent>\n    </Sidebar>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/field-sidebar.tsx"
    },
    {
      "path": "registry/shadcn/builder/form-builder.tsx",
      "content": "\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport {\n  BuilderDndProvider,\n  BuilderCanvas as HeadlessCanvas,\n  useBuilderStore,\n  DefaultBuilderProvider,\n  BuilderFormProvider,\n  getBrowserLocalStorageProvider,\n} from \"@buildnbuzz/form-builder-react\";\nimport { type BuilderStorageProvider } from \"@buildnbuzz/form-builder-core\";\nimport { SHADCN_BUILDER_REGISTRY } from \"./registry\";\nimport { SiteHeader } from \"./header\";\n\nimport { FieldSidebar } from \"./field-sidebar\";\nimport { NodeWrapper } from \"./node-wrapper\";\nimport { PropertyPanel } from \"./property-panel\";\nimport { DragOverlayItem } from \"./drag-overlay\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { Button } from \"@/components/ui/button\";\nimport { useDroppable } from \"@dnd-kit/core\";\nimport {\n  SortableContext,\n  verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { cn } from \"@/lib/utils\";\nimport { SidebarProvider } from \"@/components/ui/sidebar\";\nimport { CanvasToolbar } from \"./canvas/canvas-toolbar\";\nimport { MobileOverlay } from \"./mobile-overlay\";\nimport { toast } from \"sonner\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport {\n  Empty,\n  EmptyContent,\n  EmptyDescription,\n  EmptyMedia,\n  EmptyTitle,\n} from \"@/components/ui/empty\";\n\n// Inline SubmitToastContent\nfunction SubmitToastContent({ data }: { data: Record<string, unknown> }) {\n  const [copied, setCopied] = useState(false);\n\n  const handleCopy = () => {\n    navigator.clipboard.writeText(JSON.stringify(data, null, 2));\n    setCopied(true);\n    setTimeout(() => setCopied(false), 2000);\n  };\n\n  return (\n    <div className=\"relative mt-2 w-full\">\n      <Button\n        variant=\"ghost\"\n        size=\"icon\"\n        onClick={handleCopy}\n        className=\"absolute right-2 top-2 h-7 w-7\"\n        title=\"Copy JSON\"\n      >\n        {copied ? (\n          <IconPlaceholder\n            lucide=\"Check\"\n            hugeicons=\"Tick01Icon\"\n            tabler=\"IconCheck\"\n            phosphor=\"Check\"\n            remixicon=\"RiCheckLine\"\n            size={14}\n            className=\"text-primary\"\n          />\n        ) : (\n          <IconPlaceholder\n            lucide=\"Copy\"\n            hugeicons=\"Copy01Icon\"\n            tabler=\"IconCopy\"\n            phosphor=\"Copy\"\n            remixicon=\"RiFileCopyLine\"\n            size={14}\n          />\n        )}\n      </Button>\n      <pre className=\"max-h-75 overflow-auto rounded-md bg-muted p-3 pt-6 text-xs text-muted-foreground sm:p-3 sm:pr-10 sm:pt-3\">\n        <code>{JSON.stringify(data, null, 2)}</code>\n      </pre>\n    </div>\n  );\n}\n\nconst EmptyCanvas = () => {\n  return (\n    <Empty className=\"relative z-10 h-full border-0 bg-transparent min-h-60 pointer-events-none select-none\">\n      <EmptyMedia>\n        <IconPlaceholder\n          lucide=\"MousePointerClick\"\n          hugeicons=\"DragDropIcon\"\n          tabler=\"IconHandClick\"\n          phosphor=\"HandArrowUp\"\n          remixicon=\"RiDragDropLine\"\n          size={24}\n        />\n      </EmptyMedia>\n      <EmptyContent className=\"max-w-[70%]\">\n        <EmptyTitle className=\"text-sm font-medium\">Empty Canvas</EmptyTitle>\n        <EmptyDescription className=\"text-xs\">\n          Drag components from the left sidebar to start building your form.\n        </EmptyDescription>\n      </EmptyContent>\n    </Empty>\n  );\n};\n\ninterface WindowFrameProps {\n  children: React.ReactNode;\n  className?: string;\n}\n\nexport function WindowFrame({ children, className }: WindowFrameProps) {\n  const viewport = useBuilderStore((state) => state.viewport);\n  const zoom = useBuilderStore((state) => state.zoom);\n  const mode = useBuilderStore((state) => state.mode);\n\n  const getViewportWidth = () => {\n    switch (viewport) {\n      case \"mobile\":\n        return \"375px\";\n      case \"tablet\":\n        return \"768px\";\n      default:\n        return \"100%\";\n    }\n  };\n\n  return (\n    <div\n      className={cn(\n        \"bg-background h-160 border border-border rounded-xl shadow-[0_0_60px_-5px_hsl(var(--primary)/0.4)] flex flex-col relative transition-all duration-300 ease-in-out origin-top overflow-hidden\",\n        className,\n      )}\n      style={{\n        transform: `scale(${zoom})`,\n        width: getViewportWidth(),\n        maxWidth: viewport === \"desktop\" ? \"896px\" : getViewportWidth(),\n      }}\n    >\n      <div className=\"h-10 bg-muted/50 border-b flex items-center px-4 justify-between shrink-0\">\n        <div className=\"flex items-center gap-1.5 w-20\">\n          <div className=\"w-3 h-3 rounded-full bg-destructive/80\" />\n          <div className=\"w-3 h-3 rounded-full bg-yellow-500/80\" />\n          <div className=\"w-3 h-3 rounded-full bg-green-500/80\" />\n        </div>\n        <div className=\"text-xs text-muted-foreground font-medium flex-1 text-center\">\n          {mode === \"preview\" ? \"Preview Mode\" : \"Edit Mode\"}\n        </div>\n        <div className=\"w-20\" />\n      </div>\n\n      {/* Content Area */}\n      <ScrollArea className=\"flex-1 overflow-hidden\">{children}</ScrollArea>\n    </div>\n  );\n}\n\nimport { PreviewForm } from \"./preview/preview-form\";\n\n/**\n * Centered frame for the canvas to simulate different viewports.\n */\nconst CanvasFrame = () => {\n  const rootIds = useBuilderStore((s) => s.rootIds);\n  const mode = useBuilderStore((s) => s.mode);\n  const selectNode = useBuilderStore((s) => s.selectNode);\n\n  const isPreviewMode = mode === \"preview\";\n\n  const { setNodeRef } = useDroppable({\n    id: \"root\",\n    disabled: isPreviewMode,\n  });\n\n  const handleBackgroundClick = () => {\n    if (!isPreviewMode) {\n      selectNode(null);\n    }\n  };\n\n  return (\n    <div\n      className=\"p-8 pt-10 flex justify-center items-start min-h-full\"\n      onClick={handleBackgroundClick}\n    >\n      <WindowFrame>\n        <div\n          ref={isPreviewMode ? undefined : setNodeRef}\n          className=\"p-8 max-w-2xl mx-auto min-h-full relative\"\n          data-id=\"root\"\n        >\n          {rootIds.length === 0 ? (\n            <EmptyCanvas />\n          ) : isPreviewMode ? (\n            <PreviewForm />\n          ) : (\n            <div className=\"min-h-120 relative\">\n              <SortableContext\n                items={rootIds}\n                strategy={verticalListSortingStrategy}\n              >\n                <HeadlessCanvas\n                  nodeRenderer={({ node, content }) => (\n                    <NodeWrapper node={node}>{content}</NodeWrapper>\n                  )}\n                />\n              </SortableContext>\n            </div>\n          )}\n        </div>\n      </WindowFrame>\n    </div>\n  );\n};\n\n/**\n * Main Form Builder component that orchestrates the entire UI.\n */\nconst NEW_BUILDER_STORAGE_NAMESPACE = \"buzzform-builder:v2:forms\";\n\nexport const FormBuilder = () => {\n  const storageProvider = React.useMemo(() => {\n    if (typeof window === \"undefined\") return null;\n    try {\n      return getBrowserLocalStorageProvider(NEW_BUILDER_STORAGE_NAMESPACE);\n    } catch {\n      return null;\n    }\n  }, []);\n\n  return (\n    <DefaultBuilderProvider\n      registry={SHADCN_BUILDER_REGISTRY}\n      storageProvider={storageProvider}\n    >\n      <FormBuilderContent storageProvider={storageProvider} />\n    </DefaultBuilderProvider>\n  );\n};\n\n/**\n * Inner component that uses builder hooks.\n */\nconst FormBuilderContent = ({\n  storageProvider,\n}: {\n  storageProvider: BuilderStorageProvider | null;\n}) => {\n  const mounted = React.useSyncExternalStore(\n    () => () => {},\n    () => true,\n    () => false,\n  );\n  const containerRef = useRef<HTMLDivElement>(null);\n  const zoom = useBuilderStore((state) => state.zoom);\n  const setZoom = useBuilderStore((state) => state.setZoom);\n  const mode = useBuilderStore((s) => s.mode);\n\n  const onSubmit = async (data: Record<string, unknown>) => {\n    await new Promise((r) => setTimeout(r, 500));\n    toast(\"Form Submitted!\", {\n      description: <SubmitToastContent data={data} />,\n      duration: 10000,\n    });\n  };\n\n  // Handle Ctrl+Wheel zoom\n  useEffect(() => {\n    if (!mounted) return;\n    const container = containerRef.current;\n    if (!container) return;\n\n    const handleWheel = (e: WheelEvent) => {\n      if (e.ctrlKey) {\n        e.preventDefault();\n        const delta = e.deltaY * -0.002;\n        const nextZoom = Math.round((zoom + delta) * 100) / 100;\n        // Clamp zoom between 0.25 and 2\n        const clampedZoom = Math.max(0.25, Math.min(2, nextZoom));\n        setZoom(clampedZoom);\n      }\n    };\n\n    container.addEventListener(\"wheel\", handleWheel, { passive: false });\n    return () => container.removeEventListener(\"wheel\", handleWheel);\n  }, [zoom, setZoom, mounted]);\n\n  if (!mounted) return null;\n\n  return (\n    <BuilderDndProvider\n      renderOverlay={({ activeId, activeData }) => (\n        <DragOverlayItem activeId={activeId} activeData={activeData} />\n      )}\n    >\n      <BuilderFormProvider mode={mode} onSubmit={onSubmit}>\n        <MobileOverlay />\n        <div className=\"flex flex-col h-screen w-full bg-muted/30 overflow-hidden text-foreground\">\n          {/* Top Header */}\n          <SiteHeader storageProvider={storageProvider} />\n\n          {/* Main Layout */}\n          <SidebarProvider className=\"flex-1 overflow-hidden min-h-0 min-w-0\">\n            <div className=\"flex h-full w-full\">\n              {/* Left Sidebar: Components */}\n              <div\n                className={cn(\n                  \"border-r bg-background transition-all duration-300 ease-in-out\",\n                  mode === \"preview\"\n                    ? \"w-0 opacity-0 overflow-hidden border-none\"\n                    : \"w-64\",\n                )}\n              >\n                <div className=\"w-64\">\n                  <FieldSidebar />\n                </div>\n              </div>\n\n              {/* Central Canvas */}\n              <main className=\"flex-1 flex flex-col relative overflow-hidden bg-muted/20 min-w-0\">\n                <CanvasToolbar />\n                <div ref={containerRef} className=\"flex-1 min-h-0\">\n                  <div className=\"h-full overflow-auto [&::-webkit-scrollbar]:hidden [scrollbar-width:none] bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] dark:bg-[radial-gradient(#1f2937_1px,transparent_1px)] bg-size-[20px_20px]\">\n                    <CanvasFrame />\n                  </div>\n                </div>\n              </main>\n\n              {/* Right Sidebar: Properties */}\n              <aside\n                className={cn(\n                  \"border-l bg-background flex flex-col shrink-0 transition-all duration-300 ease-in-out\",\n                  mode === \"preview\"\n                    ? \"w-0 opacity-0 overflow-hidden border-none\"\n                    : \"w-80\",\n                )}\n              >\n                <div className=\"w-80 h-full flex flex-col\">\n                  <PropertyPanel />\n                </div>\n              </aside>\n            </div>\n          </SidebarProvider>\n        </div>\n      </BuilderFormProvider>\n    </BuilderDndProvider>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/form-builder.tsx"
    },
    {
      "path": "registry/shadcn/builder/header/cloud-save-dialog.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n  DialogFooter,\n} from \"@/components/ui/dialog\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { CloudServerIcon } from \"@hugeicons/core-free-icons\";\nimport { Sparkles } from \"lucide-react\";\nimport { joinWaitlist } from \"@/app/(builder)/lib/actions\";\nimport { toast } from \"sonner\";\nimport { createSchema, InferType } from \"@buildnbuzz/buzzform\";\nimport {\n  Form,\n  FormContent,\n  FormFields,\n  FormSubmit,\n  FormAction,\n} from \"@/registry/base/form\";\nimport Link from \"next/link\";\n\nconst waitlistSchema = createSchema([\n  {\n    type: \"email\",\n    name: \"email\",\n    label: \"Email Address\",\n    placeholder: \"you@example.com\",\n    required: true,\n    description: (\n      <span className=\"text-xs\">\n        By joining, you agree to our{\" \"}\n        <Link\n          href=\"/terms\"\n          className=\"underline hover:text-primary underline-offset-4\"\n        >\n          Terms\n        </Link>{\" \"}\n        and{\" \"}\n        <Link\n          href=\"/privacy\"\n          className=\"underline hover:text-primary underline-offset-4\"\n        >\n          Privacy Policy\n        </Link>\n        .\n      </span>\n    ),\n  },\n]);\n\nexport type WaitlistData = InferType<typeof waitlistSchema>;\n\nexport function CloudSaveDialog() {\n  const [open, setOpen] = useState(false);\n\n  const handleSubmit = async (data: WaitlistData) => {\n    try {\n      const result = await joinWaitlist(data.email);\n\n      if (result.error) {\n        toast.error(result.error);\n      } else {\n        toast.success(result.message || \"You've been added to the waitlist!\");\n        setOpen(false);\n      }\n    } catch {\n      toast.error(\"Something went wrong. Please try again.\");\n    }\n  };\n\n  return (\n    <Dialog open={open} onOpenChange={setOpen}>\n      <DialogTrigger\n        render={\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"gap-2 h-8 hidden sm:flex\"\n          >\n            <HugeiconsIcon icon={CloudServerIcon} size={16} />\n            Save\n          </Button>\n        }\n      />\n      <DialogContent className=\"sm:max-w-md\">\n        <DialogHeader>\n          <DialogTitle className=\"flex items-center gap-2\">\n            <HugeiconsIcon\n              icon={CloudServerIcon}\n              className=\"text-primary h-6 w-6\"\n            />\n            Save & Sync\n          </DialogTitle>\n          <DialogDescription>\n            Never lose your work again. Save your forms to the cloud, access\n            version history, and create your central form repository.\n          </DialogDescription>\n        </DialogHeader>\n\n        <div className=\"flex flex-col\">\n          <div className=\"bg-primary/5 border border-primary/20 rounded-lg p-3 text-sm flex gap-3 text-primary mb-6\">\n            <Sparkles className=\"h-5 w-5 shrink-0 mt-0.5\" />\n            <div>\n              <p className=\"font-medium mb-1\">Coming Soon</p>\n              <p className=\"text-muted-foreground text-xs\">\n                We&apos;re currently building the persistence layer. Join the\n                waitlist to get <b>early access</b> and{\" \"}\n                <b>free cloud storage</b> when we launch.\n              </p>\n            </div>\n          </div>\n\n          <Form schema={waitlistSchema} onSubmit={handleSubmit}>\n            <FormContent className=\"space-y-4\">\n              <FormFields />\n              <DialogFooter>\n                <FormAction\n                  variant=\"ghost\"\n                  onClick={() => setOpen(false)}\n                  type=\"button\"\n                >\n                  Cancel\n                </FormAction>\n                <FormSubmit>Join Waitlist</FormSubmit>\n              </DialogFooter>\n            </FormContent>\n          </Form>\n        </div>\n      </DialogContent>\n    </Dialog>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/header/cloud-save-dialog.tsx"
    },
    {
      "path": "registry/shadcn/builder/header/form-manager-dialog.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { FormManagerNewPanel } from \"./form-manager-new-panel\";\nimport { FormManagerSavedPanel } from \"./form-manager-saved-panel\";\nimport type { BuilderStorageProvider } from \"@buildnbuzz/form-builder-core\";\n\nexport function FormManagerDialog({\n  storageProvider,\n}: {\n  storageProvider: BuilderStorageProvider | null;\n}) {\n  const [open, setOpen] = React.useState(false);\n\n  const handleDone = React.useCallback(() => setOpen(false), []);\n\n  return (\n    <Dialog open={open} onOpenChange={setOpen}>\n      <DialogTrigger\n        render={\n          <Button className=\"group gap-2\">\n            <IconPlaceholder\n              hugeicons=\"Add01Icon\"\n              lucide=\"Plus\"\n              tabler=\"IconPlus\"\n              phosphor=\"Plus\"\n              remixicon=\"RiAddLine\"\n              size={16}\n              strokeWidth={2}\n              className=\"transition-transform duration-300 group-hover:rotate-90\"\n            />\n            New\n          </Button>\n        }\n      />\n\n      <DialogContent className=\"sm:max-w-3xl\">\n        <DialogHeader>\n          <DialogTitle>Forms</DialogTitle>\n          <DialogDescription>\n            Create a new form, import a file, or open a previously saved form.\n          </DialogDescription>\n        </DialogHeader>\n\n        <Tabs defaultValue=\"new\">\n          <div className=\"flex justify-center\">\n            <TabsList className=\"grid w-full max-w-xs grid-cols-2 rounded-full bg-muted\">\n              <TabsTrigger value=\"new\" className=\"gap-2 rounded-full\">\n                <IconPlaceholder\n                  hugeicons=\"Add01Icon\"\n                  lucide=\"Plus\"\n                  tabler=\"IconPlus\"\n                  phosphor=\"Plus\"\n                  remixicon=\"RiAddLine\"\n                  size={16}\n                  strokeWidth={2}\n                />\n                New\n              </TabsTrigger>\n              <TabsTrigger value=\"saved\" className=\"gap-2 rounded-full\">\n                <IconPlaceholder\n                  hugeicons=\"FolderIcon\"\n                  lucide=\"Folder\"\n                  tabler=\"IconFolder\"\n                  phosphor=\"Folder\"\n                  remixicon=\"RiFolderLine\"\n                  size={16}\n                  strokeWidth={2}\n                />\n                Saved Forms\n              </TabsTrigger>\n            </TabsList>\n          </div>\n\n          <TabsContent value=\"new\">\n            <FormManagerNewPanel onDone={handleDone} />\n          </TabsContent>\n\n          <TabsContent value=\"saved\">\n            <FormManagerSavedPanel\n              onDone={handleDone}\n              storageProvider={storageProvider}\n            />\n          </TabsContent>\n        </Tabs>\n      </DialogContent>\n    </Dialog>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/header/form-manager-dialog.tsx"
    },
    {
      "path": "registry/shadcn/builder/header/form-manager-new-panel.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Alert, AlertDescription, AlertTitle } from \"@/components/ui/alert\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { useBuilderStore } from \"@buildnbuzz/form-builder-react\";\nimport { toast } from \"sonner\";\nimport {\n  parseImportedFormJson,\n  type ParsedImportPayload,\n} from \"@buildnbuzz/form-builder-core\";\n\nconst MIN_IMPORT_FEEDBACK_MS = 500;\n\ntype PendingImport = {\n  sourceName: string;\n  formName: string;\n  nodeCount: number;\n  state: ParsedImportPayload[\"state\"];\n  warnings?: string[];\n};\n\ntype FormManagerNewPanelProps = {\n  onDone: () => void;\n};\n\ntype FormManagerPendingImportStateProps = {\n  pendingImport: PendingImport;\n  isImporting: boolean;\n  onConfirmImport: () => void;\n  onClearSelection: () => void;\n};\n\ntype FormManagerPasteImportStateProps = {\n  value: string;\n  isImporting: boolean;\n  onChangeValue: (value: string) => void;\n  onBack: () => void;\n  onPasteFromClipboard: () => void;\n  onImport: () => void;\n  onDragOver: (event: React.DragEvent<HTMLDivElement>) => void;\n  onDrop: (event: React.DragEvent<HTMLDivElement>) => void;\n};\n\nfunction FormManagerPendingImportState({\n  pendingImport,\n  isImporting,\n  onConfirmImport,\n  onClearSelection,\n}: FormManagerPendingImportStateProps) {\n  return (\n    <div className=\"flex w-full flex-1 flex-col animate-in fade-in duration-200\">\n      <div className=\"flex flex-1 flex-col items-center justify-center gap-4 py-8\">\n        <div className=\"flex h-16 w-16 items-center justify-center rounded-full bg-primary/10 text-primary\">\n          <IconPlaceholder\n            hugeicons=\"File02Icon\"\n            lucide=\"File\"\n            tabler=\"IconFile\"\n            phosphor=\"File\"\n            remixicon=\"RiFileLine\"\n            size={32}\n            strokeWidth={1.5}\n          />\n        </div>\n\n        <div className=\"space-y-2 text-center\">\n          <h3 className=\"text-xl font-semibold tracking-tight\">\n            {pendingImport.formName}\n          </h3>\n          <p className=\"text-sm text-muted-foreground\">\n            {pendingImport.sourceName}\n          </p>\n          <div className=\"flex items-center justify-center gap-2\">\n            <span className=\"text-xs text-muted-foreground\">\n              {pendingImport.nodeCount} nodes\n            </span>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"mt-auto flex w-full flex-col gap-4 rounded-xl border bg-muted/30 p-4\">\n        {pendingImport.warnings && pendingImport.warnings.length > 0 && (\n          <Alert className=\"border-amber-500/30 bg-amber-500/10 text-amber-600 dark:border-amber-500/20 dark:text-amber-400\">\n            <div className=\"flex items-center gap-2\">\n              <IconPlaceholder\n                hugeicons=\"Alert01Icon\"\n                lucide=\"AlertTriangle\"\n                tabler=\"IconAlertTriangle\"\n                phosphor=\"Warning\"\n                remixicon=\"RiAlertFill\"\n                size={16}\n              />\n              <AlertTitle className=\"m-0 text-sm font-semibold\">\n                Legacy Schema Migrated\n              </AlertTitle>\n            </div>\n            <AlertDescription className=\"mt-2 max-h-32 overflow-y-auto\">\n              <ul className=\"ml-5 list-disc space-y-1 text-xs opacity-90\">\n                {pendingImport.warnings.map((warning, idx) => (\n                  <li key={idx}>{warning}</li>\n                ))}\n              </ul>\n            </AlertDescription>\n          </Alert>\n        )}\n\n        <div className=\"flex items-start gap-3\">\n          <div className=\"mt-0.5 text-amber-600 dark:text-amber-500\">\n            <IconPlaceholder\n              hugeicons=\"Alert01Icon\"\n              lucide=\"AlertCircle\"\n              tabler=\"IconAlertCircle\"\n              phosphor=\"WarningCircle\"\n              remixicon=\"RiAlertLine\"\n              size={18}\n              strokeWidth={2}\n            />\n          </div>\n          <div className=\"flex-1 space-y-0.5\">\n            <p className=\"text-sm font-medium leading-none\">\n              Replace current workspace?\n            </p>\n            <p className=\"text-xs text-muted-foreground\">\n              Continuing will overwrite any unsaved changes.\n            </p>\n          </div>\n        </div>\n\n        <div className=\"mt-1 grid grid-cols-2 gap-2\">\n          <Button\n            variant=\"outline\"\n            onClick={onClearSelection}\n            disabled={isImporting}\n          >\n            Cancel\n          </Button>\n          <Button onClick={onConfirmImport} disabled={isImporting}>\n            <IconPlaceholder\n              hugeicons=\"Upload01Icon\"\n              lucide=\"Upload\"\n              tabler=\"IconUpload\"\n              phosphor=\"UploadSimple\"\n              remixicon=\"RiUpload2Line\"\n              size={16}\n              className=\"mr-2\"\n              strokeWidth={2}\n            />\n            Import Now\n          </Button>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nfunction FormManagerPasteImportState({\n  value,\n  isImporting,\n  onChangeValue,\n  onBack,\n  onPasteFromClipboard,\n  onImport,\n  onDragOver,\n  onDrop,\n}: FormManagerPasteImportStateProps) {\n  return (\n    <div className=\"flex min-h-0 w-full flex-1 flex-col gap-3 animate-in fade-in duration-200\">\n      <div className=\"space-y-1\">\n        <h3 className=\"text-lg font-semibold tracking-tight\">Import JSON</h3>\n        <p className=\"text-sm text-muted-foreground\">\n          Paste a BuzzForm schema or Builder backup JSON.\n        </p>\n      </div>\n\n      <div\n        className=\"h-56 min-h-0 overflow-hidden rounded-lg border border-dashed border-border/70 p-2 transition-colors hover:border-primary/50\"\n        onDragOver={onDragOver}\n        onDrop={onDrop}\n      >\n        <Textarea\n          value={value}\n          onChange={(event) => onChangeValue(event.target.value)}\n          placeholder='[\\n  { \"type\": \"text\", \"name\": \"email\", \"label\": \"Email\" }\\n]'\n          wrap=\"off\"\n          className=\"h-full min-h-0 resize-none overflow-x-auto overflow-y-auto border-0 bg-transparent font-mono text-xs whitespace-pre shadow-none field-sizing-fixed focus-visible:ring-0\"\n        />\n      </div>\n\n      <div className=\"mt-auto flex flex-wrap justify-end gap-2\">\n        <Button variant=\"ghost\" onClick={onBack} disabled={isImporting}>\n          Back\n        </Button>\n        <Button\n          variant=\"outline\"\n          onClick={onPasteFromClipboard}\n          disabled={isImporting}\n        >\n          <IconPlaceholder\n            hugeicons=\"Copy01Icon\"\n            lucide=\"Copy\"\n            tabler=\"IconCopy\"\n            phosphor=\"Copy\"\n            remixicon=\"RiFileCopyLine\"\n            size={16}\n            className=\"mr-2\"\n            strokeWidth={2}\n          />\n          Paste from Clipboard\n        </Button>\n        <Button\n          onClick={onImport}\n          disabled={isImporting || value.trim().length === 0}\n        >\n          {isImporting ? (\n            <Spinner className=\"mr-2 size-4\" />\n          ) : (\n            <IconPlaceholder\n              hugeicons=\"Upload01Icon\"\n              lucide=\"Upload\"\n              tabler=\"IconUpload\"\n              phosphor=\"UploadSimple\"\n              remixicon=\"RiUpload2Line\"\n              size={16}\n              className=\"mr-2\"\n              strokeWidth={2}\n            />\n          )}\n          Validate JSON\n        </Button>\n      </div>\n    </div>\n  );\n}\n\nexport function FormManagerNewPanel({ onDone }: FormManagerNewPanelProps) {\n  const [isImporting, setIsImporting] = React.useState(false);\n  const [pendingImport, setPendingImport] =\n    React.useState<PendingImport | null>(null);\n  const [importError, setImportError] = React.useState<string | null>(null);\n  const [isPasteMode, setIsPasteMode] = React.useState(false);\n  const [pastedJson, setPastedJson] = React.useState(\"\");\n\n  const fileInputRef = React.useRef<HTMLInputElement | null>(null);\n  const clearState = useBuilderStore((state) => state.clearState);\n  const loadDocumentState = useBuilderStore((state) => state.loadDocumentState);\n\n  const resetImportState = React.useCallback(() => {\n    setIsImporting(false);\n    setPendingImport(null);\n    setImportError(null);\n  }, []);\n\n  const handleNewForm = () => {\n    clearState();\n    onDone();\n  };\n\n  const handleConfirmImport = () => {\n    if (!pendingImport) return;\n    loadDocumentState(\n      pendingImport.state as Parameters<typeof loadDocumentState>[0],\n    );\n    toast.success(`Imported \"${pendingImport.formName}\"`);\n    onDone();\n  };\n\n  const handleImportClick = () => {\n    if (isImporting) return;\n    fileInputRef.current?.click();\n  };\n\n  const handleOpenPasteMode = () => {\n    if (isImporting) return;\n    setImportError(null);\n    setIsPasteMode(true);\n  };\n\n  const handleClosePasteMode = () => {\n    if (isImporting) return;\n    setImportError(null);\n    setIsPasteMode(false);\n  };\n\n  const processImportJson = React.useCallback(\n    async ({\n      json,\n      sourceName,\n      schemaFileNameHint,\n      closePasteModeOnSuccess,\n    }: {\n      json: string;\n      sourceName: string;\n      schemaFileNameHint?: string;\n      closePasteModeOnSuccess: boolean;\n    }) => {\n      const startedAt = Date.now();\n      setImportError(null);\n      setPendingImport(null);\n      setIsImporting(true);\n\n      try {\n        const parsed = parseImportedFormJson(json);\n        const importedState =\n          schemaFileNameHint && parsed.state.formName === \"Imported Form\"\n            ? {\n                ...parsed.state,\n                formName: schemaFileNameHint,\n              }\n            : parsed.state;\n\n        setPendingImport({\n          sourceName,\n          formName: importedState.formName,\n          nodeCount: Object.keys(importedState.nodes).length,\n          state: importedState,\n          warnings: parsed.warnings,\n        });\n\n        if (closePasteModeOnSuccess) {\n          setIsPasteMode(false);\n        }\n      } catch (error) {\n        const rawMessage =\n          error instanceof Error ? error.message : \"Failed to import JSON.\";\n        const message = `Invalid import JSON: ${rawMessage}`;\n        setImportError(message);\n        toast.error(message);\n      } finally {\n        const elapsed = Date.now() - startedAt;\n        if (elapsed < MIN_IMPORT_FEEDBACK_MS) {\n          await new Promise((resolve) =>\n            setTimeout(resolve, MIN_IMPORT_FEEDBACK_MS - elapsed),\n          );\n        }\n        setIsImporting(false);\n      }\n    },\n    [],\n  );\n\n  const handleFileImport = async (\n    event: React.ChangeEvent<HTMLInputElement>,\n  ) => {\n    const file = event.target.files?.[0];\n    event.target.value = \"\";\n    if (!file) return;\n\n    const contents = await file.text();\n    await processImportJson({\n      json: contents,\n      sourceName: file.name,\n      schemaFileNameHint: toFormNameHint(file.name),\n      closePasteModeOnSuccess: false,\n    });\n  };\n\n  const handleImportPastedJson = async () => {\n    const trimmedJson = pastedJson.trim();\n    if (!trimmedJson) {\n      const message = \"Paste JSON content before importing.\";\n      setImportError(message);\n      toast.error(message);\n      return;\n    }\n\n    await processImportJson({\n      json: trimmedJson,\n      sourceName: \"Pasted JSON\",\n      closePasteModeOnSuccess: true,\n    });\n  };\n\n  const handlePasteFromClipboard = async () => {\n    if (typeof navigator === \"undefined\" || !navigator.clipboard?.readText) {\n      toast.error(\"Clipboard access is not available. Paste manually.\");\n      return;\n    }\n\n    try {\n      const clipboardText = await navigator.clipboard.readText();\n      if (!clipboardText.trim()) {\n        toast.error(\"Clipboard is empty.\");\n        return;\n      }\n\n      setPastedJson(clipboardText);\n      setImportError(null);\n      toast.success(\"Pasted JSON from clipboard\");\n    } catch {\n      toast.error(\"Clipboard access was denied. Paste JSON manually.\");\n    }\n  };\n\n  const handlePasteDropZoneDragOver = (\n    event: React.DragEvent<HTMLDivElement>,\n  ) => {\n    event.preventDefault();\n  };\n\n  const handlePasteDropZoneDrop = async (\n    event: React.DragEvent<HTMLDivElement>,\n  ) => {\n    event.preventDefault();\n    if (isImporting) return;\n\n    const file = event.dataTransfer.files?.[0];\n    if (file) {\n      try {\n        const droppedContents = await file.text();\n        if (!droppedContents.trim()) {\n          toast.error(\"Dropped file is empty.\");\n          return;\n        }\n        setPastedJson(droppedContents);\n        setImportError(null);\n        toast.success(`Loaded JSON from \"${file.name}\"`);\n      } catch {\n        toast.error(\"Failed to read dropped file.\");\n      }\n      return;\n    }\n\n    const droppedText = event.dataTransfer.getData(\"text/plain\");\n    if (!droppedText.trim()) {\n      toast.error(\"Dropped content is empty.\");\n      return;\n    }\n\n    setPastedJson(droppedText);\n    setImportError(null);\n    toast.success(\"Loaded dropped text\");\n  };\n\n  React.useEffect(() => resetImportState, [resetImportState]);\n\n  const hasPendingImport =\n    pendingImport !== null && !isImporting && !importError;\n\n  return (\n    <div className=\"flex min-h-80 flex-col gap-3\">\n      <div className=\"flex flex-1 p-4\">\n        {hasPendingImport ? (\n          <FormManagerPendingImportState\n            pendingImport={pendingImport}\n            isImporting={isImporting}\n            onConfirmImport={handleConfirmImport}\n            onClearSelection={resetImportState}\n          />\n        ) : isPasteMode ? (\n          <FormManagerPasteImportState\n            value={pastedJson}\n            isImporting={isImporting}\n            onChangeValue={setPastedJson}\n            onBack={handleClosePasteMode}\n            onPasteFromClipboard={handlePasteFromClipboard}\n            onImport={handleImportPastedJson}\n            onDragOver={handlePasteDropZoneDragOver}\n            onDrop={handlePasteDropZoneDrop}\n          />\n        ) : (\n          <div className=\"grid w-full flex-1 gap-4 sm:grid-cols-3\">\n            <Card\n              className=\"group flex cursor-pointer flex-col justify-center transition-all duration-200 hover:ring-1 hover:ring-primary/50\"\n              onClick={handleNewForm}\n            >\n              <CardContent className=\"flex justify-center pb-2 pt-6\">\n                <IconPlaceholder\n                  hugeicons=\"Add01Icon\"\n                  lucide=\"Plus\"\n                  tabler=\"IconPlus\"\n                  phosphor=\"Plus\"\n                  remixicon=\"RiAddLine\"\n                  size={32}\n                  strokeWidth={1.5}\n                  className=\"text-muted-foreground transition-all duration-300 group-hover:scale-110 group-hover:rotate-90 group-hover:text-primary\"\n                />\n              </CardContent>\n              <CardHeader className=\"justify-center text-center\">\n                <CardTitle className=\"text-lg\">Start Blank</CardTitle>\n                <CardDescription>Create a fresh empty form</CardDescription>\n              </CardHeader>\n            </Card>\n\n            <Card\n              className=\"group flex cursor-pointer flex-col justify-center transition-all duration-200 hover:ring-1 hover:ring-primary/50\"\n              onClick={handleImportClick}\n            >\n              <CardContent className=\"flex justify-center pb-2 pt-6\">\n                {isImporting ? (\n                  <div className=\"flex items-center justify-center p-2 text-muted-foreground transition-colors group-hover:text-primary\">\n                    <Spinner className=\"size-10\" />\n                  </div>\n                ) : (\n                  <IconPlaceholder\n                    hugeicons=\"Upload01Icon\"\n                    lucide=\"Upload\"\n                    tabler=\"IconUpload\"\n                    phosphor=\"UploadSimple\"\n                    remixicon=\"RiUpload2Line\"\n                    size={32}\n                    strokeWidth={1.5}\n                    className=\"text-muted-foreground transition-all duration-300 group-hover:-translate-y-1 group-hover:scale-110 group-hover:text-primary\"\n                  />\n                )}\n              </CardContent>\n              <CardHeader className=\"justify-center text-center\">\n                <CardTitle className=\"text-lg\">\n                  {isImporting ? \"Validating File\" : \"Import File\"}\n                </CardTitle>\n                <CardDescription>\n                  {isImporting\n                    ? \"Checking JSON before import\"\n                    : \"Load .json from disk\"}\n                </CardDescription>\n              </CardHeader>\n            </Card>\n\n            <Card\n              className=\"group flex cursor-pointer flex-col justify-center transition-all duration-200 hover:ring-1 hover:ring-primary/50\"\n              onClick={handleOpenPasteMode}\n            >\n              <CardContent className=\"flex justify-center pb-2 pt-6\">\n                <IconPlaceholder\n                  hugeicons=\"Copy01Icon\"\n                  lucide=\"Copy\"\n                  tabler=\"IconCopy\"\n                  phosphor=\"Copy\"\n                  remixicon=\"RiFileCopyLine\"\n                  size={32}\n                  strokeWidth={1.5}\n                  className=\"text-muted-foreground transition-all duration-300 group-hover:-translate-y-1 group-hover:scale-110 group-hover:text-primary\"\n                />\n              </CardContent>\n              <CardHeader className=\"justify-center text-center\">\n                <CardTitle className=\"text-lg\">Import JSON</CardTitle>\n                <CardDescription>Paste schema from clipboard</CardDescription>\n              </CardHeader>\n            </Card>\n          </div>\n        )}\n      </div>\n\n      {importError && (\n        <Alert variant=\"destructive\">\n          <IconPlaceholder\n            hugeicons=\"Alert01Icon\"\n            lucide=\"AlertCircle\"\n            tabler=\"IconAlertCircle\"\n            phosphor=\"WarningCircle\"\n            remixicon=\"RiAlertLine\"\n            size={16}\n          />\n          <AlertTitle>Import Failed</AlertTitle>\n          <AlertDescription>{importError}</AlertDescription>\n        </Alert>\n      )}\n\n      <input\n        ref={fileInputRef}\n        type=\"file\"\n        accept=\".json,application/json\"\n        className=\"hidden\"\n        onChange={handleFileImport}\n      />\n    </div>\n  );\n}\n\nfunction toFormNameHint(sourceName: string): string | undefined {\n  const normalizedBase = sourceName\n    .replace(/\\.[^/.]+$/, \"\")\n    .replace(/[_-]+/g, \" \")\n    .replace(/\\s+/g, \" \")\n    .trim();\n\n  if (normalizedBase.length === 0) {\n    return undefined;\n  }\n\n  return normalizedBase\n    .split(\" \")\n    .map((segment) => {\n      if (segment.length === 0) return segment;\n      return segment[0]!.toUpperCase() + segment.slice(1).toLowerCase();\n    })\n    .join(\" \");\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/header/form-manager-new-panel.tsx"
    },
    {
      "path": "registry/shadcn/builder/header/form-manager-saved-panel.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Empty,\n  EmptyDescription,\n  EmptyHeader,\n  EmptyMedia,\n  EmptyTitle,\n} from \"@/components/ui/empty\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport type {\n  FormSummary,\n  BuilderStorageProvider,\n} from \"@buildnbuzz/form-builder-core\";\nimport { toSafeFileName, fieldsToBuilderState } from \"@buildnbuzz/form-builder-core\";\nimport { useBuilderStore, downloadTextFile } from \"@buildnbuzz/form-builder-react\";\nimport type { Field } from \"@buildnbuzz/form-core\";\nimport { toast } from \"sonner\";\n\nconst dateFormatter = new Intl.DateTimeFormat(undefined, {\n  dateStyle: \"medium\",\n  timeStyle: \"short\",\n});\n\ntype FormManagerSavedPanelProps = {\n  onDone: () => void;\n  storageProvider: BuilderStorageProvider | null;\n};\n\nexport function FormManagerSavedPanel({\n  onDone,\n  storageProvider,\n}: FormManagerSavedPanelProps) {\n  const [forms, setForms] = React.useState<FormSummary[]>([]);\n  const [isLoading, setIsLoading] = React.useState(false);\n  const [loadError, setLoadError] = React.useState<string | null>(null);\n  const [openingFormId, setOpeningFormId] = React.useState<string | null>(null);\n  const [removingFormId, setRemovingFormId] = React.useState<string | null>(\n    null,\n  );\n  const [downloadingFormId, setDownloadingFormId] = React.useState<\n    string | null\n  >(null);\n\n  const loadDocumentState = useBuilderStore((state) => state.loadDocumentState);\n  const currentFormId = useBuilderStore((state) => state.formId);\n\n  const loadForms = React.useCallback(async () => {\n    setIsLoading(true);\n    setLoadError(null);\n\n    try {\n      if (!storageProvider) return;\n      const items = await storageProvider.list();\n      setForms(items);\n    } catch (error) {\n      const message =\n        error instanceof Error ? error.message : \"Failed to load forms.\";\n      setLoadError(message);\n    } finally {\n      setIsLoading(false);\n    }\n  }, [storageProvider]);\n\n  React.useEffect(() => {\n    void loadForms();\n  }, [loadForms]);\n\n  const handleOpenForm = async (formId: string) => {\n    setOpeningFormId(formId);\n\n    try {\n      if (!storageProvider) return;\n      const document = await storageProvider.load(formId);\n      if (!document) throw new Error(\"Document not found\");\n      const { nodes, rootIds } = fieldsToBuilderState(\n        document.fields as readonly Field[],\n      );\n\n      loadDocumentState({\n        nodes,\n        rootIds,\n        formId: document.id || formId,\n        formName: document.title || \"Untitled\",\n      });\n      onDone();\n      toast.success(`Opened \"${document.title || \"Untitled\"}\"`);\n    } catch (error) {\n      const message =\n        error instanceof Error ? error.message : \"Failed to open form.\";\n      toast.error(message);\n    } finally {\n      setOpeningFormId(null);\n    }\n  };\n\n  const handleRemoveForm = async (form: FormSummary) => {\n    if (\n      !window.confirm(\n        `Remove \"${form.formName}\" from local saved forms? This does not affect the currently open editor until you switch forms.`,\n      )\n    ) {\n      return;\n    }\n\n    setRemovingFormId(form.formId);\n\n    try {\n      if (!storageProvider) return;\n      await storageProvider.remove(form.formId);\n      setForms((prev) => prev.filter((item) => item.formId !== form.formId));\n      toast.success(`Removed \"${form.formName}\"`);\n    } catch (error) {\n      const message =\n        error instanceof Error ? error.message : \"Failed to remove form.\";\n      toast.error(message);\n    } finally {\n      setRemovingFormId(null);\n    }\n  };\n\n  const handleDownloadForm = async (form: FormSummary) => {\n    setDownloadingFormId(form.formId);\n\n    try {\n      if (!storageProvider) return;\n      const document = await storageProvider.load(form.formId);\n      if (!document) throw new Error(\"Document not found\");\n      const fileName = `${toSafeFileName(document.title || \"Untitled\")}.json`;\n\n      downloadTextFile(\n        JSON.stringify(document, null, 2),\n        fileName,\n        \"application/json\",\n      );\n      toast.success(`Downloaded \"${document.title || \"Untitled\"}\"`);\n    } catch (error) {\n      const message =\n        error instanceof Error ? error.message : \"Failed to download form.\";\n      toast.error(message);\n    } finally {\n      setDownloadingFormId(null);\n    }\n  };\n\n  return (\n    <div className=\"flex min-h-80 flex-col gap-3\">\n      {isLoading ? (\n        <div className=\"flex h-64 items-center justify-center gap-2 text-sm text-muted-foreground\">\n          <Spinner className=\"size-4\" />\n          Loading saved forms...\n        </div>\n      ) : loadError ? (\n        <div className=\"flex h-64 flex-col items-center justify-center gap-3 text-center\">\n          <p className=\"text-sm text-destructive\">{loadError}</p>\n          <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={loadForms}>\n            Retry\n          </Button>\n        </div>\n      ) : forms.length === 0 ? (\n        <Empty className=\"min-h-64\">\n          <EmptyHeader>\n            <EmptyMedia variant=\"icon\">\n              <IconPlaceholder\n                hugeicons=\"FolderIcon\"\n                lucide=\"Folder\"\n                tabler=\"IconFolder\"\n                phosphor=\"Folder\"\n                remixicon=\"RiFolderLine\"\n                size={16}\n                strokeWidth={2}\n              />\n            </EmptyMedia>\n            <EmptyTitle>No saved forms yet</EmptyTitle>\n            <EmptyDescription>\n              Forms appear here after you edit and save them locally.\n            </EmptyDescription>\n          </EmptyHeader>\n        </Empty>\n      ) : (\n        <>\n          <div className=\"rounded-lg border\">\n            <ScrollArea className=\"h-72 w-full\">\n              <div className=\"space-y-2 p-2\">\n                {forms.map((form) => {\n                  const isOpening = openingFormId === form.formId;\n                  const isRemoving = removingFormId === form.formId;\n                  const isDownloading = downloadingFormId === form.formId;\n                  const isBusy = isOpening || isRemoving || isDownloading;\n                  const isCurrent = currentFormId === form.formId;\n\n                  return (\n                    <div\n                      key={form.formId}\n                      className=\"flex items-start gap-3 rounded-md border p-3\"\n                    >\n                      <div className=\"mt-0.5 rounded-md border bg-muted p-1.5\">\n                        <IconPlaceholder\n                          hugeicons=\"InputShortTextIcon\"\n                          lucide=\"Type\"\n                          tabler=\"IconLetterT\"\n                          phosphor=\"TextT\"\n                          remixicon=\"RiText\"\n                          size={14}\n                          strokeWidth={2}\n                        />\n                      </div>\n\n                      <div className=\"min-w-0 flex-1\">\n                        <div className=\"flex items-center gap-2\">\n                          <p className=\"truncate text-sm font-medium\">\n                            {form.formName}\n                          </p>\n                          {isCurrent && (\n                            <Badge variant=\"secondary\">Current</Badge>\n                          )}\n                        </div>\n\n                        <div className=\"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground\">\n                          <IconPlaceholder\n                            hugeicons=\"Clock01Icon\"\n                            lucide=\"Clock\"\n                            tabler=\"IconClock\"\n                            phosphor=\"Clock\"\n                            remixicon=\"RiTimeLine\"\n                            size={12}\n                            strokeWidth={2}\n                          />\n                          <span>{dateFormatter.format(form.updatedAt)}</span>\n                        </div>\n                      </div>\n\n                      <div className=\"flex items-center gap-1\">\n                        <Button\n                          type=\"button\"\n                          variant=\"outline\"\n                          size=\"sm\"\n                          className=\"gap-1.5\"\n                          disabled={isBusy}\n                          onClick={() => handleOpenForm(form.formId)}\n                        >\n                          {isOpening ? (\n                            <Spinner className=\"size-3.5\" />\n                          ) : (\n                            <IconPlaceholder\n                              hugeicons=\"ArrowRight01Icon\"\n                              lucide=\"ArrowRight\"\n                              tabler=\"IconArrowRight\"\n                              phosphor=\"ArrowRight\"\n                              remixicon=\"RiArrowRightLine\"\n                              size={14}\n                              strokeWidth={2}\n                            />\n                          )}\n                          Open\n                        </Button>\n\n                        <Tooltip>\n                          <TooltipTrigger\n                            render={\n                              <Button\n                                type=\"button\"\n                                variant=\"ghost\"\n                                size=\"icon-sm\"\n                                disabled={isBusy}\n                                onClick={() => handleDownloadForm(form)}\n                                className=\"text-muted-foreground\"\n                              >\n                                {isDownloading ? (\n                                  <Spinner className=\"size-3.5\" />\n                                ) : (\n                                  <IconPlaceholder\n                                    hugeicons=\"Download02Icon\"\n                                    lucide=\"Download\"\n                                    tabler=\"IconDownload\"\n                                    phosphor=\"DownloadSimple\"\n                                    remixicon=\"RiDownload2Line\"\n                                    size={14}\n                                    strokeWidth={2}\n                                  />\n                                )}\n                                <span className=\"sr-only\">\n                                  Download saved form\n                                </span>\n                              </Button>\n                            }\n                          />\n                          <TooltipContent side=\"top\">Download</TooltipContent>\n                        </Tooltip>\n\n                        <Tooltip>\n                          <TooltipTrigger\n                            render={\n                              <Button\n                                type=\"button\"\n                                variant=\"ghost\"\n                                size=\"icon-sm\"\n                                disabled={isBusy}\n                                onClick={() => handleRemoveForm(form)}\n                                className=\"text-muted-foreground hover:text-destructive\"\n                              >\n                                {isRemoving ? (\n                                  <Spinner className=\"size-3.5\" />\n                                ) : (\n                                  <IconPlaceholder\n                                    hugeicons=\"Delete02Icon\"\n                                    lucide=\"Trash2\"\n                                    tabler=\"IconTrash\"\n                                    phosphor=\"Trash\"\n                                    remixicon=\"RiDeleteBinLine\"\n                                    size={14}\n                                    strokeWidth={2}\n                                  />\n                                )}\n                                <span className=\"sr-only\">\n                                  Remove saved form\n                                </span>\n                              </Button>\n                            }\n                          />\n                          <TooltipContent side=\"top\">Delete</TooltipContent>\n                        </Tooltip>\n                      </div>\n                    </div>\n                  );\n                })}\n              </div>\n            </ScrollArea>\n          </div>\n\n          <div className=\"flex justify-start\">\n            <Button\n              type=\"button\"\n              variant=\"outline\"\n              size=\"sm\"\n              className=\"gap-2\"\n              onClick={loadForms}\n            >\n              <IconPlaceholder\n                hugeicons=\"Refresh01Icon\"\n                lucide=\"RefreshCw\"\n                tabler=\"IconRefresh\"\n                phosphor=\"ArrowsClockwise\"\n                remixicon=\"RiRefreshLine\"\n                size={14}\n                strokeWidth={2}\n              />\n              Refresh\n            </Button>\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/header/form-manager-saved-panel.tsx"
    },
    {
      "path": "registry/shadcn/builder/header/index.tsx",
      "content": "\"use client\";\n\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { ThemeToggle } from \"@/components/theme-toggle\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { useBuilderStore } from \"@buildnbuzz/form-builder-react\";\n\nimport { SaveIndicator } from \"./save-indicator\";\nimport { FormManagerDialog } from \"./form-manager-dialog\";\nimport { CloudSaveDialog } from \"./cloud-save-dialog\";\nimport { ExportSheet } from \"../export-sheet\";\nimport type { BuilderStorageProvider } from \"@buildnbuzz/form-builder-core\";\n\nexport function SiteHeader({\n  storageProvider,\n}: {\n  storageProvider: BuilderStorageProvider | null;\n}) {\n  const hasContent = useBuilderStore((state) => state.rootIds.length > 0);\n\n  return (\n    <header className=\"bg-background sticky top-0 z-50 flex w-full items-center border-b\">\n      <div className=\"flex h-header w-full items-center gap-2 px-4 text-foreground\">\n        <div className=\"flex min-w-0 items-center gap-2\">\n          <Link href=\"/\" className=\"flex items-center gap-2\">\n            <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg invert dark:invert-0\">\n              <Image src=\"/bb-icon.svg\" alt=\"Logo\" width={24} height={24} />\n            </div>\n            <span className=\"text-sm font-semibold tracking-tight\">\n              BuzzForm\n            </span>\n            <Badge\n              variant=\"secondary\"\n              className=\"h-5 rounded-full px-2 text-[10px] font-semibold tracking-wide\"\n            >\n              Preview\n            </Badge>\n          </Link>\n        </div>\n\n        <div className=\"ml-auto flex items-center gap-4\">\n          <SaveIndicator />\n          {hasContent && (\n            <Separator\n              orientation=\"vertical\"\n              className=\"h-5 data-[orientation=vertical]:self-center\"\n            />\n          )}\n          <div className=\"flex items-center gap-2\">\n            <ThemeToggle />\n            <CloudSaveDialog />\n            <ExportSheet />\n            <FormManagerDialog storageProvider={storageProvider} />\n          </div>\n        </div>\n      </div>\n    </header>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/header/index.tsx"
    },
    {
      "path": "registry/shadcn/builder/header/save-indicator.tsx",
      "content": "\"use client\";\n\nimport { useBuilderStore } from \"@buildnbuzz/form-builder-react\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { cn } from \"@/lib/utils\";\n\nfunction formatTime(timestamp: number): string {\n  return new Date(timestamp).toLocaleTimeString([], {\n    hour: \"numeric\",\n    minute: \"2-digit\",\n  });\n}\n\nexport function SaveIndicator() {\n  const saveStatus = useBuilderStore((state) => state.saveStatus);\n  const lastSavedAt = useBuilderStore((state) => state.lastSavedAt);\n  const hasContent = useBuilderStore((state) => state.rootIds.length > 0);\n\n  if (!hasContent) return null;\n\n  return (\n    <div\n      className={cn(\n        \"flex items-center gap-1.5 text-xs text-muted-foreground transition-opacity duration-200\",\n        saveStatus === \"idle\" && !lastSavedAt && \"opacity-0\",\n      )}\n    >\n      {saveStatus === \"saving\" ? (\n        <>\n          <IconPlaceholder\n            hugeicons=\"Loading03Icon\"\n            lucide=\"Loader2\"\n            tabler=\"IconLoader2\"\n            phosphor=\"CircleNotch\"\n            remixicon=\"RiLoader2Line\"\n            size={14}\n            className=\"animate-spin\"\n          />\n          <span>Saving...</span>\n        </>\n      ) : lastSavedAt ? (\n        <>\n          <IconPlaceholder\n            hugeicons=\"CheckmarkCircle01Icon\"\n            lucide=\"CheckCircle2\"\n            tabler=\"IconCircleCheck\"\n            phosphor=\"CheckCircle\"\n            remixicon=\"RiCheckboxCircleLine\"\n            size={14}\n            className=\"text-emerald-500\"\n          />\n          <span>Last saved at {formatTime(lastSavedAt)}</span>\n        </>\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/header/save-indicator.tsx"
    },
    {
      "path": "registry/shadcn/builder/layout/array-renderer.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { useDroppable } from \"@dnd-kit/core\";\nimport { cn } from \"@/lib/utils\";\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport {\n  DEFAULT_SLOT,\n  useBuilderStore,\n  type BuilderNodeRendererProps,\n} from \"@buildnbuzz/form-builder-react\";\nimport type { ArrayField } from \"@buildnbuzz/form-core\";\n\n/**\n * Visual renderer for 'array' layout fields.\n * Wraps repeating items with min/max indicator limits securely resolving DnD sorting wrappers context.\n */\nexport const ArrayRenderer = ({\n  id,\n  field,\n  childrenIds,\n  renderSlot,\n}: BuilderNodeRendererProps) => {\n  const arrayField = field as ArrayField;\n  const rawField = arrayField as unknown as Record<string, unknown>;\n  const uiConfig = (arrayField.ui as Record<string, unknown> | undefined) ?? {};\n  const defaultCollapsed = (uiConfig.collapsed as boolean | undefined) ?? false;\n  const minItems = arrayField.minItems;\n  const maxItems = arrayField.maxItems;\n\n  const isCollapsed = useBuilderStore(\n    (s) => s.collapsedNodes[id] ?? defaultCollapsed,\n  );\n  const toggleCollapsed = useBuilderStore((s) => s.toggleCollapsed);\n  const setCollapsed = useBuilderStore((s) => s.setCollapsed);\n\n  const initializedRef = useRef(false);\n  useEffect(() => {\n    if (!initializedRef.current) {\n      initializedRef.current = true;\n      if (defaultCollapsed) {\n        setCollapsed(id, true);\n      }\n    }\n  }, [id, defaultCollapsed, setCollapsed]);\n\n  const { setNodeRef, isOver } = useDroppable({\n    id: `${id}-dropzone`,\n    data: { type: \"array\", parentId: id, parentSlot: DEFAULT_SLOT },\n  });\n\n  const isEmpty = childrenIds.length === 0;\n\n  const renderDropZone = () => (\n    <div\n      ref={setNodeRef}\n      data-container-padding\n      className={cn(\"min-h-16 transition-colors\", isOver && \"bg-primary/5\")}\n    >\n      {isEmpty ? (\n        <div\n          className={cn(\n            \"h-16 flex items-center justify-center rounded-lg border-2 border-dashed transition-colors\",\n            isOver\n              ? \"border-primary/50 bg-primary/5\"\n              : \"border-muted-foreground/20 bg-muted/30\",\n          )}\n        >\n          <span className=\"text-muted-foreground text-sm italic\">\n            Drop fields for each array item\n          </span>\n        </div>\n      ) : (\n        <div className=\"space-y-3\">{renderSlot(DEFAULT_SLOT)}</div>\n      )}\n    </div>\n  );\n\n  return (\n    <Collapsible open={!isCollapsed} onOpenChange={() => toggleCollapsed(id)}>\n      <Card className=\"w-full py-0 gap-0 border-dashed\">\n        <CardHeader className=\"p-0 border-b-0\">\n          <CollapsibleTrigger\n            className={cn(\n              \"w-full px-4 py-3 flex flex-row items-center justify-between\",\n              \"hover:bg-muted/75 bg-muted/50 transition-colors select-none cursor-pointer\",\n              !isCollapsed && \"border-b\",\n            )}\n          >\n            <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n              <IconPlaceholder\n                lucide=\"Menu\"\n                hugeicons=\"Menu01Icon\"\n                size={16}\n                className=\"text-muted-foreground shrink-0\"\n              />\n              <span className=\"text-sm font-semibold truncate\">\n                {(rawField.label as string) || \"Array\"}\n              </span>\n              <Badge variant=\"secondary\" className=\"h-5 px-1.5 text-[10px]\">\n                {childrenIds.length}{\" \"}\n                {childrenIds.length === 1 ? \"field\" : \"fields\"}\n              </Badge>\n              {typeof minItems === \"number\" && (\n                <Badge\n                  variant=\"outline\"\n                  className=\"h-5 px-1.5 text-[10px] text-muted-foreground\"\n                >\n                  min {minItems}\n                </Badge>\n              )}\n              {typeof maxItems === \"number\" && (\n                <Badge\n                  variant=\"outline\"\n                  className=\"h-5 px-1.5 text-[10px] text-muted-foreground\"\n                >\n                  max {maxItems}\n                </Badge>\n              )}\n            </div>\n\n            <IconPlaceholder\n              lucide=\"ChevronDown\"\n              hugeicons=\"ArrowDown01Icon\"\n              size={16}\n              className={cn(\n                \"text-muted-foreground transition-transform duration-200 shrink-0\",\n                isCollapsed && \"-rotate-90\",\n              )}\n            />\n          </CollapsibleTrigger>\n        </CardHeader>\n\n        <CollapsibleContent>\n          <CardContent className=\"p-4\">\n            {!!rawField.description && (\n              <p className=\"text-sm text-muted-foreground mb-3\">\n                {rawField.description as string}\n              </p>\n            )}\n            {renderDropZone()}\n          </CardContent>\n        </CollapsibleContent>\n      </Card>\n    </Collapsible>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/layout/array-renderer.tsx"
    },
    {
      "path": "registry/shadcn/builder/layout/collapsible-renderer.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { useDroppable } from \"@dnd-kit/core\";\nimport { cn } from \"@/lib/utils\";\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport {\n  DEFAULT_SLOT,\n  useBuilderStore,\n  type BuilderNodeRendererProps,\n} from \"@buildnbuzz/form-builder-react\";\n\nconst spacingMap = {\n  sm: \"space-y-2\",\n  md: \"space-y-3\",\n  lg: \"space-y-4\",\n};\n\n/**\n * Visual renderer for 'collapsible' container fields.\n * Includes multiple UI variants natively integrated with builder store state tracking.\n */\nexport const CollapsibleRenderer = ({\n  id,\n  field,\n  childrenIds,\n  renderSlot,\n}: BuilderNodeRendererProps) => {\n  const rawField = field as unknown as Record<string, unknown>;\n  const uiConfig = (rawField.ui as Record<string, unknown> | undefined) ?? {};\n\n  const label = rawField.label as string | undefined;\n  const variant =\n    (uiConfig.variant as \"ghost\" | \"bordered\" | \"card\" | \"flat\" | undefined) ??\n    \"bordered\";\n  const spacingConfig = uiConfig.spacing as string | undefined;\n  const spacingExtracted =\n    spacingConfig && spacingConfig in spacingMap\n      ? (spacingConfig as keyof typeof spacingMap)\n      : \"md\";\n\n  const defaultCollapsed = (rawField.collapsed as boolean | undefined) ?? false;\n\n  const isCollapsed = useBuilderStore(\n    (s) => s.collapsedNodes[id] ?? defaultCollapsed,\n  );\n  const toggleCollapsed = useBuilderStore((s) => s.toggleCollapsed);\n  const setCollapsed = useBuilderStore((s) => s.setCollapsed);\n\n  const initializedRef = useRef(false);\n  useEffect(() => {\n    if (!initializedRef.current) {\n      initializedRef.current = true;\n      if (defaultCollapsed) {\n        setCollapsed(id, true);\n      }\n    }\n  }, [id, defaultCollapsed, setCollapsed]);\n\n  const { setNodeRef, isOver } = useDroppable({\n    id: `${id}-dropzone`,\n    data: { type: \"collapsible\", parentId: id, parentSlot: DEFAULT_SLOT },\n  });\n\n  const isEmpty = childrenIds.length === 0;\n\n  const renderDropZone = () => (\n    <div\n      ref={setNodeRef}\n      data-container-padding\n      className={cn(\"min-h-16 transition-colors\", isOver && \"bg-primary/5\")}\n    >\n      {isEmpty ? (\n        <div\n          className={cn(\n            \"h-16 flex items-center justify-center rounded-lg border-2 border-dashed transition-colors\",\n            isOver\n              ? \"border-primary/50 bg-primary/5\"\n              : \"border-muted-foreground/20 bg-muted/30\",\n          )}\n        >\n          <span className=\"text-muted-foreground text-sm italic\">\n            Drop fields here\n          </span>\n        </div>\n      ) : (\n        <div className={cn(spacingMap[spacingExtracted])}>\n          {renderSlot(DEFAULT_SLOT)}\n        </div>\n      )}\n    </div>\n  );\n\n  const renderHeaderContent = () => (\n    <div className=\"flex-1 min-w-0 flex items-center gap-2\">\n      <IconPlaceholder\n        lucide=\"FoldVertical\"\n        hugeicons=\"ArrowShrink02Icon\"\n        size={16}\n        className=\"text-muted-foreground shrink-0\"\n      />\n      <span\n        className={cn(\n          \"text-sm truncate\",\n          variant === \"card\" ? \"font-semibold\" : \"font-medium\",\n        )}\n      >\n        {label || \"Collapsible\"}\n      </span>\n      {!isEmpty && (\n        <span className=\"text-xs text-muted-foreground\">\n          ({childrenIds.length} {childrenIds.length === 1 ? \"field\" : \"fields\"})\n        </span>\n      )}\n    </div>\n  );\n\n  const renderChevron = (size: number = 16) => (\n    <IconPlaceholder\n      lucide=\"ChevronDown\"\n      hugeicons=\"ArrowDown01Icon\"\n      size={size}\n      className={cn(\n        \"text-muted-foreground transition-transform duration-200 shrink-0\",\n        isCollapsed && \"-rotate-90\",\n      )}\n    />\n  );\n\n  // === GHOST VARIANT ===\n  if (variant === \"ghost\") {\n    return (\n      <Collapsible open={!isCollapsed} onOpenChange={() => toggleCollapsed(id)}>\n        <div className=\"w-full\">\n          <CollapsibleTrigger className=\"w-full px-2 py-2 rounded-md flex flex-row items-center justify-between hover:bg-muted/50 transition-colors select-none cursor-pointer\">\n            {renderHeaderContent()}\n            {renderChevron(14)}\n          </CollapsibleTrigger>\n          <CollapsibleContent>\n            <div className=\"pt-3 pl-2\">{renderDropZone()}</div>\n          </CollapsibleContent>\n        </div>\n      </Collapsible>\n    );\n  }\n\n  // === BORDERED VARIANT (DEFAULT) ===\n  if (variant === \"bordered\" || variant === \"flat\") {\n    return (\n      <Collapsible open={!isCollapsed} onOpenChange={() => toggleCollapsed(id)}>\n        <div className=\"w-full border border-dashed border-border rounded-lg overflow-hidden\">\n          <CollapsibleTrigger className=\"w-full px-4 py-2 flex flex-row items-center justify-between hover:bg-muted/50 transition-colors select-none cursor-pointer\">\n            {renderHeaderContent()}\n            {renderChevron(14)}\n          </CollapsibleTrigger>\n          <CollapsibleContent>\n            <div className=\"px-4 pt-2 pb-4\">{renderDropZone()}</div>\n          </CollapsibleContent>\n        </div>\n      </Collapsible>\n    );\n  }\n\n  // === CARD VARIANT ===\n  return (\n    <Collapsible open={!isCollapsed} onOpenChange={() => toggleCollapsed(id)}>\n      <Card className=\"w-full py-0 gap-0\">\n        <CardHeader className=\"p-0 border-b-0\">\n          <CollapsibleTrigger\n            className={cn(\n              \"w-full px-4 py-3 flex flex-row items-center justify-between\",\n              \"hover:bg-muted/75 bg-muted/50 transition-colors select-none cursor-pointer\",\n              !isCollapsed && \"border-b\",\n            )}\n          >\n            {renderHeaderContent()}\n            {renderChevron()}\n          </CollapsibleTrigger>\n        </CardHeader>\n        <CollapsibleContent>\n          <CardContent className=\"p-4\">{renderDropZone()}</CardContent>\n        </CollapsibleContent>\n      </Card>\n    </Collapsible>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/layout/collapsible-renderer.tsx"
    },
    {
      "path": "registry/shadcn/builder/layout/group-renderer.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { useDroppable } from \"@dnd-kit/core\";\nimport { cn } from \"@/lib/utils\";\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { DEFAULT_SLOT, useBuilderStore, type BuilderNodeRendererProps } from \"@buildnbuzz/form-builder-react\";\nimport type { GroupField } from \"@buildnbuzz/form-core\";\n\nconst spacingMap = {\n  sm: \"space-y-2\",\n  md: \"space-y-3\",\n  lg: \"space-y-4\",\n} as const;\n\n/**\n * Visual renderer for 'group' container fields.\n */\nexport const GroupRenderer = ({ id, field, renderSlot, childrenIds }: BuilderNodeRendererProps) => {\n  const groupField = field as GroupField;\n  const { label } = groupField;\n  const variant = groupField.ui?.variant ?? \"card\";\n  const spacing = (groupField.ui?.spacing as keyof typeof spacingMap) ?? \"md\";\n  const defaultCollapsed = groupField.ui?.collapsed ?? false;\n\n  const isCollapsed = useBuilderStore(\n    (s) => s.collapsedNodes[id] ?? defaultCollapsed,\n  );\n  const toggleCollapsed = useBuilderStore((s) => s.toggleCollapsed);\n  const setCollapsed = useBuilderStore((s) => s.setCollapsed);\n\n  const initializedRef = useRef(false);\n  useEffect(() => {\n    if (!initializedRef.current) {\n      initializedRef.current = true;\n      if (defaultCollapsed) {\n        setCollapsed(id, true);\n      }\n    }\n  }, [id, defaultCollapsed, setCollapsed]);\n\n  const { setNodeRef, isOver } = useDroppable({\n    id: `${id}-dropzone`,\n    data: { type: \"group\", parentId: id, parentSlot: DEFAULT_SLOT },\n  });\n\n  const isEmpty = childrenIds.length === 0;\n\n  const renderDropZone = () => (\n    <div\n      ref={setNodeRef}\n      data-container-padding\n      className={cn(\"min-h-16 transition-colors\", isOver && \"bg-primary/5\")}\n    >\n      {isEmpty ? (\n        <div\n          className={cn(\n            \"h-16 flex items-center justify-center rounded-lg border-2 border-dashed transition-colors\",\n            isOver\n              ? \"border-primary/50 bg-primary/5\"\n              : \"border-muted-foreground/20 bg-muted/30\",\n          )}\n        >\n          <span className=\"text-muted-foreground text-sm italic\">\n            Drop fields here\n          </span>\n        </div>\n      ) : (\n        <div className={cn(spacingMap[spacing])}>\n          {renderSlot(DEFAULT_SLOT)}\n        </div>\n      )}\n    </div>\n  );\n\n  // === FLAT VARIANT ===\n  if (variant === \"flat\") {\n    return (\n      <div className=\"w-full\">\n        {label && (\n          <div className=\"flex items-center gap-2 mb-2\">\n            <IconPlaceholder\n              lucide=\"Folder\"\n              hugeicons=\"FolderIcon\"\n              size={14}\n              className=\"text-muted-foreground\"\n            />\n            <span className=\"font-medium text-sm text-foreground\">{label as string}</span>\n          </div>\n        )}\n        <div className=\"pl-1\">{renderDropZone()}</div>\n      </div>\n    );\n  }\n\n  // === GHOST VARIANT ===\n  if (variant === \"ghost\") {\n    return (\n      <div className=\"w-full border border-border/50 rounded-lg p-4\">\n        {label && (\n          <div className=\"flex items-center gap-2 mb-3\">\n            <IconPlaceholder\n              lucide=\"Folder\"\n              hugeicons=\"FolderIcon\"\n              size={14}\n              className=\"text-muted-foreground\"\n            />\n            <span className=\"font-medium text-sm text-foreground\">{label as string}</span>\n          </div>\n        )}\n        {renderDropZone()}\n      </div>\n    );\n  }\n\n  // === BORDERED VARIANT ===\n  if (variant === \"bordered\") {\n    return (\n      <Collapsible open={!isCollapsed} onOpenChange={() => toggleCollapsed(id)}>\n        <div className=\"w-full border border-dashed border-border rounded-lg overflow-hidden\">\n          {label && (\n            <CollapsibleTrigger className=\"w-full px-4 py-2 flex flex-row items-center justify-between hover:bg-muted/50 transition-colors select-none cursor-pointer\">\n              <div className=\"flex items-center gap-2\">\n                <IconPlaceholder\n                  lucide=\"Folder\"\n                  hugeicons=\"FolderIcon\"\n                  size={14}\n                  className=\"text-muted-foreground\"\n                />\n                <span className=\"font-medium text-muted-foreground text-sm\">\n                  {label as string}\n                </span>\n              </div>\n              <IconPlaceholder\n                lucide=\"ChevronDown\"\n                hugeicons=\"ArrowDown01Icon\"\n                size={14}\n                className={cn(\n                  \"text-muted-foreground transition-transform duration-200\",\n                  isCollapsed && \"-rotate-90\",\n                )}\n              />\n            </CollapsibleTrigger>\n          )}\n          <CollapsibleContent>\n            <div className=\"px-4 pt-2 pb-4\">{renderDropZone()}</div>\n          </CollapsibleContent>\n        </div>\n      </Collapsible>\n    );\n  }\n\n  // === CARD VARIANT (DEFAULT) ===\n  return (\n    <Collapsible open={!isCollapsed} onOpenChange={() => toggleCollapsed(id)}>\n      <Card className=\"w-full py-0 gap-0\">\n        {label && (\n          <CardHeader className=\"p-0 border-b-0\">\n            <CollapsibleTrigger\n              className={cn(\n                \"w-full px-4 py-3 flex flex-row items-center justify-between\",\n                \"hover:bg-muted/75 bg-muted/50 transition-colors select-none cursor-pointer\",\n                !isCollapsed && \"border-b\",\n              )}\n            >\n              <div className=\"flex items-center gap-2\">\n                <IconPlaceholder\n                  lucide=\"Folder\"\n                  hugeicons=\"FolderIcon\"\n                  size={16}\n                  className=\"text-muted-foreground\"\n                />\n                <span className=\"text-sm font-semibold\">{label as string}</span>\n              </div>\n              <IconPlaceholder\n                lucide=\"ChevronDown\"\n                hugeicons=\"ArrowDown01Icon\"\n                size={16}\n                className={cn(\n                  \"text-muted-foreground transition-transform duration-200\",\n                  isCollapsed && \"-rotate-90\",\n                )}\n              />\n            </CollapsibleTrigger>\n          </CardHeader>\n        )}\n        <CollapsibleContent>\n          <CardContent className=\"p-4\">{renderDropZone()}</CardContent>\n        </CollapsibleContent>\n      </Card>\n    </Collapsible>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/layout/group-renderer.tsx"
    },
    {
      "path": "registry/shadcn/builder/layout/row-renderer.tsx",
      "content": "\"use client\";\n\nimport { useDroppable } from \"@dnd-kit/core\";\nimport { horizontalListSortingStrategy } from \"@dnd-kit/sortable\";\nimport { cn } from \"@/lib/utils\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport {\n  DEFAULT_SLOT,\n  type BuilderNodeRendererProps,\n} from \"@buildnbuzz/form-builder-react\";\n\n/**\n * Visual renderer for 'row' layout fields.\n * Displays children in a horizontal grid.\n */\nexport const RowRenderer = ({\n  id,\n  renderSlot,\n  childrenIds,\n}: BuilderNodeRendererProps) => {\n  const { setNodeRef, isOver } = useDroppable({\n    id: `${id}-dropzone`,\n    data: { type: \"row\", parentId: id, parentSlot: DEFAULT_SLOT },\n  });\n\n  const isEmpty = childrenIds.length === 0;\n\n  return (\n    <div className=\"w-full\">\n      {/* Header */}\n      <div className=\"flex items-center gap-1.5 mb-2 text-muted-foreground\">\n        <IconPlaceholder lucide=\"Columns\" hugeicons=\"InsertRowDownIcon\" size={14} />\n        <span className=\"text-xs font-medium\">Row</span>\n      </div>\n\n      {/* Drop zone container */}\n      <div\n        ref={setNodeRef}\n        data-container-padding\n        className={cn(\n          \"flex flex-row gap-3 p-3 min-h-16 rounded-lg border-2 border-dashed transition-colors\",\n          isEmpty ? \"items-center justify-center\" : \"items-stretch\",\n          isOver\n            ? \"border-primary/50 bg-primary/5\"\n            : \"border-muted-foreground/20 bg-muted/30 hover:border-muted-foreground/30\",\n        )}\n      >\n        {isEmpty ? (\n          <div className=\"text-muted-foreground text-sm italic\">\n            Drop fields here\n          </div>\n        ) : (\n          renderSlot(DEFAULT_SLOT, horizontalListSortingStrategy)\n        )}\n      </div>\n    </div>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/layout/row-renderer.tsx"
    },
    {
      "path": "registry/shadcn/builder/layout/tabs-renderer.tsx",
      "content": "\"use client\";\n\nimport React, { useMemo, useEffect } from \"react\";\nimport {\n  useBuilderStore,\n  type BuilderNodeRendererProps,\n} from \"@buildnbuzz/form-builder-react\";\nimport { getTabSlotKeys } from \"@buildnbuzz/form-builder-core\";\nimport { useDroppable } from \"@dnd-kit/core\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { cn } from \"@/lib/utils\";\nimport type { TabsField, Tab } from \"@buildnbuzz/form-core\";\n\nfunction getTabDisplayLabel(tab: Tab, index: number) {\n  const label = tab.label;\n  if (typeof label === \"string\" && label.trim().length > 0) {\n    return label;\n  }\n  if (typeof label === \"number\") {\n    return String(label);\n  }\n  return `Tab ${index + 1}`;\n}\n\ninterface TabDropZoneProps {\n  containerId: string;\n  slot: string;\n  tab: Tab;\n  childrenIds: string[];\n  renderSlot: (slot: string) => React.ReactNode;\n}\n\nfunction TabDropZone({\n  containerId,\n  slot,\n  tab,\n  childrenIds,\n  renderSlot,\n}: TabDropZoneProps) {\n  const { setNodeRef, isOver } = useDroppable({\n    id: `${containerId}::tab::${encodeURIComponent(slot)}-dropzone`,\n    data: { type: \"tabs\", parentId: containerId, parentSlot: slot },\n  });\n\n  const isEmpty = childrenIds.length === 0;\n  const description = (tab as unknown as Record<string, unknown>).description;\n\n  return (\n    <div\n      ref={setNodeRef}\n      data-container-padding\n      className={cn(\"min-h-16 transition-colors\", isOver && \"bg-primary/5\")}\n    >\n      {typeof description === \"string\" && description && (\n        <p className=\"text-sm text-muted-foreground mb-3\">{description}</p>\n      )}\n\n      {isEmpty ? (\n        <div\n          className={cn(\n            \"h-16 flex items-center justify-center rounded-lg border-2 border-dashed transition-colors\",\n            isOver\n              ? \"border-primary/50 bg-primary/5\"\n              : \"border-muted-foreground/20 bg-muted/30\",\n          )}\n        >\n          <span className=\"text-muted-foreground text-sm italic\">\n            Drop fields in this tab\n          </span>\n        </div>\n      ) : (\n        renderSlot(slot)\n      )}\n    </div>\n  );\n}\n\n/**\n * Visual renderer for 'tabs' fields.\n * Orchestrates multiple slots as tabs.\n */\nexport const TabsRenderer = ({\n  id,\n  field,\n  renderSlot,\n}: BuilderNodeRendererProps) => {\n  const tabsField = field as TabsField;\n  const tabs = useMemo(() => tabsField.tabs ?? [], [tabsField.tabs]);\n  const slots = useMemo(() => getTabSlotKeys(tabs), [tabs]);\n\n  const activeSlotFromStore = useBuilderStore(\n    (state) => state.activeTabs[id] ?? null,\n  );\n  const setActiveTab = useBuilderStore((state) => state.setActiveTab);\n  const tabChildren = useBuilderStore(\n    (state) => state.nodes[id]?.children ?? {},\n  );\n\n  const defaultSlot = useMemo(() => {\n    if (slots.length === 0) return \"\";\n    const configuredDefault = tabsField.ui?.defaultTab;\n    const enabledSlots = slots.filter(\n      (_, index) => tabs[index]?.disabled !== true,\n    );\n    const enabledFallbackSlot = enabledSlots[0] ?? slots[0];\n\n    if (typeof configuredDefault === \"number\") {\n      const index = Math.max(0, Math.min(slots.length - 1, configuredDefault));\n      return tabs[index]?.disabled === true\n        ? enabledFallbackSlot\n        : slots[index];\n    }\n\n    if (typeof configuredDefault === \"string\") {\n      const index = tabs.findIndex((tab) => tab.name === configuredDefault);\n      if (index >= 0 && tabs[index]?.disabled !== true) {\n        return slots[index];\n      }\n    }\n\n    return enabledFallbackSlot;\n  }, [tabsField.ui?.defaultTab, tabs, slots]);\n\n  const activeSlot =\n    activeSlotFromStore && slots.includes(activeSlotFromStore)\n      ? activeSlotFromStore\n      : defaultSlot;\n\n  useEffect(() => {\n    if (!activeSlot) return;\n    if (activeSlotFromStore !== activeSlot) {\n      setActiveTab(id, activeSlot);\n    }\n  }, [activeSlot, activeSlotFromStore, id, setActiveTab]);\n\n  if (tabs.length === 0) {\n    return (\n      <div className=\"w-full rounded-lg border border-dashed border-muted-foreground/30 bg-muted/20 p-4\">\n        <div className=\"flex items-center gap-2 text-muted-foreground mb-2\">\n          <IconPlaceholder lucide=\"Layout\" hugeicons=\"Layout01Icon\" size={14} />\n          <span className=\"text-xs font-medium\">Tabs</span>\n        </div>\n        <p className=\"text-sm text-muted-foreground\">\n          Add at least one tab in the properties panel.\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"w-full\">\n      <div className=\"flex items-center gap-1.5 mb-2 text-muted-foreground\">\n        <IconPlaceholder lucide=\"Layout\" hugeicons=\"Layout01Icon\" size={14} />\n        <span className=\"text-xs font-medium\">Tabs</span>\n      </div>\n\n      <Tabs\n        value={activeSlot}\n        onValueChange={(val) => val && setActiveTab(id, val)}\n        className=\"w-full\"\n      >\n        <TabsList\n          variant={(tabsField.ui?.variant as \"line\" | \"default\") ?? \"line\"}\n          className=\"w-full justify-start\"\n        >\n          {tabs.map((tab, index) => {\n            const slot = slots[index];\n            const childCount = tabChildren[slot]?.length ?? 0;\n\n            return (\n              <TabsTrigger\n                key={slot}\n                value={slot}\n                className={cn(\n                  tab.disabled &&\n                    \"opacity-80 text-muted-foreground data-[state=active]:text-muted-foreground\",\n                )}\n              >\n                <span className=\"inline-flex items-center gap-1.5\">\n                  <span>{getTabDisplayLabel(tab, index)}</span>\n                  <Badge variant=\"secondary\" className=\"h-5 px-1.5 text-[10px]\">\n                    {childCount}\n                  </Badge>\n                  {tab.disabled && (\n                    <IconPlaceholder\n                      lucide=\"Ban\"\n                      hugeicons=\"BlockedIcon\"\n                      size={12}\n                      className=\"text-muted-foreground/70\"\n                    />\n                  )}\n                </span>\n              </TabsTrigger>\n            );\n          })}\n        </TabsList>\n\n        {tabs.map((tab, index) => {\n          const slot = slots[index];\n          const childrenIdsForSlot = tabChildren[slot] || [];\n\n          return (\n            <TabsContent key={slot} value={slot} className=\"mt-4\">\n              {tab.name && (\n                <p className=\"text-xs text-muted-foreground mb-2\">\n                  Key: <code className=\"font-mono\">{tab.name}</code>\n                  {tab.disabled && (\n                    <Badge\n                      variant=\"outline\"\n                      className=\"ml-2 h-5 gap-1 border-muted-foreground/20 bg-muted/50 px-1.5 text-[10px] font-normal text-muted-foreground\"\n                    >\n                      <IconPlaceholder\n                        lucide=\"Ban\"\n                        hugeicons=\"BlockedIcon\"\n                        size={12}\n                      />\n                      Disabled\n                    </Badge>\n                  )}\n                </p>\n              )}\n              <TabDropZone\n                containerId={id}\n                slot={slot}\n                tab={tab}\n                childrenIds={childrenIdsForSlot}\n                renderSlot={renderSlot}\n              />\n            </TabsContent>\n          );\n        })}\n      </Tabs>\n    </div>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/layout/tabs-renderer.tsx"
    },
    {
      "path": "registry/shadcn/builder/mobile-overlay.tsx",
      "content": "\"use client\";\n\nimport { useIsMobile } from \"@/hooks/use-mobile\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\n\n/**\n * Overlay shown on mobile devices to prompt users to use a desktop browser.\n */\nexport function MobileOverlay() {\n  const isMobile = useIsMobile();\n\n  if (!isMobile) return null;\n\n  return (\n    <div className=\"fixed inset-0 z-[100] flex items-center justify-center bg-background/80 p-6 backdrop-blur-md lg:hidden\">\n      <div className=\"relative w-full max-w-sm overflow-hidden rounded-3xl border border-border/60 bg-card/90 shadow-2xl shadow-black/20\">\n        <div className=\"absolute -left-16 -top-16 h-44 w-44 rounded-full bg-primary/20 blur-3xl\" />\n        <div className=\"absolute -bottom-20 -right-10 h-48 w-48 rounded-full bg-sky-500/15 blur-3xl\" />\n\n        <div className=\"relative space-y-4 p-8 text-center\">\n          <div className=\"mx-auto flex h-14 w-14 items-center justify-center rounded-2xl border border-border/60 bg-background/70 shadow-sm\">\n            <IconPlaceholder\n              lucide=\"Monitor\"\n              hugeicons=\"ComputerIcon\"\n              tabler=\"IconDeviceDesktop\"\n              phosphor=\"Monitor\"\n              remixicon=\"RiComputerLine\"\n              size={24}\n              className=\"text-primary\"\n            />\n          </div>\n          <div className=\"space-y-2\">\n            <h1 className=\"text-xl font-bold tracking-tight\">\n              Best on Desktop\n            </h1>\n            <p className=\"text-sm text-muted-foreground leading-relaxed\">\n              BuzzForm Builder requires a larger screen to provide the best\n              editing experience. Please switch to a desktop or tablet.\n            </p>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/mobile-overlay.tsx"
    },
    {
      "path": "registry/shadcn/builder/node-wrapper.tsx",
      "content": "\"use client\";\n\nimport React, { useState } from \"react\";\nimport { useBuilderStore, SortableNode } from \"@buildnbuzz/form-builder-react\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { cn } from \"@/lib/utils\";\nimport type { Node } from \"@buildnbuzz/form-builder-core\";\nimport { isDataField, isContainerType } from \"@buildnbuzz/form-core\";\n\ninterface NodeWrapperProps {\n  node: Node;\n  children: React.ReactNode;\n}\n\n/**\n * Visual frame for canvas nodes.\n * Provides selection states, drag handling, and a contextual toolbar.\n */\nexport const NodeWrapper = ({ node, children }: NodeWrapperProps) => {\n  const selectedId = useBuilderStore((s) => s.selectedId);\n  const selectNode = useBuilderStore((s) => s.selectNode);\n  const removeNode = useBuilderStore((s) => s.removeNode);\n  const duplicateNode = useBuilderStore((s) => s.duplicateNode);\n\n  const [isHovered, setIsHovered] = useState(false);\n  const isSelected = selectedId === node.id;\n  const isHidden = isDataField(node.field) && node.field.hidden === true;\n\n  const fieldStyle = \"style\" in node.field ? node.field.style : undefined;\n  const fieldWidth = (fieldStyle as React.CSSProperties | undefined)?.width;\n\n  return (\n    <SortableNode\n      id={node.id}\n      render={({ setNodeRef, attributes, listeners, style, isDragging }) => (\n        <div\n          ref={setNodeRef}\n          style={{\n            ...style,\n            ...(isHidden && {\n              backgroundImage:\n                \"repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(128,128,128,0.05) 10px, rgba(128,128,128,0.05) 20px)\",\n            }),\n            ...(fieldWidth && fieldWidth !== \"auto\"\n              ? { width: fieldWidth, flex: \"0 0 auto\" }\n              : { flex: \"1 1 0%\", minWidth: 0 }),\n          }}\n          onClick={(e) => {\n            e.stopPropagation();\n            selectNode(node.id);\n          }}\n          onMouseEnter={() => setIsHovered(true)}\n          onMouseLeave={() => setIsHovered(false)}\n          {...attributes}\n          {...listeners}\n          className={cn(\n            \"relative group/node my-2 rounded-xl transition-all duration-200 cursor-default\",\n            \"hover:p-2\",\n            isSelected\n              ? \"border-primary/50 ring-2 ring-primary/10 p-2 bg-primary/5\"\n              : \"border-transparent\",\n            !isSelected && \"border hover:border-border/40\",\n            isDragging && \"opacity-30\",\n            isHidden &&\n              \"opacity-60 grayscale border-dashed border-muted-foreground/30\",\n          )}\n        >\n          {/* Node Toolbar - visible on hover or selection */}\n          <TooltipProvider>\n            <div\n              className={cn(\n                \"absolute -top-9 right-0 z-50 flex items-center gap-0.5 rounded-lg border border-border/50 bg-card/75 p-1 shadow-lg shadow-black/10 backdrop-blur-md transition-opacity duration-200\",\n                isSelected || isHovered\n                  ? \"opacity-100 pointer-events-auto\"\n                  : \"opacity-0 pointer-events-none\",\n              )}\n              onClick={(e) => e.stopPropagation()}\n              onPointerDown={(e) => e.stopPropagation()}\n            >\n              <Tooltip>\n                <TooltipTrigger\n                  render={\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon\"\n                      className=\"size-7 text-muted-foreground hover:text-primary\"\n                      onClick={(e) => {\n                        e.stopPropagation();\n                        duplicateNode(node.id);\n                      }}\n                    />\n                  }\n                >\n                  <IconPlaceholder\n                    lucide=\"Copy\"\n                    hugeicons=\"Copy01Icon\"\n                    tabler=\"IconCopy\"\n                    phosphor=\"Copy\"\n                    remixicon=\"RiFileCopyLine\"\n                    size={14}\n                  />\n                </TooltipTrigger>\n                <TooltipContent>Duplicate field</TooltipContent>\n              </Tooltip>\n\n              <Tooltip>\n                <TooltipTrigger\n                  render={\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon\"\n                      className=\"size-7 text-muted-foreground hover:text-destructive\"\n                      onClick={(e) => {\n                        e.stopPropagation();\n                        removeNode(node.id);\n                      }}\n                    />\n                  }\n                >\n                  <IconPlaceholder\n                    lucide=\"Trash2\"\n                    hugeicons=\"Delete02Icon\"\n                    tabler=\"IconTrash\"\n                    phosphor=\"Trash\"\n                    remixicon=\"RiDeleteBinLine\"\n                    size={14}\n                  />\n                </TooltipTrigger>\n                <TooltipContent>Remove field</TooltipContent>\n              </Tooltip>\n            </div>\n          </TooltipProvider>\n\n          {/* Node Content */}\n          <div\n            className={cn(\n              \"relative w-full transition-all duration-200\",\n              !isContainerType(node.field.type) && \"pointer-events-none\",\n            )}\n          >\n            {isHidden && (\n              <Badge\n                className=\"absolute bottom-1.5 right-2 z-10 select-none bg-background/80 backdrop-blur-sm pointer-events-auto\"\n                variant=\"outline\"\n              >\n                Hidden\n              </Badge>\n            )}\n            {children}\n          </div>\n        </div>\n      )}\n    />\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/node-wrapper.tsx"
    },
    {
      "path": "registry/shadcn/builder/preview/preview-form.tsx",
      "content": "\"use client\";\n\nimport { useBuilderFormContext } from \"@buildnbuzz/form-builder-react\";\nimport {\n  Form,\n  FormContent,\n  FormFields,\n  FormActions,\n  FormSubmit,\n} from \"@/registry/shadcn/form\";\n\n/**\n * PreviewForm: Renders the builder's current state as a functional shadcn-based form.\n * Uses the form instance provided by BuilderFormProvider.\n */\nexport function PreviewForm() {\n  const { form, fields } = useBuilderFormContext();\n\n  return (\n    <Form form={form} schema={{ fields }}>\n      <FormContent noValidate className=\"p-0 gap-6\">\n        <FormFields />\n        <FormActions className=\"mt-4\" align=\"start\">\n          <FormSubmit>Submit</FormSubmit>\n        </FormActions>\n      </FormContent>\n    </Form>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/preview/preview-form.tsx"
    },
    {
      "path": "registry/shadcn/builder/property-panel.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport {\n  useBuilderContext,\n  BuilderProperties,\n  useSyncProperty,\n  getRegistryEntry,\n} from \"@buildnbuzz/form-builder-react\";\nimport { Form, FormContent, useFormContext } from \"@/registry/shadcn/form\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { FieldIcon } from \"./field-icon\";\nimport { IconPlaceholder } from \"@/components/icon-placeholder\";\nimport { flattenFieldToFormValues } from \"@buildnbuzz/form-builder-core\";\nimport type { Field, FormSchema } from \"@buildnbuzz/form-core\";\nimport { ExpressionCheckbox } from \"./expression-builder/expression-checkbox\";\nimport { registry as shadcnRegistry } from \"../registry\";\n\n/** Renders nothing — syncs form state ↔ builder store bidirectionally. */\nfunction SyncPropertyState({\n  update,\n  data,\n  schema,\n}: {\n  update: (data: Record<string, unknown>) => void;\n  data: Record<string, unknown>;\n  schema: Field[];\n}) {\n  const { form } = useFormContext();\n  useSyncProperty({ form, data, schema, update });\n  return null;\n}\n\n/**\n * Side panel for editing node or global form properties.\n */\nexport const PropertyPanel = () => {\n  const { registry } = useBuilderContext();\n\n  return (\n    <div className=\"flex h-full flex-col bg-background border-l overflow-hidden\">\n      <BuilderProperties\n        render={({ node, id, schema, data, update }) => {\n          const entry = node\n            ? getRegistryEntry(registry, node.field.type)\n            : null;\n          const label =\n            entry?.sidebar.label ??\n            (id === \"form\" ? \"Form Settings\" : \"Properties\");\n\n          const defaultValues = flattenFieldToFormValues(\n            data as unknown as Field,\n            schema,\n          );\n\n          return (\n            <>\n              <div className=\"p-4 border-b h-header flex items-center\">\n                {node && entry ? (\n                  <div className=\"flex items-center gap-3 w-full\">\n                    <div className=\"flex h-10 w-10 items-center justify-center rounded-xl border bg-secondary/30 shadow-sm\">\n                      {node && (\n                        <FieldIcon\n                          type={node.field.type}\n                          size={20}\n                          className=\"text-foreground\"\n                        />\n                      )}\n                    </div>\n                    <div className=\"flex flex-col gap-0.5 min-w-0 flex-1\">\n                      <span className=\"font-semibold text-sm truncate\">\n                        {label}\n                      </span>\n                      <span className=\"text-[11px] text-muted-foreground/80 truncate\">\n                        Properties\n                      </span>\n                    </div>\n                  </div>\n                ) : (\n                  <div className=\"flex items-center gap-3 w-full\">\n                    <div className=\"flex h-10 w-10 items-center justify-center rounded-xl border bg-secondary/30 shadow-sm\">\n                      <IconPlaceholder\n                        lucide=\"Settings\"\n                        hugeicons=\"Settings01Icon\"\n                        size={20}\n                        className=\"text-muted-foreground\"\n                      />\n                    </div>\n                    <div className=\"flex flex-col gap-0.5 min-w-0 flex-1\">\n                      <span className=\"font-semibold text-sm\">\n                        Form Settings\n                      </span>\n                      <span className=\"text-[11px] text-muted-foreground/80 truncate\">\n                        Configuration\n                      </span>\n                    </div>\n                  </div>\n                )}\n              </div>\n              <div className=\"flex-1 min-h-0\">\n                <ScrollArea className=\"h-full\">\n                  <div className=\"flex flex-col gap-6 p-4\">\n                    {schema.length > 0 ? (\n                      <Form\n                        key={id}\n                        schema={{ fields: schema } as unknown as FormSchema}\n                        defaultValues={defaultValues}\n                        registries={{\n                          fields: {\n                            ...shadcnRegistry,\n                            checkbox: ExpressionCheckbox,\n                            switch: ExpressionCheckbox,\n                          },\n                        }}\n                      >\n                        <FormContent autoRender as=\"div\" className=\"gap-6\">\n                          <SyncPropertyState\n                            update={update}\n                            data={data}\n                            schema={schema}\n                          />\n                        </FormContent>\n                      </Form>\n                    ) : (\n                      <div className=\"flex flex-col items-center justify-center gap-2 py-10 text-center opacity-30\">\n                        <span className=\"text-[11px]\">\n                          No properties available\n                        </span>\n                      </div>\n                    )}\n                  </div>\n                </ScrollArea>\n              </div>\n            </>\n          );\n        }}\n      />\n    </div>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/property-panel.tsx"
    },
    {
      "path": "registry/shadcn/builder/registry.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport {\n  DEFAULT_FIELD_REGISTRY,\n  isDataField,\n} from \"@buildnbuzz/form-builder-core\";\nimport { Field, type DataField } from \"@buildnbuzz/form-react\";\nimport { registry as shadcnRegistry } from \"../registry\";\nimport { RowRenderer } from \"./layout/row-renderer\";\nimport { GroupRenderer } from \"./layout/group-renderer\";\nimport { ArrayRenderer } from \"./layout/array-renderer\";\nimport { TabsRenderer } from \"./layout/tabs-renderer\";\nimport { CollapsibleRenderer } from \"./layout/collapsible-renderer\";\nimport {\n  useBuilderFormContext,\n  type BuilderNodeRendererProps,\n  type BuilderFieldRegistry,\n} from \"@buildnbuzz/form-builder-react\";\n\n/**\n * Generic renderer for data fields that uses the runtime components.\n * Wraps the component in a Field to provide the necessary headless context.\n */\nconst DataFieldRenderer = ({ field }: BuilderNodeRendererProps) => {\n  const { form } = useBuilderFormContext();\n  const Component = shadcnRegistry[field.type];\n\n  if (!Component || !isDataField(field)) {\n    return null;\n  }\n\n  return (\n    <Field field={field as DataField} form={form}>\n      <Component />\n    </Field>\n  );\n};\n\nconst specializedRenderers: Record<\n  string,\n  React.ComponentType<BuilderNodeRendererProps>\n> = {\n  row: RowRenderer,\n  group: GroupRenderer,\n  array: ArrayRenderer,\n  tabs: TabsRenderer,\n  collapsible: CollapsibleRenderer,\n};\n\n/**\n * Shadcn-specific builder registry.\n * Hydrates the core metadata registry with React renderers.\n */\nexport const SHADCN_BUILDER_REGISTRY: BuilderFieldRegistry = Object.entries(\n  DEFAULT_FIELD_REGISTRY,\n).reduce((acc, [type, entry]) => {\n  if (!entry) return acc;\n\n  acc[type] = {\n    ...entry,\n    renderer: (specializedRenderers[type] ??\n      DataFieldRenderer) as React.ComponentType<BuilderNodeRendererProps>,\n  };\n  return acc;\n}, {} as BuilderFieldRegistry);\n",
      "type": "registry:component",
      "target": "components/buzzform/builder/registry.tsx"
    }
  ],
  "type": "registry:ui"
}