{"version":3,"file":"RemoteRoot.mjs","names":[],"sources":["../../src/components/RemoteRoot.tsx"],"sourcesContent":["\"use client\";\nimport * as remoteComponents from \"@/auto-generated\";\nimport * as customViewComponents from \"@/views\";\nimport { useWatchPathname } from \"@/hooks/useWatchPathname\";\nimport { stringifyError } from \"@/lib/stringifyError\";\nimport { packageVersion } from \"@/version\";\nimport {\n  ComponentUsageProvider,\n  markViewComponents,\n  ViewComponentContextProvider,\n  type ComponentUsageHandler,\n} from \"@mittwald/flow-react-components/internal\";\nimport {\n  connectHostRenderRootRef,\n  connectRemoteReceiver,\n  type RemoteReceiver,\n  type RemoteToHostConnection,\n} from \"@mittwald/flow-remote-core\";\nimport {\n  Suspense,\n  useLayoutEffect,\n  useRef,\n  useState,\n  useTransition,\n  type CSSProperties,\n  type FC,\n  type PropsWithChildren,\n} from \"react\";\nimport { ErrorBoundary, type FallbackProps } from \"react-error-boundary\";\nimport { RemoteContextProvider } from \"@/components/RemoteContextProvider\";\nimport { LoadingFallbackTrigger } from \"@/components/LoadingFallbackTrigger\";\nimport {\n  DeprecationWarningProvider,\n  type DeprecationWarningHandler,\n  IntlProvider,\n  useLanguage,\n} from \"@mittwald/flow-react-components/flr-universal\";\nimport type { HostConfig } from \"@mittwald/ext-bridge\";\nimport { initExtBridge } from \"@mittwald/ext-bridge/browser\";\n\nconst viewComponents = {\n  ...remoteComponents,\n  ...customViewComponents,\n} as FlowViewComponents;\n\nconst { Div: LoadingFallbackDiv } = markViewComponents({\n  Div: remoteComponents.Div,\n});\n\nexport interface RemoteRootProps extends PropsWithChildren {\n  onHostPathnameChanged?: (pathname: string) => void;\n  isLoading?: boolean;\n  /** Internal use only */\n  __remoteReceiver?: RemoteReceiver;\n}\n\nconst hiddenStyle: CSSProperties = {\n  visibility: \"hidden\",\n  height: 0,\n  width: 0,\n  border: \"none\",\n  position: \"absolute\",\n  marginLeft: \"-9999px\",\n};\n\nexport const RemoteRoot: FC<RemoteRootProps> = (props) => {\n  const {\n    children,\n    onHostPathnameChanged,\n    isLoading,\n    __remoteReceiver: remoteReceiver,\n  } = props;\n\n  // The two branches use disjoint sets of hooks, so they live in dedicated\n  // components. This keeps each component's hook order stable (Rules of Hooks)\n  // while preserving the exact rendering of both paths.\n  if (remoteReceiver) {\n    return (\n      <RemoteReceiverRoot remoteReceiver={remoteReceiver}>\n        {children}\n      </RemoteReceiverRoot>\n    );\n  }\n\n  return (\n    <RemoteConnectionRoot\n      onHostPathnameChanged={onHostPathnameChanged}\n      isLoading={isLoading}\n    >\n      {children}\n    </RemoteConnectionRoot>\n  );\n};\n\ninterface RemoteReceiverRootProps extends PropsWithChildren {\n  remoteReceiver: RemoteReceiver;\n}\n\nconst RemoteReceiverRoot: FC<RemoteReceiverRootProps> = ({\n  remoteReceiver,\n  children,\n}) => (\n  <div\n    style={hiddenStyle}\n    ref={(div) => {\n      if (div) {\n        connectRemoteReceiver(div, remoteReceiver.connection);\n      }\n    }}\n  >\n    <ViewComponentContextProvider components={viewComponents}>\n      {children}\n    </ViewComponentContextProvider>\n  </div>\n);\n\ntype RemoteConnectionRootProps = Omit<RemoteRootProps, \"__remoteReceiver\">;\n\nconst RemoteConnectionRoot: FC<RemoteConnectionRootProps> = (props) => {\n  const {\n    children,\n    onHostPathnameChanged,\n    isLoading: isLoadingFromProps,\n  } = props;\n\n  const connectionRef = useRef<RemoteToHostConnection>(undefined);\n  const hostConfigRef = useRef<HostConfig | undefined>(undefined);\n  const isConnectionInitialized = useRef(false);\n  const [connectionError, setConnectionError] = useState(null);\n  const [hostError, setHostError] = useState<string | undefined>(undefined);\n  const [isConnected, setIsConnected] = useState(false);\n\n  const fallbackLanguage = useLanguage();\n  const language =\n    hostConfigRef.current?.language === undefined ||\n    hostConfigRef.current?.language?.trim() === \"\"\n      ? fallbackLanguage\n      : hostConfigRef.current.language;\n\n  const [pathnameChangedPending, startPathnameChangedTransition] =\n    useTransition();\n\n  const renderErrorRef = useRef<unknown>(undefined);\n\n  const handleRenderError = (error: unknown) => {\n    renderErrorRef.current = error;\n    connectionRef.current?.imports.setError(stringifyError(error));\n  };\n\n  const forwardDeprecationWarning: DeprecationWarningHandler = (message) => {\n    void connectionRef.current?.imports\n      .reportDeprecation?.(message)\n      ?.catch(() => {\n        // ignore: host does not support deprecation reporting\n      });\n  };\n\n  const reportedComponentUsage = useRef(new Set<string>());\n\n  const forwardComponentUsage: ComponentUsageHandler = ({ component }) => {\n    if (reportedComponentUsage.current.has(component)) {\n      return;\n    }\n    reportedComponentUsage.current.add(component);\n\n    void connectionRef.current?.imports\n      .reportEvent?.({\n        event: \"ComponentRendered\",\n        data: { component },\n      })\n      ?.catch(() => {\n        // ignore: host does not support event reporting\n      });\n  };\n\n  const setIsLoadingFromProps = () => {\n    if (isLoadingFromProps !== undefined) {\n      connectionRef.current?.imports.setIsLoading(isLoadingFromProps);\n    }\n  };\n\n  useLayoutEffect(() => {\n    setIsLoadingFromProps();\n  }, [isLoadingFromProps]);\n\n  useWatchPathname((pathname) =>\n    connectionRef.current?.imports.setNavigationState({\n      pathname,\n      isPending: pathnameChangedPending,\n    }),\n  );\n\n  if (connectionError) {\n    throw connectionError;\n  }\n\n  if (hostError) {\n    throw new Error(hostError);\n  }\n\n  const connect = connectHostRenderRootRef({\n    onPathnameChanged: (pathname) =>\n      startPathnameChangedTransition(() => onHostPathnameChanged?.(pathname)),\n    onHostError: (error) => setHostError(error),\n    packageVersion,\n  });\n\n  /** Is wrapped in Div to resolve render awaiter in <RemoteRenderer /> */\n  const loadingFallback = (\n    <LoadingFallbackDiv>\n      <LoadingFallbackTrigger />\n    </LoadingFallbackDiv>\n  );\n\n  const connectDiv = (div: HTMLDivElement) => {\n    if (isConnectionInitialized.current) {\n      return;\n    }\n    initExtBridge();\n    isConnectionInitialized.current = true;\n    connect(div)\n      ?.then((connection) => {\n        connectionRef.current = connection;\n        setIsLoadingFromProps();\n        return connection.imports.getHostConfig();\n      })\n      .then((hostConfig) => {\n        hostConfigRef.current = hostConfig;\n        setIsConnected(true);\n      })\n      .catch((error) => {\n        setConnectionError(error);\n      });\n\n    if (renderErrorRef.current) {\n      handleRenderError(renderErrorRef.current);\n    }\n  };\n\n  const ErrorFallbackComponent: FC<FallbackProps> = (props) => {\n    handleRenderError(props.error);\n    return null;\n  };\n\n  return (\n    <div ref={connectDiv}>\n      <ErrorBoundary FallbackComponent={ErrorFallbackComponent}>\n        {isConnected && connectionRef.current && (\n          <RemoteContextProvider\n            value={{\n              connection: connectionRef.current,\n            }}\n          >\n            <IntlProvider locale={language}>\n              <DeprecationWarningProvider onWarning={forwardDeprecationWarning}>\n                <ComponentUsageProvider onUsage={forwardComponentUsage}>\n                  <Suspense fallback={loadingFallback}>\n                    <ViewComponentContextProvider components={viewComponents}>\n                      {children}\n                    </ViewComponentContextProvider>\n                  </Suspense>\n                </ComponentUsageProvider>\n              </DeprecationWarningProvider>\n            </IntlProvider>\n          </RemoteContextProvider>\n        )}\n      </ErrorBoundary>\n    </div>\n  );\n};\n\nexport default RemoteRoot;\n"],"mappings":"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"}