'use client'; import { createElement, useEffect, useMemo, useSyncExternalStore, type ComponentType } from 'react'; import { FunnelProvider, FunnelRuntimeConfigBoundary, PrimaryButton, isPreviewFrameRuntime, runtimePublicConfig, scheduleNextStepImagePreload, usePreviewDefinitionOverrideRevision, usePreviewStepLocalizedContent, } from '@funnelsgrove/runtime'; import { FunnelEditorPanel, FunnelEditorPanelStyles } from './FunnelEditorPanel'; import { runtimeContent } from '@/steps/content/runtime.content'; import { getStepContentLocale } from '@/runtime/step-content-context'; import { funnelManifest } from '@/config/funnel.manifest'; import type { FunnelStepId } from '@/runtime/funnel-runtime'; import { useFunnelFlowController } from '@/runtime/use-funnel-flow-controller'; type FunnelFlowProps = { initialStepId?: FunnelStepId; lockToInitialStep?: boolean; isPreviewFrame?: boolean; isPreviewThumbnail?: boolean; }; function RuntimeConfigLoading() { const content = usePreviewStepLocalizedContent('runtime', runtimeContent, getStepContentLocale({})); return (
); } function RuntimeConfigStatus() { const content = usePreviewStepLocalizedContent('runtime', runtimeContent, getStepContentLocale({})); return (

{content.unavailableTitle}

{content.unavailableDescription}

); } export function FunnelFlow({ initialStepId, lockToInitialStep, isPreviewFrame, isPreviewThumbnail, }: FunnelFlowProps = {}) { const isPreviewRuntime = useMemo(() => { if (typeof isPreviewFrame === 'boolean') { return isPreviewFrame; } return isPreviewFrameRuntime(); }, [isPreviewFrame]); const previewFrameMounted = useSyncExternalStore( () => () => undefined, () => isPreviewRuntime, () => false, ); return ( } errorFallback={} > ); } function FunnelFlowRuntime({ initialStepId, lockToInitialStep, previewFrameMounted, isPreviewThumbnail, }: FunnelFlowProps & { previewFrameMounted: boolean; }) { const previewDefinitionRevision = usePreviewDefinitionOverrideRevision(); const content = usePreviewStepLocalizedContent('runtime', runtimeContent, getStepContentLocale({})); const controller = useFunnelFlowController({ initialStepId, lockToInitialStep, }); useEffect( () => scheduleNextStepImagePreload(funnelManifest, controller.activeStepId), [controller.activeStepId], ); if (!controller.activeStepComponent || !controller.activeStepMeta || !controller.renderedStepMeta) { return null; } const ActiveStep = controller.activeStepComponent as ComponentType>; return (
{controller.renderSuspended ? (
) : (
{createElement(ActiveStep)}
)}
{controller.showShellContinue && !controller.renderSuspended ? (
{controller.activeStepMeta.actionBar?.buttonText ? controller.buttonText : content.continueLabel}
) : null}
{ controller.setEditorPanelExpanded((currentValue) => !currentValue); }} />
); }