{"version":3,"file":"LLM2UI.cjs","sources":["../../../../../../src/sdk/react/LLM2UI.tsx"],"sourcesContent":["/**\r\n * LLM2UI React Component Wrapper\r\n * \r\n * React component wrapper for the LLM2UI JSON Renderer SDK.\r\n * Provides a declarative way to render UISchema in React applications.\r\n * \r\n * @module @llm2ui/renderer/react\r\n * @see Requirements 14.3, 14.5\r\n * \r\n * @example\r\n * ```tsx\r\n * import { LLM2UI } from '@llm2ui/renderer/react';\r\n * \r\n * function App() {\r\n *   return (\r\n *     <LLM2UI \r\n *       schema={schema}\r\n *       data={{ user: { name: 'John' } }}\r\n *       onEvent={(event) => console.log('Event:', event)}\r\n *     />\r\n *   );\r\n * }\r\n * ```\r\n */\r\n\r\nimport React, { useEffect, useMemo, useCallback, useRef, type ComponentType } from 'react';\r\nimport type { UISchema, DataContext, EventAction } from '../../types';\r\nimport type { PlatformType } from '../../lib/component-registry';\r\nimport { UIRenderer, type EventHandler } from '../../lib/renderer';\r\nimport { defaultRegistry, ComponentRegistry } from '../../lib/component-registry';\r\nimport { initializeDefaultRegistry } from '../../lib/shadcn-components';\r\n\r\n/**\r\n * UI Event emitted by the LLM2UI component\r\n */\r\nexport interface LLM2UIEvent {\r\n  /** Event type */\r\n  type: string;\r\n  /** Component ID that triggered the event */\r\n  componentId: string;\r\n  /** Event action payload */\r\n  action: EventAction;\r\n  /** Original React synthetic event */\r\n  originalEvent?: React.SyntheticEvent;\r\n}\r\n\r\n/**\r\n * Event callback function type\r\n */\r\nexport type LLM2UIEventCallback = (event: LLM2UIEvent) => void;\r\n\r\n/**\r\n * Custom component definition for SDK registration\r\n * Simplified version of ComponentDefinition for external use\r\n */\r\nexport interface CustomComponentDefinition {\r\n  /** Component name/type identifier */\r\n  name: string;\r\n  /** The actual React component */\r\n  component: ComponentType<Record<string, unknown>>;\r\n  /** Component description */\r\n  description?: string;\r\n  /** Component category for organization */\r\n  category?: 'input' | 'layout' | 'display' | 'feedback' | 'navigation' | string;\r\n  /** Props schema for validation */\r\n  propsSchema?: Record<string, {\r\n    type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'function';\r\n    required?: boolean;\r\n    default?: unknown;\r\n    description?: string;\r\n    enum?: string[];\r\n  }>;\r\n  /** Searchable tags */\r\n  tags?: string[];\r\n  /** Icon name */\r\n  icon?: string;\r\n}\r\n\r\n/**\r\n * LLM2UI Component Props\r\n */\r\nexport interface LLM2UIProps {\r\n  /** The UISchema to render */\r\n  schema: UISchema;\r\n  /** Additional data context to merge with schema.data */\r\n  data?: DataContext;\r\n  /** Event callback handler */\r\n  onEvent?: LLM2UIEventCallback;\r\n  /** Target platform for rendering */\r\n  platform?: PlatformType;\r\n  /** Theme mode */\r\n  theme?: 'light' | 'dark';\r\n  /** Custom CSS class name */\r\n  className?: string;\r\n  /** Inline styles */\r\n  style?: React.CSSProperties;\r\n  /** Custom component registry */\r\n  registry?: ComponentRegistry;\r\n  /** Custom components to register (simple format: name -> component) */\r\n  customComponents?: Record<string, ComponentType<Record<string, unknown>>>;\r\n  /** Custom component definitions with full metadata */\r\n  customComponentDefinitions?: CustomComponentDefinition[];\r\n  /** Whether to show error boundaries for component errors */\r\n  showErrors?: boolean;\r\n  /** Custom component for unknown types */\r\n  unknownComponent?: React.ComponentType<{ type: string; id: string }>;\r\n  /** Callback when rendering is complete */\r\n  onRender?: () => void;\r\n  /** Callback when an error occurs */\r\n  onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Initialize registry flag to prevent multiple initializations\r\n */\r\nlet defaultRegistryInitialized = false;\r\n\r\n/**\r\n * Ensure default registry is initialized\r\n */\r\nfunction ensureDefaultRegistryInitialized(): void {\r\n  if (!defaultRegistryInitialized) {\r\n    initializeDefaultRegistry();\r\n    defaultRegistryInitialized = true;\r\n  }\r\n}\r\n\r\n/**\r\n * LLM2UI React Component\r\n * \r\n * A declarative React component for rendering UISchema.\r\n * Provides a simple interface similar to amis low-code framework.\r\n * \r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * <LLM2UI schema={schema} />\r\n * \r\n * // With event handling\r\n * <LLM2UI \r\n *   schema={schema}\r\n *   onEvent={(event) => {\r\n *     if (event.type === 'submit') {\r\n *       handleSubmit(event.action);\r\n *     }\r\n *   }}\r\n * />\r\n * \r\n * // With custom components\r\n * <LLM2UI \r\n *   schema={schema}\r\n *   customComponents={{\r\n *     MyButton: ({ children, ...props }) => (\r\n *       <button className=\"my-btn\" {...props}>{children}</button>\r\n *     )\r\n *   }}\r\n * />\r\n * ```\r\n */\r\nexport const LLM2UI: React.FC<LLM2UIProps> = ({\r\n  schema,\r\n  data,\r\n  onEvent,\r\n  platform,\r\n  theme,\r\n  className,\r\n  style,\r\n  registry: customRegistry,\r\n  customComponents,\r\n  customComponentDefinitions,\r\n  showErrors = false,\r\n  unknownComponent,\r\n  onRender,\r\n  onError,\r\n}) => {\r\n  // Track if custom components have been registered\r\n  const registeredComponentsRef = useRef<Set<string>>(new Set());\r\n  \r\n  // Get or create registry\r\n  const registry = useMemo(() => {\r\n    if (customRegistry) {\r\n      return customRegistry;\r\n    }\r\n    ensureDefaultRegistryInitialized();\r\n    return defaultRegistry;\r\n  }, [customRegistry]);\r\n\r\n  // Register custom components (simple format)\r\n  useEffect(() => {\r\n    if (!customComponents) return;\r\n\r\n    const newComponents: string[] = [];\r\n    \r\n    for (const [name, component] of Object.entries(customComponents)) {\r\n      if (!registeredComponentsRef.current.has(name)) {\r\n        try {\r\n          registry.register({\r\n            name,\r\n            component,\r\n            description: `Custom component: ${name}`,\r\n          });\r\n          registeredComponentsRef.current.add(name);\r\n          newComponents.push(name);\r\n        } catch (error) {\r\n          // Component might already be registered, ignore\r\n          console.warn(`Failed to register custom component \"${name}\":`, error);\r\n        }\r\n      }\r\n    }\r\n\r\n    // Cleanup: we don't unregister components as they might be used elsewhere\r\n    // This is intentional to match amis behavior\r\n  }, [customComponents, registry]);\r\n\r\n  // Register custom component definitions (full format)\r\n  useEffect(() => {\r\n    if (!customComponentDefinitions) return;\r\n\r\n    for (const definition of customComponentDefinitions) {\r\n      if (!registeredComponentsRef.current.has(definition.name)) {\r\n        try {\r\n          registry.register({\r\n            name: definition.name,\r\n            component: definition.component,\r\n            description: definition.description || `Custom component: ${definition.name}`,\r\n            category: definition.category,\r\n            propsSchema: definition.propsSchema,\r\n            tags: definition.tags,\r\n            icon: definition.icon,\r\n          });\r\n          registeredComponentsRef.current.add(definition.name);\r\n        } catch (error) {\r\n          console.warn(`Failed to register custom component \"${definition.name}\":`, error);\r\n        }\r\n      }\r\n    }\r\n  }, [customComponentDefinitions, registry]);\r\n\r\n  // Merge schema data with additional data prop\r\n  const mergedSchema = useMemo<UISchema>(() => {\r\n    if (!data) return schema;\r\n    \r\n    return {\r\n      ...schema,\r\n      data: {\r\n        ...schema.data,\r\n        ...data,\r\n      },\r\n    };\r\n  }, [schema, data]);\r\n\r\n  // Create event handler that wraps the callback\r\n  const handleEvent = useCallback<EventHandler>(\r\n    (action, event, componentId) => {\r\n      if (onEvent) {\r\n        const llm2uiEvent: LLM2UIEvent = {\r\n          type: action.type,\r\n          componentId,\r\n          action,\r\n          originalEvent: event,\r\n        };\r\n        \r\n        try {\r\n          onEvent(llm2uiEvent);\r\n        } catch (error) {\r\n          console.error('Error in LLM2UI event handler:', error);\r\n          if (onError && error instanceof Error) {\r\n            onError(error);\r\n          }\r\n        }\r\n      }\r\n    },\r\n    [onEvent, onError]\r\n  );\r\n\r\n  // Call onRender callback after render\r\n  useEffect(() => {\r\n    if (onRender) {\r\n      onRender();\r\n    }\r\n  }, [mergedSchema, onRender]);\r\n\r\n  // Apply theme class\r\n  const themeClass = theme === 'dark' ? 'dark' : '';\r\n  const combinedClassName = [className, themeClass].filter(Boolean).join(' ') || undefined;\r\n\r\n  // Wrap in container div for styling\r\n  const containerStyle: React.CSSProperties = {\r\n    ...style,\r\n  };\r\n\r\n  return (\r\n    <div className={combinedClassName} style={containerStyle} data-llm2ui-root data-platform={platform}>\r\n      <UIRenderer\r\n        schema={mergedSchema}\r\n        registry={registry}\r\n        onEvent={handleEvent}\r\n        unknownComponent={unknownComponent}\r\n        showErrors={showErrors}\r\n      />\r\n    </div>\r\n  );\r\n};\r\n\r\n/**\r\n * Default export for convenience\r\n */\r\nexport default LLM2UI;\r\n"],"names":["defaultRegistryInitialized","ensureDefaultRegistryInitialized","initializeDefaultRegistry","LLM2UI","schema","data","onEvent","platform","theme","className","style","customRegistry","customComponents","customComponentDefinitions","showErrors","unknownComponent","onRender","onError","registeredComponentsRef","useRef","registry","useMemo","defaultRegistry","useEffect","name","component","definition","mergedSchema","handleEvent","useCallback","action","event","componentId","llm2uiEvent","error","combinedClassName","containerStyle","jsx","UIRenderer"],"mappings":"mSAmHA,IAAIA,EAA6B,GAKjC,SAASC,GAAyC,CAC3CD,IACHE,4BAAA,EACAF,EAA6B,GAEjC,CAkCO,MAAMG,EAAgC,CAAC,CAC5C,OAAAC,EACA,KAAAC,EACA,QAAAC,EACA,SAAAC,EACA,MAAAC,EACA,UAAAC,EACA,MAAAC,EACA,SAAUC,EACV,iBAAAC,EACA,2BAAAC,EACA,WAAAC,EAAa,GACb,iBAAAC,EACA,SAAAC,EACA,QAAAC,CACF,IAAM,CAEJ,MAAMC,EAA0BC,EAAAA,OAAoB,IAAI,GAAK,EAGvDC,EAAWC,EAAAA,QAAQ,IACnBV,IAGJV,EAAA,EACOqB,EAAAA,iBACN,CAACX,CAAc,CAAC,EAGnBY,EAAAA,UAAU,IAAM,CACd,GAAKX,GAIL,SAAW,CAACY,EAAMC,CAAS,IAAK,OAAO,QAAQb,CAAgB,EAC7D,GAAI,CAACM,EAAwB,QAAQ,IAAIM,CAAI,EAC3C,GAAI,CACFJ,EAAS,SAAS,CAChB,KAAAI,EACA,UAAAC,EACA,YAAa,qBAAqBD,CAAI,EAAA,CACvC,EACDN,EAAwB,QAAQ,IAAIM,CAAI,CAE1C,MAAgB,CAGhB,EAMN,EAAG,CAACZ,EAAkBQ,CAAQ,CAAC,EAG/BG,EAAAA,UAAU,IAAM,CACd,GAAKV,GAEL,UAAWa,KAAcb,EACvB,GAAI,CAACK,EAAwB,QAAQ,IAAIQ,EAAW,IAAI,EACtD,GAAI,CACFN,EAAS,SAAS,CAChB,KAAMM,EAAW,KACjB,UAAWA,EAAW,UACtB,YAAaA,EAAW,aAAe,qBAAqBA,EAAW,IAAI,GAC3E,SAAUA,EAAW,SACrB,YAAaA,EAAW,YACxB,KAAMA,EAAW,KACjB,KAAMA,EAAW,IAAA,CAClB,EACDR,EAAwB,QAAQ,IAAIQ,EAAW,IAAI,CACrD,MAAgB,CAEhB,EAGN,EAAG,CAACb,EAA4BO,CAAQ,CAAC,EAGzC,MAAMO,EAAeN,EAAAA,QAAkB,IAChChB,EAEE,CACL,GAAGD,EACH,KAAM,CACJ,GAAGA,EAAO,KACV,GAAGC,CAAA,CACL,EAPgBD,EASjB,CAACA,EAAQC,CAAI,CAAC,EAGXuB,EAAcC,EAAAA,YAClB,CAACC,EAAQC,EAAOC,IAAgB,CAC9B,GAAI1B,EAAS,CACX,MAAM2B,EAA2B,CAC/B,KAAMH,EAAO,KACb,YAAAE,EACA,OAAAF,EACA,cAAeC,CAAA,EAGjB,GAAI,CACFzB,EAAQ2B,CAAW,CACrB,OAASC,EAAO,CAEVjB,GAAWiB,aAAiB,OAC9BjB,EAAQiB,CAAK,CAEjB,CACF,CACF,EACA,CAAC5B,EAASW,CAAO,CAAA,EAInBM,EAAAA,UAAU,IAAM,CACVP,GACFA,EAAA,CAEJ,EAAG,CAACW,EAAcX,CAAQ,CAAC,EAI3B,MAAMmB,EAAoB,CAAC1B,EADRD,IAAU,OAAS,OAAS,EACC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAK,OAGzE4B,EAAsC,CAC1C,GAAG1B,CAAA,EAGL,OACE2B,EAAAA,IAAC,OAAI,UAAWF,EAAmB,MAAOC,EAAgB,mBAAgB,GAAC,gBAAe7B,EACxF,SAAA8B,EAAAA,IAACC,EAAAA,WAAA,CACC,OAAQX,EACR,SAAAP,EACA,QAASQ,EACT,iBAAAb,EACA,WAAAD,CAAA,CAAA,EAEJ,CAEJ"}