import React from 'react' import { BackHandler, AccessibilityInfo } from 'react-native' import { Host, Portal } from 'react-native-portalize' import { QuickPreviewOptions, QuickPreviewController } from './types' import { QuickPreviewRoot } from './internal/QuickPreviewRoot' import { QuickPreview as QuickPreviewStatic } from './QuickPreviewAPI' export const QuickPreviewContext = React.createContext(null) /** * Hosts the preview layer and registers the controller. Mount this once, near the * root of your app, inside a ``. After it's mounted you can * present previews via {@link useQuickPreview} or the static `QuickPreview` handle. * * @example * ```tsx * * * * * * ``` */ export function PreviewProvider({ children }: { children: React.ReactNode }) { const [content, setContent] = React.useState(null) const [options, setOptions] = React.useState(undefined) const openRef = React.useRef(false) const announce = React.useCallback((msg: string) => { // eslint-disable-next-line no-empty try { AccessibilityInfo.announceForAccessibility?.(msg) } catch {} }, []) const close = React.useCallback(() => { if (!openRef.current) return openRef.current = false setContent(null) setOptions(undefined) announce('Quick preview closed') }, [announce]) const present = React.useCallback( (node: React.ReactNode, opts?: Partial) => { // Replace, don't merge: options from a previous presentation must not // leak into the next one. Merging is what update() is for. setOptions(opts) openRef.current = true setContent(() => node) announce('Quick preview opened') }, [announce] ) const update = React.useCallback((opts: Partial) => { setOptions(prev => ({ ...prev, ...opts })) }, []) React.useEffect(() => { const sub = BackHandler.addEventListener('hardwareBackPress', () => { if (openRef.current) { close(); return true } return false }) return () => sub.remove() }, [close]) const value = React.useMemo( () => ({ present, close, update, isOpen: () => openRef.current }), [present, close, update] ) // Register the static API (layout effect = available ASAP) React.useLayoutEffect(() => { QuickPreviewStatic._set(value) return () => QuickPreviewStatic._set(null) }, [value]) return ( {children} {content ? ( {content} ) : null} ) }