/** * Style Customizer v2 — live preview pane. Owns the `?evf_preview` iframe and its bridge, * plus the device switcher, save-lifecycle state, skeleton loader, and error card. */ import React from 'react'; import { DEVICE_ICONS, DEVICE_LABELS } from './constants'; import { HoverTip } from './HoverTip'; import { PreviewBridge, SelectionInfo, setActiveBridge } from './PreviewBridge'; import { BuilderSync, getActiveSync, setActiveSync } from './BuilderSync'; import { getStore, useStore } from './store'; import { Device } from './types'; const __ = ( window as any ).wp?.i18n?.__ || ( ( s: string ) => s ); type PreviewStatus = 'loading' | 'ready' | 'error'; const MIGRATION_DISMISS_PREFIX = 'evf_scv2_migration_dismissed_'; /** Notice that this form's legacy styles were auto-migrated. Dismisses once per form. */ function MigrationNotice() { const store = useStore(); const dismissKey = MIGRATION_DISMISS_PREFIX + store.settings.formId; const [ dismissed, setDismissed ] = React.useState( () => { try { return window.localStorage.getItem( dismissKey ) === '1'; } catch ( e ) { return false; } } ); if ( ! store.migration?.just_migrated || dismissed ) { return null; } return (
{ __( 'Styles upgraded from the legacy editor.', 'everest-forms' ) }{ ' ' } { __( 'Nothing should look different — review the preview below, then hit Save to keep it.', 'everest-forms' ) }
); } /** Notice that the Fields or Settings tab has changes not yet saved — shows/hides live as that changes. */ function UnsavedFieldsNotice() { const store = useStore(); const [ dismissed, setDismissed ] = React.useState( false ); React.useEffect( () => { if ( store.hasUnsavedFieldChanges ) { setDismissed( false ); } }, [ store.hasUnsavedFieldChanges ] ); if ( ! store.hasUnsavedFieldChanges || dismissed ) { return null; } return (
{ __( 'Previewing unsaved changes.', 'everest-forms' ) }{ ' ' } { __( 'From the Fields or Settings tab.', 'everest-forms' ) }
); } /** Preview loader (skeleton form + spinner), shared with the panel bootstrap in index.tsx. */ export function PreviewSkeleton( { note }: { note?: string } ) { return (