markdown-flow-ui 0.2.26-dev.2 → 0.2.26-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/markdown-flow-ui.css +1 -1
- package/dist/components/Slide/Player.cjs +1 -1
- package/dist/components/Slide/Player.cjs.map +1 -1
- package/dist/components/Slide/Player.d.ts +2 -1
- package/dist/components/Slide/Player.es.js +192 -195
- package/dist/components/Slide/Player.es.js.map +1 -1
- package/dist/components/Slide/Slide.cjs +1 -1
- package/dist/components/Slide/Slide.cjs.map +1 -1
- package/dist/components/Slide/Slide.d.ts +3 -1
- package/dist/components/Slide/Slide.es.js +685 -671
- package/dist/components/Slide/Slide.es.js.map +1 -1
- package/dist/markdown-flow-ui.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slide.cjs","sources":["../../../src/components/Slide/Slide.tsx"],"sourcesContent":["import React, {\n memo,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { ChevronLeft, GripHorizontal } from \"lucide-react\";\n\nimport { isSandboxInteractionMessage } from \"../../lib/sandboxInteraction\";\nimport { cn } from \"../../lib/utils\";\nimport { useResolvedDirection } from \"../../lib/useResolvedDirection\";\nimport {\n getMarkdownFlowDirection,\n getMarkdownFlowLanguage,\n type MarkdownFlowLocale,\n} from \"../../lib/locale\";\nimport LoadingOverlayCard from \"../ui/loading-overlay-card\";\nimport ContentRender from \"../ContentRender\";\nimport type { ContentRenderProps } from \"../ContentRender/ContentRender\";\nimport IframeSandbox from \"../ContentRender/IframeSandbox\";\nimport type { OnSendContentParams } from \"../types\";\nimport type { InteractionDefaultValueOptions } from \"../../lib/interaction-defaults\";\nimport {\n isLandscapeViewport as getIsFullscreenPreferredViewport,\n isMobileDevice as getIsMobileDevice,\n subscribeMobileDeviceChange,\n} from \"../../lib/mobileDevice\";\nimport Player from \"./Player\";\nimport MarkdownSlideScaling from \"./MarkdownSlideScaling\";\nimport SubtitleOverlay from \"./SubtitleOverlay\";\nimport type {\n PlayerProps,\n SlidePlayerNavigationContext,\n SlidePlayerSubtitleJumpTarget,\n SlidePlayerSubtitleSeekRequest,\n SlidePlayerTexts,\n} from \"./Player\";\nimport type { SlidePlayerLoadingReason } from \"./Player\";\nimport type { Element } from \"./types\";\nimport useSlide from \"./useSlide\";\nimport useWakePlayerFromIframe from \"./useWakePlayerFromIframe\";\nimport { PlayerKeyboardShortcutContext } from \"./utils/playerKeyboardShortcutContext\";\nimport { activatePlayerKeyboardShortcutOwner } from \"./utils/playerKeyboardShortcuts\";\nimport {\n DEFAULT_MOBILE_VIEW_MODE,\n resolveMobileViewModeState,\n type MobileViewMode,\n} from \"./utils/mobileScreenMode\";\nimport {\n clampInteractionOverlayDragOffset,\n shouldPresentInteractionOverlay,\n shouldRenderInteractionOverlay,\n type InteractionOverlayDragBounds,\n type InteractionOverlayDragOffset,\n} from \"./utils/interactionPlayback\";\nimport { resolveMarkdownScalingMode } from \"./utils/markdownScaling\";\nimport { shouldWakePlayerControlsAfterNavigation } from \"./utils/playerNavigationContext\";\nimport { shouldAutoAdvanceIntoAppendedMarker } from \"./utils/appendedMarkerAdvance\";\nimport {\n hasUnplayedStepAudio,\n resolvePendingStepAudioKey,\n} from \"./utils/stepAudioProgress\";\nimport {\n getPlaybackSequenceTransition,\n shouldStartDefaultAudioSequence,\n} from \"./utils/playbackSequence\";\nimport {\n canReachSubtitleJumpTarget,\n hasResolvedInteractionElement,\n} from \"./utils/subtitleJumpNavigation\";\nimport {\n getPlayerCustomActionCount,\n resolvePlayerCustomActionElement,\n} from \"./utils/playerCustomActions\";\nimport { createPlaybackTimeStore } from \"./utils/playbackTimeStore\";\nimport { resolveSlideInteractionState } from \"./utils/interactionResolution\";\nimport { shouldUseAutoAdvanceToggle } from \"./utils/playerToggleMode\";\nimport {\n areImageOnlyStepIframeVisualsReady,\n DEFAULT_IMAGE_ONLY_VISUAL_READY_TIMEOUT_MS,\n} from \"./utils/imageOnlyStepVisualReady\";\nimport { resolveSilentStepAutoAdvanceBehavior } from \"./utils/silentStepAutoAdvance\";\nimport {\n resolveSlidePlayerLayoutState,\n resolveSlidePlayerVisibility,\n type SlidePlayerControlsVisibility,\n} from \"./utils/playerVisibility\";\nimport {\n DEFAULT_SLIDE_BUFFERING_TEXTS,\n getSlideLocaleTexts,\n type SlideBufferingReason,\n} from \"./slideI18n\";\nimport \"./slide.css\";\nexport type {\n Element,\n ElementAudioSegment,\n ElementSubtitleCue,\n SlidePlayerCustomActionContext,\n SlidePlayerCustomActions,\n} from \"./types\";\nexport type { SlidePlayerControlsVisibility } from \"./utils/playerVisibility\";\n\nconst DEFAULT_MARKER_AUTO_ADVANCE_DELAY_MS = 2000;\nconst DEFAULT_INTERACTION_OVERLAY_OPEN_DELAY_MS = 300;\nconst DEFAULT_INTERACTION_OVERLAY_FALLBACK_OFFSET_PX = 160;\nconst DEFAULT_INTERACTION_SUBTITLE_GAP_PX = 16;\nconst DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS = 3000;\nconst DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET: InteractionOverlayDragOffset = {\n x: 0,\n y: 0,\n};\nconst INTERACTION_OVERLAY_LAYOUT_EPSILON_PX = 0.5;\ntype InteractionOverlayLayoutRect = Pick<DOMRect, \"left\" | \"top\">;\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\nconst INTERACTION_ACTIVITY_SELECTOR = [\n \"button\",\n \"input\",\n \"textarea\",\n '[contenteditable=\"\"]',\n '[contenteditable=\"true\"]',\n '[contenteditable=\"plaintext-only\"]',\n].join(\", \");\nconst DEFAULT_BUFFERING_REASON: SlideBufferingReason = \"waitingForAudio\";\n\nconst normalizeInteractionOverlayDragOffset = ({\n x,\n y,\n}: InteractionOverlayDragOffset): InteractionOverlayDragOffset => ({\n x: Number(x.toFixed(2)),\n y: Number(y.toFixed(2)),\n});\n\nconst hasMeaningfulInteractionOverlayLayoutDelta = (delta: number) =>\n Math.abs(delta) >= INTERACTION_OVERLAY_LAYOUT_EPSILON_PX;\n\nconst areInteractionOverlayDragOffsetsEqual = (\n first: InteractionOverlayDragOffset,\n second: InteractionOverlayDragOffset\n) =>\n Math.abs(first.x - second.x) < INTERACTION_OVERLAY_LAYOUT_EPSILON_PX &&\n Math.abs(first.y - second.y) < INTERACTION_OVERLAY_LAYOUT_EPSILON_PX;\n\nexport type { SlideBufferingReason } from \"./slideI18n\";\n\nexport type SlideBufferingTextConfig =\n | string\n | Partial<Record<SlideBufferingReason, string>>;\n\nconst resolveBufferingTextByReason = (\n bufferingText: SlideBufferingTextConfig,\n reason: SlideBufferingReason\n) => {\n if (typeof bufferingText === \"string\") {\n return bufferingText;\n }\n\n return (\n bufferingText[reason] ??\n bufferingText[DEFAULT_BUFFERING_REASON] ??\n DEFAULT_SLIDE_BUFFERING_TEXTS[reason]\n );\n};\n\nconst mergeBufferingTextWithLocaleDefaults = (\n bufferingText: SlideBufferingTextConfig | undefined,\n localeBufferingText: Record<string, string>\n): SlideBufferingTextConfig => {\n if (typeof bufferingText === \"string\") {\n return bufferingText;\n }\n\n return {\n ...localeBufferingText,\n ...bufferingText,\n };\n};\n\nconst shouldShowBufferingOverlay = (\n reason: SlideBufferingReason | null,\n loading: boolean\n) => {\n if (!loading) {\n return false;\n }\n\n // Keep the silent preload/loading phase invisible until audio is actually playable.\n return reason !== \"loadingAudio\";\n};\n\ntype RenderSlideElementOptions = {\n replaceRootScreenHeightWithFull?: boolean;\n};\n\ninterface InteractionOverlayCardProps {\n dir?: ContentRenderProps[\"dir\"];\n lang?: string;\n content: string;\n title: string;\n dragHandleAriaLabel: string;\n locale?: MarkdownFlowLocale;\n defaultButtonText?: string;\n defaultInputText?: string;\n defaultSelectedValues?: string[];\n confirmButtonText?: string;\n copyButtonText?: string;\n copiedButtonText?: string;\n onSend?: (content: OnSendContentParams) => void;\n onDragHandlePointerCancel?: React.PointerEventHandler<HTMLButtonElement>;\n onDragHandlePointerDown?: React.PointerEventHandler<HTMLButtonElement>;\n onDragHandlePointerMove?: React.PointerEventHandler<HTMLButtonElement>;\n onDragHandlePointerUp?: React.PointerEventHandler<HTMLButtonElement>;\n readonly?: boolean;\n}\n\nexport interface SlideInteractionTexts\n extends Pick<\n ContentRenderProps,\n \"confirmButtonText\" | \"copyButtonText\" | \"copiedButtonText\"\n > {\n title?: string;\n /** Accessible label for the interaction panel drag handle. */\n dragHandleAriaLabel?: string;\n}\n\nexport type SlideFullscreenHeader = {\n content?: React.ReactNode;\n backAriaLabel?: string;\n onBack?: () => void;\n};\n\nconst InteractionOverlayCard = memo(\n ({\n content,\n title,\n dragHandleAriaLabel,\n locale,\n dir,\n lang,\n defaultButtonText,\n defaultInputText,\n defaultSelectedValues,\n confirmButtonText,\n copyButtonText,\n copiedButtonText,\n onSend,\n onDragHandlePointerCancel,\n onDragHandlePointerDown,\n onDragHandlePointerMove,\n onDragHandlePointerUp,\n readonly = false,\n }: InteractionOverlayCardProps) => (\n <div className=\"slide-player__interaction-card\">\n <button\n type=\"button\"\n className=\"slide-player__interaction-drag-handle\"\n aria-label={dragHandleAriaLabel}\n onPointerCancel={onDragHandlePointerCancel}\n onPointerDown={onDragHandlePointerDown}\n onPointerMove={onDragHandlePointerMove}\n onPointerUp={onDragHandlePointerUp}\n >\n <span className=\"slide-player__interaction-drag-handle-icon\">\n <GripHorizontal aria-hidden=\"true\" />\n <GripHorizontal aria-hidden=\"true\" />\n <GripHorizontal aria-hidden=\"true\" />\n </span>\n </button>\n <div className=\"slide-player__interaction-header\">\n <p className=\"slide-player__interaction-title\">{title}</p>\n </div>\n <div className=\"slide-player__interaction-body\">\n <ContentRender\n content={content}\n locale={locale}\n dir={dir}\n lang={lang}\n defaultButtonText={defaultButtonText}\n defaultInputText={defaultInputText}\n defaultSelectedValues={defaultSelectedValues}\n confirmButtonText={confirmButtonText}\n copyButtonText={copyButtonText}\n copiedButtonText={copiedButtonText}\n onSend={onSend}\n readonly={readonly}\n sandboxMode=\"content\"\n />\n </div>\n </div>\n )\n);\n\nInteractionOverlayCard.displayName = \"InteractionOverlayCard\";\n\nconst areStepElementListsEqual = (\n prevElementList: Element[],\n nextElementList: Element[]\n) =>\n prevElementList.length === nextElementList.length &&\n prevElementList.every((element, index) => {\n const nextElement = nextElementList[index];\n\n return (\n element.sequence_number === nextElement?.sequence_number &&\n element.type === nextElement?.type &&\n element.content === nextElement?.content\n );\n });\n\nconst isInteractionActivityTarget = (\n target: EventTarget | null\n): target is HTMLElement =>\n target instanceof HTMLElement &&\n Boolean(target.closest(INTERACTION_ACTIVITY_SELECTOR));\nexport interface SlideProps extends React.ComponentProps<\"section\"> {\n elementList?: Element[];\n /** Locale used for built-in UI text when a more specific text prop is not provided. */\n locale?: MarkdownFlowLocale;\n /** Enables the player runtime, including audio playback and keyboard shortcuts. */\n playerEnabled?: boolean;\n /**\n * Controls whether the player controls are always visible, always hidden, or auto-hidden.\n *\n * Use `\"hidden\"` to keep audio playback and keyboard shortcuts active while\n * hiding the visual controls.\n *\n * @example\n * ```tsx\n * <Slide playerControlsVisibility=\"hidden\" enableKeyboardShortcuts />\n * ```\n */\n playerControlsVisibility?: SlidePlayerControlsVisibility;\n playerClassName?: string;\n fullscreenHeader?: SlideFullscreenHeader;\n playerCustomActions?: PlayerProps[\"customActions\"];\n playerCustomActionPauseOnActive?: boolean;\n bufferingText?: SlideBufferingTextConfig;\n interactionTitle?: string;\n interactionTexts?: SlideInteractionTexts;\n playerTexts?: SlidePlayerTexts;\n playerAutoHideDelay?: number;\n markerAutoAdvanceDelay?: number;\n /** Shows a read-only segmented indicator for generated slide steps. */\n showSlideProgress?: boolean;\n interactionDefaultValueOptions?: InteractionDefaultValueOptions;\n onSend?: (content: OnSendContentParams, element?: Element) => void;\n onPlayerVisibilityChange?: (visible: boolean) => void;\n onMobileViewModeChange?: (viewMode: MobileViewMode) => void;\n onStepChange?: (element: Element | undefined, index: number) => void;\n /** Emits a low-frequency checkpoint for the active logical audio item. */\n onPlaybackCheckpoint?: (checkpoint: SlidePlaybackCheckpoint) => void;\n /** Restores one logical audio item and continues its normal playback. */\n playbackRestoreRequest?: SlidePlaybackRestoreRequest | null;\n /**\n * Enables keyboard shortcuts for existing player actions.\n *\n * Defaults to `true`. The active slide responds after users click, touch, or\n * focus the slide/player surface; ignored targets include form controls and\n * interaction overlays.\n *\n * @example\n * ```tsx\n * <Slide elementList={slides} enableKeyboardShortcuts={false} />\n * ```\n */\n enableKeyboardShortcuts?: boolean;\n enableIframeScaling?: boolean;\n /**\n * Fits Markdown-only slides to the available presentation viewport.\n *\n * Defaults to `true`. Disable this to preserve the fixed 16px article\n * typography used by standalone ContentRender.\n */\n enableMarkdownScaling?: boolean;\n disableLoadingOverlay?: boolean;\n}\n\nexport interface SlidePlaybackCheckpoint {\n audioKey: string;\n element: Element;\n isComplete: boolean;\n stepIndex: number;\n timeMs: number;\n}\n\nexport interface SlidePlaybackRestoreRequest {\n audioKey: string;\n id: number | string;\n timeMs: number;\n}\n\nconst Slide: React.FC<SlideProps> = ({\n elementList = [],\n locale,\n playerEnabled,\n playerControlsVisibility,\n playerClassName,\n fullscreenHeader,\n playerCustomActions,\n playerCustomActionPauseOnActive = true,\n bufferingText,\n interactionTitle,\n interactionTexts,\n playerTexts,\n playerAutoHideDelay = 3000,\n markerAutoAdvanceDelay = DEFAULT_MARKER_AUTO_ADVANCE_DELAY_MS,\n showSlideProgress = false,\n interactionDefaultValueOptions,\n onSend,\n onPlayerVisibilityChange,\n onMobileViewModeChange,\n onStepChange,\n onPlaybackCheckpoint,\n playbackRestoreRequest = null,\n enableKeyboardShortcuts = true,\n enableIframeScaling = true,\n enableMarkdownScaling = true,\n disableLoadingOverlay = false,\n className,\n dir,\n lang,\n onPointerDown,\n onFocusCapture,\n ...props\n}) => {\n const direction = dir ?? getMarkdownFlowDirection(locale);\n const language = lang ?? getMarkdownFlowLanguage(locale);\n const localeTexts = useMemo(() => getSlideLocaleTexts(locale), [locale]);\n const resolvedBufferingText = useMemo(\n () =>\n mergeBufferingTextWithLocaleDefaults(\n bufferingText,\n localeTexts.bufferingText\n ),\n [bufferingText, localeTexts.bufferingText]\n );\n const {\n playerEnabled: resolvedPlayerEnabled,\n playerControlsVisibility: resolvedPlayerControlsVisibility,\n } = resolveSlidePlayerVisibility({\n playerEnabled,\n playerControlsVisibility,\n });\n const keyboardShortcutOwnerId = useId();\n const sectionRef = useRef<HTMLElement | null>(null);\n const { resolvedDirection } = useResolvedDirection(sectionRef, direction);\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const stageLayerRef = useRef<HTMLDivElement | null>(null);\n const lastElementRef = useRef<HTMLDivElement | null>(null);\n const playerHideTimerRef = useRef<number | null>(null);\n const isPointerInsidePlayerControlsRef = useRef(false);\n const autoAdvanceTimerRef = useRef<number | null>(null);\n const imageOnlyStepReadyTimeoutRef = useRef<number | null>(null);\n const interactionAutoCloseTimerRef = useRef<number | null>(null);\n const interactionOverlayOpenTimerRef = useRef<number | null>(null);\n const interactionOverlayRef = useRef<HTMLDivElement | null>(null);\n const interactionOverlayLayoutRectRef =\n useRef<InteractionOverlayLayoutRect | null>(null);\n const interactionOverlayDragRef = useRef<{\n pointerId: number;\n startClientX: number;\n startClientY: number;\n startOffset: InteractionOverlayDragOffset;\n bounds: InteractionOverlayDragBounds;\n } | null>(null);\n const prevRenderElementKeysRef = useRef<string[]>([]);\n const shouldScrollToBottomRef = useRef(false);\n const pendingInteractionOverlayStepIndexRef = useRef<number | null>(null);\n const pendingSubtitleJumpRef = useRef<{\n audioIndex: number;\n audioKey: string;\n slideIndex: number;\n timeMs: number;\n } | null>(null);\n const subtitleSeekRequestIdRef = useRef(0);\n const playbackResetKeyRef = useRef<string | null>(null);\n const appendedMarkerAdvanceStateRef = useRef({\n markerCount: 0,\n currentIndex: -1,\n canGoNext: false,\n });\n const shouldSkipDefaultAudioStartForSubtitleJumpRef = useRef(false);\n const {\n currentElementList,\n stepElementLists,\n slideElementList,\n currentIndex,\n audioList,\n audioSlideIndexes,\n currentAudioSequenceIndexes,\n currentStepHasSpeakableElement,\n currentInteractionElement,\n canGoPrev,\n canGoNext,\n handlePrev: goPrev,\n handleNext: goNext,\n handleGoTo: goTo,\n } = useSlide(elementList);\n const currentStepElement = useMemo(() => {\n if (currentIndex < 0) {\n return undefined;\n }\n\n return slideElementList[currentIndex];\n }, [currentIndex, slideElementList]);\n const currentRenderElementKeys = useMemo(\n () =>\n currentElementList.map(\n (element, index) =>\n `${element.sequence_number ?? `${element.type}-${index}`}:${String(element.is_new ?? \"\")}`\n ),\n [currentElementList]\n );\n const generatedSlideCount = slideElementList.length;\n const isSingleSlide = generatedSlideCount === 1;\n const shouldMountPlayer =\n resolvedPlayerEnabled &&\n (slideElementList.length > 0 ||\n audioList.length > 0 ||\n Boolean(currentInteractionElement));\n const keyboardShortcutContextValue = useMemo(\n () => ({\n enabled: enableKeyboardShortcuts,\n ownerId: keyboardShortcutOwnerId,\n }),\n [enableKeyboardShortcuts, keyboardShortcutOwnerId]\n );\n const activateKeyboardShortcutOwner = useCallback(() => {\n if (!enableKeyboardShortcuts || !shouldMountPlayer) {\n return;\n }\n\n activatePlayerKeyboardShortcutOwner(keyboardShortcutOwnerId);\n }, [enableKeyboardShortcuts, keyboardShortcutOwnerId, shouldMountPlayer]);\n const currentAudioSequenceKeys = useMemo(\n () =>\n currentAudioSequenceIndexes\n .map((audioIndex) => audioList[audioIndex]?.audioKey)\n .filter((audioKey): audioKey is string => Boolean(audioKey)),\n [audioList, currentAudioSequenceIndexes]\n );\n const [isPlayerVisible, setIsPlayerVisible] = useState(true);\n const [hasPlayerInteracted, setHasPlayerInteracted] = useState(false);\n const [isPlaybackRequested, setIsPlaybackRequested] = useState(true);\n const [isAutoAdvanceEnabled, setIsAutoAdvanceEnabled] = useState(true);\n const [currentAudioKey, setCurrentAudioKey] = useState<string | null>(null);\n const [pendingPlaybackRestore, setPendingPlaybackRestore] =\n useState<SlidePlaybackRestoreRequest | null>(null);\n const pendingPlaybackRestoreRef = useRef<SlidePlaybackRestoreRequest | null>(\n null\n );\n const lastPlaybackRestoreRequestIdRef = useRef<number | string | null>(null);\n const [subtitleSeekRequest, setSubtitleSeekRequest] =\n useState<SlidePlayerSubtitleSeekRequest | null>(null);\n const [isAudioLoadingVisible, setIsAudioLoadingVisible] = useState(false);\n const [audioLoadingReason, setAudioLoadingReason] =\n useState<SlideBufferingReason>(DEFAULT_BUFFERING_REASON);\n const [hasCompletedCurrentStepAudio, setHasCompletedCurrentStepAudio] =\n useState(false);\n // Audio keys already played within the current step. A step's audio arrives\n // progressively while content is still being generated, so \"completed\" has to\n // mean \"every key played\" rather than \"reached the end of the list once\".\n const playedAudioKeysRef = useRef<Set<string>>(new Set());\n const [hasCurrentAudioPlaybackStarted, setHasCurrentAudioPlaybackStarted] =\n useState(false);\n const [isSubtitleEnabled, setIsSubtitleEnabled] = useState(true);\n const [isPlayerCustomActionActive, setIsPlayerCustomActionActive] =\n useState(false);\n const [activeInteractionElement, setActiveInteractionElement] = useState<\n Element | undefined\n >();\n const [isInteractionOverlayOpen, setIsInteractionOverlayOpen] =\n useState(false);\n const [hasInteractionOverlayActivity, setHasInteractionOverlayActivity] =\n useState(false);\n const [interactionOverlayDragOffset, setInteractionOverlayDragOffset] =\n useState<InteractionOverlayDragOffset>(\n DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET\n );\n const [isInteractionOverlayDragging, setIsInteractionOverlayDragging] =\n useState(false);\n const [\n interactionOverlaySubtitleOffset,\n setInteractionOverlaySubtitleOffset,\n ] = useState(0);\n const [isBrowserFullscreen, setIsBrowserFullscreen] = useState(false);\n const isMobileDevice = useMemo(() => getIsMobileDevice(), []);\n const [mobileViewMode, setMobileViewMode] = useState<MobileViewMode>(\n DEFAULT_MOBILE_VIEW_MODE\n );\n const [hasManualMobileViewMode, setHasManualMobileViewMode] = useState(false);\n const [isViewportFullscreenPreferred, setIsViewportFullscreenPreferred] =\n useState(() =>\n isMobileDevice ? getIsFullscreenPreferredViewport() : false\n );\n const playbackTimeStore = useMemo(() => createPlaybackTimeStore(), []);\n const {\n effectiveMobileViewMode,\n isImmersiveMobileFullscreen,\n isNativeMobileFullscreen,\n shouldRotateFullscreenViewport,\n } = useMemo(\n () =>\n resolveMobileViewModeState({\n hasManualMobileViewMode,\n isMobileDevice,\n isViewportFullscreenPreferred,\n mobileViewMode,\n }),\n [\n hasManualMobileViewMode,\n isMobileDevice,\n isViewportFullscreenPreferred,\n mobileViewMode,\n ]\n );\n const previousEffectiveMobileViewModeRef = useRef(effectiveMobileViewMode);\n const {\n controlsVisible: playerControlsVisible,\n layoutReserved: playerLayoutReserved,\n } = resolveSlidePlayerLayoutState({\n isAutoVisible: isPlayerVisible,\n playerControlsVisibility: resolvedPlayerControlsVisibility,\n shouldMountPlayer,\n });\n const shouldShowFullscreenHeader =\n isImmersiveMobileFullscreen && playerControlsVisible;\n const shouldApplyFullscreenViewportPadding =\n isImmersiveMobileFullscreen && playerLayoutReserved;\n const shouldShowMobileFullscreenMask =\n isImmersiveMobileFullscreen || isNativeMobileFullscreen;\n const isDesktopBrowserFullscreen = isBrowserFullscreen && !isMobileDevice;\n const handleMobileViewModeSelect = useCallback(\n (nextViewMode: MobileViewMode) => {\n setHasManualMobileViewMode(true);\n setMobileViewMode(nextViewMode);\n },\n []\n );\n const handleMobileViewModeReset = useCallback(() => {\n // Clear manual override so the effective mode returns to the default non-fullscreen state.\n setHasManualMobileViewMode(false);\n setMobileViewMode(DEFAULT_MOBILE_VIEW_MODE);\n }, []);\n const handleFullscreenHeaderBack = useCallback(() => {\n handleMobileViewModeReset();\n fullscreenHeader?.onBack?.();\n }, [fullscreenHeader, handleMobileViewModeReset]);\n\n const clearInteractionAutoCloseTimer = useCallback(() => {\n if (interactionAutoCloseTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(interactionAutoCloseTimerRef.current);\n interactionAutoCloseTimerRef.current = null;\n }, []);\n\n const clearInteractionOverlayOpenTimer = useCallback(() => {\n if (interactionOverlayOpenTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(interactionOverlayOpenTimerRef.current);\n interactionOverlayOpenTimerRef.current = null;\n }, []);\n\n const closeInteractionOverlayForCustomAction = useCallback(() => {\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n setIsInteractionOverlayOpen(false);\n setInteractionOverlaySubtitleOffset(0);\n }, [clearInteractionAutoCloseTimer, clearInteractionOverlayOpenTimer]);\n\n const setPlayerCustomActionActive = useCallback(\n (active: boolean) => {\n if (active) {\n closeInteractionOverlayForCustomAction();\n }\n\n setIsPlayerCustomActionActive(active);\n },\n [closeInteractionOverlayForCustomAction]\n );\n const togglePlayerCustomActionActive = useCallback(() => {\n closeInteractionOverlayForCustomAction();\n setIsPlayerCustomActionActive((previousActive) => !previousActive);\n }, [closeInteractionOverlayForCustomAction]);\n const resetInteractionOverlayDragState = useCallback(() => {\n setInteractionOverlayDragOffset((previousOffset) =>\n previousOffset.x === DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET.x &&\n previousOffset.y === DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET.y\n ? previousOffset\n : DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET\n );\n setIsInteractionOverlayDragging(false);\n interactionOverlayDragRef.current = null;\n interactionOverlayLayoutRectRef.current = null;\n }, []);\n const { mountedStepStates, currentMountedStateIndex } = useMemo(() => {\n const nextMountedStepStates: Array<{\n elementList: Element[];\n sourceStepIndexes: number[];\n }> = [];\n const mountedStateIndexByStep = new Map<number, number>();\n\n stepElementLists.forEach((stepElementList, stepIndex) => {\n const existingMountedStateIndex = nextMountedStepStates.findIndex(\n (mountedStepState) =>\n areStepElementListsEqual(\n mountedStepState.elementList,\n stepElementList\n )\n );\n\n if (existingMountedStateIndex >= 0) {\n nextMountedStepStates[\n existingMountedStateIndex\n ]?.sourceStepIndexes.push(stepIndex);\n mountedStateIndexByStep.set(stepIndex, existingMountedStateIndex);\n return;\n }\n\n nextMountedStepStates.push({\n elementList: stepElementList,\n sourceStepIndexes: [stepIndex],\n });\n mountedStateIndexByStep.set(stepIndex, nextMountedStepStates.length - 1);\n });\n\n return {\n mountedStepStates: nextMountedStepStates,\n currentMountedStateIndex:\n currentIndex >= 0\n ? (mountedStateIndexByStep.get(currentIndex) ?? -1)\n : -1,\n };\n }, [currentIndex, stepElementLists]);\n const currentStepKey = useMemo(() => String(currentIndex), [currentIndex]);\n const currentAudioIndex = useMemo(() => {\n if (!currentAudioKey) {\n return -1;\n }\n\n return audioList.findIndex(\n (audioItem) => (audioItem.audioKey ?? \"\") === currentAudioKey\n );\n }, [audioList, currentAudioKey]);\n const currentAudioItem = useMemo(\n () => (currentAudioIndex >= 0 ? audioList[currentAudioIndex] : undefined),\n [audioList, currentAudioIndex]\n );\n\n useEffect(() => {\n if (\n !playbackRestoreRequest ||\n playbackRestoreRequest.id === lastPlaybackRestoreRequestIdRef.current\n ) {\n return;\n }\n\n const targetAudioIndex = audioList.findIndex(\n (audioItem) => audioItem.audioKey === playbackRestoreRequest.audioKey\n );\n if (targetAudioIndex < 0) {\n return;\n }\n\n const targetStepIndex = audioSlideIndexes[targetAudioIndex];\n if (targetStepIndex == null) {\n return;\n }\n\n lastPlaybackRestoreRequestIdRef.current = playbackRestoreRequest.id;\n setIsPlaybackRequested(true);\n setCurrentAudioKey(playbackRestoreRequest.audioKey);\n pendingPlaybackRestoreRef.current = playbackRestoreRequest;\n setPendingPlaybackRestore(playbackRestoreRequest);\n if (currentIndex !== targetStepIndex) {\n goTo(targetStepIndex);\n }\n }, [\n audioList,\n audioSlideIndexes,\n currentIndex,\n goTo,\n playbackRestoreRequest,\n ]);\n const currentSubtitleCues = currentAudioItem?.element?.subtitle_cues ?? [];\n const currentAudioSequenceStartKey = useMemo(\n () => currentAudioSequenceKeys[0] ?? \"none\",\n [currentAudioSequenceKeys]\n );\n const playerCustomActionContext = useMemo(\n () => ({\n currentElement: resolvePlayerCustomActionElement({\n currentAudioIndex,\n currentAudioSequenceIndexes,\n audioList,\n currentInteractionElement: activeInteractionElement,\n currentStepElement,\n }),\n currentIndex,\n currentStepElement,\n isActive: isPlayerCustomActionActive,\n setActive: setPlayerCustomActionActive,\n toggleActive: togglePlayerCustomActionActive,\n }),\n [\n activeInteractionElement,\n audioList,\n currentAudioIndex,\n currentAudioSequenceIndexes,\n currentIndex,\n currentStepElement,\n isPlayerCustomActionActive,\n setPlayerCustomActionActive,\n togglePlayerCustomActionActive,\n ]\n );\n const playerCustomActionCount = useMemo(\n () =>\n getPlayerCustomActionCount(\n playerCustomActions,\n playerCustomActionContext\n ),\n [playerCustomActionContext, playerCustomActions]\n );\n const hasPlayerCustomActions = playerCustomActionCount > 0;\n const isPlayerCustomActionEffectivelyActive =\n hasPlayerCustomActions && isPlayerCustomActionActive;\n const interactionOverlayStyle = useMemo(\n () =>\n ({\n \"--slide-player-custom-action-count\": String(playerCustomActionCount),\n \"--slide-player-mobile-control-count\": String(\n playerCustomActionCount + 4\n ),\n \"--slide-interaction-drag-x\": `${interactionOverlayDragOffset.x}px`,\n \"--slide-interaction-drag-y\": `${interactionOverlayDragOffset.y}px`,\n }) as React.CSSProperties,\n [\n interactionOverlayDragOffset.x,\n interactionOverlayDragOffset.y,\n playerCustomActionCount,\n ]\n );\n const hasAvailableStepAudio = currentAudioSequenceKeys.length > 0;\n const currentInteractionResetKey = useMemo(() => {\n if (!currentInteractionElement) {\n return \"none\";\n }\n\n return `${currentInteractionElement.sequence_number ?? \"none\"}:${String(\n currentInteractionElement.content ?? \"\"\n )}`;\n }, [currentInteractionElement]);\n const currentPlaybackResetKey = useMemo(\n () => [currentStepKey, currentInteractionResetKey].join(\"|\"),\n [currentInteractionResetKey, currentStepKey]\n );\n const currentPlaybackStartedResetKey = useMemo(\n () =>\n [\n currentPlaybackResetKey,\n currentAudioItem?.audioKey ?? \"none\",\n String(currentAudioIndex),\n ].join(\"|\"),\n [currentAudioIndex, currentAudioItem?.audioKey, currentPlaybackResetKey]\n );\n const currentStepAudioUrl = useMemo(() => {\n if (\n !currentAudioSequenceStartKey ||\n currentAudioSequenceStartKey === \"none\"\n ) {\n return \"\";\n }\n\n const currentStepAudioItem = audioList.find(\n (audioItem) => audioItem.audioKey === currentAudioSequenceStartKey\n );\n\n return currentStepAudioItem?.audioUrl?.trim() ?? \"\";\n }, [audioList, currentAudioSequenceStartKey]);\n const hasCurrentStepAudioUrl = Boolean(currentStepAudioUrl);\n const shouldPausePlaybackForCustomAction =\n playerCustomActionPauseOnActive && isPlayerCustomActionEffectivelyActive;\n const shouldUseSilentStepAutoAdvanceToggle = useMemo(\n () =>\n shouldUseAutoAdvanceToggle({\n canGoNext,\n currentAudioIndex,\n currentStepHasSpeakableElement,\n hasInteraction: Boolean(currentInteractionElement),\n }),\n [\n canGoNext,\n currentAudioIndex,\n currentInteractionElement,\n currentStepHasSpeakableElement,\n ]\n );\n const silentStepAutoAdvanceBehavior = useMemo(\n () =>\n resolveSilentStepAutoAdvanceBehavior({\n currentElementList,\n currentStepHasSpeakableElement,\n currentInteractionElement,\n markerAutoAdvanceDelay,\n }),\n [\n currentElementList,\n currentInteractionElement,\n currentStepHasSpeakableElement,\n markerAutoAdvanceDelay,\n ]\n );\n const silentStepAutoAdvanceDelay = silentStepAutoAdvanceBehavior.delayMs;\n const isImageOnlySilentStep =\n silentStepAutoAdvanceBehavior.usesImageOnlyDelay;\n const imageOnlyStepVisualReadyKey = useMemo(\n () => `${currentIndex}:${currentRenderElementKeys.join(\"|\")}`,\n [currentIndex, currentRenderElementKeys]\n );\n const [readyImageOnlyStepKey, setReadyImageOnlyStepKey] = useState<\n string | null\n >(null);\n const isImageOnlyStepVisualReady =\n !isImageOnlySilentStep ||\n readyImageOnlyStepKey === imageOnlyStepVisualReadyKey;\n\n const clearPlayerHideTimer = useCallback(() => {\n if (playerHideTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(playerHideTimerRef.current);\n playerHideTimerRef.current = null;\n }, []);\n\n const clearAutoAdvanceTimer = useCallback(() => {\n if (autoAdvanceTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(autoAdvanceTimerRef.current);\n autoAdvanceTimerRef.current = null;\n }, []);\n\n const clearImageOnlyStepReadyTimeout = useCallback(() => {\n if (imageOnlyStepReadyTimeoutRef.current === null) {\n return;\n }\n\n window.clearTimeout(imageOnlyStepReadyTimeoutRef.current);\n imageOnlyStepReadyTimeoutRef.current = null;\n }, []);\n\n const resetAudioSequence = useCallback(\n (\n options: {\n preservePendingSubtitleJump?: boolean;\n } = {}\n ) => {\n clearAutoAdvanceTimer();\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n clearImageOnlyStepReadyTimeout();\n setCurrentAudioKey(null);\n playbackTimeStore.reset();\n setIsAudioLoadingVisible(false);\n setAudioLoadingReason(DEFAULT_BUFFERING_REASON);\n setHasCompletedCurrentStepAudio(false);\n playedAudioKeysRef.current = new Set();\n setHasCurrentAudioPlaybackStarted(false);\n setSubtitleSeekRequest(null);\n if (!options.preservePendingSubtitleJump) {\n pendingSubtitleJumpRef.current = null;\n }\n setActiveInteractionElement(undefined);\n setIsInteractionOverlayOpen(false);\n setInteractionOverlaySubtitleOffset(0);\n },\n [\n clearAutoAdvanceTimer,\n clearImageOnlyStepReadyTimeout,\n clearInteractionAutoCloseTimer,\n clearInteractionOverlayOpenTimer,\n playbackTimeStore,\n ]\n );\n\n const requestSubtitleCueSeek = useCallback(\n (target: SlidePlayerSubtitleJumpTarget) => {\n subtitleSeekRequestIdRef.current += 1;\n setSubtitleSeekRequest({\n ...target,\n id: subtitleSeekRequestIdRef.current,\n });\n },\n []\n );\n\n const startCurrentAudioSequence = useCallback(() => {\n // Resume at the first key that has not played yet. Falling back to index 0\n // unconditionally would replay the opening segment every time late audio\n // extends the current step.\n const nextAudioKey = resolvePendingStepAudioKey(\n currentAudioSequenceKeys,\n playedAudioKeysRef.current\n );\n\n if (!nextAudioKey) {\n return false;\n }\n\n // Start the first pending audio segment for the current step immediately.\n setCurrentAudioKey(nextAudioKey);\n return true;\n }, [currentAudioSequenceKeys]);\n\n const continueAfterInteraction = useCallback(() => {\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n setIsInteractionOverlayOpen(false);\n setInteractionOverlaySubtitleOffset(0);\n\n if (startCurrentAudioSequence()) {\n return;\n }\n\n if (canGoNext) {\n goNext();\n }\n }, [\n canGoNext,\n clearInteractionAutoCloseTimer,\n clearInteractionOverlayOpenTimer,\n goNext,\n startCurrentAudioSequence,\n ]);\n\n const scheduleInteractionOverlayOpen = useCallback(\n (interactionElement?: Element) => {\n clearInteractionOverlayOpenTimer();\n\n if (!interactionElement) {\n return;\n }\n\n const openOverlay = () => {\n interactionOverlayOpenTimerRef.current = null;\n setInteractionOverlaySubtitleOffset(\n DEFAULT_INTERACTION_OVERLAY_FALLBACK_OFFSET_PX\n );\n setIsInteractionOverlayOpen(true);\n pendingInteractionOverlayStepIndexRef.current = null;\n };\n\n interactionOverlayOpenTimerRef.current = window.setTimeout(\n openOverlay,\n DEFAULT_INTERACTION_OVERLAY_OPEN_DELAY_MS\n );\n },\n [clearInteractionOverlayOpenTimer]\n );\n\n const isPlayerControlsHovered = useCallback(\n () =>\n isPointerInsidePlayerControlsRef.current ||\n Boolean(\n sectionRef.current?.querySelector(\".slide-player__controls:hover\")\n ),\n []\n );\n\n const revealPlayerControls = useCallback(\n (enableAutoHide = hasPlayerInteracted) => {\n if (!shouldMountPlayer || resolvedPlayerControlsVisibility === \"hidden\") {\n return;\n }\n\n setIsPlayerVisible(true);\n clearPlayerHideTimer();\n\n if (\n resolvedPlayerControlsVisibility === \"visible\" ||\n !enableAutoHide ||\n playerAutoHideDelay <= 0 ||\n isPlayerControlsHovered()\n ) {\n return;\n }\n\n playerHideTimerRef.current = window.setTimeout(() => {\n if (isPlayerControlsHovered()) {\n playerHideTimerRef.current = null;\n return;\n }\n\n setIsPlayerVisible(false);\n playerHideTimerRef.current = null;\n }, playerAutoHideDelay);\n },\n [\n clearPlayerHideTimer,\n hasPlayerInteracted,\n isPlayerControlsHovered,\n playerAutoHideDelay,\n resolvedPlayerControlsVisibility,\n shouldMountPlayer,\n ]\n );\n\n const hasResolvedCurrentInteraction = Boolean(\n hasResolvedInteractionElement(currentInteractionElement)\n );\n\n const shouldBlockPlaybackForInteraction =\n Boolean(currentInteractionElement) && !hasResolvedCurrentInteraction;\n\n const handlePlaybackPreferenceChange = useCallback((playing: boolean) => {\n setIsPlaybackRequested(playing);\n }, []);\n\n const syncPlaybackPreferenceBeforeNavigation = useCallback(\n (context?: SlidePlayerNavigationContext) => {\n if (context) {\n setIsPlaybackRequested(context.shouldContinuePlayback);\n }\n },\n []\n );\n\n useEffect(() => {\n // Keep silent-step autoplay aligned with the same play/pause preference as audio.\n setIsAutoAdvanceEnabled(isPlaybackRequested);\n }, [currentIndex, isPlaybackRequested, playerCustomActionPauseOnActive]);\n\n useEffect(() => {\n if (playerCustomActionPauseOnActive) {\n setPlayerCustomActionActive(false);\n }\n }, [\n currentIndex,\n playerCustomActionPauseOnActive,\n setPlayerCustomActionActive,\n ]);\n\n useEffect(() => {\n if (!hasPlayerCustomActions) {\n setIsPlayerCustomActionActive(false);\n }\n }, [hasPlayerCustomActions]);\n\n useEffect(() => {\n return () => {\n clearAutoAdvanceTimer();\n clearImageOnlyStepReadyTimeout();\n clearPlayerHideTimer();\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n };\n }, [\n clearAutoAdvanceTimer,\n clearImageOnlyStepReadyTimeout,\n clearInteractionAutoCloseTimer,\n clearInteractionOverlayOpenTimer,\n clearPlayerHideTimer,\n ]);\n\n useEffect(() => {\n if (!isImageOnlySilentStep) {\n clearImageOnlyStepReadyTimeout();\n return;\n }\n\n let cancelled = false;\n let rafId: number | null = null;\n let cleanupListeners: (() => void) | null = null;\n\n const detachListeners = () => {\n cleanupListeners?.();\n cleanupListeners = null;\n };\n\n const finishVisualReady = () => {\n if (cancelled) {\n return;\n }\n\n detachListeners();\n clearImageOnlyStepReadyTimeout();\n setReadyImageOnlyStepKey(imageOnlyStepVisualReadyKey);\n };\n\n const evaluateVisualReady = () => {\n if (cancelled) {\n return;\n }\n\n detachListeners();\n\n const activeStepContainer = stageLayerRef.current?.querySelector(\n '[data-active-step=\"true\"]'\n ) as HTMLElement | null;\n\n if (!activeStepContainer) {\n return;\n }\n\n const iframeElements = Array.from(\n activeStepContainer.querySelectorAll(\"iframe\")\n ) as HTMLIFrameElement[];\n\n if (\n iframeElements.length === 0 ||\n areImageOnlyStepIframeVisualsReady(iframeElements)\n ) {\n finishVisualReady();\n return;\n }\n\n const cleanupCallbacks: Array<() => void> = [];\n const queueRecheck = () => {\n if (cancelled) {\n return;\n }\n\n if (rafId !== null) {\n window.cancelAnimationFrame(rafId);\n }\n\n rafId = window.requestAnimationFrame(() => {\n rafId = null;\n evaluateVisualReady();\n });\n };\n const registerEvent = (\n target: EventTarget,\n eventName: string,\n listener: EventListener\n ) => {\n target.addEventListener(eventName, listener, { once: true });\n cleanupCallbacks.push(() =>\n target.removeEventListener(eventName, listener)\n );\n };\n\n iframeElements.forEach((iframeElement) => {\n const iframeDocument = iframeElement.contentDocument;\n\n if (!iframeDocument || iframeDocument.readyState !== \"complete\") {\n registerEvent(iframeElement, \"load\", queueRecheck);\n return;\n }\n\n Array.from(iframeDocument.images)\n .filter((image) => !image.complete)\n .forEach((image) => {\n registerEvent(image, \"load\", queueRecheck);\n registerEvent(image, \"error\", queueRecheck);\n });\n });\n\n cleanupListeners = () => {\n cleanupCallbacks.forEach((cleanup) => cleanup());\n };\n };\n\n rafId = window.requestAnimationFrame(() => {\n rafId = null;\n evaluateVisualReady();\n });\n\n imageOnlyStepReadyTimeoutRef.current = window.setTimeout(() => {\n finishVisualReady();\n }, DEFAULT_IMAGE_ONLY_VISUAL_READY_TIMEOUT_MS);\n\n return () => {\n cancelled = true;\n detachListeners();\n clearImageOnlyStepReadyTimeout();\n if (rafId !== null) {\n window.cancelAnimationFrame(rafId);\n }\n };\n }, [\n clearImageOnlyStepReadyTimeout,\n currentElementList,\n currentIndex,\n imageOnlyStepVisualReadyKey,\n isImageOnlySilentStep,\n ]);\n\n useEffect(() => {\n onPlayerVisibilityChange?.(playerControlsVisible);\n\n return () => {\n onPlayerVisibilityChange?.(false);\n };\n }, [onPlayerVisibilityChange, playerControlsVisible]);\n\n useEffect(() => {\n if (playerControlsVisible) {\n return;\n }\n\n isPointerInsidePlayerControlsRef.current = false;\n }, [playerControlsVisible]);\n\n useEffect(() => {\n if (isMobileDevice || mobileViewMode === DEFAULT_MOBILE_VIEW_MODE) {\n return;\n }\n\n setHasManualMobileViewMode(false);\n setMobileViewMode(DEFAULT_MOBILE_VIEW_MODE);\n }, [isMobileDevice, mobileViewMode]);\n\n useEffect(() => {\n if (!isMobileDevice) {\n setIsViewportFullscreenPreferred(false);\n return;\n }\n\n const syncViewportFullscreenPreference = () => {\n setIsViewportFullscreenPreferred(getIsFullscreenPreferredViewport());\n resetInteractionOverlayDragState();\n };\n const handleOrientationChange = () => {\n resetInteractionOverlayDragState();\n };\n\n syncViewportFullscreenPreference();\n window.addEventListener(\"orientationchange\", handleOrientationChange);\n window.screen?.orientation?.addEventListener?.(\n \"change\",\n handleOrientationChange\n );\n const unsubscribeMobileDeviceChange = subscribeMobileDeviceChange(\n syncViewportFullscreenPreference\n );\n\n return () => {\n unsubscribeMobileDeviceChange();\n window.removeEventListener(\"orientationchange\", handleOrientationChange);\n window.screen?.orientation?.removeEventListener?.(\n \"change\",\n handleOrientationChange\n );\n };\n }, [isMobileDevice, resetInteractionOverlayDragState]);\n\n useEffect(() => {\n onMobileViewModeChange?.(effectiveMobileViewMode);\n }, [effectiveMobileViewMode, onMobileViewModeChange]);\n\n useEffect(() => {\n if (\n previousEffectiveMobileViewModeRef.current !== effectiveMobileViewMode\n ) {\n resetInteractionOverlayDragState();\n }\n previousEffectiveMobileViewModeRef.current = effectiveMobileViewMode;\n }, [effectiveMobileViewMode, resetInteractionOverlayDragState]);\n\n useEffect(() => {\n onStepChange?.(currentStepElement, currentIndex);\n }, [currentIndex, currentStepElement, onStepChange]);\n\n useEffect(() => {\n const previousState = appendedMarkerAdvanceStateRef.current;\n const shouldAdvanceIntoAppendedMarker = shouldAutoAdvanceIntoAppendedMarker(\n {\n previousMarkerCount: previousState.markerCount,\n nextMarkerCount: slideElementList.length,\n previousIndex: previousState.currentIndex,\n previousCanGoNext: previousState.canGoNext,\n nextCanGoNext: canGoNext,\n currentAudioKey,\n hasCompletedCurrentStepAudio,\n hasResolvedCurrentInteraction,\n currentStepHasSpeakableElement,\n currentInteractionElement,\n isAutoAdvanceEnabled,\n shouldUseSilentStepAutoAdvanceToggle,\n }\n );\n\n appendedMarkerAdvanceStateRef.current = {\n markerCount: slideElementList.length,\n currentIndex,\n canGoNext,\n };\n\n if (!shouldAdvanceIntoAppendedMarker) {\n return;\n }\n\n goNext();\n }, [\n canGoNext,\n currentAudioKey,\n currentIndex,\n currentInteractionElement,\n currentStepHasSpeakableElement,\n goNext,\n hasCompletedCurrentStepAudio,\n hasResolvedCurrentInteraction,\n isAutoAdvanceEnabled,\n shouldUseSilentStepAutoAdvanceToggle,\n slideElementList.length,\n ]);\n\n useEffect(() => {\n if (!shouldMountPlayer || resolvedPlayerControlsVisibility === \"hidden\") {\n clearPlayerHideTimer();\n setIsPlayerVisible(false);\n return;\n }\n\n if (resolvedPlayerControlsVisibility === \"visible\") {\n clearPlayerHideTimer();\n setIsPlayerVisible(true);\n return;\n }\n\n if (!hasPlayerInteracted) {\n // Keep the initial player visible briefly, then hide it automatically.\n revealPlayerControls(true);\n }\n }, [\n clearPlayerHideTimer,\n hasPlayerInteracted,\n resolvedPlayerControlsVisibility,\n shouldMountPlayer,\n revealPlayerControls,\n ]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleSandboxInteraction = (event: MessageEvent) => {\n if (event.origin !== window.location.origin) {\n return;\n }\n\n if (!isSandboxInteractionMessage(event.data)) {\n return;\n }\n\n if (event.data.eventType !== \"click\") {\n return;\n }\n\n if (!shouldMountPlayer) {\n return;\n }\n\n // Restore player controls on explicit click/tap without waking on scroll start.\n activateKeyboardShortcutOwner();\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n };\n\n window.addEventListener(\"message\", handleSandboxInteraction);\n\n return () => {\n window.removeEventListener(\"message\", handleSandboxInteraction);\n };\n }, [activateKeyboardShortcutOwner, shouldMountPlayer, revealPlayerControls]);\n\n useWakePlayerFromIframe({\n sectionRef,\n enabled: shouldMountPlayer,\n keyboardShortcutsEnabled: enableKeyboardShortcuts,\n onKeyboardShortcut: activateKeyboardShortcutOwner,\n onWake: () => {\n activateKeyboardShortcutOwner();\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n },\n });\n\n useEffect(() => {\n if (!shouldMountPlayer) {\n resetAudioSequence();\n return;\n }\n\n // A restore request sets the target audio in an earlier effect. Without\n // this guard, the normal first-audio initializer in this same commit can\n // overwrite that target before Player receives the restore request.\n if (pendingPlaybackRestoreRef.current) {\n // Record the target context before Player finishes its restore callback.\n // The next sequence effect then sees this step as initialized instead of\n // resetting it back to the default first audio item.\n playbackResetKeyRef.current = currentPlaybackResetKey;\n return;\n }\n\n const { hasPlaybackContextChanged, shouldInitializeAudioSequence } =\n getPlaybackSequenceTransition({\n previousResetKey: playbackResetKeyRef.current,\n nextResetKey: currentPlaybackResetKey,\n currentAudioKey,\n hasCompletedCurrentStepAudio,\n });\n\n playbackResetKeyRef.current = currentPlaybackResetKey;\n\n const shouldOpenInteractionOverlayAfterAudio =\n pendingInteractionOverlayStepIndexRef.current === currentIndex &&\n Boolean(currentInteractionElement);\n const shouldPresentOverlay = shouldPresentInteractionOverlay({\n hasInteraction: Boolean(currentInteractionElement),\n shouldBlockPlaybackForInteraction,\n shouldOpenInteractionOverlayAfterAudio,\n hasPlaybackContextChanged,\n hasResolvedCurrentInteraction,\n currentStepHasSpeakableElement,\n isPlayerCustomActionActive: isPlayerCustomActionEffectivelyActive,\n });\n\n const pendingSubtitleJump = pendingSubtitleJumpRef.current;\n const shouldPreservePendingSubtitleJump =\n pendingSubtitleJump?.slideIndex === currentIndex;\n\n if (hasPlaybackContextChanged) {\n resetAudioSequence({\n preservePendingSubtitleJump: shouldPreservePendingSubtitleJump,\n });\n }\n\n if (currentElementList.length === 0 && !currentInteractionElement) {\n return;\n }\n\n if (shouldPausePlaybackForCustomAction) {\n return;\n }\n\n if (pendingSubtitleJump?.slideIndex === currentIndex) {\n if (\n !canReachSubtitleJumpTarget({\n currentIndex,\n resolvedCurrentInteractionElement: activeInteractionElement,\n slideElementList,\n targetSlideIndex: pendingSubtitleJump.slideIndex,\n })\n ) {\n // Keep the pending seek queued while the interaction overlay gates playback.\n } else {\n pendingSubtitleJumpRef.current = null;\n // The default audio-start effect still sees the pre-seek render state.\n // Skip it once so it does not replace the subtitle target audio.\n shouldSkipDefaultAudioStartForSubtitleJumpRef.current = true;\n setCurrentAudioKey(pendingSubtitleJump.audioKey);\n requestSubtitleCueSeek({\n audioIndex: pendingSubtitleJump.audioIndex,\n timeMs: pendingSubtitleJump.timeMs,\n });\n return;\n }\n }\n\n if (currentInteractionElement) {\n setActiveInteractionElement(currentInteractionElement);\n }\n\n if (shouldPresentOverlay) {\n // Delay auto-presenting the overlay so subtitles can settle above it.\n scheduleInteractionOverlayOpen(currentInteractionElement);\n return;\n }\n\n clearInteractionOverlayOpenTimer();\n pendingInteractionOverlayStepIndexRef.current = null;\n\n // A custom action may intentionally remain active without pausing ordinary\n // playback. Unresolved interactions still gate progression even while that\n // action temporarily owns the visible overlay surface.\n if (shouldBlockPlaybackForInteraction) {\n return;\n }\n\n if (!shouldInitializeAudioSequence) {\n return;\n }\n\n if (startCurrentAudioSequence()) {\n return;\n }\n\n if (currentStepHasSpeakableElement) {\n if (disableLoadingOverlay) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n setIsAudioLoadingVisible(true);\n return;\n }\n\n if (!canGoNext) {\n return;\n }\n\n if (shouldUseSilentStepAutoAdvanceToggle && !isAutoAdvanceEnabled) {\n return;\n }\n\n if (isImageOnlySilentStep && !isImageOnlyStepVisualReady) {\n return;\n }\n\n // Auto-advance silent marker-only steps so playback flow does not stall.\n autoAdvanceTimerRef.current = window.setTimeout(() => {\n autoAdvanceTimerRef.current = null;\n goNext();\n }, silentStepAutoAdvanceDelay);\n\n return () => {\n clearAutoAdvanceTimer();\n };\n }, [\n activeInteractionElement,\n canGoNext,\n clearAutoAdvanceTimer,\n currentElementList.length,\n currentIndex,\n currentInteractionElement,\n currentAudioKey,\n currentPlaybackResetKey,\n currentStepHasSpeakableElement,\n isImageOnlySilentStep,\n isImageOnlyStepVisualReady,\n silentStepAutoAdvanceDelay,\n goNext,\n hasCompletedCurrentStepAudio,\n disableLoadingOverlay,\n isAutoAdvanceEnabled,\n hasResolvedCurrentInteraction,\n isPlayerCustomActionEffectivelyActive,\n shouldBlockPlaybackForInteraction,\n clearInteractionOverlayOpenTimer,\n resetAudioSequence,\n requestSubtitleCueSeek,\n scheduleInteractionOverlayOpen,\n shouldMountPlayer,\n slideElementList,\n startCurrentAudioSequence,\n shouldPausePlaybackForCustomAction,\n shouldUseSilentStepAutoAdvanceToggle,\n ]);\n\n useEffect(() => {\n if (\n disableLoadingOverlay ||\n shouldPausePlaybackForCustomAction ||\n !currentStepHasSpeakableElement ||\n shouldBlockPlaybackForInteraction\n ) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (hasCompletedCurrentStepAudio) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (hasAvailableStepAudio) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n setAudioLoadingReason(\"waitingForAudio\");\n setIsAudioLoadingVisible(true);\n }, [\n hasAvailableStepAudio,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n disableLoadingOverlay,\n shouldPausePlaybackForCustomAction,\n shouldBlockPlaybackForInteraction,\n ]);\n\n // A step's audio can keep arriving after the last available segment finished,\n // because narration is synthesized while the lesson is still streaming. The\n // step-completed flag is otherwise only cleared when the reset key changes -\n // which tracks the step index and the interaction content, neither of which\n // moves while new audio is appended to the step the learner is already on.\n // Without this, everything synthesized after that first gap stays silent.\n useEffect(() => {\n if (!hasCompletedCurrentStepAudio) {\n return;\n }\n\n if (\n !hasUnplayedStepAudio(\n currentAudioSequenceKeys,\n playedAudioKeysRef.current\n )\n ) {\n return;\n }\n\n setHasCompletedCurrentStepAudio(false);\n }, [currentAudioSequenceKeys, hasCompletedCurrentStepAudio]);\n\n useEffect(() => {\n // A restore request may arrive after the slide itself mounts. Do not let\n // this independent default-start path select the first audio item while\n // the restore target is still being applied.\n if (pendingPlaybackRestoreRef.current) {\n return;\n }\n\n const shouldSkipDefaultAudioStart =\n shouldSkipDefaultAudioStartForSubtitleJumpRef.current;\n shouldSkipDefaultAudioStartForSubtitleJumpRef.current = false;\n\n if (\n !shouldStartDefaultAudioSequence({\n currentAudioKey,\n currentAudioSequenceLength: currentAudioSequenceKeys.length,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n shouldBlockPlaybackForInteraction,\n shouldPausePlaybackForCustomAction,\n shouldSkipDefaultAudioStart,\n })\n ) {\n return;\n }\n\n startCurrentAudioSequence();\n }, [\n currentAudioKey,\n currentAudioSequenceKeys,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n shouldPausePlaybackForCustomAction,\n shouldBlockPlaybackForInteraction,\n startCurrentAudioSequence,\n ]);\n\n useEffect(() => {\n if (!currentAudioKey || currentAudioIndex >= 0) {\n return;\n }\n\n setCurrentAudioKey(null);\n }, [currentAudioIndex, currentAudioKey]);\n\n useEffect(() => {\n if (currentAudioIndex >= 0) {\n return;\n }\n\n playbackTimeStore.reset();\n }, [currentAudioIndex, playbackTimeStore]);\n\n useEffect(() => {\n setHasCurrentAudioPlaybackStarted(false);\n }, [currentPlaybackStartedResetKey]);\n\n const {\n interactionDefaults,\n interactionDefaultSelectedValues,\n hasResolvedInteractionInput,\n isInteractionReadonly: resolvedInteractionReadonly,\n shouldAutoContinueInteraction,\n } = useMemo(\n () =>\n resolveSlideInteractionState(activeInteractionElement, {\n interactionDefaultValueOptions,\n }),\n [activeInteractionElement, interactionDefaultValueOptions]\n );\n\n const isInteractionReadonly =\n Boolean(activeInteractionElement?.readonly) || resolvedInteractionReadonly;\n const shouldShowInteractionOverlay = shouldRenderInteractionOverlay({\n hasActiveInteraction: Boolean(activeInteractionElement),\n isInteractionOverlayOpen,\n });\n\n const handleInteractionSend = useCallback(\n (content: OnSendContentParams) => {\n const submittedValues = [\n ...(content.selectedValues ?? []),\n content.inputText?.trim() ?? \"\",\n content.buttonText?.trim() ?? \"\",\n ].filter(Boolean);\n const resolvedUserInput = submittedValues.join(\", \");\n\n setActiveInteractionElement((prevElement) => {\n if (!prevElement || !resolvedUserInput) {\n return prevElement;\n }\n\n return {\n ...prevElement,\n user_input: resolvedUserInput,\n };\n });\n\n onSend?.(content, activeInteractionElement);\n continueAfterInteraction();\n },\n [activeInteractionElement, continueAfterInteraction, onSend]\n );\n\n useEffect(() => {\n // Keep the player icon in sync with the actual fullscreen owner.\n const syncFullscreenState = () => {\n setIsBrowserFullscreen(document.fullscreenElement === sectionRef.current);\n };\n\n syncFullscreenState();\n document.addEventListener(\"fullscreenchange\", syncFullscreenState);\n\n return () => {\n document.removeEventListener(\"fullscreenchange\", syncFullscreenState);\n };\n }, []);\n\n useEffect(() => {\n if (activeInteractionElement && isInteractionOverlayOpen) {\n return;\n }\n\n setHasInteractionOverlayActivity(false);\n }, [activeInteractionElement, isInteractionOverlayOpen]);\n\n useEffect(() => {\n resetInteractionOverlayDragState();\n }, [activeInteractionElement, resetInteractionOverlayDragState]);\n\n useEffect(() => {\n if (!shouldShowInteractionOverlay) {\n setInteractionOverlaySubtitleOffset(0);\n return;\n }\n\n const interactionOverlayElement = interactionOverlayRef.current;\n\n if (!interactionOverlayElement) {\n return;\n }\n\n const updateSubtitleOffset = () => {\n const overlayHeight = Math.ceil(\n interactionOverlayElement.getBoundingClientRect().height\n );\n\n setInteractionOverlaySubtitleOffset(\n overlayHeight + DEFAULT_INTERACTION_SUBTITLE_GAP_PX\n );\n };\n\n updateSubtitleOffset();\n\n if (typeof ResizeObserver === \"undefined\") {\n return;\n }\n\n const resizeObserver = new ResizeObserver(() => {\n updateSubtitleOffset();\n });\n\n resizeObserver.observe(interactionOverlayElement);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [shouldShowInteractionOverlay]);\n\n useEffect(() => {\n clearInteractionAutoCloseTimer();\n\n if (!isInteractionOverlayOpen) {\n return;\n }\n\n if (shouldAutoContinueInteraction) {\n // Auto-close passive interaction markers to keep playback moving.\n interactionAutoCloseTimerRef.current = window.setTimeout(() => {\n interactionAutoCloseTimerRef.current = null;\n\n continueAfterInteraction();\n }, DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS);\n return () => {\n clearInteractionAutoCloseTimer();\n };\n }\n\n if (hasInteractionOverlayActivity || !hasResolvedInteractionInput) {\n return;\n }\n\n // Give resolved history interactions a short revisit window before\n // playback resumes, but stop auto-closing once the learner starts editing.\n interactionAutoCloseTimerRef.current = window.setTimeout(() => {\n interactionAutoCloseTimerRef.current = null;\n\n continueAfterInteraction();\n }, DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS);\n\n return () => {\n clearInteractionAutoCloseTimer();\n };\n }, [\n clearInteractionAutoCloseTimer,\n continueAfterInteraction,\n hasInteractionOverlayActivity,\n hasResolvedInteractionInput,\n isInteractionOverlayOpen,\n shouldAutoContinueInteraction,\n ]);\n\n const renderSlideElement = (\n element?: Element,\n options: RenderSlideElementOptions = {}\n ) => {\n if (!element) {\n return null;\n }\n\n if (element.type === \"slot\") {\n return <>{element.content}</>;\n }\n\n if (element.type === \"html\") {\n return (\n <IframeSandbox\n className=\"content-render-iframe\"\n disableLoadingOverlay={disableLoadingOverlay}\n hideFullScreen\n locale={locale}\n dir={direction}\n lang={language}\n mode=\"blackboard\"\n replaceRootScreenHeightWithFull={\n options.replaceRootScreenHeightWithFull\n }\n type=\"sandbox\"\n content={element.content as string}\n enableScaling={enableIframeScaling}\n />\n );\n }\n\n return (\n <IframeSandbox\n className=\"content-render-iframe\"\n disableLoadingOverlay={disableLoadingOverlay}\n hideFullScreen\n locale={locale}\n dir={direction}\n lang={language}\n mode=\"blackboard\"\n type=\"markdown\"\n content={element.content as string}\n />\n );\n };\n\n const renderSlideElementList = (\n elementList: Element[] = [],\n isActiveStep = false\n ) => {\n if (elementList.length === 0) {\n return null;\n }\n\n const visibleElementCount = elementList.filter(\n (element) => element.is_renderable !== false\n ).length;\n const markdownScalingMode =\n isActiveStep && enableMarkdownScaling\n ? resolveMarkdownScalingMode(elementList)\n : \"disabled\";\n const lastVisibleElementIndex = elementList.reduce(\n (lastVisibleIndex, element, index) =>\n element.is_renderable !== false ? index : lastVisibleIndex,\n -1\n );\n\n return (\n <MarkdownSlideScaling\n className=\"slide-stage__content flex w-full flex-col gap-4\"\n mode={markdownScalingMode}\n >\n {elementList.map((element, index) => {\n const isPreRenderedHtml =\n element.type === \"html\" && element.is_renderable === false;\n\n return (\n <div\n key={element.sequence_number ?? `${element.type}-${index}`}\n ref={\n isActiveStep && index === lastVisibleElementIndex\n ? lastElementRef\n : null\n }\n aria-hidden={isPreRenderedHtml || undefined}\n className={cn(\n \"w-full shrink-0\",\n visibleElementCount === 1 &&\n element.is_renderable !== false &&\n \"slide-element--single\",\n isPreRenderedHtml\n ? \"pointer-events-none fixed left-[-200vw] top-0 -z-10 h-[100dvh] w-[100vw] overflow-hidden opacity-0\"\n : element.is_renderable === false && \"hidden\"\n )}\n >\n {renderSlideElement(element, {\n replaceRootScreenHeightWithFull:\n visibleElementCount === 1 &&\n element.type === \"html\" &&\n element.is_renderable !== false,\n })}\n </div>\n );\n })}\n </MarkdownSlideScaling>\n );\n };\n\n const handleFullscreen = useCallback(() => {\n const target = sectionRef.current;\n if (!target) {\n return;\n }\n\n if (document.fullscreenElement === target) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n\n target.requestFullscreen?.().catch(() => {});\n }, []);\n\n const scrollStageToBottom = useCallback(() => {\n const stageLayerElement = stageLayerRef.current;\n\n if (!stageLayerElement) {\n return;\n }\n\n // Keep the latest content visible after manual player navigation.\n stageLayerElement.scrollTo({\n top: stageLayerElement.scrollHeight,\n behavior: \"smooth\",\n });\n }, []);\n\n const canJumpToSubtitleTarget = useCallback(\n (target: SlidePlayerSubtitleJumpTarget) =>\n canReachSubtitleJumpTarget({\n currentIndex,\n resolvedCurrentInteractionElement: activeInteractionElement,\n slideElementList,\n targetSlideIndex: audioSlideIndexes[target.audioIndex],\n }),\n [\n activeInteractionElement,\n audioSlideIndexes,\n currentIndex,\n slideElementList,\n ]\n );\n\n const handleSubtitleJump = useCallback(\n (\n target: SlidePlayerSubtitleJumpTarget,\n context: SlidePlayerNavigationContext\n ) => {\n const targetAudio = audioList[target.audioIndex];\n const targetAudioKey = targetAudio?.audioKey;\n const targetSlideIndex = audioSlideIndexes[target.audioIndex];\n\n if (!targetAudioKey || targetSlideIndex == null) {\n return false;\n }\n\n if (!canJumpToSubtitleTarget(target)) {\n return false;\n }\n\n syncPlaybackPreferenceBeforeNavigation(context);\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n setHasCompletedCurrentStepAudio(false);\n setHasCurrentAudioPlaybackStarted(false);\n\n if (shouldWakePlayerControlsAfterNavigation(context)) {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }\n\n if (targetSlideIndex === currentIndex) {\n pendingSubtitleJumpRef.current = null;\n resetAudioSequence();\n setCurrentAudioKey(targetAudioKey);\n requestSubtitleCueSeek(target);\n return true;\n }\n\n shouldScrollToBottomRef.current = true;\n resetAudioSequence();\n pendingSubtitleJumpRef.current = {\n audioIndex: target.audioIndex,\n audioKey: targetAudioKey,\n slideIndex: targetSlideIndex,\n timeMs: target.timeMs,\n };\n goTo(targetSlideIndex);\n\n return true;\n },\n [\n audioList,\n audioSlideIndexes,\n canJumpToSubtitleTarget,\n currentIndex,\n goTo,\n requestSubtitleCueSeek,\n resetAudioSequence,\n revealPlayerControls,\n syncPlaybackPreferenceBeforeNavigation,\n ]\n );\n\n const handlePrev = useCallback(\n (context?: SlidePlayerNavigationContext) => {\n syncPlaybackPreferenceBeforeNavigation(context);\n shouldScrollToBottomRef.current = true;\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n if (shouldWakePlayerControlsAfterNavigation(context)) {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }\n resetAudioSequence();\n goPrev();\n },\n [\n goPrev,\n resetAudioSequence,\n revealPlayerControls,\n syncPlaybackPreferenceBeforeNavigation,\n ]\n );\n\n const handleNext = useCallback(\n (context?: SlidePlayerNavigationContext) => {\n syncPlaybackPreferenceBeforeNavigation(context);\n shouldScrollToBottomRef.current = true;\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n if (shouldWakePlayerControlsAfterNavigation(context)) {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }\n resetAudioSequence();\n goNext();\n },\n [\n goNext,\n resetAudioSequence,\n revealPlayerControls,\n syncPlaybackPreferenceBeforeNavigation,\n ]\n );\n\n const handlePlayerLoadingChange = useCallback(\n ({\n loading,\n reason,\n }: {\n loading: boolean;\n reason: SlidePlayerLoadingReason | null;\n }) => {\n if (disableLoadingOverlay) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (!currentStepHasSpeakableElement || hasCompletedCurrentStepAudio) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (loading && reason) {\n setAudioLoadingReason(reason);\n }\n setIsAudioLoadingVisible(shouldShowBufferingOverlay(reason, loading));\n },\n [\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n disableLoadingOverlay,\n ]\n );\n\n useEffect(() => {\n if (!disableLoadingOverlay) {\n return;\n }\n\n setIsAudioLoadingVisible(false);\n }, [disableLoadingOverlay]);\n\n const handlePlayerEnded = useCallback(\n (audioIndex: number) => {\n const endedAudioKey = audioList[audioIndex]?.audioKey;\n\n if (!endedAudioKey || !currentAudioKey) {\n return;\n }\n\n if (endedAudioKey !== currentAudioKey) {\n return;\n }\n\n playedAudioKeysRef.current.add(endedAudioKey);\n\n const activeSequencePosition = currentAudioSequenceKeys.findIndex(\n (audioSequenceKey) => audioSequenceKey === endedAudioKey\n );\n if (activeSequencePosition < 0) {\n setCurrentAudioKey(null);\n return;\n }\n\n const nextSequencePosition = activeSequencePosition + 1;\n const nextAudioKey = currentAudioSequenceKeys[nextSequencePosition];\n\n if (nextAudioKey) {\n setCurrentAudioKey(nextAudioKey);\n return;\n }\n\n setCurrentAudioKey(null);\n setHasCompletedCurrentStepAudio(true);\n setIsAudioLoadingVisible(false);\n\n if (canGoNext) {\n const nextStepIndex = currentIndex + 1;\n const nextStepElement = slideElementList[nextStepIndex];\n\n if (hasCurrentStepAudioUrl && nextStepElement?.type === \"interaction\") {\n pendingInteractionOverlayStepIndexRef.current = nextStepIndex;\n }\n\n goNext();\n return;\n }\n },\n [\n audioList,\n canGoNext,\n currentIndex,\n currentAudioKey,\n currentAudioSequenceKeys,\n goNext,\n hasCurrentStepAudioUrl,\n slideElementList,\n ]\n );\n\n const handlePlayerControlsPointerEnter = useCallback(() => {\n isPointerInsidePlayerControlsRef.current = true;\n clearPlayerHideTimer();\n\n if (shouldMountPlayer) {\n setIsPlayerVisible(true);\n }\n }, [clearPlayerHideTimer, shouldMountPlayer]);\n\n const handlePlayerControlsPointerLeave = useCallback(() => {\n isPointerInsidePlayerControlsRef.current = false;\n revealPlayerControls(true);\n }, [revealPlayerControls]);\n\n const stopOverlayPropagation = useCallback(\n (\n event: React.PointerEvent<HTMLElement> | React.MouseEvent<HTMLElement>\n ) => {\n event.stopPropagation();\n\n // Keep the player visible a bit longer when users interact with the overlay.\n if (playerControlsVisible) {\n revealPlayerControls(true);\n }\n },\n [playerControlsVisible, revealPlayerControls]\n );\n\n const getInteractionOverlayDragBounds = useCallback(\n (\n overlayElement: HTMLElement,\n startOffset: InteractionOverlayDragOffset\n ): InteractionOverlayDragBounds | null => {\n const viewportElement = viewportRef.current;\n\n if (!viewportElement) {\n return null;\n }\n\n const overlayRect = overlayElement.getBoundingClientRect();\n const viewportRect = viewportElement.getBoundingClientRect();\n\n return {\n minX: startOffset.x + viewportRect.left - overlayRect.left,\n maxX: startOffset.x + viewportRect.right - overlayRect.right,\n minY: startOffset.y + viewportRect.top - overlayRect.top,\n maxY: startOffset.y + viewportRect.bottom - overlayRect.bottom,\n };\n },\n []\n );\n\n useIsomorphicLayoutEffect(() => {\n const overlayElement = interactionOverlayRef.current;\n\n if (!shouldShowInteractionOverlay || !overlayElement) {\n interactionOverlayLayoutRectRef.current = null;\n return;\n }\n\n const previousRect = interactionOverlayLayoutRectRef.current;\n const currentRect = overlayElement.getBoundingClientRect();\n\n if (!previousRect || isInteractionOverlayDragging) {\n interactionOverlayLayoutRectRef.current = {\n left: currentRect.left,\n top: currentRect.top,\n };\n return;\n }\n\n const deltaX = previousRect.left - currentRect.left;\n const deltaY = previousRect.top - currentRect.top;\n\n if (\n !hasMeaningfulInteractionOverlayLayoutDelta(deltaX) &&\n !hasMeaningfulInteractionOverlayLayoutDelta(deltaY)\n ) {\n interactionOverlayLayoutRectRef.current = {\n left: currentRect.left,\n top: currentRect.top,\n };\n return;\n }\n\n const nextOffset = {\n x: interactionOverlayDragOffset.x + deltaX,\n y: interactionOverlayDragOffset.y + deltaY,\n };\n const bounds = getInteractionOverlayDragBounds(\n overlayElement,\n interactionOverlayDragOffset\n );\n const clampedOffset = normalizeInteractionOverlayDragOffset(\n bounds\n ? clampInteractionOverlayDragOffset(nextOffset, bounds)\n : nextOffset\n );\n\n interactionOverlayLayoutRectRef.current = {\n left: currentRect.left + clampedOffset.x - interactionOverlayDragOffset.x,\n top: currentRect.top + clampedOffset.y - interactionOverlayDragOffset.y,\n };\n\n if (\n !areInteractionOverlayDragOffsetsEqual(\n clampedOffset,\n interactionOverlayDragOffset\n )\n ) {\n setInteractionOverlayDragOffset((previousOffset) =>\n areInteractionOverlayDragOffsetsEqual(previousOffset, clampedOffset)\n ? previousOffset\n : clampedOffset\n );\n }\n }, [\n getInteractionOverlayDragBounds,\n interactionOverlayDragOffset,\n isInteractionOverlayDragging,\n playerLayoutReserved,\n shouldShowInteractionOverlay,\n ]);\n\n const handleInteractionOverlayPointerDown = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n stopOverlayPropagation(event);\n\n if (\n event.button !== 0 ||\n !event.currentTarget.isConnected ||\n !interactionOverlayRef.current\n ) {\n return;\n }\n\n const bounds = getInteractionOverlayDragBounds(\n interactionOverlayRef.current,\n interactionOverlayDragOffset\n );\n\n if (!bounds) {\n return;\n }\n\n event.preventDefault();\n if (event.currentTarget.hasPointerCapture?.(event.pointerId) !== true) {\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n interactionOverlayDragRef.current = {\n pointerId: event.pointerId,\n startClientX: event.clientX,\n startClientY: event.clientY,\n startOffset: interactionOverlayDragOffset,\n bounds,\n };\n setIsInteractionOverlayDragging(true);\n },\n [\n getInteractionOverlayDragBounds,\n interactionOverlayDragOffset,\n stopOverlayPropagation,\n ]\n );\n\n const handleInteractionOverlayPointerMove = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n const dragState = interactionOverlayDragRef.current;\n\n if (!dragState || dragState.pointerId !== event.pointerId) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n setInteractionOverlayDragOffset(\n clampInteractionOverlayDragOffset(\n {\n x: dragState.startOffset.x + event.clientX - dragState.startClientX,\n y: dragState.startOffset.y + event.clientY - dragState.startClientY,\n },\n dragState.bounds\n )\n );\n },\n []\n );\n\n const endInteractionOverlayDrag = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n const dragState = interactionOverlayDragRef.current;\n\n if (!dragState || dragState.pointerId !== event.pointerId) {\n return;\n }\n\n event.stopPropagation();\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n interactionOverlayDragRef.current = null;\n setIsInteractionOverlayDragging(false);\n },\n []\n );\n\n const handleSurfacePointerDown = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n activateKeyboardShortcutOwner();\n onPointerDown?.(event);\n },\n [activateKeyboardShortcutOwner, onPointerDown]\n );\n\n const handleSurfaceFocusCapture = useCallback(\n (event: React.FocusEvent<HTMLElement>) => {\n activateKeyboardShortcutOwner();\n onFocusCapture?.(event);\n },\n [activateKeyboardShortcutOwner, onFocusCapture]\n );\n\n const handleSurfaceClick = useCallback(() => {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }, [revealPlayerControls]);\n useEffect(() => {\n const prevKeys = prevRenderElementKeysRef.current;\n const hasStablePrefix =\n prevKeys.length > 0 &&\n prevKeys.length < currentRenderElementKeys.length &&\n prevKeys.every((key, index) => key === currentRenderElementKeys[index]);\n const appendedElements = hasStablePrefix\n ? currentElementList.slice(prevKeys.length)\n : [];\n const shouldAutoScrollToAppend = appendedElements.some(\n (element) => element.is_new === false\n );\n\n prevRenderElementKeysRef.current = currentRenderElementKeys;\n\n if (!shouldAutoScrollToAppend) {\n return;\n }\n\n const animationFrameId = window.requestAnimationFrame(() => {\n const stageLayerElement = stageLayerRef.current;\n const targetElement = lastElementRef.current;\n\n if (!stageLayerElement || !targetElement) {\n return;\n }\n\n const stageLayerRect = stageLayerElement.getBoundingClientRect();\n const targetRect = targetElement.getBoundingClientRect();\n const nextScrollTop =\n stageLayerElement.scrollTop + (targetRect.top - stageLayerRect.top);\n\n // Keep newly appended content visible when the current slide grows downward.\n stageLayerElement.scrollTo({\n top: Math.max(nextScrollTop, 0),\n behavior: \"smooth\",\n });\n });\n\n return () => {\n window.cancelAnimationFrame(animationFrameId);\n };\n }, [currentElementList, currentRenderElementKeys]);\n\n useEffect(() => {\n if (!shouldScrollToBottomRef.current) {\n return;\n }\n\n shouldScrollToBottomRef.current = false;\n\n if (currentElementList.length === 0) {\n return;\n }\n\n const animationFrameId = window.requestAnimationFrame(() => {\n scrollStageToBottom();\n });\n\n return () => {\n window.cancelAnimationFrame(animationFrameId);\n };\n }, [currentElementList, scrollStageToBottom]);\n\n return (\n <section\n ref={sectionRef}\n className={cn(\n \"relative h-full w-full\",\n isMobileDevice && \"slide--mobile-device\",\n isDesktopBrowserFullscreen && \"slide--browser-fullscreen\",\n isImmersiveMobileFullscreen && \"slide--mobile-landscape\",\n isNativeMobileFullscreen && \"slide--mobile-landscape-native\",\n className\n )}\n dir={direction}\n lang={language}\n onClick={handleSurfaceClick}\n onFocusCapture={handleSurfaceFocusCapture}\n onPointerDown={handleSurfacePointerDown}\n {...props}\n >\n {shouldShowMobileFullscreenMask ? (\n <div\n aria-hidden=\"true\"\n className=\"pointer-events-none fixed left-0 top-0 z-[9999] h-[100vh] max-h-[100vh] w-[100vw]\"\n />\n ) : null}\n\n <div\n ref={viewportRef}\n className={cn(\n \"slide__viewport relative h-full min-h-0 w-full\",\n isImmersiveMobileFullscreen && \"slide__viewport--mobile-landscape\",\n isImmersiveMobileFullscreen &&\n !shouldRotateFullscreenViewport &&\n \"slide__viewport--mobile-landscape-native\"\n )}\n >\n {shouldShowFullscreenHeader ? (\n <div className=\"slide-landscape-header\">\n <button\n aria-label={\n fullscreenHeader?.backAriaLabel ??\n localeTexts.fullscreenBackAriaLabel\n }\n className=\"slide-landscape-header__back\"\n onClick={handleFullscreenHeaderBack}\n type=\"button\"\n >\n <ChevronLeft\n className=\"slide-landscape-header__icon h-6 w-6\"\n strokeWidth={2.25}\n />\n </button>\n\n {fullscreenHeader?.content ? (\n <div className=\"min-w-0 flex-1 overflow-hidden\">\n {fullscreenHeader.content}\n </div>\n ) : null}\n </div>\n ) : null}\n\n <div\n className={cn(\n \"h-full min-h-0 w-full\",\n shouldApplyFullscreenViewportPadding &&\n \"slide__viewport-content--with-header\",\n isSingleSlide ? \"slide-content--single\" : \"grid gap-4\"\n )}\n >\n {currentElementList.length > 0 ? (\n <div className=\"slide-stage\">\n <div ref={stageLayerRef} className=\"slide-stage__layer w-full\">\n {mountedStepStates.map(\n (mountedStepState, mountedStepStateIndex) => {\n const isActiveStep =\n mountedStepStateIndex === currentMountedStateIndex;\n\n return (\n <div\n key={\n mountedStepState.sourceStepIndexes[0] ??\n mountedStepStateIndex\n }\n data-active-step={isActiveStep ? \"true\" : undefined}\n aria-hidden={!isActiveStep || undefined}\n className=\"w-full h-full\"\n style={{ display: isActiveStep ? undefined : \"none\" }}\n >\n {renderSlideElementList(\n mountedStepState.elementList,\n isActiveStep\n )}\n </div>\n );\n }\n )}\n </div>\n </div>\n ) : null}\n </div>\n\n {isAudioLoadingVisible ? (\n <LoadingOverlayCard\n message={resolveBufferingTextByReason(\n resolvedBufferingText,\n audioLoadingReason\n )}\n className=\"absolute left-1/2 top-1/2 z-[3] -translate-x-1/2 -translate-y-1/2\"\n />\n ) : null}\n\n <SubtitleOverlay\n extraBottomOffset={interactionOverlaySubtitleOffset}\n hasPlayerGap={playerLayoutReserved}\n isEnabled={isSubtitleEnabled && hasCurrentAudioPlaybackStarted}\n playbackTimeStore={playbackTimeStore}\n subtitleCues={currentSubtitleCues}\n />\n\n {shouldShowInteractionOverlay ? (\n <div\n ref={interactionOverlayRef}\n data-player-keyboard-shortcuts-ignore=\"true\"\n className={cn(\n \"slide-interaction-overlay\",\n playerLayoutReserved\n ? \"slide-interaction-overlay--with-player\"\n : \"slide-interaction-overlay--standalone\",\n isInteractionOverlayDragging &&\n \"slide-interaction-overlay--dragging\"\n )}\n onClick={stopOverlayPropagation}\n onPointerDownCapture={(event) => {\n if (isInteractionActivityTarget(event.target)) {\n setHasInteractionOverlayActivity(true);\n }\n }}\n onFocusCapture={(event) => {\n if (isInteractionActivityTarget(event.target)) {\n setHasInteractionOverlayActivity(true);\n }\n }}\n onInputCapture={(event) => {\n if (isInteractionActivityTarget(event.target)) {\n setHasInteractionOverlayActivity(true);\n }\n }}\n style={interactionOverlayStyle}\n >\n <InteractionOverlayCard\n dir={direction}\n lang={language}\n content={String(activeInteractionElement?.content ?? \"\")}\n dragHandleAriaLabel={\n interactionTexts?.dragHandleAriaLabel ??\n localeTexts.interactionTexts.dragHandleAriaLabel\n }\n locale={locale}\n defaultButtonText={interactionDefaults.buttonText ?? \"\"}\n defaultInputText={interactionDefaults.inputText ?? \"\"}\n defaultSelectedValues={interactionDefaultSelectedValues}\n confirmButtonText={\n interactionTexts?.confirmButtonText ??\n localeTexts.interactionTexts.confirmButtonText\n }\n copyButtonText={\n interactionTexts?.copyButtonText ??\n localeTexts.interactionTexts.copyButtonText\n }\n copiedButtonText={\n interactionTexts?.copiedButtonText ??\n localeTexts.interactionTexts.copiedButtonText\n }\n onSend={handleInteractionSend}\n onDragHandlePointerCancel={endInteractionOverlayDrag}\n onDragHandlePointerDown={handleInteractionOverlayPointerDown}\n onDragHandlePointerMove={handleInteractionOverlayPointerMove}\n onDragHandlePointerUp={endInteractionOverlayDrag}\n readonly={isInteractionReadonly}\n title={\n interactionTexts?.title ??\n interactionTitle ??\n localeTexts.interactionTexts.title\n }\n />\n </div>\n ) : null}\n\n {shouldMountPlayer ? (\n <PlayerKeyboardShortcutContext.Provider\n value={keyboardShortcutContextValue}\n >\n <Player\n dir={direction === \"auto\" ? resolvedDirection : direction}\n lang={language}\n audioList={audioList}\n className={cn(\n \"absolute left-1/2 z-[2] -translate-x-1/2\",\n isDesktopBrowserFullscreen ? \"bottom-3\" : \"-bottom-3\",\n playerClassName,\n !playerControlsVisible && \"pointer-events-none opacity-0\"\n )}\n currentAudioIndex={currentAudioIndex}\n defaultPlaying={isPlaybackRequested}\n enableKeyboardShortcuts={enableKeyboardShortcuts}\n isPlaybackPaused={shouldPausePlaybackForCustomAction}\n isAutoAdvanceEnabled={isAutoAdvanceEnabled}\n locale={locale}\n isInteractionOpen={isInteractionOverlayOpen}\n isSubtitleEnabled={isSubtitleEnabled}\n onAutoAdvanceToggle={setIsAutoAdvanceEnabled}\n onLoadingChange={handlePlayerLoadingChange}\n onPlaybackStarted={() => {\n setHasCurrentAudioPlaybackStarted(true);\n }}\n onPlaybackCheckpoint={({ audioKey, isComplete, timeMs }) => {\n const checkpointAudioIndex = audioList.findIndex(\n (audioItem) => audioItem.audioKey === audioKey\n );\n const checkpointAudioItem =\n checkpointAudioIndex >= 0\n ? audioList[checkpointAudioIndex]\n : undefined;\n\n if (\n !checkpointAudioItem?.audioKey ||\n !checkpointAudioItem.element\n ) {\n return;\n }\n\n onPlaybackCheckpoint?.({\n audioKey: checkpointAudioItem.audioKey,\n element: checkpointAudioItem.element,\n isComplete,\n stepIndex:\n audioSlideIndexes[checkpointAudioIndex] ?? currentIndex,\n timeMs,\n });\n }}\n onPlaybackPreferenceChange={handlePlaybackPreferenceChange}\n onPlaybackTimeChange={playbackTimeStore.setTime}\n onSubtitleToggle={() => {\n setIsSubtitleEnabled((previousEnabled) => !previousEnabled);\n }}\n nextDisabled={!canGoNext}\n onEnded={handlePlayerEnded}\n onFullscreen={handleFullscreen}\n isFullscreen={isBrowserFullscreen}\n mobileViewMode={effectiveMobileViewMode}\n settingsPortalContainer={viewportRef.current}\n onMobileViewModeChange={handleMobileViewModeSelect}\n onControlsPointerEnter={handlePlayerControlsPointerEnter}\n onControlsPointerLeave={handlePlayerControlsPointerLeave}\n onNext={handleNext}\n onPrev={handlePrev}\n onSubtitleJump={handleSubtitleJump}\n canJumpToSubtitleTarget={canJumpToSubtitleTarget}\n prevDisabled={!canGoPrev}\n showControls={playerControlsVisible}\n slideProgress={\n showSlideProgress\n ? {\n ariaLabel: localeTexts.slideProgressAriaLabel,\n currentIndex,\n totalSteps: generatedSlideCount,\n }\n : null\n }\n subtitleSeekRequest={subtitleSeekRequest}\n playbackRestoreRequest={\n pendingPlaybackRestore &&\n pendingPlaybackRestore.audioKey === currentAudioItem?.audioKey\n ? {\n id: pendingPlaybackRestore.id,\n timeMs: pendingPlaybackRestore.timeMs,\n }\n : null\n }\n onPlaybackRestoreComplete={(requestId) => {\n if (pendingPlaybackRestoreRef.current?.id !== requestId) {\n return;\n }\n\n pendingPlaybackRestoreRef.current = null;\n setPendingPlaybackRestore(null);\n }}\n texts={playerTexts}\n customActionContext={playerCustomActionContext}\n customActions={playerCustomActions}\n useAutoAdvanceToggle={shouldUseSilentStepAutoAdvanceToggle}\n />\n </PlayerKeyboardShortcutContext.Provider>\n ) : null}\n </div>\n </section>\n );\n};\n\nexport default Slide;\n"],"names":["DEFAULT_MARKER_AUTO_ADVANCE_DELAY_MS","DEFAULT_INTERACTION_OVERLAY_OPEN_DELAY_MS","DEFAULT_INTERACTION_OVERLAY_FALLBACK_OFFSET_PX","DEFAULT_INTERACTION_SUBTITLE_GAP_PX","DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS","DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET","INTERACTION_OVERLAY_LAYOUT_EPSILON_PX","useIsomorphicLayoutEffect","useEffect","useLayoutEffect","INTERACTION_ACTIVITY_SELECTOR","DEFAULT_BUFFERING_REASON","normalizeInteractionOverlayDragOffset","x","y","hasMeaningfulInteractionOverlayLayoutDelta","delta","areInteractionOverlayDragOffsetsEqual","first","second","resolveBufferingTextByReason","bufferingText","reason","DEFAULT_SLIDE_BUFFERING_TEXTS","mergeBufferingTextWithLocaleDefaults","localeBufferingText","shouldShowBufferingOverlay","loading","InteractionOverlayCard","memo","content","title","dragHandleAriaLabel","locale","dir","lang","defaultButtonText","defaultInputText","defaultSelectedValues","confirmButtonText","copyButtonText","copiedButtonText","onSend","onDragHandlePointerCancel","onDragHandlePointerDown","onDragHandlePointerMove","onDragHandlePointerUp","readonly","jsxs","jsx","GripHorizontal","ContentRender","areStepElementListsEqual","prevElementList","nextElementList","element","index","nextElement","isInteractionActivityTarget","target","Slide","elementList","playerEnabled","playerControlsVisibility","playerClassName","fullscreenHeader","playerCustomActions","playerCustomActionPauseOnActive","interactionTitle","interactionTexts","playerTexts","playerAutoHideDelay","markerAutoAdvanceDelay","showSlideProgress","interactionDefaultValueOptions","onPlayerVisibilityChange","onMobileViewModeChange","onStepChange","onPlaybackCheckpoint","playbackRestoreRequest","enableKeyboardShortcuts","enableIframeScaling","enableMarkdownScaling","disableLoadingOverlay","className","onPointerDown","onFocusCapture","props","direction","getMarkdownFlowDirection","language","getMarkdownFlowLanguage","localeTexts","useMemo","getSlideLocaleTexts","resolvedBufferingText","resolvedPlayerEnabled","resolvedPlayerControlsVisibility","resolveSlidePlayerVisibility","keyboardShortcutOwnerId","useId","sectionRef","useRef","resolvedDirection","useResolvedDirection","viewportRef","stageLayerRef","lastElementRef","playerHideTimerRef","isPointerInsidePlayerControlsRef","autoAdvanceTimerRef","imageOnlyStepReadyTimeoutRef","interactionAutoCloseTimerRef","interactionOverlayOpenTimerRef","interactionOverlayRef","interactionOverlayLayoutRectRef","interactionOverlayDragRef","prevRenderElementKeysRef","shouldScrollToBottomRef","pendingInteractionOverlayStepIndexRef","pendingSubtitleJumpRef","subtitleSeekRequestIdRef","playbackResetKeyRef","appendedMarkerAdvanceStateRef","shouldSkipDefaultAudioStartForSubtitleJumpRef","currentElementList","stepElementLists","slideElementList","currentIndex","audioList","audioSlideIndexes","currentAudioSequenceIndexes","currentStepHasSpeakableElement","currentInteractionElement","canGoPrev","canGoNext","goPrev","goNext","goTo","useSlide","currentStepElement","currentRenderElementKeys","generatedSlideCount","isSingleSlide","shouldMountPlayer","keyboardShortcutContextValue","activateKeyboardShortcutOwner","useCallback","activatePlayerKeyboardShortcutOwner","currentAudioSequenceKeys","audioIndex","audioKey","isPlayerVisible","setIsPlayerVisible","useState","hasPlayerInteracted","setHasPlayerInteracted","isPlaybackRequested","setIsPlaybackRequested","isAutoAdvanceEnabled","setIsAutoAdvanceEnabled","currentAudioKey","setCurrentAudioKey","pendingPlaybackRestore","setPendingPlaybackRestore","pendingPlaybackRestoreRef","lastPlaybackRestoreRequestIdRef","subtitleSeekRequest","setSubtitleSeekRequest","isAudioLoadingVisible","setIsAudioLoadingVisible","audioLoadingReason","setAudioLoadingReason","hasCompletedCurrentStepAudio","setHasCompletedCurrentStepAudio","playedAudioKeysRef","hasCurrentAudioPlaybackStarted","setHasCurrentAudioPlaybackStarted","isSubtitleEnabled","setIsSubtitleEnabled","isPlayerCustomActionActive","setIsPlayerCustomActionActive","activeInteractionElement","setActiveInteractionElement","isInteractionOverlayOpen","setIsInteractionOverlayOpen","hasInteractionOverlayActivity","setHasInteractionOverlayActivity","interactionOverlayDragOffset","setInteractionOverlayDragOffset","isInteractionOverlayDragging","setIsInteractionOverlayDragging","interactionOverlaySubtitleOffset","setInteractionOverlaySubtitleOffset","isBrowserFullscreen","setIsBrowserFullscreen","isMobileDevice","getIsMobileDevice","mobileViewMode","setMobileViewMode","DEFAULT_MOBILE_VIEW_MODE","hasManualMobileViewMode","setHasManualMobileViewMode","isViewportFullscreenPreferred","setIsViewportFullscreenPreferred","getIsFullscreenPreferredViewport","playbackTimeStore","createPlaybackTimeStore","effectiveMobileViewMode","isImmersiveMobileFullscreen","isNativeMobileFullscreen","shouldRotateFullscreenViewport","resolveMobileViewModeState","previousEffectiveMobileViewModeRef","playerControlsVisible","playerLayoutReserved","resolveSlidePlayerLayoutState","shouldShowFullscreenHeader","shouldApplyFullscreenViewportPadding","shouldShowMobileFullscreenMask","isDesktopBrowserFullscreen","handleMobileViewModeSelect","nextViewMode","handleMobileViewModeReset","handleFullscreenHeaderBack","clearInteractionAutoCloseTimer","clearInteractionOverlayOpenTimer","closeInteractionOverlayForCustomAction","setPlayerCustomActionActive","active","togglePlayerCustomActionActive","previousActive","resetInteractionOverlayDragState","previousOffset","mountedStepStates","currentMountedStateIndex","nextMountedStepStates","mountedStateIndexByStep","stepElementList","stepIndex","existingMountedStateIndex","mountedStepState","currentStepKey","currentAudioIndex","audioItem","currentAudioItem","targetAudioIndex","targetStepIndex","currentSubtitleCues","currentAudioSequenceStartKey","playerCustomActionContext","resolvePlayerCustomActionElement","playerCustomActionCount","getPlayerCustomActionCount","hasPlayerCustomActions","isPlayerCustomActionEffectivelyActive","interactionOverlayStyle","hasAvailableStepAudio","currentInteractionResetKey","currentPlaybackResetKey","currentPlaybackStartedResetKey","hasCurrentStepAudioUrl","shouldPausePlaybackForCustomAction","shouldUseSilentStepAutoAdvanceToggle","shouldUseAutoAdvanceToggle","silentStepAutoAdvanceBehavior","resolveSilentStepAutoAdvanceBehavior","silentStepAutoAdvanceDelay","isImageOnlySilentStep","imageOnlyStepVisualReadyKey","readyImageOnlyStepKey","setReadyImageOnlyStepKey","isImageOnlyStepVisualReady","clearPlayerHideTimer","clearAutoAdvanceTimer","clearImageOnlyStepReadyTimeout","resetAudioSequence","options","requestSubtitleCueSeek","startCurrentAudioSequence","nextAudioKey","resolvePendingStepAudioKey","continueAfterInteraction","scheduleInteractionOverlayOpen","interactionElement","openOverlay","isPlayerControlsHovered","revealPlayerControls","enableAutoHide","hasResolvedCurrentInteraction","hasResolvedInteractionElement","shouldBlockPlaybackForInteraction","handlePlaybackPreferenceChange","playing","syncPlaybackPreferenceBeforeNavigation","context","cancelled","rafId","cleanupListeners","detachListeners","finishVisualReady","evaluateVisualReady","activeStepContainer","iframeElements","areImageOnlyStepIframeVisualsReady","cleanupCallbacks","queueRecheck","registerEvent","eventName","listener","iframeElement","iframeDocument","image","cleanup","DEFAULT_IMAGE_ONLY_VISUAL_READY_TIMEOUT_MS","syncViewportFullscreenPreference","handleOrientationChange","unsubscribeMobileDeviceChange","subscribeMobileDeviceChange","previousState","shouldAdvanceIntoAppendedMarker","shouldAutoAdvanceIntoAppendedMarker","handleSandboxInteraction","event","isSandboxInteractionMessage","useWakePlayerFromIframe","hasPlaybackContextChanged","shouldInitializeAudioSequence","getPlaybackSequenceTransition","shouldOpenInteractionOverlayAfterAudio","shouldPresentOverlay","shouldPresentInteractionOverlay","pendingSubtitleJump","shouldPreservePendingSubtitleJump","canReachSubtitleJumpTarget","hasUnplayedStepAudio","shouldSkipDefaultAudioStart","shouldStartDefaultAudioSequence","interactionDefaults","interactionDefaultSelectedValues","hasResolvedInteractionInput","resolvedInteractionReadonly","shouldAutoContinueInteraction","resolveSlideInteractionState","isInteractionReadonly","shouldShowInteractionOverlay","shouldRenderInteractionOverlay","handleInteractionSend","resolvedUserInput","prevElement","syncFullscreenState","interactionOverlayElement","updateSubtitleOffset","overlayHeight","resizeObserver","renderSlideElement","Fragment","IframeSandbox","renderSlideElementList","isActiveStep","visibleElementCount","markdownScalingMode","resolveMarkdownScalingMode","lastVisibleElementIndex","lastVisibleIndex","MarkdownSlideScaling","isPreRenderedHtml","cn","handleFullscreen","scrollStageToBottom","stageLayerElement","canJumpToSubtitleTarget","handleSubtitleJump","targetAudioKey","targetSlideIndex","shouldWakePlayerControlsAfterNavigation","handlePrev","handleNext","handlePlayerLoadingChange","handlePlayerEnded","endedAudioKey","activeSequencePosition","audioSequenceKey","nextSequencePosition","nextStepIndex","nextStepElement","handlePlayerControlsPointerEnter","handlePlayerControlsPointerLeave","stopOverlayPropagation","getInteractionOverlayDragBounds","overlayElement","startOffset","viewportElement","overlayRect","viewportRect","previousRect","currentRect","deltaX","deltaY","nextOffset","bounds","clampedOffset","clampInteractionOverlayDragOffset","handleInteractionOverlayPointerDown","handleInteractionOverlayPointerMove","dragState","endInteractionOverlayDrag","handleSurfacePointerDown","handleSurfaceFocusCapture","handleSurfaceClick","prevKeys","shouldAutoScrollToAppend","key","animationFrameId","targetElement","stageLayerRect","targetRect","nextScrollTop","ChevronLeft","mountedStepStateIndex","LoadingOverlayCard","SubtitleOverlay","PlayerKeyboardShortcutContext","Player","isComplete","timeMs","checkpointAudioIndex","checkpointAudioItem","previousEnabled","requestId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Slide.cjs","sources":["../../../src/components/Slide/Slide.tsx"],"sourcesContent":["import React, {\n memo,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { ChevronLeft, GripHorizontal } from \"lucide-react\";\n\nimport { isSandboxInteractionMessage } from \"../../lib/sandboxInteraction\";\nimport { cn } from \"../../lib/utils\";\nimport { useResolvedDirection } from \"../../lib/useResolvedDirection\";\nimport {\n getMarkdownFlowDirection,\n getMarkdownFlowLanguage,\n type MarkdownFlowLocale,\n} from \"../../lib/locale\";\nimport LoadingOverlayCard from \"../ui/loading-overlay-card\";\nimport ContentRender from \"../ContentRender\";\nimport type { ContentRenderProps } from \"../ContentRender/ContentRender\";\nimport IframeSandbox from \"../ContentRender/IframeSandbox\";\nimport type { OnSendContentParams } from \"../types\";\nimport type { InteractionDefaultValueOptions } from \"../../lib/interaction-defaults\";\nimport {\n isLandscapeViewport as getIsFullscreenPreferredViewport,\n isMobileDevice as getIsMobileDevice,\n subscribeMobileDeviceChange,\n} from \"../../lib/mobileDevice\";\nimport Player from \"./Player\";\nimport MarkdownSlideScaling from \"./MarkdownSlideScaling\";\nimport SubtitleOverlay from \"./SubtitleOverlay\";\nimport type {\n PlayerProps,\n SlidePlayerNavigationContext,\n SlidePlayerSubtitleJumpTarget,\n SlidePlayerSubtitleSeekRequest,\n SlidePlayerTexts,\n} from \"./Player\";\nimport type { SlidePlayerLoadingReason } from \"./Player\";\nimport type { Element } from \"./types\";\nimport useSlide from \"./useSlide\";\nimport useWakePlayerFromIframe from \"./useWakePlayerFromIframe\";\nimport { PlayerKeyboardShortcutContext } from \"./utils/playerKeyboardShortcutContext\";\nimport { activatePlayerKeyboardShortcutOwner } from \"./utils/playerKeyboardShortcuts\";\nimport {\n DEFAULT_MOBILE_VIEW_MODE,\n resolveMobileViewModeState,\n type MobileViewMode,\n} from \"./utils/mobileScreenMode\";\nimport {\n clampInteractionOverlayDragOffset,\n shouldPresentInteractionOverlay,\n shouldRenderInteractionOverlay,\n type InteractionOverlayDragBounds,\n type InteractionOverlayDragOffset,\n} from \"./utils/interactionPlayback\";\nimport { resolveMarkdownScalingMode } from \"./utils/markdownScaling\";\nimport { shouldWakePlayerControlsAfterNavigation } from \"./utils/playerNavigationContext\";\nimport { shouldAutoAdvanceIntoAppendedMarker } from \"./utils/appendedMarkerAdvance\";\nimport {\n hasUnplayedStepAudio,\n resolvePendingStepAudioKey,\n} from \"./utils/stepAudioProgress\";\nimport {\n getPlaybackSequenceTransition,\n shouldStartDefaultAudioSequence,\n} from \"./utils/playbackSequence\";\nimport {\n canReachSubtitleJumpTarget,\n hasResolvedInteractionElement,\n} from \"./utils/subtitleJumpNavigation\";\nimport {\n getPlayerCustomActionCount,\n resolvePlayerCustomActionElement,\n} from \"./utils/playerCustomActions\";\nimport { createPlaybackTimeStore } from \"./utils/playbackTimeStore\";\nimport { resolveSlideInteractionState } from \"./utils/interactionResolution\";\nimport { shouldUseAutoAdvanceToggle } from \"./utils/playerToggleMode\";\nimport {\n areImageOnlyStepIframeVisualsReady,\n DEFAULT_IMAGE_ONLY_VISUAL_READY_TIMEOUT_MS,\n} from \"./utils/imageOnlyStepVisualReady\";\nimport { resolveSilentStepAutoAdvanceBehavior } from \"./utils/silentStepAutoAdvance\";\nimport {\n resolveSlidePlayerLayoutState,\n resolveSlidePlayerVisibility,\n type SlidePlayerControlsVisibility,\n} from \"./utils/playerVisibility\";\nimport {\n DEFAULT_SLIDE_BUFFERING_TEXTS,\n getSlideLocaleTexts,\n type SlideBufferingReason,\n} from \"./slideI18n\";\nimport \"./slide.css\";\nexport type {\n Element,\n ElementAudioSegment,\n ElementSubtitleCue,\n SlidePlayerCustomActionContext,\n SlidePlayerCustomActions,\n} from \"./types\";\nexport type { SlidePlayerControlsVisibility } from \"./utils/playerVisibility\";\n\nconst DEFAULT_MARKER_AUTO_ADVANCE_DELAY_MS = 2000;\nconst DEFAULT_INTERACTION_OVERLAY_OPEN_DELAY_MS = 300;\nconst DEFAULT_INTERACTION_OVERLAY_FALLBACK_OFFSET_PX = 160;\nconst DEFAULT_INTERACTION_SUBTITLE_GAP_PX = 16;\nconst DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS = 3000;\nconst DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET: InteractionOverlayDragOffset = {\n x: 0,\n y: 0,\n};\nconst INTERACTION_OVERLAY_LAYOUT_EPSILON_PX = 0.5;\ntype InteractionOverlayLayoutRect = Pick<DOMRect, \"left\" | \"top\">;\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\nconst INTERACTION_ACTIVITY_SELECTOR = [\n \"button\",\n \"input\",\n \"textarea\",\n '[contenteditable=\"\"]',\n '[contenteditable=\"true\"]',\n '[contenteditable=\"plaintext-only\"]',\n].join(\", \");\nconst DEFAULT_BUFFERING_REASON: SlideBufferingReason = \"waitingForAudio\";\n\nconst normalizeInteractionOverlayDragOffset = ({\n x,\n y,\n}: InteractionOverlayDragOffset): InteractionOverlayDragOffset => ({\n x: Number(x.toFixed(2)),\n y: Number(y.toFixed(2)),\n});\n\nconst hasMeaningfulInteractionOverlayLayoutDelta = (delta: number) =>\n Math.abs(delta) >= INTERACTION_OVERLAY_LAYOUT_EPSILON_PX;\n\nconst areInteractionOverlayDragOffsetsEqual = (\n first: InteractionOverlayDragOffset,\n second: InteractionOverlayDragOffset\n) =>\n Math.abs(first.x - second.x) < INTERACTION_OVERLAY_LAYOUT_EPSILON_PX &&\n Math.abs(first.y - second.y) < INTERACTION_OVERLAY_LAYOUT_EPSILON_PX;\n\nexport type { SlideBufferingReason } from \"./slideI18n\";\n\nexport type SlideBufferingTextConfig =\n | string\n | Partial<Record<SlideBufferingReason, string>>;\n\nconst resolveBufferingTextByReason = (\n bufferingText: SlideBufferingTextConfig,\n reason: SlideBufferingReason\n) => {\n if (typeof bufferingText === \"string\") {\n return bufferingText;\n }\n\n return (\n bufferingText[reason] ??\n bufferingText[DEFAULT_BUFFERING_REASON] ??\n DEFAULT_SLIDE_BUFFERING_TEXTS[reason]\n );\n};\n\nconst mergeBufferingTextWithLocaleDefaults = (\n bufferingText: SlideBufferingTextConfig | undefined,\n localeBufferingText: Record<string, string>\n): SlideBufferingTextConfig => {\n if (typeof bufferingText === \"string\") {\n return bufferingText;\n }\n\n return {\n ...localeBufferingText,\n ...bufferingText,\n };\n};\n\nconst shouldShowBufferingOverlay = (\n reason: SlideBufferingReason | null,\n loading: boolean\n) => {\n if (!loading) {\n return false;\n }\n\n // Keep the silent preload/loading phase invisible until audio is actually playable.\n return reason !== \"loadingAudio\";\n};\n\ntype RenderSlideElementOptions = {\n replaceRootScreenHeightWithFull?: boolean;\n};\n\ninterface InteractionOverlayCardProps {\n dir?: ContentRenderProps[\"dir\"];\n lang?: string;\n content: string;\n title: string;\n dragHandleAriaLabel: string;\n locale?: MarkdownFlowLocale;\n defaultButtonText?: string;\n defaultInputText?: string;\n defaultSelectedValues?: string[];\n confirmButtonText?: string;\n copyButtonText?: string;\n copiedButtonText?: string;\n onSend?: (content: OnSendContentParams) => void;\n onDragHandlePointerCancel?: React.PointerEventHandler<HTMLButtonElement>;\n onDragHandlePointerDown?: React.PointerEventHandler<HTMLButtonElement>;\n onDragHandlePointerMove?: React.PointerEventHandler<HTMLButtonElement>;\n onDragHandlePointerUp?: React.PointerEventHandler<HTMLButtonElement>;\n readonly?: boolean;\n}\n\nexport interface SlideInteractionTexts\n extends Pick<\n ContentRenderProps,\n \"confirmButtonText\" | \"copyButtonText\" | \"copiedButtonText\"\n > {\n title?: string;\n /** Accessible label for the interaction panel drag handle. */\n dragHandleAriaLabel?: string;\n}\n\nexport type SlideFullscreenHeader = {\n content?: React.ReactNode;\n backAriaLabel?: string;\n onBack?: () => void;\n};\n\nconst InteractionOverlayCard = memo(\n ({\n content,\n title,\n dragHandleAriaLabel,\n locale,\n dir,\n lang,\n defaultButtonText,\n defaultInputText,\n defaultSelectedValues,\n confirmButtonText,\n copyButtonText,\n copiedButtonText,\n onSend,\n onDragHandlePointerCancel,\n onDragHandlePointerDown,\n onDragHandlePointerMove,\n onDragHandlePointerUp,\n readonly = false,\n }: InteractionOverlayCardProps) => (\n <div className=\"slide-player__interaction-card\">\n <button\n type=\"button\"\n className=\"slide-player__interaction-drag-handle\"\n aria-label={dragHandleAriaLabel}\n onPointerCancel={onDragHandlePointerCancel}\n onPointerDown={onDragHandlePointerDown}\n onPointerMove={onDragHandlePointerMove}\n onPointerUp={onDragHandlePointerUp}\n >\n <span className=\"slide-player__interaction-drag-handle-icon\">\n <GripHorizontal aria-hidden=\"true\" />\n <GripHorizontal aria-hidden=\"true\" />\n <GripHorizontal aria-hidden=\"true\" />\n </span>\n </button>\n <div className=\"slide-player__interaction-header\">\n <p className=\"slide-player__interaction-title\">{title}</p>\n </div>\n <div className=\"slide-player__interaction-body\">\n <ContentRender\n content={content}\n locale={locale}\n dir={dir}\n lang={lang}\n defaultButtonText={defaultButtonText}\n defaultInputText={defaultInputText}\n defaultSelectedValues={defaultSelectedValues}\n confirmButtonText={confirmButtonText}\n copyButtonText={copyButtonText}\n copiedButtonText={copiedButtonText}\n onSend={onSend}\n readonly={readonly}\n sandboxMode=\"content\"\n />\n </div>\n </div>\n )\n);\n\nInteractionOverlayCard.displayName = \"InteractionOverlayCard\";\n\nconst areStepElementListsEqual = (\n prevElementList: Element[],\n nextElementList: Element[]\n) =>\n prevElementList.length === nextElementList.length &&\n prevElementList.every((element, index) => {\n const nextElement = nextElementList[index];\n\n return (\n element.sequence_number === nextElement?.sequence_number &&\n element.type === nextElement?.type &&\n element.content === nextElement?.content\n );\n });\n\nconst isInteractionActivityTarget = (\n target: EventTarget | null\n): target is HTMLElement =>\n target instanceof HTMLElement &&\n Boolean(target.closest(INTERACTION_ACTIVITY_SELECTOR));\nexport interface SlideProps extends React.ComponentProps<\"section\"> {\n elementList?: Element[];\n /** Locale used for built-in UI text when a more specific text prop is not provided. */\n locale?: MarkdownFlowLocale;\n /** Enables the player runtime, including audio playback and keyboard shortcuts. */\n playerEnabled?: boolean;\n /**\n * Controls whether the player controls are always visible, always hidden, or auto-hidden.\n *\n * Use `\"hidden\"` to keep audio playback and keyboard shortcuts active while\n * hiding the visual controls.\n *\n * @example\n * ```tsx\n * <Slide playerControlsVisibility=\"hidden\" enableKeyboardShortcuts />\n * ```\n */\n playerControlsVisibility?: SlidePlayerControlsVisibility;\n playerClassName?: string;\n fullscreenHeader?: SlideFullscreenHeader;\n playerCustomActions?: PlayerProps[\"customActions\"];\n playerCustomActionPauseOnActive?: boolean;\n bufferingText?: SlideBufferingTextConfig;\n interactionTitle?: string;\n interactionTexts?: SlideInteractionTexts;\n playerTexts?: SlidePlayerTexts;\n playerAutoHideDelay?: number;\n markerAutoAdvanceDelay?: number;\n /** Shows an interactive navigation timeline for generated slide steps. */\n showSlideProgress?: boolean;\n /** Fired when a generated slide is selected from the progress navigation. */\n onSlideProgressNavigate?: (\n element: Element | undefined,\n index: number\n ) => void;\n interactionDefaultValueOptions?: InteractionDefaultValueOptions;\n onSend?: (content: OnSendContentParams, element?: Element) => void;\n onPlayerVisibilityChange?: (visible: boolean) => void;\n onMobileViewModeChange?: (viewMode: MobileViewMode) => void;\n onStepChange?: (element: Element | undefined, index: number) => void;\n /** Emits a low-frequency checkpoint for the active logical audio item. */\n onPlaybackCheckpoint?: (checkpoint: SlidePlaybackCheckpoint) => void;\n /** Restores one logical audio item and continues its normal playback. */\n playbackRestoreRequest?: SlidePlaybackRestoreRequest | null;\n /**\n * Enables keyboard shortcuts for existing player actions.\n *\n * Defaults to `true`. The active slide responds after users click, touch, or\n * focus the slide/player surface; ignored targets include form controls and\n * interaction overlays.\n *\n * @example\n * ```tsx\n * <Slide elementList={slides} enableKeyboardShortcuts={false} />\n * ```\n */\n enableKeyboardShortcuts?: boolean;\n enableIframeScaling?: boolean;\n /**\n * Fits Markdown-only slides to the available presentation viewport.\n *\n * Defaults to `true`. Disable this to preserve the fixed 16px article\n * typography used by standalone ContentRender.\n */\n enableMarkdownScaling?: boolean;\n disableLoadingOverlay?: boolean;\n}\n\nexport interface SlidePlaybackCheckpoint {\n audioKey: string;\n element: Element;\n isComplete: boolean;\n stepIndex: number;\n timeMs: number;\n}\n\nexport interface SlidePlaybackRestoreRequest {\n audioKey: string;\n id: number | string;\n timeMs: number;\n}\n\nconst Slide: React.FC<SlideProps> = ({\n elementList = [],\n locale,\n playerEnabled,\n playerControlsVisibility,\n playerClassName,\n fullscreenHeader,\n playerCustomActions,\n playerCustomActionPauseOnActive = true,\n bufferingText,\n interactionTitle,\n interactionTexts,\n playerTexts,\n playerAutoHideDelay = 3000,\n markerAutoAdvanceDelay = DEFAULT_MARKER_AUTO_ADVANCE_DELAY_MS,\n showSlideProgress = false,\n onSlideProgressNavigate,\n interactionDefaultValueOptions,\n onSend,\n onPlayerVisibilityChange,\n onMobileViewModeChange,\n onStepChange,\n onPlaybackCheckpoint,\n playbackRestoreRequest = null,\n enableKeyboardShortcuts = true,\n enableIframeScaling = true,\n enableMarkdownScaling = true,\n disableLoadingOverlay = false,\n className,\n dir,\n lang,\n onPointerDown,\n onFocusCapture,\n ...props\n}) => {\n const direction = dir ?? getMarkdownFlowDirection(locale);\n const language = lang ?? getMarkdownFlowLanguage(locale);\n const localeTexts = useMemo(() => getSlideLocaleTexts(locale), [locale]);\n const resolvedBufferingText = useMemo(\n () =>\n mergeBufferingTextWithLocaleDefaults(\n bufferingText,\n localeTexts.bufferingText\n ),\n [bufferingText, localeTexts.bufferingText]\n );\n const {\n playerEnabled: resolvedPlayerEnabled,\n playerControlsVisibility: resolvedPlayerControlsVisibility,\n } = resolveSlidePlayerVisibility({\n playerEnabled,\n playerControlsVisibility,\n });\n const keyboardShortcutOwnerId = useId();\n const sectionRef = useRef<HTMLElement | null>(null);\n const { resolvedDirection } = useResolvedDirection(sectionRef, direction);\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const stageLayerRef = useRef<HTMLDivElement | null>(null);\n const lastElementRef = useRef<HTMLDivElement | null>(null);\n const playerHideTimerRef = useRef<number | null>(null);\n const isPointerInsidePlayerControlsRef = useRef(false);\n const autoAdvanceTimerRef = useRef<number | null>(null);\n const imageOnlyStepReadyTimeoutRef = useRef<number | null>(null);\n const interactionAutoCloseTimerRef = useRef<number | null>(null);\n const interactionOverlayOpenTimerRef = useRef<number | null>(null);\n const interactionOverlayRef = useRef<HTMLDivElement | null>(null);\n const interactionOverlayLayoutRectRef =\n useRef<InteractionOverlayLayoutRect | null>(null);\n const interactionOverlayDragRef = useRef<{\n pointerId: number;\n startClientX: number;\n startClientY: number;\n startOffset: InteractionOverlayDragOffset;\n bounds: InteractionOverlayDragBounds;\n } | null>(null);\n const prevRenderElementKeysRef = useRef<string[]>([]);\n const shouldScrollToBottomRef = useRef(false);\n const pendingInteractionOverlayStepIndexRef = useRef<number | null>(null);\n const pendingSubtitleJumpRef = useRef<{\n audioIndex: number;\n audioKey: string;\n slideIndex: number;\n timeMs: number;\n } | null>(null);\n const subtitleSeekRequestIdRef = useRef(0);\n const playbackResetKeyRef = useRef<string | null>(null);\n const appendedMarkerAdvanceStateRef = useRef({\n markerCount: 0,\n currentIndex: -1,\n canGoNext: false,\n });\n const shouldSkipDefaultAudioStartForSubtitleJumpRef = useRef(false);\n const {\n currentElementList,\n stepElementLists,\n slideElementList,\n currentIndex,\n audioList,\n audioSlideIndexes,\n currentAudioSequenceIndexes,\n currentStepHasSpeakableElement,\n currentInteractionElement,\n canGoPrev,\n canGoNext,\n handlePrev: goPrev,\n handleNext: goNext,\n handleGoTo: goTo,\n } = useSlide(elementList);\n const currentStepElement = useMemo(() => {\n if (currentIndex < 0) {\n return undefined;\n }\n\n return slideElementList[currentIndex];\n }, [currentIndex, slideElementList]);\n const currentRenderElementKeys = useMemo(\n () =>\n currentElementList.map(\n (element, index) =>\n `${element.sequence_number ?? `${element.type}-${index}`}:${String(element.is_new ?? \"\")}`\n ),\n [currentElementList]\n );\n const generatedSlideCount = slideElementList.length;\n const isSingleSlide = generatedSlideCount === 1;\n const shouldMountPlayer =\n resolvedPlayerEnabled &&\n (slideElementList.length > 0 ||\n audioList.length > 0 ||\n Boolean(currentInteractionElement));\n const keyboardShortcutContextValue = useMemo(\n () => ({\n enabled: enableKeyboardShortcuts,\n ownerId: keyboardShortcutOwnerId,\n }),\n [enableKeyboardShortcuts, keyboardShortcutOwnerId]\n );\n const activateKeyboardShortcutOwner = useCallback(() => {\n if (!enableKeyboardShortcuts || !shouldMountPlayer) {\n return;\n }\n\n activatePlayerKeyboardShortcutOwner(keyboardShortcutOwnerId);\n }, [enableKeyboardShortcuts, keyboardShortcutOwnerId, shouldMountPlayer]);\n const currentAudioSequenceKeys = useMemo(\n () =>\n currentAudioSequenceIndexes\n .map((audioIndex) => audioList[audioIndex]?.audioKey)\n .filter((audioKey): audioKey is string => Boolean(audioKey)),\n [audioList, currentAudioSequenceIndexes]\n );\n const [isPlayerVisible, setIsPlayerVisible] = useState(true);\n const [hasPlayerInteracted, setHasPlayerInteracted] = useState(false);\n const [isPlaybackRequested, setIsPlaybackRequested] = useState(true);\n const [isAutoAdvanceEnabled, setIsAutoAdvanceEnabled] = useState(true);\n const [currentAudioKey, setCurrentAudioKey] = useState<string | null>(null);\n const [pendingPlaybackRestore, setPendingPlaybackRestore] =\n useState<SlidePlaybackRestoreRequest | null>(null);\n const pendingPlaybackRestoreRef = useRef<SlidePlaybackRestoreRequest | null>(\n null\n );\n const lastPlaybackRestoreRequestIdRef = useRef<number | string | null>(null);\n const [subtitleSeekRequest, setSubtitleSeekRequest] =\n useState<SlidePlayerSubtitleSeekRequest | null>(null);\n const [isAudioLoadingVisible, setIsAudioLoadingVisible] = useState(false);\n const [audioLoadingReason, setAudioLoadingReason] =\n useState<SlideBufferingReason>(DEFAULT_BUFFERING_REASON);\n const [hasCompletedCurrentStepAudio, setHasCompletedCurrentStepAudio] =\n useState(false);\n // Audio keys already played within the current step. A step's audio arrives\n // progressively while content is still being generated, so \"completed\" has to\n // mean \"every key played\" rather than \"reached the end of the list once\".\n const playedAudioKeysRef = useRef<Set<string>>(new Set());\n const [hasCurrentAudioPlaybackStarted, setHasCurrentAudioPlaybackStarted] =\n useState(false);\n const [isSubtitleEnabled, setIsSubtitleEnabled] = useState(true);\n const [isPlayerCustomActionActive, setIsPlayerCustomActionActive] =\n useState(false);\n const [activeInteractionElement, setActiveInteractionElement] = useState<\n Element | undefined\n >();\n const [isInteractionOverlayOpen, setIsInteractionOverlayOpen] =\n useState(false);\n const [hasInteractionOverlayActivity, setHasInteractionOverlayActivity] =\n useState(false);\n const [interactionOverlayDragOffset, setInteractionOverlayDragOffset] =\n useState<InteractionOverlayDragOffset>(\n DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET\n );\n const [isInteractionOverlayDragging, setIsInteractionOverlayDragging] =\n useState(false);\n const [\n interactionOverlaySubtitleOffset,\n setInteractionOverlaySubtitleOffset,\n ] = useState(0);\n const [isBrowserFullscreen, setIsBrowserFullscreen] = useState(false);\n const isMobileDevice = useMemo(() => getIsMobileDevice(), []);\n const [mobileViewMode, setMobileViewMode] = useState<MobileViewMode>(\n DEFAULT_MOBILE_VIEW_MODE\n );\n const [hasManualMobileViewMode, setHasManualMobileViewMode] = useState(false);\n const [isViewportFullscreenPreferred, setIsViewportFullscreenPreferred] =\n useState(() =>\n isMobileDevice ? getIsFullscreenPreferredViewport() : false\n );\n const playbackTimeStore = useMemo(() => createPlaybackTimeStore(), []);\n const {\n effectiveMobileViewMode,\n isImmersiveMobileFullscreen,\n isNativeMobileFullscreen,\n shouldRotateFullscreenViewport,\n } = useMemo(\n () =>\n resolveMobileViewModeState({\n hasManualMobileViewMode,\n isMobileDevice,\n isViewportFullscreenPreferred,\n mobileViewMode,\n }),\n [\n hasManualMobileViewMode,\n isMobileDevice,\n isViewportFullscreenPreferred,\n mobileViewMode,\n ]\n );\n const previousEffectiveMobileViewModeRef = useRef(effectiveMobileViewMode);\n const {\n controlsVisible: playerControlsVisible,\n layoutReserved: playerLayoutReserved,\n } = resolveSlidePlayerLayoutState({\n isAutoVisible: isPlayerVisible,\n playerControlsVisibility: resolvedPlayerControlsVisibility,\n shouldMountPlayer,\n });\n const shouldShowFullscreenHeader =\n isImmersiveMobileFullscreen && playerControlsVisible;\n const shouldApplyFullscreenViewportPadding =\n isImmersiveMobileFullscreen && playerLayoutReserved;\n const shouldShowMobileFullscreenMask =\n isImmersiveMobileFullscreen || isNativeMobileFullscreen;\n const isDesktopBrowserFullscreen = isBrowserFullscreen && !isMobileDevice;\n const handleMobileViewModeSelect = useCallback(\n (nextViewMode: MobileViewMode) => {\n setHasManualMobileViewMode(true);\n setMobileViewMode(nextViewMode);\n },\n []\n );\n const handleMobileViewModeReset = useCallback(() => {\n // Clear manual override so the effective mode returns to the default non-fullscreen state.\n setHasManualMobileViewMode(false);\n setMobileViewMode(DEFAULT_MOBILE_VIEW_MODE);\n }, []);\n const handleFullscreenHeaderBack = useCallback(() => {\n handleMobileViewModeReset();\n fullscreenHeader?.onBack?.();\n }, [fullscreenHeader, handleMobileViewModeReset]);\n\n const clearInteractionAutoCloseTimer = useCallback(() => {\n if (interactionAutoCloseTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(interactionAutoCloseTimerRef.current);\n interactionAutoCloseTimerRef.current = null;\n }, []);\n\n const clearInteractionOverlayOpenTimer = useCallback(() => {\n if (interactionOverlayOpenTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(interactionOverlayOpenTimerRef.current);\n interactionOverlayOpenTimerRef.current = null;\n }, []);\n\n const closeInteractionOverlayForCustomAction = useCallback(() => {\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n setIsInteractionOverlayOpen(false);\n setInteractionOverlaySubtitleOffset(0);\n }, [clearInteractionAutoCloseTimer, clearInteractionOverlayOpenTimer]);\n\n const setPlayerCustomActionActive = useCallback(\n (active: boolean) => {\n if (active) {\n closeInteractionOverlayForCustomAction();\n }\n\n setIsPlayerCustomActionActive(active);\n },\n [closeInteractionOverlayForCustomAction]\n );\n const togglePlayerCustomActionActive = useCallback(() => {\n closeInteractionOverlayForCustomAction();\n setIsPlayerCustomActionActive((previousActive) => !previousActive);\n }, [closeInteractionOverlayForCustomAction]);\n const resetInteractionOverlayDragState = useCallback(() => {\n setInteractionOverlayDragOffset((previousOffset) =>\n previousOffset.x === DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET.x &&\n previousOffset.y === DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET.y\n ? previousOffset\n : DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET\n );\n setIsInteractionOverlayDragging(false);\n interactionOverlayDragRef.current = null;\n interactionOverlayLayoutRectRef.current = null;\n }, []);\n const { mountedStepStates, currentMountedStateIndex } = useMemo(() => {\n const nextMountedStepStates: Array<{\n elementList: Element[];\n sourceStepIndexes: number[];\n }> = [];\n const mountedStateIndexByStep = new Map<number, number>();\n\n stepElementLists.forEach((stepElementList, stepIndex) => {\n const existingMountedStateIndex = nextMountedStepStates.findIndex(\n (mountedStepState) =>\n areStepElementListsEqual(\n mountedStepState.elementList,\n stepElementList\n )\n );\n\n if (existingMountedStateIndex >= 0) {\n nextMountedStepStates[\n existingMountedStateIndex\n ]?.sourceStepIndexes.push(stepIndex);\n mountedStateIndexByStep.set(stepIndex, existingMountedStateIndex);\n return;\n }\n\n nextMountedStepStates.push({\n elementList: stepElementList,\n sourceStepIndexes: [stepIndex],\n });\n mountedStateIndexByStep.set(stepIndex, nextMountedStepStates.length - 1);\n });\n\n return {\n mountedStepStates: nextMountedStepStates,\n currentMountedStateIndex:\n currentIndex >= 0\n ? (mountedStateIndexByStep.get(currentIndex) ?? -1)\n : -1,\n };\n }, [currentIndex, stepElementLists]);\n const currentStepKey = useMemo(() => String(currentIndex), [currentIndex]);\n const currentAudioIndex = useMemo(() => {\n if (!currentAudioKey) {\n return -1;\n }\n\n return audioList.findIndex(\n (audioItem) => (audioItem.audioKey ?? \"\") === currentAudioKey\n );\n }, [audioList, currentAudioKey]);\n const currentAudioItem = useMemo(\n () => (currentAudioIndex >= 0 ? audioList[currentAudioIndex] : undefined),\n [audioList, currentAudioIndex]\n );\n\n useEffect(() => {\n if (\n !playbackRestoreRequest ||\n playbackRestoreRequest.id === lastPlaybackRestoreRequestIdRef.current\n ) {\n return;\n }\n\n const targetAudioIndex = audioList.findIndex(\n (audioItem) => audioItem.audioKey === playbackRestoreRequest.audioKey\n );\n if (targetAudioIndex < 0) {\n return;\n }\n\n const targetStepIndex = audioSlideIndexes[targetAudioIndex];\n if (targetStepIndex == null) {\n return;\n }\n\n lastPlaybackRestoreRequestIdRef.current = playbackRestoreRequest.id;\n setIsPlaybackRequested(true);\n setCurrentAudioKey(playbackRestoreRequest.audioKey);\n pendingPlaybackRestoreRef.current = playbackRestoreRequest;\n setPendingPlaybackRestore(playbackRestoreRequest);\n if (currentIndex !== targetStepIndex) {\n goTo(targetStepIndex);\n }\n }, [\n audioList,\n audioSlideIndexes,\n currentIndex,\n goTo,\n playbackRestoreRequest,\n ]);\n const currentSubtitleCues = currentAudioItem?.element?.subtitle_cues ?? [];\n const currentAudioSequenceStartKey = useMemo(\n () => currentAudioSequenceKeys[0] ?? \"none\",\n [currentAudioSequenceKeys]\n );\n const playerCustomActionContext = useMemo(\n () => ({\n currentElement: resolvePlayerCustomActionElement({\n currentAudioIndex,\n currentAudioSequenceIndexes,\n audioList,\n currentInteractionElement: activeInteractionElement,\n currentStepElement,\n }),\n currentIndex,\n currentStepElement,\n isActive: isPlayerCustomActionActive,\n setActive: setPlayerCustomActionActive,\n toggleActive: togglePlayerCustomActionActive,\n }),\n [\n activeInteractionElement,\n audioList,\n currentAudioIndex,\n currentAudioSequenceIndexes,\n currentIndex,\n currentStepElement,\n isPlayerCustomActionActive,\n setPlayerCustomActionActive,\n togglePlayerCustomActionActive,\n ]\n );\n const playerCustomActionCount = useMemo(\n () =>\n getPlayerCustomActionCount(\n playerCustomActions,\n playerCustomActionContext\n ),\n [playerCustomActionContext, playerCustomActions]\n );\n const hasPlayerCustomActions = playerCustomActionCount > 0;\n const isPlayerCustomActionEffectivelyActive =\n hasPlayerCustomActions && isPlayerCustomActionActive;\n const interactionOverlayStyle = useMemo(\n () =>\n ({\n \"--slide-player-custom-action-count\": String(playerCustomActionCount),\n \"--slide-player-mobile-control-count\": String(\n playerCustomActionCount + 4\n ),\n \"--slide-interaction-drag-x\": `${interactionOverlayDragOffset.x}px`,\n \"--slide-interaction-drag-y\": `${interactionOverlayDragOffset.y}px`,\n }) as React.CSSProperties,\n [\n interactionOverlayDragOffset.x,\n interactionOverlayDragOffset.y,\n playerCustomActionCount,\n ]\n );\n const hasAvailableStepAudio = currentAudioSequenceKeys.length > 0;\n const currentInteractionResetKey = useMemo(() => {\n if (!currentInteractionElement) {\n return \"none\";\n }\n\n return `${currentInteractionElement.sequence_number ?? \"none\"}:${String(\n currentInteractionElement.content ?? \"\"\n )}`;\n }, [currentInteractionElement]);\n const currentPlaybackResetKey = useMemo(\n () => [currentStepKey, currentInteractionResetKey].join(\"|\"),\n [currentInteractionResetKey, currentStepKey]\n );\n const currentPlaybackStartedResetKey = useMemo(\n () =>\n [\n currentPlaybackResetKey,\n currentAudioItem?.audioKey ?? \"none\",\n String(currentAudioIndex),\n ].join(\"|\"),\n [currentAudioIndex, currentAudioItem?.audioKey, currentPlaybackResetKey]\n );\n const currentStepAudioUrl = useMemo(() => {\n if (\n !currentAudioSequenceStartKey ||\n currentAudioSequenceStartKey === \"none\"\n ) {\n return \"\";\n }\n\n const currentStepAudioItem = audioList.find(\n (audioItem) => audioItem.audioKey === currentAudioSequenceStartKey\n );\n\n return currentStepAudioItem?.audioUrl?.trim() ?? \"\";\n }, [audioList, currentAudioSequenceStartKey]);\n const hasCurrentStepAudioUrl = Boolean(currentStepAudioUrl);\n const shouldPausePlaybackForCustomAction =\n playerCustomActionPauseOnActive && isPlayerCustomActionEffectivelyActive;\n const shouldUseSilentStepAutoAdvanceToggle = useMemo(\n () =>\n shouldUseAutoAdvanceToggle({\n canGoNext,\n currentAudioIndex,\n currentStepHasSpeakableElement,\n hasInteraction: Boolean(currentInteractionElement),\n }),\n [\n canGoNext,\n currentAudioIndex,\n currentInteractionElement,\n currentStepHasSpeakableElement,\n ]\n );\n const silentStepAutoAdvanceBehavior = useMemo(\n () =>\n resolveSilentStepAutoAdvanceBehavior({\n currentElementList,\n currentStepHasSpeakableElement,\n currentInteractionElement,\n markerAutoAdvanceDelay,\n }),\n [\n currentElementList,\n currentInteractionElement,\n currentStepHasSpeakableElement,\n markerAutoAdvanceDelay,\n ]\n );\n const silentStepAutoAdvanceDelay = silentStepAutoAdvanceBehavior.delayMs;\n const isImageOnlySilentStep =\n silentStepAutoAdvanceBehavior.usesImageOnlyDelay;\n const imageOnlyStepVisualReadyKey = useMemo(\n () => `${currentIndex}:${currentRenderElementKeys.join(\"|\")}`,\n [currentIndex, currentRenderElementKeys]\n );\n const [readyImageOnlyStepKey, setReadyImageOnlyStepKey] = useState<\n string | null\n >(null);\n const isImageOnlyStepVisualReady =\n !isImageOnlySilentStep ||\n readyImageOnlyStepKey === imageOnlyStepVisualReadyKey;\n\n const clearPlayerHideTimer = useCallback(() => {\n if (playerHideTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(playerHideTimerRef.current);\n playerHideTimerRef.current = null;\n }, []);\n\n const clearAutoAdvanceTimer = useCallback(() => {\n if (autoAdvanceTimerRef.current === null) {\n return;\n }\n\n window.clearTimeout(autoAdvanceTimerRef.current);\n autoAdvanceTimerRef.current = null;\n }, []);\n\n const clearImageOnlyStepReadyTimeout = useCallback(() => {\n if (imageOnlyStepReadyTimeoutRef.current === null) {\n return;\n }\n\n window.clearTimeout(imageOnlyStepReadyTimeoutRef.current);\n imageOnlyStepReadyTimeoutRef.current = null;\n }, []);\n\n const resetAudioSequence = useCallback(\n (\n options: {\n preservePendingSubtitleJump?: boolean;\n } = {}\n ) => {\n clearAutoAdvanceTimer();\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n clearImageOnlyStepReadyTimeout();\n setCurrentAudioKey(null);\n playbackTimeStore.reset();\n setIsAudioLoadingVisible(false);\n setAudioLoadingReason(DEFAULT_BUFFERING_REASON);\n setHasCompletedCurrentStepAudio(false);\n playedAudioKeysRef.current = new Set();\n setHasCurrentAudioPlaybackStarted(false);\n setSubtitleSeekRequest(null);\n if (!options.preservePendingSubtitleJump) {\n pendingSubtitleJumpRef.current = null;\n }\n setActiveInteractionElement(undefined);\n setIsInteractionOverlayOpen(false);\n setInteractionOverlaySubtitleOffset(0);\n },\n [\n clearAutoAdvanceTimer,\n clearImageOnlyStepReadyTimeout,\n clearInteractionAutoCloseTimer,\n clearInteractionOverlayOpenTimer,\n playbackTimeStore,\n ]\n );\n\n const requestSubtitleCueSeek = useCallback(\n (target: SlidePlayerSubtitleJumpTarget) => {\n subtitleSeekRequestIdRef.current += 1;\n setSubtitleSeekRequest({\n ...target,\n id: subtitleSeekRequestIdRef.current,\n });\n },\n []\n );\n\n const startCurrentAudioSequence = useCallback(() => {\n // Resume at the first key that has not played yet. Falling back to index 0\n // unconditionally would replay the opening segment every time late audio\n // extends the current step.\n const nextAudioKey = resolvePendingStepAudioKey(\n currentAudioSequenceKeys,\n playedAudioKeysRef.current\n );\n\n if (!nextAudioKey) {\n return false;\n }\n\n // Start the first pending audio segment for the current step immediately.\n setCurrentAudioKey(nextAudioKey);\n return true;\n }, [currentAudioSequenceKeys]);\n\n const continueAfterInteraction = useCallback(() => {\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n setIsInteractionOverlayOpen(false);\n setInteractionOverlaySubtitleOffset(0);\n\n if (startCurrentAudioSequence()) {\n return;\n }\n\n if (canGoNext) {\n goNext();\n }\n }, [\n canGoNext,\n clearInteractionAutoCloseTimer,\n clearInteractionOverlayOpenTimer,\n goNext,\n startCurrentAudioSequence,\n ]);\n\n const scheduleInteractionOverlayOpen = useCallback(\n (interactionElement?: Element) => {\n clearInteractionOverlayOpenTimer();\n\n if (!interactionElement) {\n return;\n }\n\n const openOverlay = () => {\n interactionOverlayOpenTimerRef.current = null;\n setInteractionOverlaySubtitleOffset(\n DEFAULT_INTERACTION_OVERLAY_FALLBACK_OFFSET_PX\n );\n setIsInteractionOverlayOpen(true);\n pendingInteractionOverlayStepIndexRef.current = null;\n };\n\n interactionOverlayOpenTimerRef.current = window.setTimeout(\n openOverlay,\n DEFAULT_INTERACTION_OVERLAY_OPEN_DELAY_MS\n );\n },\n [clearInteractionOverlayOpenTimer]\n );\n\n const isPlayerControlsHovered = useCallback(\n () =>\n isPointerInsidePlayerControlsRef.current ||\n Boolean(\n sectionRef.current?.querySelector(\".slide-player__controls:hover\")\n ),\n []\n );\n\n const revealPlayerControls = useCallback(\n (enableAutoHide = hasPlayerInteracted) => {\n if (!shouldMountPlayer || resolvedPlayerControlsVisibility === \"hidden\") {\n return;\n }\n\n setIsPlayerVisible(true);\n clearPlayerHideTimer();\n\n if (\n resolvedPlayerControlsVisibility === \"visible\" ||\n !enableAutoHide ||\n playerAutoHideDelay <= 0 ||\n isPlayerControlsHovered()\n ) {\n return;\n }\n\n playerHideTimerRef.current = window.setTimeout(() => {\n if (isPlayerControlsHovered()) {\n playerHideTimerRef.current = null;\n return;\n }\n\n setIsPlayerVisible(false);\n playerHideTimerRef.current = null;\n }, playerAutoHideDelay);\n },\n [\n clearPlayerHideTimer,\n hasPlayerInteracted,\n isPlayerControlsHovered,\n playerAutoHideDelay,\n resolvedPlayerControlsVisibility,\n shouldMountPlayer,\n ]\n );\n\n const hasResolvedCurrentInteraction = Boolean(\n hasResolvedInteractionElement(currentInteractionElement)\n );\n\n const shouldBlockPlaybackForInteraction =\n Boolean(currentInteractionElement) && !hasResolvedCurrentInteraction;\n\n const handlePlaybackPreferenceChange = useCallback((playing: boolean) => {\n setIsPlaybackRequested(playing);\n }, []);\n\n const syncPlaybackPreferenceBeforeNavigation = useCallback(\n (context?: SlidePlayerNavigationContext) => {\n if (context) {\n setIsPlaybackRequested(context.shouldContinuePlayback);\n }\n },\n []\n );\n\n useEffect(() => {\n // Keep silent-step autoplay aligned with the same play/pause preference as audio.\n setIsAutoAdvanceEnabled(isPlaybackRequested);\n }, [currentIndex, isPlaybackRequested, playerCustomActionPauseOnActive]);\n\n useEffect(() => {\n if (playerCustomActionPauseOnActive) {\n setPlayerCustomActionActive(false);\n }\n }, [\n currentIndex,\n playerCustomActionPauseOnActive,\n setPlayerCustomActionActive,\n ]);\n\n useEffect(() => {\n if (!hasPlayerCustomActions) {\n setIsPlayerCustomActionActive(false);\n }\n }, [hasPlayerCustomActions]);\n\n useEffect(() => {\n return () => {\n clearAutoAdvanceTimer();\n clearImageOnlyStepReadyTimeout();\n clearPlayerHideTimer();\n clearInteractionAutoCloseTimer();\n clearInteractionOverlayOpenTimer();\n };\n }, [\n clearAutoAdvanceTimer,\n clearImageOnlyStepReadyTimeout,\n clearInteractionAutoCloseTimer,\n clearInteractionOverlayOpenTimer,\n clearPlayerHideTimer,\n ]);\n\n useEffect(() => {\n if (!isImageOnlySilentStep) {\n clearImageOnlyStepReadyTimeout();\n return;\n }\n\n let cancelled = false;\n let rafId: number | null = null;\n let cleanupListeners: (() => void) | null = null;\n\n const detachListeners = () => {\n cleanupListeners?.();\n cleanupListeners = null;\n };\n\n const finishVisualReady = () => {\n if (cancelled) {\n return;\n }\n\n detachListeners();\n clearImageOnlyStepReadyTimeout();\n setReadyImageOnlyStepKey(imageOnlyStepVisualReadyKey);\n };\n\n const evaluateVisualReady = () => {\n if (cancelled) {\n return;\n }\n\n detachListeners();\n\n const activeStepContainer = stageLayerRef.current?.querySelector(\n '[data-active-step=\"true\"]'\n ) as HTMLElement | null;\n\n if (!activeStepContainer) {\n return;\n }\n\n const iframeElements = Array.from(\n activeStepContainer.querySelectorAll(\"iframe\")\n ) as HTMLIFrameElement[];\n\n if (\n iframeElements.length === 0 ||\n areImageOnlyStepIframeVisualsReady(iframeElements)\n ) {\n finishVisualReady();\n return;\n }\n\n const cleanupCallbacks: Array<() => void> = [];\n const queueRecheck = () => {\n if (cancelled) {\n return;\n }\n\n if (rafId !== null) {\n window.cancelAnimationFrame(rafId);\n }\n\n rafId = window.requestAnimationFrame(() => {\n rafId = null;\n evaluateVisualReady();\n });\n };\n const registerEvent = (\n target: EventTarget,\n eventName: string,\n listener: EventListener\n ) => {\n target.addEventListener(eventName, listener, { once: true });\n cleanupCallbacks.push(() =>\n target.removeEventListener(eventName, listener)\n );\n };\n\n iframeElements.forEach((iframeElement) => {\n const iframeDocument = iframeElement.contentDocument;\n\n if (!iframeDocument || iframeDocument.readyState !== \"complete\") {\n registerEvent(iframeElement, \"load\", queueRecheck);\n return;\n }\n\n Array.from(iframeDocument.images)\n .filter((image) => !image.complete)\n .forEach((image) => {\n registerEvent(image, \"load\", queueRecheck);\n registerEvent(image, \"error\", queueRecheck);\n });\n });\n\n cleanupListeners = () => {\n cleanupCallbacks.forEach((cleanup) => cleanup());\n };\n };\n\n rafId = window.requestAnimationFrame(() => {\n rafId = null;\n evaluateVisualReady();\n });\n\n imageOnlyStepReadyTimeoutRef.current = window.setTimeout(() => {\n finishVisualReady();\n }, DEFAULT_IMAGE_ONLY_VISUAL_READY_TIMEOUT_MS);\n\n return () => {\n cancelled = true;\n detachListeners();\n clearImageOnlyStepReadyTimeout();\n if (rafId !== null) {\n window.cancelAnimationFrame(rafId);\n }\n };\n }, [\n clearImageOnlyStepReadyTimeout,\n currentElementList,\n currentIndex,\n imageOnlyStepVisualReadyKey,\n isImageOnlySilentStep,\n ]);\n\n useEffect(() => {\n onPlayerVisibilityChange?.(playerControlsVisible);\n\n return () => {\n onPlayerVisibilityChange?.(false);\n };\n }, [onPlayerVisibilityChange, playerControlsVisible]);\n\n useEffect(() => {\n if (playerControlsVisible) {\n return;\n }\n\n isPointerInsidePlayerControlsRef.current = false;\n }, [playerControlsVisible]);\n\n useEffect(() => {\n if (isMobileDevice || mobileViewMode === DEFAULT_MOBILE_VIEW_MODE) {\n return;\n }\n\n setHasManualMobileViewMode(false);\n setMobileViewMode(DEFAULT_MOBILE_VIEW_MODE);\n }, [isMobileDevice, mobileViewMode]);\n\n useEffect(() => {\n if (!isMobileDevice) {\n setIsViewportFullscreenPreferred(false);\n return;\n }\n\n const syncViewportFullscreenPreference = () => {\n setIsViewportFullscreenPreferred(getIsFullscreenPreferredViewport());\n resetInteractionOverlayDragState();\n };\n const handleOrientationChange = () => {\n resetInteractionOverlayDragState();\n };\n\n syncViewportFullscreenPreference();\n window.addEventListener(\"orientationchange\", handleOrientationChange);\n window.screen?.orientation?.addEventListener?.(\n \"change\",\n handleOrientationChange\n );\n const unsubscribeMobileDeviceChange = subscribeMobileDeviceChange(\n syncViewportFullscreenPreference\n );\n\n return () => {\n unsubscribeMobileDeviceChange();\n window.removeEventListener(\"orientationchange\", handleOrientationChange);\n window.screen?.orientation?.removeEventListener?.(\n \"change\",\n handleOrientationChange\n );\n };\n }, [isMobileDevice, resetInteractionOverlayDragState]);\n\n useEffect(() => {\n onMobileViewModeChange?.(effectiveMobileViewMode);\n }, [effectiveMobileViewMode, onMobileViewModeChange]);\n\n useEffect(() => {\n if (\n previousEffectiveMobileViewModeRef.current !== effectiveMobileViewMode\n ) {\n resetInteractionOverlayDragState();\n }\n previousEffectiveMobileViewModeRef.current = effectiveMobileViewMode;\n }, [effectiveMobileViewMode, resetInteractionOverlayDragState]);\n\n useEffect(() => {\n onStepChange?.(currentStepElement, currentIndex);\n }, [currentIndex, currentStepElement, onStepChange]);\n\n useEffect(() => {\n const previousState = appendedMarkerAdvanceStateRef.current;\n const shouldAdvanceIntoAppendedMarker = shouldAutoAdvanceIntoAppendedMarker(\n {\n previousMarkerCount: previousState.markerCount,\n nextMarkerCount: slideElementList.length,\n previousIndex: previousState.currentIndex,\n previousCanGoNext: previousState.canGoNext,\n nextCanGoNext: canGoNext,\n currentAudioKey,\n hasCompletedCurrentStepAudio,\n hasResolvedCurrentInteraction,\n currentStepHasSpeakableElement,\n currentInteractionElement,\n isAutoAdvanceEnabled,\n shouldUseSilentStepAutoAdvanceToggle,\n }\n );\n\n appendedMarkerAdvanceStateRef.current = {\n markerCount: slideElementList.length,\n currentIndex,\n canGoNext,\n };\n\n if (!shouldAdvanceIntoAppendedMarker) {\n return;\n }\n\n goNext();\n }, [\n canGoNext,\n currentAudioKey,\n currentIndex,\n currentInteractionElement,\n currentStepHasSpeakableElement,\n goNext,\n hasCompletedCurrentStepAudio,\n hasResolvedCurrentInteraction,\n isAutoAdvanceEnabled,\n shouldUseSilentStepAutoAdvanceToggle,\n slideElementList.length,\n ]);\n\n useEffect(() => {\n if (!shouldMountPlayer || resolvedPlayerControlsVisibility === \"hidden\") {\n clearPlayerHideTimer();\n setIsPlayerVisible(false);\n return;\n }\n\n if (resolvedPlayerControlsVisibility === \"visible\") {\n clearPlayerHideTimer();\n setIsPlayerVisible(true);\n return;\n }\n\n if (!hasPlayerInteracted) {\n // Keep the initial player visible briefly, then hide it automatically.\n revealPlayerControls(true);\n }\n }, [\n clearPlayerHideTimer,\n hasPlayerInteracted,\n resolvedPlayerControlsVisibility,\n shouldMountPlayer,\n revealPlayerControls,\n ]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleSandboxInteraction = (event: MessageEvent) => {\n if (event.origin !== window.location.origin) {\n return;\n }\n\n if (!isSandboxInteractionMessage(event.data)) {\n return;\n }\n\n if (event.data.eventType !== \"click\") {\n return;\n }\n\n if (!shouldMountPlayer) {\n return;\n }\n\n // Restore player controls on explicit click/tap without waking on scroll start.\n activateKeyboardShortcutOwner();\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n };\n\n window.addEventListener(\"message\", handleSandboxInteraction);\n\n return () => {\n window.removeEventListener(\"message\", handleSandboxInteraction);\n };\n }, [activateKeyboardShortcutOwner, shouldMountPlayer, revealPlayerControls]);\n\n useWakePlayerFromIframe({\n sectionRef,\n enabled: shouldMountPlayer,\n keyboardShortcutsEnabled: enableKeyboardShortcuts,\n onKeyboardShortcut: activateKeyboardShortcutOwner,\n onWake: () => {\n activateKeyboardShortcutOwner();\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n },\n });\n\n useEffect(() => {\n if (!shouldMountPlayer) {\n resetAudioSequence();\n return;\n }\n\n // A restore request sets the target audio in an earlier effect. Without\n // this guard, the normal first-audio initializer in this same commit can\n // overwrite that target before Player receives the restore request.\n if (pendingPlaybackRestoreRef.current) {\n // Record the target context before Player finishes its restore callback.\n // The next sequence effect then sees this step as initialized instead of\n // resetting it back to the default first audio item.\n playbackResetKeyRef.current = currentPlaybackResetKey;\n return;\n }\n\n const { hasPlaybackContextChanged, shouldInitializeAudioSequence } =\n getPlaybackSequenceTransition({\n previousResetKey: playbackResetKeyRef.current,\n nextResetKey: currentPlaybackResetKey,\n currentAudioKey,\n hasCompletedCurrentStepAudio,\n });\n\n playbackResetKeyRef.current = currentPlaybackResetKey;\n\n const shouldOpenInteractionOverlayAfterAudio =\n pendingInteractionOverlayStepIndexRef.current === currentIndex &&\n Boolean(currentInteractionElement);\n const shouldPresentOverlay = shouldPresentInteractionOverlay({\n hasInteraction: Boolean(currentInteractionElement),\n shouldBlockPlaybackForInteraction,\n shouldOpenInteractionOverlayAfterAudio,\n hasPlaybackContextChanged,\n hasResolvedCurrentInteraction,\n currentStepHasSpeakableElement,\n isPlayerCustomActionActive: isPlayerCustomActionEffectivelyActive,\n });\n\n const pendingSubtitleJump = pendingSubtitleJumpRef.current;\n const shouldPreservePendingSubtitleJump =\n pendingSubtitleJump?.slideIndex === currentIndex;\n\n if (hasPlaybackContextChanged) {\n resetAudioSequence({\n preservePendingSubtitleJump: shouldPreservePendingSubtitleJump,\n });\n }\n\n if (currentElementList.length === 0 && !currentInteractionElement) {\n return;\n }\n\n if (shouldPausePlaybackForCustomAction) {\n return;\n }\n\n if (pendingSubtitleJump?.slideIndex === currentIndex) {\n if (\n !canReachSubtitleJumpTarget({\n currentIndex,\n resolvedCurrentInteractionElement: activeInteractionElement,\n slideElementList,\n targetSlideIndex: pendingSubtitleJump.slideIndex,\n })\n ) {\n // Keep the pending seek queued while the interaction overlay gates playback.\n } else {\n pendingSubtitleJumpRef.current = null;\n // The default audio-start effect still sees the pre-seek render state.\n // Skip it once so it does not replace the subtitle target audio.\n shouldSkipDefaultAudioStartForSubtitleJumpRef.current = true;\n setCurrentAudioKey(pendingSubtitleJump.audioKey);\n requestSubtitleCueSeek({\n audioIndex: pendingSubtitleJump.audioIndex,\n timeMs: pendingSubtitleJump.timeMs,\n });\n return;\n }\n }\n\n if (currentInteractionElement) {\n setActiveInteractionElement(currentInteractionElement);\n }\n\n if (shouldPresentOverlay) {\n // Delay auto-presenting the overlay so subtitles can settle above it.\n scheduleInteractionOverlayOpen(currentInteractionElement);\n return;\n }\n\n clearInteractionOverlayOpenTimer();\n pendingInteractionOverlayStepIndexRef.current = null;\n\n // A custom action may intentionally remain active without pausing ordinary\n // playback. Unresolved interactions still gate progression even while that\n // action temporarily owns the visible overlay surface.\n if (shouldBlockPlaybackForInteraction) {\n return;\n }\n\n if (!shouldInitializeAudioSequence) {\n return;\n }\n\n if (startCurrentAudioSequence()) {\n return;\n }\n\n if (currentStepHasSpeakableElement) {\n if (disableLoadingOverlay) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n setIsAudioLoadingVisible(true);\n return;\n }\n\n if (!canGoNext) {\n return;\n }\n\n if (shouldUseSilentStepAutoAdvanceToggle && !isAutoAdvanceEnabled) {\n return;\n }\n\n if (isImageOnlySilentStep && !isImageOnlyStepVisualReady) {\n return;\n }\n\n // Auto-advance silent marker-only steps so playback flow does not stall.\n autoAdvanceTimerRef.current = window.setTimeout(() => {\n autoAdvanceTimerRef.current = null;\n goNext();\n }, silentStepAutoAdvanceDelay);\n\n return () => {\n clearAutoAdvanceTimer();\n };\n }, [\n activeInteractionElement,\n canGoNext,\n clearAutoAdvanceTimer,\n currentElementList.length,\n currentIndex,\n currentInteractionElement,\n currentAudioKey,\n currentPlaybackResetKey,\n currentStepHasSpeakableElement,\n isImageOnlySilentStep,\n isImageOnlyStepVisualReady,\n silentStepAutoAdvanceDelay,\n goNext,\n hasCompletedCurrentStepAudio,\n disableLoadingOverlay,\n isAutoAdvanceEnabled,\n hasResolvedCurrentInteraction,\n isPlayerCustomActionEffectivelyActive,\n shouldBlockPlaybackForInteraction,\n clearInteractionOverlayOpenTimer,\n resetAudioSequence,\n requestSubtitleCueSeek,\n scheduleInteractionOverlayOpen,\n shouldMountPlayer,\n slideElementList,\n startCurrentAudioSequence,\n shouldPausePlaybackForCustomAction,\n shouldUseSilentStepAutoAdvanceToggle,\n ]);\n\n useEffect(() => {\n if (\n disableLoadingOverlay ||\n shouldPausePlaybackForCustomAction ||\n !currentStepHasSpeakableElement ||\n shouldBlockPlaybackForInteraction\n ) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (hasCompletedCurrentStepAudio) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (hasAvailableStepAudio) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n setAudioLoadingReason(\"waitingForAudio\");\n setIsAudioLoadingVisible(true);\n }, [\n hasAvailableStepAudio,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n disableLoadingOverlay,\n shouldPausePlaybackForCustomAction,\n shouldBlockPlaybackForInteraction,\n ]);\n\n // A step's audio can keep arriving after the last available segment finished,\n // because narration is synthesized while the lesson is still streaming. The\n // step-completed flag is otherwise only cleared when the reset key changes -\n // which tracks the step index and the interaction content, neither of which\n // moves while new audio is appended to the step the learner is already on.\n // Without this, everything synthesized after that first gap stays silent.\n useEffect(() => {\n if (!hasCompletedCurrentStepAudio) {\n return;\n }\n\n if (\n !hasUnplayedStepAudio(\n currentAudioSequenceKeys,\n playedAudioKeysRef.current\n )\n ) {\n return;\n }\n\n setHasCompletedCurrentStepAudio(false);\n }, [currentAudioSequenceKeys, hasCompletedCurrentStepAudio]);\n\n useEffect(() => {\n // A restore request may arrive after the slide itself mounts. Do not let\n // this independent default-start path select the first audio item while\n // the restore target is still being applied.\n if (pendingPlaybackRestoreRef.current) {\n return;\n }\n\n const shouldSkipDefaultAudioStart =\n shouldSkipDefaultAudioStartForSubtitleJumpRef.current;\n shouldSkipDefaultAudioStartForSubtitleJumpRef.current = false;\n\n if (\n !shouldStartDefaultAudioSequence({\n currentAudioKey,\n currentAudioSequenceLength: currentAudioSequenceKeys.length,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n shouldBlockPlaybackForInteraction,\n shouldPausePlaybackForCustomAction,\n shouldSkipDefaultAudioStart,\n })\n ) {\n return;\n }\n\n startCurrentAudioSequence();\n }, [\n currentAudioKey,\n currentAudioSequenceKeys,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n shouldPausePlaybackForCustomAction,\n shouldBlockPlaybackForInteraction,\n startCurrentAudioSequence,\n ]);\n\n useEffect(() => {\n if (!currentAudioKey || currentAudioIndex >= 0) {\n return;\n }\n\n setCurrentAudioKey(null);\n }, [currentAudioIndex, currentAudioKey]);\n\n useEffect(() => {\n if (currentAudioIndex >= 0) {\n return;\n }\n\n playbackTimeStore.reset();\n }, [currentAudioIndex, playbackTimeStore]);\n\n useEffect(() => {\n setHasCurrentAudioPlaybackStarted(false);\n }, [currentPlaybackStartedResetKey]);\n\n const {\n interactionDefaults,\n interactionDefaultSelectedValues,\n hasResolvedInteractionInput,\n isInteractionReadonly: resolvedInteractionReadonly,\n shouldAutoContinueInteraction,\n } = useMemo(\n () =>\n resolveSlideInteractionState(activeInteractionElement, {\n interactionDefaultValueOptions,\n }),\n [activeInteractionElement, interactionDefaultValueOptions]\n );\n\n const isInteractionReadonly =\n Boolean(activeInteractionElement?.readonly) || resolvedInteractionReadonly;\n const shouldShowInteractionOverlay = shouldRenderInteractionOverlay({\n hasActiveInteraction: Boolean(activeInteractionElement),\n isInteractionOverlayOpen,\n });\n\n const handleInteractionSend = useCallback(\n (content: OnSendContentParams) => {\n const submittedValues = [\n ...(content.selectedValues ?? []),\n content.inputText?.trim() ?? \"\",\n content.buttonText?.trim() ?? \"\",\n ].filter(Boolean);\n const resolvedUserInput = submittedValues.join(\", \");\n\n setActiveInteractionElement((prevElement) => {\n if (!prevElement || !resolvedUserInput) {\n return prevElement;\n }\n\n return {\n ...prevElement,\n user_input: resolvedUserInput,\n };\n });\n\n onSend?.(content, activeInteractionElement);\n continueAfterInteraction();\n },\n [activeInteractionElement, continueAfterInteraction, onSend]\n );\n\n useEffect(() => {\n // Keep the player icon in sync with the actual fullscreen owner.\n const syncFullscreenState = () => {\n setIsBrowserFullscreen(document.fullscreenElement === sectionRef.current);\n };\n\n syncFullscreenState();\n document.addEventListener(\"fullscreenchange\", syncFullscreenState);\n\n return () => {\n document.removeEventListener(\"fullscreenchange\", syncFullscreenState);\n };\n }, []);\n\n useEffect(() => {\n if (activeInteractionElement && isInteractionOverlayOpen) {\n return;\n }\n\n setHasInteractionOverlayActivity(false);\n }, [activeInteractionElement, isInteractionOverlayOpen]);\n\n useEffect(() => {\n resetInteractionOverlayDragState();\n }, [activeInteractionElement, resetInteractionOverlayDragState]);\n\n useEffect(() => {\n if (!shouldShowInteractionOverlay) {\n setInteractionOverlaySubtitleOffset(0);\n return;\n }\n\n const interactionOverlayElement = interactionOverlayRef.current;\n\n if (!interactionOverlayElement) {\n return;\n }\n\n const updateSubtitleOffset = () => {\n const overlayHeight = Math.ceil(\n interactionOverlayElement.getBoundingClientRect().height\n );\n\n setInteractionOverlaySubtitleOffset(\n overlayHeight + DEFAULT_INTERACTION_SUBTITLE_GAP_PX\n );\n };\n\n updateSubtitleOffset();\n\n if (typeof ResizeObserver === \"undefined\") {\n return;\n }\n\n const resizeObserver = new ResizeObserver(() => {\n updateSubtitleOffset();\n });\n\n resizeObserver.observe(interactionOverlayElement);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [shouldShowInteractionOverlay]);\n\n useEffect(() => {\n clearInteractionAutoCloseTimer();\n\n if (!isInteractionOverlayOpen) {\n return;\n }\n\n if (shouldAutoContinueInteraction) {\n // Auto-close passive interaction markers to keep playback moving.\n interactionAutoCloseTimerRef.current = window.setTimeout(() => {\n interactionAutoCloseTimerRef.current = null;\n\n continueAfterInteraction();\n }, DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS);\n return () => {\n clearInteractionAutoCloseTimer();\n };\n }\n\n if (hasInteractionOverlayActivity || !hasResolvedInteractionInput) {\n return;\n }\n\n // Give resolved history interactions a short revisit window before\n // playback resumes, but stop auto-closing once the learner starts editing.\n interactionAutoCloseTimerRef.current = window.setTimeout(() => {\n interactionAutoCloseTimerRef.current = null;\n\n continueAfterInteraction();\n }, DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS);\n\n return () => {\n clearInteractionAutoCloseTimer();\n };\n }, [\n clearInteractionAutoCloseTimer,\n continueAfterInteraction,\n hasInteractionOverlayActivity,\n hasResolvedInteractionInput,\n isInteractionOverlayOpen,\n shouldAutoContinueInteraction,\n ]);\n\n const renderSlideElement = (\n element?: Element,\n options: RenderSlideElementOptions = {}\n ) => {\n if (!element) {\n return null;\n }\n\n if (element.type === \"slot\") {\n return <>{element.content}</>;\n }\n\n if (element.type === \"html\") {\n return (\n <IframeSandbox\n className=\"content-render-iframe\"\n disableLoadingOverlay={disableLoadingOverlay}\n hideFullScreen\n locale={locale}\n dir={direction}\n lang={language}\n mode=\"blackboard\"\n replaceRootScreenHeightWithFull={\n options.replaceRootScreenHeightWithFull\n }\n type=\"sandbox\"\n content={element.content as string}\n enableScaling={enableIframeScaling}\n />\n );\n }\n\n return (\n <IframeSandbox\n className=\"content-render-iframe\"\n disableLoadingOverlay={disableLoadingOverlay}\n hideFullScreen\n locale={locale}\n dir={direction}\n lang={language}\n mode=\"blackboard\"\n type=\"markdown\"\n content={element.content as string}\n />\n );\n };\n\n const renderSlideElementList = (\n elementList: Element[] = [],\n isActiveStep = false\n ) => {\n if (elementList.length === 0) {\n return null;\n }\n\n const visibleElementCount = elementList.filter(\n (element) => element.is_renderable !== false\n ).length;\n const markdownScalingMode =\n isActiveStep && enableMarkdownScaling\n ? resolveMarkdownScalingMode(elementList)\n : \"disabled\";\n const lastVisibleElementIndex = elementList.reduce(\n (lastVisibleIndex, element, index) =>\n element.is_renderable !== false ? index : lastVisibleIndex,\n -1\n );\n\n return (\n <MarkdownSlideScaling\n className=\"slide-stage__content flex w-full flex-col gap-4\"\n mode={markdownScalingMode}\n >\n {elementList.map((element, index) => {\n const isPreRenderedHtml =\n element.type === \"html\" && element.is_renderable === false;\n\n return (\n <div\n key={element.sequence_number ?? `${element.type}-${index}`}\n ref={\n isActiveStep && index === lastVisibleElementIndex\n ? lastElementRef\n : null\n }\n aria-hidden={isPreRenderedHtml || undefined}\n className={cn(\n \"w-full shrink-0\",\n visibleElementCount === 1 &&\n element.is_renderable !== false &&\n \"slide-element--single\",\n isPreRenderedHtml\n ? \"pointer-events-none fixed left-[-200vw] top-0 -z-10 h-[100dvh] w-[100vw] overflow-hidden opacity-0\"\n : element.is_renderable === false && \"hidden\"\n )}\n >\n {renderSlideElement(element, {\n replaceRootScreenHeightWithFull:\n visibleElementCount === 1 &&\n element.type === \"html\" &&\n element.is_renderable !== false,\n })}\n </div>\n );\n })}\n </MarkdownSlideScaling>\n );\n };\n\n const handleFullscreen = useCallback(() => {\n const target = sectionRef.current;\n if (!target) {\n return;\n }\n\n if (document.fullscreenElement === target) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n\n target.requestFullscreen?.().catch(() => {});\n }, []);\n\n const scrollStageToBottom = useCallback(() => {\n const stageLayerElement = stageLayerRef.current;\n\n if (!stageLayerElement) {\n return;\n }\n\n // Keep the latest content visible after manual player navigation.\n stageLayerElement.scrollTo({\n top: stageLayerElement.scrollHeight,\n behavior: \"smooth\",\n });\n }, []);\n\n const canJumpToSubtitleTarget = useCallback(\n (target: SlidePlayerSubtitleJumpTarget) =>\n canReachSubtitleJumpTarget({\n currentIndex,\n resolvedCurrentInteractionElement: activeInteractionElement,\n slideElementList,\n targetSlideIndex: audioSlideIndexes[target.audioIndex],\n }),\n [\n activeInteractionElement,\n audioSlideIndexes,\n currentIndex,\n slideElementList,\n ]\n );\n\n const handleSubtitleJump = useCallback(\n (\n target: SlidePlayerSubtitleJumpTarget,\n context: SlidePlayerNavigationContext\n ) => {\n const targetAudio = audioList[target.audioIndex];\n const targetAudioKey = targetAudio?.audioKey;\n const targetSlideIndex = audioSlideIndexes[target.audioIndex];\n\n if (!targetAudioKey || targetSlideIndex == null) {\n return false;\n }\n\n if (!canJumpToSubtitleTarget(target)) {\n return false;\n }\n\n syncPlaybackPreferenceBeforeNavigation(context);\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n setHasCompletedCurrentStepAudio(false);\n setHasCurrentAudioPlaybackStarted(false);\n\n if (shouldWakePlayerControlsAfterNavigation(context)) {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }\n\n if (targetSlideIndex === currentIndex) {\n pendingSubtitleJumpRef.current = null;\n resetAudioSequence();\n setCurrentAudioKey(targetAudioKey);\n requestSubtitleCueSeek(target);\n return true;\n }\n\n shouldScrollToBottomRef.current = true;\n resetAudioSequence();\n pendingSubtitleJumpRef.current = {\n audioIndex: target.audioIndex,\n audioKey: targetAudioKey,\n slideIndex: targetSlideIndex,\n timeMs: target.timeMs,\n };\n goTo(targetSlideIndex);\n\n return true;\n },\n [\n audioList,\n audioSlideIndexes,\n canJumpToSubtitleTarget,\n currentIndex,\n goTo,\n requestSubtitleCueSeek,\n resetAudioSequence,\n revealPlayerControls,\n syncPlaybackPreferenceBeforeNavigation,\n ]\n );\n\n const handlePrev = useCallback(\n (context?: SlidePlayerNavigationContext) => {\n syncPlaybackPreferenceBeforeNavigation(context);\n shouldScrollToBottomRef.current = true;\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n if (shouldWakePlayerControlsAfterNavigation(context)) {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }\n resetAudioSequence();\n goPrev();\n },\n [\n goPrev,\n resetAudioSequence,\n revealPlayerControls,\n syncPlaybackPreferenceBeforeNavigation,\n ]\n );\n\n const handleNext = useCallback(\n (context?: SlidePlayerNavigationContext) => {\n syncPlaybackPreferenceBeforeNavigation(context);\n shouldScrollToBottomRef.current = true;\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n if (shouldWakePlayerControlsAfterNavigation(context)) {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }\n resetAudioSequence();\n goNext();\n },\n [\n goNext,\n resetAudioSequence,\n revealPlayerControls,\n syncPlaybackPreferenceBeforeNavigation,\n ]\n );\n\n const handleSlideProgressNavigate = useCallback(\n (targetIndex: number) => {\n if (\n targetIndex < 0 ||\n targetIndex >= slideElementList.length ||\n targetIndex === currentIndex\n ) {\n return;\n }\n\n shouldScrollToBottomRef.current = true;\n pendingInteractionOverlayStepIndexRef.current = null;\n setIsAudioLoadingVisible(false);\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n resetAudioSequence();\n goTo(targetIndex);\n onSlideProgressNavigate?.(slideElementList[targetIndex], targetIndex);\n },\n [\n currentIndex,\n goTo,\n onSlideProgressNavigate,\n resetAudioSequence,\n revealPlayerControls,\n slideElementList,\n ]\n );\n\n const handlePlayerLoadingChange = useCallback(\n ({\n loading,\n reason,\n }: {\n loading: boolean;\n reason: SlidePlayerLoadingReason | null;\n }) => {\n if (disableLoadingOverlay) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (!currentStepHasSpeakableElement || hasCompletedCurrentStepAudio) {\n setIsAudioLoadingVisible(false);\n return;\n }\n\n if (loading && reason) {\n setAudioLoadingReason(reason);\n }\n setIsAudioLoadingVisible(shouldShowBufferingOverlay(reason, loading));\n },\n [\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n disableLoadingOverlay,\n ]\n );\n\n useEffect(() => {\n if (!disableLoadingOverlay) {\n return;\n }\n\n setIsAudioLoadingVisible(false);\n }, [disableLoadingOverlay]);\n\n const handlePlayerEnded = useCallback(\n (audioIndex: number) => {\n const endedAudioKey = audioList[audioIndex]?.audioKey;\n\n if (!endedAudioKey || !currentAudioKey) {\n return;\n }\n\n if (endedAudioKey !== currentAudioKey) {\n return;\n }\n\n playedAudioKeysRef.current.add(endedAudioKey);\n\n const activeSequencePosition = currentAudioSequenceKeys.findIndex(\n (audioSequenceKey) => audioSequenceKey === endedAudioKey\n );\n if (activeSequencePosition < 0) {\n setCurrentAudioKey(null);\n return;\n }\n\n const nextSequencePosition = activeSequencePosition + 1;\n const nextAudioKey = currentAudioSequenceKeys[nextSequencePosition];\n\n if (nextAudioKey) {\n setCurrentAudioKey(nextAudioKey);\n return;\n }\n\n setCurrentAudioKey(null);\n setHasCompletedCurrentStepAudio(true);\n setIsAudioLoadingVisible(false);\n\n if (canGoNext) {\n const nextStepIndex = currentIndex + 1;\n const nextStepElement = slideElementList[nextStepIndex];\n\n if (hasCurrentStepAudioUrl && nextStepElement?.type === \"interaction\") {\n pendingInteractionOverlayStepIndexRef.current = nextStepIndex;\n }\n\n goNext();\n return;\n }\n },\n [\n audioList,\n canGoNext,\n currentIndex,\n currentAudioKey,\n currentAudioSequenceKeys,\n goNext,\n hasCurrentStepAudioUrl,\n slideElementList,\n ]\n );\n\n const handlePlayerControlsPointerEnter = useCallback(() => {\n isPointerInsidePlayerControlsRef.current = true;\n clearPlayerHideTimer();\n\n if (shouldMountPlayer) {\n setIsPlayerVisible(true);\n }\n }, [clearPlayerHideTimer, shouldMountPlayer]);\n\n const handlePlayerControlsPointerLeave = useCallback(() => {\n isPointerInsidePlayerControlsRef.current = false;\n revealPlayerControls(true);\n }, [revealPlayerControls]);\n\n const stopOverlayPropagation = useCallback(\n (\n event: React.PointerEvent<HTMLElement> | React.MouseEvent<HTMLElement>\n ) => {\n event.stopPropagation();\n\n // Keep the player visible a bit longer when users interact with the overlay.\n if (playerControlsVisible) {\n revealPlayerControls(true);\n }\n },\n [playerControlsVisible, revealPlayerControls]\n );\n\n const getInteractionOverlayDragBounds = useCallback(\n (\n overlayElement: HTMLElement,\n startOffset: InteractionOverlayDragOffset\n ): InteractionOverlayDragBounds | null => {\n const viewportElement = viewportRef.current;\n\n if (!viewportElement) {\n return null;\n }\n\n const overlayRect = overlayElement.getBoundingClientRect();\n const viewportRect = viewportElement.getBoundingClientRect();\n\n return {\n minX: startOffset.x + viewportRect.left - overlayRect.left,\n maxX: startOffset.x + viewportRect.right - overlayRect.right,\n minY: startOffset.y + viewportRect.top - overlayRect.top,\n maxY: startOffset.y + viewportRect.bottom - overlayRect.bottom,\n };\n },\n []\n );\n\n useIsomorphicLayoutEffect(() => {\n const overlayElement = interactionOverlayRef.current;\n\n if (!shouldShowInteractionOverlay || !overlayElement) {\n interactionOverlayLayoutRectRef.current = null;\n return;\n }\n\n const previousRect = interactionOverlayLayoutRectRef.current;\n const currentRect = overlayElement.getBoundingClientRect();\n\n if (!previousRect || isInteractionOverlayDragging) {\n interactionOverlayLayoutRectRef.current = {\n left: currentRect.left,\n top: currentRect.top,\n };\n return;\n }\n\n const deltaX = previousRect.left - currentRect.left;\n const deltaY = previousRect.top - currentRect.top;\n\n if (\n !hasMeaningfulInteractionOverlayLayoutDelta(deltaX) &&\n !hasMeaningfulInteractionOverlayLayoutDelta(deltaY)\n ) {\n interactionOverlayLayoutRectRef.current = {\n left: currentRect.left,\n top: currentRect.top,\n };\n return;\n }\n\n const nextOffset = {\n x: interactionOverlayDragOffset.x + deltaX,\n y: interactionOverlayDragOffset.y + deltaY,\n };\n const bounds = getInteractionOverlayDragBounds(\n overlayElement,\n interactionOverlayDragOffset\n );\n const clampedOffset = normalizeInteractionOverlayDragOffset(\n bounds\n ? clampInteractionOverlayDragOffset(nextOffset, bounds)\n : nextOffset\n );\n\n interactionOverlayLayoutRectRef.current = {\n left: currentRect.left + clampedOffset.x - interactionOverlayDragOffset.x,\n top: currentRect.top + clampedOffset.y - interactionOverlayDragOffset.y,\n };\n\n if (\n !areInteractionOverlayDragOffsetsEqual(\n clampedOffset,\n interactionOverlayDragOffset\n )\n ) {\n setInteractionOverlayDragOffset((previousOffset) =>\n areInteractionOverlayDragOffsetsEqual(previousOffset, clampedOffset)\n ? previousOffset\n : clampedOffset\n );\n }\n }, [\n getInteractionOverlayDragBounds,\n interactionOverlayDragOffset,\n isInteractionOverlayDragging,\n playerLayoutReserved,\n shouldShowInteractionOverlay,\n ]);\n\n const handleInteractionOverlayPointerDown = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n stopOverlayPropagation(event);\n\n if (\n event.button !== 0 ||\n !event.currentTarget.isConnected ||\n !interactionOverlayRef.current\n ) {\n return;\n }\n\n const bounds = getInteractionOverlayDragBounds(\n interactionOverlayRef.current,\n interactionOverlayDragOffset\n );\n\n if (!bounds) {\n return;\n }\n\n event.preventDefault();\n if (event.currentTarget.hasPointerCapture?.(event.pointerId) !== true) {\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n interactionOverlayDragRef.current = {\n pointerId: event.pointerId,\n startClientX: event.clientX,\n startClientY: event.clientY,\n startOffset: interactionOverlayDragOffset,\n bounds,\n };\n setIsInteractionOverlayDragging(true);\n },\n [\n getInteractionOverlayDragBounds,\n interactionOverlayDragOffset,\n stopOverlayPropagation,\n ]\n );\n\n const handleInteractionOverlayPointerMove = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n const dragState = interactionOverlayDragRef.current;\n\n if (!dragState || dragState.pointerId !== event.pointerId) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n setInteractionOverlayDragOffset(\n clampInteractionOverlayDragOffset(\n {\n x: dragState.startOffset.x + event.clientX - dragState.startClientX,\n y: dragState.startOffset.y + event.clientY - dragState.startClientY,\n },\n dragState.bounds\n )\n );\n },\n []\n );\n\n const endInteractionOverlayDrag = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n const dragState = interactionOverlayDragRef.current;\n\n if (!dragState || dragState.pointerId !== event.pointerId) {\n return;\n }\n\n event.stopPropagation();\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n interactionOverlayDragRef.current = null;\n setIsInteractionOverlayDragging(false);\n },\n []\n );\n\n const handleSurfacePointerDown = useCallback(\n (event: React.PointerEvent<HTMLElement>) => {\n activateKeyboardShortcutOwner();\n onPointerDown?.(event);\n },\n [activateKeyboardShortcutOwner, onPointerDown]\n );\n\n const handleSurfaceFocusCapture = useCallback(\n (event: React.FocusEvent<HTMLElement>) => {\n activateKeyboardShortcutOwner();\n onFocusCapture?.(event);\n },\n [activateKeyboardShortcutOwner, onFocusCapture]\n );\n\n const handleSurfaceClick = useCallback(() => {\n setHasPlayerInteracted(true);\n revealPlayerControls(true);\n }, [revealPlayerControls]);\n useEffect(() => {\n const prevKeys = prevRenderElementKeysRef.current;\n const hasStablePrefix =\n prevKeys.length > 0 &&\n prevKeys.length < currentRenderElementKeys.length &&\n prevKeys.every((key, index) => key === currentRenderElementKeys[index]);\n const appendedElements = hasStablePrefix\n ? currentElementList.slice(prevKeys.length)\n : [];\n const shouldAutoScrollToAppend = appendedElements.some(\n (element) => element.is_new === false\n );\n\n prevRenderElementKeysRef.current = currentRenderElementKeys;\n\n if (!shouldAutoScrollToAppend) {\n return;\n }\n\n const animationFrameId = window.requestAnimationFrame(() => {\n const stageLayerElement = stageLayerRef.current;\n const targetElement = lastElementRef.current;\n\n if (!stageLayerElement || !targetElement) {\n return;\n }\n\n const stageLayerRect = stageLayerElement.getBoundingClientRect();\n const targetRect = targetElement.getBoundingClientRect();\n const nextScrollTop =\n stageLayerElement.scrollTop + (targetRect.top - stageLayerRect.top);\n\n // Keep newly appended content visible when the current slide grows downward.\n stageLayerElement.scrollTo({\n top: Math.max(nextScrollTop, 0),\n behavior: \"smooth\",\n });\n });\n\n return () => {\n window.cancelAnimationFrame(animationFrameId);\n };\n }, [currentElementList, currentRenderElementKeys]);\n\n useEffect(() => {\n if (!shouldScrollToBottomRef.current) {\n return;\n }\n\n shouldScrollToBottomRef.current = false;\n\n if (currentElementList.length === 0) {\n return;\n }\n\n const animationFrameId = window.requestAnimationFrame(() => {\n scrollStageToBottom();\n });\n\n return () => {\n window.cancelAnimationFrame(animationFrameId);\n };\n }, [currentElementList, scrollStageToBottom]);\n\n return (\n <section\n ref={sectionRef}\n className={cn(\n \"relative h-full w-full\",\n isMobileDevice && \"slide--mobile-device\",\n isDesktopBrowserFullscreen && \"slide--browser-fullscreen\",\n isImmersiveMobileFullscreen && \"slide--mobile-landscape\",\n isNativeMobileFullscreen && \"slide--mobile-landscape-native\",\n className\n )}\n dir={direction}\n lang={language}\n onClick={handleSurfaceClick}\n onFocusCapture={handleSurfaceFocusCapture}\n onPointerDown={handleSurfacePointerDown}\n {...props}\n >\n {shouldShowMobileFullscreenMask ? (\n <div\n aria-hidden=\"true\"\n className=\"pointer-events-none fixed left-0 top-0 z-[9999] h-[100vh] max-h-[100vh] w-[100vw]\"\n />\n ) : null}\n\n <div\n ref={viewportRef}\n className={cn(\n \"slide__viewport relative h-full min-h-0 w-full\",\n isImmersiveMobileFullscreen && \"slide__viewport--mobile-landscape\",\n isImmersiveMobileFullscreen &&\n !shouldRotateFullscreenViewport &&\n \"slide__viewport--mobile-landscape-native\"\n )}\n >\n {shouldShowFullscreenHeader ? (\n <div className=\"slide-landscape-header\">\n <button\n aria-label={\n fullscreenHeader?.backAriaLabel ??\n localeTexts.fullscreenBackAriaLabel\n }\n className=\"slide-landscape-header__back\"\n onClick={handleFullscreenHeaderBack}\n type=\"button\"\n >\n <ChevronLeft\n className=\"slide-landscape-header__icon h-6 w-6\"\n strokeWidth={2.25}\n />\n </button>\n\n {fullscreenHeader?.content ? (\n <div className=\"min-w-0 flex-1 overflow-hidden\">\n {fullscreenHeader.content}\n </div>\n ) : null}\n </div>\n ) : null}\n\n <div\n className={cn(\n \"h-full min-h-0 w-full\",\n shouldApplyFullscreenViewportPadding &&\n \"slide__viewport-content--with-header\",\n isSingleSlide ? \"slide-content--single\" : \"grid gap-4\"\n )}\n >\n {currentElementList.length > 0 ? (\n <div className=\"slide-stage\">\n <div ref={stageLayerRef} className=\"slide-stage__layer w-full\">\n {mountedStepStates.map(\n (mountedStepState, mountedStepStateIndex) => {\n const isActiveStep =\n mountedStepStateIndex === currentMountedStateIndex;\n\n return (\n <div\n key={\n mountedStepState.sourceStepIndexes[0] ??\n mountedStepStateIndex\n }\n data-active-step={isActiveStep ? \"true\" : undefined}\n aria-hidden={!isActiveStep || undefined}\n className=\"w-full h-full\"\n style={{ display: isActiveStep ? undefined : \"none\" }}\n >\n {renderSlideElementList(\n mountedStepState.elementList,\n isActiveStep\n )}\n </div>\n );\n }\n )}\n </div>\n </div>\n ) : null}\n </div>\n\n {isAudioLoadingVisible ? (\n <LoadingOverlayCard\n message={resolveBufferingTextByReason(\n resolvedBufferingText,\n audioLoadingReason\n )}\n className=\"absolute left-1/2 top-1/2 z-[3] -translate-x-1/2 -translate-y-1/2\"\n />\n ) : null}\n\n <SubtitleOverlay\n extraBottomOffset={interactionOverlaySubtitleOffset}\n hasPlayerGap={playerLayoutReserved}\n isEnabled={isSubtitleEnabled && hasCurrentAudioPlaybackStarted}\n playbackTimeStore={playbackTimeStore}\n subtitleCues={currentSubtitleCues}\n />\n\n {shouldShowInteractionOverlay ? (\n <div\n ref={interactionOverlayRef}\n data-player-keyboard-shortcuts-ignore=\"true\"\n className={cn(\n \"slide-interaction-overlay\",\n playerLayoutReserved\n ? \"slide-interaction-overlay--with-player\"\n : \"slide-interaction-overlay--standalone\",\n isInteractionOverlayDragging &&\n \"slide-interaction-overlay--dragging\"\n )}\n onClick={stopOverlayPropagation}\n onPointerDownCapture={(event) => {\n if (isInteractionActivityTarget(event.target)) {\n setHasInteractionOverlayActivity(true);\n }\n }}\n onFocusCapture={(event) => {\n if (isInteractionActivityTarget(event.target)) {\n setHasInteractionOverlayActivity(true);\n }\n }}\n onInputCapture={(event) => {\n if (isInteractionActivityTarget(event.target)) {\n setHasInteractionOverlayActivity(true);\n }\n }}\n style={interactionOverlayStyle}\n >\n <InteractionOverlayCard\n dir={direction}\n lang={language}\n content={String(activeInteractionElement?.content ?? \"\")}\n dragHandleAriaLabel={\n interactionTexts?.dragHandleAriaLabel ??\n localeTexts.interactionTexts.dragHandleAriaLabel\n }\n locale={locale}\n defaultButtonText={interactionDefaults.buttonText ?? \"\"}\n defaultInputText={interactionDefaults.inputText ?? \"\"}\n defaultSelectedValues={interactionDefaultSelectedValues}\n confirmButtonText={\n interactionTexts?.confirmButtonText ??\n localeTexts.interactionTexts.confirmButtonText\n }\n copyButtonText={\n interactionTexts?.copyButtonText ??\n localeTexts.interactionTexts.copyButtonText\n }\n copiedButtonText={\n interactionTexts?.copiedButtonText ??\n localeTexts.interactionTexts.copiedButtonText\n }\n onSend={handleInteractionSend}\n onDragHandlePointerCancel={endInteractionOverlayDrag}\n onDragHandlePointerDown={handleInteractionOverlayPointerDown}\n onDragHandlePointerMove={handleInteractionOverlayPointerMove}\n onDragHandlePointerUp={endInteractionOverlayDrag}\n readonly={isInteractionReadonly}\n title={\n interactionTexts?.title ??\n interactionTitle ??\n localeTexts.interactionTexts.title\n }\n />\n </div>\n ) : null}\n\n {shouldMountPlayer ? (\n <PlayerKeyboardShortcutContext.Provider\n value={keyboardShortcutContextValue}\n >\n <Player\n dir={direction === \"auto\" ? resolvedDirection : direction}\n lang={language}\n audioList={audioList}\n className={cn(\n \"absolute left-1/2 z-[2] -translate-x-1/2\",\n isDesktopBrowserFullscreen ? \"bottom-3\" : \"-bottom-3\",\n playerClassName,\n !playerControlsVisible && \"pointer-events-none opacity-0\"\n )}\n currentAudioIndex={currentAudioIndex}\n defaultPlaying={isPlaybackRequested}\n enableKeyboardShortcuts={enableKeyboardShortcuts}\n isPlaybackPaused={shouldPausePlaybackForCustomAction}\n isAutoAdvanceEnabled={isAutoAdvanceEnabled}\n locale={locale}\n isInteractionOpen={isInteractionOverlayOpen}\n isSubtitleEnabled={isSubtitleEnabled}\n onAutoAdvanceToggle={setIsAutoAdvanceEnabled}\n onLoadingChange={handlePlayerLoadingChange}\n onPlaybackStarted={() => {\n setHasCurrentAudioPlaybackStarted(true);\n }}\n onPlaybackCheckpoint={({ audioKey, isComplete, timeMs }) => {\n const checkpointAudioIndex = audioList.findIndex(\n (audioItem) => audioItem.audioKey === audioKey\n );\n const checkpointAudioItem =\n checkpointAudioIndex >= 0\n ? audioList[checkpointAudioIndex]\n : undefined;\n\n if (\n !checkpointAudioItem?.audioKey ||\n !checkpointAudioItem.element\n ) {\n return;\n }\n\n onPlaybackCheckpoint?.({\n audioKey: checkpointAudioItem.audioKey,\n element: checkpointAudioItem.element,\n isComplete,\n stepIndex:\n audioSlideIndexes[checkpointAudioIndex] ?? currentIndex,\n timeMs,\n });\n }}\n onPlaybackPreferenceChange={handlePlaybackPreferenceChange}\n onPlaybackTimeChange={playbackTimeStore.setTime}\n onSubtitleToggle={() => {\n setIsSubtitleEnabled((previousEnabled) => !previousEnabled);\n }}\n nextDisabled={!canGoNext}\n onEnded={handlePlayerEnded}\n onFullscreen={handleFullscreen}\n isFullscreen={isBrowserFullscreen}\n mobileViewMode={effectiveMobileViewMode}\n settingsPortalContainer={viewportRef.current}\n onMobileViewModeChange={handleMobileViewModeSelect}\n onControlsPointerEnter={handlePlayerControlsPointerEnter}\n onControlsPointerLeave={handlePlayerControlsPointerLeave}\n onNext={handleNext}\n onPrev={handlePrev}\n onSubtitleJump={handleSubtitleJump}\n canJumpToSubtitleTarget={canJumpToSubtitleTarget}\n prevDisabled={!canGoPrev}\n showControls={playerControlsVisible}\n slideProgress={\n showSlideProgress\n ? {\n ariaLabel: localeTexts.slideProgressAriaLabel,\n currentIndex,\n onNavigate: handleSlideProgressNavigate,\n totalSteps: generatedSlideCount,\n }\n : null\n }\n subtitleSeekRequest={subtitleSeekRequest}\n playbackRestoreRequest={\n pendingPlaybackRestore &&\n pendingPlaybackRestore.audioKey === currentAudioItem?.audioKey\n ? {\n id: pendingPlaybackRestore.id,\n timeMs: pendingPlaybackRestore.timeMs,\n }\n : null\n }\n onPlaybackRestoreComplete={(requestId) => {\n if (pendingPlaybackRestoreRef.current?.id !== requestId) {\n return;\n }\n\n pendingPlaybackRestoreRef.current = null;\n setPendingPlaybackRestore(null);\n }}\n texts={playerTexts}\n customActionContext={playerCustomActionContext}\n customActions={playerCustomActions}\n useAutoAdvanceToggle={shouldUseSilentStepAutoAdvanceToggle}\n />\n </PlayerKeyboardShortcutContext.Provider>\n ) : null}\n </div>\n </section>\n );\n};\n\nexport default Slide;\n"],"names":["DEFAULT_MARKER_AUTO_ADVANCE_DELAY_MS","DEFAULT_INTERACTION_OVERLAY_OPEN_DELAY_MS","DEFAULT_INTERACTION_OVERLAY_FALLBACK_OFFSET_PX","DEFAULT_INTERACTION_SUBTITLE_GAP_PX","DEFAULT_RESOLVED_INTERACTION_AUTO_CLOSE_DELAY_MS","DEFAULT_INTERACTION_OVERLAY_DRAG_OFFSET","INTERACTION_OVERLAY_LAYOUT_EPSILON_PX","useIsomorphicLayoutEffect","useEffect","useLayoutEffect","INTERACTION_ACTIVITY_SELECTOR","DEFAULT_BUFFERING_REASON","normalizeInteractionOverlayDragOffset","x","y","hasMeaningfulInteractionOverlayLayoutDelta","delta","areInteractionOverlayDragOffsetsEqual","first","second","resolveBufferingTextByReason","bufferingText","reason","DEFAULT_SLIDE_BUFFERING_TEXTS","mergeBufferingTextWithLocaleDefaults","localeBufferingText","shouldShowBufferingOverlay","loading","InteractionOverlayCard","memo","content","title","dragHandleAriaLabel","locale","dir","lang","defaultButtonText","defaultInputText","defaultSelectedValues","confirmButtonText","copyButtonText","copiedButtonText","onSend","onDragHandlePointerCancel","onDragHandlePointerDown","onDragHandlePointerMove","onDragHandlePointerUp","readonly","jsxs","jsx","GripHorizontal","ContentRender","areStepElementListsEqual","prevElementList","nextElementList","element","index","nextElement","isInteractionActivityTarget","target","Slide","elementList","playerEnabled","playerControlsVisibility","playerClassName","fullscreenHeader","playerCustomActions","playerCustomActionPauseOnActive","interactionTitle","interactionTexts","playerTexts","playerAutoHideDelay","markerAutoAdvanceDelay","showSlideProgress","onSlideProgressNavigate","interactionDefaultValueOptions","onPlayerVisibilityChange","onMobileViewModeChange","onStepChange","onPlaybackCheckpoint","playbackRestoreRequest","enableKeyboardShortcuts","enableIframeScaling","enableMarkdownScaling","disableLoadingOverlay","className","onPointerDown","onFocusCapture","props","direction","getMarkdownFlowDirection","language","getMarkdownFlowLanguage","localeTexts","useMemo","getSlideLocaleTexts","resolvedBufferingText","resolvedPlayerEnabled","resolvedPlayerControlsVisibility","resolveSlidePlayerVisibility","keyboardShortcutOwnerId","useId","sectionRef","useRef","resolvedDirection","useResolvedDirection","viewportRef","stageLayerRef","lastElementRef","playerHideTimerRef","isPointerInsidePlayerControlsRef","autoAdvanceTimerRef","imageOnlyStepReadyTimeoutRef","interactionAutoCloseTimerRef","interactionOverlayOpenTimerRef","interactionOverlayRef","interactionOverlayLayoutRectRef","interactionOverlayDragRef","prevRenderElementKeysRef","shouldScrollToBottomRef","pendingInteractionOverlayStepIndexRef","pendingSubtitleJumpRef","subtitleSeekRequestIdRef","playbackResetKeyRef","appendedMarkerAdvanceStateRef","shouldSkipDefaultAudioStartForSubtitleJumpRef","currentElementList","stepElementLists","slideElementList","currentIndex","audioList","audioSlideIndexes","currentAudioSequenceIndexes","currentStepHasSpeakableElement","currentInteractionElement","canGoPrev","canGoNext","goPrev","goNext","goTo","useSlide","currentStepElement","currentRenderElementKeys","generatedSlideCount","isSingleSlide","shouldMountPlayer","keyboardShortcutContextValue","activateKeyboardShortcutOwner","useCallback","activatePlayerKeyboardShortcutOwner","currentAudioSequenceKeys","audioIndex","audioKey","isPlayerVisible","setIsPlayerVisible","useState","hasPlayerInteracted","setHasPlayerInteracted","isPlaybackRequested","setIsPlaybackRequested","isAutoAdvanceEnabled","setIsAutoAdvanceEnabled","currentAudioKey","setCurrentAudioKey","pendingPlaybackRestore","setPendingPlaybackRestore","pendingPlaybackRestoreRef","lastPlaybackRestoreRequestIdRef","subtitleSeekRequest","setSubtitleSeekRequest","isAudioLoadingVisible","setIsAudioLoadingVisible","audioLoadingReason","setAudioLoadingReason","hasCompletedCurrentStepAudio","setHasCompletedCurrentStepAudio","playedAudioKeysRef","hasCurrentAudioPlaybackStarted","setHasCurrentAudioPlaybackStarted","isSubtitleEnabled","setIsSubtitleEnabled","isPlayerCustomActionActive","setIsPlayerCustomActionActive","activeInteractionElement","setActiveInteractionElement","isInteractionOverlayOpen","setIsInteractionOverlayOpen","hasInteractionOverlayActivity","setHasInteractionOverlayActivity","interactionOverlayDragOffset","setInteractionOverlayDragOffset","isInteractionOverlayDragging","setIsInteractionOverlayDragging","interactionOverlaySubtitleOffset","setInteractionOverlaySubtitleOffset","isBrowserFullscreen","setIsBrowserFullscreen","isMobileDevice","getIsMobileDevice","mobileViewMode","setMobileViewMode","DEFAULT_MOBILE_VIEW_MODE","hasManualMobileViewMode","setHasManualMobileViewMode","isViewportFullscreenPreferred","setIsViewportFullscreenPreferred","getIsFullscreenPreferredViewport","playbackTimeStore","createPlaybackTimeStore","effectiveMobileViewMode","isImmersiveMobileFullscreen","isNativeMobileFullscreen","shouldRotateFullscreenViewport","resolveMobileViewModeState","previousEffectiveMobileViewModeRef","playerControlsVisible","playerLayoutReserved","resolveSlidePlayerLayoutState","shouldShowFullscreenHeader","shouldApplyFullscreenViewportPadding","shouldShowMobileFullscreenMask","isDesktopBrowserFullscreen","handleMobileViewModeSelect","nextViewMode","handleMobileViewModeReset","handleFullscreenHeaderBack","clearInteractionAutoCloseTimer","clearInteractionOverlayOpenTimer","closeInteractionOverlayForCustomAction","setPlayerCustomActionActive","active","togglePlayerCustomActionActive","previousActive","resetInteractionOverlayDragState","previousOffset","mountedStepStates","currentMountedStateIndex","nextMountedStepStates","mountedStateIndexByStep","stepElementList","stepIndex","existingMountedStateIndex","mountedStepState","currentStepKey","currentAudioIndex","audioItem","currentAudioItem","targetAudioIndex","targetStepIndex","currentSubtitleCues","currentAudioSequenceStartKey","playerCustomActionContext","resolvePlayerCustomActionElement","playerCustomActionCount","getPlayerCustomActionCount","hasPlayerCustomActions","isPlayerCustomActionEffectivelyActive","interactionOverlayStyle","hasAvailableStepAudio","currentInteractionResetKey","currentPlaybackResetKey","currentPlaybackStartedResetKey","hasCurrentStepAudioUrl","shouldPausePlaybackForCustomAction","shouldUseSilentStepAutoAdvanceToggle","shouldUseAutoAdvanceToggle","silentStepAutoAdvanceBehavior","resolveSilentStepAutoAdvanceBehavior","silentStepAutoAdvanceDelay","isImageOnlySilentStep","imageOnlyStepVisualReadyKey","readyImageOnlyStepKey","setReadyImageOnlyStepKey","isImageOnlyStepVisualReady","clearPlayerHideTimer","clearAutoAdvanceTimer","clearImageOnlyStepReadyTimeout","resetAudioSequence","options","requestSubtitleCueSeek","startCurrentAudioSequence","nextAudioKey","resolvePendingStepAudioKey","continueAfterInteraction","scheduleInteractionOverlayOpen","interactionElement","openOverlay","isPlayerControlsHovered","revealPlayerControls","enableAutoHide","hasResolvedCurrentInteraction","hasResolvedInteractionElement","shouldBlockPlaybackForInteraction","handlePlaybackPreferenceChange","playing","syncPlaybackPreferenceBeforeNavigation","context","cancelled","rafId","cleanupListeners","detachListeners","finishVisualReady","evaluateVisualReady","activeStepContainer","iframeElements","areImageOnlyStepIframeVisualsReady","cleanupCallbacks","queueRecheck","registerEvent","eventName","listener","iframeElement","iframeDocument","image","cleanup","DEFAULT_IMAGE_ONLY_VISUAL_READY_TIMEOUT_MS","syncViewportFullscreenPreference","handleOrientationChange","unsubscribeMobileDeviceChange","subscribeMobileDeviceChange","previousState","shouldAdvanceIntoAppendedMarker","shouldAutoAdvanceIntoAppendedMarker","handleSandboxInteraction","event","isSandboxInteractionMessage","useWakePlayerFromIframe","hasPlaybackContextChanged","shouldInitializeAudioSequence","getPlaybackSequenceTransition","shouldOpenInteractionOverlayAfterAudio","shouldPresentOverlay","shouldPresentInteractionOverlay","pendingSubtitleJump","shouldPreservePendingSubtitleJump","canReachSubtitleJumpTarget","hasUnplayedStepAudio","shouldSkipDefaultAudioStart","shouldStartDefaultAudioSequence","interactionDefaults","interactionDefaultSelectedValues","hasResolvedInteractionInput","resolvedInteractionReadonly","shouldAutoContinueInteraction","resolveSlideInteractionState","isInteractionReadonly","shouldShowInteractionOverlay","shouldRenderInteractionOverlay","handleInteractionSend","resolvedUserInput","prevElement","syncFullscreenState","interactionOverlayElement","updateSubtitleOffset","overlayHeight","resizeObserver","renderSlideElement","Fragment","IframeSandbox","renderSlideElementList","isActiveStep","visibleElementCount","markdownScalingMode","resolveMarkdownScalingMode","lastVisibleElementIndex","lastVisibleIndex","MarkdownSlideScaling","isPreRenderedHtml","cn","handleFullscreen","scrollStageToBottom","stageLayerElement","canJumpToSubtitleTarget","handleSubtitleJump","targetAudioKey","targetSlideIndex","shouldWakePlayerControlsAfterNavigation","handlePrev","handleNext","handleSlideProgressNavigate","targetIndex","handlePlayerLoadingChange","handlePlayerEnded","endedAudioKey","activeSequencePosition","audioSequenceKey","nextSequencePosition","nextStepIndex","nextStepElement","handlePlayerControlsPointerEnter","handlePlayerControlsPointerLeave","stopOverlayPropagation","getInteractionOverlayDragBounds","overlayElement","startOffset","viewportElement","overlayRect","viewportRect","previousRect","currentRect","deltaX","deltaY","nextOffset","bounds","clampedOffset","clampInteractionOverlayDragOffset","handleInteractionOverlayPointerDown","handleInteractionOverlayPointerMove","dragState","endInteractionOverlayDrag","handleSurfacePointerDown","handleSurfaceFocusCapture","handleSurfaceClick","prevKeys","shouldAutoScrollToAppend","key","animationFrameId","targetElement","stageLayerRect","targetRect","nextScrollTop","ChevronLeft","mountedStepStateIndex","LoadingOverlayCard","SubtitleOverlay","PlayerKeyboardShortcutContext","Player","isComplete","timeMs","checkpointAudioIndex","checkpointAudioItem","previousEnabled","requestId"],"mappings":"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"}
|