{"version":3,"file":"adapter.cjs","names":["GenericBinder"],"sources":["../../../src/react-renderer/a2ui-react/adapter.tsx"],"sourcesContent":["/**\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, {\n  useRef,\n  useSyncExternalStore,\n  useCallback,\n  memo,\n  useEffect,\n} from \"react\";\nimport { type ComponentContext, GenericBinder } from \"@a2ui/web_core/v0_9\";\nimport type {\n  ComponentApi,\n  InferredComponentApiSchemaType,\n  ResolveA2uiProps,\n} from \"@a2ui/web_core/v0_9\";\n\nexport interface ReactComponentImplementation extends ComponentApi {\n  /** The framework-specific rendering wrapper. */\n  render: React.FC<{\n    context: ComponentContext;\n    buildChild: (id: string, basePath?: string) => React.ReactNode;\n  }>;\n}\n\nexport type ReactA2uiComponentProps<T> = {\n  props: T;\n  buildChild: (id: string, basePath?: string) => React.ReactNode;\n  context: ComponentContext;\n};\n\n// --- Component Factories ---\n\n/**\n * Creates a React component implementation using the deep generic binder.\n */\nexport function createReactComponent<Api extends ComponentApi>(\n  api: Api,\n  RenderComponent: React.FC<\n    ReactA2uiComponentProps<\n      ResolveA2uiProps<InferredComponentApiSchemaType<Api>>\n    >\n  >,\n): ReactComponentImplementation {\n  type Props = ResolveA2uiProps<InferredComponentApiSchemaType<Api>>;\n\n  const MemoizedRender = memo(RenderComponent, (prev, next) => {\n    if (prev.props !== next.props) return false;\n    if (prev.context.componentModel.id !== next.context.componentModel.id)\n      return false;\n    if (prev.context.dataContext.path !== next.context.dataContext.path)\n      return false;\n    return true;\n  });\n\n  const ReactWrapper: React.FC<{\n    context: ComponentContext;\n    buildChild: (id: string, basePath?: string) => React.ReactNode;\n  }> = ({ context, buildChild }) => {\n    const bindingRef = useRef<GenericBinder<Props> | null>(null);\n\n    // Create or recreate the binder if the context object changes.\n    // DeferredChild memoizes `context`, so reference changes strictly correspond\n    // to ComponentModel updates (like type changes) or Base Path adjustments.\n    if (!bindingRef.current) {\n      bindingRef.current = new GenericBinder<Props>(context, api.schema);\n    } else if (\n      (bindingRef.current as unknown as { context: ComponentContext })\n        .context !== context\n    ) {\n      bindingRef.current.dispose();\n      bindingRef.current = new GenericBinder<Props>(context, api.schema);\n    }\n    const binding = bindingRef.current;\n\n    const subscribe = useCallback(\n      (callback: () => void) => {\n        const sub = binding.subscribe(callback);\n        return () => sub.unsubscribe();\n      },\n      [binding],\n    );\n\n    const getSnapshot = useCallback(() => binding.snapshot, [binding]);\n    const props = useSyncExternalStore(subscribe, getSnapshot);\n\n    // Prevent DataModel subscription leaks on unmount\n    useEffect(() => {\n      return () => binding.dispose();\n    }, [binding]);\n\n    return (\n      <MemoizedRender\n        props={props || ({} as Props)}\n        buildChild={buildChild}\n        context={context}\n      />\n    );\n  };\n\n  return {\n    name: api.name,\n    schema: api.schema,\n    render: ReactWrapper,\n  };\n}\n\n/**\n * Creates a React component implementation that manages its own context bindings (no generic binder).\n */\nexport function createBinderlessComponent(\n  api: ComponentApi,\n  RenderComponent: React.FC<{\n    context: ComponentContext;\n    buildChild: (id: string, basePath?: string) => React.ReactNode;\n  }>,\n): ReactComponentImplementation {\n  return {\n    name: api.name,\n    schema: api.schema,\n    render: RenderComponent,\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,SAAgB,qBACd,KACA,iBAK8B;CAG9B,MAAM,iCAAsB,kBAAkB,MAAM,SAAS;AAC3D,MAAI,KAAK,UAAU,KAAK,MAAO,QAAO;AACtC,MAAI,KAAK,QAAQ,eAAe,OAAO,KAAK,QAAQ,eAAe,GACjE,QAAO;AACT,MAAI,KAAK,QAAQ,YAAY,SAAS,KAAK,QAAQ,YAAY,KAC7D,QAAO;AACT,SAAO;GACP;CAEF,MAAM,gBAGA,EAAE,SAAS,iBAAiB;EAChC,MAAM,+BAAiD,KAAK;AAK5D,MAAI,CAAC,WAAW,QACd,YAAW,UAAU,IAAIA,kCAAqB,SAAS,IAAI,OAAO;WAEjE,WAAW,QACT,YAAY,SACf;AACA,cAAW,QAAQ,SAAS;AAC5B,cAAW,UAAU,IAAIA,kCAAqB,SAAS,IAAI,OAAO;;EAEpE,MAAM,UAAU,WAAW;EAW3B,MAAM,gEARH,aAAyB;GACxB,MAAM,MAAM,QAAQ,UAAU,SAAS;AACvC,gBAAa,IAAI,aAAa;KAEhC,CAAC,QAAQ,CACV,+BAEqC,QAAQ,UAAU,CAAC,QAAQ,CAAC,CACR;AAG1D,6BAAgB;AACd,gBAAa,QAAQ,SAAS;KAC7B,CAAC,QAAQ,CAAC;AAEb,SACE,2CAAC;GACC,OAAO,SAAU,EAAE;GACP;GACH;IACT;;AAIN,QAAO;EACL,MAAM,IAAI;EACV,QAAQ,IAAI;EACZ,QAAQ;EACT"}