import { ROOT_CONTAINER_STYLE } from '@/host/constants/RootContainerStyle'; import { FrontComponentGeometryTrackerContext } from '@/host/contexts/FrontComponentGeometryTrackerContext'; import { createGeometryTracker } from '@/host/utils/createGeometryTracker'; import { FrontComponentConfirmationModalResultEffect } from '@/remote/components/FrontComponentConfirmationModalResultEffect'; import { FrontComponentErrorEffect } from '@/remote/components/FrontComponentErrorEffect'; import { FrontComponentGeometryTrackerEffect } from '@/remote/components/FrontComponentGeometryTrackerEffect'; import { FrontComponentInitializeHostCommunicationApiEffect } from '@/remote/components/FrontComponentInitializeHostCommunicationApiEffect'; import { FrontComponentUpdateContextEffect } from '@/remote/components/FrontComponentUpdateContextEffect'; import { FrontComponentUpdateHostCommunicationApiEffect } from '@/remote/components/FrontComponentUpdateHostCommunicationApiEffect'; import { type FrontComponentHostCommunicationApi } from '@/types/FrontComponentHostCommunicationApi'; import { type FrontComponentThread } from '@/types/FrontComponentThread'; import { type SdkClientUrls } from '@/types/SdkClientUrls'; import { type FrontComponentExecutionContext } from 'twenty-sdk/front-component'; import { type RemoteReceiver, RemoteRootRenderer, } from '@remote-dom/react/host'; import { type ReactNode, useState } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { isDefined } from 'twenty-shared/utils'; import { ThemeProvider } from 'twenty-ui/theme-constants'; import { FrontComponentWorkerEffect } from '../../remote/components/FrontComponentWorkerEffect'; import { componentRegistry } from '../generated/host-component-registry'; import { createFallbackComponentRegistry } from '../utils/createFallbackComponentRegistry'; import { FrontComponentErrorBox } from './FrontComponentErrorBox'; const fallbackComponentRegistry = createFallbackComponentRegistry(componentRegistry); type FrontComponentRendererProps = { componentUrl: string; applicationAccessToken?: string; apiUrl?: string; functionsBaseUrl?: string; sdkClientUrls?: SdkClientUrls; applicationVariables?: Record; executionContext: FrontComponentExecutionContext; frontComponentHostCommunicationApi: FrontComponentHostCommunicationApi; onError: (error?: Error) => void; colorScheme: 'light' | 'dark'; loadingFallback?: ReactNode; }; export const FrontComponentRenderer = ({ componentUrl, applicationAccessToken, apiUrl, functionsBaseUrl, sdkClientUrls, applicationVariables, executionContext, frontComponentHostCommunicationApi, onError, colorScheme, loadingFallback, }: FrontComponentRendererProps) => { const [receiver, setReceiver] = useState(null); const [thread, setThread] = useState(null); const [error, setError] = useState(null); const [isExecutionContextInitialized, setIsExecutionContextInitialized] = useState(false); const [geometryTracker] = useState(() => createGeometryTracker()); const isReady = isDefined(receiver) && isExecutionContextInitialized; return (
{isDefined(error) && ( )} {isDefined(thread) && ( <> setIsExecutionContextInitialized(true) } /> )} {!isDefined(error) && !isReady && loadingFallback} {isReady && ( setError(null)} resetKeys={[componentUrl]} fallbackRender={() => null} > )}
); };