@parathantl/react-email-editor 0.1.1 → 0.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/EmailEditor.tsx","../src/context/EditorContext.tsx","../src/constants.ts","../src/registry.ts","../src/utils/validate.ts","../src/utils/persistence.ts","../src/hooks/useVariables.ts","../src/hooks/useTipTapTracking.ts","../src/hooks/usePersistence.ts","../src/context/DispatchContext.tsx","../src/context/TemplateContext.tsx","../src/context/SelectionContext.tsx","../src/context/ConfigContext.tsx","../src/context/MethodsContext.tsx","../src/context/HistoryContext.tsx","../src/context/BlockIndexContext.tsx","../src/utils/id.ts","../src/utils/factory.ts","../src/utils/blockIndex.ts","../src/context/editorReducer.ts","../src/context/editorHooks.ts","../src/components/ErrorBoundary.tsx","../src/styles/error-boundary.module.css","../src/components/ConfirmDialog.tsx","../src/styles/confirm-dialog.module.css","../src/components/Toolbar/Toolbar.tsx","../src/utils/sanitize.ts","../src/mjml/generator.ts","../src/mjml/compiler.ts","../src/mjml/parser.ts","../src/styles/toolbar.module.css","../src/styles/editor.module.css","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/BlockPalette.tsx","../src/utils/dnd.ts","../src/styles/sidebar.module.css","../src/components/Sidebar/VariableList.tsx","../src/utils/variables.ts","../src/components/Sidebar/AddVariableForm.tsx","../src/components/Canvas/Canvas.tsx","../src/components/Canvas/Section.tsx","../src/components/Canvas/Column.tsx","../src/components/Canvas/BlockRenderer.tsx","../src/components/Canvas/blocks/TextBlock.tsx","../src/tiptap/TipTapEditor.tsx","../src/tiptap/extensions.ts","../src/tiptap/VariableNode.ts","../src/tiptap/FontSize.ts","../src/tiptap/FontFamily.ts","../src/tiptap/pasteClean.ts","../src/components/Toolbar/RichTextToolbar.tsx","../src/styles/blocks.module.css","../src/styles/tiptap.module.css","../src/components/Canvas/blocks/ButtonBlock.tsx","../src/components/Canvas/blocks/ImageBlock.tsx","../src/components/ImageUpload/useImageUpload.ts","../src/components/Canvas/blocks/DividerBlock.tsx","../src/components/Canvas/blocks/SpacerBlock.tsx","../src/components/Canvas/blocks/SocialBlock.tsx","../src/components/Canvas/blocks/HtmlBlock.tsx","../src/components/Canvas/blocks/VideoBlock.tsx","../src/components/Canvas/blocks/HeadingBlock.tsx","../src/components/Canvas/blocks/CountdownBlock.tsx","../src/components/Canvas/blocks/MenuBlock.tsx","../src/components/Canvas/blocks/HeroBlock.tsx","../src/components/Canvas/DropZone.tsx","../src/styles/canvas.module.css","../src/components/Canvas/SectionDropZone.tsx","../src/components/Properties/SectionProperties.tsx","../src/components/Properties/PropertyField.tsx","../src/components/Properties/controls/ColorPicker.tsx","../src/styles/properties.module.css","../src/components/Properties/controls/PaddingInput.tsx","../src/components/Properties/controls/AlignmentPicker.tsx","../src/components/Properties/controls/FontPicker.tsx","../src/components/Properties/controls/SliderInput.tsx","../src/components/Properties/controls/LinkInput.tsx","../src/components/Properties/HeadMetadataProperties.tsx","../src/hooks/useBlockUpdate.ts","../src/components/Properties/TextProperties.tsx","../src/components/Properties/ButtonProperties.tsx","../src/components/Properties/ImageProperties.tsx","../src/components/Properties/DividerProperties.tsx","../src/components/Properties/SpacerProperties.tsx","../src/components/Properties/SocialProperties.tsx","../src/types.ts","../src/components/Properties/HtmlProperties.tsx","../src/components/Properties/VideoProperties.tsx","../src/components/Properties/HeadingProperties.tsx","../src/components/Properties/CountdownProperties.tsx","../src/components/Properties/MenuProperties.tsx","../src/components/ImageUpload/ImageUploader.tsx","../src/components/Properties/HeroProperties.tsx","../src/components/Properties/PropertiesPanel.tsx","../src/components/Preview/PreviewPanel.tsx","../src/styles/preview.module.css","../src/components/SourceEditor/SourceEditor.tsx","../src/styles/source-editor.module.css"],"sourcesContent":["// Main component\nexport { EmailEditor } from './components/EmailEditor';\n\n// Context & hooks\nexport {\n EditorProvider,\n useEditorState,\n useEditorDispatch,\n useSelectedBlock,\n useSelectedSection,\n useEditorVariables,\n useEditorFonts,\n useImageAdapter,\n useTemplateContext,\n useSelectionContext,\n useDispatchContext,\n useConfigContext,\n useMethodsContext,\n useHistoryContext,\n useBlockIndexContext,\n} from './context/EditorContext';\n\n// Type guard\nexport { narrowBlock } from './types';\n\n// Types\nexport type {\n BlockType,\n Block,\n TypedBlock,\n Column,\n Section,\n SectionProperties,\n EmailTemplate,\n GlobalStyles,\n Variable,\n ImageUploadAdapter,\n UploadOptions,\n UploadResult,\n BrowseResult,\n TransformOptions,\n EmailEditorProps,\n EmailEditorRef,\n ActiveTab,\n SelectionState,\n EditorState,\n EditorAction,\n TextBlockProperties,\n ButtonBlockProperties,\n ImageBlockProperties,\n DividerBlockProperties,\n SpacerBlockProperties,\n BlockProperties,\n BlockPropertiesMap,\n VariableChipStyle,\n HeadMetadata,\n SocialElement,\n SocialBlockProperties,\n CountdownBlockProperties,\n MenuItem,\n MenuBlockProperties,\n HeroBlockProperties,\n HtmlBlockProperties,\n VideoBlockProperties,\n HeadingBlockProperties,\n PersistenceAdapter,\n} from './types';\n\n// MJML utilities\nexport { parseMJML } from './mjml/parser';\nexport { generateMJML } from './mjml/generator';\nexport { compileMJMLToHTML } from './mjml/compiler';\n\n// TipTap extensions (for custom configurations)\nexport { getExtensions } from './tiptap/extensions';\nexport { VariableNode } from './tiptap/VariableNode';\n\n// Utilities\nexport { generateId, generateBlockId, generateSectionId, generateColumnId } from './utils/id';\nexport { extractVariableKeys, replaceVariables, groupVariables } from './utils/variables';\nexport { sanitizeHTML, escapeHTML, isSafeURL } from './utils/sanitize';\nexport { validateTemplate, sanitizeTemplate } from './utils/validate';\nexport type { ValidationResult } from './utils/validate';\nexport { localStorageAdapter } from './utils/persistence';\n\n// Block type registries (for extending with custom block types)\nexport {\n registerBlockRenderer,\n registerBlockProperties,\n registerBlockGenerator,\n registerBlockParser,\n getRegisteredBlockTypes,\n} from './registry';\n\n// Constants\nexport {\n DEFAULT_BLOCK_PROPERTIES,\n DEFAULT_SECTION_PROPERTIES,\n DEFAULT_GLOBAL_STYLES,\n DEFAULT_HEAD_METADATA,\n DEFAULT_SOCIAL_PROPERTIES,\n DEFAULT_VARIABLE_CHIP_STYLE,\n DEFAULT_FONT_SIZES,\n BLOCK_DEFINITIONS,\n FONT_OPTIONS,\n COLOR_PRESETS,\n COLUMN_LAYOUTS,\n} from './constants';\n\nexport type { BlockDefinition } from './constants';\n","import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport type { EmailEditorProps, EmailEditorRef, BlockType } from '../types';\nimport { EditorProvider, useEditorDispatch, useTemplateContext, useSelectionContext, useConfigContext } from '../context/EditorContext';\nimport { ErrorBoundary } from './ErrorBoundary';\nimport { ConfirmDialog } from './ConfirmDialog';\nimport { Toolbar } from './Toolbar/Toolbar';\nimport { Sidebar } from './Sidebar/Sidebar';\nimport { Canvas } from './Canvas/Canvas';\nimport { PropertiesPanel } from './Properties/PropertiesPanel';\nimport { PreviewPanel } from './Preview/PreviewPanel';\nimport { SourceEditor } from './SourceEditor/SourceEditor';\nimport { generateMJML } from '../mjml/generator';\nimport { compileMJMLToHTML } from '../mjml/compiler';\nimport { parseMJML } from '../mjml/parser';\nimport { createSection, createBlock } from '../utils/factory';\nimport { DEFAULT_GLOBAL_STYLES, DEFAULT_HEAD_METADATA } from '../constants';\nimport { extractVariableKeys } from '../utils/variables';\nimport editorStyles from '../styles/editor.module.css';\nimport '../styles/variables.css';\n\nconst EditorInner = forwardRef<EmailEditorRef, EmailEditorProps>(function EditorInner(\n props,\n ref,\n) {\n const dispatch = useEditorDispatch();\n const { template, activeTab } = useTemplateContext();\n const selection = useSelectionContext();\n const { clearPersisted } = useConfigContext();\n const containerRef = useRef<HTMLDivElement>(null);\n const { onReady, onSave } = props;\n\n // Panel toggle state for responsive layout\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [propertiesOpen, setPropertiesOpen] = useState(false);\n\n // Confirm dialog state for keyboard-triggered removal\n const [pendingRemoval, setPendingRemoval] = useState<\n | { type: 'block'; sectionId: string; columnId: string; blockId: string }\n | { type: 'section'; sectionId: string }\n | null\n >(null);\n\n const toggleSidebar = useCallback(() => {\n setSidebarOpen((prev) => !prev);\n setPropertiesOpen(false);\n }, []);\n\n const toggleProperties = useCallback(() => {\n setPropertiesOpen((prev) => !prev);\n setSidebarOpen(false);\n }, []);\n\n const closeOverlays = useCallback(() => {\n setSidebarOpen(false);\n setPropertiesOpen(false);\n }, []);\n\n // Auto-open properties panel when a block is selected (on narrow screens)\n useEffect(() => {\n if (selection.blockId) {\n // Only auto-open if window is narrow (overlay mode)\n if (typeof window !== 'undefined' && window.innerWidth < 1024) {\n setPropertiesOpen(true);\n setSidebarOpen(false);\n }\n }\n }, [selection.blockId]);\n\n // Feature 3: onReady — fire once on mount\n useEffect(() => {\n onReady?.();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Use refs for keyboard handler to avoid re-registering on every state change\n const templateRef = useRef(template);\n templateRef.current = template;\n const selectionRef = useRef(selection);\n selectionRef.current = selection;\n const onSaveRef = useRef(onSave);\n onSaveRef.current = onSave;\n\n // Feature 5: Keyboard shortcuts\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handler = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n const isEditing =\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable;\n\n const mod = e.metaKey || e.ctrlKey;\n\n // Ctrl/Cmd+S → save\n if (mod && e.key === 's') {\n e.preventDefault();\n if (onSaveRef.current) {\n const mjml = generateMJML(templateRef.current);\n compileMJMLToHTML(mjml).then((result) => onSaveRef.current!(mjml, result.html));\n }\n return;\n }\n\n // Escape → deselect all\n if (e.key === 'Escape') {\n dispatch({ type: 'SELECT_BLOCK', payload: null });\n (document.activeElement as HTMLElement)?.blur();\n return;\n }\n\n // Skip remaining shortcuts while typing in inputs\n if (isEditing) return;\n\n // Ctrl/Cmd+Z → undo\n if (mod && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n dispatch({ type: 'UNDO' });\n return;\n }\n\n // Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y → redo\n if (mod && ((e.key === 'z' && e.shiftKey) || e.key === 'y')) {\n e.preventDefault();\n dispatch({ type: 'REDO' });\n return;\n }\n\n // Delete/Backspace → confirm then remove selected block or section\n if (e.key === 'Delete' || e.key === 'Backspace') {\n const { sectionId, columnId, blockId } = selectionRef.current;\n if (blockId && sectionId && columnId) {\n e.preventDefault();\n setPendingRemoval({ type: 'block', sectionId, columnId, blockId });\n } else if (sectionId) {\n e.preventDefault();\n setPendingRemoval({ type: 'section', sectionId });\n }\n }\n };\n\n el.addEventListener('keydown', handler);\n return () => el.removeEventListener('keydown', handler);\n }, [dispatch]);\n\n const handleConfirmRemoval = useCallback(() => {\n if (!pendingRemoval) return;\n if (pendingRemoval.type === 'block') {\n dispatch({ type: 'REMOVE_BLOCK', payload: pendingRemoval });\n } else {\n dispatch({ type: 'REMOVE_SECTION', payload: { sectionId: pendingRemoval.sectionId } });\n }\n setPendingRemoval(null);\n }, [dispatch, pendingRemoval]);\n\n useImperativeHandle(ref, () => ({\n getMJML: () => generateMJML(templateRef.current),\n\n getHTML: async () => {\n const mjml = generateMJML(templateRef.current);\n const result = await compileMJMLToHTML(mjml);\n return result.html;\n },\n\n getJSON: () => JSON.parse(JSON.stringify(templateRef.current)),\n\n loadMJML: (source: string) => {\n const parsed = parseMJML(source);\n dispatch({ type: 'SET_TEMPLATE', payload: parsed });\n },\n\n loadJSON: (t) => {\n dispatch({ type: 'SET_TEMPLATE', payload: t });\n },\n\n insertBlock: (type: BlockType, sectionIdx?: number) => {\n const currentTemplate = templateRef.current;\n const targetSection = currentTemplate.sections[sectionIdx ?? currentTemplate.sections.length - 1];\n const block = createBlock(type);\n\n if (!targetSection) {\n // Use combined action to avoid stale-data race condition\n const newSection = createSection();\n dispatch({ type: 'ADD_SECTION_WITH_BLOCK', payload: { section: newSection, block } });\n } else {\n const column = targetSection.columns[0];\n dispatch({\n type: 'ADD_BLOCK',\n payload: { sectionId: targetSection.id, columnId: column.id, block },\n });\n }\n },\n\n getVariables: () => {\n const mjml = generateMJML(templateRef.current);\n return extractVariableKeys(mjml);\n },\n\n undo: () => dispatch({ type: 'UNDO' }),\n redo: () => dispatch({ type: 'REDO' }),\n\n reset: () => {\n dispatch({\n type: 'SET_TEMPLATE',\n payload: { sections: [], globalStyles: { ...DEFAULT_GLOBAL_STYLES }, headMetadata: { ...DEFAULT_HEAD_METADATA, headStyles: [] } },\n });\n },\n\n clearPersisted: () => clearPersisted(),\n\n exportPDF: async () => {\n const mjml = generateMJML(templateRef.current);\n const result = await compileMJMLToHTML(mjml);\n const printStyles = `\n <style>\n @page { margin: 0; size: auto; }\n @media print {\n html, body { margin: 0; padding: 0; }\n }\n </style>\n `;\n const htmlWithPrintStyles = result.html.replace(\n '</head>',\n `${printStyles}</head>`,\n );\n const iframe = document.createElement('iframe');\n iframe.style.position = 'fixed';\n iframe.style.left = '-9999px';\n document.body.appendChild(iframe);\n const doc = iframe.contentDocument!;\n doc.open();\n doc.write(htmlWithPrintStyles);\n doc.close();\n iframe.contentWindow!.print();\n setTimeout(() => document.body.removeChild(iframe), 1000);\n },\n }), [dispatch, clearPersisted]);\n\n const sidebarClasses = [\n editorStyles.editorPanel,\n editorStyles.sidebarPanel,\n sidebarOpen ? editorStyles.sidebarOpen : '',\n ].filter(Boolean).join(' ');\n\n const propertiesClasses = [\n editorStyles.editorPanel,\n editorStyles.propertiesPanel,\n propertiesOpen ? editorStyles.propertiesOpen : '',\n ].filter(Boolean).join(' ');\n\n const overlayClasses = [\n editorStyles.panelOverlay,\n (sidebarOpen || propertiesOpen) ? editorStyles.panelOverlayVisible : '',\n ].filter(Boolean).join(' ');\n\n return (\n <div ref={containerRef} className={`ee-editor ${editorStyles.editorContainer}`} tabIndex={-1}>\n {pendingRemoval && (\n <ConfirmDialog\n title={pendingRemoval.type === 'block' ? 'Remove Block' : 'Remove Section'}\n message={\n pendingRemoval.type === 'block'\n ? 'Are you sure you want to remove this block? This action can be undone with Ctrl+Z.'\n : 'Are you sure you want to remove this section and all its contents? This action can be undone with Ctrl+Z.'\n }\n onConfirm={handleConfirmRemoval}\n onCancel={() => setPendingRemoval(null)}\n />\n )}\n <Toolbar\n sidebarOpen={sidebarOpen}\n propertiesOpen={propertiesOpen}\n onToggleSidebar={toggleSidebar}\n onToggleProperties={toggleProperties}\n />\n <div className={editorStyles.editorBody}>\n {activeTab === 'visual' && (\n <>\n <div className={`ee-sidebar ${sidebarClasses}`}>\n <ErrorBoundary>\n <Sidebar blockDefinitions={props.blockDefinitions} />\n </ErrorBoundary>\n </div>\n <div className={`ee-canvas ${editorStyles.editorPanel} ${editorStyles.canvasPanel}`}>\n <ErrorBoundary>\n <Canvas />\n </ErrorBoundary>\n </div>\n <div className={`ee-properties ${propertiesClasses}`}>\n <ErrorBoundary>\n <PropertiesPanel />\n </ErrorBoundary>\n </div>\n {/* Backdrop overlay for narrow screens */}\n <div className={overlayClasses} onClick={closeOverlays} />\n </>\n )}\n {activeTab === 'source' && (\n <div className={`ee-source-layout ${editorStyles.sourceLayout}`}>\n <div className={`ee-source-pane ${editorStyles.sourcePane}`}>\n <ErrorBoundary>\n <SourceEditor />\n </ErrorBoundary>\n </div>\n <div className={`ee-preview-pane ${editorStyles.sourcePaneDivider}`}>\n <ErrorBoundary>\n <PreviewPanel />\n </ErrorBoundary>\n </div>\n </div>\n )}\n {activeTab === 'preview' && (\n <ErrorBoundary>\n <PreviewPanel />\n </ErrorBoundary>\n )}\n </div>\n </div>\n );\n});\n\nexport const EmailEditor = forwardRef<EmailEditorRef, EmailEditorProps>(\n function EmailEditor(props, ref) {\n const {\n initialTemplate,\n initialMJML,\n variables,\n imageUploadAdapter,\n onChange,\n onVariablesChange,\n fontFamilies,\n fontSizes,\n persistenceKey,\n persistenceAdapter,\n className,\n style,\n onBlockAdd,\n onBlockRemove,\n onBlockUpdate,\n onSectionAdd,\n onSectionRemove,\n onSelectionChange,\n onTemplateLoad,\n onHistoryChange,\n } = props;\n\n let template = initialTemplate;\n if (!template && initialMJML) {\n try {\n template = parseMJML(initialMJML);\n } catch {\n template = undefined;\n }\n }\n\n return (\n <EditorProvider\n initialTemplate={template}\n variables={variables}\n imageUploadAdapter={imageUploadAdapter}\n onChange={onChange}\n onVariablesChange={onVariablesChange}\n fontFamilies={fontFamilies}\n fontSizes={fontSizes}\n persistenceKey={persistenceKey}\n persistenceAdapter={persistenceAdapter}\n onBlockAdd={onBlockAdd}\n onBlockRemove={onBlockRemove}\n onBlockUpdate={onBlockUpdate}\n onSectionAdd={onSectionAdd}\n onSectionRemove={onSectionRemove}\n onSelectionChange={onSelectionChange}\n onTemplateLoad={onTemplateLoad}\n onHistoryChange={onHistoryChange}\n >\n <div className={`ee-editor-wrapper ${editorStyles.editorWrapper} ${className || ''}`} style={style}>\n <EditorInner ref={ref} {...props} />\n </div>\n </EditorProvider>\n );\n },\n);\n","import React, {\n useReducer,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport type {\n EditorAction,\n EmailTemplate,\n Variable,\n ImageUploadAdapter,\n PersistenceAdapter,\n Block,\n BlockProperties,\n Section,\n SelectionState,\n} from '../types';\nimport { DEFAULT_FONT_SIZES, FONT_OPTIONS } from '../constants';\nimport { sanitizeTemplate } from '../utils/validate';\nimport { localStorageAdapter } from '../utils/persistence';\nimport { useVariables } from '../hooks/useVariables';\nimport { useTipTapTracking } from '../hooks/useTipTapTracking';\nimport { usePersistence } from '../hooks/usePersistence';\nimport { DispatchContext } from './DispatchContext';\nimport { TemplateContext, type TemplateContextValue } from './TemplateContext';\nimport { SelectionContext } from './SelectionContext';\nimport { ConfigContext, type ConfigContextValue } from './ConfigContext';\nimport { MethodsContext } from './MethodsContext';\nimport { HistoryContext } from './HistoryContext';\nimport { BlockIndexContext } from './BlockIndexContext';\n\n// Import reducer + helpers from extracted module\nimport {\n editorReducer,\n createInitialState,\n DEBOUNCE_ELIGIBLE,\n INITIAL_SELECTION,\n} from './editorReducer';\n\nconst EMPTY_VARIABLES: Variable[] = [];\n\n// ---- Provider ----\n\ninterface EditorProviderProps {\n children: ReactNode;\n initialTemplate?: EmailTemplate;\n variables?: Variable[];\n imageUploadAdapter?: ImageUploadAdapter;\n onChange?: (template: EmailTemplate) => void;\n onVariablesChange?: (customVariables: Variable[]) => void;\n fontFamilies?: string[];\n fontSizes?: string[];\n persistenceKey?: string;\n persistenceAdapter?: PersistenceAdapter;\n // Event callbacks\n onBlockAdd?: (block: Block, sectionId: string, columnId: string) => void;\n onBlockRemove?: (blockId: string, sectionId: string, columnId: string) => void;\n onBlockUpdate?: (blockId: string, properties: Partial<BlockProperties>) => void;\n onBlockMove?: (blockId: string, toSectionId: string, toColumnId: string, toIndex: number) => void;\n onSectionAdd?: (section: Section, index?: number) => void;\n onSectionRemove?: (sectionId: string) => void;\n onSectionMove?: (sectionId: string, toIndex: number) => void;\n onSelectionChange?: (selection: SelectionState) => void;\n onTemplateLoad?: (template: EmailTemplate) => void;\n onHistoryChange?: (canUndo: boolean, canRedo: boolean) => void;\n}\n\nexport function EditorProvider({\n children,\n initialTemplate,\n variables: predefinedVariables = EMPTY_VARIABLES,\n imageUploadAdapter,\n onChange,\n onVariablesChange,\n fontFamilies: fontFamiliesProp,\n fontSizes: fontSizesProp,\n persistenceKey,\n persistenceAdapter,\n onBlockAdd,\n onBlockRemove,\n onBlockUpdate,\n onBlockMove,\n onSectionAdd,\n onSectionRemove,\n onSectionMove,\n onSelectionChange,\n onTemplateLoad,\n onHistoryChange,\n}: EditorProviderProps) {\n const fontFamilies = fontFamiliesProp ?? FONT_OPTIONS;\n const fontSizes = fontSizesProp ?? DEFAULT_FONT_SIZES;\n\n // Resolve initial template: persisted data takes priority over prop (sync case).\n const resolvedInitial = useMemo((): EmailTemplate | undefined => {\n if (persistenceKey) {\n const adapter = persistenceAdapter ?? localStorageAdapter;\n const persisted = adapter.load(persistenceKey);\n if (persisted && !(persisted instanceof Promise)) return sanitizeTemplate(persisted);\n // Async case handled in useEffect below\n }\n return initialTemplate;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const [state, rawDispatch] = useReducer(editorReducer, resolvedInitial, createInitialState);\n\n // Handle async persistence adapters — load in effect and apply via SET_TEMPLATE\n const asyncLoadedKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!persistenceKey) return;\n // Skip if we already loaded for this exact key\n if (asyncLoadedKeyRef.current === persistenceKey) return;\n const adapter = persistenceAdapter ?? localStorageAdapter;\n const result = adapter.load(persistenceKey);\n if (result instanceof Promise) {\n asyncLoadedKeyRef.current = persistenceKey;\n const key = persistenceKey; // capture for async callback\n result.then((persisted) => {\n // Only apply if the key hasn't changed since we started loading\n if (asyncLoadedKeyRef.current === key && persisted) {\n rawDispatch({ type: 'SET_TEMPLATE', payload: persisted });\n }\n }).catch(() => {\n // Async persistence load failed — fall through to initialTemplate\n });\n }\n }, [persistenceKey, persistenceAdapter]);\n\n // Debounced dispatch\n const historyTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const flushHistoryTimer = useCallback(() => {\n if (historyTimerRef.current !== null) {\n clearTimeout(historyTimerRef.current);\n historyTimerRef.current = null;\n rawDispatch({ type: 'PUSH_HISTORY' });\n }\n }, []);\n\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n // Store event callbacks in refs to avoid re-render cascades\n const eventRefs = useRef({\n onBlockAdd, onBlockRemove, onBlockUpdate, onBlockMove,\n onSectionAdd, onSectionRemove, onSectionMove,\n onSelectionChange, onTemplateLoad, onHistoryChange,\n });\n eventRefs.current = {\n onBlockAdd, onBlockRemove, onBlockUpdate, onBlockMove,\n onSectionAdd, onSectionRemove, onSectionMove,\n onSelectionChange, onTemplateLoad, onHistoryChange,\n };\n\n const dispatch: React.Dispatch<EditorAction> = useCallback(\n (action: EditorAction) => {\n if (DEBOUNCE_ELIGIBLE.has(action.type)) {\n rawDispatch(action);\n if (historyTimerRef.current !== null) {\n clearTimeout(historyTimerRef.current);\n }\n historyTimerRef.current = setTimeout(() => {\n historyTimerRef.current = null;\n rawDispatch({ type: 'PUSH_HISTORY' });\n }, 500);\n } else if (action.type === 'UNDO' || action.type === 'REDO') {\n flushHistoryTimer();\n rawDispatch(action);\n } else if (\n action.type === 'SELECT_BLOCK' ||\n action.type === 'SELECT_SECTION' ||\n action.type === 'SET_ACTIVE_TAB' ||\n action.type === 'DESELECT_ALL'\n ) {\n rawDispatch(action);\n } else {\n flushHistoryTimer();\n rawDispatch(action);\n }\n\n // Fire event callbacks after dispatch (wrapped in try/catch for safety)\n try {\n const ev = eventRefs.current;\n switch (action.type) {\n case 'ADD_BLOCK':\n case 'ADD_BLOCK_AND_SELECT':\n ev.onBlockAdd?.(action.payload.block, action.payload.sectionId, action.payload.columnId);\n break;\n case 'REMOVE_BLOCK':\n ev.onBlockRemove?.(action.payload.blockId, action.payload.sectionId, action.payload.columnId);\n break;\n case 'UPDATE_BLOCK':\n ev.onBlockUpdate?.(action.payload.blockId, action.payload.properties);\n break;\n case 'ADD_SECTION':\n ev.onSectionAdd?.(action.payload.section, action.payload.index);\n break;\n case 'ADD_SECTION_WITH_BLOCK':\n ev.onSectionAdd?.(action.payload.section, action.payload.index);\n ev.onBlockAdd?.(action.payload.block, action.payload.section.id, action.payload.section.columns[0]?.id);\n break;\n case 'REMOVE_SECTION':\n ev.onSectionRemove?.(action.payload.sectionId);\n break;\n case 'MOVE_BLOCK':\n ev.onBlockMove?.(action.payload.blockId, action.payload.toSectionId, action.payload.toColumnId, action.payload.toIndex);\n break;\n case 'MOVE_SECTION':\n ev.onSectionMove?.(action.payload.sectionId, action.payload.toIndex);\n break;\n // DUPLICATE_BLOCK and DUPLICATE_SECTION: the cloned object is created inside the reducer,\n // not available here. Host apps are notified of the resulting state change via onChange.\n case 'SELECT_BLOCK':\n case 'SELECT_SECTION':\n case 'DESELECT_ALL':\n if (action.type === 'DESELECT_ALL') {\n ev.onSelectionChange?.(INITIAL_SELECTION);\n } else if (action.type === 'SELECT_BLOCK') {\n ev.onSelectionChange?.(action.payload ?? INITIAL_SELECTION);\n } else {\n ev.onSelectionChange?.(\n action.payload\n ? { sectionId: action.payload.sectionId, columnId: null, blockId: null }\n : INITIAL_SELECTION,\n );\n }\n break;\n case 'SET_TEMPLATE':\n ev.onTemplateLoad?.(action.payload);\n break;\n }\n } catch (err) {\n console.error('[EmailEditor] Event callback error:', err);\n }\n },\n [flushHistoryTimer],\n );\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (historyTimerRef.current !== null) {\n clearTimeout(historyTimerRef.current);\n }\n };\n }, []);\n\n // Delegate to focused hooks\n const {\n customVariables,\n allVariables,\n variableChipStyle,\n addCustomVariable,\n removeCustomVariable,\n updateVariableChipStyle,\n } = useVariables({ predefinedVariables, onVariablesChange });\n\n const { setActiveEditor, getActiveEditor, insertVariable } = useTipTapTracking();\n\n const { clearPersisted } = usePersistence({\n template: state.template,\n persistenceKey,\n persistenceAdapter,\n });\n\n // Debounced onChange notification\n const isFirstRender = useRef(true);\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n return;\n }\n const timer = setTimeout(() => {\n onChangeRef.current?.(state.template);\n }, 150);\n return () => clearTimeout(timer);\n }, [state.template]);\n\n // Fire onHistoryChange when undo/redo state changes\n const prevHistoryRef = useRef({ canUndo: false, canRedo: false });\n useEffect(() => {\n const canUndo = state.historyIndex > 0;\n const canRedo = state.historyIndex < state.history.length - 1;\n if (canUndo !== prevHistoryRef.current.canUndo || canRedo !== prevHistoryRef.current.canRedo) {\n prevHistoryRef.current = { canUndo, canRedo };\n try {\n eventRefs.current.onHistoryChange?.(canUndo, canRedo);\n } catch (err) {\n console.error('[EmailEditor] onHistoryChange callback error:', err);\n }\n }\n }, [state.historyIndex, state.history.length]);\n\n // Focused context values with memoization\n const templateValue: TemplateContextValue = useMemo(\n () => ({\n template: state.template,\n isDirty: state.isDirty,\n activeTab: state.activeTab,\n }),\n [state.template, state.isDirty, state.activeTab],\n );\n\n const historyValue = useMemo(\n () => ({\n canUndo: state.historyIndex > 0,\n canRedo: state.historyIndex < state.history.length - 1,\n }),\n [state.historyIndex, state.history.length],\n );\n\n const selectionValue = useMemo(\n () => state.selection,\n [state.selection.sectionId, state.selection.columnId, state.selection.blockId],\n );\n\n const methodsValue = useMemo(\n () => ({ setActiveEditor, getActiveEditor, insertVariable }),\n [setActiveEditor, getActiveEditor, insertVariable],\n );\n\n const configValue: ConfigContextValue = useMemo(\n () => ({\n variables: allVariables,\n predefinedVariables,\n customVariables,\n imageUploadAdapter,\n addCustomVariable,\n removeCustomVariable,\n variableChipStyle,\n updateVariableChipStyle,\n fontFamilies,\n fontSizes,\n clearPersisted,\n }),\n [allVariables, predefinedVariables, customVariables, imageUploadAdapter, addCustomVariable, removeCustomVariable, variableChipStyle, updateVariableChipStyle, fontFamilies, fontSizes, clearPersisted],\n );\n\n const blockIndexValue = useMemo(() => state.blockIndex, [state.blockIndex]);\n\n return (\n <DispatchContext.Provider value={dispatch}>\n <MethodsContext.Provider value={methodsValue}>\n <HistoryContext.Provider value={historyValue}>\n <TemplateContext.Provider value={templateValue}>\n <SelectionContext.Provider value={selectionValue}>\n <ConfigContext.Provider value={configValue}>\n <BlockIndexContext.Provider value={blockIndexValue}>\n {children}\n </BlockIndexContext.Provider>\n </ConfigContext.Provider>\n </SelectionContext.Provider>\n </TemplateContext.Provider>\n </HistoryContext.Provider>\n </MethodsContext.Provider>\n </DispatchContext.Provider>\n );\n}\n\n// ---- Re-exports for backward compatibility ----\n\n// Re-export reducer + helpers\nexport { editorReducer, createInitialState, DEBOUNCE_ELIGIBLE } from './editorReducer';\n\n// Re-export hooks from editorHooks\nexport {\n useEditorState,\n useEditorDispatch,\n useSelectedBlock,\n useSelectedSection,\n useEditorVariables,\n useEditorFonts,\n useImageAdapter,\n} from './editorHooks';\n\n// Re-export focused context hooks for direct consumption\nexport { useDispatchContext } from './DispatchContext';\nexport { useTemplateContext } from './TemplateContext';\nexport { useSelectionContext } from './SelectionContext';\nexport { useConfigContext } from './ConfigContext';\nexport { useMethodsContext } from './MethodsContext';\nexport { useHistoryContext, type HistoryContextValue } from './HistoryContext';\nexport { useBlockIndexContext } from './BlockIndexContext';\n","import type {\n BlockType,\n BlockPropertiesMap,\n TextBlockProperties,\n ButtonBlockProperties,\n ImageBlockProperties,\n DividerBlockProperties,\n SpacerBlockProperties,\n SocialBlockProperties,\n HtmlBlockProperties,\n VideoBlockProperties,\n HeadingBlockProperties,\n CountdownBlockProperties,\n MenuBlockProperties,\n HeroBlockProperties,\n SectionProperties,\n GlobalStyles,\n VariableChipStyle,\n HeadMetadata,\n} from './types';\n\n// ---- Default Block Properties ----\n\nexport const DEFAULT_TEXT_PROPERTIES: TextBlockProperties = {\n content: '',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n color: '#000000',\n lineHeight: '1.5',\n padding: '10px 25px',\n align: 'left',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n};\n\nexport const DEFAULT_BUTTON_PROPERTIES: ButtonBlockProperties = {\n text: 'Click me',\n href: '#',\n backgroundColor: '#2563eb',\n color: '#ffffff',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n borderRadius: '4px',\n padding: '10px 25px',\n innerPadding: '12px 24px',\n align: 'center',\n width: 'auto',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n};\n\nexport const DEFAULT_IMAGE_PROPERTIES: ImageBlockProperties = {\n src: '',\n alt: '',\n href: '',\n width: '600px',\n height: 'auto',\n padding: '10px 25px',\n align: 'center',\n fluidOnMobile: true,\n};\n\nexport const DEFAULT_DIVIDER_PROPERTIES: DividerBlockProperties = {\n borderColor: '#cccccc',\n borderWidth: '1px',\n borderStyle: 'solid',\n padding: '10px 25px',\n width: '100%',\n};\n\nexport const DEFAULT_SPACER_PROPERTIES: SpacerBlockProperties = {\n height: '20px',\n};\n\nexport const DEFAULT_SOCIAL_PROPERTIES: SocialBlockProperties = {\n elements: [\n { name: 'facebook', href: 'https://facebook.com' },\n { name: 'twitter', href: 'https://twitter.com' },\n { name: 'instagram', href: 'https://instagram.com' },\n ],\n mode: 'horizontal',\n align: 'center',\n iconSize: '20px',\n iconPadding: '5px',\n padding: '10px 25px',\n fontSize: '13px',\n color: '#333333',\n borderRadius: '3px',\n};\n\nexport const DEFAULT_HTML_PROPERTIES: HtmlBlockProperties = {\n content: '',\n padding: '10px 25px',\n};\n\nexport const DEFAULT_VIDEO_PROPERTIES: VideoBlockProperties = {\n src: '',\n thumbnailUrl: '',\n alt: 'Video',\n padding: '10px 25px',\n align: 'center',\n};\n\nexport const DEFAULT_HEADING_PROPERTIES: HeadingBlockProperties = {\n content: '',\n level: 'h2',\n fontFamily: 'Arial, sans-serif',\n fontSize: '28px',\n color: '#000000',\n lineHeight: '1.3',\n fontWeight: 'bold',\n padding: '10px 25px',\n align: 'left',\n textTransform: 'none',\n letterSpacing: 'normal',\n};\n\nexport const DEFAULT_COUNTDOWN_PROPERTIES: CountdownBlockProperties = {\n targetDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 16),\n label: 'Sale ends in',\n digitBackgroundColor: '#333333',\n digitColor: '#ffffff',\n labelColor: '#666666',\n fontSize: '24px',\n padding: '10px 25px',\n align: 'center',\n};\n\nexport const DEFAULT_MENU_PROPERTIES: MenuBlockProperties = {\n items: [\n { text: 'Home', href: '#' },\n { text: 'About', href: '#' },\n { text: 'Contact', href: '#' },\n ],\n align: 'center',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n color: '#333333',\n padding: '10px 25px',\n hamburger: false,\n iconColor: '#333333',\n};\n\nexport const DEFAULT_HERO_PROPERTIES: HeroBlockProperties = {\n heading: 'Welcome to Our Newsletter',\n subtext: 'Stay up to date with our latest news and updates.',\n buttonText: 'Get Started',\n buttonHref: '#',\n headingColor: '#333333',\n headingFontSize: '32px',\n subtextColor: '#666666',\n subtextFontSize: '16px',\n buttonBackgroundColor: '#2563eb',\n buttonColor: '#ffffff',\n buttonBorderRadius: '4px',\n align: 'center',\n padding: '40px 25px',\n backgroundImage: '',\n backgroundColor: '#ffffff',\n};\n\nexport const DEFAULT_BLOCK_PROPERTIES: { [K in BlockType]: BlockPropertiesMap[K] } = {\n text: DEFAULT_TEXT_PROPERTIES,\n button: DEFAULT_BUTTON_PROPERTIES,\n image: DEFAULT_IMAGE_PROPERTIES,\n divider: DEFAULT_DIVIDER_PROPERTIES,\n spacer: DEFAULT_SPACER_PROPERTIES,\n social: DEFAULT_SOCIAL_PROPERTIES,\n html: DEFAULT_HTML_PROPERTIES,\n video: DEFAULT_VIDEO_PROPERTIES,\n heading: DEFAULT_HEADING_PROPERTIES,\n countdown: DEFAULT_COUNTDOWN_PROPERTIES,\n menu: DEFAULT_MENU_PROPERTIES,\n hero: DEFAULT_HERO_PROPERTIES,\n};\n\n// ---- Default Section Properties ----\n\nexport const DEFAULT_SECTION_PROPERTIES: SectionProperties = {\n backgroundColor: 'transparent',\n padding: '20px 0',\n borderRadius: '0px',\n fullWidth: false,\n};\n\n// ---- Default Head Metadata ----\n\nexport const DEFAULT_HEAD_METADATA: HeadMetadata = {\n title: '',\n previewText: '',\n headStyles: [],\n};\n\n// ---- Default Global Styles ----\n\nexport const DEFAULT_GLOBAL_STYLES: GlobalStyles = {\n backgroundColor: '#f4f4f4',\n width: 600,\n fontFamily: 'Arial, sans-serif',\n};\n\n// ---- Default Variable Chip Style ----\n\nexport const DEFAULT_VARIABLE_CHIP_STYLE: VariableChipStyle = {\n backgroundColor: '#dbeafe',\n color: '#1e40af',\n borderColor: '#93c5fd',\n fontSize: 'inherit',\n borderRadius: '10px',\n};\n\n// ---- Block Palette Definitions ----\n\nexport interface BlockDefinition {\n type: BlockType;\n label: string;\n icon: string;\n description: string;\n}\n\nexport const BLOCK_DEFINITIONS: BlockDefinition[] = [\n {\n type: 'text',\n label: 'Text',\n icon: '📝',\n description: 'Rich text content with formatting',\n },\n {\n type: 'heading',\n label: 'Heading',\n icon: 'H',\n description: 'Heading with level selector',\n },\n {\n type: 'button',\n label: 'Button',\n icon: '🔘',\n description: 'Call-to-action button',\n },\n {\n type: 'image',\n label: 'Image',\n icon: '🖼️',\n description: 'Image with optional link',\n },\n {\n type: 'video',\n label: 'Video',\n icon: '▶️',\n description: 'Video thumbnail with link',\n },\n {\n type: 'divider',\n label: 'Divider',\n icon: '➖',\n description: 'Horizontal divider line',\n },\n {\n type: 'spacer',\n label: 'Spacer',\n icon: '↕️',\n description: 'Vertical spacing',\n },\n {\n type: 'social',\n label: 'Social',\n icon: '🔗',\n description: 'Social media links',\n },\n {\n type: 'html',\n label: 'HTML',\n icon: '</>',\n description: 'Raw HTML content',\n },\n {\n type: 'countdown',\n label: 'Countdown',\n icon: '⏱️',\n description: 'Countdown timer with digit boxes',\n },\n {\n type: 'menu',\n label: 'Menu',\n icon: '☰',\n description: 'Navigation menu links',\n },\n {\n type: 'hero',\n label: 'Hero',\n icon: '🦸',\n description: 'Hero section with heading, text and CTA',\n },\n];\n\n// ---- History ----\n\nexport const MAX_HISTORY_SIZE = 50;\n\n// ---- Font Size Options ----\n\nexport const DEFAULT_FONT_SIZES = [\n '10px', '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px',\n];\n\n// ---- Font Options ----\n\nexport const FONT_OPTIONS = [\n 'Arial, sans-serif',\n 'Helvetica, sans-serif',\n 'Georgia, serif',\n 'Times New Roman, serif',\n 'Courier New, monospace',\n 'Verdana, sans-serif',\n 'Trebuchet MS, sans-serif',\n 'Tahoma, sans-serif',\n];\n\n// ---- Color Presets ----\n\nexport const COLOR_PRESETS = [\n '#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff',\n '#ef4444', '#f97316', '#eab308', '#22c55e', '#3b82f6', '#8b5cf6',\n '#ec4899', '#14b8a6', '#f43f5e', '#6366f1', '#0ea5e9', '#84cc16',\n];\n\n// ---- Layout Presets ----\n\nexport const COLUMN_LAYOUTS = [\n { label: '1 Column', widths: ['100%'] },\n { label: '2 Columns', widths: ['50%', '50%'] },\n { label: '3 Columns', widths: ['33.33%', '33.33%', '33.33%'] },\n { label: '1/3 + 2/3', widths: ['33.33%', '66.67%'] },\n { label: '2/3 + 1/3', widths: ['66.67%', '33.33%'] },\n];\n","/**\n * Block type registries — single source of truth for mapping block types\n * to their renderers, property panels, generators, and parsers.\n *\n * Adding a new block type requires only adding entries here (Open/Closed Principle).\n */\nimport type { ComponentType } from 'react';\nimport type { Block, BlockType } from './types';\n\n// ---- Component Registries (populated by components at import time) ----\n\nexport const blockRendererRegistry: Record<string, ComponentType<{ block: Block }>> = {};\nexport const blockPropertiesRegistry: Record<string, ComponentType<{ block: Block }>> = {};\n\n// ---- MJML Generator Registry ----\n\nexport const blockGeneratorRegistry: Record<string, (block: Block, indent: string) => string> = {};\n\n// ---- MJML Parser Registry ----\n\nexport const blockParserRegistry: Record<string, (el: Element) => Block> = {};\n\n// ---- Registration helpers ----\n\n/**\n * Register a block renderer. Accepts BlockType for built-in types, or any string for custom blocks.\n */\nexport function registerBlockRenderer(type: BlockType | (string & {}), component: ComponentType<{ block: Block }>) {\n blockRendererRegistry[type] = component;\n}\n\n/**\n * Register a block properties panel. Accepts BlockType for built-in types, or any string for custom blocks.\n */\nexport function registerBlockProperties(type: BlockType | (string & {}), component: ComponentType<{ block: Block }>) {\n blockPropertiesRegistry[type] = component;\n}\n\n/**\n * Register a MJML generator. Accepts BlockType for built-in types, or any string for custom blocks.\n */\nexport function registerBlockGenerator(type: BlockType | (string & {}), generator: (block: Block, indent: string) => string) {\n blockGeneratorRegistry[type] = generator;\n}\n\nexport function registerBlockParser(mjmlTag: string, parser: (el: Element) => Block) {\n blockParserRegistry[mjmlTag] = parser;\n}\n\n/** Returns set of all registered block types (built-in + custom). */\nexport function getRegisteredBlockTypes(): Set<string> {\n return new Set(Object.keys(blockRendererRegistry));\n}\n","import type { EmailTemplate, BlockType, Section, Column, Block, GlobalStyles } from '../types';\nimport { DEFAULT_GLOBAL_STYLES, DEFAULT_HEAD_METADATA } from '../constants';\nimport { getRegisteredBlockTypes } from '../registry';\n\nconst BUILT_IN_BLOCK_TYPES: ReadonlySet<string> = new Set<BlockType>([\n 'text', 'button', 'image', 'divider', 'spacer', 'social',\n 'html', 'video', 'heading', 'countdown', 'menu', 'hero',\n]);\n\n/** Returns true if the type is a valid block type (built-in or registered custom). */\nfunction isValidBlockType(type: string): boolean {\n return BUILT_IN_BLOCK_TYPES.has(type) || getRegisteredBlockTypes().has(type);\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate raw data as an EmailTemplate.\n * Returns { valid, errors } with descriptive error messages.\n */\nexport function validateTemplate(data: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (!data || typeof data !== 'object') {\n return { valid: false, errors: ['Template must be a non-null object'] };\n }\n\n const d = data as Record<string, unknown>;\n\n if (!Array.isArray(d.sections)) {\n errors.push('Template must have a \"sections\" array');\n } else {\n for (let si = 0; si < d.sections.length; si++) {\n const section = d.sections[si];\n if (!section || typeof section !== 'object') {\n errors.push(`sections[${si}]: must be an object`);\n continue;\n }\n if (typeof section.id !== 'string' || !section.id) {\n errors.push(`sections[${si}]: missing or invalid \"id\"`);\n }\n if (!Array.isArray(section.columns)) {\n errors.push(`sections[${si}]: must have a \"columns\" array`);\n } else {\n for (let ci = 0; ci < section.columns.length; ci++) {\n const col = section.columns[ci];\n if (!col || typeof col !== 'object') {\n errors.push(`sections[${si}].columns[${ci}]: must be an object`);\n continue;\n }\n if (typeof col.id !== 'string' || !col.id) {\n errors.push(`sections[${si}].columns[${ci}]: missing or invalid \"id\"`);\n }\n if (!Array.isArray(col.blocks)) {\n errors.push(`sections[${si}].columns[${ci}]: must have a \"blocks\" array`);\n } else {\n for (let bi = 0; bi < col.blocks.length; bi++) {\n const block = col.blocks[bi];\n if (!block || typeof block !== 'object') {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: must be an object`);\n continue;\n }\n if (typeof block.id !== 'string' || !block.id) {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: missing or invalid \"id\"`);\n }\n if (!isValidBlockType(block.type as string)) {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: invalid block type \"${block.type}\"`);\n }\n if (!block.properties || typeof block.properties !== 'object') {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: missing \"properties\" object`);\n }\n }\n }\n }\n }\n }\n }\n\n if (d.globalStyles !== undefined && d.globalStyles !== null) {\n const gs = d.globalStyles as Record<string, unknown>;\n if (typeof gs !== 'object') {\n errors.push('globalStyles must be an object');\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n/**\n * Sanitize and coerce raw data into a valid EmailTemplate.\n * Fixes common issues (missing globalStyles, headMetadata, malformed sections).\n * Returns a safe-to-use template even if input is partially invalid.\n */\nexport function sanitizeTemplate(data: unknown): EmailTemplate {\n if (!data || typeof data !== 'object') {\n return { sections: [], globalStyles: { ...DEFAULT_GLOBAL_STYLES }, headMetadata: { ...DEFAULT_HEAD_METADATA, headStyles: [] } };\n }\n\n const d = data as Record<string, unknown>;\n\n // Sanitize globalStyles\n const rawGs = (d.globalStyles && typeof d.globalStyles === 'object') ? d.globalStyles as Record<string, unknown> : {};\n const globalStyles: GlobalStyles = {\n backgroundColor: typeof rawGs.backgroundColor === 'string' ? rawGs.backgroundColor : DEFAULT_GLOBAL_STYLES.backgroundColor,\n width: typeof rawGs.width === 'number' ? rawGs.width : DEFAULT_GLOBAL_STYLES.width,\n fontFamily: typeof rawGs.fontFamily === 'string' ? rawGs.fontFamily : DEFAULT_GLOBAL_STYLES.fontFamily,\n };\n\n // Sanitize headMetadata\n const rawHm = (d.headMetadata && typeof d.headMetadata === 'object') ? d.headMetadata as Record<string, unknown> : {};\n const headMetadata = {\n title: typeof rawHm.title === 'string' ? rawHm.title : '',\n previewText: typeof rawHm.previewText === 'string' ? rawHm.previewText : '',\n headStyles: Array.isArray(rawHm.headStyles) ? rawHm.headStyles.filter((s: unknown) => typeof s === 'string') as string[] : [],\n };\n\n // Sanitize sections\n const rawSections = Array.isArray(d.sections) ? d.sections : [];\n const sections: Section[] = [];\n\n for (const rawSection of rawSections) {\n if (!rawSection || typeof rawSection !== 'object') continue;\n const rs = rawSection as Record<string, unknown>;\n if (typeof rs.id !== 'string' || !rs.id) continue;\n if (!Array.isArray(rs.columns)) continue;\n\n const columns: Column[] = [];\n for (const rawCol of rs.columns) {\n if (!rawCol || typeof rawCol !== 'object') continue;\n const rc = rawCol as Record<string, unknown>;\n if (typeof rc.id !== 'string' || !rc.id) continue;\n\n const blocks: Block[] = [];\n const rawBlocks = Array.isArray(rc.blocks) ? rc.blocks : [];\n for (const rawBlock of rawBlocks) {\n if (!rawBlock || typeof rawBlock !== 'object') continue;\n const rb = rawBlock as Record<string, unknown>;\n if (typeof rb.id !== 'string' || !rb.id) continue;\n if (!isValidBlockType(rb.type as string)) continue;\n if (!rb.properties || typeof rb.properties !== 'object') continue;\n blocks.push({ id: rb.id, type: rb.type as BlockType, properties: rb.properties as Record<string, any> });\n }\n\n columns.push({\n id: rc.id,\n width: typeof rc.width === 'string' ? rc.width : '100%',\n blocks,\n });\n }\n\n const rawProps = (rs.properties && typeof rs.properties === 'object') ? rs.properties as Record<string, unknown> : {};\n sections.push({\n id: rs.id,\n columns,\n properties: {\n backgroundColor: typeof rawProps.backgroundColor === 'string' ? rawProps.backgroundColor : 'transparent',\n padding: typeof rawProps.padding === 'string' ? rawProps.padding : '20px 0',\n borderRadius: typeof rawProps.borderRadius === 'string' ? rawProps.borderRadius : '0px',\n fullWidth: typeof rawProps.fullWidth === 'boolean' ? rawProps.fullWidth : false,\n ...(typeof rawProps.backgroundImage === 'string' ? { backgroundImage: rawProps.backgroundImage } : {}),\n ...(typeof rawProps.backgroundSize === 'string' ? { backgroundSize: rawProps.backgroundSize } : {}),\n ...(typeof rawProps.backgroundRepeat === 'string' ? { backgroundRepeat: rawProps.backgroundRepeat } : {}),\n },\n });\n }\n\n return { sections, globalStyles, headMetadata };\n}\n","import type { PersistenceAdapter, EmailTemplate } from '../types';\nimport { sanitizeTemplate } from './validate';\n\n/**\n * Default persistence adapter using localStorage.\n * All operations are wrapped in try/catch to handle quota errors,\n * private browsing restrictions, and SSR environments.\n */\nexport const localStorageAdapter: PersistenceAdapter = {\n save(key: string, template: EmailTemplate): void {\n try {\n localStorage.setItem(key, JSON.stringify(template));\n } catch {\n // Silently fail — quota exceeded, private browsing, or SSR\n }\n },\n\n load(key: string): EmailTemplate | null {\n try {\n const data = localStorage.getItem(key);\n if (!data) return null;\n const parsed = JSON.parse(data);\n // Basic schema validation: must have sections array\n if (!parsed || !Array.isArray(parsed.sections)) return null;\n return sanitizeTemplate(parsed);\n } catch {\n return null;\n }\n },\n\n remove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // Silently fail\n }\n },\n};\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { Variable, VariableChipStyle } from '../types';\nimport { DEFAULT_VARIABLE_CHIP_STYLE } from '../constants';\n\ninterface UseVariablesOptions {\n predefinedVariables: Variable[];\n onVariablesChange?: (customVariables: Variable[]) => void;\n}\n\ninterface UseVariablesResult {\n customVariables: Variable[];\n allVariables: Variable[];\n variableChipStyle: VariableChipStyle;\n addCustomVariable: (variable: Variable) => void;\n removeCustomVariable: (key: string) => void;\n updateVariableChipStyle: (style: Partial<VariableChipStyle>) => void;\n}\n\nexport function useVariables({\n predefinedVariables,\n onVariablesChange,\n}: UseVariablesOptions): UseVariablesResult {\n const [customVariables, setCustomVariables] = useState<Variable[]>([]);\n const [variableChipStyle, setVariableChipStyle] = useState<VariableChipStyle>({ ...DEFAULT_VARIABLE_CHIP_STYLE });\n\n const addCustomVariable = useCallback((variable: Variable) => {\n setCustomVariables((prev) => {\n if (prev.some((v) => v.key === variable.key)) return prev;\n return [...prev, variable];\n });\n }, []);\n\n const removeCustomVariable = useCallback((key: string) => {\n setCustomVariables((prev) => prev.filter((v) => v.key !== key));\n }, []);\n\n const updateVariableChipStyle = useCallback((partial: Partial<VariableChipStyle>) => {\n setVariableChipStyle((prev) => ({ ...prev, ...partial }));\n }, []);\n\n // Merge pre-defined + custom variables\n const allVariables = useMemo(() => {\n const merged = [...predefinedVariables];\n for (const cv of customVariables) {\n if (!merged.some((v) => v.key === cv.key)) {\n merged.push(cv);\n }\n }\n return merged;\n }, [predefinedVariables, customVariables]);\n\n // Notify parent when custom variables change\n const onVariablesChangeRef = useRef(onVariablesChange);\n onVariablesChangeRef.current = onVariablesChange;\n const isFirstVariablesRender = useRef(true);\n useEffect(() => {\n if (isFirstVariablesRender.current) {\n isFirstVariablesRender.current = false;\n return;\n }\n onVariablesChangeRef.current?.(customVariables);\n }, [customVariables]);\n\n return {\n customVariables,\n allVariables,\n variableChipStyle,\n addCustomVariable,\n removeCustomVariable,\n updateVariableChipStyle,\n };\n}\n","import { useCallback, useRef } from 'react';\nimport type { Editor } from '@tiptap/core';\n\ninterface UseTipTapTrackingResult {\n setActiveEditor: (editor: Editor | null) => void;\n getActiveEditor: () => Editor | null;\n insertVariable: (key: string) => boolean;\n}\n\nexport function useTipTapTracking(): UseTipTapTrackingResult {\n const activeEditorRef = useRef<Editor | null>(null);\n\n const setActiveEditor = useCallback((editor: Editor | null) => {\n activeEditorRef.current = editor;\n }, []);\n\n const getActiveEditor = useCallback(() => {\n return activeEditorRef.current;\n }, []);\n\n const insertVariable = useCallback((key: string): boolean => {\n const editor = activeEditorRef.current;\n if (!editor || editor.isDestroyed) return false;\n editor.chain().focus().insertVariable(key).run();\n return true;\n }, []);\n\n return { setActiveEditor, getActiveEditor, insertVariable };\n}\n","import { useCallback, useEffect, useRef } from 'react';\nimport type { EmailTemplate, PersistenceAdapter } from '../types';\nimport { localStorageAdapter } from '../utils/persistence';\n\ninterface UsePersistenceOptions {\n template: EmailTemplate;\n persistenceKey?: string;\n persistenceAdapter?: PersistenceAdapter;\n}\n\ninterface UsePersistenceResult {\n clearPersisted: () => void;\n}\n\nexport function usePersistence({\n template,\n persistenceKey,\n persistenceAdapter,\n}: UsePersistenceOptions): UsePersistenceResult {\n const persistenceKeyRef = useRef(persistenceKey);\n persistenceKeyRef.current = persistenceKey;\n const persistenceAdapterRef = useRef(persistenceAdapter);\n persistenceAdapterRef.current = persistenceAdapter;\n\n // Debounced auto-save to persistence (500ms)\n const isFirstPersistRender = useRef(true);\n useEffect(() => {\n if (isFirstPersistRender.current) {\n isFirstPersistRender.current = false;\n return;\n }\n const key = persistenceKeyRef.current;\n if (!key) return;\n const adapter = persistenceAdapterRef.current ?? localStorageAdapter;\n const timer = setTimeout(() => {\n adapter.save(key, template);\n }, 500);\n return () => clearTimeout(timer);\n }, [template]);\n\n const clearPersisted = useCallback(() => {\n if (!persistenceKeyRef.current) return;\n const adapter = persistenceAdapterRef.current ?? localStorageAdapter;\n adapter.remove(persistenceKeyRef.current);\n }, []);\n\n return { clearPersisted };\n}\n","import { createContext, useContext } from 'react';\nimport type { EditorAction } from '../types';\n\nexport const DispatchContext = createContext<React.Dispatch<EditorAction> | null>(null);\n\nexport function useDispatchContext(): React.Dispatch<EditorAction> {\n const ctx = useContext(DispatchContext);\n if (!ctx) {\n throw new Error('useDispatchContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { EmailTemplate, ActiveTab } from '../types';\n\nexport interface TemplateContextValue {\n template: EmailTemplate;\n isDirty: boolean;\n activeTab: ActiveTab;\n}\n\nexport const TemplateContext = createContext<TemplateContextValue | null>(null);\n\nexport function useTemplateContext(): TemplateContextValue {\n const ctx = useContext(TemplateContext);\n if (!ctx) {\n throw new Error('useTemplateContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { SelectionState } from '../types';\n\nexport const SelectionContext = createContext<SelectionState | null>(null);\n\nexport function useSelectionContext(): SelectionState {\n const ctx = useContext(SelectionContext);\n if (!ctx) {\n throw new Error('useSelectionContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { Variable, VariableChipStyle, ImageUploadAdapter } from '../types';\n\nexport interface ConfigContextValue {\n variables: Variable[];\n predefinedVariables: Variable[];\n customVariables: Variable[];\n imageUploadAdapter?: ImageUploadAdapter;\n addCustomVariable: (variable: Variable) => void;\n removeCustomVariable: (key: string) => void;\n variableChipStyle: VariableChipStyle;\n updateVariableChipStyle: (style: Partial<VariableChipStyle>) => void;\n fontFamilies: string[];\n fontSizes: string[];\n clearPersisted: () => void;\n}\n\nexport const ConfigContext = createContext<ConfigContextValue | null>(null);\n\nexport function useConfigContext(): ConfigContextValue {\n const ctx = useContext(ConfigContext);\n if (!ctx) {\n throw new Error('useConfigContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { Editor } from '@tiptap/core';\n\nexport interface MethodsContextValue {\n setActiveEditor: (editor: Editor | null) => void;\n getActiveEditor: () => Editor | null;\n insertVariable: (key: string) => boolean;\n}\n\nexport const MethodsContext = createContext<MethodsContextValue | null>(null);\n\nexport function useMethodsContext(): MethodsContextValue {\n const ctx = useContext(MethodsContext);\n if (!ctx) throw new Error('useMethodsContext must be used within an EditorProvider');\n return ctx;\n}\n","import { createContext, useContext } from 'react';\n\nexport interface HistoryContextValue {\n canUndo: boolean;\n canRedo: boolean;\n}\n\nexport const HistoryContext = createContext<HistoryContextValue | null>(null);\n\nexport function useHistoryContext(): HistoryContextValue {\n const ctx = useContext(HistoryContext);\n if (!ctx) throw new Error('useHistoryContext must be used within an EditorProvider');\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { BlockIndex } from '../utils/blockIndex';\n\nexport const BlockIndexContext = createContext<BlockIndex | null>(null);\n\nexport function useBlockIndexContext(): BlockIndex {\n const ctx = useContext(BlockIndexContext);\n if (!ctx) throw new Error('useBlockIndexContext must be used within an EditorProvider');\n return ctx;\n}\n","import { nanoid } from 'nanoid';\n\nexport function generateId(prefix?: string): string {\n const id = nanoid(10);\n return prefix ? `${prefix}_${id}` : id;\n}\n\nexport function generateBlockId(): string {\n return generateId('blk');\n}\n\nexport function generateSectionId(): string {\n return generateId('sec');\n}\n\nexport function generateColumnId(): string {\n return generateId('col');\n}\n","import type { Block, BlockType, Section } from '../types';\nimport { DEFAULT_BLOCK_PROPERTIES, DEFAULT_SECTION_PROPERTIES } from '../constants';\nimport { generateBlockId, generateSectionId, generateColumnId } from './id';\n\n/** Deep-clone a block with a fresh ID */\nexport function cloneBlock(block: Block): Block {\n return {\n ...block,\n id: generateBlockId(),\n properties: JSON.parse(JSON.stringify(block.properties)),\n };\n}\n\n/** Deep-clone a section with fresh IDs for the section, all columns, and all blocks */\nexport function cloneSection(section: Section): Section {\n return {\n id: generateSectionId(),\n properties: JSON.parse(JSON.stringify(section.properties)),\n columns: section.columns.map((col) => ({\n id: generateColumnId(),\n width: col.width,\n blocks: col.blocks.map(cloneBlock),\n })),\n };\n}\n\n/** Create a new block with default properties */\nexport function createBlock<T extends BlockType>(type: T): Block<T> {\n return {\n id: generateBlockId(),\n type,\n properties: JSON.parse(JSON.stringify(DEFAULT_BLOCK_PROPERTIES[type])),\n };\n}\n\n/** Create a new section with given column widths (defaults to single 100% column) */\nexport function createSection(widths: string[] = ['100%']): Section {\n return {\n id: generateSectionId(),\n columns: widths.map((width) => ({\n id: generateColumnId(),\n width,\n blocks: [],\n })),\n properties: { ...DEFAULT_SECTION_PROPERTIES },\n };\n}\n\n/** Create a section pre-populated with a block */\nexport function createSectionWithBlock(type: BlockType): Section {\n const section = createSection();\n section.columns[0].blocks.push(createBlock(type));\n return section;\n}\n","import type { Section } from '../types';\n\nexport type BlockIndex = Map<string, { sectionId: string; columnId: string }>;\n\n/**\n * Build a lookup index from blockId → { sectionId, columnId } for O(1) block location.\n */\nexport function buildBlockIndex(sections: Section[]): BlockIndex {\n const index: BlockIndex = new Map();\n for (const section of sections) {\n for (const column of section.columns) {\n for (const block of column.blocks) {\n index.set(block.id, { sectionId: section.id, columnId: column.id });\n }\n }\n }\n return index;\n}\n","import type {\n EditorState,\n EditorAction,\n EmailTemplate,\n Block,\n SelectionState,\n} from '../types';\nimport { DEFAULT_GLOBAL_STYLES, DEFAULT_HEAD_METADATA, MAX_HISTORY_SIZE } from '../constants';\nimport { cloneBlock, cloneSection } from '../utils/factory';\nimport { buildBlockIndex } from '../utils/blockIndex';\nimport { sanitizeTemplate } from '../utils/validate';\n\n// ---- Initial State ----\n\nexport const INITIAL_SELECTION: SelectionState = {\n sectionId: null,\n columnId: null,\n blockId: null,\n};\n\nexport function createInitialState(template?: EmailTemplate): EditorState {\n const t = template ?? { sections: [], globalStyles: { ...DEFAULT_GLOBAL_STYLES }, headMetadata: { ...DEFAULT_HEAD_METADATA, headStyles: [] } };\n if (!t.headMetadata) {\n t.headMetadata = { ...DEFAULT_HEAD_METADATA, headStyles: [] };\n }\n return {\n template: t,\n selection: INITIAL_SELECTION,\n activeTab: 'visual',\n history: [t],\n historyIndex: 0,\n isDirty: false,\n blockIndex: buildBlockIndex(t.sections),\n };\n}\n\n// ---- Helpers ----\n\nexport function pushHistory(state: EditorState, newTemplate: EmailTemplate): EditorState {\n const history = state.history.slice(0, state.historyIndex + 1);\n history.push(newTemplate);\n if (history.length > MAX_HISTORY_SIZE) {\n history.shift();\n }\n return {\n ...state,\n template: newTemplate,\n history,\n historyIndex: history.length - 1,\n isDirty: true,\n blockIndex: buildBlockIndex(newTemplate.sections),\n };\n}\n\n/** Apply template change without history push. Reuses blockIndex since non-structural changes don't affect block locations. */\nfunction applyWithoutHistory(state: EditorState, newTemplate: EmailTemplate): EditorState {\n return { ...state, template: newTemplate, isDirty: true };\n}\n\n/** Validate selection against a restored template, clearing references to blocks/sections that no longer exist. */\nfunction validateSelection(\n selection: SelectionState,\n blockIndex: Map<string, { sectionId: string; columnId: string }>,\n template: EmailTemplate,\n): SelectionState {\n if (selection.blockId) {\n const loc = blockIndex.get(selection.blockId);\n if (!loc) return INITIAL_SELECTION;\n // Reconcile sectionId/columnId with actual block location\n if (selection.sectionId !== loc.sectionId || selection.columnId !== loc.columnId) {\n return { sectionId: loc.sectionId, columnId: loc.columnId, blockId: selection.blockId };\n }\n return selection;\n }\n if (selection.sectionId) {\n if (!template.sections.some((s) => s.id === selection.sectionId)) return INITIAL_SELECTION;\n return selection;\n }\n return selection;\n}\n\n// Actions that update template without pushing to history (debounced externally)\nexport const DEBOUNCE_ELIGIBLE: ReadonlySet<string> = new Set([\n 'UPDATE_BLOCK',\n 'UPDATE_SECTION',\n 'UPDATE_GLOBAL_STYLES',\n 'UPDATE_HEAD_METADATA',\n]);\n\n// ---- Reducer ----\n\nexport function editorReducer(state: EditorState, action: EditorAction): EditorState {\n switch (action.type) {\n case 'SET_TEMPLATE': {\n const sanitized = sanitizeTemplate(action.payload);\n const newState = pushHistory(state, sanitized);\n return {\n ...newState,\n selection: validateSelection(state.selection, newState.blockIndex, sanitized),\n };\n }\n\n case 'ADD_SECTION': {\n const { section, index } = action.payload;\n const sections = [...state.template.sections];\n const insertAt = index ?? sections.length;\n sections.splice(insertAt, 0, section);\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'REMOVE_SECTION': {\n const sections = state.template.sections.filter(\n (s) => s.id !== action.payload.sectionId,\n );\n const newState = pushHistory(state, { ...state.template, sections });\n if (state.selection.sectionId === action.payload.sectionId) {\n return { ...newState, selection: INITIAL_SELECTION };\n }\n return newState;\n }\n\n case 'MOVE_SECTION': {\n const { sectionId, toIndex } = action.payload;\n const sections = [...state.template.sections];\n const fromIndex = sections.findIndex((s) => s.id === sectionId);\n if (fromIndex === -1) return state;\n const [moved] = sections.splice(fromIndex, 1);\n sections.splice(toIndex, 0, moved);\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'UPDATE_SECTION': {\n const { sectionId, properties } = action.payload;\n const sections = state.template.sections.map((s) =>\n s.id === sectionId\n ? { ...s, properties: { ...s.properties, ...properties } }\n : s,\n );\n return applyWithoutHistory(state, { ...state.template, sections });\n }\n\n case 'ADD_BLOCK': {\n const { sectionId, columnId, block, index } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n const blocks = [...col.blocks];\n const insertAt = index ?? blocks.length;\n blocks.splice(insertAt, 0, block);\n return { ...col, blocks };\n }),\n };\n });\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'REMOVE_BLOCK': {\n const { sectionId, columnId, blockId } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n return { ...col, blocks: col.blocks.filter((b) => b.id !== blockId) };\n }),\n };\n });\n const newState = pushHistory(state, { ...state.template, sections });\n if (state.selection.blockId === blockId) {\n return { ...newState, selection: INITIAL_SELECTION };\n }\n return newState;\n }\n\n case 'MOVE_BLOCK': {\n const { fromSectionId, fromColumnId, blockId, toSectionId, toColumnId, toIndex: rawToIndex } =\n action.payload;\n let movedBlock: Block | null = null;\n let toIndex = rawToIndex;\n if (fromSectionId === toSectionId && fromColumnId === toColumnId) {\n const srcSection = state.template.sections.find((s) => s.id === fromSectionId);\n const srcCol = srcSection?.columns.find((c) => c.id === fromColumnId);\n if (srcCol) {\n const fromIdx = srcCol.blocks.findIndex((b) => b.id === blockId);\n if (fromIdx >= 0 && fromIdx < toIndex) {\n toIndex--;\n }\n }\n }\n let sections = state.template.sections.map((section) => {\n if (section.id !== fromSectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== fromColumnId) return col;\n const block = col.blocks.find((b) => b.id === blockId);\n if (block) movedBlock = block;\n return { ...col, blocks: col.blocks.filter((b) => b.id !== blockId) };\n }),\n };\n });\n if (!movedBlock) return state;\n sections = sections.map((section) => {\n if (section.id !== toSectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== toColumnId) return col;\n const blocks = [...col.blocks];\n blocks.splice(toIndex, 0, movedBlock!);\n return { ...col, blocks };\n }),\n };\n });\n const newState = pushHistory(state, { ...state.template, sections });\n // Update selection to the new location if the moved block was selected\n if (state.selection.blockId === blockId) {\n return { ...newState, selection: { sectionId: toSectionId, columnId: toColumnId, blockId } };\n }\n return newState;\n }\n\n case 'UPDATE_BLOCK': {\n const { blockId, properties } = action.payload;\n const loc = state.blockIndex.get(blockId);\n if (!loc) return state;\n const sections = state.template.sections.map((section) => {\n if (section.id !== loc.sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== loc.columnId) return col;\n return {\n ...col,\n blocks: col.blocks.map((b) =>\n b.id === blockId\n ? { ...b, properties: { ...b.properties, ...properties } }\n : b,\n ),\n };\n }),\n };\n });\n return { ...state, template: { ...state.template, sections }, isDirty: true };\n }\n\n case 'SELECT_BLOCK': {\n return {\n ...state,\n selection: action.payload ?? INITIAL_SELECTION,\n };\n }\n\n case 'SELECT_SECTION': {\n return {\n ...state,\n selection: action.payload\n ? { sectionId: action.payload.sectionId, columnId: null, blockId: null }\n : INITIAL_SELECTION,\n };\n }\n\n case 'ADD_BLOCK_AND_SELECT': {\n const { sectionId, columnId, block, index } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n const blocks = [...col.blocks];\n const insertAt = index ?? blocks.length;\n blocks.splice(insertAt, 0, block);\n return { ...col, blocks };\n }),\n };\n });\n const newState = pushHistory(state, { ...state.template, sections });\n return {\n ...newState,\n selection: { sectionId, columnId, blockId: block.id },\n };\n }\n\n case 'ADD_SECTION_WITH_BLOCK': {\n const { section, block, index } = action.payload;\n const sections = [...state.template.sections];\n const insertAt = index ?? sections.length;\n const sectionWithBlock = {\n ...section,\n columns: section.columns.map((col, i) =>\n i === 0 ? { ...col, blocks: [...col.blocks, block] } : col,\n ),\n };\n sections.splice(insertAt, 0, sectionWithBlock);\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'DESELECT_ALL': {\n return {\n ...state,\n selection: INITIAL_SELECTION,\n };\n }\n\n case 'SET_ACTIVE_TAB': {\n return { ...state, activeTab: action.payload };\n }\n\n case 'UPDATE_GLOBAL_STYLES': {\n const globalStyles = { ...state.template.globalStyles, ...action.payload };\n return applyWithoutHistory(state, { ...state.template, globalStyles });\n }\n\n case 'UPDATE_HEAD_METADATA': {\n const current = state.template.headMetadata ?? { ...DEFAULT_HEAD_METADATA, headStyles: [] };\n const headMetadata = { ...current, ...action.payload };\n return applyWithoutHistory(state, { ...state.template, headMetadata });\n }\n\n case 'DUPLICATE_BLOCK': {\n const { sectionId, columnId, blockId } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n const blockIndex = col.blocks.findIndex((b) => b.id === blockId);\n if (blockIndex === -1) return col;\n const blocks = [...col.blocks];\n blocks.splice(blockIndex + 1, 0, cloneBlock(col.blocks[blockIndex]));\n return { ...col, blocks };\n }),\n };\n });\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'DUPLICATE_SECTION': {\n const { sectionId } = action.payload;\n const sections = [...state.template.sections];\n const sectionIndex = sections.findIndex((s) => s.id === sectionId);\n if (sectionIndex === -1) return state;\n sections.splice(sectionIndex + 1, 0, cloneSection(sections[sectionIndex]));\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'UNDO': {\n if (state.historyIndex <= 0) return state;\n const newIndex = state.historyIndex - 1;\n const restored = state.history[newIndex];\n const newBlockIndex = buildBlockIndex(restored.sections);\n return {\n ...state,\n template: restored,\n historyIndex: newIndex,\n blockIndex: newBlockIndex,\n selection: validateSelection(state.selection, newBlockIndex, restored),\n };\n }\n\n case 'REDO': {\n if (state.historyIndex >= state.history.length - 1) return state;\n const newIndex = state.historyIndex + 1;\n const restored = state.history[newIndex];\n const newBlockIndex = buildBlockIndex(restored.sections);\n return {\n ...state,\n template: restored,\n historyIndex: newIndex,\n blockIndex: newBlockIndex,\n selection: validateSelection(state.selection, newBlockIndex, restored),\n };\n }\n\n case 'PUSH_HISTORY': {\n if (state.template === state.history[state.historyIndex]) return state;\n return pushHistory(state, state.template);\n }\n\n default:\n return state;\n }\n}\n","import { useMemo } from 'react';\nimport type { EditorAction, Block, Section } from '../types';\nimport { useTemplateContext } from './TemplateContext';\nimport { useSelectionContext } from './SelectionContext';\nimport { useDispatchContext } from './DispatchContext';\nimport { useConfigContext } from './ConfigContext';\nimport { useMethodsContext } from './MethodsContext';\nimport { useHistoryContext } from './HistoryContext';\nimport { useBlockIndexContext } from './BlockIndexContext';\n\n// ---- Primary Hooks ----\n\n/** @deprecated Use focused hooks (useTemplateContext, useSelectionContext, etc.) instead */\nexport function useEditorState() {\n const tmpl = useTemplateContext();\n const sel = useSelectionContext();\n const { canUndo, canRedo } = useHistoryContext();\n return useMemo(\n () => ({\n template: tmpl.template,\n isDirty: tmpl.isDirty,\n activeTab: tmpl.activeTab,\n selection: sel,\n canUndo,\n canRedo,\n }),\n [tmpl, sel, canUndo, canRedo],\n );\n}\n\nexport function useEditorDispatch(): React.Dispatch<EditorAction> {\n return useDispatchContext();\n}\n\n// ---- Derived Selection Hooks ----\n\nexport function useSelectedBlock(): Block | null {\n const { template } = useTemplateContext();\n const { blockId } = useSelectionContext();\n const blockIndex = useBlockIndexContext();\n return useMemo(() => {\n if (!blockId) return null;\n const loc = blockIndex.get(blockId);\n if (!loc) return null;\n const section = template.sections.find((s) => s.id === loc.sectionId);\n if (!section) return null;\n const column = section.columns.find((c) => c.id === loc.columnId);\n if (!column) return null;\n return column.blocks.find((b) => b.id === blockId) ?? null;\n }, [template.sections, blockId, blockIndex]);\n}\n\nexport function useSelectedSection(): Section | null {\n const { template } = useTemplateContext();\n const { sectionId } = useSelectionContext();\n return useMemo(() => {\n if (!sectionId) return null;\n return template.sections.find((s) => s.id === sectionId) ?? null;\n }, [template.sections, sectionId]);\n}\n\n// ---- Convenience Hooks ----\n\nexport function useEditorVariables() {\n const { variables, predefinedVariables, customVariables, addCustomVariable, removeCustomVariable, variableChipStyle, updateVariableChipStyle } = useConfigContext();\n const { insertVariable } = useMethodsContext();\n return { variables, predefinedVariables, customVariables, addCustomVariable, removeCustomVariable, insertVariable, variableChipStyle, updateVariableChipStyle };\n}\n\nexport function useEditorFonts() {\n const { fontFamilies, fontSizes } = useConfigContext();\n return { fontFamilies, fontSizes };\n}\n\nexport function useImageAdapter() {\n const { imageUploadAdapter } = useConfigContext();\n return { imageUploadAdapter };\n}\n","import React, { Component, type ReactNode, type ErrorInfo } from 'react';\nimport styles from '../styles/error-boundary.module.css';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n this.props.onError?.(error, errorInfo);\n }\n\n private handleRetry = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) return this.props.fallback;\n return (\n <div\n className={`ee-error-boundary ${styles.errorBoundary}`}\n role=\"alert\"\n >\n <strong className=\"ee-error-title\">Something went wrong</strong>\n <p className={`ee-error-message ${styles.errorMessage}`}>\n {this.state.error?.message || 'An unexpected error occurred.'}\n </p>\n <button\n className={`ee-error-retry ${styles.retryBtn}`}\n onClick={this.handleRetry}\n aria-label=\"Retry\"\n >\n Try Again\n </button>\n </div>\n );\n }\n return this.props.children;\n }\n}\n",".errorBoundary {\n padding: var(--ee-space-lg);\n margin: var(--ee-space-sm);\n background: var(--ee-color-danger-light);\n border: 1px solid var(--ee-color-danger-border);\n border-radius: var(--ee-border-radius);\n color: var(--ee-color-danger);\n font-size: var(--ee-font-size-md);\n}\n\n.errorMessage {\n margin: var(--ee-space-sm) 0 0;\n color: var(--ee-color-danger-hover);\n}\n\n.retryBtn {\n margin-top: var(--ee-space-md);\n padding: var(--ee-space-sm) var(--ee-space-lg);\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n border: none;\n border-radius: var(--ee-border-radius-sm);\n font-size: var(--ee-font-size-sm);\n cursor: pointer;\n transition: background var(--ee-transition-fast);\n}\n\n.retryBtn:hover {\n background: var(--ee-color-danger-hover);\n}\n","import { useEffect, useRef, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport styles from '../styles/confirm-dialog.module.css';\n\ninterface ConfirmDialogProps {\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function ConfirmDialog({\n title,\n message,\n confirmLabel = 'Remove',\n cancelLabel = 'Cancel',\n onConfirm,\n onCancel,\n}: ConfirmDialogProps) {\n const cancelRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCancel();\n return;\n }\n\n // Focus trap: cycle Tab/Shift+Tab within dialog\n if (e.key === 'Tab' && dialogRef.current) {\n const focusable = dialogRef.current.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n },\n [onCancel],\n );\n\n useEffect(() => {\n document.addEventListener('keydown', handleKeyDown);\n cancelRef.current?.focus();\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [handleKeyDown]);\n\n return createPortal(\n <div className={`ee-dialog-overlay ${styles.overlay}`} onClick={onCancel} role=\"dialog\" aria-modal=\"true\" aria-label={title}>\n <div ref={dialogRef} className={`ee-dialog ${styles.dialog}`} onClick={(e) => e.stopPropagation()}>\n <h3 className={`ee-dialog-title ${styles.title}`}>{title}</h3>\n <p className={`ee-dialog-message ${styles.message}`}>{message}</p>\n <div className={`ee-dialog-actions ${styles.actions}`}>\n <button ref={cancelRef} className={`ee-dialog-cancel ${styles.btnCancel}`} onClick={onCancel}>\n {cancelLabel}\n </button>\n <button className={`ee-dialog-confirm ${styles.btnConfirm}`} onClick={onConfirm}>\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n",".overlay {\n position: fixed;\n inset: 0;\n background: var(--ee-overlay-backdrop);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: var(--ee-z-modal);\n animation: fadeIn var(--ee-transition-fast);\n}\n\n.dialog {\n background: var(--ee-bg-panel);\n border-radius: var(--ee-border-radius-lg);\n box-shadow: var(--ee-shadow-lg);\n padding: var(--ee-space-xl);\n min-width: 320px;\n max-width: 400px;\n animation: slideUp var(--ee-transition-normal);\n font-family: var(--ee-font-family);\n}\n\n.title {\n margin: 0 0 var(--ee-space-sm) 0;\n font-size: var(--ee-font-size-lg);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-primary);\n}\n\n.message {\n margin: 0 0 var(--ee-space-xl) 0;\n font-size: var(--ee-font-size-base);\n color: var(--ee-text-secondary);\n line-height: 1.5;\n}\n\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--ee-space-sm);\n}\n\n.btnCancel {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-panel);\n color: var(--ee-text-primary);\n font-size: var(--ee-font-size-base);\n font-family: var(--ee-font-family);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.btnCancel:hover {\n background: var(--ee-bg-hover);\n border-color: var(--ee-border-color-strong);\n}\n\n.btnConfirm {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n border: 1px solid var(--ee-color-danger);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n font-size: var(--ee-font-size-base);\n font-family: var(--ee-font-family);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.btnConfirm:hover {\n background: var(--ee-color-danger-hover);\n border-color: var(--ee-color-danger-hover);\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n","import React, { useCallback, useRef, useState, useEffect } from 'react';\n\nimport { useTemplateContext, useEditorDispatch, useHistoryContext } from '../../context/EditorContext';\nimport { generateMJML } from '../../mjml/generator';\nimport { compileMJMLToHTML } from '../../mjml/compiler';\nimport { parseMJML } from '../../mjml/parser';\nimport type { ActiveTab, EmailTemplate } from '../../types';\nimport styles from '../../styles/toolbar.module.css';\nimport editorStyles from '../../styles/editor.module.css';\n\ninterface ToolbarProps {\n sidebarOpen?: boolean;\n propertiesOpen?: boolean;\n onToggleSidebar?: () => void;\n onToggleProperties?: () => void;\n}\n\n/**\n * Inner component that subscribes only to activeTab (not the full template).\n * Template is accessed via ref for export operations to avoid re-renders on every edit.\n */\nexport const Toolbar = React.memo(function Toolbar({ sidebarOpen, propertiesOpen, onToggleSidebar, onToggleProperties }: ToolbarProps) {\n const { template, activeTab } = useTemplateContext();\n const { canUndo, canRedo } = useHistoryContext();\n const dispatch = useEditorDispatch();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [exportOpen, setExportOpen] = useState(false);\n\n // Keep a ref to the current template so export callbacks don't need template as a dependency.\n // Toolbar still re-renders on template changes (due to TemplateContext), but the export\n // callbacks remain stable (empty deps), reducing unnecessary child re-renders.\n const templateRef = useRef<EmailTemplate>(template);\n templateRef.current = template;\n\n // Close export dropdown when clicking outside\n useEffect(() => {\n if (!exportOpen) return;\n const handleClick = () => setExportOpen(false);\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }, [exportOpen]);\n const handleTabChange = useCallback(\n (tab: ActiveTab) => {\n dispatch({ type: 'SET_ACTIVE_TAB', payload: tab });\n },\n [dispatch],\n );\n\n const handleUndo = useCallback(() => {\n dispatch({ type: 'UNDO' });\n }, [dispatch]);\n\n const handleRedo = useCallback(() => {\n dispatch({ type: 'REDO' });\n }, [dispatch]);\n\n const handleExportMJML = useCallback(() => {\n const mjml = generateMJML(templateRef.current!);\n const blob = new Blob([mjml], { type: 'text/xml' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'template.mjml';\n a.click();\n URL.revokeObjectURL(url);\n }, []);\n\n const handleExportHTML = useCallback(async () => {\n const mjml = generateMJML(templateRef.current!);\n const result = await compileMJMLToHTML(mjml);\n const blob = new Blob([result.html], { type: 'text/html' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'template.html';\n a.click();\n URL.revokeObjectURL(url);\n }, []);\n\n const handleExportPDF = useCallback(async () => {\n const mjml = generateMJML(templateRef.current!);\n const result = await compileMJMLToHTML(mjml);\n const printStyles = `\n <style>\n @page { margin: 0; size: auto; }\n @media print {\n html, body { margin: 0; padding: 0; }\n }\n </style>\n `;\n const htmlWithPrintStyles = result.html.replace(\n '</head>',\n `${printStyles}</head>`,\n );\n const iframe = document.createElement('iframe');\n iframe.style.position = 'fixed';\n iframe.style.left = '-9999px';\n document.body.appendChild(iframe);\n const doc = iframe.contentDocument!;\n doc.open();\n doc.write(htmlWithPrintStyles);\n doc.close();\n iframe.contentWindow!.print();\n setTimeout(() => document.body.removeChild(iframe), 1000);\n }, []);\n\n const handleImportMJML = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (event) => {\n try {\n const content = event.target?.result as string;\n const template = parseMJML(content);\n dispatch({ type: 'SET_TEMPLATE', payload: template });\n } catch (err) {\n console.error('Failed to parse MJML:', err);\n }\n };\n reader.readAsText(file);\n // Reset input\n e.target.value = '';\n },\n [dispatch],\n );\n\n return (\n <div className={`ee-toolbar ${styles.toolbar}`} role=\"toolbar\" aria-label=\"Editor toolbar\">\n <div className={`ee-toolbar-history ${styles.toolbarGroup}`} role=\"group\" aria-label=\"History\">\n <button\n className={`ee-toolbar-undo ${styles.toolbarBtn}`}\n onClick={handleUndo}\n disabled={!canUndo}\n title=\"Undo (Ctrl+Z)\"\n aria-label=\"Undo\"\n >\n Undo\n </button>\n <button\n className={`ee-toolbar-redo ${styles.toolbarBtn}`}\n onClick={handleRedo}\n disabled={!canRedo}\n title=\"Redo (Ctrl+Shift+Z)\"\n aria-label=\"Redo\"\n >\n Redo\n </button>\n </div>\n\n {/* Panel toggles — visible only on narrow screens via CSS */}\n <div className={editorStyles.panelToggle}>\n <button\n className={`ee-toolbar-toggle-sidebar ${styles.panelToggleBtn} ${sidebarOpen ? styles.panelToggleBtnActive : ''}`}\n onClick={onToggleSidebar}\n aria-label=\"Toggle sidebar\"\n aria-pressed={sidebarOpen}\n title=\"Toggle sidebar\"\n >\n ☰\n </button>\n <button\n className={`ee-toolbar-toggle-properties ${styles.panelToggleBtn} ${propertiesOpen ? styles.panelToggleBtnActive : ''}`}\n onClick={onToggleProperties}\n aria-label=\"Toggle properties\"\n aria-pressed={propertiesOpen}\n title=\"Toggle properties\"\n >\n ⚙\n </button>\n </div>\n\n <div className={`ee-toolbar-separator ${styles.toolbarSeparator}`} role=\"separator\" />\n\n <div className={`ee-toolbar-tabs ${styles.tabBar}`} role=\"tablist\" aria-label=\"Editor views\">\n {(['visual', 'source', 'preview'] as ActiveTab[]).map((tab) => (\n <button\n key={tab}\n role=\"tab\"\n aria-selected={activeTab === tab}\n className={`ee-toolbar-tab ee-toolbar-tab--${tab} ${styles.tabBtn} ${activeTab === tab ? styles.tabBtnActive : ''}`}\n onClick={() => handleTabChange(tab)}\n >\n {tab.charAt(0).toUpperCase() + tab.slice(1)}\n </button>\n ))}\n </div>\n\n <div className={styles.toolbarSpacer} />\n\n <div className={`ee-toolbar-io ${styles.toolbarGroup}`} role=\"group\" aria-label=\"Import/Export\">\n <button\n className={`ee-toolbar-import ${styles.toolbarBtn}`}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Import MJML file\"\n >\n Import\n </button>\n <div className={`ee-toolbar-export ${styles.exportWrapper}`}>\n <button\n className={`ee-toolbar-export-btn ${styles.toolbarBtn}`}\n onClick={(e) => { e.stopPropagation(); setExportOpen((prev) => !prev); }}\n aria-label=\"Export template\"\n aria-expanded={exportOpen}\n aria-haspopup=\"true\"\n >\n Export\n </button>\n {exportOpen && (\n <div className={`ee-toolbar-export-dropdown ${styles.exportDropdown}`} role=\"menu\">\n <button className={`ee-toolbar-export-mjml ${styles.exportDropdownItem}`} onClick={handleExportMJML} role=\"menuitem\">MJML</button>\n <button className={`ee-toolbar-export-html ${styles.exportDropdownItem}`} onClick={handleExportHTML} role=\"menuitem\">HTML</button>\n <button className={`ee-toolbar-export-pdf ${styles.exportDropdownItem}`} onClick={handleExportPDF} role=\"menuitem\">PDF</button>\n </div>\n )}\n </div>\n </div>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".mjml,.xml,.txt\"\n onChange={handleImportMJML}\n style={{ display: 'none' }}\n aria-hidden=\"true\"\n />\n </div>\n );\n});\n","const ALLOWED_TAGS = new Set([\n 'p', 'br', 'b', 'strong', 'i', 'em', 'u', 'a', 'span',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li', 'blockquote',\n 'table', 'thead', 'tbody', 'tr', 'td', 'th',\n 'img', 'hr', 'div', 'sup', 'sub',\n]);\n\nconst ALLOWED_ATTRIBUTES = new Set([\n 'href', 'src', 'alt', 'title', 'style', 'class',\n 'width', 'height', 'target', 'rel',\n 'align', 'valign', 'bgcolor', 'border',\n 'cellpadding', 'cellspacing', 'colspan', 'rowspan',\n]);\n\n/** Patterns that indicate dangerous CSS values */\nconst DANGEROUS_CSS_PATTERN = /expression\\s*\\(|javascript\\s*:|url\\s*\\(\\s*['\"]?\\s*(?:javascript|data|vbscript)\\s*:/i;\n\n/** Allowed CSS properties for email content */\nconst ALLOWED_CSS_PROPERTIES = new Set([\n 'color', 'background-color', 'background', 'font-family', 'font-size',\n 'font-weight', 'font-style', 'text-decoration', 'text-align', 'text-transform',\n 'line-height', 'letter-spacing', 'word-spacing',\n 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'border', 'border-top', 'border-right', 'border-bottom', 'border-left',\n 'border-color', 'border-width', 'border-style', 'border-radius',\n 'width', 'max-width', 'min-width', 'height', 'max-height', 'min-height',\n 'display', 'vertical-align', 'white-space', 'overflow',\n 'opacity', 'visibility',\n 'border-collapse', 'border-spacing', 'table-layout',\n]);\n\n/**\n * Sanitize a CSS style string by removing dangerous properties and values.\n * Returns the sanitized style string, or empty string if nothing is safe.\n */\nexport function sanitizeStyle(style: string): string {\n // Quick reject: check for dangerous patterns in the whole string\n if (DANGEROUS_CSS_PATTERN.test(style)) {\n // Parse individual declarations and filter\n return filterStyleDeclarations(style);\n }\n return filterStyleDeclarations(style);\n}\n\nfunction filterStyleDeclarations(style: string): string {\n const declarations = style.split(';');\n const safe: string[] = [];\n\n for (const decl of declarations) {\n const trimmed = decl.trim();\n if (!trimmed) continue;\n\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx === -1) continue;\n\n const property = trimmed.slice(0, colonIdx).trim().toLowerCase();\n const value = trimmed.slice(colonIdx + 1).trim();\n\n // Only allow known safe CSS properties\n if (!ALLOWED_CSS_PROPERTIES.has(property)) continue;\n\n // Reject dangerous values\n if (DANGEROUS_CSS_PATTERN.test(value)) continue;\n\n // Reject url() in values except for safe schemes\n if (/url\\s*\\(/i.test(value)) continue;\n\n safe.push(`${property}: ${value}`);\n }\n\n return safe.join('; ');\n}\n\nexport function sanitizeHTML(html: string): string {\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n sanitizeNode(doc.body);\n return doc.body.innerHTML;\n}\n\nfunction sanitizeNode(node: Node): void {\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType === Node.ELEMENT_NODE) {\n const element = child as Element;\n const tagName = element.tagName.toLowerCase();\n\n if (!ALLOWED_TAGS.has(tagName)) {\n // Replace disallowed elements with their text content\n const text = document.createTextNode(element.textContent ?? '');\n node.replaceChild(text, child);\n continue;\n }\n\n // Remove disallowed attributes\n const attributes = Array.from(element.attributes);\n for (const attr of attributes) {\n if (!ALLOWED_ATTRIBUTES.has(attr.name.toLowerCase())) {\n element.removeAttribute(attr.name);\n }\n }\n\n // Sanitize style attribute\n if (element.hasAttribute('style')) {\n const rawStyle = element.getAttribute('style') ?? '';\n const safeStyle = sanitizeStyle(rawStyle);\n if (safeStyle) {\n element.setAttribute('style', safeStyle);\n } else {\n element.removeAttribute('style');\n }\n }\n\n // Sanitize href to prevent javascript: URLs\n if (element.hasAttribute('href')) {\n const href = element.getAttribute('href') ?? '';\n if (href.toLowerCase().startsWith('javascript:') || href.toLowerCase().startsWith('data:')) {\n element.setAttribute('href', '#');\n }\n }\n\n // Sanitize src to prevent javascript: and data: URLs\n if (element.hasAttribute('src')) {\n const src = element.getAttribute('src') ?? '';\n if (src.toLowerCase().startsWith('javascript:') || src.toLowerCase().startsWith('data:')) {\n element.removeAttribute('src');\n }\n }\n\n sanitizeNode(child);\n }\n }\n}\n\nexport function escapeHTML(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\nconst SAFE_URL_PATTERN = /^(https?:\\/\\/|mailto:|tel:|#|\\/)/i;\n\n/**\n * Returns true if the URL scheme is safe (http, https, mailto, tel, fragment, relative path).\n * Rejects javascript:, data:, vbscript:, and other dangerous schemes.\n */\nexport function isSafeURL(url: string): boolean {\n const trimmed = url.trim();\n if (!trimmed) return false;\n if (trimmed.startsWith('/') || trimmed.startsWith('#') || trimmed.startsWith('?')) return true;\n return SAFE_URL_PATTERN.test(trimmed);\n}\n","import type { EmailTemplate, Section, Column, Block } from '../types';\nimport { blockGeneratorRegistry, registerBlockGenerator } from '../registry';\nimport { escapeHTML, sanitizeHTML, isSafeURL } from '../utils/sanitize';\n\nexport function generateMJML(template: EmailTemplate): string {\n const { globalStyles, sections } = template;\n const lines: string[] = [];\n\n const headMetadata = template.headMetadata;\n\n lines.push('<mjml>');\n lines.push(' <mj-head>');\n if (headMetadata?.title) {\n lines.push(` <mj-title>${escapeHTML(headMetadata.title)}</mj-title>`);\n }\n if (headMetadata?.previewText) {\n lines.push(` <mj-preview>${escapeHTML(headMetadata.previewText)}</mj-preview>`);\n }\n lines.push(' <mj-attributes>');\n lines.push(` <mj-all font-family=\"${escapeAttr(globalStyles.fontFamily)}\" />`);\n lines.push(' </mj-attributes>');\n if (headMetadata?.headStyles) {\n for (const style of headMetadata.headStyles) {\n // Sanitize: strip any closing mj-style tags to prevent MJML injection\n const safe = style.replace(/<\\/?mj-/gi, '');\n lines.push(` <mj-style>${safe}</mj-style>`);\n }\n }\n lines.push(' </mj-head>');\n const bodyAttrs = buildAttrs({\n 'background-color': globalStyles.backgroundColor || undefined,\n width: `${globalStyles.width}px`,\n });\n lines.push(` <mj-body${bodyAttrs}>`);\n\n for (const section of sections) {\n lines.push(generateSection(section, ' '));\n }\n\n lines.push(' </mj-body>');\n lines.push('</mjml>');\n\n return lines.join('\\n');\n}\n\nfunction generateSection(section: Section, indent: string): string {\n // If section wraps a single hero block, output mj-hero instead of mj-section\n if (\n section.columns.length === 1 &&\n section.columns[0].blocks.length === 1 &&\n section.columns[0].blocks[0].type === 'hero'\n ) {\n return generateHeroAsSection(section.columns[0].blocks[0], indent);\n }\n\n const { properties } = section;\n const bgColor = properties.backgroundColor;\n const attrs = buildAttrs({\n 'background-color': bgColor && bgColor !== 'transparent' ? bgColor : undefined,\n padding: properties.padding,\n 'border-radius': properties.borderRadius,\n 'full-width': properties.fullWidth ? 'full-width' : undefined,\n 'background-url': properties.backgroundImage || undefined,\n 'background-size': properties.backgroundSize || undefined,\n 'background-repeat': properties.backgroundRepeat || undefined,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-section${attrs}>`);\n\n for (const column of section.columns) {\n lines.push(generateColumn(column, indent + ' '));\n }\n\n lines.push(`${indent}</mj-section>`);\n return lines.join('\\n');\n}\n\nfunction generateHeroAsSection(block: Block, indent: string): string {\n const p = block.properties;\n const heroAttrs = buildAttrs({\n 'background-color': p.backgroundColor,\n 'background-url': p.backgroundImage || undefined,\n padding: p.padding,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-hero${heroAttrs}>`);\n\n if (p.heading) {\n const headingAttrs = buildAttrs({\n align: p.align,\n color: p.headingColor,\n 'font-size': p.headingFontSize,\n 'font-weight': 'bold',\n });\n lines.push(`${indent} <mj-text${headingAttrs}><h2 style=\"margin:0\">${escapeHTML(p.heading)}</h2></mj-text>`);\n }\n\n if (p.subtext) {\n const subtextAttrs = buildAttrs({\n align: p.align,\n color: p.subtextColor,\n 'font-size': p.subtextFontSize,\n });\n lines.push(`${indent} <mj-text${subtextAttrs}>${escapeHTML(p.subtext)}</mj-text>`);\n }\n\n if (p.buttonText) {\n const buttonAttrs = buildAttrs({\n href: safeHref(p.buttonHref),\n 'background-color': p.buttonBackgroundColor,\n color: p.buttonColor,\n 'border-radius': p.buttonBorderRadius,\n align: p.align,\n });\n lines.push(`${indent} <mj-button${buttonAttrs}>${escapeHTML(p.buttonText)}</mj-button>`);\n }\n\n lines.push(`${indent}</mj-hero>`);\n return lines.join('\\n');\n}\n\nfunction generateColumn(column: Column, indent: string): string {\n const attrs = buildAttrs({ width: column.width });\n const lines: string[] = [];\n lines.push(`${indent}<mj-column${attrs}>`);\n\n for (const block of column.blocks) {\n lines.push(generateBlock(block, indent + ' '));\n }\n\n lines.push(`${indent}</mj-column>`);\n return lines.join('\\n');\n}\n\n// Register built-in generators\nregisterBlockGenerator('text', generateTextBlock);\nregisterBlockGenerator('button', generateButtonBlock);\nregisterBlockGenerator('image', generateImageBlock);\nregisterBlockGenerator('divider', generateDividerBlock);\nregisterBlockGenerator('spacer', generateSpacerBlock);\nregisterBlockGenerator('social', generateSocialBlock);\nregisterBlockGenerator('html', generateHtmlBlock);\nregisterBlockGenerator('video', generateVideoBlock);\nregisterBlockGenerator('heading', generateHeadingBlock);\nregisterBlockGenerator('countdown', generateCountdownBlock);\nregisterBlockGenerator('menu', generateMenuBlock);\nregisterBlockGenerator('hero', generateHeroBlock);\n\nfunction generateBlock(block: Block, indent: string): string {\n const generator = blockGeneratorRegistry[block.type];\n return generator ? generator(block, indent) : '';\n}\n\nfunction generateTextBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n color: p.color,\n 'line-height': p.lineHeight,\n padding: p.padding,\n align: p.align,\n 'font-weight': p.fontWeight && p.fontWeight !== 'normal' ? p.fontWeight : undefined,\n 'text-transform': p.textTransform && p.textTransform !== 'none' ? p.textTransform : undefined,\n 'letter-spacing': p.letterSpacing && p.letterSpacing !== 'normal' ? p.letterSpacing : undefined,\n });\n\n const content = stripVariableChips(p.content || '');\n return `${indent}<mj-text${attrs}>${content}</mj-text>`;\n}\n\nfunction generateButtonBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n href: safeHref(p.href),\n 'background-color': p.backgroundColor,\n color: p.color,\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n 'border-radius': p.borderRadius,\n padding: p.padding,\n 'inner-padding': p.innerPadding,\n align: p.align,\n width: p.width !== 'auto' ? p.width : undefined,\n 'font-weight': p.fontWeight && p.fontWeight !== 'normal' ? p.fontWeight : undefined,\n 'text-transform': p.textTransform && p.textTransform !== 'none' ? p.textTransform : undefined,\n 'letter-spacing': p.letterSpacing && p.letterSpacing !== 'normal' ? p.letterSpacing : undefined,\n });\n\n return `${indent}<mj-button${attrs}>${escapeHTML(p.text)}</mj-button>`;\n}\n\nfunction generateImageBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n src: safeHref(p.src),\n alt: p.alt,\n href: p.href ? safeHref(p.href) : undefined,\n width: p.width,\n height: p.height !== 'auto' ? p.height : undefined,\n padding: p.padding,\n align: p.align,\n 'fluid-on-mobile': p.fluidOnMobile ? 'true' : undefined,\n });\n\n return `${indent}<mj-image${attrs} />`;\n}\n\nfunction generateDividerBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n 'border-color': p.borderColor,\n 'border-width': p.borderWidth,\n 'border-style': p.borderStyle,\n padding: p.padding,\n width: p.width,\n });\n\n return `${indent}<mj-divider${attrs} />`;\n}\n\nfunction generateSpacerBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({ height: p.height });\n return `${indent}<mj-spacer${attrs} />`;\n}\n\nfunction generateSocialBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n mode: p.mode,\n align: p.align,\n 'icon-size': p.iconSize,\n 'icon-padding': p.iconPadding,\n padding: p.padding,\n 'font-size': p.fontSize,\n color: p.color,\n 'border-radius': p.borderRadius,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-social${attrs}>`);\n\n for (const element of p.elements) {\n const elAttrs = buildAttrs({\n name: element.name,\n href: safeHref(element.href),\n src: element.src ? safeHref(element.src) : undefined,\n 'background-color': element.backgroundColor,\n color: element.color,\n });\n const content = element.content ? escapeHTML(element.content) : '';\n lines.push(`${indent} <mj-social-element${elAttrs}>${content}</mj-social-element>`);\n }\n\n lines.push(`${indent}</mj-social>`);\n return lines.join('\\n');\n}\n\nfunction generateHtmlBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({ padding: p.padding, 'css-class': 'ee-block-html' });\n const content = sanitizeHTML(p.content || '');\n return `${indent}<mj-text${attrs}>${content}</mj-text>`;\n}\n\nfunction generateVideoBlock(block: Block, indent: string): string {\n const p = block.properties;\n const thumbnailUrl = p.thumbnailUrl || getAutoThumbnail(p.src);\n const attrs = buildAttrs({\n src: safeHref(thumbnailUrl),\n href: safeHref(p.src),\n alt: p.alt,\n padding: p.padding,\n align: p.align,\n 'css-class': 'ee-block-video',\n });\n return `${indent}<mj-image${attrs} />`;\n}\n\nfunction getAutoThumbnail(url: string): string {\n if (!url) return '';\n const ytMatch = url.match(/(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/);\n if (ytMatch) return `https://img.youtube.com/vi/${ytMatch[1]}/hqdefault.jpg`;\n return '';\n}\n\nfunction generateHeadingBlock(block: Block, indent: string): string {\n const p = block.properties;\n const level = p.level || 'h2';\n const attrs = buildAttrs({\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n color: p.color,\n 'line-height': p.lineHeight,\n padding: p.padding,\n align: p.align,\n 'font-weight': p.fontWeight && p.fontWeight !== 'normal' ? p.fontWeight : undefined,\n 'text-transform': p.textTransform && p.textTransform !== 'none' ? p.textTransform : undefined,\n 'letter-spacing': p.letterSpacing && p.letterSpacing !== 'normal' ? p.letterSpacing : undefined,\n 'css-class': `ee-block-heading ee-heading-${level}`,\n });\n\n const content = stripVariableChips(p.content || '');\n return `${indent}<mj-text${attrs}><${level}>${content}</${level}></mj-text>`;\n}\n\nfunction generateCountdownBlock(block: Block, indent: string): string {\n const p = block.properties;\n const target = new Date(p.targetDate).getTime();\n const now = Date.now();\n const total = Math.max(0, target - now);\n const days = Math.floor(total / (1000 * 60 * 60 * 24));\n const hours = Math.floor((total / (1000 * 60 * 60)) % 24);\n const minutes = Math.floor((total / (1000 * 60)) % 60);\n const seconds = Math.floor((total / 1000) % 60);\n\n const digitStyle = `display:inline-block;background-color:${escapeAttr(p.digitBackgroundColor)};color:${escapeAttr(p.digitColor)};font-size:${escapeAttr(p.fontSize)};font-weight:bold;padding:8px 12px;border-radius:6px;min-width:40px;text-align:center`;\n const unitStyle = `font-size:11px;color:${escapeAttr(p.labelColor)};text-transform:uppercase;letter-spacing:0.5px`;\n\n const units = [\n { value: days, label: 'Days' },\n { value: hours, label: 'Hours' },\n { value: minutes, label: 'Minutes' },\n { value: seconds, label: 'Seconds' },\n ];\n\n const cells = units\n .map(\n (u) =>\n `<td style=\"padding:0 6px;text-align:center\"><div style=\"${digitStyle}\">${String(u.value).padStart(2, '0')}</div><div style=\"${unitStyle}\">${u.label}</div></td>`,\n )\n .join('');\n\n let html = '';\n if (p.label) {\n html += `<div style=\"color:${escapeAttr(p.labelColor)};margin-bottom:8px\">${escapeHTML(p.label)}</div>`;\n }\n html += `<table cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"margin:0 auto\"><tr>${cells}</tr></table>`;\n\n // Embed countdown metadata as data attributes for round-trip parsing\n const attrs = buildAttrs({\n padding: p.padding,\n align: p.align,\n 'css-class': 'ee-block-countdown',\n });\n const metaJson = JSON.stringify({\n targetDate: p.targetDate,\n label: p.label,\n digitBackgroundColor: p.digitBackgroundColor,\n digitColor: p.digitColor,\n labelColor: p.labelColor,\n fontSize: p.fontSize,\n });\n const meta = `<!--ee-countdown:${escapeAttr(metaJson)}-->`;\n return `${indent}<mj-text${attrs}>${meta}${html}</mj-text>`;\n}\n\nfunction generateMenuBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n align: p.align,\n hamburger: p.hamburger ? 'hamburger' : undefined,\n 'ico-color': p.hamburger ? p.iconColor : undefined,\n padding: p.padding,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-navbar${attrs}>`);\n\n for (const item of p.items) {\n const linkAttrs = buildAttrs({\n href: safeHref(item.href),\n color: p.color,\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n });\n lines.push(`${indent} <mj-navbar-link${linkAttrs}>${escapeHTML(item.text)}</mj-navbar-link>`);\n }\n\n lines.push(`${indent}</mj-navbar>`);\n return lines.join('\\n');\n}\n\nfunction generateHeroBlock(block: Block, indent: string): string {\n const p = block.properties;\n\n let html = '';\n if (p.heading) {\n html += `<h2 style=\"color:${escapeAttr(p.headingColor)};font-size:${escapeAttr(p.headingFontSize)};font-weight:bold;line-height:1.2;margin:0 0 16px\">${escapeHTML(p.heading)}</h2>`;\n }\n if (p.subtext) {\n html += `<p style=\"color:${escapeAttr(p.subtextColor)};font-size:${escapeAttr(p.subtextFontSize)};line-height:1.5;margin:0 0 24px\">${escapeHTML(p.subtext)}</p>`;\n }\n if (p.buttonText) {\n html += `<a href=\"${escapeAttr(safeHref(p.buttonHref))}\" style=\"display:inline-block;background-color:${escapeAttr(p.buttonBackgroundColor)};color:${escapeAttr(p.buttonColor)};border-radius:${escapeAttr(p.buttonBorderRadius)};padding:12px 28px;font-weight:600;font-size:16px;text-decoration:none\">${escapeHTML(p.buttonText)}</a>`;\n }\n\n const attrs = buildAttrs({ padding: p.padding, align: p.align });\n return `${indent}<mj-text${attrs}>${html}</mj-text>`;\n}\n\n// ---- Helpers ----\n\n/**\n * Strip TipTap variable chip wrappers from content HTML.\n * Converts `<span class=\"ee-variable-chip\" data-variable-key=\"name\" contenteditable=\"false\">{{ name }}</span>`\n * to plain `{{ name }}`.\n * Uses data-variable-key attribute as source of truth to handle any inner HTML.\n */\nfunction stripVariableChips(html: string): string {\n return html.replace(\n /<span[^>]*data-variable-key=\"([^\"]*)\"[^>]*>[\\s\\S]*?<\\/span>/g,\n (_match, key) => `{{ ${key} }}`,\n );\n}\n\nfunction buildAttrs(obj: Record<string, string | undefined>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && value !== '') {\n parts.push(` ${key}=\"${escapeAttr(value)}\"`);\n }\n }\n return parts.join('');\n}\n\nfunction escapeAttr(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\n/** Sanitize href: return '#' for dangerous URL schemes, pass through safe ones. */\nfunction safeHref(url: string | undefined): string {\n if (!url) return '#';\n return isSafeURL(url) ? url : '#';\n}\n","export interface CompileResult {\n html: string;\n errors: CompileError[];\n}\n\nexport interface CompileError {\n line: number;\n message: string;\n tagName: string;\n}\n\nlet mjmlBrowser: any = null;\n\nasync function loadMjmlBrowser(): Promise<any> {\n if (mjmlBrowser) return mjmlBrowser;\n try {\n mjmlBrowser = (await import('mjml-browser')).default;\n return mjmlBrowser;\n } catch {\n return null;\n }\n}\n\nexport async function compileMJMLToHTML(mjmlString: string): Promise<CompileResult> {\n const mjml = await loadMjmlBrowser();\n\n if (!mjml) {\n // Fallback: wrap in basic HTML without full MJML compilation\n return {\n html: wrapFallbackHTML(mjmlString),\n errors: [{ line: 0, message: 'mjml-browser not available, using fallback rendering', tagName: '' }],\n };\n }\n\n try {\n const result = mjml(mjmlString, {\n validationLevel: 'soft',\n minify: false,\n });\n\n return {\n html: result.html,\n errors: (result.errors ?? []).map((err: any) => ({\n line: err.line ?? 0,\n message: err.message ?? 'Unknown error',\n tagName: err.tagName ?? '',\n })),\n };\n } catch (err) {\n return {\n html: '',\n errors: [{ line: 0, message: String(err), tagName: '' }],\n };\n }\n}\n\nfunction wrapFallbackHTML(mjml: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <style>\n body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f4f4f4; }\n .fallback-notice { text-align: center; padding: 20px; color: #666; font-size: 14px; }\n pre { white-space: pre-wrap; word-wrap: break-word; background: #fff; padding: 20px; border-radius: 4px; }\n </style>\n</head>\n<body>\n <div class=\"fallback-notice\">\n <p>Install <code>mjml-browser</code> for full HTML preview.</p>\n </div>\n <pre>${mjml.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>\n</body>\n</html>`;\n}\n","import type { EmailTemplate, Section, Column, Block, GlobalStyles, HeadMetadata, SocialElement, MenuItem } from '../types';\nimport { DEFAULT_SECTION_PROPERTIES, DEFAULT_BLOCK_PROPERTIES, DEFAULT_HEAD_METADATA } from '../constants';\nimport { generateSectionId, generateColumnId, generateBlockId } from '../utils/id';\nimport { blockParserRegistry, registerBlockParser } from '../registry';\n\n/**\n * MJML's official built-in defaults. Used as parser fallbacks so that\n * round-tripping MJML preserves the original visual output.\n * These are separate from DEFAULT_BLOCK_PROPERTIES (editor defaults for new blocks).\n */\nconst MJML_DEFAULTS = {\n global: {\n backgroundColor: '',\n width: 600,\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n },\n text: {\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n fontSize: '13px',\n color: '#000000',\n lineHeight: '1',\n padding: '10px 25px',\n align: 'left',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n },\n button: {\n text: 'Click me',\n href: '#',\n backgroundColor: '#414141',\n color: '#ffffff',\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n fontSize: '13px',\n borderRadius: '3px',\n padding: '10px 25px',\n innerPadding: '10px 25px',\n align: 'center',\n width: 'auto',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n },\n image: {\n src: '',\n alt: '',\n href: '',\n width: '600px',\n height: 'auto',\n padding: '10px 25px',\n align: 'center',\n },\n divider: {\n borderColor: '#000000',\n borderWidth: '4px',\n borderStyle: 'solid',\n padding: '10px 25px',\n width: '100%',\n },\n spacer: {\n height: '20px',\n },\n social: {\n mode: 'horizontal',\n align: 'center',\n iconSize: '20px',\n iconPadding: '5px',\n padding: '10px 25px',\n fontSize: '13px',\n color: '#333333',\n borderRadius: '3px',\n },\n menu: {\n align: 'center',\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n fontSize: '13px',\n color: '#333333',\n padding: '10px 25px',\n },\n} as const;\n\nexport function parseMJML(mjmlString: string): EmailTemplate {\n const parser = new DOMParser();\n const preprocessed = fixVoidElements(decodeHtmlEntities(mjmlString));\n const doc = parser.parseFromString(preprocessed, 'text/xml');\n\n // Check for XML parse errors\n const parseError = doc.querySelector('parsererror');\n if (parseError) {\n throw new Error(`Invalid MJML: ${parseError.textContent?.slice(0, 200)}`);\n }\n\n const mjmlEl = doc.querySelector('mjml');\n if (!mjmlEl) {\n throw new Error('Invalid MJML: missing <mjml> root element');\n }\n\n const globalStyles = parseGlobalStyles(doc);\n const sections = parseSections(doc);\n const headMetadata = parseHeadMetadata(doc);\n\n return { sections, globalStyles, headMetadata };\n}\n\n/**\n * Decode HTML named entities (e.g. &copy; &nbsp; &mdash;) into their Unicode characters.\n * XML only supports &amp; &lt; &gt; &apos; &quot; — all others cause parse errors.\n * Numeric entities (&#123; &#xA0;) are valid XML and left untouched.\n */\nfunction decodeHtmlEntities(mjml: string): string {\n return mjml.replace(/&([a-zA-Z][a-zA-Z0-9]*);/g, (match, entity) => {\n // Preserve the 5 XML built-in entities\n if (entity === 'amp' || entity === 'lt' || entity === 'gt' || entity === 'apos' || entity === 'quot') {\n return match;\n }\n // Decode HTML entity using a temporary element\n const tmp = document.createElement('span');\n tmp.innerHTML = match;\n return tmp.textContent || match;\n });\n}\n\n/**\n * Self-close HTML void elements that are not already self-closed.\n * XML requires <br/> but HTML allows <br>. MJML content (mj-text etc.)\n * often contains HTML-style void elements that break XML parsing.\n */\nfunction fixVoidElements(mjml: string): string {\n // Match void elements that are NOT already self-closed (no /> at end)\n return mjml.replace(\n /<(br|hr|img|input|meta|link|col|area|base|embed|param|source|track|wbr)\\b([^>]*?)(?<!\\/)>/gi,\n '<$1$2/>',\n );\n}\n\n/**\n * Convert legacy HTML elements (<font>, etc.) to modern <span style=\"...\">\n * for TipTap compatibility. Uses DOM parsing for robustness.\n */\nfunction convertLegacyHtml(html: string): string {\n if (!html || (!html.includes('<font') && !html.includes('<FONT'))) return html;\n\n const FONT_SIZE_MAP: Record<string, string> = {\n '1': '10px', '2': '13px', '3': '16px',\n '4': '18px', '5': '24px', '6': '32px', '7': '48px',\n };\n\n const doc = document.createElement('div');\n doc.innerHTML = html;\n\n const fonts = doc.querySelectorAll('font');\n for (let i = 0; i < fonts.length; i++) {\n const font = fonts[i];\n const span = document.createElement('span');\n const styles: string[] = [];\n\n const color = font.getAttribute('color');\n if (color) styles.push(`color: ${color}`);\n\n const size = font.getAttribute('size');\n if (size && FONT_SIZE_MAP[size]) {\n styles.push(`font-size: ${FONT_SIZE_MAP[size]}`);\n }\n\n const face = font.getAttribute('face');\n if (face) styles.push(`font-family: ${face}`);\n\n if (styles.length > 0) {\n span.setAttribute('style', styles.join('; '));\n }\n\n // Move all children from <font> to <span>\n while (font.firstChild) {\n span.appendChild(font.firstChild);\n }\n font.parentNode?.replaceChild(span, font);\n }\n\n return doc.innerHTML;\n}\n\nfunction parseGlobalStyles(doc: Document): GlobalStyles {\n // Start from MJML's own defaults (not editor defaults) for faithful round-tripping\n const styles: GlobalStyles = {\n backgroundColor: MJML_DEFAULTS.global.backgroundColor,\n width: MJML_DEFAULTS.global.width,\n fontFamily: MJML_DEFAULTS.global.fontFamily,\n };\n const mjBody = doc.querySelector('mj-body');\n if (mjBody) {\n const bgColor = mjBody.getAttribute('background-color');\n if (bgColor) styles.backgroundColor = bgColor;\n const width = mjBody.getAttribute('width');\n if (width) styles.width = parseInt(width, 10) || 600;\n }\n\n const mjAttributes = doc.querySelector('mj-attributes');\n if (mjAttributes) {\n const mjAll = mjAttributes.querySelector('mj-all');\n if (mjAll) {\n const fontFamily = mjAll.getAttribute('font-family');\n if (fontFamily) styles.fontFamily = fontFamily;\n }\n }\n\n return styles;\n}\n\nfunction parseHeadMetadata(doc: Document): HeadMetadata {\n const metadata: HeadMetadata = { ...DEFAULT_HEAD_METADATA, headStyles: [] };\n const mjHead = doc.querySelector('mj-head');\n if (!mjHead) return metadata;\n\n const titleEl = mjHead.querySelector('mj-title');\n if (titleEl) {\n metadata.title = titleEl.textContent ?? '';\n }\n\n const previewEl = mjHead.querySelector('mj-preview');\n if (previewEl) {\n metadata.previewText = previewEl.textContent ?? '';\n }\n\n const styleEls = mjHead.querySelectorAll('mj-style');\n for (let i = 0; i < styleEls.length; i++) {\n const content = styleEls[i].textContent ?? '';\n if (content.trim()) {\n metadata.headStyles.push(content);\n }\n }\n\n return metadata;\n}\n\nfunction parseSections(doc: Document): Section[] {\n const mjBody = doc.querySelector('mj-body');\n if (!mjBody) return [];\n\n const sections: Section[] = [];\n\n // Walk direct children of mj-body: handle mj-section, mj-hero, and mj-wrapper\n for (let i = 0; i < mjBody.children.length; i++) {\n const child = mjBody.children[i];\n const tag = child.tagName.toLowerCase();\n\n if (tag === 'mj-section') {\n sections.push(parseSectionElement(child));\n } else if (tag === 'mj-hero') {\n sections.push(parseHeroElement(child));\n } else if (tag === 'mj-wrapper') {\n // mj-wrapper groups multiple mj-sections — unwrap them\n const innerSections = child.querySelectorAll(':scope > mj-section');\n for (let j = 0; j < innerSections.length; j++) {\n sections.push(parseSectionElement(innerSections[j]));\n }\n }\n }\n\n return sections;\n}\n\nfunction parseSectionElement(el: Element): Section {\n const id = generateSectionId();\n const properties: any = {\n backgroundColor: el.getAttribute('background-color') ?? DEFAULT_SECTION_PROPERTIES.backgroundColor,\n padding: resolvePadding(el, DEFAULT_SECTION_PROPERTIES.padding),\n borderRadius: el.getAttribute('border-radius') ?? DEFAULT_SECTION_PROPERTIES.borderRadius,\n fullWidth: el.getAttribute('full-width') === 'full-width',\n };\n const bgUrl = el.getAttribute('background-url');\n if (bgUrl) properties.backgroundImage = bgUrl;\n const bgSize = el.getAttribute('background-size');\n if (bgSize) properties.backgroundSize = bgSize;\n const bgRepeat = el.getAttribute('background-repeat');\n if (bgRepeat) properties.backgroundRepeat = bgRepeat;\n\n // Collect columns from direct mj-column children and also from mj-group children\n const columnEls: Element[] = [];\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i];\n const tag = child.tagName.toLowerCase();\n if (tag === 'mj-column') {\n columnEls.push(child);\n } else if (tag === 'mj-group') {\n // mj-group wraps columns — extract them\n const groupCols = child.querySelectorAll(':scope > mj-column');\n for (let j = 0; j < groupCols.length; j++) {\n columnEls.push(groupCols[j]);\n }\n }\n }\n\n let columns: Column[];\n\n if (columnEls.length === 0) {\n // No columns, treat direct children as blocks in a single 100% column\n columns = [{\n id: generateColumnId(),\n width: '100%',\n blocks: parseBlockElements(el),\n }];\n } else {\n // MJML auto-distributes columns when width isn't specified.\n // Calculate the default width based on sibling count.\n const autoWidth = `${Math.round((100 / columnEls.length) * 100) / 100}%`;\n columns = columnEls.map((colEl) => parseColumnElement(colEl, autoWidth));\n }\n\n return { id, columns, properties };\n}\n\n/**\n * Parse mj-hero as a section. mj-hero doesn't use mj-column —\n * its direct children (mj-text, mj-image, mj-button) become blocks\n * in a single 100% column. The background-url maps to backgroundImage.\n */\nfunction parseHeroElement(el: Element): Section {\n const id = generateSectionId();\n\n // Check if hero has mj-image children — if so, parse as a regular section\n // with individual blocks to preserve all content (images, text, buttons).\n // Otherwise, parse as a single structured hero block.\n let hasImages = false;\n for (let i = 0; i < el.children.length; i++) {\n if (el.children[i].tagName.toLowerCase() === 'mj-image') {\n hasImages = true;\n break;\n }\n }\n\n if (hasImages) {\n // Complex hero with images → section with background + individual blocks\n const properties: any = {\n backgroundColor: el.getAttribute('background-color') ?? DEFAULT_SECTION_PROPERTIES.backgroundColor,\n padding: resolvePadding(el, DEFAULT_SECTION_PROPERTIES.padding),\n borderRadius: '0px',\n fullWidth: false,\n };\n const bgUrl = el.getAttribute('background-url');\n if (bgUrl) properties.backgroundImage = bgUrl;\n\n return {\n id,\n columns: [{\n id: generateColumnId(),\n width: '100%',\n blocks: parseBlockElements(el),\n }],\n properties,\n };\n }\n\n // Simple hero (text/button only) → structured hero block\n const properties: any = {\n backgroundColor: DEFAULT_SECTION_PROPERTIES.backgroundColor,\n padding: '0',\n borderRadius: '0px',\n fullWidth: false,\n };\n\n const heroBlock = buildHeroBlock(el);\n\n return {\n id,\n columns: [{\n id: generateColumnId(),\n width: '100%',\n blocks: [heroBlock],\n }],\n properties,\n };\n}\n\n/**\n * Build a hero block from an mj-hero element.\n * Extracts heading, subtext, and button from child mj-text/mj-button elements.\n */\nfunction buildHeroBlock(el: Element): Block {\n const defaults = DEFAULT_BLOCK_PROPERTIES.hero;\n\n let heading = '';\n let subtext = '';\n let buttonText = '';\n let buttonHref = defaults.buttonHref;\n let headingColor = defaults.headingColor;\n let headingFontSize = defaults.headingFontSize;\n let subtextColor = defaults.subtextColor;\n let subtextFontSize = defaults.subtextFontSize;\n let buttonBackgroundColor = defaults.buttonBackgroundColor;\n let buttonColor = defaults.buttonColor;\n let buttonBorderRadius = defaults.buttonBorderRadius;\n let align: string = defaults.align;\n\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i];\n const tag = child.tagName.toLowerCase();\n\n if (tag === 'mj-text') {\n const content = child.innerHTML?.trim() ?? '';\n const textContent = child.textContent?.trim() ?? '';\n // If content contains a heading tag, treat as heading\n if (/<h[1-4]/i.test(content) && !heading) {\n heading = textContent;\n headingColor = child.getAttribute('color') ?? defaults.headingColor;\n headingFontSize = child.getAttribute('font-size') ?? defaults.headingFontSize;\n } else if (!subtext) {\n subtext = textContent;\n subtextColor = child.getAttribute('color') ?? defaults.subtextColor;\n subtextFontSize = child.getAttribute('font-size') ?? defaults.subtextFontSize;\n }\n const a = child.getAttribute('align');\n if (a) align = a;\n } else if (tag === 'mj-button') {\n buttonText = child.textContent?.trim() ?? '';\n buttonHref = child.getAttribute('href') ?? defaults.buttonHref;\n buttonBackgroundColor = child.getAttribute('background-color') ?? defaults.buttonBackgroundColor;\n buttonColor = child.getAttribute('color') ?? defaults.buttonColor;\n buttonBorderRadius = child.getAttribute('border-radius') ?? defaults.buttonBorderRadius;\n const a = child.getAttribute('align');\n if (a) align = a;\n }\n // mj-image children are not mapped to hero block properties\n }\n\n // If no heading was found but there's a plain mj-text, promote first text to heading\n if (!heading && subtext) {\n heading = subtext;\n headingColor = subtextColor;\n headingFontSize = subtextFontSize;\n subtext = '';\n subtextColor = defaults.subtextColor;\n subtextFontSize = defaults.subtextFontSize;\n }\n\n return {\n id: generateBlockId(),\n type: 'hero',\n properties: {\n heading,\n subtext,\n buttonText,\n buttonHref,\n headingColor,\n headingFontSize,\n subtextColor,\n subtextFontSize,\n buttonBackgroundColor,\n buttonColor,\n buttonBorderRadius,\n align,\n padding: resolvePadding(el, defaults.padding),\n backgroundImage: el.getAttribute('background-url') ?? defaults.backgroundImage,\n backgroundColor: el.getAttribute('background-color') ?? defaults.backgroundColor,\n },\n };\n}\n\nfunction parseColumnElement(el: Element, defaultWidth: string): Column {\n return {\n id: generateColumnId(),\n width: el.getAttribute('width') ?? defaultWidth,\n blocks: parseBlockElements(el),\n };\n}\n\n/** Resolve padding from shorthand or individual padding-top/right/bottom/left attributes */\nfunction resolvePadding(el: Element, fallback: string): string {\n const shorthand = el.getAttribute('padding');\n if (shorthand) return shorthand;\n\n const pt = el.getAttribute('padding-top');\n const pr = el.getAttribute('padding-right');\n const pb = el.getAttribute('padding-bottom');\n const pl = el.getAttribute('padding-left');\n\n if (pt || pr || pb || pl) {\n return `${pt ?? '0'} ${pr ?? '0'} ${pb ?? '0'} ${pl ?? '0'}`;\n }\n\n return fallback;\n}\n\n// Register built-in parsers\nregisterBlockParser('mj-text', parseTextBlock);\nregisterBlockParser('mj-button', parseButtonBlock);\nregisterBlockParser('mj-image', parseImageBlock);\nregisterBlockParser('mj-divider', parseDividerBlock);\nregisterBlockParser('mj-spacer', parseSpacerBlock);\nregisterBlockParser('mj-social', parseSocialBlock);\nregisterBlockParser('mj-navbar', parseMenuBlock);\n\nfunction parseBlockElements(parent: Element): Block[] {\n const blocks: Block[] = [];\n const children = parent.children;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n const tagName = child.tagName.toLowerCase();\n\n if (tagName === 'mj-column') continue; // handled at section level\n\n const parser = blockParserRegistry[tagName];\n if (parser) {\n blocks.push(parser(child));\n }\n }\n\n return blocks;\n}\n\nfunction parseTextBlock(el: Element): Block {\n const cssClass = el.getAttribute('css-class') ?? '';\n\n // Detect heading block by css-class marker or content heuristic\n if (cssClass.includes('ee-block-heading')) {\n return parseHeadingFromMjText(el, cssClass);\n }\n\n // Detect countdown block by css-class marker\n if (cssClass.includes('ee-block-countdown')) {\n return parseCountdownFromMjText(el);\n }\n\n // Detect HTML block by css-class marker\n if (cssClass.includes('ee-block-html')) {\n return parseHtmlFromMjText(el);\n }\n\n const innerHTML = el.innerHTML?.trim() ?? '';\n\n const d = MJML_DEFAULTS.text;\n return {\n id: generateBlockId(),\n type: 'text',\n properties: {\n content: convertLegacyHtml(innerHTML),\n fontFamily: el.getAttribute('font-family') ?? d.fontFamily,\n fontSize: el.getAttribute('font-size') ?? d.fontSize,\n color: el.getAttribute('color') ?? d.color,\n lineHeight: el.getAttribute('line-height') ?? d.lineHeight,\n padding: resolvePadding(el, d.padding),\n align: el.getAttribute('align') ?? d.align,\n fontWeight: el.getAttribute('font-weight') ?? d.fontWeight,\n textTransform: el.getAttribute('text-transform') ?? d.textTransform,\n letterSpacing: el.getAttribute('letter-spacing') ?? d.letterSpacing,\n },\n };\n}\n\nfunction parseHeadingFromMjText(el: Element, cssClass: string): Block {\n const d = MJML_DEFAULTS.text;\n const defaults = DEFAULT_BLOCK_PROPERTIES.heading;\n const innerHTML = el.innerHTML?.trim() ?? '';\n\n // Extract heading level from css-class (ee-heading-h1, ee-heading-h2, etc.)\n const levelMatch = cssClass.match(/ee-heading-(h[1-4])/);\n const level = levelMatch ? levelMatch[1] : 'h2';\n\n // Extract content from heading tag wrapper\n const contentMatch = innerHTML.match(new RegExp(`^<${level}[^>]*>([\\\\s\\\\S]*)<\\\\/${level}>$`, 'i'));\n const content = contentMatch ? contentMatch[1].trim() : innerHTML;\n\n return {\n id: generateBlockId(),\n type: 'heading',\n properties: {\n content,\n level,\n fontFamily: el.getAttribute('font-family') ?? defaults.fontFamily,\n fontSize: el.getAttribute('font-size') ?? defaults.fontSize,\n color: el.getAttribute('color') ?? defaults.color,\n lineHeight: el.getAttribute('line-height') ?? defaults.lineHeight,\n fontWeight: el.getAttribute('font-weight') ?? defaults.fontWeight,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? d.align,\n textTransform: el.getAttribute('text-transform') ?? defaults.textTransform,\n letterSpacing: el.getAttribute('letter-spacing') ?? defaults.letterSpacing,\n },\n };\n}\n\nfunction parseCountdownFromMjText(el: Element): Block {\n const defaults = DEFAULT_BLOCK_PROPERTIES.countdown;\n const innerHTML = el.innerHTML?.trim() ?? '';\n\n // Extract metadata from embedded JSON comment\n const metaMatch = innerHTML.match(/<!--ee-countdown:([\\s\\S]*?)-->/);\n\n if (metaMatch) {\n try {\n // Decode HTML entities back to JSON (escapeAttr encodes &, \", <, >)\n const raw = metaMatch[1].replace(/&amp;/g, '&').replace(/&quot;/g, '\"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#39;/g, \"'\");\n const meta = JSON.parse(raw);\n return {\n id: generateBlockId(),\n type: 'countdown',\n properties: {\n targetDate: meta.targetDate || defaults.targetDate,\n label: meta.label ?? '',\n digitBackgroundColor: meta.digitBackgroundColor || defaults.digitBackgroundColor,\n digitColor: meta.digitColor || defaults.digitColor,\n labelColor: meta.labelColor || defaults.labelColor,\n fontSize: meta.fontSize || defaults.fontSize,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? defaults.align,\n },\n };\n } catch {\n // JSON parse failed — fall through to default\n }\n }\n\n // Fallback: create a default countdown block\n return {\n id: generateBlockId(),\n type: 'countdown',\n properties: {\n ...defaults,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? defaults.align,\n },\n };\n}\n\nfunction parseHtmlFromMjText(el: Element): Block {\n const defaults = DEFAULT_BLOCK_PROPERTIES.html;\n return {\n id: generateBlockId(),\n type: 'html',\n properties: {\n content: el.innerHTML?.trim() ?? '',\n padding: resolvePadding(el, defaults.padding),\n },\n };\n}\n\nfunction parseButtonBlock(el: Element): Block {\n const d = MJML_DEFAULTS.button;\n return {\n id: generateBlockId(),\n type: 'button',\n properties: {\n text: el.textContent?.trim() ?? d.text,\n href: el.getAttribute('href') ?? d.href,\n backgroundColor: el.getAttribute('background-color') ?? d.backgroundColor,\n color: el.getAttribute('color') ?? d.color,\n fontFamily: el.getAttribute('font-family') ?? d.fontFamily,\n fontSize: el.getAttribute('font-size') ?? d.fontSize,\n borderRadius: el.getAttribute('border-radius') ?? d.borderRadius,\n padding: resolvePadding(el, d.padding),\n innerPadding: el.getAttribute('inner-padding') ?? d.innerPadding,\n align: el.getAttribute('align') ?? d.align,\n width: el.getAttribute('width') ?? d.width,\n fontWeight: el.getAttribute('font-weight') ?? d.fontWeight,\n textTransform: el.getAttribute('text-transform') ?? d.textTransform,\n letterSpacing: el.getAttribute('letter-spacing') ?? d.letterSpacing,\n },\n };\n}\n\nfunction parseImageBlock(el: Element): Block {\n const cssClass = el.getAttribute('css-class') ?? '';\n const href = el.getAttribute('href') ?? '';\n\n // Detect video block by css-class marker or href heuristic (YouTube/Vimeo)\n if (cssClass.includes('ee-block-video') || isVideoUrl(href)) {\n const defaults = DEFAULT_BLOCK_PROPERTIES.video;\n return {\n id: generateBlockId(),\n type: 'video',\n properties: {\n src: href || defaults.src,\n thumbnailUrl: el.getAttribute('src') ?? defaults.thumbnailUrl,\n alt: el.getAttribute('alt') ?? defaults.alt,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? defaults.align,\n },\n };\n }\n\n const d = MJML_DEFAULTS.image;\n return {\n id: generateBlockId(),\n type: 'image',\n properties: {\n src: el.getAttribute('src') ?? d.src,\n alt: el.getAttribute('alt') ?? d.alt,\n href: href || d.href,\n width: el.getAttribute('width') ?? d.width,\n height: el.getAttribute('height') ?? d.height,\n padding: resolvePadding(el, d.padding),\n align: el.getAttribute('align') ?? d.align,\n fluidOnMobile: el.getAttribute('fluid-on-mobile') === 'true',\n },\n };\n}\n\nfunction isVideoUrl(url: string): boolean {\n if (!url) return false;\n return /(?:youtube\\.com\\/watch|youtu\\.be\\/|vimeo\\.com\\/)/i.test(url);\n}\n\nfunction parseDividerBlock(el: Element): Block {\n const d = MJML_DEFAULTS.divider;\n return {\n id: generateBlockId(),\n type: 'divider',\n properties: {\n borderColor: el.getAttribute('border-color') ?? d.borderColor,\n borderWidth: el.getAttribute('border-width') ?? d.borderWidth,\n borderStyle: el.getAttribute('border-style') ?? d.borderStyle,\n padding: resolvePadding(el, d.padding),\n width: el.getAttribute('width') ?? d.width,\n },\n };\n}\n\nfunction parseSpacerBlock(el: Element): Block {\n const d = MJML_DEFAULTS.spacer;\n return {\n id: generateBlockId(),\n type: 'spacer',\n properties: {\n height: el.getAttribute('height') ?? d.height,\n },\n };\n}\n\nfunction parseSocialBlock(el: Element): Block {\n const d = MJML_DEFAULTS.social;\n const editorDefaults = DEFAULT_BLOCK_PROPERTIES.social;\n\n const elements: SocialElement[] = [];\n const childEls = el.querySelectorAll('mj-social-element');\n for (let i = 0; i < childEls.length; i++) {\n const child = childEls[i];\n const element: SocialElement = {\n name: child.getAttribute('name') ?? 'web',\n href: child.getAttribute('href') ?? '#',\n };\n const src = child.getAttribute('src');\n if (src) element.src = src;\n const content = child.textContent?.trim();\n if (content) element.content = content;\n const bgColor = child.getAttribute('background-color');\n if (bgColor) element.backgroundColor = bgColor;\n const color = child.getAttribute('color');\n if (color) element.color = color;\n elements.push(element);\n }\n\n return {\n id: generateBlockId(),\n type: 'social',\n properties: {\n elements: elements.length > 0 ? elements : editorDefaults.elements,\n mode: el.getAttribute('mode') ?? d.mode,\n align: el.getAttribute('align') ?? d.align,\n iconSize: el.getAttribute('icon-size') ?? d.iconSize,\n iconPadding: el.getAttribute('icon-padding') ?? d.iconPadding,\n padding: resolvePadding(el, d.padding),\n fontSize: el.getAttribute('font-size') ?? d.fontSize,\n color: el.getAttribute('color') ?? d.color,\n borderRadius: el.getAttribute('border-radius') ?? d.borderRadius,\n },\n };\n}\n\nfunction parseMenuBlock(el: Element): Block {\n const d = MJML_DEFAULTS.menu;\n const editorDefaults = DEFAULT_BLOCK_PROPERTIES.menu;\n\n const items: MenuItem[] = [];\n const linkEls = el.querySelectorAll('mj-navbar-link');\n for (let i = 0; i < linkEls.length; i++) {\n const child = linkEls[i];\n items.push({\n text: child.textContent?.trim() ?? 'Link',\n href: child.getAttribute('href') ?? '#',\n });\n }\n\n // Read color/font from first link element if present\n const firstLink = linkEls.length > 0 ? linkEls[0] : null;\n\n return {\n id: generateBlockId(),\n type: 'menu',\n properties: {\n items: items.length > 0 ? items : editorDefaults.items,\n align: el.getAttribute('align') ?? d.align,\n fontFamily: firstLink?.getAttribute('font-family') ?? d.fontFamily,\n fontSize: firstLink?.getAttribute('font-size') ?? d.fontSize,\n color: firstLink?.getAttribute('color') ?? d.color,\n padding: resolvePadding(el, d.padding),\n hamburger: el.getAttribute('hamburger') === 'hamburger',\n iconColor: el.getAttribute('ico-color') ?? editorDefaults.iconColor,\n },\n };\n}\n",".toolbar {\n display: flex;\n align-items: center;\n height: var(--ee-toolbar-height);\n padding: 0 var(--ee-space-lg);\n background: var(--ee-bg-toolbar);\n border-bottom: 1px solid var(--ee-border-color);\n gap: var(--ee-space-sm);\n flex-shrink: 0;\n}\n\n.toolbarGroup {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.toolbarSeparator {\n width: 1px;\n height: 24px;\n background: var(--ee-border-color);\n margin: 0 var(--ee-space-sm);\n}\n\n.toolbarSpacer {\n flex: 1;\n}\n\n.toolbarBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-xs);\n padding: 6px 10px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n background: transparent;\n border: 1px solid transparent;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n white-space: nowrap;\n}\n\n.toolbarBtn:hover {\n background: var(--ee-bg-hover);\n color: var(--ee-text-primary);\n border-color: var(--ee-border-color);\n}\n\n.toolbarBtn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.toolbarBtnActive {\n background: var(--ee-bg-selected);\n color: var(--ee-color-primary);\n border-color: var(--ee-color-primary);\n}\n\n.toolbarBtnPrimary {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.toolbarBtnPrimary:hover {\n background: var(--ee-color-primary-hover);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary-hover);\n}\n\n/* Tab bar within toolbar */\n.tabBar {\n display: flex;\n gap: 2px;\n background: var(--ee-bg-app);\n border-radius: var(--ee-border-radius);\n padding: 2px;\n}\n\n.tabBtn {\n padding: 4px 12px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n background: transparent;\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.tabBtn:hover {\n color: var(--ee-text-primary);\n}\n\n.tabBtnActive {\n background: var(--ee-bg-panel);\n color: var(--ee-text-primary);\n box-shadow: var(--ee-shadow-sm);\n}\n\n/* Panel toggle buttons (visible only on narrow screens via editor.module.css) */\n.panelToggleBtn {\n composes: toolbarBtn;\n font-size: var(--ee-font-size-lg);\n padding: 4px 8px;\n line-height: 1;\n}\n\n.panelToggleBtnActive {\n background: var(--ee-bg-selected);\n color: var(--ee-color-primary);\n border-color: var(--ee-color-primary);\n}\n\n/* Export dropdown */\n.exportWrapper {\n position: relative;\n}\n\n.exportDropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n z-index: var(--ee-z-dropdown);\n min-width: 120px;\n overflow: hidden;\n}\n\n.exportDropdownItem {\n display: block;\n width: 100%;\n padding: 8px 16px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n color: var(--ee-text-primary);\n background: none;\n border: none;\n text-align: left;\n cursor: pointer;\n transition: background var(--ee-transition-fast);\n}\n\n.exportDropdownItem:hover {\n background: var(--ee-bg-hover);\n}\n\n/* Rich text toolbar */\n.richTextToolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: var(--ee-space-xs) var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-sm);\n flex-wrap: wrap;\n}\n\n.richTextBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n font-size: var(--ee-font-size-sm);\n background: transparent;\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.richTextBtn:hover {\n background: var(--ee-bg-hover);\n color: var(--ee-text-primary);\n}\n\n.richTextBtnActive {\n background: var(--ee-bg-selected);\n color: var(--ee-color-primary);\n}\n\n.richTextSeparator {\n width: 1px;\n height: 20px;\n background: var(--ee-border-color);\n margin: 0 2px;\n}\n\n/* Rich text select controls */\n.richTextSelect {\n height: 28px;\n padding: 0 4px;\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n cursor: pointer;\n max-width: 110px;\n}\n\n.richTextSelect:focus {\n border-color: var(--ee-border-focus);\n}\n\n.richTextSelectSmall {\n composes: richTextSelect;\n max-width: 64px;\n}\n\n/* Rich text inline color picker */\n.richTextColorWrapper {\n position: relative;\n}\n\n.richTextColorLabel {\n font-weight: var(--ee-font-weight-semibold);\n font-size: var(--ee-font-size-sm);\n}\n\n.richTextColorIndicator {\n display: block;\n width: 16px;\n height: 3px;\n border-radius: 1px;\n margin-top: 1px;\n}\n\n.richTextColorDropdown {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 4px;\n padding: var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n z-index: var(--ee-z-dropdown);\n min-width: 176px;\n}\n\n.richTextColorGrid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 4px;\n margin-bottom: var(--ee-space-sm);\n}\n\n.richTextColorSwatch {\n width: 24px;\n height: 24px;\n border-radius: 3px;\n border: 2px solid transparent;\n cursor: pointer;\n padding: 0;\n transition: all var(--ee-transition-fast);\n}\n\n.richTextColorSwatch:hover {\n transform: scale(1.2);\n border-color: var(--ee-border-color-strong);\n}\n\n.richTextColorActions {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n border-top: 1px solid var(--ee-border-color);\n padding-top: var(--ee-space-sm);\n}\n\n.richTextColorInput {\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid var(--ee-border-color);\n border-radius: 3px;\n cursor: pointer;\n background: none;\n}\n\n.richTextColorClearBtn {\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n color: var(--ee-text-secondary);\n background: transparent;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n padding: 3px 8px;\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.richTextColorClearBtn:hover {\n background: var(--ee-bg-hover);\n color: var(--ee-text-primary);\n}\n\n/* Link editor popover */\n.richTextLinkDropdown {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 4px;\n padding: var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n z-index: var(--ee-z-dropdown);\n min-width: 260px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.richTextLinkLabel {\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-secondary);\n}\n\n.richTextLinkInput {\n width: 100%;\n padding: 6px 8px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n box-sizing: border-box;\n}\n\n.richTextLinkInput:focus {\n border-color: var(--ee-border-focus);\n}\n\n.richTextLinkError {\n color: var(--ee-color-danger, #dc2626);\n font-size: 11px;\n margin-bottom: 4px;\n}\n\n.richTextLinkActions {\n display: flex;\n gap: 6px;\n}\n\n.richTextLinkApply {\n flex: 1;\n padding: 4px 10px;\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-inverse);\n background: var(--ee-color-primary);\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: background var(--ee-transition-fast);\n}\n\n.richTextLinkApply:hover {\n background: var(--ee-color-primary-hover);\n}\n\n.richTextLinkRemove {\n padding: 4px 10px;\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n color: var(--ee-color-danger, #ef4444);\n background: transparent;\n border: 1px solid var(--ee-color-danger, #ef4444);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.richTextLinkRemove:hover {\n background: var(--ee-color-danger, #ef4444);\n color: var(--ee-text-inverse);\n}\n\n",".editorWrapper {\n height: 100%;\n min-height: 0;\n}\n\n.editorContainer {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 500px;\n font-family: var(--ee-font-family);\n font-size: var(--ee-font-size-base);\n color: var(--ee-text-primary);\n background: var(--ee-bg-app);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-lg);\n overflow: hidden;\n}\n\n.editorContainer:focus {\n outline: none;\n}\n\n.editorBody {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.editorPanel {\n min-height: 0;\n max-height: 100%;\n}\n\n.sidebarPanel {\n width: var(--ee-sidebar-width);\n border-right: 1px solid var(--ee-border-color);\n background: var(--ee-bg-panel);\n overflow-y: auto;\n flex-shrink: 0;\n}\n\n.canvasPanel {\n flex: 1;\n min-width: 0;\n background: var(--ee-bg-canvas);\n overflow-y: auto;\n}\n\n.propertiesPanel {\n width: var(--ee-properties-width);\n border-left: 1px solid var(--ee-border-color);\n background: var(--ee-bg-panel);\n overflow-y: auto;\n flex-shrink: 0;\n}\n\n/* Source tab split layout */\n.sourceLayout {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.sourcePane {\n flex: 1;\n min-width: 0;\n}\n\n.sourcePaneDivider {\n flex: 1;\n min-width: 0;\n border-left: 1px solid var(--ee-border-color);\n}\n\n/* Panel toggle buttons — hidden on desktop, shown on narrow screens */\n.panelToggle {\n display: none;\n}\n\n/* Overlay backdrop */\n.panelOverlay {\n display: none;\n}\n\n/* ---- Responsive: tablet / narrow screens ---- */\n@media (max-width: 1023px) {\n .editorBody {\n position: relative;\n }\n\n .sidebarPanel {\n display: none;\n }\n\n .propertiesPanel {\n display: none;\n }\n\n .panelToggle {\n display: flex;\n }\n\n /* Sidebar overlay (open state) */\n .sidebarPanel.sidebarOpen {\n display: block;\n position: absolute;\n z-index: var(--ee-z-overlay);\n left: 0;\n top: 0;\n bottom: 0;\n box-shadow: var(--ee-shadow-lg);\n }\n\n /* Properties overlay (open state) */\n .propertiesPanel.propertiesOpen {\n display: block;\n position: absolute;\n z-index: var(--ee-z-overlay);\n right: 0;\n top: 0;\n bottom: 0;\n box-shadow: var(--ee-shadow-lg);\n }\n\n /* Backdrop when a panel is open */\n .panelOverlay.panelOverlayVisible {\n display: block;\n position: absolute;\n inset: 0;\n background: var(--ee-overlay-backdrop);\n z-index: calc(var(--ee-z-overlay) - 1);\n }\n}\n\n/* ---- Responsive: mobile ---- */\n@media (max-width: 767px) {\n .editorContainer {\n min-height: 400px;\n }\n}\n","import React, { useCallback } from 'react';\nimport { BlockPalette } from './BlockPalette';\nimport { VariableList } from './VariableList';\nimport { AddVariableForm } from './AddVariableForm';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport { COLUMN_LAYOUTS } from '../../constants';\nimport type { BlockDefinition } from '../../constants';\nimport { createSection } from '../../utils/factory';\nimport styles from '../../styles/sidebar.module.css';\n\ninterface SidebarProps {\n blockDefinitions?: BlockDefinition[];\n}\n\nexport function Sidebar({ blockDefinitions }: SidebarProps) {\n const dispatch = useEditorDispatch();\n\n const handleAddSection = useCallback(\n (widths: string[]) => {\n dispatch({ type: 'ADD_SECTION', payload: { section: createSection(widths) } });\n },\n [dispatch],\n );\n\n return (\n <div className={`ee-sidebar ${styles.sidebar}`}>\n <h3 className={`ee-sidebar-title ${styles.sectionTitle}`}>Variables</h3>\n <VariableList />\n <div className={styles.addVariableSection}>\n <AddVariableForm />\n </div>\n\n <h3 className={`ee-sidebar-title ${styles.sectionTitle}`}>Blocks</h3>\n <BlockPalette blockDefinitions={blockDefinitions} />\n\n <h3 className={`ee-sidebar-title ${styles.sectionTitle}`}>Layouts</h3>\n <div className={`ee-layout-section ${styles.layoutSection}`}>\n {COLUMN_LAYOUTS.map((layout) => (\n <div\n key={layout.label}\n className={`ee-layout-option ${styles.layoutOption}`}\n onClick={() => handleAddSection(layout.widths)}\n >\n <div className={`ee-layout-preview ${styles.layoutPreview}`}>\n {layout.widths.map((w, i) => (\n <div\n key={i}\n className={`ee-layout-column ${styles.layoutColumn}`}\n style={{ width: w }}\n />\n ))}\n </div>\n <span className={`ee-layout-label ${styles.layoutLabel}`}>{layout.label}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport { BLOCK_DEFINITIONS } from '../../constants';\nimport type { BlockDefinition } from '../../constants';\nimport { setBlockTypeDragData } from '../../utils/dnd';\nimport type { BlockType } from '../../types';\nimport { useEditorDispatch, useTemplateContext } from '../../context/EditorContext';\nimport { createSection, createBlock } from '../../utils/factory';\nimport styles from '../../styles/sidebar.module.css';\n\ninterface BlockPaletteProps {\n blockDefinitions?: BlockDefinition[];\n}\n\nexport const BlockPalette = React.memo(function BlockPalette({ blockDefinitions }: BlockPaletteProps) {\n const defs = blockDefinitions ?? BLOCK_DEFINITIONS;\n const dispatch = useEditorDispatch();\n const { template } = useTemplateContext();\n\n const handleDragStart = useCallback(\n (type: BlockType, e: React.DragEvent) => {\n setBlockTypeDragData(e, type);\n },\n [],\n );\n\n const handleKeyboardAdd = useCallback(\n (type: BlockType) => {\n let targetSection = template.sections[template.sections.length - 1];\n if (!targetSection) {\n targetSection = createSection();\n dispatch({ type: 'ADD_SECTION', payload: { section: targetSection } });\n }\n const column = targetSection.columns[0];\n const block = createBlock(type);\n dispatch({\n type: 'ADD_BLOCK_AND_SELECT',\n payload: { sectionId: targetSection.id, columnId: column.id, block },\n });\n },\n [dispatch, template.sections],\n );\n\n return (\n <div className={`ee-block-palette ${styles.blockPalette}`} role=\"list\" aria-label=\"Available blocks\">\n {defs.map((def) => (\n <div\n key={def.type}\n data-block-type={def.type}\n className={`ee-palette-item ee-palette-item--${def.type} ${styles.blockCard}`}\n draggable\n onDragStart={(e) => handleDragStart(def.type, e)}\n title={def.description}\n role=\"listitem\"\n aria-label={`${def.label} block - drag or press Enter to add`}\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleKeyboardAdd(def.type);\n }\n }}\n >\n <span className={`ee-palette-icon ${styles.blockCardIcon}`} aria-hidden=\"true\">{def.icon}</span>\n <span className={`ee-palette-label ${styles.blockCardLabel}`}>{def.label}</span>\n </div>\n ))}\n </div>\n );\n});\n","import type { BlockType } from '../types';\n\nexport const DND_TYPES = {\n BLOCK_TYPE: 'application/x-block-type',\n BLOCK_ID: 'application/x-block-id',\n SECTION_ID: 'application/x-section-id',\n COLUMN_ID: 'application/x-column-id',\n SECTION_MOVE: 'application/x-section-move',\n} as const;\n\nexport function setBlockTypeDragData(e: React.DragEvent, type: BlockType): void {\n e.dataTransfer.setData(DND_TYPES.BLOCK_TYPE, type);\n e.dataTransfer.effectAllowed = 'copy';\n}\n\nexport function setBlockMoveDragData(\n e: React.DragEvent,\n blockId: string,\n sectionId: string,\n columnId: string,\n): void {\n e.dataTransfer.setData(DND_TYPES.BLOCK_ID, blockId);\n e.dataTransfer.setData(DND_TYPES.SECTION_ID, sectionId);\n e.dataTransfer.setData(DND_TYPES.COLUMN_ID, columnId);\n e.dataTransfer.effectAllowed = 'move';\n}\n\nexport function getBlockTypeFromDrop(e: React.DragEvent): BlockType | null {\n const type = e.dataTransfer.getData(DND_TYPES.BLOCK_TYPE);\n return (type as BlockType) || null;\n}\n\nexport function getBlockMoveFromDrop(e: React.DragEvent): {\n blockId: string;\n sectionId: string;\n columnId: string;\n} | null {\n const blockId = e.dataTransfer.getData(DND_TYPES.BLOCK_ID);\n const sectionId = e.dataTransfer.getData(DND_TYPES.SECTION_ID);\n const columnId = e.dataTransfer.getData(DND_TYPES.COLUMN_ID);\n if (!blockId) return null;\n return { blockId, sectionId, columnId };\n}\n\nexport function setSectionMoveDragData(e: React.DragEvent, sectionId: string): void {\n e.dataTransfer.setData(DND_TYPES.SECTION_MOVE, sectionId);\n e.dataTransfer.effectAllowed = 'move';\n}\n\nexport function getSectionMoveFromDrop(e: React.DragEvent): string | null {\n return e.dataTransfer.getData(DND_TYPES.SECTION_MOVE) || null;\n}\n\nexport function isSectionDrop(e: React.DragEvent): boolean {\n return e.dataTransfer.types.includes(DND_TYPES.SECTION_MOVE);\n}\n\nexport function isDropAllowed(e: React.DragEvent): boolean {\n return (\n e.dataTransfer.types.includes(DND_TYPES.BLOCK_TYPE) ||\n e.dataTransfer.types.includes(DND_TYPES.BLOCK_ID)\n );\n}\n",".sidebar {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n.sectionTitle {\n font-size: var(--ee-font-size-sm);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: var(--ee-space-md) var(--ee-space-lg);\n margin: 0;\n border-bottom: 1px solid var(--ee-border-color);\n}\n\n/* Block Palette */\n.blockPalette {\n padding: var(--ee-space-sm);\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--ee-space-sm);\n}\n\n.blockCard {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--ee-space-xs);\n padding: var(--ee-space-md) var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n cursor: grab;\n transition: all var(--ee-transition-fast);\n user-select: none;\n}\n\n.blockCard:hover {\n border-color: var(--ee-border-focus);\n background: var(--ee-bg-selected);\n box-shadow: var(--ee-shadow-sm);\n}\n\n.blockCard:active {\n cursor: grabbing;\n opacity: 0.7;\n}\n\n.blockCardIcon {\n font-size: 20px;\n line-height: 1;\n}\n\n.blockCardLabel {\n font-size: var(--ee-font-size-sm);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-primary);\n}\n\n/* Variable List */\n.variableList {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n}\n\n.variableHint {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-muted);\n margin: 0 0 var(--ee-space-sm) 0;\n line-height: 1.4;\n font-style: italic;\n}\n\n.variableGroup {\n margin-bottom: var(--ee-space-md);\n}\n\n.variableGroupTitle {\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-muted);\n margin: 0 0 var(--ee-space-xs) 0;\n text-transform: uppercase;\n}\n\n.variableChips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--ee-space-xs);\n}\n\n.variableChip {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 2px 8px;\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-medium);\n background: var(--ee-variable-bg);\n color: var(--ee-variable-color);\n border: 1px solid var(--ee-variable-border);\n border-radius: 12px;\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n white-space: nowrap;\n}\n\n.variableChip:hover {\n background: var(--ee-color-primary-light);\n border-color: var(--ee-color-primary);\n transform: translateY(-1px);\n box-shadow: var(--ee-shadow-sm);\n}\n\n.variableChip:active {\n transform: translateY(0);\n box-shadow: none;\n}\n\n.variableChipInserted {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n transition: all 0.15s ease;\n}\n\n.variableChipCustom {\n background: var(--ee-color-success-light);\n color: var(--ee-color-success-text);\n border-color: var(--ee-color-success-border);\n}\n\n.variableChipCustom:hover {\n background: var(--ee-color-success-light-hover);\n border-color: var(--ee-color-success);\n}\n\n.variableChipDelete {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n margin-left: 2px;\n padding: 0;\n font-size: 9px;\n line-height: 1;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n color: inherit;\n opacity: 0.5;\n transition: all var(--ee-transition-fast);\n}\n\n.variableChipDelete:hover {\n opacity: 1;\n background: var(--ee-overlay-subtle);\n}\n\n.variableChipIcon {\n font-size: 11px;\n}\n\n/* Add Variable */\n.addVariableSection {\n padding: var(--ee-space-xs) var(--ee-space-lg) var(--ee-space-lg);\n}\n\n.addVariableBtn {\n width: 100%;\n padding: 6px 12px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-color-primary);\n background: transparent;\n border: 1px dashed var(--ee-color-primary);\n border-radius: var(--ee-border-radius);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.addVariableBtn:hover {\n background: var(--ee-color-primary-light);\n}\n\n.addVariableForm {\n display: flex;\n flex-direction: column;\n gap: var(--ee-space-sm);\n padding: var(--ee-space-md);\n background: var(--ee-bg-hover);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n}\n\n.addVariableField {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.addVariableLabel {\n font-size: 10px;\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.addVariableInput {\n width: 100%;\n padding: 5px 8px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n box-sizing: border-box;\n transition: border-color var(--ee-transition-fast);\n}\n\n.addVariableInput:focus {\n border-color: var(--ee-border-focus);\n box-shadow: var(--ee-shadow-focus);\n}\n\n.addVariableError {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-color-danger);\n padding: 2px 0;\n}\n\n.addVariableActions {\n display: flex;\n gap: var(--ee-space-sm);\n justify-content: flex-end;\n padding-top: var(--ee-space-xs);\n}\n\n.addVariableCancelBtn {\n padding: 4px 12px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n color: var(--ee-text-secondary);\n background: transparent;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.addVariableCancelBtn:hover {\n background: var(--ee-bg-hover);\n}\n\n.addVariableSubmitBtn {\n padding: 4px 16px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-inverse);\n background: var(--ee-color-primary);\n border: 1px solid var(--ee-color-primary);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.addVariableSubmitBtn:hover {\n background: var(--ee-color-primary-hover);\n}\n\n/* Layout section */\n.layoutSection {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n}\n\n.layoutOption {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n padding: var(--ee-space-sm) var(--ee-space-md);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n cursor: pointer;\n margin-bottom: var(--ee-space-xs);\n transition: all var(--ee-transition-fast);\n}\n\n.layoutOption:hover {\n border-color: var(--ee-border-focus);\n background: var(--ee-bg-selected);\n}\n\n.layoutPreview {\n display: flex;\n gap: 2px;\n flex: 1;\n height: 20px;\n}\n\n.layoutColumn {\n background: var(--ee-color-primary-light);\n border: 1px solid var(--ee-color-primary);\n border-radius: 2px;\n height: 100%;\n}\n\n.layoutLabel {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-secondary);\n white-space: nowrap;\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useEditorVariables } from '../../context/EditorContext';\nimport { groupVariables } from '../../utils/variables';\nimport styles from '../../styles/sidebar.module.css';\n\nexport function VariableList() {\n const { variables, customVariables, insertVariable, removeCustomVariable } = useEditorVariables();\n const [flashKey, setFlashKey] = useState<string | null>(null);\n const flashTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Cleanup flash timer on unmount\n useEffect(() => {\n return () => {\n if (flashTimerRef.current !== null) clearTimeout(flashTimerRef.current);\n };\n }, []);\n\n const customKeys = new Set(customVariables.map((v) => v.key));\n\n const handleChipClick = useCallback(\n (key: string) => {\n const inserted = insertVariable(key);\n if (inserted) {\n setFlashKey(key);\n if (flashTimerRef.current !== null) clearTimeout(flashTimerRef.current);\n flashTimerRef.current = setTimeout(() => {\n flashTimerRef.current = null;\n setFlashKey(null);\n }, 400);\n }\n },\n [insertVariable],\n );\n\n const handleDelete = useCallback(\n (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n removeCustomVariable(key);\n },\n [removeCustomVariable],\n );\n\n if (variables.length === 0) {\n return (\n <div className={`ee-variable-list ${styles.variableList}`}>\n <p className={`ee-variable-hint ${styles.variableHint}`}>\n No variables yet. Add one below.\n </p>\n </div>\n );\n }\n\n const grouped = groupVariables(variables);\n\n return (\n <div className={`ee-variable-list ${styles.variableList}`}>\n <p className={`ee-variable-hint ${styles.variableHint}`}>\n Click to insert at cursor, or drag into text.\n </p>\n {Array.from(grouped.entries()).map(([group, vars]) => (\n <div key={group} className={`ee-variable-group ${styles.variableGroup}`}>\n <h4 className={`ee-variable-group-title ${styles.variableGroupTitle}`}>{group}</h4>\n <div className={`ee-variable-chips ${styles.variableChips}`}>\n {vars.map((v) => (\n <span\n key={v.key}\n className={`ee-variable-chip ${styles.variableChip} ${flashKey === v.key ? styles.variableChipInserted : ''} ${customKeys.has(v.key) ? styles.variableChipCustom : ''}`}\n title={`Click to insert${v.sample ? ` • Sample: ${v.sample}` : ''}${customKeys.has(v.key) ? ' • Custom variable' : ''}`}\n onClick={() => handleChipClick(v.key)}\n draggable\n onDragStart={(e) => {\n e.dataTransfer.setData('text/plain', `{{ ${v.key} }}`);\n e.dataTransfer.setData('application/x-variable-key', v.key);\n }}\n >\n {v.icon && <span className={`ee-variable-chip-icon ${styles.variableChipIcon}`}>{v.icon}</span>}\n {v.label ?? v.key}\n {customKeys.has(v.key) && (\n <button\n className={`ee-variable-chip-delete ${styles.variableChipDelete}`}\n onClick={(e) => handleDelete(v.key, e)}\n title=\"Remove variable\"\n >\n x\n </button>\n )}\n </span>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import type { Variable } from '../types';\n\nconst VARIABLE_REGEX = /\\{\\{\\s*([^}]+?)\\s*\\}\\}/g;\n\nexport function extractVariableKeys(text: string): string[] {\n const seen = new Set<string>();\n const keys: string[] = [];\n for (const match of text.matchAll(VARIABLE_REGEX)) {\n const key = match[1].trim();\n if (!seen.has(key)) {\n seen.add(key);\n keys.push(key);\n }\n }\n return keys;\n}\n\nexport function replaceVariables(\n text: string,\n variables: Variable[],\n useSample = true,\n): string {\n return text.replace(VARIABLE_REGEX, (_match, key: string) => {\n const trimmedKey = key.trim();\n const variable = variables.find((v) => v.key === trimmedKey);\n if (!variable) return `{{ ${trimmedKey} }}`;\n return useSample && variable.sample ? variable.sample : `{{ ${trimmedKey} }}`;\n });\n}\n\nexport function groupVariables(variables: Variable[]): Map<string, Variable[]> {\n const groups = new Map<string, Variable[]>();\n for (const variable of variables) {\n const group = variable.group ?? 'General';\n const existing = groups.get(group) ?? [];\n existing.push(variable);\n groups.set(group, existing);\n }\n return groups;\n}\n","import React, { useState, useCallback } from 'react';\nimport { useEditorVariables } from '../../context/EditorContext';\nimport styles from '../../styles/sidebar.module.css';\n\nexport function AddVariableForm() {\n const { variables, addCustomVariable } = useEditorVariables();\n const [isOpen, setIsOpen] = useState(false);\n const [key, setKey] = useState('');\n const [label, setLabel] = useState('');\n const [group, setGroup] = useState('Custom');\n const [error, setError] = useState<string | null>(null);\n\n const resetForm = useCallback(() => {\n setKey('');\n setLabel('');\n setGroup('Custom');\n setError(null);\n }, []);\n\n const handleSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedKey = key.trim().toLowerCase().replace(/\\s+/g, '_').replace(/[^a-z0-9_]/g, '');\n if (!trimmedKey) {\n setError('Variable key is required');\n return;\n }\n\n if (variables.some((v) => v.key === trimmedKey)) {\n setError(`Variable \"${trimmedKey}\" already exists`);\n return;\n }\n\n addCustomVariable({\n key: trimmedKey,\n label: label.trim() || trimmedKey,\n group: group.trim() || 'Custom',\n });\n\n resetForm();\n setIsOpen(false);\n },\n [key, label, group, variables, addCustomVariable, resetForm],\n );\n\n const handleCancel = useCallback(() => {\n resetForm();\n setIsOpen(false);\n }, [resetForm]);\n\n if (!isOpen) {\n return (\n <button\n className={`ee-add-variable-btn ${styles.addVariableBtn}`}\n onClick={() => setIsOpen(true)}\n >\n + Add Variable\n </button>\n );\n }\n\n return (\n <form className={`ee-add-variable-form ${styles.addVariableForm}`} onSubmit={handleSubmit}>\n <div className={`ee-add-variable-field ${styles.addVariableField}`}>\n <label className={`ee-add-variable-label ${styles.addVariableLabel}`}>Key *</label>\n <input\n className={`ee-add-variable-input ${styles.addVariableInput}`}\n value={key}\n onChange={(e) => {\n setKey(e.target.value);\n setError(null);\n }}\n placeholder=\"e.g. coupon_code\"\n autoFocus\n />\n </div>\n <div className={`ee-add-variable-field ${styles.addVariableField}`}>\n <label className={`ee-add-variable-label ${styles.addVariableLabel}`}>Label</label>\n <input\n className={`ee-add-variable-input ${styles.addVariableInput}`}\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder=\"e.g. Coupon Code\"\n />\n </div>\n <div className={`ee-add-variable-field ${styles.addVariableField}`}>\n <label className={`ee-add-variable-label ${styles.addVariableLabel}`}>Group</label>\n <input\n className={`ee-add-variable-input ${styles.addVariableInput}`}\n value={group}\n onChange={(e) => setGroup(e.target.value)}\n placeholder=\"Custom\"\n />\n </div>\n {error && <div className={`ee-add-variable-error ${styles.addVariableError}`}>{error}</div>}\n <div className={`ee-add-variable-actions ${styles.addVariableActions}`}>\n <button type=\"button\" className={`ee-add-variable-cancel ${styles.addVariableCancelBtn}`} onClick={handleCancel}>\n Cancel\n </button>\n <button type=\"submit\" className={`ee-add-variable-submit ${styles.addVariableSubmitBtn}`}>\n Add\n </button>\n </div>\n </form>\n );\n}\n","import React, { useCallback, useState } from 'react';\nimport { Section } from './Section';\nimport { SectionDropZone } from './SectionDropZone';\nimport { useTemplateContext, useEditorDispatch } from '../../context/EditorContext';\nimport { createSection, createSectionWithBlock } from '../../utils/factory';\nimport { isDropAllowed, getBlockTypeFromDrop } from '../../utils/dnd';\nimport styles from '../../styles/canvas.module.css';\n\nexport const Canvas = React.memo(function Canvas() {\n const { template } = useTemplateContext();\n const dispatch = useEditorDispatch();\n const [isDragOver, setIsDragOver] = useState(false);\n\n const handleAddSection = useCallback(() => {\n dispatch({ type: 'ADD_SECTION', payload: { section: createSection() } });\n }, [dispatch]);\n\n const handleCanvasClick = useCallback(() => {\n dispatch({ type: 'DESELECT_ALL' });\n }, [dispatch]);\n\n const handleBodyDragOver = useCallback((e: React.DragEvent) => {\n if (!isDropAllowed(e)) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n setIsDragOver(true);\n }, []);\n\n const handleBodyDragLeave = useCallback((e: React.DragEvent) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom) {\n return;\n }\n setIsDragOver(false);\n }, []);\n\n const handleBodyDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragOver(false);\n\n const blockType = getBlockTypeFromDrop(e);\n if (!blockType) return;\n\n const section = createSectionWithBlock(blockType);\n const column = section.columns[0];\n const block = column.blocks[0];\n\n dispatch({ type: 'ADD_SECTION', payload: { section } });\n dispatch({\n type: 'SELECT_BLOCK',\n payload: { sectionId: section.id, columnId: column.id, blockId: block.id },\n });\n // Note: ADD_SECTION must happen first so the section exists before selection.\n // These are both cheap (SELECT_BLOCK is UI-only, no history push).\n },\n [dispatch],\n );\n\n return (\n <div className={`ee-canvas-wrapper ${styles.canvasWrapper}`} onClick={handleCanvasClick} role=\"main\" aria-label=\"Email canvas\">\n <div\n className={`ee-canvas-body ${styles.canvasBody} ${isDragOver ? styles.canvasBodyDragOver : ''}`}\n style={{\n width: template.globalStyles.width,\n backgroundColor: template.globalStyles.backgroundColor,\n fontFamily: template.globalStyles.fontFamily,\n }}\n onClick={(e) => e.stopPropagation()}\n onDragOver={handleBodyDragOver}\n onDragLeave={handleBodyDragLeave}\n onDrop={handleBodyDrop}\n aria-label=\"Email content area\"\n >\n {template.sections.map((section, index) => (\n <React.Fragment key={section.id}>\n <SectionDropZone index={index} />\n <Section section={section} />\n </React.Fragment>\n ))}\n {template.sections.length > 0 && (\n <SectionDropZone index={template.sections.length} />\n )}\n <button className={`ee-add-section ${styles.addSectionBtn}`} onClick={handleAddSection} aria-label=\"Add new section\">\n + Add Section\n </button>\n </div>\n </div>\n );\n});\n","import React, { useCallback, useState } from 'react';\nimport type { Section as SectionType } from '../../types';\nimport { Column } from './Column';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { useSelectionContext, useEditorDispatch, useTemplateContext } from '../../context/EditorContext';\nimport { setSectionMoveDragData } from '../../utils/dnd';\nimport styles from '../../styles/canvas.module.css';\n\ninterface SectionProps {\n section: SectionType;\n}\n\nexport const Section = React.memo(function Section({ section }: SectionProps) {\n const selection = useSelectionContext();\n const dispatch = useEditorDispatch();\n const { template } = useTemplateContext();\n const isSelected = selection.sectionId === section.id && !selection.blockId;\n const [showRemoveConfirm, setShowRemoveConfirm] = useState(false);\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n dispatch({ type: 'SELECT_SECTION', payload: { sectionId: section.id } });\n },\n [dispatch, section.id],\n );\n\n const handleRemove = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n setShowRemoveConfirm(true);\n },\n [],\n );\n\n const handleConfirmRemove = useCallback(() => {\n dispatch({ type: 'REMOVE_SECTION', payload: { sectionId: section.id } });\n setShowRemoveConfirm(false);\n }, [dispatch, section.id]);\n\n const handleDuplicate = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n dispatch({ type: 'DUPLICATE_SECTION', payload: { sectionId: section.id } });\n },\n [dispatch, section.id],\n );\n\n const handleDragStart = useCallback(\n (e: React.DragEvent) => {\n setSectionMoveDragData(e, section.id);\n },\n [section.id],\n );\n\n const handleDragKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n e.preventDefault();\n e.stopPropagation();\n const sections = template.sections;\n const currentIndex = sections.findIndex((s) => s.id === section.id);\n if (currentIndex === -1) return;\n const toIndex = e.key === 'ArrowUp' ? currentIndex - 1 : currentIndex + 1;\n if (toIndex < 0 || toIndex >= sections.length) return;\n dispatch({ type: 'MOVE_SECTION', payload: { sectionId: section.id, toIndex } });\n },\n [dispatch, section.id, template.sections],\n );\n\n return (\n <div\n className={`ee-section ${isSelected ? 'ee-section--selected' : ''} ${section.properties.fullWidth ? 'ee-section--full-width' : ''} ${styles.section} ${isSelected ? styles.sectionSelected : ''} ${section.properties.fullWidth ? styles.sectionFullWidth : ''}`}\n style={{\n backgroundColor: section.properties.backgroundColor,\n padding: section.properties.padding,\n borderRadius: section.properties.borderRadius,\n backgroundImage: section.properties.backgroundImage ? `url(${section.properties.backgroundImage})` : undefined,\n backgroundSize: section.properties.backgroundSize || undefined,\n backgroundRepeat: section.properties.backgroundRepeat || undefined,\n }}\n onClick={handleClick}\n role=\"region\"\n aria-label={`Email section${isSelected ? ' (selected)' : ''}`}\n aria-selected={isSelected}\n >\n <div className={`ee-section-actions ${styles.sectionOverlay}`} role=\"group\" aria-label=\"Section actions\">\n <span\n className={`ee-section-drag ${styles.sectionDragHandle}`}\n draggable\n onDragStart={handleDragStart}\n onKeyDown={handleDragKeyDown}\n title=\"Drag to reorder (or use Arrow keys)\"\n role=\"button\"\n aria-label=\"Reorder section with Arrow Up/Down keys\"\n tabIndex={0}\n >\n ⠿\n </span>\n <button\n className={`ee-section-duplicate ${styles.sectionBtn} ${styles.sectionBtnDuplicate}`}\n onClick={handleDuplicate}\n title=\"Duplicate section\"\n aria-label=\"Duplicate section\"\n >\n ⧉\n </button>\n <button\n className={`ee-section-remove ${styles.sectionBtn}`}\n onClick={handleRemove}\n title=\"Remove section\"\n aria-label=\"Remove section\"\n >\n x\n </button>\n </div>\n <div className={styles.sectionContent}>\n {section.columns.map((column) => (\n <Column key={column.id} column={column} sectionId={section.id} />\n ))}\n </div>\n {showRemoveConfirm && (\n <ConfirmDialog\n title=\"Remove Section\"\n message=\"Are you sure you want to remove this section and all its contents? This action can be undone with Ctrl+Z.\"\n onConfirm={handleConfirmRemove}\n onCancel={() => setShowRemoveConfirm(false)}\n />\n )}\n </div>\n );\n});\n","import React, { useCallback, useState } from 'react';\nimport type { Column as ColumnType } from '../../types';\nimport { BlockRenderer } from './BlockRenderer';\nimport { DropZone } from './DropZone';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { useSelectionContext, useEditorDispatch } from '../../context/EditorContext';\nimport {\n setBlockMoveDragData,\n isDropAllowed,\n getBlockTypeFromDrop,\n getBlockMoveFromDrop,\n DND_TYPES,\n} from '../../utils/dnd';\nimport { generateBlockId } from '../../utils/id';\nimport { DEFAULT_BLOCK_PROPERTIES } from '../../constants';\nimport styles from '../../styles/canvas.module.css';\n\ninterface ColumnProps {\n column: ColumnType;\n sectionId: string;\n}\n\n/** Read block ID and index from a block wrapper element's data attributes */\nfunction getBlockData(e: React.SyntheticEvent): { blockId: string; index: number } | null {\n const el = (e.currentTarget as HTMLElement);\n const blockId = el.dataset.blockId;\n const index = el.dataset.blockIndex;\n if (!blockId || index === undefined) return null;\n return { blockId, index: Number(index) };\n}\n\nexport const Column = React.memo(function Column({ column, sectionId }: ColumnProps) {\n const selection = useSelectionContext();\n const dispatch = useEditorDispatch();\n const [blockToRemove, setBlockToRemove] = useState<string | null>(null);\n\n const confirmRemoveBlock = useCallback(\n (blockId: string) => {\n setBlockToRemove(blockId);\n },\n [],\n );\n\n const handleConfirmRemove = useCallback(() => {\n if (blockToRemove) {\n dispatch({\n type: 'REMOVE_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: blockToRemove },\n });\n setBlockToRemove(null);\n }\n }, [dispatch, sectionId, column.id, blockToRemove]);\n\n // Single click handler — reads blockId from data attribute\n const handleBlockClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const data = getBlockData(e);\n if (!data) return;\n dispatch({\n type: 'SELECT_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: data.blockId },\n });\n },\n [dispatch, sectionId, column.id],\n );\n\n // Action button handlers use event delegation — walk up to find block wrapper\n const handleRemoveClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const wrapper = (e.currentTarget as HTMLElement).closest('[data-block-id]') as HTMLElement | null;\n if (wrapper?.dataset.blockId) confirmRemoveBlock(wrapper.dataset.blockId);\n },\n [confirmRemoveBlock],\n );\n\n const handleDuplicateClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const wrapper = (e.currentTarget as HTMLElement).closest('[data-block-id]') as HTMLElement | null;\n if (wrapper?.dataset.blockId) {\n dispatch({\n type: 'DUPLICATE_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: wrapper.dataset.blockId },\n });\n }\n },\n [dispatch, sectionId, column.id],\n );\n\n const handleBlockDragStart = useCallback(\n (e: React.DragEvent) => {\n const data = getBlockData(e);\n if (!data) return;\n setBlockMoveDragData(e, data.blockId, sectionId, column.id);\n },\n [sectionId, column.id],\n );\n\n // Block-level drop detection: determines top/bottom half for precise insertion\n const [dropTarget, setDropTarget] = useState<{\n blockId: string;\n position: 'before' | 'after';\n } | null>(null);\n\n const handleBlockDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!isDropAllowed(e)) return;\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.dropEffect = e.dataTransfer.types.includes(DND_TYPES.BLOCK_ID)\n ? 'move'\n : 'copy';\n const data = getBlockData(e);\n if (!data) return;\n const rect = e.currentTarget.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position: 'before' | 'after' = e.clientY < midY ? 'before' : 'after';\n setDropTarget((prev) => {\n if (prev?.blockId === data.blockId && prev?.position === position) return prev;\n return { blockId: data.blockId, position };\n });\n },\n [],\n );\n\n const handleBlockDragLeave = useCallback((e: React.DragEvent) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX >= rect.left &&\n clientX <= rect.right &&\n clientY >= rect.top &&\n clientY <= rect.bottom\n ) {\n return;\n }\n setDropTarget(null);\n }, []);\n\n const handleBlockDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDropTarget(null);\n\n const data = getBlockData(e);\n if (!data) return;\n const rect = e.currentTarget.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const insertIndex = e.clientY < midY ? data.index : data.index + 1;\n\n const blockType = getBlockTypeFromDrop(e);\n if (blockType) {\n const newBlock = {\n id: generateBlockId(),\n type: blockType,\n properties: JSON.parse(JSON.stringify(DEFAULT_BLOCK_PROPERTIES[blockType])),\n };\n dispatch({\n type: 'ADD_BLOCK_AND_SELECT',\n payload: { sectionId, columnId: column.id, block: newBlock, index: insertIndex },\n });\n return;\n }\n\n const moveData = getBlockMoveFromDrop(e);\n if (moveData) {\n dispatch({\n type: 'MOVE_BLOCK',\n payload: {\n fromSectionId: moveData.sectionId,\n fromColumnId: moveData.columnId,\n blockId: moveData.blockId,\n toSectionId: sectionId,\n toColumnId: column.id,\n toIndex: insertIndex,\n },\n });\n }\n },\n [dispatch, sectionId, column.id],\n );\n\n const handleBlockKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if (target.isContentEditable || target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {\n return;\n }\n const data = getBlockData(e);\n if (!data) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n dispatch({\n type: 'SELECT_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: data.blockId },\n });\n } else if (e.key === 'Delete' || e.key === 'Backspace') {\n e.preventDefault();\n e.stopPropagation();\n confirmRemoveBlock(data.blockId);\n }\n },\n [dispatch, sectionId, column.id, confirmRemoveBlock],\n );\n\n if (column.blocks.length === 0) {\n return (\n <div className={`ee-column ${styles.column}`} style={{ width: column.width }}>\n <DropZone\n sectionId={sectionId}\n columnId={column.id}\n index={0}\n emptyPlaceholder\n />\n </div>\n );\n }\n\n return (\n <div className={`ee-column ${styles.column}`} style={{ width: column.width }}>\n {column.blocks.map((block, index) => (\n <React.Fragment key={block.id}>\n <DropZone sectionId={sectionId} columnId={column.id} index={index} />\n <div\n data-block-type={block.type}\n data-block-id={block.id}\n data-block-index={index}\n className={[\n 'ee-block',\n `ee-block--${block.type}`,\n selection.blockId === block.id && 'ee-block--selected',\n styles.blockWrapper,\n selection.blockId === block.id && styles.blockSelected,\n dropTarget?.blockId === block.id &&\n dropTarget.position === 'before' &&\n styles.blockDropBefore,\n dropTarget?.blockId === block.id &&\n dropTarget.position === 'after' &&\n styles.blockDropAfter,\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={handleBlockClick}\n draggable\n onDragStart={handleBlockDragStart}\n onDragOver={handleBlockDragOver}\n onDragLeave={handleBlockDragLeave}\n onDrop={handleBlockDrop}\n onKeyDown={handleBlockKeyDown}\n role=\"button\"\n aria-label={`${block.type} block${selection.blockId === block.id ? ' (selected)' : ''}`}\n aria-selected={selection.blockId === block.id}\n tabIndex={0}\n >\n <div className={`ee-block-actions ${styles.blockOverlay}`} role=\"group\" aria-label=\"Block actions\">\n <button\n className={`ee-block-duplicate ${styles.blockBtn} ${styles.blockBtnDuplicate}`}\n onClick={handleDuplicateClick}\n title=\"Duplicate block\"\n aria-label=\"Duplicate block\"\n >\n ⧉\n </button>\n <button\n className={`ee-block-remove ${styles.blockBtn}`}\n onClick={handleRemoveClick}\n title=\"Remove block\"\n aria-label=\"Remove block\"\n >\n x\n </button>\n </div>\n <BlockRenderer block={block} />\n </div>\n </React.Fragment>\n ))}\n <DropZone\n sectionId={sectionId}\n columnId={column.id}\n index={column.blocks.length}\n />\n {blockToRemove && (\n <ConfirmDialog\n title=\"Remove Block\"\n message=\"Are you sure you want to remove this block? This action can be undone with Ctrl+Z.\"\n onConfirm={handleConfirmRemove}\n onCancel={() => setBlockToRemove(null)}\n />\n )}\n </div>\n );\n});\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { blockRendererRegistry, registerBlockRenderer } from '../../registry';\nimport { ErrorBoundary } from '../ErrorBoundary';\nimport { TextBlock } from './blocks/TextBlock';\nimport { ButtonBlock } from './blocks/ButtonBlock';\nimport { ImageBlock } from './blocks/ImageBlock';\nimport { DividerBlock } from './blocks/DividerBlock';\nimport { SpacerBlock } from './blocks/SpacerBlock';\nimport { SocialBlock } from './blocks/SocialBlock';\nimport { HtmlBlock } from './blocks/HtmlBlock';\nimport { VideoBlock } from './blocks/VideoBlock';\nimport { HeadingBlock } from './blocks/HeadingBlock';\nimport { CountdownBlock } from './blocks/CountdownBlock';\nimport { MenuBlock } from './blocks/MenuBlock';\nimport { HeroBlock } from './blocks/HeroBlock';\n\n// Register built-in block renderers\nregisterBlockRenderer('text', TextBlock);\nregisterBlockRenderer('button', ButtonBlock);\nregisterBlockRenderer('image', ImageBlock);\nregisterBlockRenderer('divider', DividerBlock);\nregisterBlockRenderer('spacer', SpacerBlock);\nregisterBlockRenderer('social', SocialBlock);\nregisterBlockRenderer('html', HtmlBlock);\nregisterBlockRenderer('video', VideoBlock);\nregisterBlockRenderer('heading', HeadingBlock);\nregisterBlockRenderer('countdown', CountdownBlock);\nregisterBlockRenderer('menu', MenuBlock);\nregisterBlockRenderer('hero', HeroBlock);\n\ninterface BlockRendererProps {\n block: Block;\n}\n\nexport const BlockRenderer = React.memo(function BlockRenderer({ block }: BlockRendererProps) {\n const Component = blockRendererRegistry[block.type];\n if (!Component) return null;\n return (\n <ErrorBoundary>\n <Component block={block} />\n </ErrorBoundary>\n );\n});\n","import React, { useCallback, useRef, useState, useEffect, useReducer, useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport { useEditorDispatch, useMethodsContext } from '../../../context/EditorContext';\nimport { TipTapEditor } from '../../../tiptap/TipTapEditor';\nimport { RichTextToolbar } from '../../Toolbar/RichTextToolbar';\nimport type { Editor } from '@tiptap/core';\nimport styles from '../../../styles/blocks.module.css';\nimport tiptapStyles from '../../../styles/tiptap.module.css';\n\ninterface TextBlockProps {\n block: Block;\n}\n\nconst TextBlockInner = function TextBlock({ block }: TextBlockProps) {\n const dispatch = useEditorDispatch();\n const { setActiveEditor } = useMethodsContext();\n const editorRef = useRef<Editor | null>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const blurTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n // Track the editor instance in state so the effect has a proper dependency\n const [editorInstance, setEditorInstance] = useState<Editor | null>(null);\n\n // Force toolbar re-render when editor formatting state changes (selection/transaction)\n const [, forceToolbarUpdate] = useReducer((c: number) => c + 1, 0);\n\n useEffect(() => {\n if (!editorInstance) return;\n\n const onStateChange = () => forceToolbarUpdate();\n editorInstance.on('selectionUpdate', onStateChange);\n editorInstance.on('transaction', onStateChange);\n\n return () => {\n editorInstance.off('selectionUpdate', onStateChange);\n editorInstance.off('transaction', onStateChange);\n };\n }, [editorInstance]);\n\n const handleUpdate = useCallback(\n (html: string) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: { blockId: block.id, properties: { content: html } },\n });\n },\n [dispatch, block.id],\n );\n\n const handleFocus = useCallback(() => {\n setActiveEditor(editorRef.current);\n setIsFocused(true);\n }, [setActiveEditor]);\n\n // Cleanup blur timer on unmount\n useEffect(() => {\n return () => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n };\n }, []);\n\n const handleBlur = useCallback(() => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n blurTimerRef.current = setTimeout(() => {\n blurTimerRef.current = null;\n const activeEl = document.activeElement;\n if (wrapperRef.current && wrapperRef.current.contains(activeEl)) {\n return;\n }\n if (editorRef.current && !editorRef.current.isFocused) {\n setActiveEditor(null);\n setIsFocused(false);\n }\n }, 200);\n }, [setActiveEditor]);\n\n const handleEditorRef = useCallback((editor: Editor | null) => {\n editorRef.current = editor;\n setEditorInstance(editor);\n }, []);\n\n const p = block.properties;\n const wrapperStyle = useMemo(() => ({\n fontFamily: p.fontFamily,\n fontSize: p.fontSize,\n color: p.color,\n lineHeight: p.lineHeight,\n padding: p.padding,\n fontWeight: p.fontWeight,\n textTransform: p.textTransform,\n letterSpacing: p.letterSpacing,\n }), [p.fontFamily, p.fontSize, p.color, p.lineHeight, p.padding, p.fontWeight, p.textTransform, p.letterSpacing]);\n\n return (\n <div className={`ee-block-text ${styles.textBlock}`} ref={wrapperRef}>\n {isFocused && editorRef.current && (\n <div className={styles.textBlockToolbar}>\n <RichTextToolbar editor={editorRef.current} />\n </div>\n )}\n <div style={wrapperStyle}>\n <TipTapEditor\n content={block.properties.content}\n onUpdate={handleUpdate}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className={tiptapStyles.tiptapWrapper}\n editorRef={handleEditorRef}\n placeholder=\"Edit this text...\"\n />\n </div>\n </div>\n );\n};\n\nexport const TextBlock = React.memo(TextBlockInner);\n","import React, { useMemo, useEffect, useRef } from 'react';\nimport { useEditor as useTipTapEditor, EditorContent } from '@tiptap/react';\nimport type { Editor } from '@tiptap/core';\nimport { getExtensions } from './extensions';\nimport { cleanPastedHTML } from './pasteClean';\n\nexport interface TipTapEditorProps {\n content: string;\n onUpdate: (html: string) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n editable?: boolean;\n className?: string;\n editorRef?: (editor: Editor | null) => void;\n placeholder?: string;\n}\n\nexport function TipTapEditor({\n content,\n onUpdate,\n onFocus,\n onBlur,\n editable = true,\n className,\n editorRef,\n placeholder,\n}: TipTapEditorProps) {\n // Memoize extensions to prevent TipTap editor re-creation on every render\n const extensions = useMemo(() => getExtensions(placeholder), [placeholder]);\n\n // Use refs for callbacks to avoid stale closures in TipTap event handlers\n const onUpdateRef = useRef(onUpdate);\n onUpdateRef.current = onUpdate;\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n const editorRefCb = useRef(editorRef);\n editorRefCb.current = editorRef;\n\n const editor = useTipTapEditor({\n extensions,\n content,\n editable,\n editorProps: {\n transformPastedHTML(html) {\n return cleanPastedHTML(html);\n },\n },\n onUpdate: ({ editor: e }) => {\n onUpdateRef.current(e.getHTML());\n },\n onFocus: () => onFocusRef.current?.(),\n onBlur: () => onBlurRef.current?.(),\n onCreate: ({ editor: e }) => {\n editorRefCb.current?.(e);\n },\n onDestroy: () => {\n editorRefCb.current?.(null);\n },\n });\n\n // Sync content from external changes (undo/redo, loadJSON, loadMJML)\n // Only update if the editor is not focused (user is not actively editing)\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n if (editor.isFocused) return;\n const currentHTML = editor.getHTML();\n if (currentHTML !== content) {\n editor.commands.setContent(content, false);\n }\n }, [editor, content]);\n\n return (\n <div className={className}>\n <EditorContent editor={editor} />\n </div>\n );\n}\n\nexport { useTipTapEditor };\n","import StarterKit from '@tiptap/starter-kit';\nimport Underline from '@tiptap/extension-underline';\nimport TextAlign from '@tiptap/extension-text-align';\nimport TextStyle from '@tiptap/extension-text-style';\nimport Color from '@tiptap/extension-color';\nimport Highlight from '@tiptap/extension-highlight';\nimport Link from '@tiptap/extension-link';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport { VariableNode } from './VariableNode';\nimport { FontSize } from './FontSize';\nimport { FontFamily } from './FontFamily';\n\nexport function getExtensions(placeholder?: string) {\n return [\n StarterKit.configure({\n history: false,\n }),\n Underline,\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n alignments: ['left', 'center', 'right', 'justify'],\n }),\n TextStyle,\n Color,\n FontSize,\n FontFamily,\n Highlight.configure({\n multicolor: true,\n }),\n Link.configure({\n openOnClick: false,\n HTMLAttributes: {\n rel: 'noopener noreferrer',\n target: '_blank',\n },\n }),\n Placeholder.configure({\n placeholder: placeholder ?? 'Type something...',\n }),\n VariableNode,\n ];\n}\n","import { Node, mergeAttributes } from '@tiptap/core';\n\nexport interface VariableNodeAttrs {\n key: string;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n variableNode: {\n insertVariable: (key: string) => ReturnType;\n };\n }\n}\n\nexport const VariableNode = Node.create({\n name: 'variable',\n group: 'inline',\n inline: true,\n atom: true,\n\n addAttributes() {\n return {\n key: {\n default: '',\n parseHTML: (element: HTMLElement) => element.getAttribute('data-variable-key'),\n renderHTML: (attributes: Record<string, any>) => ({\n 'data-variable-key': attributes.key,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-variable-key]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'span',\n mergeAttributes(HTMLAttributes, {\n class: 'ee-variable-chip',\n contenteditable: 'false',\n }),\n `{{ ${HTMLAttributes['data-variable-key']} }}`,\n ];\n },\n\n addCommands() {\n return {\n insertVariable:\n (key: string) =>\n ({ commands }) => {\n return commands.insertContent({\n type: this.name,\n attrs: { key },\n });\n },\n };\n },\n});\n","import { Extension } from '@tiptap/core';\nimport '@tiptap/extension-text-style';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n fontSize: {\n setFontSize: (size: string) => ReturnType;\n unsetFontSize: () => ReturnType;\n };\n }\n}\n\nexport const FontSize = Extension.create({\n name: 'fontSize',\n\n addOptions() {\n return {\n types: ['textStyle'],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontSize: {\n default: null,\n parseHTML: (element: HTMLElement) => element.style.fontSize || null,\n renderHTML: (attributes: Record<string, any>) => {\n if (!attributes.fontSize) return {};\n return { style: `font-size: ${attributes.fontSize}` };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontSize:\n (fontSize: string) =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontSize }).run();\n },\n unsetFontSize:\n () =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontSize: null }).removeEmptyTextStyle().run();\n },\n };\n },\n});\n","import { Extension } from '@tiptap/core';\nimport '@tiptap/extension-text-style';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n fontFamily: {\n setFontFamily: (fontFamily: string) => ReturnType;\n unsetFontFamily: () => ReturnType;\n };\n }\n}\n\nexport const FontFamily = Extension.create({\n name: 'fontFamily',\n\n addOptions() {\n return {\n types: ['textStyle'],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontFamily: {\n default: null,\n parseHTML: (element: HTMLElement) => element.style.fontFamily?.replace(/['\"]/g, '') || null,\n renderHTML: (attributes: Record<string, any>) => {\n if (!attributes.fontFamily) return {};\n return { style: `font-family: ${attributes.fontFamily}` };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontFamily:\n (fontFamily: string) =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontFamily }).run();\n },\n unsetFontFamily:\n () =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontFamily: null }).removeEmptyTextStyle().run();\n },\n };\n },\n});\n","/**\n * Sanitize pasted HTML for email safety.\n *\n * Strips Google Docs / Word / web junk and only keeps email-safe\n * tags and a small set of inline styles that TipTap understands.\n */\n\n/** Tags that are safe in email content */\nconst ALLOWED_TAGS = new Set([\n 'p', 'br', 'b', 'strong', 'i', 'em', 'u', 's', 'a', 'span',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li', 'blockquote',\n 'table', 'thead', 'tbody', 'tr', 'td', 'th',\n 'hr', 'div', 'sup', 'sub',\n]);\n\n/** CSS properties that are meaningful in email + TipTap */\nconst ALLOWED_STYLE_PROPS = new Set([\n 'color',\n 'background-color',\n 'font-size',\n 'font-family',\n 'font-weight',\n 'font-style',\n 'text-decoration',\n 'text-align',\n]);\n\n/** Tags that should be removed entirely (including their content) */\nconst REMOVE_WITH_CONTENT = new Set([\n 'style', 'script', 'meta', 'link', 'title', 'head',\n]);\n\nexport function cleanPastedHTML(html: string): string {\n // Strip MS Office / Google Docs conditional comments\n let cleaned = html\n .replace(/<!--\\[if[\\s\\S]*?<!\\[endif\\]-->/gi, '')\n .replace(/<!--[\\s\\S]*?-->/g, '');\n\n // Strip XML namespaced tags (Word's <o:p>, <v:shape>, etc.)\n cleaned = cleaned.replace(/<\\/?[a-z]+:[^>]*>/gi, '');\n\n // Parse into DOM for structured cleaning\n const parser = new DOMParser();\n const doc = parser.parseFromString(cleaned, 'text/html');\n\n cleanNode(doc.body);\n removeEmptyWrappers(doc.body);\n\n return doc.body.innerHTML;\n}\n\nfunction cleanNode(node: Node): void {\n const children = Array.from(node.childNodes);\n\n for (const child of children) {\n if (child.nodeType === Node.COMMENT_NODE) {\n node.removeChild(child);\n continue;\n }\n\n if (child.nodeType === Node.ELEMENT_NODE) {\n const el = child as HTMLElement;\n const tag = el.tagName.toLowerCase();\n\n // Remove tags that should disappear with their content\n if (REMOVE_WITH_CONTENT.has(tag)) {\n node.removeChild(child);\n continue;\n }\n\n // Remove base64 images (too heavy for email)\n if (tag === 'img') {\n const src = el.getAttribute('src') ?? '';\n if (src.startsWith('data:')) {\n node.removeChild(child);\n continue;\n }\n }\n\n if (!ALLOWED_TAGS.has(tag)) {\n // Unwrap: replace element with its children\n const frag = document.createDocumentFragment();\n while (el.firstChild) {\n frag.appendChild(el.firstChild);\n }\n node.replaceChild(frag, child);\n // Re-process from parent since structure changed\n cleanNode(node);\n return;\n }\n\n // Clean attributes: remove everything except href, src, alt, target, rel\n const attrs = Array.from(el.attributes);\n for (const attr of attrs) {\n const name = attr.name.toLowerCase();\n if (name === 'style') continue; // handle below\n if (name === 'href' || name === 'src' || name === 'alt' || name === 'target' || name === 'rel') {\n continue;\n }\n el.removeAttribute(attr.name);\n }\n\n // Sanitize href\n if (el.hasAttribute('href')) {\n const href = el.getAttribute('href') ?? '';\n if (href.toLowerCase().startsWith('javascript:')) {\n el.setAttribute('href', '#');\n }\n }\n\n // Clean inline styles: keep only email-safe properties\n cleanStyles(el);\n\n // Fix Google Docs pattern: <b style=\"font-weight:normal\"> → unwrap\n if ((tag === 'b' || tag === 'strong') && el.style.fontWeight && isNormalWeight(el.style.fontWeight)) {\n el.style.removeProperty('font-weight');\n const frag = document.createDocumentFragment();\n while (el.firstChild) {\n frag.appendChild(el.firstChild);\n }\n node.replaceChild(frag, child);\n cleanNode(node);\n return;\n }\n\n // Recurse\n cleanNode(child);\n }\n }\n}\n\nfunction cleanStyles(el: HTMLElement): void {\n const style = el.getAttribute('style');\n if (!style) return;\n\n const kept: string[] = [];\n // Parse style string into individual declarations\n const declarations = style.split(';');\n for (const decl of declarations) {\n const colonIdx = decl.indexOf(':');\n if (colonIdx === -1) continue;\n const prop = decl.substring(0, colonIdx).trim().toLowerCase();\n const value = decl.substring(colonIdx + 1).trim();\n if (ALLOWED_STYLE_PROPS.has(prop) && value) {\n kept.push(`${prop}: ${value}`);\n }\n }\n\n if (kept.length > 0) {\n el.setAttribute('style', kept.join('; '));\n } else {\n el.removeAttribute('style');\n }\n}\n\nfunction isNormalWeight(weight: string): boolean {\n const w = weight.toLowerCase().trim();\n return w === 'normal' || w === '400';\n}\n\n/** Remove empty span/div wrappers that carry no meaning */\nfunction removeEmptyWrappers(node: Node): void {\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\n const el = child as HTMLElement;\n const tag = el.tagName.toLowerCase();\n\n removeEmptyWrappers(el);\n\n // Empty span/div with no attributes and only whitespace/children\n if ((tag === 'span' || tag === 'div') && el.attributes.length === 0) {\n const frag = document.createDocumentFragment();\n while (el.firstChild) {\n frag.appendChild(el.firstChild);\n }\n node.replaceChild(frag, child);\n }\n }\n}\n","import React, { useState, useCallback, useRef, useEffect } from 'react';\nimport type { Editor } from '@tiptap/core';\nimport { useEditorFonts } from '../../context/EditorContext';\nimport { isSafeURL } from '../../utils/sanitize';\nimport { COLOR_PRESETS } from '../../constants';\nimport styles from '../../styles/toolbar.module.css';\n\ninterface RichTextToolbarProps {\n editor: Editor | null;\n}\n\n/** Prevent mousedown on buttons only so editor keeps focus, but allow selects to work natively */\nfunction preventBlur(e: React.MouseEvent) {\n const target = e.target as HTMLElement;\n const tag = target.tagName.toLowerCase();\n // Allow native behavior for select, option, and color input\n if (tag === 'select' || tag === 'option' || (tag === 'input' && (target as HTMLInputElement).type === 'color')) {\n return;\n }\n e.preventDefault();\n}\n\nexport const RichTextToolbar = React.memo(function RichTextToolbar({ editor }: RichTextToolbarProps) {\n if (!editor) return null;\n\n return (\n <div className={`ee-richtext-toolbar ${styles.richTextToolbar}`} onMouseDown={preventBlur}>\n {/* Font Family */}\n <FontFamilySelect editor={editor} />\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Font Size */}\n <FontSizeSelect editor={editor} />\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Bold / Italic / Underline */}\n <button\n className={`ee-richtext-btn ee-richtext-bold ${styles.richTextBtn} ${editor.isActive('bold') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleBold().run()}\n title=\"Bold (Ctrl+B)\"\n aria-label=\"Bold (Ctrl+B)\"\n aria-pressed={editor.isActive('bold')}\n >\n <strong>B</strong>\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-italic ${styles.richTextBtn} ${editor.isActive('italic') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleItalic().run()}\n title=\"Italic (Ctrl+I)\"\n aria-label=\"Italic (Ctrl+I)\"\n aria-pressed={editor.isActive('italic')}\n >\n <em>I</em>\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-underline ${styles.richTextBtn} ${editor.isActive('underline') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleUnderline().run()}\n title=\"Underline (Ctrl+U)\"\n aria-label=\"Underline (Ctrl+U)\"\n aria-pressed={editor.isActive('underline')}\n >\n <u>U</u>\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-strike ${styles.richTextBtn} ${editor.isActive('strike') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleStrike().run()}\n title=\"Strikethrough (Ctrl+Shift+X)\"\n aria-label=\"Strikethrough (Ctrl+Shift+X)\"\n aria-pressed={editor.isActive('strike')}\n >\n <s>S</s>\n </button>\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Text Color */}\n <InlineColorPicker\n editor={editor}\n type=\"color\"\n title=\"Text Color\"\n label=\"A\"\n />\n\n {/* Highlight Color */}\n <InlineColorPicker\n editor={editor}\n type=\"highlight\"\n title=\"Highlight\"\n label=\"H\"\n />\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Alignment */}\n <button\n className={`ee-richtext-btn ee-richtext-align-left ${styles.richTextBtn} ${editor.isActive({ textAlign: 'left' }) ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().setTextAlign('left').run()}\n title=\"Align Left\"\n aria-label=\"Align Left\"\n aria-pressed={editor.isActive({ textAlign: 'left' })}\n >\n L\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-align-center ${styles.richTextBtn} ${editor.isActive({ textAlign: 'center' }) ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().setTextAlign('center').run()}\n title=\"Align Center\"\n aria-label=\"Align Center\"\n aria-pressed={editor.isActive({ textAlign: 'center' })}\n >\n C\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-align-right ${styles.richTextBtn} ${editor.isActive({ textAlign: 'right' }) ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().setTextAlign('right').run()}\n title=\"Align Right\"\n aria-label=\"Align Right\"\n aria-pressed={editor.isActive({ textAlign: 'right' })}\n >\n R\n </button>\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Lists */}\n <button\n className={`ee-richtext-btn ee-richtext-bullet-list ${styles.richTextBtn} ${editor.isActive('bulletList') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleBulletList().run()}\n title=\"Bullet List\"\n aria-label=\"Bullet List\"\n aria-pressed={editor.isActive('bulletList')}\n >\n &#8226;\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-ordered-list ${styles.richTextBtn} ${editor.isActive('orderedList') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleOrderedList().run()}\n title=\"Ordered List\"\n aria-label=\"Ordered List\"\n aria-pressed={editor.isActive('orderedList')}\n >\n 1.\n </button>\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Link */}\n <InlineLinkEditor editor={editor} />\n\n {/* Clear formatting */}\n <button\n className={`ee-richtext-btn ee-richtext-clear ${styles.richTextBtn}`}\n onClick={() => editor.chain().focus().unsetAllMarks().run()}\n title=\"Clear Formatting\"\n aria-label=\"Clear Formatting\"\n >\n &#10006;\n </button>\n </div>\n );\n});\n\n// ---- Font Family Select ----\n\nfunction FontFamilySelect({ editor }: { editor: Editor }) {\n const { fontFamilies } = useEditorFonts();\n const currentFont = editor.getAttributes('textStyle').fontFamily || '';\n\n // Include current font if it's not in the predefined list\n const fonts = fontFamilies.slice();\n if (currentFont && !fonts.some((f) => f.toLowerCase() === currentFont.toLowerCase())) {\n fonts.push(currentFont);\n }\n\n return (\n <select\n className={`ee-richtext-font-select ${styles.richTextSelect}`}\n value={currentFont}\n onChange={(e) => {\n const value = e.target.value;\n if (value) {\n editor.chain().focus().setFontFamily(value).run();\n } else {\n editor.chain().focus().unsetFontFamily().run();\n }\n }}\n title=\"Font Family\"\n >\n <option value=\"\">Default</option>\n {fonts.map((font) => (\n <option key={font} value={font} style={{ fontFamily: font }}>\n {font.split(',')[0].trim()}\n </option>\n ))}\n </select>\n );\n}\n\n// ---- Font Size Select ----\n\nfunction FontSizeSelect({ editor }: { editor: Editor }) {\n const { fontSizes } = useEditorFonts();\n const currentSize = editor.getAttributes('textStyle').fontSize || '';\n\n // Build size list, including current size if it's not in the predefined list\n const sizes = fontSizes.slice();\n if (currentSize && !sizes.includes(currentSize)) {\n sizes.push(currentSize);\n sizes.sort((a, b) => parseInt(a, 10) - parseInt(b, 10));\n }\n\n return (\n <select\n className={`ee-richtext-size-select ${styles.richTextSelectSmall}`}\n value={currentSize}\n onChange={(e) => {\n const value = e.target.value;\n if (value) {\n editor.chain().focus().setFontSize(value).run();\n } else {\n editor.chain().focus().unsetFontSize().run();\n }\n }}\n title=\"Font Size\"\n >\n <option value=\"\">Size</option>\n {sizes.map((size) => (\n <option key={size} value={size}>\n {parseInt(size, 10)}\n </option>\n ))}\n </select>\n );\n}\n\n// ---- Inline Color Picker ----\n\ninterface InlineColorPickerProps {\n editor: Editor;\n type: 'color' | 'highlight';\n title: string;\n label: string;\n}\n\n// ---- Inline Link Editor ----\n\nfunction InlineLinkEditor({ editor }: { editor: Editor }) {\n const [isOpen, setIsOpen] = useState(false);\n const [url, setUrl] = useState('');\n const wrapperRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const isActive = editor.isActive('link');\n const currentHref = editor.getAttributes('link').href || '';\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const handleOpen = useCallback(() => {\n setUrl(currentHref);\n setUrlError('');\n setIsOpen(true);\n setTimeout(() => inputRef.current?.focus(), 50);\n }, [currentHref]);\n\n const [urlError, setUrlError] = useState('');\n\n const handleApply = useCallback(() => {\n const trimmed = url.trim();\n if (trimmed) {\n if (!isSafeURL(trimmed)) {\n setUrlError('Only http, https, mailto, and tel URLs are allowed');\n return;\n }\n setUrlError('');\n editor.chain().focus().setLink({ href: trimmed }).run();\n }\n setIsOpen(false);\n }, [editor, url]);\n\n const handleRemove = useCallback(() => {\n editor.chain().focus().unsetLink().run();\n setIsOpen(false);\n setUrl('');\n }, [editor]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleApply();\n } else if (e.key === 'Escape') {\n setIsOpen(false);\n }\n },\n [handleApply],\n );\n\n return (\n <div className={`ee-richtext-link ${styles.richTextColorWrapper}`} ref={wrapperRef}>\n <button\n className={`ee-richtext-btn ee-richtext-link-btn ${styles.richTextBtn} ${isActive ? styles.richTextBtnActive : ''}`}\n onClick={handleOpen}\n title=\"Link\"\n aria-label=\"Link\"\n aria-pressed={isActive}\n >\n &#128279;\n </button>\n {isOpen && (\n <div className={`ee-richtext-link-dropdown ${styles.richTextLinkDropdown}`}>\n <label className={`ee-richtext-link-label ${styles.richTextLinkLabel}`}>URL</label>\n <input\n ref={inputRef}\n className={`ee-richtext-link-input ${styles.richTextLinkInput}`}\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"https://, mailto:, or tel:\"\n />\n {urlError && <div className={`ee-richtext-link-error ${styles.richTextLinkError}`}>{urlError}</div>}\n <div className={`ee-richtext-link-actions ${styles.richTextLinkActions}`}>\n <button className={`ee-richtext-link-apply ${styles.richTextLinkApply}`} onClick={handleApply}>\n Apply\n </button>\n {isActive && (\n <button className={`ee-richtext-link-remove ${styles.richTextLinkRemove}`} onClick={handleRemove}>\n Remove\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction InlineColorPicker({ editor, type, title, label }: InlineColorPickerProps) {\n const [isOpen, setIsOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const currentColor =\n type === 'color'\n ? editor.getAttributes('textStyle').color || '#000000'\n : editor.getAttributes('highlight').color || '';\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const applyColor = useCallback(\n (color: string) => {\n if (type === 'color') {\n editor.chain().focus().setColor(color).run();\n } else {\n editor.chain().focus().toggleHighlight({ color }).run();\n }\n setIsOpen(false);\n },\n [editor, type],\n );\n\n const clearColor = useCallback(() => {\n if (type === 'color') {\n editor.chain().focus().unsetColor().run();\n } else {\n editor.chain().focus().unsetHighlight().run();\n }\n setIsOpen(false);\n }, [editor, type]);\n\n const indicatorColor = type === 'color' ? currentColor : (currentColor || 'transparent');\n\n return (\n <div className={`ee-richtext-color ee-richtext-color--${type} ${styles.richTextColorWrapper}`} ref={wrapperRef}>\n <button\n className={`ee-richtext-btn ee-richtext-color-btn ${styles.richTextBtn}`}\n onClick={() => setIsOpen(!isOpen)}\n title={title}\n aria-label={title}\n aria-expanded={isOpen}\n >\n <span className={`ee-richtext-color-label ${styles.richTextColorLabel}`}>{label}</span>\n <span\n className={`ee-richtext-color-indicator ${styles.richTextColorIndicator}`}\n style={{ backgroundColor: indicatorColor }}\n />\n </button>\n {isOpen && (\n <div className={`ee-richtext-color-dropdown ${styles.richTextColorDropdown}`}>\n <div className={`ee-richtext-color-grid ${styles.richTextColorGrid}`}>\n {COLOR_PRESETS.map((color) => (\n <button\n key={color}\n className={`ee-richtext-color-swatch ${styles.richTextColorSwatch}`}\n style={{ backgroundColor: color }}\n onClick={() => applyColor(color)}\n title={color}\n />\n ))}\n </div>\n <div className={`ee-richtext-color-actions ${styles.richTextColorActions}`}>\n <input\n type=\"color\"\n value={currentColor || '#000000'}\n onChange={(e) => applyColor(e.target.value)}\n className={`ee-richtext-color-input ${styles.richTextColorInput}`}\n title=\"Custom color\"\n />\n <button\n className={`ee-richtext-color-clear ${styles.richTextColorClearBtn}`}\n onClick={clearColor}\n >\n Clear\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n","/* Text Block */\n.textBlock {\n min-height: 24px;\n cursor: text;\n position: relative;\n}\n\n.textBlockToolbar {\n position: sticky;\n top: 0;\n z-index: var(--ee-z-block-toolbar);\n margin-bottom: 4px;\n}\n\n/* Button Block */\n.buttonBlock {\n display: flex;\n padding: 10px 25px;\n}\n\n.buttonBlockLeft {\n justify-content: flex-start;\n}\n\n.buttonBlockCenter {\n justify-content: center;\n}\n\n.buttonBlockRight {\n justify-content: flex-end;\n}\n\n.buttonPreview {\n display: inline-block;\n padding: 12px 24px;\n font-weight: var(--ee-font-weight-medium);\n text-decoration: none;\n cursor: pointer;\n text-align: center;\n line-height: 1.4;\n border: none;\n}\n\n/* Image Block */\n.imageBlock {\n display: flex;\n padding: 10px 25px;\n}\n\n.imageBlockLeft {\n justify-content: flex-start;\n}\n\n.imageBlockCenter {\n justify-content: center;\n}\n\n.imageBlockRight {\n justify-content: flex-end;\n}\n\n.imagePreview {\n max-width: 100%;\n height: auto;\n display: block;\n}\n\n.imagePlaceholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n width: 100%;\n min-height: 120px;\n background: var(--ee-bg-app);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.imagePlaceholder:hover {\n border-color: var(--ee-color-primary);\n color: var(--ee-color-primary);\n background: var(--ee-color-primary-light);\n}\n\n.imagePlaceholderIcon {\n font-size: 32px;\n}\n\n.imageUploading {\n position: relative;\n}\n\n.imageProgress {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 4px;\n background: var(--ee-color-primary);\n border-radius: 2px;\n transition: width 200ms ease;\n}\n\n.imageError {\n color: var(--ee-color-danger);\n font-size: var(--ee-font-size-xs);\n padding: var(--ee-space-xs);\n text-align: center;\n}\n\n/* Divider Block */\n.dividerBlock {\n display: flex;\n align-items: center;\n}\n\n.dividerLine {\n height: 0;\n border: none;\n margin: 0;\n}\n\n/* Spacer Block */\n.spacerBlock {\n position: relative;\n background: repeating-linear-gradient(\n 45deg,\n transparent,\n transparent 5px,\n var(--ee-bg-app) 5px,\n var(--ee-bg-app) 10px\n );\n opacity: 0.5;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.spacerLabel {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-muted);\n background: var(--ee-bg-panel);\n padding: 2px 6px;\n border-radius: 3px;\n}\n\n/* Social Block */\n.socialBlock {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n min-height: 30px;\n}\n\n.socialElement {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.socialIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: bold;\n line-height: 1;\n flex-shrink: 0;\n}\n\n.socialLabel {\n white-space: nowrap;\n}\n\n.socialElementsContainer {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.socialElementItem {\n padding: 8px;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-app);\n}\n\n/* HTML Block */\n.htmlBlock {\n min-height: 24px;\n position: relative;\n}\n\n.htmlPlaceholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n width: 100%;\n min-height: 80px;\n background: var(--ee-bg-app);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n font-family: monospace;\n}\n\n/* Video Block */\n.videoBlock {\n display: flex;\n padding: 10px 25px;\n}\n\n.videoBlockLeft {\n justify-content: flex-start;\n}\n\n.videoBlockCenter {\n justify-content: center;\n}\n\n.videoBlockRight {\n justify-content: flex-end;\n}\n\n.videoPreview {\n position: relative;\n display: inline-block;\n max-width: 100%;\n}\n\n.playOverlay {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 60px;\n height: 60px;\n background: var(--ee-overlay-dark);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--ee-text-inverse);\n font-size: 24px;\n pointer-events: none;\n}\n\n.videoPlaceholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n width: 100%;\n min-height: 120px;\n background: var(--ee-bg-app);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n}\n\n/* Heading Block */\n.headingBlock {\n min-height: 24px;\n cursor: text;\n position: relative;\n}\n\n/* Countdown Block */\n.countdownBlock {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.countdownLabel {\n font-size: 14px;\n font-weight: 500;\n}\n\n.countdownDigits {\n display: flex;\n gap: 12px;\n}\n\n.countdownUnit {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.countdownDigitBox {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 56px;\n padding: 8px 12px;\n border-radius: 6px;\n font-weight: bold;\n font-variant-numeric: tabular-nums;\n}\n\n.countdownUnitLabel {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Menu Block */\n.menuBlock {\n display: flex;\n}\n\n.menuItems {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.menuItem {\n padding: 6px 12px;\n text-decoration: none;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.menuItemsContainer {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.menuItemEntry {\n padding: 8px;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-app);\n}\n\n/* Hero Block */\n.heroBlock {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n min-height: 80px;\n}\n\n.heroHeading {\n margin: 0;\n font-weight: bold;\n line-height: 1.2;\n}\n\n.heroSubtext {\n margin: 0;\n line-height: 1.5;\n}\n\n.heroButton {\n display: inline-block;\n padding: 12px 28px;\n font-weight: 600;\n font-size: 16px;\n text-decoration: none;\n cursor: pointer;\n}\n",".tiptapWrapper {\n position: relative;\n}\n\n.tiptapWrapper :global(.ProseMirror) {\n outline: none;\n min-height: 24px;\n padding: 4px;\n word-break: break-word;\n}\n\n.tiptapWrapper :global(.ProseMirror) p {\n margin: 0 0 0.5em 0;\n}\n\n.tiptapWrapper :global(.ProseMirror) p:last-child {\n margin-bottom: 0;\n}\n\n.tiptapWrapper :global(.ProseMirror) h1,\n.tiptapWrapper :global(.ProseMirror) h2,\n.tiptapWrapper :global(.ProseMirror) h3,\n.tiptapWrapper :global(.ProseMirror) h4 {\n margin: 0 0 0.5em 0;\n line-height: 1.3;\n}\n\n.tiptapWrapper :global(.ProseMirror) ul,\n.tiptapWrapper :global(.ProseMirror) ol {\n margin: 0 0 0.5em 0;\n padding-left: 1.5em;\n}\n\n.tiptapWrapper :global(.ProseMirror) blockquote {\n border-left: 3px solid var(--ee-border-color-strong);\n margin: 0 0 0.5em 0;\n padding-left: 1em;\n color: var(--ee-text-secondary);\n}\n\n.tiptapWrapper :global(.ProseMirror) a {\n color: var(--ee-text-link);\n text-decoration: underline;\n}\n\n/* Variable chips in TipTap */\n.tiptapWrapper :global(.ee-variable-chip) {\n display: inline-flex;\n align-items: center;\n padding: 1px 6px;\n margin: 0 1px;\n font-size: inherit;\n font-family: inherit;\n font-weight: inherit;\n font-style: inherit;\n background: var(--ee-variable-bg);\n color: var(--ee-variable-color);\n border: 1px solid var(--ee-variable-border);\n border-radius: var(--ee-border-radius-sm);\n vertical-align: baseline;\n user-select: none;\n white-space: nowrap;\n}\n\n/* Focus styling */\n.tiptapWrapper :global(.ProseMirror-focused) {\n outline: none;\n}\n\n/* Placeholder — uses TipTap Placeholder extension's data-placeholder attribute */\n.tiptapWrapper :global(.ProseMirror) :global(.is-editor-empty):first-child::before {\n content: attr(data-placeholder);\n float: left;\n color: var(--ee-text-muted);\n pointer-events: none;\n height: 0;\n font-style: italic;\n opacity: 0.6;\n}\n","import React, { useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface ButtonBlockProps {\n block: Block;\n}\n\nexport const ButtonBlock = React.memo(function ButtonBlock({ block }: ButtonBlockProps) {\n const p = block.properties;\n const alignClass =\n p.align === 'left'\n ? styles.buttonBlockLeft\n : p.align === 'right'\n ? styles.buttonBlockRight\n : styles.buttonBlockCenter;\n\n const outerStyle = useMemo(() => ({ padding: p.padding }), [p.padding]);\n const buttonStyle = useMemo(() => ({\n backgroundColor: p.backgroundColor,\n color: p.color,\n fontFamily: p.fontFamily,\n fontSize: p.fontSize,\n borderRadius: p.borderRadius,\n padding: p.innerPadding,\n width: p.width !== 'auto' ? p.width : undefined,\n fontWeight: p.fontWeight,\n textTransform: p.textTransform,\n letterSpacing: p.letterSpacing,\n }), [p.backgroundColor, p.color, p.fontFamily, p.fontSize, p.borderRadius, p.innerPadding, p.width, p.fontWeight, p.textTransform, p.letterSpacing]);\n\n return (\n <div className={`ee-block-button ${styles.buttonBlock} ${alignClass}`} style={outerStyle}>\n <span\n className={styles.buttonPreview}\n style={buttonStyle}\n >\n {p.text}\n </span>\n </div>\n );\n});\n","import React, { useCallback, useRef } from 'react';\nimport type { Block } from '../../../types';\nimport { useEditorDispatch, useConfigContext } from '../../../context/EditorContext';\nimport { useImageUpload } from '../../ImageUpload/useImageUpload';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface ImageBlockProps {\n block: Block;\n}\n\nconst ImageBlockInner = function ImageBlock({ block }: ImageBlockProps) {\n const dispatch = useEditorDispatch();\n const { imageUploadAdapter } = useConfigContext();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const p = block.properties;\n\n const { upload, status } = useImageUpload({\n adapter: imageUploadAdapter,\n blockId: block.id,\n onSuccess: (result) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: {\n blockId: block.id,\n properties: {\n src: result.url,\n alt: result.alt ?? p.alt,\n width: result.width ? `${result.width}px` : p.width,\n },\n },\n });\n },\n });\n\n const alignClass =\n p.align === 'left'\n ? styles.imageBlockLeft\n : p.align === 'right'\n ? styles.imageBlockRight\n : styles.imageBlockCenter;\n\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n await upload(file);\n },\n [upload],\n );\n\n const handlePlaceholderClick = useCallback(() => {\n fileInputRef.current?.click();\n }, []);\n\n return (\n <div className={`ee-block-image ${styles.imageBlock} ${alignClass}`} style={{ padding: p.padding }}>\n {p.src ? (\n <img\n src={p.src}\n alt={p.alt}\n className={styles.imagePreview}\n style={{\n width: p.width,\n height: p.height !== 'auto' ? p.height : undefined,\n }}\n />\n ) : (\n <div className={styles.imagePlaceholder} onClick={handlePlaceholderClick}>\n <span className={styles.imagePlaceholderIcon}>+</span>\n <span>{status === 'uploading' ? 'Uploading...' : 'Click to upload image'}</span>\n </div>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n />\n </div>\n );\n};\n\nexport const ImageBlock = React.memo(ImageBlockInner);\n","import { useState, useCallback, useRef } from 'react';\nimport type { ImageUploadAdapter, UploadResult } from '../../types';\n\nexport type UploadStatus = 'idle' | 'uploading' | 'success' | 'error';\n\ninterface UseImageUploadOptions {\n adapter?: ImageUploadAdapter;\n blockId: string;\n onSuccess?: (result: UploadResult) => void;\n onError?: (error: string) => void;\n}\n\ninterface UseImageUploadReturn {\n status: UploadStatus;\n progress: number;\n error: string | null;\n upload: (file: File) => Promise<UploadResult | null>;\n cancel: () => void;\n browse: () => Promise<UploadResult | null>;\n reset: () => void;\n}\n\nexport function useImageUpload({\n adapter,\n blockId,\n onSuccess,\n onError,\n}: UseImageUploadOptions): UseImageUploadReturn {\n const [status, setStatus] = useState<UploadStatus>('idle');\n const [progress, setProgress] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const controllerRef = useRef<AbortController | null>(null);\n\n const upload = useCallback(\n async (file: File): Promise<UploadResult | null> => {\n if (!adapter) {\n setError('No upload adapter configured');\n setStatus('error');\n return null;\n }\n\n // Validate file\n if (adapter.validate) {\n const validationError = adapter.validate(file);\n if (validationError) {\n setError(validationError);\n setStatus('error');\n onError?.(validationError);\n return null;\n }\n }\n\n // Start upload\n controllerRef.current = new AbortController();\n setStatus('uploading');\n setProgress(0);\n setError(null);\n\n try {\n const result = await adapter.upload(file, {\n context: 'block',\n blockId,\n signal: controllerRef.current.signal,\n });\n\n setStatus('success');\n setProgress(100);\n onSuccess?.(result);\n return result;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n setStatus('idle');\n setProgress(0);\n return null;\n }\n const errorMessage = (err as Error).message || 'Upload failed';\n setError(errorMessage);\n setStatus('error');\n onError?.(errorMessage);\n return null;\n }\n },\n [adapter, blockId, onSuccess, onError],\n );\n\n const cancel = useCallback(() => {\n controllerRef.current?.abort();\n setStatus('idle');\n setProgress(0);\n }, []);\n\n const browse = useCallback(async (): Promise<UploadResult | null> => {\n if (!adapter?.browse) return null;\n try {\n const result = await adapter.browse();\n if (result) {\n onSuccess?.(result);\n }\n return result;\n } catch {\n return null;\n }\n }, [adapter, onSuccess]);\n\n const reset = useCallback(() => {\n setStatus('idle');\n setProgress(0);\n setError(null);\n }, []);\n\n return { status, progress, error, upload, cancel, browse, reset };\n}\n","import React, { useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface DividerBlockProps {\n block: Block;\n}\n\nexport const DividerBlock = React.memo(function DividerBlock({ block }: DividerBlockProps) {\n const p = block.properties;\n\n const outerStyle = useMemo(() => ({ padding: p.padding }), [p.padding]);\n const hrStyle = useMemo(() => ({\n width: p.width,\n borderTop: `${p.borderWidth} ${p.borderStyle} ${p.borderColor}`,\n }), [p.width, p.borderWidth, p.borderStyle, p.borderColor]);\n\n return (\n <div className={`ee-block-divider ${styles.dividerBlock}`} style={outerStyle}>\n <hr\n className={styles.dividerLine}\n style={hrStyle}\n />\n </div>\n );\n});\n","import React from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface SpacerBlockProps {\n block: Block;\n}\n\nexport const SpacerBlock = React.memo(function SpacerBlock({ block }: SpacerBlockProps) {\n const p = block.properties;\n\n return (\n <div className={`ee-block-spacer ${styles.spacerBlock}`} style={{ height: p.height }}>\n <span className={styles.spacerLabel}>{p.height}</span>\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport type { Block, SocialElement } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface SocialBlockProps {\n block: Block;\n}\n\nconst PLATFORM_COLORS: Record<string, string> = {\n facebook: '#3b5998',\n twitter: '#1da1f2',\n instagram: '#e1306c',\n linkedin: '#0077b5',\n youtube: '#ff0000',\n github: '#333333',\n pinterest: '#bd081c',\n snapchat: '#fffc00',\n tiktok: '#000000',\n web: '#4caf50',\n};\n\nexport const SocialBlock = React.memo(function SocialBlock({ block }: SocialBlockProps) {\n const p = block.properties;\n const isVertical = p.mode === 'vertical';\n\n const alignStyle =\n p.align === 'left'\n ? 'flex-start'\n : p.align === 'right'\n ? 'flex-end'\n : 'center';\n\n const iconSizeNum = parseInt(p.iconSize, 10) || 20;\n\n const wrapperStyle = useMemo(() => ({\n padding: p.padding,\n justifyContent: alignStyle,\n flexDirection: (isVertical ? 'column' : 'row') as React.CSSProperties['flexDirection'],\n alignItems: isVertical ? alignStyle : 'center',\n }), [p.padding, alignStyle, isVertical]);\n\n const elementPaddingStyle = useMemo(() => ({\n padding: p.iconPadding,\n }), [p.iconPadding]);\n\n const labelStyle = useMemo(() => ({\n fontSize: p.fontSize, color: p.color,\n }), [p.fontSize, p.color]);\n\n return (\n <div\n className={`ee-block-social ${styles.socialBlock}`}\n style={wrapperStyle}\n >\n {p.elements.map((element: SocialElement) => {\n const bgColor = element.backgroundColor || PLATFORM_COLORS[element.name] || '#999999';\n const initial = element.name.charAt(0).toUpperCase();\n\n return (\n <div\n key={`${element.name}-${element.href}`}\n className={styles.socialElement}\n style={elementPaddingStyle}\n >\n <span\n className={styles.socialIcon}\n style={{\n width: iconSizeNum,\n height: iconSizeNum,\n backgroundColor: bgColor,\n borderRadius: p.borderRadius,\n color: element.color || '#ffffff',\n fontSize: Math.max(10, iconSizeNum * 0.5),\n }}\n >\n {initial}\n </span>\n {element.content && (\n <span\n className={styles.socialLabel}\n style={labelStyle}\n >\n {element.content}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport DOMPurify from 'dompurify';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface HtmlBlockProps {\n block: Block;\n}\n\nexport const HtmlBlock = React.memo(function HtmlBlock({ block }: HtmlBlockProps) {\n const p = block.properties;\n\n const sanitizedContent = useMemo(() => {\n if (!p.content) return '';\n return DOMPurify.sanitize(p.content, {\n ADD_TAGS: ['table', 'thead', 'tbody', 'tr', 'td', 'th'],\n ADD_ATTR: ['style', 'class', 'align', 'valign', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'colspan', 'rowspan', 'width', 'height'],\n });\n }, [p.content]);\n\n if (!p.content) {\n return (\n <div className={`ee-block-html ${styles.htmlBlock}`} style={{ padding: p.padding }}>\n <div className={styles.htmlPlaceholder}>\n <span>&lt;/&gt;</span>\n <span>Raw HTML Block</span>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`ee-block-html ${styles.htmlBlock}`}\n style={{ padding: p.padding }}\n dangerouslySetInnerHTML={{ __html: sanitizedContent }}\n />\n );\n});\n","import React from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface VideoBlockProps {\n block: Block;\n}\n\nexport const VideoBlock = React.memo(function VideoBlock({ block }: VideoBlockProps) {\n const p = block.properties;\n const alignClass = p.align === 'left' ? styles.videoBlockLeft\n : p.align === 'right' ? styles.videoBlockRight\n : styles.videoBlockCenter;\n\n const thumbnailUrl = p.thumbnailUrl || getAutoThumbnail(p.src);\n\n if (!thumbnailUrl && !p.src) {\n return (\n <div className={`ee-block-video ${styles.videoBlock} ${alignClass}`} style={{ padding: p.padding }}>\n <div className={styles.videoPlaceholder}>\n <span style={{ fontSize: '32px' }}>&#9654;</span>\n <span>Video Block</span>\n </div>\n </div>\n );\n }\n\n return (\n <div className={`ee-block-video ${styles.videoBlock} ${alignClass}`} style={{ padding: p.padding }}>\n <div className={styles.videoPreview}>\n {thumbnailUrl ? (\n <img src={thumbnailUrl} alt={p.alt} style={{ maxWidth: '100%', display: 'block' }} />\n ) : (\n <div className={styles.videoPlaceholder}>\n <span style={{ fontSize: '32px' }}>&#9654;</span>\n <span>No thumbnail</span>\n </div>\n )}\n <div className={styles.playOverlay}>&#9654;</div>\n </div>\n </div>\n );\n});\n\nfunction getAutoThumbnail(url: string): string {\n if (!url) return '';\n // YouTube\n const ytMatch = url.match(/(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/);\n if (ytMatch) return `https://img.youtube.com/vi/${ytMatch[1]}/hqdefault.jpg`;\n // Vimeo — can't auto-generate without API, return empty\n return '';\n}\n","import React, { useCallback, useRef, useState, useEffect, useReducer, useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport { useEditorDispatch, useMethodsContext } from '../../../context/EditorContext';\nimport { TipTapEditor } from '../../../tiptap/TipTapEditor';\nimport { RichTextToolbar } from '../../Toolbar/RichTextToolbar';\nimport type { Editor } from '@tiptap/core';\nimport styles from '../../../styles/blocks.module.css';\nimport tiptapStyles from '../../../styles/tiptap.module.css';\n\ninterface HeadingBlockProps {\n block: Block;\n}\n\nconst HEADING_FONT_SIZES: Record<string, string> = {\n h1: '36px',\n h2: '28px',\n h3: '22px',\n h4: '18px',\n};\n\nconst HeadingBlockInner = function HeadingBlock({ block }: HeadingBlockProps) {\n const dispatch = useEditorDispatch();\n const { setActiveEditor } = useMethodsContext();\n const editorRef = useRef<Editor | null>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const blurTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n // Track the editor instance in state so the effect has a proper dependency\n const [editorInstance, setEditorInstance] = useState<Editor | null>(null);\n\n // Force toolbar re-render when editor formatting state changes (selection/transaction)\n const [, forceToolbarUpdate] = useReducer((c: number) => c + 1, 0);\n\n useEffect(() => {\n if (!editorInstance) return;\n\n const onStateChange = () => forceToolbarUpdate();\n editorInstance.on('selectionUpdate', onStateChange);\n editorInstance.on('transaction', onStateChange);\n\n return () => {\n editorInstance.off('selectionUpdate', onStateChange);\n editorInstance.off('transaction', onStateChange);\n };\n }, [editorInstance]);\n\n const handleUpdate = useCallback(\n (html: string) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: { blockId: block.id, properties: { content: html } },\n });\n },\n [dispatch, block.id],\n );\n\n const handleFocus = useCallback(() => {\n setActiveEditor(editorRef.current);\n setIsFocused(true);\n }, [setActiveEditor]);\n\n // Cleanup blur timer on unmount\n useEffect(() => {\n return () => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n };\n }, []);\n\n const handleBlur = useCallback(() => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n blurTimerRef.current = setTimeout(() => {\n blurTimerRef.current = null;\n const activeEl = document.activeElement;\n if (wrapperRef.current && wrapperRef.current.contains(activeEl)) {\n return;\n }\n if (editorRef.current && !editorRef.current.isFocused) {\n setActiveEditor(null);\n setIsFocused(false);\n }\n }, 200);\n }, [setActiveEditor]);\n\n const handleEditorRef = useCallback((editor: Editor | null) => {\n editorRef.current = editor;\n setEditorInstance(editor);\n }, []);\n\n const p = block.properties;\n const fontSize = p.fontSize || HEADING_FONT_SIZES[p.level] || '28px';\n\n const wrapperStyle = useMemo(() => ({\n fontFamily: p.fontFamily,\n fontSize,\n color: p.color,\n lineHeight: p.lineHeight,\n padding: p.padding,\n fontWeight: p.fontWeight,\n textTransform: p.textTransform,\n letterSpacing: p.letterSpacing,\n }), [p.fontFamily, fontSize, p.color, p.lineHeight, p.padding, p.fontWeight, p.textTransform, p.letterSpacing]);\n\n return (\n <div className={`ee-block-heading ${styles.headingBlock}`} ref={wrapperRef}>\n {isFocused && editorRef.current && (\n <div className={styles.textBlockToolbar}>\n <RichTextToolbar editor={editorRef.current} />\n </div>\n )}\n <div style={wrapperStyle}>\n <TipTapEditor\n content={p.content}\n onUpdate={handleUpdate}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className={tiptapStyles.tiptapWrapper}\n editorRef={handleEditorRef}\n placeholder=\"Enter heading...\"\n />\n </div>\n </div>\n );\n};\n\nexport const HeadingBlock = React.memo(HeadingBlockInner);\n","import React, { useState, useEffect, useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface CountdownBlockProps {\n block: Block;\n}\n\nfunction getTimeRemaining(targetDate: string) {\n const total = Math.max(0, new Date(targetDate).getTime() - Date.now());\n return {\n days: Math.floor(total / (1000 * 60 * 60 * 24)),\n hours: Math.floor((total / (1000 * 60 * 60)) % 24),\n minutes: Math.floor((total / (1000 * 60)) % 60),\n seconds: Math.floor((total / 1000) % 60),\n };\n}\n\nexport const CountdownBlock = React.memo(function CountdownBlock({ block }: CountdownBlockProps) {\n const p = block.properties;\n const [time, setTime] = useState(() => getTimeRemaining(p.targetDate));\n\n useEffect(() => {\n setTime(getTimeRemaining(p.targetDate));\n const interval = setInterval(() => {\n setTime(getTimeRemaining(p.targetDate));\n }, 1000);\n return () => clearInterval(interval);\n }, [p.targetDate]);\n\n const units = [\n { value: time.days, label: 'Days' },\n { value: time.hours, label: 'Hours' },\n { value: time.minutes, label: 'Minutes' },\n { value: time.seconds, label: 'Seconds' },\n ];\n\n const alignStyle =\n p.align === 'left'\n ? 'flex-start'\n : p.align === 'right'\n ? 'flex-end'\n : 'center';\n\n const wrapperStyle = useMemo(() => ({\n padding: p.padding, justifyContent: alignStyle,\n }), [p.padding, alignStyle]);\n\n const labelStyle = useMemo(() => ({\n color: p.labelColor, textAlign: p.align as React.CSSProperties['textAlign'],\n }), [p.labelColor, p.align]);\n\n const digitsContainerStyle = useMemo(() => ({\n justifyContent: alignStyle,\n }), [alignStyle]);\n\n const digitBoxStyle = useMemo(() => ({\n backgroundColor: p.digitBackgroundColor,\n color: p.digitColor,\n fontSize: p.fontSize,\n }), [p.digitBackgroundColor, p.digitColor, p.fontSize]);\n\n const unitLabelStyle = useMemo(() => ({\n color: p.labelColor,\n }), [p.labelColor]);\n\n return (\n <div className={`ee-block-countdown ${styles.countdownBlock}`} style={wrapperStyle}>\n {p.label && (\n <div className={styles.countdownLabel} style={labelStyle}>\n {p.label}\n </div>\n )}\n <div className={styles.countdownDigits} style={digitsContainerStyle}>\n {units.map((unit) => (\n <div key={unit.label} className={styles.countdownUnit}>\n <div\n className={styles.countdownDigitBox}\n style={digitBoxStyle}\n >\n {String(unit.value).padStart(2, '0')}\n </div>\n <div className={styles.countdownUnitLabel} style={unitLabelStyle}>\n {unit.label}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport type { Block, MenuItem } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface MenuBlockProps {\n block: Block;\n}\n\nexport const MenuBlock = React.memo(function MenuBlock({ block }: MenuBlockProps) {\n const p = block.properties;\n\n const alignStyle =\n p.align === 'left'\n ? 'flex-start'\n : p.align === 'right'\n ? 'flex-end'\n : 'center';\n\n const wrapperStyle = useMemo(() => ({\n padding: p.padding, justifyContent: alignStyle,\n }), [p.padding, alignStyle]);\n\n const itemsStyle = useMemo(() => ({\n justifyContent: alignStyle,\n }), [alignStyle]);\n\n const itemStyle = useMemo(() => ({\n fontFamily: p.fontFamily,\n fontSize: p.fontSize,\n color: p.color,\n }), [p.fontFamily, p.fontSize, p.color]);\n\n return (\n <div className={`ee-block-menu ${styles.menuBlock}`} style={wrapperStyle}>\n <div className={styles.menuItems} style={itemsStyle}>\n {p.items.map((item: MenuItem) => (\n <span\n key={`${item.text}-${item.href}`}\n className={styles.menuItem}\n style={itemStyle}\n >\n {item.text}\n </span>\n ))}\n </div>\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface HeroBlockProps {\n block: Block;\n}\n\nexport const HeroBlock = React.memo(function HeroBlock({ block }: HeroBlockProps) {\n const p = block.properties;\n\n const containerStyle = useMemo<React.CSSProperties>(() => ({\n padding: p.padding,\n textAlign: p.align,\n backgroundColor: p.backgroundColor || undefined,\n backgroundImage: p.backgroundImage ? `url(${p.backgroundImage})` : undefined,\n backgroundSize: p.backgroundImage ? 'cover' : undefined,\n backgroundPosition: p.backgroundImage ? 'center' : undefined,\n backgroundRepeat: p.backgroundImage ? 'no-repeat' : undefined,\n }), [p.padding, p.align, p.backgroundColor, p.backgroundImage]);\n\n const headingStyle = useMemo(() => ({\n color: p.headingColor,\n fontSize: p.headingFontSize,\n }), [p.headingColor, p.headingFontSize]);\n\n const subtextStyle = useMemo(() => ({\n color: p.subtextColor,\n fontSize: p.subtextFontSize,\n }), [p.subtextColor, p.subtextFontSize]);\n\n const buttonStyle = useMemo(() => ({\n backgroundColor: p.buttonBackgroundColor,\n color: p.buttonColor,\n borderRadius: p.buttonBorderRadius,\n }), [p.buttonBackgroundColor, p.buttonColor, p.buttonBorderRadius]);\n\n return (\n <div className={`ee-block-hero ${styles.heroBlock}`} style={containerStyle}>\n {p.heading && (\n <h2\n className={styles.heroHeading}\n style={headingStyle}\n >\n {p.heading}\n </h2>\n )}\n {p.subtext && (\n <p\n className={styles.heroSubtext}\n style={subtextStyle}\n >\n {p.subtext}\n </p>\n )}\n {p.buttonText && (\n <span\n className={styles.heroButton}\n style={buttonStyle}\n >\n {p.buttonText}\n </span>\n )}\n </div>\n );\n});\n","import React, { useState, useCallback, useRef } from 'react';\nimport { isDropAllowed, getBlockTypeFromDrop, getBlockMoveFromDrop, DND_TYPES } from '../../utils/dnd';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport { generateBlockId } from '../../utils/id';\nimport { DEFAULT_BLOCK_PROPERTIES } from '../../constants';\nimport styles from '../../styles/canvas.module.css';\n\ninterface DropZoneProps {\n sectionId: string;\n columnId: string;\n index: number;\n /** Render as a full-size empty column placeholder */\n emptyPlaceholder?: boolean;\n}\n\nexport const DropZone = React.memo(function DropZone({ sectionId, columnId, index, emptyPlaceholder }: DropZoneProps) {\n const dispatch = useEditorDispatch();\n const [isOver, setIsOver] = useState(false);\n const isOverRef = useRef(false);\n\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!isDropAllowed(e)) return;\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.dropEffect = e.dataTransfer.types.includes(DND_TYPES.BLOCK_ID) ? 'move' : 'copy';\n if (!isOverRef.current) {\n isOverRef.current = true;\n setIsOver(true);\n }\n },\n [],\n );\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n // Only trigger leave if we actually left this element\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX >= rect.left &&\n clientX <= rect.right &&\n clientY >= rect.top &&\n clientY <= rect.bottom\n ) {\n return;\n }\n isOverRef.current = false;\n setIsOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n isOverRef.current = false;\n setIsOver(false);\n\n // Check for new block from palette\n const blockType = getBlockTypeFromDrop(e);\n if (blockType) {\n const block = {\n id: generateBlockId(),\n type: blockType,\n properties: JSON.parse(JSON.stringify(DEFAULT_BLOCK_PROPERTIES[blockType])),\n };\n dispatch({\n type: 'ADD_BLOCK_AND_SELECT',\n payload: { sectionId, columnId, block, index },\n });\n return;\n }\n\n // Check for block move\n const moveData = getBlockMoveFromDrop(e);\n if (moveData) {\n dispatch({\n type: 'MOVE_BLOCK',\n payload: {\n fromSectionId: moveData.sectionId,\n fromColumnId: moveData.columnId,\n blockId: moveData.blockId,\n toSectionId: sectionId,\n toColumnId: columnId,\n toIndex: index,\n },\n });\n }\n },\n [dispatch, sectionId, columnId, index],\n );\n\n if (emptyPlaceholder) {\n return (\n <div\n className={`ee-drop-zone ee-drop-zone--empty ${styles.emptyColumn} ${isOver ? styles.emptyColumnActive : ''}`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isOver ? 'Release to drop' : 'Drag blocks here'}\n </div>\n );\n }\n\n return (\n <div\n className={`ee-drop-zone ${styles.dropZone} ${isOver ? styles.dropZoneActive : ''}`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isOver && <div className={styles.dropZoneLabel}>Drop here</div>}\n </div>\n );\n});\n",".canvasWrapper {\n display: flex;\n justify-content: center;\n padding: var(--ee-space-xl);\n}\n\n.canvasBody {\n width: 600px;\n min-height: 400px;\n background: var(--ee-bg-email-body);\n box-shadow: var(--ee-shadow-lg);\n border-radius: var(--ee-border-radius);\n position: relative;\n transition: box-shadow var(--ee-transition-fast);\n}\n\n.canvasBodyDragOver {\n box-shadow: var(--ee-shadow-lg), 0 0 0 3px var(--ee-dropzone-color);\n}\n\n/* Section */\n.section {\n position: relative;\n border: 1px solid transparent;\n transition: border-color var(--ee-transition-fast);\n cursor: pointer;\n}\n\n.section:hover {\n border-color: var(--ee-border-color-strong);\n}\n\n.section.sectionSelected,\n.sectionSelected:hover {\n border-color: var(--ee-border-selected);\n}\n\n.sectionFullWidth {\n border-left: 3px solid var(--ee-color-primary);\n}\n\n.sectionOverlay {\n position: absolute;\n top: -1px;\n right: -1px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity var(--ee-transition-fast);\n z-index: var(--ee-z-block-overlay);\n}\n\n.section:hover .sectionOverlay {\n opacity: 1;\n}\n\n.sectionBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n font-size: 12px;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.sectionBtn:hover {\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-danger);\n}\n\n.sectionBtnDuplicate:hover {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.sectionDragHandle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n cursor: grab;\n font-size: 14px;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n user-select: none;\n line-height: 1;\n}\n\n.sectionDragHandle:hover {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.sectionDragHandle:active {\n cursor: grabbing;\n}\n\n.sectionContent {\n display: flex;\n min-height: 40px;\n}\n\n/* Column */\n.column {\n flex: 1;\n min-height: 40px;\n padding: 2px;\n position: relative;\n}\n\n/* Block */\n.blockWrapper {\n position: relative;\n border: 1px solid transparent;\n border-radius: var(--ee-border-radius-sm);\n transition: all var(--ee-transition-fast);\n cursor: pointer;\n}\n\n.blockWrapper:hover {\n border-color: var(--ee-border-color-strong);\n}\n\n.blockWrapper.blockSelected,\n.blockSelected:hover {\n border-color: var(--ee-border-selected);\n box-shadow: var(--ee-shadow-focus);\n}\n\n.blockOverlay {\n position: absolute;\n top: -1px;\n right: -1px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity var(--ee-transition-fast);\n z-index: var(--ee-z-block-overlay);\n}\n\n.blockWrapper:hover .blockOverlay {\n opacity: 1;\n}\n\n.blockBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: 3px;\n cursor: pointer;\n font-size: 10px;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.blockBtn:hover {\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-danger);\n}\n\n.blockBtnDuplicate:hover {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.blockWrapper.blockDropBefore {\n box-shadow: 0 -2px 0 0 var(--ee-color-primary);\n}\n\n.blockWrapper.blockDropAfter {\n box-shadow: 0 2px 0 0 var(--ee-color-primary);\n}\n\n/* Drop Zone */\n.dropZone {\n min-height: 2px;\n padding: 4px 0;\n transition: all var(--ee-transition-fast);\n position: relative;\n margin: 0 4px;\n}\n\n.dropZoneActive {\n min-height: var(--ee-dropzone-height-active);\n background: var(--ee-dropzone-bg);\n border: 2px dashed var(--ee-dropzone-color);\n border-radius: var(--ee-border-radius-sm);\n}\n\n.dropZoneLabel {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--ee-font-size-xs);\n color: var(--ee-dropzone-color);\n font-weight: var(--ee-font-weight-medium);\n}\n\n/* Empty column */\n.emptyColumn {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100px;\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n margin: var(--ee-space-sm);\n transition: all var(--ee-transition-fast);\n cursor: default;\n}\n\n.emptyColumnActive {\n border-color: var(--ee-dropzone-color);\n background: var(--ee-dropzone-bg);\n color: var(--ee-dropzone-color);\n font-weight: var(--ee-font-weight-medium);\n}\n\n/* Section Drop Zone */\n.sectionDropZone {\n min-height: 2px;\n transition: all var(--ee-transition-fast);\n position: relative;\n}\n\n.sectionDropZoneActive {\n min-height: 40px;\n background: var(--ee-dropzone-bg);\n border: 2px dashed var(--ee-dropzone-color);\n border-radius: var(--ee-border-radius-sm);\n margin: 2px 4px;\n}\n\n.sectionDropZoneLabel {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--ee-font-size-xs);\n color: var(--ee-dropzone-color);\n font-weight: var(--ee-font-weight-medium);\n}\n\n/* Add section button */\n.addSectionBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n padding: var(--ee-space-md);\n margin: var(--ee-space-sm) var(--ee-space-lg);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n background: transparent;\n color: var(--ee-text-secondary);\n font-size: var(--ee-font-size-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n width: calc(100% - 2 * var(--ee-space-lg));\n}\n\n.addSectionBtn:hover {\n border-color: var(--ee-color-primary);\n color: var(--ee-color-primary);\n background: var(--ee-color-primary-light);\n}\n","import React, { useState, useCallback, useRef } from 'react';\nimport { isSectionDrop, getSectionMoveFromDrop } from '../../utils/dnd';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport styles from '../../styles/canvas.module.css';\n\ninterface SectionDropZoneProps {\n index: number;\n}\n\nexport const SectionDropZone = React.memo(function SectionDropZone({ index }: SectionDropZoneProps) {\n const dispatch = useEditorDispatch();\n const [isOver, setIsOver] = useState(false);\n const isOverRef = useRef(false);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n if (!isSectionDrop(e)) return;\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.dropEffect = 'move';\n if (!isOverRef.current) {\n isOverRef.current = true;\n setIsOver(true);\n }\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX >= rect.left &&\n clientX <= rect.right &&\n clientY >= rect.top &&\n clientY <= rect.bottom\n ) {\n return;\n }\n isOverRef.current = false;\n setIsOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n isOverRef.current = false;\n setIsOver(false);\n\n const sectionId = getSectionMoveFromDrop(e);\n if (!sectionId) return;\n\n dispatch({\n type: 'MOVE_SECTION',\n payload: { sectionId, toIndex: index },\n });\n },\n [dispatch, index],\n );\n\n return (\n <div\n className={`ee-section-drop-zone ${styles.sectionDropZone} ${isOver ? styles.sectionDropZoneActive : ''}`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isOver && <div className={styles.sectionDropZoneLabel}>Move section here</div>}\n </div>\n );\n});\n","import React, { useCallback } from 'react';\nimport type { Section } from '../../types';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst BG_SIZE_OPTIONS = [\n { value: 'cover', label: 'Cover' }, { value: 'contain', label: 'Contain' }, { value: 'auto', label: 'Auto' },\n];\n\nconst BG_REPEAT_OPTIONS = [\n { value: 'no-repeat', label: 'No Repeat' }, { value: 'repeat', label: 'Repeat' },\n { value: 'repeat-x', label: 'Repeat X' }, { value: 'repeat-y', label: 'Repeat Y' },\n];\n\ninterface SectionPropertiesProps {\n section: Section;\n}\n\nexport function SectionProperties({ section }: SectionPropertiesProps) {\n const dispatch = useEditorDispatch();\n const { properties } = section;\n\n const update = useCallback(\n (props: Record<string, any>) => {\n dispatch({ type: 'UPDATE_SECTION', payload: { sectionId: section.id, properties: props } });\n },\n [dispatch, section.id],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"color\" label=\"Background Color\" value={properties.backgroundColor} onChange={(v) => update({ backgroundColor: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={properties.padding} onChange={(v) => update({ padding: v })} />\n <PropertyField type=\"text\" label=\"Border Radius\" value={properties.borderRadius} onChange={(v) => update({ borderRadius: v })} />\n <PropertyField type=\"toggle\" label=\"Full Width\" value={properties.fullWidth || false} onChange={(v) => update({ fullWidth: v })} />\n <FieldSeparator />\n <PropertyField type=\"text\" label=\"Background Image URL\" value={properties.backgroundImage || ''} onChange={(v) => update({ backgroundImage: v })} placeholder=\"https://...\" />\n <PropertyField type=\"select\" label=\"Background Size\" value={properties.backgroundSize || 'cover'} onChange={(v) => update({ backgroundSize: v })} options={BG_SIZE_OPTIONS} />\n <PropertyField type=\"select\" label=\"Background Repeat\" value={properties.backgroundRepeat || 'no-repeat'} onChange={(v) => update({ backgroundRepeat: v })} options={BG_REPEAT_OPTIONS} />\n </div>\n );\n}\n","import React from 'react';\nimport { ColorPicker } from './controls/ColorPicker';\nimport { PaddingInput } from './controls/PaddingInput';\nimport { AlignmentPicker } from './controls/AlignmentPicker';\nimport { FontPicker } from './controls/FontPicker';\nimport { SliderInput } from './controls/SliderInput';\nimport { LinkInput } from './controls/LinkInput';\nimport styles from '../../styles/properties.module.css';\n\ninterface SelectOption {\n value: string;\n label: string;\n}\n\ntype PropertyFieldProps =\n | { type: 'color'; label: string; value: string; onChange: (v: string) => void }\n | { type: 'text'; label: string; value: string; onChange: (v: string) => void; placeholder?: string }\n | { type: 'textarea'; label: string; value: string; onChange: (v: string) => void; placeholder?: string; rows?: number; code?: boolean }\n | { type: 'select'; label: string; value: string; onChange: (v: string) => void; options: SelectOption[] }\n | { type: 'padding'; label: string; value: string; onChange: (v: string) => void }\n | { type: 'alignment'; label: string; value: string; onChange: (v: string) => void; options?: string[] }\n | { type: 'slider'; label: string; value: number; onChange: (v: number) => void; min: number; max: number; step?: number; unit?: string }\n | { type: 'toggle'; label: string; value: boolean; onChange: (v: boolean) => void }\n | { type: 'font'; label: string; value: string; onChange: (v: string) => void }\n | { type: 'link'; label: string; value: string; onChange: (v: string) => void };\n\n/**\n * Declarative property field that renders the appropriate control.\n * Reduces per-panel boilerplate from repeated JSX to a single component.\n * Wrapped in React.memo to prevent cascading re-renders when sibling fields change.\n */\nexport const PropertyField = React.memo(function PropertyField(props: PropertyFieldProps) {\n switch (props.type) {\n case 'color':\n return <ColorPicker label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'padding':\n return <PaddingInput label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'alignment':\n return <AlignmentPicker label={props.label} value={props.value} onChange={props.onChange} options={props.options} />;\n\n case 'font':\n return <FontPicker label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'link':\n return <LinkInput label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'slider':\n return (\n <SliderInput\n label={props.label}\n value={props.value}\n min={props.min}\n max={props.max}\n step={props.step}\n unit={props.unit}\n onChange={props.onChange}\n />\n );\n\n case 'toggle':\n return (\n <div className={styles.fieldGroup}>\n <label className={`ee-checkbox-label ${styles.checkboxLabel}`}>\n <input\n type=\"checkbox\"\n checked={props.value}\n onChange={(e) => props.onChange(e.target.checked)}\n />\n {props.label}\n </label>\n </div>\n );\n\n case 'select':\n return (\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>{props.label}</label>\n <select\n className={styles.fieldSelect}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n >\n {props.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n );\n\n case 'textarea':\n return (\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>{props.label}</label>\n <textarea\n className={props.code ? `ee-code-textarea ${styles.fieldTextareaCode}` : styles.fieldTextarea}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n placeholder={props.placeholder}\n rows={props.rows ?? 3}\n />\n </div>\n );\n\n case 'text':\n default:\n return (\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>{props.label}</label>\n <input\n className={styles.fieldInput}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n placeholder={props.placeholder}\n />\n </div>\n );\n }\n});\n\n/** Visual separator between field groups */\nexport function FieldSeparator() {\n return <div className={styles.separator} />;\n}\n","import React, { useState, useCallback, useRef, useEffect } from 'react';\nimport { COLOR_PRESETS } from '../../../constants';\nimport styles from '../../../styles/properties.module.css';\n\ninterface ColorPickerProps {\n label: string;\n value: string;\n onChange: (color: string) => void;\n}\n\nexport function ColorPicker({ label, value, onChange }: ColorPickerProps) {\n const [isOpen, setIsOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const handlePresetClick = useCallback(\n (color: string) => {\n onChange(color);\n setIsOpen(false);\n },\n [onChange],\n );\n\n const isHex = /^#[0-9a-fA-F]{6}$/.test(value);\n\n return (\n <div className={`ee-field-group ee-color-picker ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.colorPickerWrapper} ref={wrapperRef}>\n <div\n className={styles.colorPickerTrigger}\n onClick={() => setIsOpen(!isOpen)}\n >\n <div\n className={`${styles.colorSwatch} ${value === 'transparent' ? styles.colorSwatchTransparent : ''}`}\n style={value !== 'transparent' ? { backgroundColor: value || 'transparent' } : undefined}\n />\n <span className={styles.colorValue}>{value || 'transparent'}</span>\n </div>\n {isOpen && (\n <div className={styles.colorPresets}>\n <button\n className={`ee-color-preset-transparent ${styles.colorPresetBtn} ${styles.colorPresetBtnTransparent} ${styles.colorPresetBtnFull} ${\n value === 'transparent' ? styles.colorPresetBtnActive : ''\n }`}\n onClick={() => handlePresetClick('transparent')}\n title=\"transparent\"\n >\n Transparent\n </button>\n {COLOR_PRESETS.map((color) => (\n <button\n key={color}\n className={`${styles.colorPresetBtn} ${\n color === value ? styles.colorPresetBtnActive : ''\n }`}\n style={{ backgroundColor: color }}\n onClick={() => handlePresetClick(color)}\n title={color}\n />\n ))}\n <input\n type=\"color\"\n className={`ee-color-native-input ${styles.colorNativeInput}`}\n value={isHex ? value : '#ffffff'}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n",".propertiesPanel {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n.propertiesHeader {\n padding: var(--ee-space-md) var(--ee-space-lg);\n border-bottom: 1px solid var(--ee-border-color);\n font-size: var(--ee-font-size-sm);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.propertiesBody {\n padding: var(--ee-space-md) var(--ee-space-lg);\n display: flex;\n flex-direction: column;\n gap: var(--ee-space-md);\n}\n\n.emptyProperties {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n text-align: center;\n padding: var(--ee-space-lg);\n}\n\n.fieldHint {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-muted);\n background: var(--ee-bg-hover);\n padding: var(--ee-space-sm) var(--ee-space-md);\n border-radius: var(--ee-border-radius-sm);\n margin: 0;\n line-height: 1.4;\n}\n\n/* Form controls */\n.fieldGroup {\n display: flex;\n flex-direction: column;\n gap: var(--ee-space-xs);\n}\n\n.fieldLabel {\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.fieldInput {\n width: 100%;\n padding: 6px 8px;\n font-size: var(--ee-font-size-md);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n transition: border-color var(--ee-transition-fast);\n box-sizing: border-box;\n}\n\n.fieldInput:focus {\n border-color: var(--ee-border-focus);\n box-shadow: var(--ee-shadow-focus);\n}\n\n.fieldTextarea {\n composes: fieldInput;\n resize: vertical;\n min-height: 60px;\n}\n\n.fieldSelect {\n composes: fieldInput;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M3 5l3 3 3-3z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 8px center;\n padding-right: 24px;\n}\n\n.fieldRow {\n display: flex;\n gap: var(--ee-space-sm);\n align-items: center;\n}\n\n.fieldHalf {\n flex: 1;\n}\n\n/* Color Picker */\n.colorPickerWrapper {\n position: relative;\n}\n\n.colorPickerTrigger {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n padding: 6px 8px;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n cursor: pointer;\n width: 100%;\n box-sizing: border-box;\n}\n\n.colorSwatch {\n width: 20px;\n height: 20px;\n border-radius: 3px;\n border: 1px solid var(--ee-border-color);\n flex-shrink: 0;\n}\n\n.colorValue {\n font-size: var(--ee-font-size-sm);\n color: var(--ee-text-primary);\n font-family: monospace;\n}\n\n.colorPresets {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 4px;\n padding: var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: var(--ee-z-dropdown);\n margin-top: 4px;\n}\n\n.colorPresetBtn {\n width: 28px;\n height: 28px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.colorPresetBtn:hover {\n transform: scale(1.15);\n}\n\n.colorPresetBtnActive {\n border-color: var(--ee-color-primary);\n}\n\n.colorPresetBtnTransparent {\n background: repeating-conic-gradient(var(--ee-border-color-strong) 0% 25%, var(--ee-bg-panel) 0% 50%) 0 0 / 12px 12px;\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-secondary);\n font-weight: var(--ee-font-weight-medium);\n height: 24px;\n}\n\n.colorSwatchTransparent {\n background: repeating-conic-gradient(var(--ee-border-color-strong) 0% 25%, var(--ee-bg-panel) 0% 50%) 0 0 / 8px 8px;\n}\n\n/* Padding Input */\n.paddingGrid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--ee-space-xs);\n}\n\n.paddingField {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.paddingLabel {\n font-size: 10px;\n color: var(--ee-text-muted);\n text-align: center;\n}\n\n.paddingInput {\n composes: fieldInput;\n text-align: center;\n padding: 4px;\n font-size: var(--ee-font-size-xs);\n}\n\n/* Alignment Picker */\n.alignmentPicker {\n display: flex;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n overflow: hidden;\n}\n\n.alignmentBtn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n background: var(--ee-bg-input);\n border: none;\n border-right: 1px solid var(--ee-border-color);\n cursor: pointer;\n font-size: var(--ee-font-size-sm);\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.alignmentBtn:last-child {\n border-right: none;\n}\n\n.alignmentBtn:hover {\n background: var(--ee-bg-hover);\n}\n\n.alignmentBtnActive {\n background: var(--ee-color-primary) !important;\n color: var(--ee-text-inverse);\n}\n\n/* Slider Input */\n.sliderWrapper {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n}\n\n.sliderInput {\n flex: 1;\n height: 4px;\n appearance: none;\n background: var(--ee-border-color);\n border-radius: 2px;\n outline: none;\n}\n\n.sliderInput::-webkit-slider-thumb {\n appearance: none;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--ee-color-primary);\n cursor: pointer;\n}\n\n.sliderInput::-moz-range-thumb {\n width: 14px;\n height: 14px;\n border: none;\n border-radius: 50%;\n background: var(--ee-color-primary);\n cursor: pointer;\n}\n\n.sliderValue {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-secondary);\n min-width: 36px;\n text-align: right;\n font-family: monospace;\n}\n\n/* Item action buttons (move up/down, remove) in list editors */\n.itemActionBtn {\n padding: 4px 6px;\n cursor: pointer;\n border: 1px solid var(--ee-border-color);\n border-radius: 3px;\n background: var(--ee-bg-input);\n}\n\n.itemActionBtnDanger {\n composes: itemActionBtn;\n color: var(--ee-color-danger);\n}\n\n/* Add item button (e.g. \"+ Add Item\", \"+ Add Element\") */\n.addItemBtn {\n margin-top: 8px;\n padding: 6px 12px;\n cursor: pointer;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n font-size: var(--ee-font-size-sm);\n width: 100%;\n}\n\n/* Input that stretches to fill remaining row space */\n.fieldInputFlex {\n composes: fieldInput;\n flex: 1;\n}\n\n/* Flex row for link-type input combos */\n.fieldRowCompact {\n display: flex;\n gap: 4px;\n}\n\n.fieldSelectNarrow {\n composes: fieldSelect;\n width: 90px;\n flex-shrink: 0;\n}\n\n/* Monospace textarea for code/HTML editing */\n.fieldTextareaCode {\n composes: fieldInput;\n font-family: monospace;\n font-size: 12px;\n resize: vertical;\n}\n\n/* Upload-style button with centered text */\n.fieldBtnUpload {\n composes: fieldInput;\n cursor: pointer;\n text-align: center;\n}\n\n.fieldBtnUploadDisabled {\n composes: fieldBtnUpload;\n cursor: wait;\n}\n\n/* Validation error message */\n.validationError {\n color: var(--ee-color-danger);\n font-size: var(--ee-font-size-xs);\n margin-top: 2px;\n}\n\n/* Spacing helper for stacked inputs within a list item */\n.fieldInputStacked {\n composes: fieldInput;\n margin-top: 4px;\n}\n\n/* Checkbox label inline */\n.checkboxLabel {\n composes: fieldLabel;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Color picker grid overrides */\n.colorPresetBtnFull {\n grid-column: 1 / -1;\n width: 100%;\n}\n\n.colorNativeInput {\n width: 100%;\n grid-column: 1 / -1;\n height: 28px;\n cursor: pointer;\n border: none;\n}\n\n/* Separator */\n.separator {\n height: 1px;\n background: var(--ee-border-color);\n margin: var(--ee-space-xs) 0;\n}\n","import React, { useCallback, useMemo } from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ninterface PaddingInputProps {\n label: string;\n value: string;\n onChange: (padding: string) => void;\n}\n\nfunction parsePadding(value: string): [string, string, string, string] {\n const parts = value.split(/\\s+/).map((p) => p.trim()).filter(Boolean);\n switch (parts.length) {\n case 1:\n return [parts[0], parts[0], parts[0], parts[0]];\n case 2:\n return [parts[0], parts[1], parts[0], parts[1]];\n case 3:\n return [parts[0], parts[1], parts[2], parts[1]];\n case 4:\n return [parts[0], parts[1], parts[2], parts[3]];\n default:\n return ['0px', '0px', '0px', '0px'];\n }\n}\n\nexport function PaddingInput({ label, value, onChange }: PaddingInputProps) {\n const [top, right, bottom, left] = useMemo(() => parsePadding(value), [value]);\n\n const handleChange = useCallback(\n (position: 'top' | 'right' | 'bottom' | 'left', newVal: string) => {\n const parts = parsePadding(value);\n const idx = { top: 0, right: 1, bottom: 2, left: 3 }[position];\n parts[idx] = newVal || '0px';\n onChange(parts.join(' '));\n },\n [value, onChange],\n );\n\n return (\n <div className={`ee-field-group ee-padding ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.paddingGrid}>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Top</span>\n <input\n className={styles.paddingInput}\n value={top}\n onChange={(e) => handleChange('top', e.target.value)}\n />\n </div>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Right</span>\n <input\n className={styles.paddingInput}\n value={right}\n onChange={(e) => handleChange('right', e.target.value)}\n />\n </div>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Bottom</span>\n <input\n className={styles.paddingInput}\n value={bottom}\n onChange={(e) => handleChange('bottom', e.target.value)}\n />\n </div>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Left</span>\n <input\n className={styles.paddingInput}\n value={left}\n onChange={(e) => handleChange('left', e.target.value)}\n />\n </div>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ninterface AlignmentPickerProps {\n label: string;\n value: string;\n onChange: (align: string) => void;\n options?: string[];\n}\n\nconst ALIGN_ICONS: Record<string, string> = {\n left: '\\u2261',\n center: '\\u2261',\n right: '\\u2261',\n justify: '\\u2261',\n};\n\nexport function AlignmentPicker({\n label,\n value,\n onChange,\n options = ['left', 'center', 'right'],\n}: AlignmentPickerProps) {\n return (\n <div className={`ee-field-group ee-alignment ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.alignmentPicker}>\n {options.map((option) => (\n <button\n key={option}\n className={`${styles.alignmentBtn} ${\n value === option ? styles.alignmentBtnActive : ''\n }`}\n onClick={() => onChange(option)}\n title={option.charAt(0).toUpperCase() + option.slice(1)}\n >\n {option.charAt(0).toUpperCase()}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { FONT_OPTIONS } from '../../../constants';\nimport styles from '../../../styles/properties.module.css';\n\ninterface FontPickerProps {\n label: string;\n value: string;\n onChange: (font: string) => void;\n}\n\nexport function FontPicker({ label, value, onChange }: FontPickerProps) {\n return (\n <div className={`ee-field-group ee-font-picker ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <select\n className={styles.fieldSelect}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n {FONT_OPTIONS.map((font) => (\n <option key={font} value={font} style={{ fontFamily: font }}>\n {font.split(',')[0].trim()}\n </option>\n ))}\n </select>\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ninterface SliderInputProps {\n label: string;\n value: number;\n min: number;\n max: number;\n step?: number;\n unit?: string;\n onChange: (value: number) => void;\n}\n\nexport function SliderInput({\n label,\n value,\n min,\n max,\n step = 1,\n unit = 'px',\n onChange,\n}: SliderInputProps) {\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(Number(e.target.value));\n },\n [onChange],\n );\n\n return (\n <div className={`ee-field-group ee-slider ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.sliderWrapper}>\n <input\n type=\"range\"\n className={styles.sliderInput}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleChange}\n />\n <span className={styles.sliderValue}>\n {value}{unit}\n </span>\n </div>\n </div>\n );\n}\n","import React, { useState, useCallback, useEffect, useMemo } from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ntype LinkType = 'url' | 'email' | 'phone';\n\nfunction validateLink(value: string, type: LinkType): string | null {\n if (!value) return null;\n if (type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n return 'Invalid email address';\n }\n if (type === 'phone' && !/^[+\\d][\\d\\s\\-().]{4,}$/.test(value)) {\n return 'Invalid phone number';\n }\n if (type === 'url' && value && !/^(https?:\\/\\/|\\/|#)/.test(value)) {\n return 'URL should start with https://';\n }\n return null;\n}\n\ninterface LinkInputProps {\n label: string;\n value: string;\n onChange: (href: string) => void;\n}\n\nfunction detectType(href: string): LinkType {\n if (href.startsWith('mailto:')) return 'email';\n if (href.startsWith('tel:')) return 'phone';\n return 'url';\n}\n\nfunction stripPrefix(href: string, type: LinkType): string {\n if (type === 'email') return href.replace(/^mailto:/, '');\n if (type === 'phone') return href.replace(/^tel:/, '');\n return href;\n}\n\nfunction addPrefix(value: string, type: LinkType): string {\n if (type === 'email' && value && !value.startsWith('mailto:')) return `mailto:${value}`;\n if (type === 'phone' && value && !value.startsWith('tel:')) return `tel:${value}`;\n return value;\n}\n\nexport function LinkInput({ label, value, onChange }: LinkInputProps) {\n const [type, setType] = useState<LinkType>(() => detectType(value));\n const [rawValue, setRawValue] = useState(() => stripPrefix(value, detectType(value)));\n const validationError = useMemo(() => validateLink(rawValue, type), [rawValue, type]);\n\n useEffect(() => {\n const detected = detectType(value);\n setType(detected);\n setRawValue(stripPrefix(value, detected));\n }, [value]);\n\n const handleTypeChange = useCallback(\n (newType: LinkType) => {\n setType(newType);\n onChange(addPrefix(rawValue, newType));\n },\n [rawValue, onChange],\n );\n\n const handleValueChange = useCallback(\n (newValue: string) => {\n setRawValue(newValue);\n onChange(addPrefix(newValue, type));\n },\n [type, onChange],\n );\n\n const placeholder = type === 'email' ? 'user@example.com'\n : type === 'phone' ? '+1234567890'\n : 'https://';\n\n return (\n <div className={`ee-field-group ee-link-input ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.fieldRowCompact}>\n <select\n className={styles.fieldSelectNarrow}\n value={type}\n onChange={(e) => handleTypeChange(e.target.value as LinkType)}\n >\n <option value=\"url\">URL</option>\n <option value=\"email\">Email</option>\n <option value=\"phone\">Phone</option>\n </select>\n <input\n className={styles.fieldInputFlex}\n value={rawValue}\n onChange={(e) => handleValueChange(e.target.value)}\n placeholder={placeholder}\n aria-label={label}\n aria-invalid={!!validationError}\n />\n </div>\n {validationError && (\n <span className={`ee-validation-error ${styles.validationError}`} role=\"alert\">\n {validationError}\n </span>\n )}\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { HeadMetadata } from '../../types';\nimport { useTemplateContext, useEditorDispatch } from '../../context/EditorContext';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nexport function HeadMetadataProperties() {\n const { template } = useTemplateContext();\n const dispatch = useEditorDispatch();\n const metadata = template.headMetadata ?? { title: '', previewText: '', headStyles: [] };\n\n const update = useCallback(\n (props: Partial<HeadMetadata>) => {\n dispatch({ type: 'UPDATE_HEAD_METADATA', payload: props });\n },\n [dispatch],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Email Title\" value={metadata.title} onChange={(v) => update({ title: v })} placeholder=\"Email title (mj-title)\" />\n <PropertyField type=\"text\" label=\"Preview Text\" value={metadata.previewText} onChange={(v) => update({ previewText: v })} placeholder=\"Preview text shown in inbox (mj-preview)\" />\n <PropertyField\n type=\"textarea\"\n label=\"Custom Styles\"\n value={metadata.headStyles.join('\\n\\n')}\n onChange={(v) => {\n const headStyles = v.trim() ? [v] : [];\n update({ headStyles });\n }}\n placeholder=\"Custom CSS (mj-style)\"\n rows={6}\n code\n />\n </div>\n );\n}\n","import { useCallback } from 'react';\nimport type { BlockProperties } from '../types';\nimport { useEditorDispatch } from '../context/EditorContext';\n\n/**\n * Hook that returns a memoized `update` function for dispatching UPDATE_BLOCK.\n * Eliminates the repeated useCallback + dispatch boilerplate in every property panel.\n *\n * Accepts `Record<string, unknown>` to avoid `as any` casts when PropertyField\n * onChange returns a plain string for select/alignment values.\n */\nexport function useBlockUpdate(blockId: string) {\n const dispatch = useEditorDispatch();\n\n const update = useCallback(\n (properties: Partial<BlockProperties> | Record<string, unknown>) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: { blockId, properties: properties as Partial<BlockProperties> },\n });\n },\n [dispatch, blockId],\n );\n\n return update;\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface TextPropertiesProps {\n block: Block;\n}\n\nexport function TextProperties({ block }: TextPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <p className={styles.fieldHint}>\n Use the inline toolbar above the text block to format font, size, color, and alignment.\n </p>\n <PropertyField type=\"text\" label=\"Line Height\" value={p.lineHeight} onChange={(v) => update({ lineHeight: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst FONT_WEIGHT_OPTIONS = [\n { value: 'normal', label: 'Normal' }, { value: 'bold', label: 'Bold' },\n { value: '100', label: '100' }, { value: '200', label: '200' },\n { value: '300', label: '300' }, { value: '400', label: '400' },\n { value: '500', label: '500' }, { value: '600', label: '600' },\n { value: '700', label: '700' }, { value: '800', label: '800' },\n { value: '900', label: '900' },\n];\n\nconst TEXT_TRANSFORM_OPTIONS = [\n { value: 'none', label: 'None' }, { value: 'uppercase', label: 'Uppercase' },\n { value: 'lowercase', label: 'Lowercase' }, { value: 'capitalize', label: 'Capitalize' },\n];\n\ninterface ButtonPropertiesProps {\n block: Block;\n}\n\nexport function ButtonProperties({ block }: ButtonPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Button Text\" value={p.text} onChange={(v) => update({ text: v })} />\n <PropertyField type=\"link\" label=\"Link URL\" value={p.href} onChange={(v) => update({ href: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Background Color\" value={p.backgroundColor} onChange={(v) => update({ backgroundColor: v })} />\n <PropertyField type=\"color\" label=\"Text Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"font\" label=\"Font Family\" value={p.fontFamily} onChange={(v) => update({ fontFamily: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"text\" label=\"Border Radius\" value={p.borderRadius} onChange={(v) => update({ borderRadius: v })} />\n <PropertyField type=\"text\" label=\"Width\" value={p.width} onChange={(v) => update({ width: v })} placeholder=\"auto\" />\n <PropertyField type=\"select\" label=\"Font Weight\" value={p.fontWeight || 'normal'} onChange={(v) => update({ fontWeight: v })} options={FONT_WEIGHT_OPTIONS} />\n <PropertyField type=\"select\" label=\"Text Transform\" value={p.textTransform || 'none'} onChange={(v) => update({ textTransform: v })} options={TEXT_TRANSFORM_OPTIONS} />\n <PropertyField type=\"text\" label=\"Letter Spacing\" value={p.letterSpacing || 'normal'} onChange={(v) => update({ letterSpacing: v })} placeholder=\"normal\" />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Outer Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <PropertyField type=\"padding\" label=\"Inner Padding\" value={p.innerPadding} onChange={(v) => update({ innerPadding: v })} />\n </div>\n );\n}\n","import React, { useCallback, useRef } from 'react';\nimport type { Block } from '../../types';\nimport { useImageAdapter } from '../../context/EditorContext';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { useImageUpload } from '../ImageUpload/useImageUpload';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface ImagePropertiesProps {\n block: Block;\n}\n\nexport function ImageProperties({ block }: ImagePropertiesProps) {\n const update = useBlockUpdate(block.id);\n const { imageUploadAdapter } = useImageAdapter();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const p = block.properties;\n\n const { upload, status, error } = useImageUpload({\n adapter: imageUploadAdapter,\n blockId: block.id,\n onSuccess: (result) => {\n update({\n src: result.url,\n alt: result.alt ?? p.alt,\n width: result.width ? `${result.width}px` : p.width,\n });\n },\n });\n\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n await upload(file);\n },\n [upload],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Image URL\" value={p.src} onChange={(v) => update({ src: v })} placeholder=\"https://...\" />\n {imageUploadAdapter && (\n <div className={styles.fieldGroup}>\n <button\n className={`ee-upload-btn ${status === 'uploading' ? styles.fieldBtnUploadDisabled : styles.fieldBtnUpload}`}\n onClick={() => fileInputRef.current?.click()}\n disabled={status === 'uploading'}\n >\n {status === 'uploading' ? 'Uploading...' : 'Upload Image'}\n </button>\n {error && <span className={`ee-upload-error ${styles.validationError}`}>{error}</span>}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n />\n </div>\n )}\n <PropertyField type=\"text\" label=\"Alt Text\" value={p.alt} onChange={(v) => update({ alt: v })} placeholder=\"Image description\" />\n <PropertyField type=\"link\" label=\"Link URL\" value={p.href} onChange={(v) => update({ href: v })} />\n <FieldSeparator />\n <div className={styles.fieldRow}>\n <div className={styles.fieldHalf}>\n <PropertyField type=\"text\" label=\"Width\" value={p.width} onChange={(v) => update({ width: v })} />\n </div>\n <div className={styles.fieldHalf}>\n <PropertyField type=\"text\" label=\"Height\" value={p.height} onChange={(v) => update({ height: v })} />\n </div>\n </div>\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <PropertyField type=\"toggle\" label=\"Fluid on Mobile\" value={p.fluidOnMobile} onChange={(v) => update({ fluidOnMobile: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst BORDER_STYLE_OPTIONS = [\n { value: 'solid', label: 'Solid' },\n { value: 'dashed', label: 'Dashed' },\n { value: 'dotted', label: 'Dotted' },\n];\n\ninterface DividerPropertiesProps {\n block: Block;\n}\n\nexport function DividerProperties({ block }: DividerPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"color\" label=\"Border Color\" value={p.borderColor} onChange={(v) => update({ borderColor: v })} />\n <PropertyField type=\"text\" label=\"Border Width\" value={p.borderWidth} onChange={(v) => update({ borderWidth: v })} />\n <PropertyField type=\"select\" label=\"Border Style\" value={p.borderStyle} onChange={(v) => update({ borderStyle: v })} options={BORDER_STYLE_OPTIONS} />\n <PropertyField type=\"text\" label=\"Width\" value={p.width} onChange={(v) => update({ width: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface SpacerPropertiesProps {\n block: Block;\n}\n\nexport function SpacerProperties({ block }: SpacerPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n const heightNum = parseInt(p.height, 10) || 20;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"slider\" label=\"Height\" value={heightNum} min={5} max={200} step={5} unit=\"px\" onChange={(v) => update({ height: `${v}px` })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block, SocialElement } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\nimport blockStyles from '../../styles/blocks.module.css';\n\nconst MODE_OPTIONS = [\n { value: 'horizontal', label: 'Horizontal' }, { value: 'vertical', label: 'Vertical' },\n];\n\ninterface SocialPropertiesProps {\n block: Block;\n}\n\nexport function SocialProperties({ block }: SocialPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n const updateElement = useCallback(\n (index: number, changes: Partial<SocialElement>) => {\n const elements = [...block.properties.elements];\n elements[index] = { ...elements[index], ...changes };\n update({ elements });\n },\n [block.properties.elements, update],\n );\n\n const addElement = useCallback(() => {\n const elements = [...block.properties.elements, { name: 'web', href: '#' }];\n update({ elements });\n }, [block.properties.elements, update]);\n\n const removeElement = useCallback(\n (index: number) => {\n const elements = block.properties.elements.filter((_: any, i: number) => i !== index);\n update({ elements });\n },\n [block.properties.elements, update],\n );\n\n const moveElement = useCallback(\n (index: number, direction: -1 | 1) => {\n const elements = [...block.properties.elements];\n const newIndex = index + direction;\n if (newIndex < 0 || newIndex >= elements.length) return;\n [elements[index], elements[newIndex]] = [elements[newIndex], elements[index]];\n update({ elements });\n },\n [block.properties.elements, update],\n );\n\n if (!narrowBlock(block, 'social')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"select\" label=\"Mode\" value={p.mode} onChange={(v) => update({ mode: v })} options={MODE_OPTIONS} />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"text\" label=\"Icon Size\" value={p.iconSize} onChange={(v) => update({ iconSize: v })} />\n <PropertyField type=\"text\" label=\"Icon Padding\" value={p.iconPadding} onChange={(v) => update({ iconPadding: v })} />\n <PropertyField type=\"text\" label=\"Border Radius\" value={p.borderRadius} onChange={(v) => update({ borderRadius: v })} />\n <PropertyField type=\"color\" label=\"Text Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <FieldSeparator />\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Social Elements</label>\n <div className={blockStyles.socialElementsContainer}>\n {p.elements.map((element: SocialElement, index: number) => (\n <div key={index} className={blockStyles.socialElementItem}>\n <div className={styles.fieldRow}>\n <select\n className={`${styles.fieldSelect} ${styles.fieldInputFlex}`}\n value={element.name}\n onChange={(e) => updateElement(index, { name: e.target.value })}\n >\n <option value=\"facebook\">Facebook</option>\n <option value=\"twitter\">Twitter</option>\n <option value=\"instagram\">Instagram</option>\n <option value=\"linkedin\">LinkedIn</option>\n <option value=\"youtube\">YouTube</option>\n <option value=\"github\">GitHub</option>\n <option value=\"pinterest\">Pinterest</option>\n <option value=\"snapchat\">Snapchat</option>\n <option value=\"tiktok\">TikTok</option>\n <option value=\"web\">Web</option>\n </select>\n <button className={`ee-item-move-up ${styles.itemActionBtn}`} onClick={() => moveElement(index, -1)} disabled={index === 0} title=\"Move up\">↑</button>\n <button className={`ee-item-move-down ${styles.itemActionBtn}`} onClick={() => moveElement(index, 1)} disabled={index === p.elements.length - 1} title=\"Move down\">↓</button>\n <button className={`ee-item-remove ${styles.itemActionBtnDanger}`} onClick={() => removeElement(index)} title=\"Remove\">×</button>\n </div>\n <input\n className={styles.fieldInputStacked}\n value={element.href}\n onChange={(e) => updateElement(index, { href: e.target.value })}\n placeholder=\"URL\"\n />\n <input\n className={styles.fieldInputStacked}\n value={element.content || ''}\n onChange={(e) => updateElement(index, { content: e.target.value })}\n placeholder=\"Label (optional)\"\n />\n </div>\n ))}\n </div>\n <button className={`ee-add-item ${styles.addItemBtn}`} onClick={addElement}>+ Add Element</button>\n </div>\n </div>\n );\n}\n","// ---- Block Types ----\n\nexport type BlockType = 'text' | 'button' | 'image' | 'divider' | 'spacer' | 'social' | 'html' | 'video' | 'heading' | 'countdown' | 'menu' | 'hero';\n\nexport interface TextBlockProperties {\n content: string; // TipTap JSON string\n fontFamily: string;\n fontSize: string;\n color: string;\n lineHeight: string;\n padding: string;\n align: 'left' | 'center' | 'right' | 'justify';\n fontWeight: string;\n textTransform: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n letterSpacing: string;\n}\n\nexport interface ButtonBlockProperties {\n text: string;\n href: string;\n backgroundColor: string;\n color: string;\n fontFamily: string;\n fontSize: string;\n borderRadius: string;\n padding: string;\n innerPadding: string;\n align: 'left' | 'center' | 'right';\n width: string;\n fontWeight: string;\n textTransform: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n letterSpacing: string;\n}\n\nexport interface ImageBlockProperties {\n src: string;\n alt: string;\n href: string;\n width: string;\n height: string;\n padding: string;\n align: 'left' | 'center' | 'right';\n fluidOnMobile: boolean;\n}\n\nexport interface DividerBlockProperties {\n borderColor: string;\n borderWidth: string;\n borderStyle: 'solid' | 'dashed' | 'dotted';\n padding: string;\n width: string;\n}\n\nexport interface SpacerBlockProperties {\n height: string;\n}\n\nexport interface SocialElement {\n name: string;\n href: string;\n src?: string;\n content?: string;\n backgroundColor?: string;\n color?: string;\n}\n\nexport interface SocialBlockProperties {\n elements: SocialElement[];\n mode: 'horizontal' | 'vertical';\n align: 'left' | 'center' | 'right';\n iconSize: string;\n iconPadding: string;\n padding: string;\n fontSize: string;\n color: string;\n borderRadius: string;\n}\n\nexport interface HtmlBlockProperties {\n content: string;\n padding: string;\n}\n\nexport interface VideoBlockProperties {\n src: string;\n thumbnailUrl: string;\n alt: string;\n padding: string;\n align: 'left' | 'center' | 'right';\n}\n\nexport interface HeadingBlockProperties {\n content: string;\n level: 'h1' | 'h2' | 'h3' | 'h4';\n fontFamily: string;\n fontSize: string;\n color: string;\n lineHeight: string;\n fontWeight: string;\n padding: string;\n align: 'left' | 'center' | 'right' | 'justify';\n textTransform: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n letterSpacing: string;\n}\n\nexport interface CountdownBlockProperties {\n targetDate: string;\n label: string;\n digitBackgroundColor: string;\n digitColor: string;\n labelColor: string;\n fontSize: string;\n padding: string;\n align: 'left' | 'center' | 'right';\n}\n\nexport interface MenuItem {\n text: string;\n href: string;\n}\n\nexport interface MenuBlockProperties {\n items: MenuItem[];\n align: 'left' | 'center' | 'right';\n fontFamily: string;\n fontSize: string;\n color: string;\n padding: string;\n hamburger: boolean;\n iconColor: string;\n}\n\nexport interface HeroBlockProperties {\n heading: string;\n subtext: string;\n buttonText: string;\n buttonHref: string;\n headingColor: string;\n headingFontSize: string;\n subtextColor: string;\n subtextFontSize: string;\n buttonBackgroundColor: string;\n buttonColor: string;\n buttonBorderRadius: string;\n align: 'left' | 'center' | 'right';\n padding: string;\n backgroundImage: string;\n backgroundColor: string;\n}\n\nexport type BlockProperties =\n | TextBlockProperties\n | ButtonBlockProperties\n | ImageBlockProperties\n | DividerBlockProperties\n | SpacerBlockProperties\n | SocialBlockProperties\n | HtmlBlockProperties\n | VideoBlockProperties\n | HeadingBlockProperties\n | CountdownBlockProperties\n | MenuBlockProperties\n | HeroBlockProperties;\n\nexport interface BlockPropertiesMap {\n text: TextBlockProperties;\n button: ButtonBlockProperties;\n image: ImageBlockProperties;\n divider: DividerBlockProperties;\n spacer: SpacerBlockProperties;\n social: SocialBlockProperties;\n html: HtmlBlockProperties;\n video: VideoBlockProperties;\n heading: HeadingBlockProperties;\n countdown: CountdownBlockProperties;\n menu: MenuBlockProperties;\n hero: HeroBlockProperties;\n}\n\nexport interface Block<T extends BlockType = BlockType> {\n id: string;\n type: T;\n properties: Record<string, any>;\n}\n\n/** A Block with type-safe properties, returned by narrowBlock */\nexport interface TypedBlock<T extends BlockType> extends Block<T> {\n properties: BlockPropertiesMap[T];\n}\n\n/** Narrow a Block to a specific type for type-safe property access */\nexport function narrowBlock<T extends BlockType>(block: Block, type: T): block is TypedBlock<T> {\n return block.type === type;\n}\n\n// ---- Layout ----\n\nexport interface Column {\n id: string;\n width: string;\n blocks: Block[];\n}\n\nexport interface SectionProperties {\n backgroundColor: string;\n padding: string;\n borderRadius: string;\n fullWidth: boolean;\n backgroundImage?: string;\n backgroundSize?: string;\n backgroundRepeat?: string;\n}\n\nexport interface Section {\n id: string;\n columns: Column[];\n properties: SectionProperties;\n}\n\n// ---- Template ----\n\nexport interface GlobalStyles {\n backgroundColor: string;\n width: number;\n fontFamily: string;\n}\n\nexport interface HeadMetadata {\n title: string;\n previewText: string;\n headStyles: string[];\n}\n\nexport interface EmailTemplate {\n sections: Section[];\n globalStyles: GlobalStyles;\n headMetadata?: HeadMetadata;\n}\n\n// ---- Variables ----\n\nexport interface Variable {\n key: string;\n icon?: string;\n sample?: string;\n label?: string;\n group?: string;\n}\n\nexport interface VariableChipStyle {\n backgroundColor: string;\n color: string;\n borderColor: string;\n fontSize: string;\n borderRadius: string;\n}\n\n// ---- Persistence ----\n\nexport interface PersistenceAdapter {\n save(key: string, template: EmailTemplate): void | Promise<void>;\n load(key: string): EmailTemplate | null | Promise<EmailTemplate | null>;\n remove(key: string): void | Promise<void>;\n}\n\n// ---- Image Upload ----\n\nexport interface UploadOptions {\n context: string;\n blockId: string;\n signal: AbortSignal;\n}\n\nexport interface UploadResult {\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n}\n\nexport interface BrowseResult {\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n}\n\nexport interface TransformOptions {\n width: number;\n height?: number;\n fit: string;\n format: string;\n quality: number;\n}\n\nexport interface ImageUploadAdapter {\n upload: (file: File, opts?: UploadOptions) => Promise<UploadResult>;\n browse?: () => Promise<BrowseResult | null>;\n delete?: (url: string) => Promise<void>;\n validate?: (file: File) => string | null;\n transform?: (url: string, opts: TransformOptions) => string;\n}\n\n// ---- Editor ----\n\nexport type ActiveTab = 'visual' | 'source' | 'preview';\n\nexport interface SelectionState {\n sectionId: string | null;\n columnId: string | null;\n blockId: string | null;\n}\n\nexport interface EditorState {\n template: EmailTemplate;\n selection: SelectionState;\n activeTab: ActiveTab;\n history: EmailTemplate[];\n historyIndex: number;\n isDirty: boolean;\n blockIndex: Map<string, { sectionId: string; columnId: string }>;\n}\n\n// ---- Editor Actions ----\n\nexport type EditorAction =\n | { type: 'SET_TEMPLATE'; payload: EmailTemplate }\n | { type: 'ADD_SECTION'; payload: { section: Section; index?: number } }\n | { type: 'REMOVE_SECTION'; payload: { sectionId: string } }\n | { type: 'MOVE_SECTION'; payload: { sectionId: string; toIndex: number } }\n | { type: 'UPDATE_SECTION'; payload: { sectionId: string; properties: Partial<SectionProperties> } }\n | { type: 'ADD_BLOCK'; payload: { sectionId: string; columnId: string; block: Block; index?: number } }\n | { type: 'REMOVE_BLOCK'; payload: { sectionId: string; columnId: string; blockId: string } }\n | { type: 'MOVE_BLOCK'; payload: { fromSectionId: string; fromColumnId: string; blockId: string; toSectionId: string; toColumnId: string; toIndex: number } }\n | { type: 'UPDATE_BLOCK'; payload: { blockId: string; properties: Partial<BlockProperties> } }\n | { type: 'SELECT_BLOCK'; payload: { sectionId: string; columnId: string; blockId: string } | null }\n | { type: 'SELECT_SECTION'; payload: { sectionId: string } | null }\n | { type: 'SET_ACTIVE_TAB'; payload: ActiveTab }\n | { type: 'UPDATE_GLOBAL_STYLES'; payload: Partial<GlobalStyles> }\n | { type: 'UPDATE_HEAD_METADATA'; payload: Partial<HeadMetadata> }\n | { type: 'DUPLICATE_BLOCK'; payload: { sectionId: string; columnId: string; blockId: string } }\n | { type: 'DUPLICATE_SECTION'; payload: { sectionId: string } }\n | { type: 'ADD_BLOCK_AND_SELECT'; payload: { sectionId: string; columnId: string; block: Block; index?: number } }\n | { type: 'ADD_SECTION_WITH_BLOCK'; payload: { section: Section; block: Block; index?: number } }\n | { type: 'DESELECT_ALL' }\n | { type: 'UNDO' }\n | { type: 'REDO' }\n | { type: 'PUSH_HISTORY' };\n\n// ---- Props ----\n\nexport interface EmailEditorProps {\n initialTemplate?: EmailTemplate;\n initialMJML?: string;\n variables?: Variable[];\n imageUploadAdapter?: ImageUploadAdapter;\n onChange?: (template: EmailTemplate) => void;\n onSave?: (mjml: string, html: string) => void;\n onReady?: () => void;\n /** Called when custom variables are added or removed by the user. Receives all custom variables. */\n onVariablesChange?: (customVariables: Variable[]) => void;\n /** Custom font family options for the rich text toolbar. Falls back to FONT_OPTIONS constant. */\n fontFamilies?: string[];\n /** Custom font size options for the rich text toolbar (e.g. ['12px', '14px', '16px']). Falls back to DEFAULT_FONT_SIZES constant. */\n fontSizes?: string[];\n /** Custom block definitions for the sidebar palette. Override icons, labels, descriptions, or hide specific blocks. Falls back to BLOCK_DEFINITIONS constant. */\n blockDefinitions?: import('./constants').BlockDefinition[];\n /** Key for auto-persisting the template. Different keys allow multiple editor instances to coexist. */\n persistenceKey?: string;\n /** Custom persistence adapter. Defaults to localStorage when persistenceKey is set. */\n persistenceAdapter?: PersistenceAdapter;\n className?: string;\n style?: React.CSSProperties;\n\n // Event callbacks for host app integration\n /** Called when a block is added to the template */\n onBlockAdd?: (block: Block, sectionId: string, columnId: string) => void;\n /** Called when a block is removed from the template */\n onBlockRemove?: (blockId: string, sectionId: string, columnId: string) => void;\n /** Called when block properties are updated */\n onBlockUpdate?: (blockId: string, properties: Partial<BlockProperties>) => void;\n /** Called when a block is moved to a new position */\n onBlockMove?: (blockId: string, toSectionId: string, toColumnId: string, toIndex: number) => void;\n /** Called when a section is added to the template */\n onSectionAdd?: (section: Section, index?: number) => void;\n /** Called when a section is removed from the template */\n onSectionRemove?: (sectionId: string) => void;\n /** Called when a section is moved to a new position */\n onSectionMove?: (sectionId: string, toIndex: number) => void;\n /** Called when the selection changes */\n onSelectionChange?: (selection: SelectionState) => void;\n /** Called when a template is loaded via SET_TEMPLATE */\n onTemplateLoad?: (template: EmailTemplate) => void;\n /** Called when history state changes (undo/redo) */\n onHistoryChange?: (canUndo: boolean, canRedo: boolean) => void;\n}\n\nexport interface EmailEditorRef {\n getMJML: () => string;\n getHTML: () => Promise<string>;\n getJSON: () => EmailTemplate;\n loadMJML: (source: string) => void;\n loadJSON: (template: EmailTemplate) => void;\n insertBlock: (type: BlockType, sectionIdx?: number) => void;\n getVariables: () => string[];\n undo: () => void;\n redo: () => void;\n reset: () => void;\n exportPDF: () => Promise<void>;\n /** Remove persisted template data for the current persistenceKey. No-op if no key is set. */\n clearPersisted: () => void;\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface HtmlPropertiesProps {\n block: Block;\n}\n\nexport function HtmlProperties({ block }: HtmlPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"textarea\" label=\"HTML Content\" value={p.content} onChange={(v) => update({ content: v })} placeholder=\"<p>Enter raw HTML here...</p>\" rows={10} code />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block, VideoBlockProperties } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface VideoPropertiesProps {\n block: Block;\n}\n\nfunction getAutoThumbnail(url: string): string {\n if (!url) return '';\n const ytMatch = url.match(/(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/);\n if (ytMatch) return `https://img.youtube.com/vi/${ytMatch[1]}/hqdefault.jpg`;\n return '';\n}\n\nexport function VideoProperties({ block }: VideoPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n const handleVideoUrlChange = useCallback(\n (src: string) => {\n const updates: Partial<VideoBlockProperties> = { src };\n if (!p.thumbnailUrl) {\n const auto = getAutoThumbnail(src);\n if (auto) updates.thumbnailUrl = auto;\n }\n update(updates);\n },\n [update, p.thumbnailUrl],\n );\n\n const handleAutoThumbnail = useCallback(() => {\n const auto = getAutoThumbnail(p.src);\n if (auto) update({ thumbnailUrl: auto });\n }, [update, p.src]);\n\n return (\n <div className={styles.propertiesBody}>\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Video URL</label>\n <input\n className={styles.fieldInput}\n value={p.src}\n onChange={(e) => handleVideoUrlChange(e.target.value)}\n placeholder=\"https://youtube.com/watch?v=...\"\n />\n </div>\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Thumbnail URL</label>\n <input\n className={styles.fieldInput}\n value={p.thumbnailUrl}\n onChange={(e) => update({ thumbnailUrl: e.target.value })}\n placeholder=\"https://...\"\n />\n {p.src && (\n <button\n className={`ee-auto-thumbnail ${styles.fieldBtnUpload} ${styles.fieldInputStacked}`}\n onClick={handleAutoThumbnail}\n >\n Auto-generate from URL\n </button>\n )}\n </div>\n <PropertyField type=\"text\" label=\"Alt Text\" value={p.alt} onChange={(v) => update({ alt: v })} placeholder=\"Video description\" />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst LEVEL_OPTIONS = [\n { value: 'h1', label: 'H1' }, { value: 'h2', label: 'H2' },\n { value: 'h3', label: 'H3' }, { value: 'h4', label: 'H4' },\n];\n\nconst FONT_WEIGHT_OPTIONS = [\n { value: 'normal', label: 'Normal' }, { value: 'bold', label: 'Bold' },\n { value: '100', label: '100' }, { value: '200', label: '200' },\n { value: '300', label: '300' }, { value: '400', label: '400' },\n { value: '500', label: '500' }, { value: '600', label: '600' },\n { value: '700', label: '700' }, { value: '800', label: '800' },\n { value: '900', label: '900' },\n];\n\nconst TEXT_TRANSFORM_OPTIONS = [\n { value: 'none', label: 'None' }, { value: 'uppercase', label: 'Uppercase' },\n { value: 'lowercase', label: 'Lowercase' }, { value: 'capitalize', label: 'Capitalize' },\n];\n\nconst LEVEL_DEFAULTS: Record<string, { fontSize: string; lineHeight: string }> = {\n h1: { fontSize: '36px', lineHeight: '1.2' },\n h2: { fontSize: '28px', lineHeight: '1.3' },\n h3: { fontSize: '22px', lineHeight: '1.3' },\n h4: { fontSize: '18px', lineHeight: '1.4' },\n};\n\ninterface HeadingPropertiesProps {\n block: Block;\n}\n\nexport function HeadingProperties({ block }: HeadingPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n const handleLevelChange = useCallback(\n (level: string) => {\n const defaults = LEVEL_DEFAULTS[level] || LEVEL_DEFAULTS.h2;\n update({ level: level, fontSize: defaults.fontSize, lineHeight: defaults.lineHeight });\n },\n [update],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"select\" label=\"Heading Level\" value={p.level} onChange={handleLevelChange} options={LEVEL_OPTIONS} />\n <FieldSeparator />\n <PropertyField type=\"font\" label=\"Font Family\" value={p.fontFamily} onChange={(v) => update({ fontFamily: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"color\" label=\"Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"text\" label=\"Line Height\" value={p.lineHeight} onChange={(v) => update({ lineHeight: v })} />\n <PropertyField type=\"select\" label=\"Font Weight\" value={p.fontWeight || 'bold'} onChange={(v) => update({ fontWeight: v })} options={FONT_WEIGHT_OPTIONS} />\n <PropertyField type=\"select\" label=\"Text Transform\" value={p.textTransform || 'none'} onChange={(v) => update({ textTransform: v })} options={TEXT_TRANSFORM_OPTIONS} />\n <PropertyField type=\"text\" label=\"Letter Spacing\" value={p.letterSpacing || 'normal'} onChange={(v) => update({ letterSpacing: v })} placeholder=\"normal\" />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface CountdownPropertiesProps {\n block: Block;\n}\n\nexport function CountdownProperties({ block }: CountdownPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n if (!narrowBlock(block, 'countdown')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Target Date</label>\n <input\n className={styles.fieldInput}\n type=\"datetime-local\"\n value={p.targetDate}\n onChange={(e) => update({ targetDate: e.target.value })}\n />\n </div>\n <PropertyField type=\"text\" label=\"Label\" value={p.label} onChange={(v) => update({ label: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Digit Background\" value={p.digitBackgroundColor} onChange={(v) => update({ digitBackgroundColor: v })} />\n <PropertyField type=\"color\" label=\"Digit Color\" value={p.digitColor} onChange={(v) => update({ digitColor: v })} />\n <PropertyField type=\"color\" label=\"Label Color\" value={p.labelColor} onChange={(v) => update({ labelColor: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block, MenuItem } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\nimport blockStyles from '../../styles/blocks.module.css';\n\nconst HAMBURGER_OPTIONS = [\n { value: 'false', label: 'Off' }, { value: 'true', label: 'On' },\n];\n\ninterface MenuPropertiesProps {\n block: Block;\n}\n\nexport function MenuProperties({ block }: MenuPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n const updateItem = useCallback(\n (index: number, changes: Partial<MenuItem>) => {\n const items = [...block.properties.items];\n items[index] = { ...items[index], ...changes };\n update({ items });\n },\n [block.properties.items, update],\n );\n\n const addItem = useCallback(() => {\n const items = [...block.properties.items, { text: 'Link', href: '#' }];\n update({ items });\n }, [block.properties.items, update]);\n\n const removeItem = useCallback(\n (index: number) => {\n const items = block.properties.items.filter((_: any, i: number) => i !== index);\n update({ items });\n },\n [block.properties.items, update],\n );\n\n const moveItem = useCallback(\n (index: number, direction: -1 | 1) => {\n const items = [...block.properties.items];\n const newIndex = index + direction;\n if (newIndex < 0 || newIndex >= items.length) return;\n [items[index], items[newIndex]] = [items[newIndex], items[index]];\n update({ items });\n },\n [block.properties.items, update],\n );\n\n if (!narrowBlock(block, 'menu')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"font\" label=\"Font Family\" value={p.fontFamily} onChange={(v) => update({ fontFamily: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"color\" label=\"Text Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"select\" label=\"Hamburger Mode\" value={p.hamburger ? 'true' : 'false'} onChange={(v) => update({ hamburger: v === 'true' })} options={HAMBURGER_OPTIONS} />\n {p.hamburger && (\n <PropertyField type=\"color\" label=\"Icon Color\" value={p.iconColor} onChange={(v) => update({ iconColor: v })} />\n )}\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <FieldSeparator />\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Menu Items</label>\n <div className={blockStyles.menuItemsContainer}>\n {p.items.map((item: MenuItem, index: number) => (\n <div key={index} className={blockStyles.menuItemEntry}>\n <div className={styles.fieldRow}>\n <input\n className={styles.fieldInputFlex}\n value={item.text}\n onChange={(e) => updateItem(index, { text: e.target.value })}\n placeholder=\"Label\"\n />\n <button className={`ee-item-move-up ${styles.itemActionBtn}`} onClick={() => moveItem(index, -1)} disabled={index === 0} title=\"Move up\">↑</button>\n <button className={`ee-item-move-down ${styles.itemActionBtn}`} onClick={() => moveItem(index, 1)} disabled={index === p.items.length - 1} title=\"Move down\">↓</button>\n <button className={`ee-item-remove ${styles.itemActionBtnDanger}`} onClick={() => removeItem(index)} title=\"Remove\">×</button>\n </div>\n <input\n className={styles.fieldInputStacked}\n value={item.href}\n onChange={(e) => updateItem(index, { href: e.target.value })}\n placeholder=\"URL\"\n />\n </div>\n ))}\n </div>\n <button className={`ee-add-item ${styles.addItemBtn}`} onClick={addItem}>+ Add Item</button>\n </div>\n </div>\n );\n}\n","import React, { useCallback, useRef } from 'react';\nimport { useImageUpload } from './useImageUpload';\nimport { useImageAdapter } from '../../context/EditorContext';\nimport styles from '../../styles/blocks.module.css';\n\ninterface ImageUploaderProps {\n blockId: string;\n onUploadComplete: (url: string, alt?: string) => void;\n}\n\nexport function ImageUploader({ blockId, onUploadComplete }: ImageUploaderProps) {\n const { imageUploadAdapter } = useImageAdapter();\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const { status, progress, error, upload, cancel } = useImageUpload({\n adapter: imageUploadAdapter,\n blockId,\n onSuccess: (result) => {\n onUploadComplete(result.url, result.alt);\n },\n });\n\n const handleFileChange = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n await upload(file);\n }\n },\n [upload],\n );\n\n const handleClick = useCallback(() => {\n fileInputRef.current?.click();\n }, []);\n\n return (\n <div>\n {status === 'uploading' ? (\n <div className={`ee-image-uploading ${styles.imageUploading}`}>\n <div className={`ee-image-placeholder ${styles.imagePlaceholder}`}>\n <span>Uploading... {Math.round(progress)}%</span>\n <button className=\"ee-upload-cancel\" onClick={cancel}>\n Cancel\n </button>\n </div>\n <div className={`ee-image-progress ${styles.imageProgress}`} style={{ width: `${progress}%` }} />\n </div>\n ) : (\n <div className={`ee-image-placeholder ${styles.imagePlaceholder}`} onClick={handleClick}>\n <span className={`ee-image-placeholder-icon ${styles.imagePlaceholderIcon}`}>+</span>\n <span>Click to upload image</span>\n </div>\n )}\n {error && <div className={`ee-image-error ${styles.imageError}`}>{error}</div>}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { ImageUploader } from '../ImageUpload/ImageUploader';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface HeroPropertiesProps {\n block: Block;\n}\n\nexport function HeroProperties({ block }: HeroPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n if (!narrowBlock(block, 'hero')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Heading\" value={p.heading} onChange={(v) => update({ heading: v })} />\n <PropertyField type=\"textarea\" label=\"Subtext\" value={p.subtext} onChange={(v) => update({ subtext: v })} rows={3} />\n <FieldSeparator />\n <PropertyField type=\"text\" label=\"Button Text\" value={p.buttonText} onChange={(v) => update({ buttonText: v })} />\n <PropertyField type=\"link\" label=\"Button Link\" value={p.buttonHref} onChange={(v) => update({ buttonHref: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Heading Color\" value={p.headingColor} onChange={(v) => update({ headingColor: v })} />\n <PropertyField type=\"text\" label=\"Heading Font Size\" value={p.headingFontSize} onChange={(v) => update({ headingFontSize: v })} />\n <PropertyField type=\"color\" label=\"Subtext Color\" value={p.subtextColor} onChange={(v) => update({ subtextColor: v })} />\n <PropertyField type=\"text\" label=\"Subtext Font Size\" value={p.subtextFontSize} onChange={(v) => update({ subtextFontSize: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Button Background\" value={p.buttonBackgroundColor} onChange={(v) => update({ buttonBackgroundColor: v })} />\n <PropertyField type=\"color\" label=\"Button Text Color\" value={p.buttonColor} onChange={(v) => update({ buttonColor: v })} />\n <PropertyField type=\"text\" label=\"Button Border Radius\" value={p.buttonBorderRadius} onChange={(v) => update({ buttonBorderRadius: v })} />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Background Color\" value={p.backgroundColor} onChange={(v) => update({ backgroundColor: v })} />\n <PropertyField type=\"text\" label=\"Background Image URL\" value={p.backgroundImage} onChange={(v) => update({ backgroundImage: v })} placeholder=\"https://example.com/image.jpg\" />\n {!p.backgroundImage && (\n <ImageUploader\n blockId={block.id}\n onUploadComplete={(url) => update({ backgroundImage: url })}\n />\n )}\n {p.backgroundImage && (\n <div className={styles.fieldGroup}>\n <button\n className={`ee-remove-bg ${styles.fieldBtnUpload}`}\n onClick={() => update({ backgroundImage: '' })}\n >\n Remove Background Image\n </button>\n </div>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { Block, BlockType } from '../../types';\nimport { useSelectedBlock, useSelectedSection } from '../../context/EditorContext';\nimport { blockPropertiesRegistry } from '../../registry';\nimport { SectionProperties } from './SectionProperties';\nimport { HeadMetadataProperties } from './HeadMetadataProperties';\nimport { TextProperties } from './TextProperties';\nimport { ButtonProperties } from './ButtonProperties';\nimport { ImageProperties } from './ImageProperties';\nimport { DividerProperties } from './DividerProperties';\nimport { SpacerProperties } from './SpacerProperties';\nimport { SocialProperties } from './SocialProperties';\nimport { HtmlProperties } from './HtmlProperties';\nimport { VideoProperties } from './VideoProperties';\nimport { HeadingProperties } from './HeadingProperties';\nimport { CountdownProperties } from './CountdownProperties';\nimport { MenuProperties } from './MenuProperties';\nimport { HeroProperties } from './HeroProperties';\nimport styles from '../../styles/properties.module.css';\n\ntype BlockPanelComponent = React.ComponentType<{ block: Block }>;\n\n/** Static lookup for built-in block property panels — no module-level side effects */\nconst BUILT_IN_PANELS: Record<string, BlockPanelComponent> = {\n text: TextProperties as BlockPanelComponent,\n button: ButtonProperties as BlockPanelComponent,\n image: ImageProperties as BlockPanelComponent,\n divider: DividerProperties as BlockPanelComponent,\n spacer: SpacerProperties as BlockPanelComponent,\n social: SocialProperties as BlockPanelComponent,\n html: HtmlProperties as BlockPanelComponent,\n video: VideoProperties as BlockPanelComponent,\n heading: HeadingProperties as BlockPanelComponent,\n countdown: CountdownProperties as BlockPanelComponent,\n menu: MenuProperties as BlockPanelComponent,\n hero: HeroProperties as BlockPanelComponent,\n};\n\nfunction getBlockPanel(type: string): BlockPanelComponent | undefined {\n // Custom-registered panels take precedence over built-in ones\n return blockPropertiesRegistry[type] ?? BUILT_IN_PANELS[type];\n}\n\nexport function PropertiesPanel() {\n const selectedBlock = useSelectedBlock();\n const selectedSection = useSelectedSection();\n\n if (selectedBlock) {\n const title = selectedBlock.type.charAt(0).toUpperCase() + selectedBlock.type.slice(1);\n const Component = getBlockPanel(selectedBlock.type);\n return (\n <div className={`ee-properties-panel ${styles.propertiesPanel}`}>\n <div className={`ee-properties-header ${styles.propertiesHeader}`}>{title} Properties</div>\n {Component ? <Component block={selectedBlock} /> : null}\n </div>\n );\n }\n\n if (selectedSection) {\n return (\n <div className={`ee-properties-panel ${styles.propertiesPanel}`}>\n <div className={`ee-properties-header ${styles.propertiesHeader}`}>Section Properties</div>\n <SectionProperties section={selectedSection} />\n </div>\n );\n }\n\n return (\n <div className={`ee-properties-panel ${styles.propertiesPanel}`}>\n <div className={`ee-properties-header ${styles.propertiesHeader}`}>Email Settings</div>\n <HeadMetadataProperties />\n </div>\n );\n}\n","import { useEffect, useState, useRef } from 'react';\nimport { useTemplateContext } from '../../context/EditorContext';\nimport { generateMJML } from '../../mjml/generator';\nimport { compileMJMLToHTML } from '../../mjml/compiler';\nimport styles from '../../styles/preview.module.css';\n\ntype PreviewMode = 'desktop' | 'mobile';\n\nconst PREVIEW_WIDTHS: Record<PreviewMode, number> = {\n desktop: 600,\n mobile: 375,\n};\n\nexport function PreviewPanel() {\n const { template } = useTemplateContext();\n const [html, setHtml] = useState('');\n const [previewMode, setPreviewMode] = useState<PreviewMode>('desktop');\n const iframeRef = useRef<HTMLIFrameElement>(null);\n\n // Debounce preview compilation to avoid excessive recompilations during rapid edits\n useEffect(() => {\n let cancelled = false;\n const timer = setTimeout(() => {\n async function compile() {\n const mjml = generateMJML(template);\n const result = await compileMJMLToHTML(mjml);\n if (!cancelled) {\n setHtml(result.html);\n }\n }\n compile();\n }, 300);\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [template]);\n\n useEffect(() => {\n if (iframeRef.current && html) {\n const doc = iframeRef.current.contentDocument;\n if (doc) {\n doc.open();\n doc.write(html);\n doc.close();\n }\n }\n }, [html]);\n\n return (\n <div className={`ee-preview ${styles.preview}`}>\n <div className={`ee-preview-toggles ${styles.previewToggles}`} role=\"group\" aria-label=\"Preview size\">\n <button\n className={`ee-preview-toggle ee-preview-toggle--desktop ${styles.previewToggle} ${styles.previewToggleDesktop} ${previewMode === 'desktop' ? `ee-preview-toggle--active ${styles.previewToggleActive}` : ''}`}\n onClick={() => setPreviewMode('desktop')}\n aria-pressed={previewMode === 'desktop'}\n aria-label=\"Desktop preview\"\n >\n Desktop\n </button>\n <button\n className={`ee-preview-toggle ee-preview-toggle--mobile ${styles.previewToggle} ${styles.previewToggleMobile} ${previewMode === 'mobile' ? `ee-preview-toggle--active ${styles.previewToggleActive}` : ''}`}\n onClick={() => setPreviewMode('mobile')}\n aria-pressed={previewMode === 'mobile'}\n aria-label=\"Mobile preview\"\n >\n Mobile\n </button>\n </div>\n <div className={`ee-preview-container ${styles.previewContainer}`}>\n <iframe\n className={`ee-preview-iframe ${styles.previewIframe}`}\n ref={iframeRef}\n title=\"Email Preview\"\n style={{ width: PREVIEW_WIDTHS[previewMode] }}\n sandbox=\"allow-same-origin\"\n />\n </div>\n </div>\n );\n}\n",".preview {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n}\n\n.previewToggles {\n display: flex;\n justify-content: center;\n gap: 0;\n padding: 12px 24px 0;\n}\n\n.previewToggle {\n padding: 6px 16px;\n border: 1px solid var(--ee-border-color);\n background: var(--ee-bg-panel);\n cursor: pointer;\n font-size: var(--ee-font-size-md);\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.previewToggleActive {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.previewToggleDesktop {\n border-radius: var(--ee-border-radius-sm) 0 0 var(--ee-border-radius-sm);\n}\n\n.previewToggleMobile {\n border-radius: 0 var(--ee-border-radius-sm) var(--ee-border-radius-sm) 0;\n border-left: none;\n}\n\n.previewContainer {\n flex: 1;\n display: flex;\n justify-content: center;\n padding: 24px;\n box-sizing: border-box;\n}\n\n.previewIframe {\n height: 100%;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n background: var(--ee-bg-panel);\n transition: width var(--ee-transition-normal);\n}\n","import React, { useState, useCallback, useEffect } from 'react';\nimport { useTemplateContext, useEditorDispatch } from '../../context/EditorContext';\nimport { generateMJML } from '../../mjml/generator';\nimport { parseMJML } from '../../mjml/parser';\nimport styles from '../../styles/source-editor.module.css';\n\nexport function SourceEditor() {\n const { template } = useTemplateContext();\n const dispatch = useEditorDispatch();\n const [source, setSource] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n setSource(generateMJML(template));\n }, [template]);\n\n const handleApply = useCallback(() => {\n try {\n const template = parseMJML(source);\n dispatch({ type: 'SET_TEMPLATE', payload: template });\n setError(null);\n } catch (err) {\n setError((err as Error).message);\n }\n }, [source, dispatch]);\n\n return (\n <div className={`ee-source-editor ${styles.sourceEditor}`}>\n <div className={`ee-source-header ${styles.sourceHeader}`}>\n <span className={`ee-source-label ${styles.sourceLabel}`}>\n MJML Source\n </span>\n <button\n className={`ee-source-apply ${styles.sourceApply}`}\n onClick={handleApply}\n >\n Apply Changes\n </button>\n </div>\n {error && (\n <div className={`ee-source-error ${styles.sourceError}`}>\n {error}\n </div>\n )}\n <textarea\n className={`ee-source-textarea ${styles.sourceTextarea}`}\n value={source}\n onChange={(e) => setSource(e.target.value)}\n spellCheck={false}\n />\n </div>\n );\n}\n",".sourceEditor {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: var(--ee-space-lg);\n gap: var(--ee-space-sm);\n box-sizing: border-box;\n}\n\n.sourceHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.sourceLabel {\n font-size: var(--ee-font-size-md);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-secondary);\n}\n\n.sourceApply {\n padding: 6px 16px;\n font-size: var(--ee-font-size-md);\n font-weight: var(--ee-font-weight-medium);\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n}\n\n.sourceError {\n padding: var(--ee-space-sm);\n font-size: var(--ee-font-size-sm);\n color: var(--ee-color-danger);\n background: var(--ee-color-danger-light);\n border-radius: var(--ee-border-radius-sm);\n}\n\n.sourceTextarea {\n flex: 1;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: var(--ee-font-size-md);\n line-height: 1.5;\n padding: var(--ee-space-md);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n resize: none;\n outline: none;\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n tab-size: 2;\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","properties","import_jsx_runtime","React","Toolbar","template","import_react","import_react","import_jsx_runtime","React","BlockPalette","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_react","import_react","import_react","import_react","import_extension_text_style","import_core","import_core","import_extension_text_style","StarterKit","Underline","TextAlign","TextStyle","Color","Highlight","Link","Placeholder","ALLOWED_TAGS","import_jsx_runtime","useTipTapEditor","import_react","import_jsx_runtime","React","RichTextToolbar","import_jsx_runtime","TextBlock","React","import_react","import_jsx_runtime","React","ButtonBlock","import_react","import_react","import_jsx_runtime","ImageBlock","React","import_react","import_jsx_runtime","React","DividerBlock","import_react","import_jsx_runtime","React","SpacerBlock","import_react","import_jsx_runtime","React","SocialBlock","import_react","import_jsx_runtime","React","HtmlBlock","DOMPurify","import_react","import_jsx_runtime","React","VideoBlock","getAutoThumbnail","import_react","import_jsx_runtime","HeadingBlock","React","import_react","import_jsx_runtime","React","CountdownBlock","import_react","import_jsx_runtime","React","MenuBlock","import_react","import_jsx_runtime","React","HeroBlock","import_jsx_runtime","TextBlock","ImageBlock","HeadingBlock","React","BlockRenderer","Component","import_react","import_jsx_runtime","React","DropZone","import_jsx_runtime","React","Column","import_jsx_runtime","React","Section","import_react","import_jsx_runtime","React","SectionDropZone","import_jsx_runtime","React","Canvas","import_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","React","PropertyField","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","getAutoThumbnail","import_react","import_jsx_runtime","FONT_WEIGHT_OPTIONS","TEXT_TRANSFORM_OPTIONS","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Component","import_react","import_jsx_runtime","import_react","import_jsx_runtime","template","import_jsx_runtime","EditorInner","EmailEditor"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/EmailEditor.tsx","../src/context/EditorContext.tsx","../src/constants.ts","../src/registry.ts","../src/utils/validate.ts","../src/utils/persistence.ts","../src/hooks/useVariables.ts","../src/hooks/useTipTapTracking.ts","../src/hooks/usePersistence.ts","../src/context/DispatchContext.tsx","../src/context/TemplateContext.tsx","../src/context/SelectionContext.tsx","../src/context/ConfigContext.tsx","../src/context/MethodsContext.tsx","../src/context/HistoryContext.tsx","../src/context/BlockIndexContext.tsx","../src/utils/id.ts","../src/utils/factory.ts","../src/utils/blockIndex.ts","../src/context/editorReducer.ts","../src/context/editorHooks.ts","../src/components/ErrorBoundary.tsx","../src/styles/error-boundary.module.css","../src/components/ConfirmDialog.tsx","../src/styles/confirm-dialog.module.css","../src/components/Toolbar/Toolbar.tsx","../src/utils/sanitize.ts","../src/mjml/generator.ts","../src/mjml/compiler.ts","../src/mjml/parser.ts","../src/styles/toolbar.module.css","../src/styles/editor.module.css","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/BlockPalette.tsx","../src/utils/dnd.ts","../src/styles/sidebar.module.css","../src/components/Sidebar/VariableList.tsx","../src/utils/variables.ts","../src/components/Sidebar/AddVariableForm.tsx","../src/components/Canvas/Canvas.tsx","../src/components/Canvas/Section.tsx","../src/components/Canvas/Column.tsx","../src/components/Canvas/BlockRenderer.tsx","../src/components/Canvas/blocks/TextBlock.tsx","../src/tiptap/TipTapEditor.tsx","../src/tiptap/extensions.ts","../src/tiptap/VariableNode.ts","../src/tiptap/FontSize.ts","../src/tiptap/FontFamily.ts","../src/tiptap/pasteClean.ts","../src/components/Toolbar/RichTextToolbar.tsx","../src/styles/blocks.module.css","../src/styles/tiptap.module.css","../src/components/Canvas/blocks/ButtonBlock.tsx","../src/components/Canvas/blocks/ImageBlock.tsx","../src/components/ImageUpload/useImageUpload.ts","../src/components/Canvas/blocks/DividerBlock.tsx","../src/components/Canvas/blocks/SpacerBlock.tsx","../src/components/Canvas/blocks/SocialBlock.tsx","../src/components/Canvas/blocks/HtmlBlock.tsx","../src/components/Canvas/blocks/VideoBlock.tsx","../src/components/Canvas/blocks/HeadingBlock.tsx","../src/components/Canvas/blocks/CountdownBlock.tsx","../src/components/Canvas/blocks/MenuBlock.tsx","../src/components/Canvas/blocks/HeroBlock.tsx","../src/components/Canvas/DropZone.tsx","../src/styles/canvas.module.css","../src/components/Canvas/SectionDropZone.tsx","../src/components/Properties/SectionProperties.tsx","../src/components/Properties/PropertyField.tsx","../src/components/Properties/controls/ColorPicker.tsx","../src/styles/properties.module.css","../src/components/Properties/controls/PaddingInput.tsx","../src/components/Properties/controls/AlignmentPicker.tsx","../src/components/Properties/controls/FontPicker.tsx","../src/components/Properties/controls/SliderInput.tsx","../src/components/Properties/controls/LinkInput.tsx","../src/components/Properties/HeadMetadataProperties.tsx","../src/hooks/useBlockUpdate.ts","../src/components/Properties/TextProperties.tsx","../src/components/Properties/ButtonProperties.tsx","../src/components/Properties/ImageProperties.tsx","../src/components/Properties/DividerProperties.tsx","../src/components/Properties/SpacerProperties.tsx","../src/components/Properties/SocialProperties.tsx","../src/types.ts","../src/components/Properties/HtmlProperties.tsx","../src/components/Properties/VideoProperties.tsx","../src/components/Properties/HeadingProperties.tsx","../src/components/Properties/CountdownProperties.tsx","../src/components/Properties/MenuProperties.tsx","../src/components/ImageUpload/ImageUploader.tsx","../src/components/Properties/HeroProperties.tsx","../src/components/Properties/PropertiesPanel.tsx","../src/components/Preview/PreviewPanel.tsx","../src/styles/preview.module.css","../src/components/SourceEditor/SourceEditor.tsx","../src/styles/source-editor.module.css"],"sourcesContent":["// Main component\nexport { EmailEditor } from './components/EmailEditor';\n\n// Context & hooks\nexport {\n EditorProvider,\n useEditorState,\n useEditorDispatch,\n useSelectedBlock,\n useSelectedSection,\n useEditorVariables,\n useEditorFonts,\n useImageAdapter,\n useTemplateContext,\n useSelectionContext,\n useDispatchContext,\n useConfigContext,\n useMethodsContext,\n useHistoryContext,\n useBlockIndexContext,\n} from './context/EditorContext';\n\n// Type guard\nexport { narrowBlock } from './types';\n\n// Types\nexport type {\n BlockType,\n Block,\n TypedBlock,\n Column,\n Section,\n SectionProperties,\n EmailTemplate,\n GlobalStyles,\n Variable,\n ImageUploadAdapter,\n UploadOptions,\n UploadResult,\n BrowseResult,\n TransformOptions,\n EmailEditorProps,\n EmailEditorRef,\n ActiveTab,\n SelectionState,\n EditorState,\n EditorAction,\n TextBlockProperties,\n ButtonBlockProperties,\n ImageBlockProperties,\n DividerBlockProperties,\n SpacerBlockProperties,\n BlockProperties,\n BlockPropertiesMap,\n VariableChipStyle,\n HeadMetadata,\n SocialElement,\n SocialBlockProperties,\n CountdownBlockProperties,\n MenuItem,\n MenuBlockProperties,\n HeroBlockProperties,\n HtmlBlockProperties,\n VideoBlockProperties,\n HeadingBlockProperties,\n PersistenceAdapter,\n} from './types';\n\n// MJML utilities\nexport { parseMJML } from './mjml/parser';\nexport { generateMJML } from './mjml/generator';\nexport { compileMJMLToHTML } from './mjml/compiler';\n\n// TipTap extensions (for custom configurations)\nexport { getExtensions } from './tiptap/extensions';\nexport { VariableNode } from './tiptap/VariableNode';\n\n// Utilities\nexport { generateId, generateBlockId, generateSectionId, generateColumnId } from './utils/id';\nexport { extractVariableKeys, replaceVariables, groupVariables } from './utils/variables';\nexport { sanitizeHTML, escapeHTML, isSafeURL } from './utils/sanitize';\nexport { validateTemplate, sanitizeTemplate } from './utils/validate';\nexport type { ValidationResult } from './utils/validate';\nexport { localStorageAdapter } from './utils/persistence';\n\n// Block type registries (for extending with custom block types)\nexport {\n registerBlockRenderer,\n registerBlockProperties,\n registerBlockGenerator,\n registerBlockParser,\n getRegisteredBlockTypes,\n} from './registry';\n\n// Constants\nexport {\n DEFAULT_BLOCK_PROPERTIES,\n DEFAULT_SECTION_PROPERTIES,\n DEFAULT_GLOBAL_STYLES,\n DEFAULT_HEAD_METADATA,\n DEFAULT_SOCIAL_PROPERTIES,\n DEFAULT_VARIABLE_CHIP_STYLE,\n DEFAULT_FONT_SIZES,\n BLOCK_DEFINITIONS,\n FONT_OPTIONS,\n COLOR_PRESETS,\n COLUMN_LAYOUTS,\n} from './constants';\n\nexport type { BlockDefinition } from './constants';\n","import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport type { EmailEditorProps, EmailEditorRef, BlockType } from '../types';\nimport { EditorProvider, useEditorDispatch, useTemplateContext, useSelectionContext, useConfigContext } from '../context/EditorContext';\nimport { ErrorBoundary } from './ErrorBoundary';\nimport { ConfirmDialog } from './ConfirmDialog';\nimport { Toolbar } from './Toolbar/Toolbar';\nimport { Sidebar } from './Sidebar/Sidebar';\nimport { Canvas } from './Canvas/Canvas';\nimport { PropertiesPanel } from './Properties/PropertiesPanel';\nimport { PreviewPanel } from './Preview/PreviewPanel';\nimport { SourceEditor } from './SourceEditor/SourceEditor';\nimport { generateMJML } from '../mjml/generator';\nimport { compileMJMLToHTML } from '../mjml/compiler';\nimport { parseMJML } from '../mjml/parser';\nimport { createSection, createBlock } from '../utils/factory';\nimport { DEFAULT_GLOBAL_STYLES, DEFAULT_HEAD_METADATA } from '../constants';\nimport { extractVariableKeys } from '../utils/variables';\nimport editorStyles from '../styles/editor.module.css';\nimport '../styles/variables.css';\n\nconst EditorInner = forwardRef<EmailEditorRef, EmailEditorProps>(function EditorInner(\n props,\n ref,\n) {\n const dispatch = useEditorDispatch();\n const { template, activeTab } = useTemplateContext();\n const selection = useSelectionContext();\n const { clearPersisted } = useConfigContext();\n const containerRef = useRef<HTMLDivElement>(null);\n const { onReady, onSave } = props;\n\n // Panel toggle state for responsive layout\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [propertiesOpen, setPropertiesOpen] = useState(false);\n\n // Confirm dialog state for keyboard-triggered removal\n const [pendingRemoval, setPendingRemoval] = useState<\n | { type: 'block'; sectionId: string; columnId: string; blockId: string }\n | { type: 'section'; sectionId: string }\n | null\n >(null);\n\n const toggleSidebar = useCallback(() => {\n setSidebarOpen((prev) => !prev);\n setPropertiesOpen(false);\n }, []);\n\n const toggleProperties = useCallback(() => {\n setPropertiesOpen((prev) => !prev);\n setSidebarOpen(false);\n }, []);\n\n const closeOverlays = useCallback(() => {\n setSidebarOpen(false);\n setPropertiesOpen(false);\n }, []);\n\n // Auto-open properties panel when a block is selected (on narrow screens)\n useEffect(() => {\n if (selection.blockId) {\n // Only auto-open if window is narrow (overlay mode)\n if (typeof window !== 'undefined' && window.innerWidth < 1024) {\n setPropertiesOpen(true);\n setSidebarOpen(false);\n }\n }\n }, [selection.blockId]);\n\n // Feature 3: onReady — fire once on mount\n useEffect(() => {\n onReady?.();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Use refs for keyboard handler to avoid re-registering on every state change\n const templateRef = useRef(template);\n templateRef.current = template;\n const selectionRef = useRef(selection);\n selectionRef.current = selection;\n const onSaveRef = useRef(onSave);\n onSaveRef.current = onSave;\n\n // Feature 5: Keyboard shortcuts\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handler = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n const isEditing =\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable;\n\n const mod = e.metaKey || e.ctrlKey;\n\n // Ctrl/Cmd+S → save\n if (mod && e.key === 's') {\n e.preventDefault();\n if (onSaveRef.current) {\n const mjml = generateMJML(templateRef.current);\n compileMJMLToHTML(mjml).then((result) => onSaveRef.current!(mjml, result.html));\n }\n return;\n }\n\n // Escape → deselect all\n if (e.key === 'Escape') {\n dispatch({ type: 'SELECT_BLOCK', payload: null });\n (document.activeElement as HTMLElement)?.blur();\n return;\n }\n\n // Skip remaining shortcuts while typing in inputs\n if (isEditing) return;\n\n // Ctrl/Cmd+Z → undo\n if (mod && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n dispatch({ type: 'UNDO' });\n return;\n }\n\n // Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y → redo\n if (mod && ((e.key === 'z' && e.shiftKey) || e.key === 'y')) {\n e.preventDefault();\n dispatch({ type: 'REDO' });\n return;\n }\n\n // Delete/Backspace → confirm then remove selected block or section\n if (e.key === 'Delete' || e.key === 'Backspace') {\n const { sectionId, columnId, blockId } = selectionRef.current;\n if (blockId && sectionId && columnId) {\n e.preventDefault();\n setPendingRemoval({ type: 'block', sectionId, columnId, blockId });\n } else if (sectionId) {\n e.preventDefault();\n setPendingRemoval({ type: 'section', sectionId });\n }\n }\n };\n\n el.addEventListener('keydown', handler);\n return () => el.removeEventListener('keydown', handler);\n }, [dispatch]);\n\n const handleConfirmRemoval = useCallback(() => {\n if (!pendingRemoval) return;\n if (pendingRemoval.type === 'block') {\n dispatch({ type: 'REMOVE_BLOCK', payload: pendingRemoval });\n } else {\n dispatch({ type: 'REMOVE_SECTION', payload: { sectionId: pendingRemoval.sectionId } });\n }\n setPendingRemoval(null);\n }, [dispatch, pendingRemoval]);\n\n useImperativeHandle(ref, () => ({\n getMJML: () => generateMJML(templateRef.current),\n\n getHTML: async () => {\n const mjml = generateMJML(templateRef.current);\n const result = await compileMJMLToHTML(mjml);\n return result.html;\n },\n\n getJSON: () => JSON.parse(JSON.stringify(templateRef.current)),\n\n loadMJML: (source: string) => {\n const parsed = parseMJML(source);\n dispatch({ type: 'SET_TEMPLATE', payload: parsed });\n },\n\n loadJSON: (t) => {\n dispatch({ type: 'SET_TEMPLATE', payload: t });\n },\n\n insertBlock: (type: BlockType, sectionIdx?: number) => {\n const currentTemplate = templateRef.current;\n const targetSection = currentTemplate.sections[sectionIdx ?? currentTemplate.sections.length - 1];\n const block = createBlock(type);\n\n if (!targetSection) {\n // Use combined action to avoid stale-data race condition\n const newSection = createSection();\n dispatch({ type: 'ADD_SECTION_WITH_BLOCK', payload: { section: newSection, block } });\n } else {\n const column = targetSection.columns[0];\n dispatch({\n type: 'ADD_BLOCK',\n payload: { sectionId: targetSection.id, columnId: column.id, block },\n });\n }\n },\n\n getVariables: () => {\n const mjml = generateMJML(templateRef.current);\n return extractVariableKeys(mjml);\n },\n\n undo: () => dispatch({ type: 'UNDO' }),\n redo: () => dispatch({ type: 'REDO' }),\n\n reset: () => {\n dispatch({\n type: 'SET_TEMPLATE',\n payload: { sections: [], globalStyles: { ...DEFAULT_GLOBAL_STYLES }, headMetadata: { ...DEFAULT_HEAD_METADATA, headStyles: [] } },\n });\n },\n\n clearPersisted: () => clearPersisted(),\n\n exportPDF: async () => {\n const mjml = generateMJML(templateRef.current);\n const result = await compileMJMLToHTML(mjml);\n const printStyles = `\n <style>\n @page { margin: 0; size: auto; }\n @media print {\n html, body { margin: 0; padding: 0; }\n }\n </style>\n `;\n const htmlWithPrintStyles = result.html.replace(\n '</head>',\n `${printStyles}</head>`,\n );\n const iframe = document.createElement('iframe');\n iframe.style.position = 'fixed';\n iframe.style.left = '-9999px';\n document.body.appendChild(iframe);\n const doc = iframe.contentDocument!;\n doc.open();\n doc.write(htmlWithPrintStyles);\n doc.close();\n iframe.contentWindow!.print();\n setTimeout(() => document.body.removeChild(iframe), 1000);\n },\n }), [dispatch, clearPersisted]);\n\n const sidebarClasses = [\n editorStyles.editorPanel,\n editorStyles.sidebarPanel,\n sidebarOpen ? editorStyles.sidebarOpen : '',\n ].filter(Boolean).join(' ');\n\n const propertiesClasses = [\n editorStyles.editorPanel,\n editorStyles.propertiesPanel,\n propertiesOpen ? editorStyles.propertiesOpen : '',\n ].filter(Boolean).join(' ');\n\n const overlayClasses = [\n editorStyles.panelOverlay,\n (sidebarOpen || propertiesOpen) ? editorStyles.panelOverlayVisible : '',\n ].filter(Boolean).join(' ');\n\n return (\n <div ref={containerRef} className={`ee-editor ${editorStyles.editorContainer}`} tabIndex={-1}>\n {pendingRemoval && (\n <ConfirmDialog\n title={pendingRemoval.type === 'block' ? 'Remove Block' : 'Remove Section'}\n message={\n pendingRemoval.type === 'block'\n ? 'Are you sure you want to remove this block? This action can be undone with Ctrl+Z.'\n : 'Are you sure you want to remove this section and all its contents? This action can be undone with Ctrl+Z.'\n }\n onConfirm={handleConfirmRemoval}\n onCancel={() => setPendingRemoval(null)}\n />\n )}\n <Toolbar\n sidebarOpen={sidebarOpen}\n propertiesOpen={propertiesOpen}\n onToggleSidebar={toggleSidebar}\n onToggleProperties={toggleProperties}\n />\n <div className={editorStyles.editorBody}>\n {activeTab === 'visual' && (\n <>\n <div className={`ee-sidebar ${sidebarClasses}`}>\n <ErrorBoundary>\n <Sidebar blockDefinitions={props.blockDefinitions} />\n </ErrorBoundary>\n </div>\n <div className={`ee-canvas ${editorStyles.editorPanel} ${editorStyles.canvasPanel}`}>\n <ErrorBoundary>\n <Canvas />\n </ErrorBoundary>\n </div>\n <div className={`ee-properties ${propertiesClasses}`}>\n <ErrorBoundary>\n <PropertiesPanel />\n </ErrorBoundary>\n </div>\n {/* Backdrop overlay for narrow screens */}\n <div className={overlayClasses} onClick={closeOverlays} />\n </>\n )}\n {activeTab === 'source' && (\n <div className={`ee-source-layout ${editorStyles.sourceLayout}`}>\n <div className={`ee-source-pane ${editorStyles.sourcePane}`}>\n <ErrorBoundary>\n <SourceEditor />\n </ErrorBoundary>\n </div>\n <div className={`ee-preview-pane ${editorStyles.sourcePaneDivider}`}>\n <ErrorBoundary>\n <PreviewPanel />\n </ErrorBoundary>\n </div>\n </div>\n )}\n {activeTab === 'preview' && (\n <ErrorBoundary>\n <PreviewPanel />\n </ErrorBoundary>\n )}\n </div>\n </div>\n );\n});\n\nexport const EmailEditor = forwardRef<EmailEditorRef, EmailEditorProps>(\n function EmailEditor(props, ref) {\n const {\n initialTemplate,\n initialMJML,\n variables,\n imageUploadAdapter,\n onChange,\n onVariablesChange,\n fontFamilies,\n fontSizes,\n persistenceKey,\n persistenceAdapter,\n className,\n style,\n onBlockAdd,\n onBlockRemove,\n onBlockUpdate,\n onSectionAdd,\n onSectionRemove,\n onSelectionChange,\n onTemplateLoad,\n onHistoryChange,\n } = props;\n\n let template = initialTemplate;\n if (!template && initialMJML) {\n try {\n template = parseMJML(initialMJML);\n } catch {\n template = undefined;\n }\n }\n\n return (\n <EditorProvider\n initialTemplate={template}\n variables={variables}\n imageUploadAdapter={imageUploadAdapter}\n onChange={onChange}\n onVariablesChange={onVariablesChange}\n fontFamilies={fontFamilies}\n fontSizes={fontSizes}\n persistenceKey={persistenceKey}\n persistenceAdapter={persistenceAdapter}\n onBlockAdd={onBlockAdd}\n onBlockRemove={onBlockRemove}\n onBlockUpdate={onBlockUpdate}\n onSectionAdd={onSectionAdd}\n onSectionRemove={onSectionRemove}\n onSelectionChange={onSelectionChange}\n onTemplateLoad={onTemplateLoad}\n onHistoryChange={onHistoryChange}\n >\n <div className={`ee-editor-wrapper ${editorStyles.editorWrapper} ${className || ''}`} style={style}>\n <EditorInner ref={ref} {...props} />\n </div>\n </EditorProvider>\n );\n },\n);\n","import React, {\n useReducer,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react';\nimport type {\n EditorAction,\n EmailTemplate,\n Variable,\n ImageUploadAdapter,\n PersistenceAdapter,\n Block,\n BlockProperties,\n Section,\n SelectionState,\n} from '../types';\nimport { DEFAULT_FONT_SIZES, FONT_OPTIONS } from '../constants';\nimport { sanitizeTemplate } from '../utils/validate';\nimport { localStorageAdapter } from '../utils/persistence';\nimport { useVariables } from '../hooks/useVariables';\nimport { useTipTapTracking } from '../hooks/useTipTapTracking';\nimport { usePersistence } from '../hooks/usePersistence';\nimport { DispatchContext } from './DispatchContext';\nimport { TemplateContext, type TemplateContextValue } from './TemplateContext';\nimport { SelectionContext } from './SelectionContext';\nimport { ConfigContext, type ConfigContextValue } from './ConfigContext';\nimport { MethodsContext } from './MethodsContext';\nimport { HistoryContext } from './HistoryContext';\nimport { BlockIndexContext } from './BlockIndexContext';\n\n// Import reducer + helpers from extracted module\nimport {\n editorReducer,\n createInitialState,\n DEBOUNCE_ELIGIBLE,\n INITIAL_SELECTION,\n} from './editorReducer';\n\nconst EMPTY_VARIABLES: Variable[] = [];\n\n// ---- Provider ----\n\ninterface EditorProviderProps {\n children: ReactNode;\n initialTemplate?: EmailTemplate;\n variables?: Variable[];\n imageUploadAdapter?: ImageUploadAdapter;\n onChange?: (template: EmailTemplate) => void;\n onVariablesChange?: (customVariables: Variable[]) => void;\n fontFamilies?: string[];\n fontSizes?: string[];\n persistenceKey?: string;\n persistenceAdapter?: PersistenceAdapter;\n // Event callbacks\n onBlockAdd?: (block: Block, sectionId: string, columnId: string) => void;\n onBlockRemove?: (blockId: string, sectionId: string, columnId: string) => void;\n onBlockUpdate?: (blockId: string, properties: Partial<BlockProperties>) => void;\n onBlockMove?: (blockId: string, toSectionId: string, toColumnId: string, toIndex: number) => void;\n onSectionAdd?: (section: Section, index?: number) => void;\n onSectionRemove?: (sectionId: string) => void;\n onSectionMove?: (sectionId: string, toIndex: number) => void;\n onSelectionChange?: (selection: SelectionState) => void;\n onTemplateLoad?: (template: EmailTemplate) => void;\n onHistoryChange?: (canUndo: boolean, canRedo: boolean) => void;\n}\n\nexport function EditorProvider({\n children,\n initialTemplate,\n variables: predefinedVariables = EMPTY_VARIABLES,\n imageUploadAdapter,\n onChange,\n onVariablesChange,\n fontFamilies: fontFamiliesProp,\n fontSizes: fontSizesProp,\n persistenceKey,\n persistenceAdapter,\n onBlockAdd,\n onBlockRemove,\n onBlockUpdate,\n onBlockMove,\n onSectionAdd,\n onSectionRemove,\n onSectionMove,\n onSelectionChange,\n onTemplateLoad,\n onHistoryChange,\n}: EditorProviderProps) {\n const fontFamilies = fontFamiliesProp ?? FONT_OPTIONS;\n const fontSizes = fontSizesProp ?? DEFAULT_FONT_SIZES;\n\n // Resolve initial template: persisted data takes priority over prop (sync case).\n const resolvedInitial = useMemo((): EmailTemplate | undefined => {\n if (persistenceKey) {\n const adapter = persistenceAdapter ?? localStorageAdapter;\n const persisted = adapter.load(persistenceKey);\n if (persisted && !(persisted instanceof Promise)) return sanitizeTemplate(persisted);\n // Async case handled in useEffect below\n }\n return initialTemplate;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const [state, rawDispatch] = useReducer(editorReducer, resolvedInitial, createInitialState);\n\n // Handle async persistence adapters — load in effect and apply via SET_TEMPLATE\n const asyncLoadedKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!persistenceKey) return;\n // Skip if we already loaded for this exact key\n if (asyncLoadedKeyRef.current === persistenceKey) return;\n const adapter = persistenceAdapter ?? localStorageAdapter;\n const result = adapter.load(persistenceKey);\n if (result instanceof Promise) {\n asyncLoadedKeyRef.current = persistenceKey;\n const key = persistenceKey; // capture for async callback\n result.then((persisted) => {\n // Only apply if the key hasn't changed since we started loading\n if (asyncLoadedKeyRef.current === key && persisted) {\n rawDispatch({ type: 'SET_TEMPLATE', payload: persisted });\n }\n }).catch(() => {\n // Async persistence load failed — fall through to initialTemplate\n });\n }\n }, [persistenceKey, persistenceAdapter]);\n\n // Debounced dispatch\n const historyTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const flushHistoryTimer = useCallback(() => {\n if (historyTimerRef.current !== null) {\n clearTimeout(historyTimerRef.current);\n historyTimerRef.current = null;\n rawDispatch({ type: 'PUSH_HISTORY' });\n }\n }, []);\n\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n // Store event callbacks in refs to avoid re-render cascades\n const eventRefs = useRef({\n onBlockAdd, onBlockRemove, onBlockUpdate, onBlockMove,\n onSectionAdd, onSectionRemove, onSectionMove,\n onSelectionChange, onTemplateLoad, onHistoryChange,\n });\n eventRefs.current = {\n onBlockAdd, onBlockRemove, onBlockUpdate, onBlockMove,\n onSectionAdd, onSectionRemove, onSectionMove,\n onSelectionChange, onTemplateLoad, onHistoryChange,\n };\n\n const dispatch: React.Dispatch<EditorAction> = useCallback(\n (action: EditorAction) => {\n if (DEBOUNCE_ELIGIBLE.has(action.type)) {\n rawDispatch(action);\n if (historyTimerRef.current !== null) {\n clearTimeout(historyTimerRef.current);\n }\n historyTimerRef.current = setTimeout(() => {\n historyTimerRef.current = null;\n rawDispatch({ type: 'PUSH_HISTORY' });\n }, 500);\n } else if (action.type === 'UNDO' || action.type === 'REDO') {\n flushHistoryTimer();\n rawDispatch(action);\n } else if (\n action.type === 'SELECT_BLOCK' ||\n action.type === 'SELECT_SECTION' ||\n action.type === 'SET_ACTIVE_TAB' ||\n action.type === 'DESELECT_ALL'\n ) {\n rawDispatch(action);\n } else {\n flushHistoryTimer();\n rawDispatch(action);\n }\n\n // Fire event callbacks after dispatch (wrapped in try/catch for safety)\n try {\n const ev = eventRefs.current;\n switch (action.type) {\n case 'ADD_BLOCK':\n case 'ADD_BLOCK_AND_SELECT':\n ev.onBlockAdd?.(action.payload.block, action.payload.sectionId, action.payload.columnId);\n break;\n case 'REMOVE_BLOCK':\n ev.onBlockRemove?.(action.payload.blockId, action.payload.sectionId, action.payload.columnId);\n break;\n case 'UPDATE_BLOCK':\n ev.onBlockUpdate?.(action.payload.blockId, action.payload.properties);\n break;\n case 'ADD_SECTION':\n ev.onSectionAdd?.(action.payload.section, action.payload.index);\n break;\n case 'ADD_SECTION_WITH_BLOCK':\n ev.onSectionAdd?.(action.payload.section, action.payload.index);\n ev.onBlockAdd?.(action.payload.block, action.payload.section.id, action.payload.section.columns[0]?.id);\n break;\n case 'REMOVE_SECTION':\n ev.onSectionRemove?.(action.payload.sectionId);\n break;\n case 'MOVE_BLOCK':\n ev.onBlockMove?.(action.payload.blockId, action.payload.toSectionId, action.payload.toColumnId, action.payload.toIndex);\n break;\n case 'MOVE_SECTION':\n ev.onSectionMove?.(action.payload.sectionId, action.payload.toIndex);\n break;\n // DUPLICATE_BLOCK and DUPLICATE_SECTION: the cloned object is created inside the reducer,\n // not available here. Host apps are notified of the resulting state change via onChange.\n case 'SELECT_BLOCK':\n case 'SELECT_SECTION':\n case 'DESELECT_ALL':\n if (action.type === 'DESELECT_ALL') {\n ev.onSelectionChange?.(INITIAL_SELECTION);\n } else if (action.type === 'SELECT_BLOCK') {\n ev.onSelectionChange?.(action.payload ?? INITIAL_SELECTION);\n } else {\n ev.onSelectionChange?.(\n action.payload\n ? { sectionId: action.payload.sectionId, columnId: null, blockId: null }\n : INITIAL_SELECTION,\n );\n }\n break;\n case 'SET_TEMPLATE':\n ev.onTemplateLoad?.(action.payload);\n break;\n }\n } catch (err) {\n console.error('[EmailEditor] Event callback error:', err);\n }\n },\n [flushHistoryTimer],\n );\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (historyTimerRef.current !== null) {\n clearTimeout(historyTimerRef.current);\n }\n };\n }, []);\n\n // Delegate to focused hooks\n const {\n customVariables,\n allVariables,\n variableChipStyle,\n addCustomVariable,\n removeCustomVariable,\n updateVariableChipStyle,\n } = useVariables({ predefinedVariables, onVariablesChange });\n\n const { setActiveEditor, getActiveEditor, insertVariable } = useTipTapTracking();\n\n const { clearPersisted } = usePersistence({\n template: state.template,\n persistenceKey,\n persistenceAdapter,\n });\n\n // Debounced onChange notification\n const isFirstRender = useRef(true);\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n return;\n }\n const timer = setTimeout(() => {\n onChangeRef.current?.(state.template);\n }, 150);\n return () => clearTimeout(timer);\n }, [state.template]);\n\n // Fire onHistoryChange when undo/redo state changes\n const prevHistoryRef = useRef({ canUndo: false, canRedo: false });\n useEffect(() => {\n const canUndo = state.historyIndex > 0;\n const canRedo = state.historyIndex < state.history.length - 1;\n if (canUndo !== prevHistoryRef.current.canUndo || canRedo !== prevHistoryRef.current.canRedo) {\n prevHistoryRef.current = { canUndo, canRedo };\n try {\n eventRefs.current.onHistoryChange?.(canUndo, canRedo);\n } catch (err) {\n console.error('[EmailEditor] onHistoryChange callback error:', err);\n }\n }\n }, [state.historyIndex, state.history.length]);\n\n // Focused context values with memoization\n const templateValue: TemplateContextValue = useMemo(\n () => ({\n template: state.template,\n isDirty: state.isDirty,\n activeTab: state.activeTab,\n }),\n [state.template, state.isDirty, state.activeTab],\n );\n\n const historyValue = useMemo(\n () => ({\n canUndo: state.historyIndex > 0,\n canRedo: state.historyIndex < state.history.length - 1,\n }),\n [state.historyIndex, state.history.length],\n );\n\n const selectionValue = useMemo(\n () => state.selection,\n [state.selection.sectionId, state.selection.columnId, state.selection.blockId],\n );\n\n const methodsValue = useMemo(\n () => ({ setActiveEditor, getActiveEditor, insertVariable }),\n [setActiveEditor, getActiveEditor, insertVariable],\n );\n\n const configValue: ConfigContextValue = useMemo(\n () => ({\n variables: allVariables,\n predefinedVariables,\n customVariables,\n imageUploadAdapter,\n addCustomVariable,\n removeCustomVariable,\n variableChipStyle,\n updateVariableChipStyle,\n fontFamilies,\n fontSizes,\n clearPersisted,\n }),\n [allVariables, predefinedVariables, customVariables, imageUploadAdapter, addCustomVariable, removeCustomVariable, variableChipStyle, updateVariableChipStyle, fontFamilies, fontSizes, clearPersisted],\n );\n\n const blockIndexValue = useMemo(() => state.blockIndex, [state.blockIndex]);\n\n return (\n <DispatchContext.Provider value={dispatch}>\n <MethodsContext.Provider value={methodsValue}>\n <HistoryContext.Provider value={historyValue}>\n <TemplateContext.Provider value={templateValue}>\n <SelectionContext.Provider value={selectionValue}>\n <ConfigContext.Provider value={configValue}>\n <BlockIndexContext.Provider value={blockIndexValue}>\n {children}\n </BlockIndexContext.Provider>\n </ConfigContext.Provider>\n </SelectionContext.Provider>\n </TemplateContext.Provider>\n </HistoryContext.Provider>\n </MethodsContext.Provider>\n </DispatchContext.Provider>\n );\n}\n\n// ---- Re-exports for backward compatibility ----\n\n// Re-export reducer + helpers\nexport { editorReducer, createInitialState, DEBOUNCE_ELIGIBLE } from './editorReducer';\n\n// Re-export hooks from editorHooks\nexport {\n useEditorState,\n useEditorDispatch,\n useSelectedBlock,\n useSelectedSection,\n useEditorVariables,\n useEditorFonts,\n useImageAdapter,\n} from './editorHooks';\n\n// Re-export focused context hooks for direct consumption\nexport { useDispatchContext } from './DispatchContext';\nexport { useTemplateContext } from './TemplateContext';\nexport { useSelectionContext } from './SelectionContext';\nexport { useConfigContext } from './ConfigContext';\nexport { useMethodsContext } from './MethodsContext';\nexport { useHistoryContext, type HistoryContextValue } from './HistoryContext';\nexport { useBlockIndexContext } from './BlockIndexContext';\n","import type {\n BlockType,\n BlockPropertiesMap,\n TextBlockProperties,\n ButtonBlockProperties,\n ImageBlockProperties,\n DividerBlockProperties,\n SpacerBlockProperties,\n SocialBlockProperties,\n HtmlBlockProperties,\n VideoBlockProperties,\n HeadingBlockProperties,\n CountdownBlockProperties,\n MenuBlockProperties,\n HeroBlockProperties,\n SectionProperties,\n GlobalStyles,\n VariableChipStyle,\n HeadMetadata,\n} from './types';\n\n// ---- Default Block Properties ----\n\nexport const DEFAULT_TEXT_PROPERTIES: TextBlockProperties = {\n content: '',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n color: '#000000',\n lineHeight: '1.5',\n padding: '10px 25px',\n align: 'left',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n};\n\nexport const DEFAULT_BUTTON_PROPERTIES: ButtonBlockProperties = {\n text: 'Click me',\n href: '#',\n backgroundColor: '#2563eb',\n color: '#ffffff',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n borderRadius: '4px',\n padding: '10px 25px',\n innerPadding: '12px 24px',\n align: 'center',\n width: 'auto',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n};\n\nexport const DEFAULT_IMAGE_PROPERTIES: ImageBlockProperties = {\n src: '',\n alt: '',\n href: '',\n width: '600px',\n height: 'auto',\n padding: '10px 25px',\n align: 'center',\n fluidOnMobile: true,\n};\n\nexport const DEFAULT_DIVIDER_PROPERTIES: DividerBlockProperties = {\n borderColor: '#cccccc',\n borderWidth: '1px',\n borderStyle: 'solid',\n padding: '10px 25px',\n width: '100%',\n};\n\nexport const DEFAULT_SPACER_PROPERTIES: SpacerBlockProperties = {\n height: '20px',\n};\n\nexport const DEFAULT_SOCIAL_PROPERTIES: SocialBlockProperties = {\n elements: [\n { name: 'facebook', href: 'https://facebook.com' },\n { name: 'twitter', href: 'https://twitter.com' },\n { name: 'instagram', href: 'https://instagram.com' },\n ],\n mode: 'horizontal',\n align: 'center',\n iconSize: '20px',\n iconPadding: '5px',\n padding: '10px 25px',\n fontSize: '13px',\n color: '#333333',\n borderRadius: '3px',\n};\n\nexport const DEFAULT_HTML_PROPERTIES: HtmlBlockProperties = {\n content: '',\n padding: '10px 25px',\n};\n\nexport const DEFAULT_VIDEO_PROPERTIES: VideoBlockProperties = {\n src: '',\n thumbnailUrl: '',\n alt: 'Video',\n padding: '10px 25px',\n align: 'center',\n};\n\nexport const DEFAULT_HEADING_PROPERTIES: HeadingBlockProperties = {\n content: '',\n level: 'h2',\n fontFamily: 'Arial, sans-serif',\n fontSize: '28px',\n color: '#000000',\n lineHeight: '1.3',\n fontWeight: 'bold',\n padding: '10px 25px',\n align: 'left',\n textTransform: 'none',\n letterSpacing: 'normal',\n};\n\nexport const DEFAULT_COUNTDOWN_PROPERTIES: CountdownBlockProperties = {\n targetDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 16),\n label: 'Sale ends in',\n digitBackgroundColor: '#333333',\n digitColor: '#ffffff',\n labelColor: '#666666',\n fontSize: '24px',\n padding: '10px 25px',\n align: 'center',\n};\n\nexport const DEFAULT_MENU_PROPERTIES: MenuBlockProperties = {\n items: [\n { text: 'Home', href: '#' },\n { text: 'About', href: '#' },\n { text: 'Contact', href: '#' },\n ],\n align: 'center',\n fontFamily: 'Arial, sans-serif',\n fontSize: '14px',\n color: '#333333',\n padding: '10px 25px',\n hamburger: false,\n iconColor: '#333333',\n};\n\nexport const DEFAULT_HERO_PROPERTIES: HeroBlockProperties = {\n heading: 'Welcome to Our Newsletter',\n subtext: 'Stay up to date with our latest news and updates.',\n buttonText: 'Get Started',\n buttonHref: '#',\n headingColor: '#333333',\n headingFontSize: '32px',\n subtextColor: '#666666',\n subtextFontSize: '16px',\n buttonBackgroundColor: '#2563eb',\n buttonColor: '#ffffff',\n buttonBorderRadius: '4px',\n align: 'center',\n padding: '40px 25px',\n backgroundImage: '',\n backgroundColor: '#ffffff',\n};\n\nexport const DEFAULT_BLOCK_PROPERTIES: { [K in BlockType]: BlockPropertiesMap[K] } = {\n text: DEFAULT_TEXT_PROPERTIES,\n button: DEFAULT_BUTTON_PROPERTIES,\n image: DEFAULT_IMAGE_PROPERTIES,\n divider: DEFAULT_DIVIDER_PROPERTIES,\n spacer: DEFAULT_SPACER_PROPERTIES,\n social: DEFAULT_SOCIAL_PROPERTIES,\n html: DEFAULT_HTML_PROPERTIES,\n video: DEFAULT_VIDEO_PROPERTIES,\n heading: DEFAULT_HEADING_PROPERTIES,\n countdown: DEFAULT_COUNTDOWN_PROPERTIES,\n menu: DEFAULT_MENU_PROPERTIES,\n hero: DEFAULT_HERO_PROPERTIES,\n};\n\n// ---- Default Section Properties ----\n\nexport const DEFAULT_SECTION_PROPERTIES: SectionProperties = {\n backgroundColor: 'transparent',\n padding: '20px 0',\n borderRadius: '0px',\n fullWidth: false,\n};\n\n// ---- Default Head Metadata ----\n\nexport const DEFAULT_HEAD_METADATA: HeadMetadata = {\n title: '',\n previewText: '',\n headStyles: [],\n};\n\n// ---- Default Global Styles ----\n\nexport const DEFAULT_GLOBAL_STYLES: GlobalStyles = {\n backgroundColor: '#f4f4f4',\n width: 600,\n fontFamily: 'Arial, sans-serif',\n};\n\n// ---- Default Variable Chip Style ----\n\nexport const DEFAULT_VARIABLE_CHIP_STYLE: VariableChipStyle = {\n backgroundColor: '#dbeafe',\n color: '#1e40af',\n borderColor: '#93c5fd',\n fontSize: 'inherit',\n borderRadius: '10px',\n};\n\n// ---- Block Palette Definitions ----\n\nexport interface BlockDefinition {\n type: BlockType;\n label: string;\n icon: string;\n description: string;\n}\n\nexport const BLOCK_DEFINITIONS: BlockDefinition[] = [\n {\n type: 'text',\n label: 'Text',\n icon: '📝',\n description: 'Rich text content with formatting',\n },\n {\n type: 'heading',\n label: 'Heading',\n icon: 'H',\n description: 'Heading with level selector',\n },\n {\n type: 'button',\n label: 'Button',\n icon: '🔘',\n description: 'Call-to-action button',\n },\n {\n type: 'image',\n label: 'Image',\n icon: '🖼️',\n description: 'Image with optional link',\n },\n {\n type: 'video',\n label: 'Video',\n icon: '▶️',\n description: 'Video thumbnail with link',\n },\n {\n type: 'divider',\n label: 'Divider',\n icon: '➖',\n description: 'Horizontal divider line',\n },\n {\n type: 'spacer',\n label: 'Spacer',\n icon: '↕️',\n description: 'Vertical spacing',\n },\n {\n type: 'social',\n label: 'Social',\n icon: '🔗',\n description: 'Social media links',\n },\n {\n type: 'html',\n label: 'HTML',\n icon: '</>',\n description: 'Raw HTML content',\n },\n {\n type: 'countdown',\n label: 'Countdown',\n icon: '⏱️',\n description: 'Countdown timer with digit boxes',\n },\n {\n type: 'menu',\n label: 'Menu',\n icon: '☰',\n description: 'Navigation menu links',\n },\n {\n type: 'hero',\n label: 'Hero',\n icon: '🦸',\n description: 'Hero section with heading, text and CTA',\n },\n];\n\n// ---- History ----\n\nexport const MAX_HISTORY_SIZE = 50;\n\n// ---- Font Size Options ----\n\nexport const DEFAULT_FONT_SIZES = [\n '10px', '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px',\n];\n\n// ---- Font Options ----\n\nexport const FONT_OPTIONS = [\n 'Arial, sans-serif',\n 'Helvetica, sans-serif',\n 'Georgia, serif',\n 'Times New Roman, serif',\n 'Courier New, monospace',\n 'Verdana, sans-serif',\n 'Trebuchet MS, sans-serif',\n 'Tahoma, sans-serif',\n];\n\n// ---- Color Presets ----\n\nexport const COLOR_PRESETS = [\n '#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff',\n '#ef4444', '#f97316', '#eab308', '#22c55e', '#3b82f6', '#8b5cf6',\n '#ec4899', '#14b8a6', '#f43f5e', '#6366f1', '#0ea5e9', '#84cc16',\n];\n\n// ---- Layout Presets ----\n\nexport const COLUMN_LAYOUTS = [\n { label: '1 Column', widths: ['100%'] },\n { label: '2 Columns', widths: ['50%', '50%'] },\n { label: '3 Columns', widths: ['33.33%', '33.33%', '33.33%'] },\n { label: '1/3 + 2/3', widths: ['33.33%', '66.67%'] },\n { label: '2/3 + 1/3', widths: ['66.67%', '33.33%'] },\n];\n","/**\n * Block type registries — single source of truth for mapping block types\n * to their renderers, property panels, generators, and parsers.\n *\n * Adding a new block type requires only adding entries here (Open/Closed Principle).\n */\nimport type { ComponentType } from 'react';\nimport type { Block, BlockType } from './types';\n\n// ---- Component Registries (populated by components at import time) ----\n\nexport const blockRendererRegistry: Record<string, ComponentType<{ block: Block }>> = {};\nexport const blockPropertiesRegistry: Record<string, ComponentType<{ block: Block }>> = {};\n\n// ---- MJML Generator Registry ----\n\nexport const blockGeneratorRegistry: Record<string, (block: Block, indent: string) => string> = {};\n\n// ---- MJML Parser Registry ----\n\nexport const blockParserRegistry: Record<string, (el: Element) => Block> = {};\n\n// ---- Registration helpers ----\n\n/**\n * Register a block renderer. Accepts BlockType for built-in types, or any string for custom blocks.\n */\nexport function registerBlockRenderer(type: BlockType | (string & {}), component: ComponentType<{ block: Block }>) {\n blockRendererRegistry[type] = component;\n}\n\n/**\n * Register a block properties panel. Accepts BlockType for built-in types, or any string for custom blocks.\n */\nexport function registerBlockProperties(type: BlockType | (string & {}), component: ComponentType<{ block: Block }>) {\n blockPropertiesRegistry[type] = component;\n}\n\n/**\n * Register a MJML generator. Accepts BlockType for built-in types, or any string for custom blocks.\n */\nexport function registerBlockGenerator(type: BlockType | (string & {}), generator: (block: Block, indent: string) => string) {\n blockGeneratorRegistry[type] = generator;\n}\n\nexport function registerBlockParser(mjmlTag: string, parser: (el: Element) => Block) {\n blockParserRegistry[mjmlTag] = parser;\n}\n\n/** Returns set of all registered block types (built-in + custom). */\nexport function getRegisteredBlockTypes(): Set<string> {\n return new Set(Object.keys(blockRendererRegistry));\n}\n","import type { EmailTemplate, BlockType, Section, Column, Block, GlobalStyles } from '../types';\nimport { DEFAULT_GLOBAL_STYLES, DEFAULT_HEAD_METADATA } from '../constants';\nimport { getRegisteredBlockTypes } from '../registry';\n\nconst BUILT_IN_BLOCK_TYPES: ReadonlySet<string> = new Set<BlockType>([\n 'text', 'button', 'image', 'divider', 'spacer', 'social',\n 'html', 'video', 'heading', 'countdown', 'menu', 'hero',\n]);\n\n/** Returns true if the type is a valid block type (built-in or registered custom). */\nfunction isValidBlockType(type: string): boolean {\n return BUILT_IN_BLOCK_TYPES.has(type) || getRegisteredBlockTypes().has(type);\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate raw data as an EmailTemplate.\n * Returns { valid, errors } with descriptive error messages.\n */\nexport function validateTemplate(data: unknown): ValidationResult {\n const errors: string[] = [];\n\n if (!data || typeof data !== 'object') {\n return { valid: false, errors: ['Template must be a non-null object'] };\n }\n\n const d = data as Record<string, unknown>;\n\n if (!Array.isArray(d.sections)) {\n errors.push('Template must have a \"sections\" array');\n } else {\n for (let si = 0; si < d.sections.length; si++) {\n const section = d.sections[si];\n if (!section || typeof section !== 'object') {\n errors.push(`sections[${si}]: must be an object`);\n continue;\n }\n if (typeof section.id !== 'string' || !section.id) {\n errors.push(`sections[${si}]: missing or invalid \"id\"`);\n }\n if (!Array.isArray(section.columns)) {\n errors.push(`sections[${si}]: must have a \"columns\" array`);\n } else {\n for (let ci = 0; ci < section.columns.length; ci++) {\n const col = section.columns[ci];\n if (!col || typeof col !== 'object') {\n errors.push(`sections[${si}].columns[${ci}]: must be an object`);\n continue;\n }\n if (typeof col.id !== 'string' || !col.id) {\n errors.push(`sections[${si}].columns[${ci}]: missing or invalid \"id\"`);\n }\n if (!Array.isArray(col.blocks)) {\n errors.push(`sections[${si}].columns[${ci}]: must have a \"blocks\" array`);\n } else {\n for (let bi = 0; bi < col.blocks.length; bi++) {\n const block = col.blocks[bi];\n if (!block || typeof block !== 'object') {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: must be an object`);\n continue;\n }\n if (typeof block.id !== 'string' || !block.id) {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: missing or invalid \"id\"`);\n }\n if (!isValidBlockType(block.type as string)) {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: invalid block type \"${block.type}\"`);\n }\n if (!block.properties || typeof block.properties !== 'object') {\n errors.push(`sections[${si}].columns[${ci}].blocks[${bi}]: missing \"properties\" object`);\n }\n }\n }\n }\n }\n }\n }\n\n if (d.globalStyles !== undefined && d.globalStyles !== null) {\n const gs = d.globalStyles as Record<string, unknown>;\n if (typeof gs !== 'object') {\n errors.push('globalStyles must be an object');\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n/**\n * Sanitize and coerce raw data into a valid EmailTemplate.\n * Fixes common issues (missing globalStyles, headMetadata, malformed sections).\n * Returns a safe-to-use template even if input is partially invalid.\n */\nexport function sanitizeTemplate(data: unknown): EmailTemplate {\n if (!data || typeof data !== 'object') {\n return { sections: [], globalStyles: { ...DEFAULT_GLOBAL_STYLES }, headMetadata: { ...DEFAULT_HEAD_METADATA, headStyles: [] } };\n }\n\n const d = data as Record<string, unknown>;\n\n // Sanitize globalStyles\n const rawGs = (d.globalStyles && typeof d.globalStyles === 'object') ? d.globalStyles as Record<string, unknown> : {};\n const globalStyles: GlobalStyles = {\n backgroundColor: typeof rawGs.backgroundColor === 'string' ? rawGs.backgroundColor : DEFAULT_GLOBAL_STYLES.backgroundColor,\n width: typeof rawGs.width === 'number' ? rawGs.width : DEFAULT_GLOBAL_STYLES.width,\n fontFamily: typeof rawGs.fontFamily === 'string' ? rawGs.fontFamily : DEFAULT_GLOBAL_STYLES.fontFamily,\n };\n\n // Sanitize headMetadata\n const rawHm = (d.headMetadata && typeof d.headMetadata === 'object') ? d.headMetadata as Record<string, unknown> : {};\n const headMetadata = {\n title: typeof rawHm.title === 'string' ? rawHm.title : '',\n previewText: typeof rawHm.previewText === 'string' ? rawHm.previewText : '',\n headStyles: Array.isArray(rawHm.headStyles) ? rawHm.headStyles.filter((s: unknown) => typeof s === 'string') as string[] : [],\n };\n\n // Sanitize sections\n const rawSections = Array.isArray(d.sections) ? d.sections : [];\n const sections: Section[] = [];\n\n for (const rawSection of rawSections) {\n if (!rawSection || typeof rawSection !== 'object') continue;\n const rs = rawSection as Record<string, unknown>;\n if (typeof rs.id !== 'string' || !rs.id) continue;\n if (!Array.isArray(rs.columns)) continue;\n\n const columns: Column[] = [];\n for (const rawCol of rs.columns) {\n if (!rawCol || typeof rawCol !== 'object') continue;\n const rc = rawCol as Record<string, unknown>;\n if (typeof rc.id !== 'string' || !rc.id) continue;\n\n const blocks: Block[] = [];\n const rawBlocks = Array.isArray(rc.blocks) ? rc.blocks : [];\n for (const rawBlock of rawBlocks) {\n if (!rawBlock || typeof rawBlock !== 'object') continue;\n const rb = rawBlock as Record<string, unknown>;\n if (typeof rb.id !== 'string' || !rb.id) continue;\n if (!isValidBlockType(rb.type as string)) continue;\n if (!rb.properties || typeof rb.properties !== 'object') continue;\n blocks.push({ id: rb.id, type: rb.type as BlockType, properties: rb.properties as Record<string, any> });\n }\n\n columns.push({\n id: rc.id,\n width: typeof rc.width === 'string' ? rc.width : '100%',\n blocks,\n });\n }\n\n const rawProps = (rs.properties && typeof rs.properties === 'object') ? rs.properties as Record<string, unknown> : {};\n sections.push({\n id: rs.id,\n columns,\n properties: {\n backgroundColor: typeof rawProps.backgroundColor === 'string' ? rawProps.backgroundColor : 'transparent',\n padding: typeof rawProps.padding === 'string' ? rawProps.padding : '20px 0',\n borderRadius: typeof rawProps.borderRadius === 'string' ? rawProps.borderRadius : '0px',\n fullWidth: typeof rawProps.fullWidth === 'boolean' ? rawProps.fullWidth : false,\n ...(typeof rawProps.backgroundImage === 'string' ? { backgroundImage: rawProps.backgroundImage } : {}),\n ...(typeof rawProps.backgroundSize === 'string' ? { backgroundSize: rawProps.backgroundSize } : {}),\n ...(typeof rawProps.backgroundRepeat === 'string' ? { backgroundRepeat: rawProps.backgroundRepeat } : {}),\n },\n });\n }\n\n return { sections, globalStyles, headMetadata };\n}\n","import type { PersistenceAdapter, EmailTemplate } from '../types';\nimport { sanitizeTemplate } from './validate';\n\n/**\n * Default persistence adapter using localStorage.\n * All operations are wrapped in try/catch to handle quota errors,\n * private browsing restrictions, and SSR environments.\n */\nexport const localStorageAdapter: PersistenceAdapter = {\n save(key: string, template: EmailTemplate): void {\n try {\n localStorage.setItem(key, JSON.stringify(template));\n } catch {\n // Silently fail — quota exceeded, private browsing, or SSR\n }\n },\n\n load(key: string): EmailTemplate | null {\n try {\n const data = localStorage.getItem(key);\n if (!data) return null;\n const parsed = JSON.parse(data);\n // Basic schema validation: must have sections array\n if (!parsed || !Array.isArray(parsed.sections)) return null;\n return sanitizeTemplate(parsed);\n } catch {\n return null;\n }\n },\n\n remove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // Silently fail\n }\n },\n};\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { Variable, VariableChipStyle } from '../types';\nimport { DEFAULT_VARIABLE_CHIP_STYLE } from '../constants';\n\ninterface UseVariablesOptions {\n predefinedVariables: Variable[];\n onVariablesChange?: (customVariables: Variable[]) => void;\n}\n\ninterface UseVariablesResult {\n customVariables: Variable[];\n allVariables: Variable[];\n variableChipStyle: VariableChipStyle;\n addCustomVariable: (variable: Variable) => void;\n removeCustomVariable: (key: string) => void;\n updateVariableChipStyle: (style: Partial<VariableChipStyle>) => void;\n}\n\nexport function useVariables({\n predefinedVariables,\n onVariablesChange,\n}: UseVariablesOptions): UseVariablesResult {\n const [customVariables, setCustomVariables] = useState<Variable[]>([]);\n const [variableChipStyle, setVariableChipStyle] = useState<VariableChipStyle>({ ...DEFAULT_VARIABLE_CHIP_STYLE });\n\n const addCustomVariable = useCallback((variable: Variable) => {\n setCustomVariables((prev) => {\n if (prev.some((v) => v.key === variable.key)) return prev;\n return [...prev, variable];\n });\n }, []);\n\n const removeCustomVariable = useCallback((key: string) => {\n setCustomVariables((prev) => prev.filter((v) => v.key !== key));\n }, []);\n\n const updateVariableChipStyle = useCallback((partial: Partial<VariableChipStyle>) => {\n setVariableChipStyle((prev) => ({ ...prev, ...partial }));\n }, []);\n\n // Merge pre-defined + custom variables\n const allVariables = useMemo(() => {\n const merged = [...predefinedVariables];\n for (const cv of customVariables) {\n if (!merged.some((v) => v.key === cv.key)) {\n merged.push(cv);\n }\n }\n return merged;\n }, [predefinedVariables, customVariables]);\n\n // Notify parent when custom variables change\n const onVariablesChangeRef = useRef(onVariablesChange);\n onVariablesChangeRef.current = onVariablesChange;\n const isFirstVariablesRender = useRef(true);\n useEffect(() => {\n if (isFirstVariablesRender.current) {\n isFirstVariablesRender.current = false;\n return;\n }\n onVariablesChangeRef.current?.(customVariables);\n }, [customVariables]);\n\n return {\n customVariables,\n allVariables,\n variableChipStyle,\n addCustomVariable,\n removeCustomVariable,\n updateVariableChipStyle,\n };\n}\n","import { useCallback, useRef } from 'react';\nimport type { Editor } from '@tiptap/core';\n\ninterface UseTipTapTrackingResult {\n setActiveEditor: (editor: Editor | null) => void;\n getActiveEditor: () => Editor | null;\n insertVariable: (key: string) => boolean;\n}\n\nexport function useTipTapTracking(): UseTipTapTrackingResult {\n const activeEditorRef = useRef<Editor | null>(null);\n\n const setActiveEditor = useCallback((editor: Editor | null) => {\n activeEditorRef.current = editor;\n }, []);\n\n const getActiveEditor = useCallback(() => {\n return activeEditorRef.current;\n }, []);\n\n const insertVariable = useCallback((key: string): boolean => {\n const editor = activeEditorRef.current;\n if (!editor || editor.isDestroyed) return false;\n editor.chain().focus().insertVariable(key).run();\n return true;\n }, []);\n\n return { setActiveEditor, getActiveEditor, insertVariable };\n}\n","import { useCallback, useEffect, useRef } from 'react';\nimport type { EmailTemplate, PersistenceAdapter } from '../types';\nimport { localStorageAdapter } from '../utils/persistence';\n\ninterface UsePersistenceOptions {\n template: EmailTemplate;\n persistenceKey?: string;\n persistenceAdapter?: PersistenceAdapter;\n}\n\ninterface UsePersistenceResult {\n clearPersisted: () => void;\n}\n\nexport function usePersistence({\n template,\n persistenceKey,\n persistenceAdapter,\n}: UsePersistenceOptions): UsePersistenceResult {\n const persistenceKeyRef = useRef(persistenceKey);\n persistenceKeyRef.current = persistenceKey;\n const persistenceAdapterRef = useRef(persistenceAdapter);\n persistenceAdapterRef.current = persistenceAdapter;\n\n // Debounced auto-save to persistence (500ms)\n const isFirstPersistRender = useRef(true);\n useEffect(() => {\n if (isFirstPersistRender.current) {\n isFirstPersistRender.current = false;\n return;\n }\n const key = persistenceKeyRef.current;\n if (!key) return;\n const adapter = persistenceAdapterRef.current ?? localStorageAdapter;\n const timer = setTimeout(() => {\n adapter.save(key, template);\n }, 500);\n return () => clearTimeout(timer);\n }, [template]);\n\n const clearPersisted = useCallback(() => {\n if (!persistenceKeyRef.current) return;\n const adapter = persistenceAdapterRef.current ?? localStorageAdapter;\n adapter.remove(persistenceKeyRef.current);\n }, []);\n\n return { clearPersisted };\n}\n","import { createContext, useContext } from 'react';\nimport type { EditorAction } from '../types';\n\nexport const DispatchContext = createContext<React.Dispatch<EditorAction> | null>(null);\n\nexport function useDispatchContext(): React.Dispatch<EditorAction> {\n const ctx = useContext(DispatchContext);\n if (!ctx) {\n throw new Error('useDispatchContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { EmailTemplate, ActiveTab } from '../types';\n\nexport interface TemplateContextValue {\n template: EmailTemplate;\n isDirty: boolean;\n activeTab: ActiveTab;\n}\n\nexport const TemplateContext = createContext<TemplateContextValue | null>(null);\n\nexport function useTemplateContext(): TemplateContextValue {\n const ctx = useContext(TemplateContext);\n if (!ctx) {\n throw new Error('useTemplateContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { SelectionState } from '../types';\n\nexport const SelectionContext = createContext<SelectionState | null>(null);\n\nexport function useSelectionContext(): SelectionState {\n const ctx = useContext(SelectionContext);\n if (!ctx) {\n throw new Error('useSelectionContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { Variable, VariableChipStyle, ImageUploadAdapter } from '../types';\n\nexport interface ConfigContextValue {\n variables: Variable[];\n predefinedVariables: Variable[];\n customVariables: Variable[];\n imageUploadAdapter?: ImageUploadAdapter;\n addCustomVariable: (variable: Variable) => void;\n removeCustomVariable: (key: string) => void;\n variableChipStyle: VariableChipStyle;\n updateVariableChipStyle: (style: Partial<VariableChipStyle>) => void;\n fontFamilies: string[];\n fontSizes: string[];\n clearPersisted: () => void;\n}\n\nexport const ConfigContext = createContext<ConfigContextValue | null>(null);\n\nexport function useConfigContext(): ConfigContextValue {\n const ctx = useContext(ConfigContext);\n if (!ctx) {\n throw new Error('useConfigContext must be used within an EditorProvider');\n }\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { Editor } from '@tiptap/core';\n\nexport interface MethodsContextValue {\n setActiveEditor: (editor: Editor | null) => void;\n getActiveEditor: () => Editor | null;\n insertVariable: (key: string) => boolean;\n}\n\nexport const MethodsContext = createContext<MethodsContextValue | null>(null);\n\nexport function useMethodsContext(): MethodsContextValue {\n const ctx = useContext(MethodsContext);\n if (!ctx) throw new Error('useMethodsContext must be used within an EditorProvider');\n return ctx;\n}\n","import { createContext, useContext } from 'react';\n\nexport interface HistoryContextValue {\n canUndo: boolean;\n canRedo: boolean;\n}\n\nexport const HistoryContext = createContext<HistoryContextValue | null>(null);\n\nexport function useHistoryContext(): HistoryContextValue {\n const ctx = useContext(HistoryContext);\n if (!ctx) throw new Error('useHistoryContext must be used within an EditorProvider');\n return ctx;\n}\n","import { createContext, useContext } from 'react';\nimport type { BlockIndex } from '../utils/blockIndex';\n\nexport const BlockIndexContext = createContext<BlockIndex | null>(null);\n\nexport function useBlockIndexContext(): BlockIndex {\n const ctx = useContext(BlockIndexContext);\n if (!ctx) throw new Error('useBlockIndexContext must be used within an EditorProvider');\n return ctx;\n}\n","import { nanoid } from 'nanoid';\n\nexport function generateId(prefix?: string): string {\n const id = nanoid(10);\n return prefix ? `${prefix}_${id}` : id;\n}\n\nexport function generateBlockId(): string {\n return generateId('blk');\n}\n\nexport function generateSectionId(): string {\n return generateId('sec');\n}\n\nexport function generateColumnId(): string {\n return generateId('col');\n}\n","import type { Block, BlockType, Section } from '../types';\nimport { DEFAULT_BLOCK_PROPERTIES, DEFAULT_SECTION_PROPERTIES } from '../constants';\nimport { generateBlockId, generateSectionId, generateColumnId } from './id';\n\n/** Deep-clone a block with a fresh ID */\nexport function cloneBlock(block: Block): Block {\n return {\n ...block,\n id: generateBlockId(),\n properties: JSON.parse(JSON.stringify(block.properties)),\n };\n}\n\n/** Deep-clone a section with fresh IDs for the section, all columns, and all blocks */\nexport function cloneSection(section: Section): Section {\n return {\n id: generateSectionId(),\n properties: JSON.parse(JSON.stringify(section.properties)),\n columns: section.columns.map((col) => ({\n id: generateColumnId(),\n width: col.width,\n blocks: col.blocks.map(cloneBlock),\n })),\n };\n}\n\n/** Create a new block with default properties */\nexport function createBlock<T extends BlockType>(type: T): Block<T> {\n return {\n id: generateBlockId(),\n type,\n properties: JSON.parse(JSON.stringify(DEFAULT_BLOCK_PROPERTIES[type])),\n };\n}\n\n/** Create a new section with given column widths (defaults to single 100% column) */\nexport function createSection(widths: string[] = ['100%']): Section {\n return {\n id: generateSectionId(),\n columns: widths.map((width) => ({\n id: generateColumnId(),\n width,\n blocks: [],\n })),\n properties: { ...DEFAULT_SECTION_PROPERTIES },\n };\n}\n\n/** Create a section pre-populated with a block */\nexport function createSectionWithBlock(type: BlockType): Section {\n const section = createSection();\n section.columns[0].blocks.push(createBlock(type));\n return section;\n}\n","import type { Section } from '../types';\n\nexport type BlockIndex = Map<string, { sectionId: string; columnId: string }>;\n\n/**\n * Build a lookup index from blockId → { sectionId, columnId } for O(1) block location.\n */\nexport function buildBlockIndex(sections: Section[]): BlockIndex {\n const index: BlockIndex = new Map();\n for (const section of sections) {\n for (const column of section.columns) {\n for (const block of column.blocks) {\n index.set(block.id, { sectionId: section.id, columnId: column.id });\n }\n }\n }\n return index;\n}\n","import type {\n EditorState,\n EditorAction,\n EmailTemplate,\n Block,\n SelectionState,\n} from '../types';\nimport { DEFAULT_GLOBAL_STYLES, DEFAULT_HEAD_METADATA, MAX_HISTORY_SIZE } from '../constants';\nimport { cloneBlock, cloneSection } from '../utils/factory';\nimport { buildBlockIndex } from '../utils/blockIndex';\nimport { sanitizeTemplate } from '../utils/validate';\n\n// ---- Initial State ----\n\nexport const INITIAL_SELECTION: SelectionState = {\n sectionId: null,\n columnId: null,\n blockId: null,\n};\n\nexport function createInitialState(template?: EmailTemplate): EditorState {\n const t = template ?? { sections: [], globalStyles: { ...DEFAULT_GLOBAL_STYLES }, headMetadata: { ...DEFAULT_HEAD_METADATA, headStyles: [] } };\n if (!t.headMetadata) {\n t.headMetadata = { ...DEFAULT_HEAD_METADATA, headStyles: [] };\n }\n return {\n template: t,\n selection: INITIAL_SELECTION,\n activeTab: 'visual',\n history: [t],\n historyIndex: 0,\n isDirty: false,\n blockIndex: buildBlockIndex(t.sections),\n };\n}\n\n// ---- Helpers ----\n\nexport function pushHistory(state: EditorState, newTemplate: EmailTemplate): EditorState {\n const history = state.history.slice(0, state.historyIndex + 1);\n history.push(newTemplate);\n if (history.length > MAX_HISTORY_SIZE) {\n history.shift();\n }\n return {\n ...state,\n template: newTemplate,\n history,\n historyIndex: history.length - 1,\n isDirty: true,\n blockIndex: buildBlockIndex(newTemplate.sections),\n };\n}\n\n/** Apply template change without history push. Reuses blockIndex since non-structural changes don't affect block locations. */\nfunction applyWithoutHistory(state: EditorState, newTemplate: EmailTemplate): EditorState {\n return { ...state, template: newTemplate, isDirty: true };\n}\n\n/** Validate selection against a restored template, clearing references to blocks/sections that no longer exist. */\nfunction validateSelection(\n selection: SelectionState,\n blockIndex: Map<string, { sectionId: string; columnId: string }>,\n template: EmailTemplate,\n): SelectionState {\n if (selection.blockId) {\n const loc = blockIndex.get(selection.blockId);\n if (!loc) return INITIAL_SELECTION;\n // Reconcile sectionId/columnId with actual block location\n if (selection.sectionId !== loc.sectionId || selection.columnId !== loc.columnId) {\n return { sectionId: loc.sectionId, columnId: loc.columnId, blockId: selection.blockId };\n }\n return selection;\n }\n if (selection.sectionId) {\n if (!template.sections.some((s) => s.id === selection.sectionId)) return INITIAL_SELECTION;\n return selection;\n }\n return selection;\n}\n\n// Actions that update template without pushing to history (debounced externally)\nexport const DEBOUNCE_ELIGIBLE: ReadonlySet<string> = new Set([\n 'UPDATE_BLOCK',\n 'UPDATE_SECTION',\n 'UPDATE_GLOBAL_STYLES',\n 'UPDATE_HEAD_METADATA',\n]);\n\n// ---- Reducer ----\n\nexport function editorReducer(state: EditorState, action: EditorAction): EditorState {\n switch (action.type) {\n case 'SET_TEMPLATE': {\n const sanitized = sanitizeTemplate(action.payload);\n const newState = pushHistory(state, sanitized);\n return {\n ...newState,\n selection: validateSelection(state.selection, newState.blockIndex, sanitized),\n };\n }\n\n case 'ADD_SECTION': {\n const { section, index } = action.payload;\n const sections = [...state.template.sections];\n const insertAt = index ?? sections.length;\n sections.splice(insertAt, 0, section);\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'REMOVE_SECTION': {\n const sections = state.template.sections.filter(\n (s) => s.id !== action.payload.sectionId,\n );\n const newState = pushHistory(state, { ...state.template, sections });\n if (state.selection.sectionId === action.payload.sectionId) {\n return { ...newState, selection: INITIAL_SELECTION };\n }\n return newState;\n }\n\n case 'MOVE_SECTION': {\n const { sectionId, toIndex } = action.payload;\n const sections = [...state.template.sections];\n const fromIndex = sections.findIndex((s) => s.id === sectionId);\n if (fromIndex === -1) return state;\n const [moved] = sections.splice(fromIndex, 1);\n sections.splice(toIndex, 0, moved);\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'UPDATE_SECTION': {\n const { sectionId, properties } = action.payload;\n const sections = state.template.sections.map((s) =>\n s.id === sectionId\n ? { ...s, properties: { ...s.properties, ...properties } }\n : s,\n );\n return applyWithoutHistory(state, { ...state.template, sections });\n }\n\n case 'ADD_BLOCK': {\n const { sectionId, columnId, block, index } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n const blocks = [...col.blocks];\n const insertAt = index ?? blocks.length;\n blocks.splice(insertAt, 0, block);\n return { ...col, blocks };\n }),\n };\n });\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'REMOVE_BLOCK': {\n const { sectionId, columnId, blockId } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n return { ...col, blocks: col.blocks.filter((b) => b.id !== blockId) };\n }),\n };\n });\n const newState = pushHistory(state, { ...state.template, sections });\n if (state.selection.blockId === blockId) {\n return { ...newState, selection: INITIAL_SELECTION };\n }\n return newState;\n }\n\n case 'MOVE_BLOCK': {\n const { fromSectionId, fromColumnId, blockId, toSectionId, toColumnId, toIndex: rawToIndex } =\n action.payload;\n let movedBlock: Block | null = null;\n let toIndex = rawToIndex;\n if (fromSectionId === toSectionId && fromColumnId === toColumnId) {\n const srcSection = state.template.sections.find((s) => s.id === fromSectionId);\n const srcCol = srcSection?.columns.find((c) => c.id === fromColumnId);\n if (srcCol) {\n const fromIdx = srcCol.blocks.findIndex((b) => b.id === blockId);\n if (fromIdx >= 0 && fromIdx < toIndex) {\n toIndex--;\n }\n }\n }\n let sections = state.template.sections.map((section) => {\n if (section.id !== fromSectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== fromColumnId) return col;\n const block = col.blocks.find((b) => b.id === blockId);\n if (block) movedBlock = block;\n return { ...col, blocks: col.blocks.filter((b) => b.id !== blockId) };\n }),\n };\n });\n if (!movedBlock) return state;\n sections = sections.map((section) => {\n if (section.id !== toSectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== toColumnId) return col;\n const blocks = [...col.blocks];\n blocks.splice(toIndex, 0, movedBlock!);\n return { ...col, blocks };\n }),\n };\n });\n const newState = pushHistory(state, { ...state.template, sections });\n // Update selection to the new location if the moved block was selected\n if (state.selection.blockId === blockId) {\n return { ...newState, selection: { sectionId: toSectionId, columnId: toColumnId, blockId } };\n }\n return newState;\n }\n\n case 'UPDATE_BLOCK': {\n const { blockId, properties } = action.payload;\n const loc = state.blockIndex.get(blockId);\n if (!loc) return state;\n const sections = state.template.sections.map((section) => {\n if (section.id !== loc.sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== loc.columnId) return col;\n return {\n ...col,\n blocks: col.blocks.map((b) =>\n b.id === blockId\n ? { ...b, properties: { ...b.properties, ...properties } }\n : b,\n ),\n };\n }),\n };\n });\n return { ...state, template: { ...state.template, sections }, isDirty: true };\n }\n\n case 'SELECT_BLOCK': {\n return {\n ...state,\n selection: action.payload ?? INITIAL_SELECTION,\n };\n }\n\n case 'SELECT_SECTION': {\n return {\n ...state,\n selection: action.payload\n ? { sectionId: action.payload.sectionId, columnId: null, blockId: null }\n : INITIAL_SELECTION,\n };\n }\n\n case 'ADD_BLOCK_AND_SELECT': {\n const { sectionId, columnId, block, index } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n const blocks = [...col.blocks];\n const insertAt = index ?? blocks.length;\n blocks.splice(insertAt, 0, block);\n return { ...col, blocks };\n }),\n };\n });\n const newState = pushHistory(state, { ...state.template, sections });\n return {\n ...newState,\n selection: { sectionId, columnId, blockId: block.id },\n };\n }\n\n case 'ADD_SECTION_WITH_BLOCK': {\n const { section, block, index } = action.payload;\n const sections = [...state.template.sections];\n const insertAt = index ?? sections.length;\n const sectionWithBlock = {\n ...section,\n columns: section.columns.map((col, i) =>\n i === 0 ? { ...col, blocks: [...col.blocks, block] } : col,\n ),\n };\n sections.splice(insertAt, 0, sectionWithBlock);\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'DESELECT_ALL': {\n return {\n ...state,\n selection: INITIAL_SELECTION,\n };\n }\n\n case 'SET_ACTIVE_TAB': {\n return { ...state, activeTab: action.payload };\n }\n\n case 'UPDATE_GLOBAL_STYLES': {\n const globalStyles = { ...state.template.globalStyles, ...action.payload };\n return applyWithoutHistory(state, { ...state.template, globalStyles });\n }\n\n case 'UPDATE_HEAD_METADATA': {\n const current = state.template.headMetadata ?? { ...DEFAULT_HEAD_METADATA, headStyles: [] };\n const headMetadata = { ...current, ...action.payload };\n return applyWithoutHistory(state, { ...state.template, headMetadata });\n }\n\n case 'DUPLICATE_BLOCK': {\n const { sectionId, columnId, blockId } = action.payload;\n const sections = state.template.sections.map((section) => {\n if (section.id !== sectionId) return section;\n return {\n ...section,\n columns: section.columns.map((col) => {\n if (col.id !== columnId) return col;\n const blockIndex = col.blocks.findIndex((b) => b.id === blockId);\n if (blockIndex === -1) return col;\n const blocks = [...col.blocks];\n blocks.splice(blockIndex + 1, 0, cloneBlock(col.blocks[blockIndex]));\n return { ...col, blocks };\n }),\n };\n });\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'DUPLICATE_SECTION': {\n const { sectionId } = action.payload;\n const sections = [...state.template.sections];\n const sectionIndex = sections.findIndex((s) => s.id === sectionId);\n if (sectionIndex === -1) return state;\n sections.splice(sectionIndex + 1, 0, cloneSection(sections[sectionIndex]));\n return pushHistory(state, { ...state.template, sections });\n }\n\n case 'UNDO': {\n if (state.historyIndex <= 0) return state;\n const newIndex = state.historyIndex - 1;\n const restored = state.history[newIndex];\n const newBlockIndex = buildBlockIndex(restored.sections);\n return {\n ...state,\n template: restored,\n historyIndex: newIndex,\n blockIndex: newBlockIndex,\n selection: validateSelection(state.selection, newBlockIndex, restored),\n };\n }\n\n case 'REDO': {\n if (state.historyIndex >= state.history.length - 1) return state;\n const newIndex = state.historyIndex + 1;\n const restored = state.history[newIndex];\n const newBlockIndex = buildBlockIndex(restored.sections);\n return {\n ...state,\n template: restored,\n historyIndex: newIndex,\n blockIndex: newBlockIndex,\n selection: validateSelection(state.selection, newBlockIndex, restored),\n };\n }\n\n case 'PUSH_HISTORY': {\n if (state.template === state.history[state.historyIndex]) return state;\n return pushHistory(state, state.template);\n }\n\n default:\n return state;\n }\n}\n","import { useMemo } from 'react';\nimport type { EditorAction, Block, Section } from '../types';\nimport { useTemplateContext } from './TemplateContext';\nimport { useSelectionContext } from './SelectionContext';\nimport { useDispatchContext } from './DispatchContext';\nimport { useConfigContext } from './ConfigContext';\nimport { useMethodsContext } from './MethodsContext';\nimport { useHistoryContext } from './HistoryContext';\nimport { useBlockIndexContext } from './BlockIndexContext';\n\n// ---- Primary Hooks ----\n\n/** @deprecated Use focused hooks (useTemplateContext, useSelectionContext, etc.) instead */\nexport function useEditorState() {\n const tmpl = useTemplateContext();\n const sel = useSelectionContext();\n const { canUndo, canRedo } = useHistoryContext();\n return useMemo(\n () => ({\n template: tmpl.template,\n isDirty: tmpl.isDirty,\n activeTab: tmpl.activeTab,\n selection: sel,\n canUndo,\n canRedo,\n }),\n [tmpl, sel, canUndo, canRedo],\n );\n}\n\nexport function useEditorDispatch(): React.Dispatch<EditorAction> {\n return useDispatchContext();\n}\n\n// ---- Derived Selection Hooks ----\n\nexport function useSelectedBlock(): Block | null {\n const { template } = useTemplateContext();\n const { blockId } = useSelectionContext();\n const blockIndex = useBlockIndexContext();\n return useMemo(() => {\n if (!blockId) return null;\n const loc = blockIndex.get(blockId);\n if (!loc) return null;\n const section = template.sections.find((s) => s.id === loc.sectionId);\n if (!section) return null;\n const column = section.columns.find((c) => c.id === loc.columnId);\n if (!column) return null;\n return column.blocks.find((b) => b.id === blockId) ?? null;\n }, [template.sections, blockId, blockIndex]);\n}\n\nexport function useSelectedSection(): Section | null {\n const { template } = useTemplateContext();\n const { sectionId } = useSelectionContext();\n return useMemo(() => {\n if (!sectionId) return null;\n return template.sections.find((s) => s.id === sectionId) ?? null;\n }, [template.sections, sectionId]);\n}\n\n// ---- Convenience Hooks ----\n\nexport function useEditorVariables() {\n const { variables, predefinedVariables, customVariables, addCustomVariable, removeCustomVariable, variableChipStyle, updateVariableChipStyle } = useConfigContext();\n const { insertVariable } = useMethodsContext();\n return { variables, predefinedVariables, customVariables, addCustomVariable, removeCustomVariable, insertVariable, variableChipStyle, updateVariableChipStyle };\n}\n\nexport function useEditorFonts() {\n const { fontFamilies, fontSizes } = useConfigContext();\n return { fontFamilies, fontSizes };\n}\n\nexport function useImageAdapter() {\n const { imageUploadAdapter } = useConfigContext();\n return { imageUploadAdapter };\n}\n","import React, { Component, type ReactNode, type ErrorInfo } from 'react';\nimport styles from '../styles/error-boundary.module.css';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n this.props.onError?.(error, errorInfo);\n }\n\n private handleRetry = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) return this.props.fallback;\n return (\n <div\n className={`ee-error-boundary ${styles.errorBoundary}`}\n role=\"alert\"\n >\n <strong className=\"ee-error-title\">Something went wrong</strong>\n <p className={`ee-error-message ${styles.errorMessage}`}>\n {this.state.error?.message || 'An unexpected error occurred.'}\n </p>\n <button\n className={`ee-error-retry ${styles.retryBtn}`}\n onClick={this.handleRetry}\n aria-label=\"Retry\"\n >\n Try Again\n </button>\n </div>\n );\n }\n return this.props.children;\n }\n}\n",".errorBoundary {\n padding: var(--ee-space-lg);\n margin: var(--ee-space-sm);\n background: var(--ee-color-danger-light);\n border: 1px solid var(--ee-color-danger-border);\n border-radius: var(--ee-border-radius);\n color: var(--ee-color-danger);\n font-size: var(--ee-font-size-md);\n}\n\n.errorMessage {\n margin: var(--ee-space-sm) 0 0;\n color: var(--ee-color-danger-hover);\n}\n\n.retryBtn {\n margin-top: var(--ee-space-md);\n padding: var(--ee-space-sm) var(--ee-space-lg);\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n border: none;\n border-radius: var(--ee-border-radius-sm);\n font-size: var(--ee-font-size-sm);\n cursor: pointer;\n transition: background var(--ee-transition-fast);\n}\n\n.retryBtn:hover {\n background: var(--ee-color-danger-hover);\n}\n","import { useEffect, useRef, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport styles from '../styles/confirm-dialog.module.css';\n\ninterface ConfirmDialogProps {\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function ConfirmDialog({\n title,\n message,\n confirmLabel = 'Remove',\n cancelLabel = 'Cancel',\n onConfirm,\n onCancel,\n}: ConfirmDialogProps) {\n const cancelRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCancel();\n return;\n }\n\n // Focus trap: cycle Tab/Shift+Tab within dialog\n if (e.key === 'Tab' && dialogRef.current) {\n const focusable = dialogRef.current.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n },\n [onCancel],\n );\n\n useEffect(() => {\n document.addEventListener('keydown', handleKeyDown);\n cancelRef.current?.focus();\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [handleKeyDown]);\n\n return createPortal(\n <div className={`ee-dialog-overlay ${styles.overlay}`} onClick={onCancel} role=\"dialog\" aria-modal=\"true\" aria-label={title}>\n <div ref={dialogRef} className={`ee-dialog ${styles.dialog}`} onClick={(e) => e.stopPropagation()}>\n <h3 className={`ee-dialog-title ${styles.title}`}>{title}</h3>\n <p className={`ee-dialog-message ${styles.message}`}>{message}</p>\n <div className={`ee-dialog-actions ${styles.actions}`}>\n <button ref={cancelRef} className={`ee-dialog-cancel ${styles.btnCancel}`} onClick={onCancel}>\n {cancelLabel}\n </button>\n <button className={`ee-dialog-confirm ${styles.btnConfirm}`} onClick={onConfirm}>\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n",".overlay {\n position: fixed;\n top: 0; right: 0; bottom: 0; left: 0;\n background: var(--ee-overlay-backdrop);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: var(--ee-z-modal);\n animation: fadeIn var(--ee-transition-fast);\n}\n\n.dialog {\n background: var(--ee-bg-panel);\n border-radius: var(--ee-border-radius-lg);\n box-shadow: var(--ee-shadow-lg);\n padding: var(--ee-space-xl);\n min-width: 320px;\n max-width: 400px;\n animation: slideUp var(--ee-transition-normal);\n font-family: var(--ee-font-family);\n}\n\n.title {\n margin: 0 0 var(--ee-space-sm) 0;\n font-size: var(--ee-font-size-lg);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-primary);\n}\n\n.message {\n margin: 0 0 var(--ee-space-xl) 0;\n font-size: var(--ee-font-size-base);\n color: var(--ee-text-secondary);\n line-height: 1.5;\n}\n\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--ee-space-sm);\n}\n\n.btnCancel {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-panel);\n color: var(--ee-text-primary);\n font-size: var(--ee-font-size-base);\n font-family: var(--ee-font-family);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.btnCancel:hover {\n background: var(--ee-bg-hover);\n border-color: var(--ee-border-color-strong);\n}\n\n.btnConfirm {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n border: 1px solid var(--ee-color-danger);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n font-size: var(--ee-font-size-base);\n font-family: var(--ee-font-family);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.btnConfirm:hover {\n background: var(--ee-color-danger-hover);\n border-color: var(--ee-color-danger-hover);\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n","import React, { useCallback, useRef, useState, useEffect } from 'react';\n\nimport { useTemplateContext, useEditorDispatch, useHistoryContext } from '../../context/EditorContext';\nimport { generateMJML } from '../../mjml/generator';\nimport { compileMJMLToHTML } from '../../mjml/compiler';\nimport { parseMJML } from '../../mjml/parser';\nimport type { ActiveTab, EmailTemplate } from '../../types';\nimport styles from '../../styles/toolbar.module.css';\nimport editorStyles from '../../styles/editor.module.css';\n\ninterface ToolbarProps {\n sidebarOpen?: boolean;\n propertiesOpen?: boolean;\n onToggleSidebar?: () => void;\n onToggleProperties?: () => void;\n}\n\n/**\n * Inner component that subscribes only to activeTab (not the full template).\n * Template is accessed via ref for export operations to avoid re-renders on every edit.\n */\nexport const Toolbar = React.memo(function Toolbar({ sidebarOpen, propertiesOpen, onToggleSidebar, onToggleProperties }: ToolbarProps) {\n const { template, activeTab } = useTemplateContext();\n const { canUndo, canRedo } = useHistoryContext();\n const dispatch = useEditorDispatch();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [exportOpen, setExportOpen] = useState(false);\n\n // Keep a ref to the current template so export callbacks don't need template as a dependency.\n // Toolbar still re-renders on template changes (due to TemplateContext), but the export\n // callbacks remain stable (empty deps), reducing unnecessary child re-renders.\n const templateRef = useRef<EmailTemplate>(template);\n templateRef.current = template;\n\n // Close export dropdown when clicking outside\n useEffect(() => {\n if (!exportOpen) return;\n const handleClick = () => setExportOpen(false);\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }, [exportOpen]);\n const handleTabChange = useCallback(\n (tab: ActiveTab) => {\n dispatch({ type: 'SET_ACTIVE_TAB', payload: tab });\n },\n [dispatch],\n );\n\n const handleUndo = useCallback(() => {\n dispatch({ type: 'UNDO' });\n }, [dispatch]);\n\n const handleRedo = useCallback(() => {\n dispatch({ type: 'REDO' });\n }, [dispatch]);\n\n const handleExportMJML = useCallback(() => {\n const mjml = generateMJML(templateRef.current!);\n const blob = new Blob([mjml], { type: 'text/xml' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'template.mjml';\n a.click();\n URL.revokeObjectURL(url);\n }, []);\n\n const handleExportHTML = useCallback(async () => {\n const mjml = generateMJML(templateRef.current!);\n const result = await compileMJMLToHTML(mjml);\n const blob = new Blob([result.html], { type: 'text/html' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'template.html';\n a.click();\n URL.revokeObjectURL(url);\n }, []);\n\n const handleExportPDF = useCallback(async () => {\n const mjml = generateMJML(templateRef.current!);\n const result = await compileMJMLToHTML(mjml);\n const printStyles = `\n <style>\n @page { margin: 0; size: auto; }\n @media print {\n html, body { margin: 0; padding: 0; }\n }\n </style>\n `;\n const htmlWithPrintStyles = result.html.replace(\n '</head>',\n `${printStyles}</head>`,\n );\n const iframe = document.createElement('iframe');\n iframe.style.position = 'fixed';\n iframe.style.left = '-9999px';\n document.body.appendChild(iframe);\n const doc = iframe.contentDocument!;\n doc.open();\n doc.write(htmlWithPrintStyles);\n doc.close();\n iframe.contentWindow!.print();\n setTimeout(() => document.body.removeChild(iframe), 1000);\n }, []);\n\n const handleImportMJML = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (event) => {\n try {\n const content = event.target?.result as string;\n const template = parseMJML(content);\n dispatch({ type: 'SET_TEMPLATE', payload: template });\n } catch (err) {\n console.error('Failed to parse MJML:', err);\n }\n };\n reader.readAsText(file);\n // Reset input\n e.target.value = '';\n },\n [dispatch],\n );\n\n return (\n <div className={`ee-toolbar ${styles.toolbar}`} role=\"toolbar\" aria-label=\"Editor toolbar\">\n <div className={`ee-toolbar-history ${styles.toolbarGroup}`} role=\"group\" aria-label=\"History\">\n <button\n className={`ee-toolbar-undo ${styles.toolbarBtn}`}\n onClick={handleUndo}\n disabled={!canUndo}\n title=\"Undo (Ctrl+Z)\"\n aria-label=\"Undo\"\n >\n Undo\n </button>\n <button\n className={`ee-toolbar-redo ${styles.toolbarBtn}`}\n onClick={handleRedo}\n disabled={!canRedo}\n title=\"Redo (Ctrl+Shift+Z)\"\n aria-label=\"Redo\"\n >\n Redo\n </button>\n </div>\n\n {/* Panel toggles — visible only on narrow screens via CSS */}\n <div className={editorStyles.panelToggle}>\n <button\n className={`ee-toolbar-toggle-sidebar ${styles.panelToggleBtn} ${sidebarOpen ? styles.panelToggleBtnActive : ''}`}\n onClick={onToggleSidebar}\n aria-label=\"Toggle sidebar\"\n aria-pressed={sidebarOpen}\n title=\"Toggle sidebar\"\n >\n ☰\n </button>\n <button\n className={`ee-toolbar-toggle-properties ${styles.panelToggleBtn} ${propertiesOpen ? styles.panelToggleBtnActive : ''}`}\n onClick={onToggleProperties}\n aria-label=\"Toggle properties\"\n aria-pressed={propertiesOpen}\n title=\"Toggle properties\"\n >\n ⚙\n </button>\n </div>\n\n <div className={`ee-toolbar-separator ${styles.toolbarSeparator}`} role=\"separator\" />\n\n <div className={`ee-toolbar-tabs ${styles.tabBar}`} role=\"tablist\" aria-label=\"Editor views\">\n {(['visual', 'source', 'preview'] as ActiveTab[]).map((tab) => (\n <button\n key={tab}\n role=\"tab\"\n aria-selected={activeTab === tab}\n className={`ee-toolbar-tab ee-toolbar-tab--${tab} ${styles.tabBtn} ${activeTab === tab ? styles.tabBtnActive : ''}`}\n onClick={() => handleTabChange(tab)}\n >\n {tab.charAt(0).toUpperCase() + tab.slice(1)}\n </button>\n ))}\n </div>\n\n <div className={styles.toolbarSpacer} />\n\n <div className={`ee-toolbar-io ${styles.toolbarGroup}`} role=\"group\" aria-label=\"Import/Export\">\n <button\n className={`ee-toolbar-import ${styles.toolbarBtn}`}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Import MJML file\"\n >\n Import\n </button>\n <div className={`ee-toolbar-export ${styles.exportWrapper}`}>\n <button\n className={`ee-toolbar-export-btn ${styles.toolbarBtn}`}\n onClick={(e) => { e.stopPropagation(); setExportOpen((prev) => !prev); }}\n aria-label=\"Export template\"\n aria-expanded={exportOpen}\n aria-haspopup=\"true\"\n >\n Export\n </button>\n {exportOpen && (\n <div className={`ee-toolbar-export-dropdown ${styles.exportDropdown}`} role=\"menu\">\n <button className={`ee-toolbar-export-mjml ${styles.exportDropdownItem}`} onClick={handleExportMJML} role=\"menuitem\">MJML</button>\n <button className={`ee-toolbar-export-html ${styles.exportDropdownItem}`} onClick={handleExportHTML} role=\"menuitem\">HTML</button>\n <button className={`ee-toolbar-export-pdf ${styles.exportDropdownItem}`} onClick={handleExportPDF} role=\"menuitem\">PDF</button>\n </div>\n )}\n </div>\n </div>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".mjml,.xml,.txt\"\n onChange={handleImportMJML}\n style={{ display: 'none' }}\n aria-hidden=\"true\"\n />\n </div>\n );\n});\n","const ALLOWED_TAGS = new Set([\n 'p', 'br', 'b', 'strong', 'i', 'em', 'u', 'a', 'span',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li', 'blockquote',\n 'table', 'thead', 'tbody', 'tr', 'td', 'th',\n 'img', 'hr', 'div', 'sup', 'sub',\n]);\n\nconst ALLOWED_ATTRIBUTES = new Set([\n 'href', 'src', 'alt', 'title', 'style', 'class',\n 'width', 'height', 'target', 'rel',\n 'align', 'valign', 'bgcolor', 'border',\n 'cellpadding', 'cellspacing', 'colspan', 'rowspan',\n]);\n\n/** Patterns that indicate dangerous CSS values */\nconst DANGEROUS_CSS_PATTERN = /expression\\s*\\(|javascript\\s*:|url\\s*\\(\\s*['\"]?\\s*(?:javascript|data|vbscript)\\s*:/i;\n\n/** Allowed CSS properties for email content */\nconst ALLOWED_CSS_PROPERTIES = new Set([\n 'color', 'background-color', 'background', 'font-family', 'font-size',\n 'font-weight', 'font-style', 'text-decoration', 'text-align', 'text-transform',\n 'line-height', 'letter-spacing', 'word-spacing',\n 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'border', 'border-top', 'border-right', 'border-bottom', 'border-left',\n 'border-color', 'border-width', 'border-style', 'border-radius',\n 'width', 'max-width', 'min-width', 'height', 'max-height', 'min-height',\n 'display', 'vertical-align', 'white-space', 'overflow',\n 'opacity', 'visibility',\n 'border-collapse', 'border-spacing', 'table-layout',\n]);\n\n/**\n * Sanitize a CSS style string by removing dangerous properties and values.\n * Returns the sanitized style string, or empty string if nothing is safe.\n */\nexport function sanitizeStyle(style: string): string {\n // Quick reject: check for dangerous patterns in the whole string\n if (DANGEROUS_CSS_PATTERN.test(style)) {\n // Parse individual declarations and filter\n return filterStyleDeclarations(style);\n }\n return filterStyleDeclarations(style);\n}\n\nfunction filterStyleDeclarations(style: string): string {\n const declarations = style.split(';');\n const safe: string[] = [];\n\n for (const decl of declarations) {\n const trimmed = decl.trim();\n if (!trimmed) continue;\n\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx === -1) continue;\n\n const property = trimmed.slice(0, colonIdx).trim().toLowerCase();\n const value = trimmed.slice(colonIdx + 1).trim();\n\n // Only allow known safe CSS properties\n if (!ALLOWED_CSS_PROPERTIES.has(property)) continue;\n\n // Reject dangerous values\n if (DANGEROUS_CSS_PATTERN.test(value)) continue;\n\n // Reject url() in values except for safe schemes\n if (/url\\s*\\(/i.test(value)) continue;\n\n safe.push(`${property}: ${value}`);\n }\n\n return safe.join('; ');\n}\n\nexport function sanitizeHTML(html: string): string {\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n sanitizeNode(doc.body);\n return doc.body.innerHTML;\n}\n\nfunction sanitizeNode(node: Node): void {\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType === Node.ELEMENT_NODE) {\n const element = child as Element;\n const tagName = element.tagName.toLowerCase();\n\n if (!ALLOWED_TAGS.has(tagName)) {\n // Replace disallowed elements with their text content\n const text = document.createTextNode(element.textContent ?? '');\n node.replaceChild(text, child);\n continue;\n }\n\n // Remove disallowed attributes\n const attributes = Array.from(element.attributes);\n for (const attr of attributes) {\n if (!ALLOWED_ATTRIBUTES.has(attr.name.toLowerCase())) {\n element.removeAttribute(attr.name);\n }\n }\n\n // Sanitize style attribute\n if (element.hasAttribute('style')) {\n const rawStyle = element.getAttribute('style') ?? '';\n const safeStyle = sanitizeStyle(rawStyle);\n if (safeStyle) {\n element.setAttribute('style', safeStyle);\n } else {\n element.removeAttribute('style');\n }\n }\n\n // Sanitize href to prevent javascript: URLs\n if (element.hasAttribute('href')) {\n const href = element.getAttribute('href') ?? '';\n if (href.toLowerCase().startsWith('javascript:') || href.toLowerCase().startsWith('data:')) {\n element.setAttribute('href', '#');\n }\n }\n\n // Sanitize src to prevent javascript: and data: URLs\n if (element.hasAttribute('src')) {\n const src = element.getAttribute('src') ?? '';\n if (src.toLowerCase().startsWith('javascript:') || src.toLowerCase().startsWith('data:')) {\n element.removeAttribute('src');\n }\n }\n\n sanitizeNode(child);\n }\n }\n}\n\nexport function escapeHTML(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\nconst SAFE_URL_PATTERN = /^(https?:\\/\\/|mailto:|tel:|#|\\/)/i;\n\n/**\n * Returns true if the URL scheme is safe (http, https, mailto, tel, fragment, relative path).\n * Rejects javascript:, data:, vbscript:, and other dangerous schemes.\n */\nexport function isSafeURL(url: string): boolean {\n const trimmed = url.trim();\n if (!trimmed) return false;\n if (trimmed.startsWith('/') || trimmed.startsWith('#') || trimmed.startsWith('?')) return true;\n return SAFE_URL_PATTERN.test(trimmed);\n}\n","import type { EmailTemplate, Section, Column, Block } from '../types';\nimport { blockGeneratorRegistry, registerBlockGenerator } from '../registry';\nimport { escapeHTML, sanitizeHTML, isSafeURL } from '../utils/sanitize';\n\nexport function generateMJML(template: EmailTemplate): string {\n const { globalStyles, sections } = template;\n const lines: string[] = [];\n\n const headMetadata = template.headMetadata;\n\n lines.push('<mjml>');\n lines.push(' <mj-head>');\n if (headMetadata?.title) {\n lines.push(` <mj-title>${escapeHTML(headMetadata.title)}</mj-title>`);\n }\n if (headMetadata?.previewText) {\n lines.push(` <mj-preview>${escapeHTML(headMetadata.previewText)}</mj-preview>`);\n }\n lines.push(' <mj-attributes>');\n lines.push(` <mj-all font-family=\"${escapeAttr(globalStyles.fontFamily)}\" />`);\n lines.push(' </mj-attributes>');\n if (headMetadata?.headStyles) {\n for (const style of headMetadata.headStyles) {\n // Sanitize: strip any closing mj-style tags to prevent MJML injection\n const safe = style.replace(/<\\/?mj-/gi, '');\n lines.push(` <mj-style>${safe}</mj-style>`);\n }\n }\n lines.push(' </mj-head>');\n const bodyAttrs = buildAttrs({\n 'background-color': globalStyles.backgroundColor || undefined,\n width: `${globalStyles.width}px`,\n });\n lines.push(` <mj-body${bodyAttrs}>`);\n\n for (const section of sections) {\n lines.push(generateSection(section, ' '));\n }\n\n lines.push(' </mj-body>');\n lines.push('</mjml>');\n\n return lines.join('\\n');\n}\n\nfunction generateSection(section: Section, indent: string): string {\n // If section wraps a single hero block, output mj-hero instead of mj-section\n if (\n section.columns.length === 1 &&\n section.columns[0].blocks.length === 1 &&\n section.columns[0].blocks[0].type === 'hero'\n ) {\n return generateHeroAsSection(section.columns[0].blocks[0], indent);\n }\n\n const { properties } = section;\n const bgColor = properties.backgroundColor;\n const attrs = buildAttrs({\n 'background-color': bgColor && bgColor !== 'transparent' ? bgColor : undefined,\n padding: properties.padding,\n 'border-radius': properties.borderRadius,\n 'full-width': properties.fullWidth ? 'full-width' : undefined,\n 'background-url': properties.backgroundImage || undefined,\n 'background-size': properties.backgroundSize || undefined,\n 'background-repeat': properties.backgroundRepeat || undefined,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-section${attrs}>`);\n\n for (const column of section.columns) {\n lines.push(generateColumn(column, indent + ' '));\n }\n\n lines.push(`${indent}</mj-section>`);\n return lines.join('\\n');\n}\n\nfunction generateHeroAsSection(block: Block, indent: string): string {\n const p = block.properties;\n const heroAttrs = buildAttrs({\n 'background-color': p.backgroundColor,\n 'background-url': p.backgroundImage || undefined,\n padding: p.padding,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-hero${heroAttrs}>`);\n\n if (p.heading) {\n const headingAttrs = buildAttrs({\n align: p.align,\n color: p.headingColor,\n 'font-size': p.headingFontSize,\n 'font-weight': 'bold',\n });\n lines.push(`${indent} <mj-text${headingAttrs}><h2 style=\"margin:0\">${escapeHTML(p.heading)}</h2></mj-text>`);\n }\n\n if (p.subtext) {\n const subtextAttrs = buildAttrs({\n align: p.align,\n color: p.subtextColor,\n 'font-size': p.subtextFontSize,\n });\n lines.push(`${indent} <mj-text${subtextAttrs}>${escapeHTML(p.subtext)}</mj-text>`);\n }\n\n if (p.buttonText) {\n const buttonAttrs = buildAttrs({\n href: safeHref(p.buttonHref),\n 'background-color': p.buttonBackgroundColor,\n color: p.buttonColor,\n 'border-radius': p.buttonBorderRadius,\n align: p.align,\n });\n lines.push(`${indent} <mj-button${buttonAttrs}>${escapeHTML(p.buttonText)}</mj-button>`);\n }\n\n lines.push(`${indent}</mj-hero>`);\n return lines.join('\\n');\n}\n\nfunction generateColumn(column: Column, indent: string): string {\n const attrs = buildAttrs({ width: column.width });\n const lines: string[] = [];\n lines.push(`${indent}<mj-column${attrs}>`);\n\n for (const block of column.blocks) {\n lines.push(generateBlock(block, indent + ' '));\n }\n\n lines.push(`${indent}</mj-column>`);\n return lines.join('\\n');\n}\n\n// Register built-in generators\nregisterBlockGenerator('text', generateTextBlock);\nregisterBlockGenerator('button', generateButtonBlock);\nregisterBlockGenerator('image', generateImageBlock);\nregisterBlockGenerator('divider', generateDividerBlock);\nregisterBlockGenerator('spacer', generateSpacerBlock);\nregisterBlockGenerator('social', generateSocialBlock);\nregisterBlockGenerator('html', generateHtmlBlock);\nregisterBlockGenerator('video', generateVideoBlock);\nregisterBlockGenerator('heading', generateHeadingBlock);\nregisterBlockGenerator('countdown', generateCountdownBlock);\nregisterBlockGenerator('menu', generateMenuBlock);\nregisterBlockGenerator('hero', generateHeroBlock);\n\nfunction generateBlock(block: Block, indent: string): string {\n const generator = blockGeneratorRegistry[block.type];\n return generator ? generator(block, indent) : '';\n}\n\nfunction generateTextBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n color: p.color,\n 'line-height': p.lineHeight,\n padding: p.padding,\n align: p.align,\n 'font-weight': p.fontWeight && p.fontWeight !== 'normal' ? p.fontWeight : undefined,\n 'text-transform': p.textTransform && p.textTransform !== 'none' ? p.textTransform : undefined,\n 'letter-spacing': p.letterSpacing && p.letterSpacing !== 'normal' ? p.letterSpacing : undefined,\n });\n\n const content = stripVariableChips(p.content || '');\n return `${indent}<mj-text${attrs}>${content}</mj-text>`;\n}\n\nfunction generateButtonBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n href: safeHref(p.href),\n 'background-color': p.backgroundColor,\n color: p.color,\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n 'border-radius': p.borderRadius,\n padding: p.padding,\n 'inner-padding': p.innerPadding,\n align: p.align,\n width: p.width !== 'auto' ? p.width : undefined,\n 'font-weight': p.fontWeight && p.fontWeight !== 'normal' ? p.fontWeight : undefined,\n 'text-transform': p.textTransform && p.textTransform !== 'none' ? p.textTransform : undefined,\n 'letter-spacing': p.letterSpacing && p.letterSpacing !== 'normal' ? p.letterSpacing : undefined,\n });\n\n return `${indent}<mj-button${attrs}>${escapeHTML(p.text)}</mj-button>`;\n}\n\nfunction generateImageBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n src: safeHref(p.src),\n alt: p.alt,\n href: p.href ? safeHref(p.href) : undefined,\n width: p.width,\n height: p.height !== 'auto' ? p.height : undefined,\n padding: p.padding,\n align: p.align,\n 'fluid-on-mobile': p.fluidOnMobile ? 'true' : undefined,\n });\n\n return `${indent}<mj-image${attrs} />`;\n}\n\nfunction generateDividerBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n 'border-color': p.borderColor,\n 'border-width': p.borderWidth,\n 'border-style': p.borderStyle,\n padding: p.padding,\n width: p.width,\n });\n\n return `${indent}<mj-divider${attrs} />`;\n}\n\nfunction generateSpacerBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({ height: p.height });\n return `${indent}<mj-spacer${attrs} />`;\n}\n\nfunction generateSocialBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n mode: p.mode,\n align: p.align,\n 'icon-size': p.iconSize,\n 'icon-padding': p.iconPadding,\n padding: p.padding,\n 'font-size': p.fontSize,\n color: p.color,\n 'border-radius': p.borderRadius,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-social${attrs}>`);\n\n for (const element of p.elements) {\n const elAttrs = buildAttrs({\n name: element.name,\n href: safeHref(element.href),\n src: element.src ? safeHref(element.src) : undefined,\n 'background-color': element.backgroundColor,\n color: element.color,\n });\n const content = element.content ? escapeHTML(element.content) : '';\n lines.push(`${indent} <mj-social-element${elAttrs}>${content}</mj-social-element>`);\n }\n\n lines.push(`${indent}</mj-social>`);\n return lines.join('\\n');\n}\n\nfunction generateHtmlBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({ padding: p.padding, 'css-class': 'ee-block-html' });\n const content = sanitizeHTML(p.content || '');\n return `${indent}<mj-text${attrs}>${content}</mj-text>`;\n}\n\nfunction generateVideoBlock(block: Block, indent: string): string {\n const p = block.properties;\n const thumbnailUrl = p.thumbnailUrl || getAutoThumbnail(p.src);\n const attrs = buildAttrs({\n src: safeHref(thumbnailUrl),\n href: safeHref(p.src),\n alt: p.alt,\n padding: p.padding,\n align: p.align,\n 'css-class': 'ee-block-video',\n });\n return `${indent}<mj-image${attrs} />`;\n}\n\nfunction getAutoThumbnail(url: string): string {\n if (!url) return '';\n const ytMatch = url.match(/(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/);\n if (ytMatch) return `https://img.youtube.com/vi/${ytMatch[1]}/hqdefault.jpg`;\n return '';\n}\n\nfunction generateHeadingBlock(block: Block, indent: string): string {\n const p = block.properties;\n const level = p.level || 'h2';\n const attrs = buildAttrs({\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n color: p.color,\n 'line-height': p.lineHeight,\n padding: p.padding,\n align: p.align,\n 'font-weight': p.fontWeight && p.fontWeight !== 'normal' ? p.fontWeight : undefined,\n 'text-transform': p.textTransform && p.textTransform !== 'none' ? p.textTransform : undefined,\n 'letter-spacing': p.letterSpacing && p.letterSpacing !== 'normal' ? p.letterSpacing : undefined,\n 'css-class': `ee-block-heading ee-heading-${level}`,\n });\n\n const content = stripVariableChips(p.content || '');\n return `${indent}<mj-text${attrs}><${level}>${content}</${level}></mj-text>`;\n}\n\nfunction generateCountdownBlock(block: Block, indent: string): string {\n const p = block.properties;\n const target = new Date(p.targetDate).getTime();\n const now = Date.now();\n const total = Math.max(0, target - now);\n const days = Math.floor(total / (1000 * 60 * 60 * 24));\n const hours = Math.floor((total / (1000 * 60 * 60)) % 24);\n const minutes = Math.floor((total / (1000 * 60)) % 60);\n const seconds = Math.floor((total / 1000) % 60);\n\n const digitStyle = `display:inline-block;background-color:${escapeAttr(p.digitBackgroundColor)};color:${escapeAttr(p.digitColor)};font-size:${escapeAttr(p.fontSize)};font-weight:bold;padding:8px 12px;border-radius:6px;min-width:40px;text-align:center`;\n const unitStyle = `font-size:11px;color:${escapeAttr(p.labelColor)};text-transform:uppercase;letter-spacing:0.5px`;\n\n const units = [\n { value: days, label: 'Days' },\n { value: hours, label: 'Hours' },\n { value: minutes, label: 'Minutes' },\n { value: seconds, label: 'Seconds' },\n ];\n\n const cells = units\n .map(\n (u) =>\n `<td style=\"padding:0 6px;text-align:center\"><div style=\"${digitStyle}\">${String(u.value).padStart(2, '0')}</div><div style=\"${unitStyle}\">${u.label}</div></td>`,\n )\n .join('');\n\n let html = '';\n if (p.label) {\n html += `<div style=\"color:${escapeAttr(p.labelColor)};margin-bottom:8px\">${escapeHTML(p.label)}</div>`;\n }\n html += `<table cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"margin:0 auto\"><tr>${cells}</tr></table>`;\n\n // Embed countdown metadata as data attributes for round-trip parsing\n const attrs = buildAttrs({\n padding: p.padding,\n align: p.align,\n 'css-class': 'ee-block-countdown',\n });\n const metaJson = JSON.stringify({\n targetDate: p.targetDate,\n label: p.label,\n digitBackgroundColor: p.digitBackgroundColor,\n digitColor: p.digitColor,\n labelColor: p.labelColor,\n fontSize: p.fontSize,\n });\n const meta = `<!--ee-countdown:${escapeAttr(metaJson)}-->`;\n return `${indent}<mj-text${attrs}>${meta}${html}</mj-text>`;\n}\n\nfunction generateMenuBlock(block: Block, indent: string): string {\n const p = block.properties;\n const attrs = buildAttrs({\n align: p.align,\n hamburger: p.hamburger ? 'hamburger' : undefined,\n 'ico-color': p.hamburger ? p.iconColor : undefined,\n padding: p.padding,\n });\n\n const lines: string[] = [];\n lines.push(`${indent}<mj-navbar${attrs}>`);\n\n for (const item of p.items) {\n const linkAttrs = buildAttrs({\n href: safeHref(item.href),\n color: p.color,\n 'font-family': p.fontFamily,\n 'font-size': p.fontSize,\n });\n lines.push(`${indent} <mj-navbar-link${linkAttrs}>${escapeHTML(item.text)}</mj-navbar-link>`);\n }\n\n lines.push(`${indent}</mj-navbar>`);\n return lines.join('\\n');\n}\n\nfunction generateHeroBlock(block: Block, indent: string): string {\n const p = block.properties;\n\n let html = '';\n if (p.heading) {\n html += `<h2 style=\"color:${escapeAttr(p.headingColor)};font-size:${escapeAttr(p.headingFontSize)};font-weight:bold;line-height:1.2;margin:0 0 16px\">${escapeHTML(p.heading)}</h2>`;\n }\n if (p.subtext) {\n html += `<p style=\"color:${escapeAttr(p.subtextColor)};font-size:${escapeAttr(p.subtextFontSize)};line-height:1.5;margin:0 0 24px\">${escapeHTML(p.subtext)}</p>`;\n }\n if (p.buttonText) {\n html += `<a href=\"${escapeAttr(safeHref(p.buttonHref))}\" style=\"display:inline-block;background-color:${escapeAttr(p.buttonBackgroundColor)};color:${escapeAttr(p.buttonColor)};border-radius:${escapeAttr(p.buttonBorderRadius)};padding:12px 28px;font-weight:600;font-size:16px;text-decoration:none\">${escapeHTML(p.buttonText)}</a>`;\n }\n\n const attrs = buildAttrs({ padding: p.padding, align: p.align });\n return `${indent}<mj-text${attrs}>${html}</mj-text>`;\n}\n\n// ---- Helpers ----\n\n/**\n * Strip TipTap variable chip wrappers from content HTML.\n * Converts `<span class=\"ee-variable-chip\" data-variable-key=\"name\" contenteditable=\"false\">{{ name }}</span>`\n * to plain `{{ name }}`.\n * Uses data-variable-key attribute as source of truth to handle any inner HTML.\n */\nfunction stripVariableChips(html: string): string {\n return html.replace(\n /<span[^>]*data-variable-key=\"([^\"]*)\"[^>]*>[\\s\\S]*?<\\/span>/g,\n (_match, key) => `{{ ${key} }}`,\n );\n}\n\nfunction buildAttrs(obj: Record<string, string | undefined>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && value !== '') {\n parts.push(` ${key}=\"${escapeAttr(value)}\"`);\n }\n }\n return parts.join('');\n}\n\nfunction escapeAttr(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\n/** Sanitize href: return '#' for dangerous URL schemes, pass through safe ones. */\nfunction safeHref(url: string | undefined): string {\n if (!url) return '#';\n return isSafeURL(url) ? url : '#';\n}\n","export interface CompileResult {\n html: string;\n errors: CompileError[];\n}\n\nexport interface CompileError {\n line: number;\n message: string;\n tagName: string;\n}\n\nlet mjmlBrowser: any = null;\n\nasync function loadMjmlBrowser(): Promise<any> {\n if (mjmlBrowser) return mjmlBrowser;\n try {\n mjmlBrowser = (await import('mjml-browser')).default;\n return mjmlBrowser;\n } catch {\n return null;\n }\n}\n\nexport async function compileMJMLToHTML(mjmlString: string): Promise<CompileResult> {\n const mjml = await loadMjmlBrowser();\n\n if (!mjml) {\n // Fallback: wrap in basic HTML without full MJML compilation\n return {\n html: wrapFallbackHTML(mjmlString),\n errors: [{ line: 0, message: 'mjml-browser not available, using fallback rendering', tagName: '' }],\n };\n }\n\n try {\n const result = mjml(mjmlString, {\n validationLevel: 'soft',\n minify: false,\n });\n\n return {\n html: result.html,\n errors: (result.errors ?? []).map((err: any) => ({\n line: err.line ?? 0,\n message: err.message ?? 'Unknown error',\n tagName: err.tagName ?? '',\n })),\n };\n } catch (err) {\n return {\n html: '',\n errors: [{ line: 0, message: String(err), tagName: '' }],\n };\n }\n}\n\nfunction wrapFallbackHTML(mjml: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <style>\n body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f4f4f4; }\n .fallback-notice { text-align: center; padding: 20px; color: #666; font-size: 14px; }\n pre { white-space: pre-wrap; word-wrap: break-word; background: #fff; padding: 20px; border-radius: 4px; }\n </style>\n</head>\n<body>\n <div class=\"fallback-notice\">\n <p>Install <code>mjml-browser</code> for full HTML preview.</p>\n </div>\n <pre>${mjml.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>\n</body>\n</html>`;\n}\n","import type { EmailTemplate, Section, Column, Block, GlobalStyles, HeadMetadata, SocialElement, MenuItem } from '../types';\nimport { DEFAULT_SECTION_PROPERTIES, DEFAULT_BLOCK_PROPERTIES, DEFAULT_HEAD_METADATA } from '../constants';\nimport { generateSectionId, generateColumnId, generateBlockId } from '../utils/id';\nimport { blockParserRegistry, registerBlockParser } from '../registry';\n\n/**\n * MJML's official built-in defaults. Used as parser fallbacks so that\n * round-tripping MJML preserves the original visual output.\n * These are separate from DEFAULT_BLOCK_PROPERTIES (editor defaults for new blocks).\n */\nconst MJML_DEFAULTS = {\n global: {\n backgroundColor: '',\n width: 600,\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n },\n text: {\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n fontSize: '13px',\n color: '#000000',\n lineHeight: '1',\n padding: '10px 25px',\n align: 'left',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n },\n button: {\n text: 'Click me',\n href: '#',\n backgroundColor: '#414141',\n color: '#ffffff',\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n fontSize: '13px',\n borderRadius: '3px',\n padding: '10px 25px',\n innerPadding: '10px 25px',\n align: 'center',\n width: 'auto',\n fontWeight: 'normal',\n textTransform: 'none',\n letterSpacing: 'normal',\n },\n image: {\n src: '',\n alt: '',\n href: '',\n width: '600px',\n height: 'auto',\n padding: '10px 25px',\n align: 'center',\n },\n divider: {\n borderColor: '#000000',\n borderWidth: '4px',\n borderStyle: 'solid',\n padding: '10px 25px',\n width: '100%',\n },\n spacer: {\n height: '20px',\n },\n social: {\n mode: 'horizontal',\n align: 'center',\n iconSize: '20px',\n iconPadding: '5px',\n padding: '10px 25px',\n fontSize: '13px',\n color: '#333333',\n borderRadius: '3px',\n },\n menu: {\n align: 'center',\n fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',\n fontSize: '13px',\n color: '#333333',\n padding: '10px 25px',\n },\n} as const;\n\nexport function parseMJML(mjmlString: string): EmailTemplate {\n const parser = new DOMParser();\n const preprocessed = fixVoidElements(decodeHtmlEntities(mjmlString));\n const doc = parser.parseFromString(preprocessed, 'text/xml');\n\n // Check for XML parse errors\n const parseError = doc.querySelector('parsererror');\n if (parseError) {\n throw new Error(`Invalid MJML: ${parseError.textContent?.slice(0, 200)}`);\n }\n\n const mjmlEl = doc.querySelector('mjml');\n if (!mjmlEl) {\n throw new Error('Invalid MJML: missing <mjml> root element');\n }\n\n const globalStyles = parseGlobalStyles(doc);\n const sections = parseSections(doc);\n const headMetadata = parseHeadMetadata(doc);\n\n return { sections, globalStyles, headMetadata };\n}\n\n/**\n * Decode HTML named entities (e.g. &copy; &nbsp; &mdash;) into their Unicode characters.\n * XML only supports &amp; &lt; &gt; &apos; &quot; — all others cause parse errors.\n * Numeric entities (&#123; &#xA0;) are valid XML and left untouched.\n */\nfunction decodeHtmlEntities(mjml: string): string {\n return mjml.replace(/&([a-zA-Z][a-zA-Z0-9]*);/g, (match, entity) => {\n // Preserve the 5 XML built-in entities\n if (entity === 'amp' || entity === 'lt' || entity === 'gt' || entity === 'apos' || entity === 'quot') {\n return match;\n }\n // Decode HTML entity using a temporary element\n const tmp = document.createElement('span');\n tmp.innerHTML = match;\n return tmp.textContent || match;\n });\n}\n\n/**\n * Self-close HTML void elements that are not already self-closed.\n * XML requires <br/> but HTML allows <br>. MJML content (mj-text etc.)\n * often contains HTML-style void elements that break XML parsing.\n */\nfunction fixVoidElements(mjml: string): string {\n // Match void elements that are NOT already self-closed (no /> at end)\n return mjml.replace(\n /<(br|hr|img|input|meta|link|col|area|base|embed|param|source|track|wbr)\\b([^>]*?)(?<!\\/)>/gi,\n '<$1$2/>',\n );\n}\n\n/**\n * Convert legacy HTML elements (<font>, etc.) to modern <span style=\"...\">\n * for TipTap compatibility. Uses DOM parsing for robustness.\n */\nfunction convertLegacyHtml(html: string): string {\n if (!html || (!html.includes('<font') && !html.includes('<FONT'))) return html;\n\n const FONT_SIZE_MAP: Record<string, string> = {\n '1': '10px', '2': '13px', '3': '16px',\n '4': '18px', '5': '24px', '6': '32px', '7': '48px',\n };\n\n const doc = document.createElement('div');\n doc.innerHTML = html;\n\n const fonts = doc.querySelectorAll('font');\n for (let i = 0; i < fonts.length; i++) {\n const font = fonts[i];\n const span = document.createElement('span');\n const styles: string[] = [];\n\n const color = font.getAttribute('color');\n if (color) styles.push(`color: ${color}`);\n\n const size = font.getAttribute('size');\n if (size && FONT_SIZE_MAP[size]) {\n styles.push(`font-size: ${FONT_SIZE_MAP[size]}`);\n }\n\n const face = font.getAttribute('face');\n if (face) styles.push(`font-family: ${face}`);\n\n if (styles.length > 0) {\n span.setAttribute('style', styles.join('; '));\n }\n\n // Move all children from <font> to <span>\n while (font.firstChild) {\n span.appendChild(font.firstChild);\n }\n font.parentNode?.replaceChild(span, font);\n }\n\n return doc.innerHTML;\n}\n\nfunction parseGlobalStyles(doc: Document): GlobalStyles {\n // Start from MJML's own defaults (not editor defaults) for faithful round-tripping\n const styles: GlobalStyles = {\n backgroundColor: MJML_DEFAULTS.global.backgroundColor,\n width: MJML_DEFAULTS.global.width,\n fontFamily: MJML_DEFAULTS.global.fontFamily,\n };\n const mjBody = doc.querySelector('mj-body');\n if (mjBody) {\n const bgColor = mjBody.getAttribute('background-color');\n if (bgColor) styles.backgroundColor = bgColor;\n const width = mjBody.getAttribute('width');\n if (width) styles.width = parseInt(width, 10) || 600;\n }\n\n const mjAttributes = doc.querySelector('mj-attributes');\n if (mjAttributes) {\n const mjAll = mjAttributes.querySelector('mj-all');\n if (mjAll) {\n const fontFamily = mjAll.getAttribute('font-family');\n if (fontFamily) styles.fontFamily = fontFamily;\n }\n }\n\n return styles;\n}\n\nfunction parseHeadMetadata(doc: Document): HeadMetadata {\n const metadata: HeadMetadata = { ...DEFAULT_HEAD_METADATA, headStyles: [] };\n const mjHead = doc.querySelector('mj-head');\n if (!mjHead) return metadata;\n\n const titleEl = mjHead.querySelector('mj-title');\n if (titleEl) {\n metadata.title = titleEl.textContent ?? '';\n }\n\n const previewEl = mjHead.querySelector('mj-preview');\n if (previewEl) {\n metadata.previewText = previewEl.textContent ?? '';\n }\n\n const styleEls = mjHead.querySelectorAll('mj-style');\n for (let i = 0; i < styleEls.length; i++) {\n const content = styleEls[i].textContent ?? '';\n if (content.trim()) {\n metadata.headStyles.push(content);\n }\n }\n\n return metadata;\n}\n\nfunction parseSections(doc: Document): Section[] {\n const mjBody = doc.querySelector('mj-body');\n if (!mjBody) return [];\n\n const sections: Section[] = [];\n\n // Walk direct children of mj-body: handle mj-section, mj-hero, and mj-wrapper\n for (let i = 0; i < mjBody.children.length; i++) {\n const child = mjBody.children[i];\n const tag = child.tagName.toLowerCase();\n\n if (tag === 'mj-section') {\n sections.push(parseSectionElement(child));\n } else if (tag === 'mj-hero') {\n sections.push(parseHeroElement(child));\n } else if (tag === 'mj-wrapper') {\n // mj-wrapper groups multiple mj-sections — unwrap them\n const innerSections = child.querySelectorAll(':scope > mj-section');\n for (let j = 0; j < innerSections.length; j++) {\n sections.push(parseSectionElement(innerSections[j]));\n }\n }\n }\n\n return sections;\n}\n\nfunction parseSectionElement(el: Element): Section {\n const id = generateSectionId();\n const properties: any = {\n backgroundColor: el.getAttribute('background-color') ?? DEFAULT_SECTION_PROPERTIES.backgroundColor,\n padding: resolvePadding(el, DEFAULT_SECTION_PROPERTIES.padding),\n borderRadius: el.getAttribute('border-radius') ?? DEFAULT_SECTION_PROPERTIES.borderRadius,\n fullWidth: el.getAttribute('full-width') === 'full-width',\n };\n const bgUrl = el.getAttribute('background-url');\n if (bgUrl) properties.backgroundImage = bgUrl;\n const bgSize = el.getAttribute('background-size');\n if (bgSize) properties.backgroundSize = bgSize;\n const bgRepeat = el.getAttribute('background-repeat');\n if (bgRepeat) properties.backgroundRepeat = bgRepeat;\n\n // Collect columns from direct mj-column children and also from mj-group children\n const columnEls: Element[] = [];\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i];\n const tag = child.tagName.toLowerCase();\n if (tag === 'mj-column') {\n columnEls.push(child);\n } else if (tag === 'mj-group') {\n // mj-group wraps columns — extract them\n const groupCols = child.querySelectorAll(':scope > mj-column');\n for (let j = 0; j < groupCols.length; j++) {\n columnEls.push(groupCols[j]);\n }\n }\n }\n\n let columns: Column[];\n\n if (columnEls.length === 0) {\n // No columns, treat direct children as blocks in a single 100% column\n columns = [{\n id: generateColumnId(),\n width: '100%',\n blocks: parseBlockElements(el),\n }];\n } else {\n // MJML auto-distributes columns when width isn't specified.\n // Calculate the default width based on sibling count.\n const autoWidth = `${Math.round((100 / columnEls.length) * 100) / 100}%`;\n columns = columnEls.map((colEl) => parseColumnElement(colEl, autoWidth));\n }\n\n return { id, columns, properties };\n}\n\n/**\n * Parse mj-hero as a section. mj-hero doesn't use mj-column —\n * its direct children (mj-text, mj-image, mj-button) become blocks\n * in a single 100% column. The background-url maps to backgroundImage.\n */\nfunction parseHeroElement(el: Element): Section {\n const id = generateSectionId();\n\n // Check if hero has mj-image children — if so, parse as a regular section\n // with individual blocks to preserve all content (images, text, buttons).\n // Otherwise, parse as a single structured hero block.\n let hasImages = false;\n for (let i = 0; i < el.children.length; i++) {\n if (el.children[i].tagName.toLowerCase() === 'mj-image') {\n hasImages = true;\n break;\n }\n }\n\n if (hasImages) {\n // Complex hero with images → section with background + individual blocks\n const properties: any = {\n backgroundColor: el.getAttribute('background-color') ?? DEFAULT_SECTION_PROPERTIES.backgroundColor,\n padding: resolvePadding(el, DEFAULT_SECTION_PROPERTIES.padding),\n borderRadius: '0px',\n fullWidth: false,\n };\n const bgUrl = el.getAttribute('background-url');\n if (bgUrl) properties.backgroundImage = bgUrl;\n\n return {\n id,\n columns: [{\n id: generateColumnId(),\n width: '100%',\n blocks: parseBlockElements(el),\n }],\n properties,\n };\n }\n\n // Simple hero (text/button only) → structured hero block\n const properties: any = {\n backgroundColor: DEFAULT_SECTION_PROPERTIES.backgroundColor,\n padding: '0',\n borderRadius: '0px',\n fullWidth: false,\n };\n\n const heroBlock = buildHeroBlock(el);\n\n return {\n id,\n columns: [{\n id: generateColumnId(),\n width: '100%',\n blocks: [heroBlock],\n }],\n properties,\n };\n}\n\n/**\n * Build a hero block from an mj-hero element.\n * Extracts heading, subtext, and button from child mj-text/mj-button elements.\n */\nfunction buildHeroBlock(el: Element): Block {\n const defaults = DEFAULT_BLOCK_PROPERTIES.hero;\n\n let heading = '';\n let subtext = '';\n let buttonText = '';\n let buttonHref = defaults.buttonHref;\n let headingColor = defaults.headingColor;\n let headingFontSize = defaults.headingFontSize;\n let subtextColor = defaults.subtextColor;\n let subtextFontSize = defaults.subtextFontSize;\n let buttonBackgroundColor = defaults.buttonBackgroundColor;\n let buttonColor = defaults.buttonColor;\n let buttonBorderRadius = defaults.buttonBorderRadius;\n let align: string = defaults.align;\n\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i];\n const tag = child.tagName.toLowerCase();\n\n if (tag === 'mj-text') {\n const content = child.innerHTML?.trim() ?? '';\n const textContent = child.textContent?.trim() ?? '';\n // If content contains a heading tag, treat as heading\n if (/<h[1-4]/i.test(content) && !heading) {\n heading = textContent;\n headingColor = child.getAttribute('color') ?? defaults.headingColor;\n headingFontSize = child.getAttribute('font-size') ?? defaults.headingFontSize;\n } else if (!subtext) {\n subtext = textContent;\n subtextColor = child.getAttribute('color') ?? defaults.subtextColor;\n subtextFontSize = child.getAttribute('font-size') ?? defaults.subtextFontSize;\n }\n const a = child.getAttribute('align');\n if (a) align = a;\n } else if (tag === 'mj-button') {\n buttonText = child.textContent?.trim() ?? '';\n buttonHref = child.getAttribute('href') ?? defaults.buttonHref;\n buttonBackgroundColor = child.getAttribute('background-color') ?? defaults.buttonBackgroundColor;\n buttonColor = child.getAttribute('color') ?? defaults.buttonColor;\n buttonBorderRadius = child.getAttribute('border-radius') ?? defaults.buttonBorderRadius;\n const a = child.getAttribute('align');\n if (a) align = a;\n }\n // mj-image children are not mapped to hero block properties\n }\n\n // If no heading was found but there's a plain mj-text, promote first text to heading\n if (!heading && subtext) {\n heading = subtext;\n headingColor = subtextColor;\n headingFontSize = subtextFontSize;\n subtext = '';\n subtextColor = defaults.subtextColor;\n subtextFontSize = defaults.subtextFontSize;\n }\n\n return {\n id: generateBlockId(),\n type: 'hero',\n properties: {\n heading,\n subtext,\n buttonText,\n buttonHref,\n headingColor,\n headingFontSize,\n subtextColor,\n subtextFontSize,\n buttonBackgroundColor,\n buttonColor,\n buttonBorderRadius,\n align,\n padding: resolvePadding(el, defaults.padding),\n backgroundImage: el.getAttribute('background-url') ?? defaults.backgroundImage,\n backgroundColor: el.getAttribute('background-color') ?? defaults.backgroundColor,\n },\n };\n}\n\nfunction parseColumnElement(el: Element, defaultWidth: string): Column {\n return {\n id: generateColumnId(),\n width: el.getAttribute('width') ?? defaultWidth,\n blocks: parseBlockElements(el),\n };\n}\n\n/** Resolve padding from shorthand or individual padding-top/right/bottom/left attributes */\nfunction resolvePadding(el: Element, fallback: string): string {\n const shorthand = el.getAttribute('padding');\n if (shorthand) return shorthand;\n\n const pt = el.getAttribute('padding-top');\n const pr = el.getAttribute('padding-right');\n const pb = el.getAttribute('padding-bottom');\n const pl = el.getAttribute('padding-left');\n\n if (pt || pr || pb || pl) {\n return `${pt ?? '0'} ${pr ?? '0'} ${pb ?? '0'} ${pl ?? '0'}`;\n }\n\n return fallback;\n}\n\n// Register built-in parsers\nregisterBlockParser('mj-text', parseTextBlock);\nregisterBlockParser('mj-button', parseButtonBlock);\nregisterBlockParser('mj-image', parseImageBlock);\nregisterBlockParser('mj-divider', parseDividerBlock);\nregisterBlockParser('mj-spacer', parseSpacerBlock);\nregisterBlockParser('mj-social', parseSocialBlock);\nregisterBlockParser('mj-navbar', parseMenuBlock);\n\nfunction parseBlockElements(parent: Element): Block[] {\n const blocks: Block[] = [];\n const children = parent.children;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n const tagName = child.tagName.toLowerCase();\n\n if (tagName === 'mj-column') continue; // handled at section level\n\n const parser = blockParserRegistry[tagName];\n if (parser) {\n blocks.push(parser(child));\n }\n }\n\n return blocks;\n}\n\nfunction parseTextBlock(el: Element): Block {\n const cssClass = el.getAttribute('css-class') ?? '';\n\n // Detect heading block by css-class marker or content heuristic\n if (cssClass.includes('ee-block-heading')) {\n return parseHeadingFromMjText(el, cssClass);\n }\n\n // Detect countdown block by css-class marker\n if (cssClass.includes('ee-block-countdown')) {\n return parseCountdownFromMjText(el);\n }\n\n // Detect HTML block by css-class marker\n if (cssClass.includes('ee-block-html')) {\n return parseHtmlFromMjText(el);\n }\n\n const innerHTML = el.innerHTML?.trim() ?? '';\n\n const d = MJML_DEFAULTS.text;\n return {\n id: generateBlockId(),\n type: 'text',\n properties: {\n content: convertLegacyHtml(innerHTML),\n fontFamily: el.getAttribute('font-family') ?? d.fontFamily,\n fontSize: el.getAttribute('font-size') ?? d.fontSize,\n color: el.getAttribute('color') ?? d.color,\n lineHeight: el.getAttribute('line-height') ?? d.lineHeight,\n padding: resolvePadding(el, d.padding),\n align: el.getAttribute('align') ?? d.align,\n fontWeight: el.getAttribute('font-weight') ?? d.fontWeight,\n textTransform: el.getAttribute('text-transform') ?? d.textTransform,\n letterSpacing: el.getAttribute('letter-spacing') ?? d.letterSpacing,\n },\n };\n}\n\nfunction parseHeadingFromMjText(el: Element, cssClass: string): Block {\n const d = MJML_DEFAULTS.text;\n const defaults = DEFAULT_BLOCK_PROPERTIES.heading;\n const innerHTML = el.innerHTML?.trim() ?? '';\n\n // Extract heading level from css-class (ee-heading-h1, ee-heading-h2, etc.)\n const levelMatch = cssClass.match(/ee-heading-(h[1-4])/);\n const level = levelMatch ? levelMatch[1] : 'h2';\n\n // Extract content from heading tag wrapper\n const contentMatch = innerHTML.match(new RegExp(`^<${level}[^>]*>([\\\\s\\\\S]*)<\\\\/${level}>$`, 'i'));\n const content = contentMatch ? contentMatch[1].trim() : innerHTML;\n\n return {\n id: generateBlockId(),\n type: 'heading',\n properties: {\n content,\n level,\n fontFamily: el.getAttribute('font-family') ?? defaults.fontFamily,\n fontSize: el.getAttribute('font-size') ?? defaults.fontSize,\n color: el.getAttribute('color') ?? defaults.color,\n lineHeight: el.getAttribute('line-height') ?? defaults.lineHeight,\n fontWeight: el.getAttribute('font-weight') ?? defaults.fontWeight,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? d.align,\n textTransform: el.getAttribute('text-transform') ?? defaults.textTransform,\n letterSpacing: el.getAttribute('letter-spacing') ?? defaults.letterSpacing,\n },\n };\n}\n\nfunction parseCountdownFromMjText(el: Element): Block {\n const defaults = DEFAULT_BLOCK_PROPERTIES.countdown;\n const innerHTML = el.innerHTML?.trim() ?? '';\n\n // Extract metadata from embedded JSON comment\n const metaMatch = innerHTML.match(/<!--ee-countdown:([\\s\\S]*?)-->/);\n\n if (metaMatch) {\n try {\n // Decode HTML entities back to JSON (escapeAttr encodes &, \", <, >)\n const raw = metaMatch[1].replace(/&amp;/g, '&').replace(/&quot;/g, '\"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&#39;/g, \"'\");\n const meta = JSON.parse(raw);\n return {\n id: generateBlockId(),\n type: 'countdown',\n properties: {\n targetDate: meta.targetDate || defaults.targetDate,\n label: meta.label ?? '',\n digitBackgroundColor: meta.digitBackgroundColor || defaults.digitBackgroundColor,\n digitColor: meta.digitColor || defaults.digitColor,\n labelColor: meta.labelColor || defaults.labelColor,\n fontSize: meta.fontSize || defaults.fontSize,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? defaults.align,\n },\n };\n } catch {\n // JSON parse failed — fall through to default\n }\n }\n\n // Fallback: create a default countdown block\n return {\n id: generateBlockId(),\n type: 'countdown',\n properties: {\n ...defaults,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? defaults.align,\n },\n };\n}\n\nfunction parseHtmlFromMjText(el: Element): Block {\n const defaults = DEFAULT_BLOCK_PROPERTIES.html;\n return {\n id: generateBlockId(),\n type: 'html',\n properties: {\n content: el.innerHTML?.trim() ?? '',\n padding: resolvePadding(el, defaults.padding),\n },\n };\n}\n\nfunction parseButtonBlock(el: Element): Block {\n const d = MJML_DEFAULTS.button;\n return {\n id: generateBlockId(),\n type: 'button',\n properties: {\n text: el.textContent?.trim() ?? d.text,\n href: el.getAttribute('href') ?? d.href,\n backgroundColor: el.getAttribute('background-color') ?? d.backgroundColor,\n color: el.getAttribute('color') ?? d.color,\n fontFamily: el.getAttribute('font-family') ?? d.fontFamily,\n fontSize: el.getAttribute('font-size') ?? d.fontSize,\n borderRadius: el.getAttribute('border-radius') ?? d.borderRadius,\n padding: resolvePadding(el, d.padding),\n innerPadding: el.getAttribute('inner-padding') ?? d.innerPadding,\n align: el.getAttribute('align') ?? d.align,\n width: el.getAttribute('width') ?? d.width,\n fontWeight: el.getAttribute('font-weight') ?? d.fontWeight,\n textTransform: el.getAttribute('text-transform') ?? d.textTransform,\n letterSpacing: el.getAttribute('letter-spacing') ?? d.letterSpacing,\n },\n };\n}\n\nfunction parseImageBlock(el: Element): Block {\n const cssClass = el.getAttribute('css-class') ?? '';\n const href = el.getAttribute('href') ?? '';\n\n // Detect video block by css-class marker or href heuristic (YouTube/Vimeo)\n if (cssClass.includes('ee-block-video') || isVideoUrl(href)) {\n const defaults = DEFAULT_BLOCK_PROPERTIES.video;\n return {\n id: generateBlockId(),\n type: 'video',\n properties: {\n src: href || defaults.src,\n thumbnailUrl: el.getAttribute('src') ?? defaults.thumbnailUrl,\n alt: el.getAttribute('alt') ?? defaults.alt,\n padding: resolvePadding(el, defaults.padding),\n align: el.getAttribute('align') ?? defaults.align,\n },\n };\n }\n\n const d = MJML_DEFAULTS.image;\n return {\n id: generateBlockId(),\n type: 'image',\n properties: {\n src: el.getAttribute('src') ?? d.src,\n alt: el.getAttribute('alt') ?? d.alt,\n href: href || d.href,\n width: el.getAttribute('width') ?? d.width,\n height: el.getAttribute('height') ?? d.height,\n padding: resolvePadding(el, d.padding),\n align: el.getAttribute('align') ?? d.align,\n fluidOnMobile: el.getAttribute('fluid-on-mobile') === 'true',\n },\n };\n}\n\nfunction isVideoUrl(url: string): boolean {\n if (!url) return false;\n return /(?:youtube\\.com\\/watch|youtu\\.be\\/|vimeo\\.com\\/)/i.test(url);\n}\n\nfunction parseDividerBlock(el: Element): Block {\n const d = MJML_DEFAULTS.divider;\n return {\n id: generateBlockId(),\n type: 'divider',\n properties: {\n borderColor: el.getAttribute('border-color') ?? d.borderColor,\n borderWidth: el.getAttribute('border-width') ?? d.borderWidth,\n borderStyle: el.getAttribute('border-style') ?? d.borderStyle,\n padding: resolvePadding(el, d.padding),\n width: el.getAttribute('width') ?? d.width,\n },\n };\n}\n\nfunction parseSpacerBlock(el: Element): Block {\n const d = MJML_DEFAULTS.spacer;\n return {\n id: generateBlockId(),\n type: 'spacer',\n properties: {\n height: el.getAttribute('height') ?? d.height,\n },\n };\n}\n\nfunction parseSocialBlock(el: Element): Block {\n const d = MJML_DEFAULTS.social;\n const editorDefaults = DEFAULT_BLOCK_PROPERTIES.social;\n\n const elements: SocialElement[] = [];\n const childEls = el.querySelectorAll('mj-social-element');\n for (let i = 0; i < childEls.length; i++) {\n const child = childEls[i];\n const element: SocialElement = {\n name: child.getAttribute('name') ?? 'web',\n href: child.getAttribute('href') ?? '#',\n };\n const src = child.getAttribute('src');\n if (src) element.src = src;\n const content = child.textContent?.trim();\n if (content) element.content = content;\n const bgColor = child.getAttribute('background-color');\n if (bgColor) element.backgroundColor = bgColor;\n const color = child.getAttribute('color');\n if (color) element.color = color;\n elements.push(element);\n }\n\n return {\n id: generateBlockId(),\n type: 'social',\n properties: {\n elements: elements.length > 0 ? elements : editorDefaults.elements,\n mode: el.getAttribute('mode') ?? d.mode,\n align: el.getAttribute('align') ?? d.align,\n iconSize: el.getAttribute('icon-size') ?? d.iconSize,\n iconPadding: el.getAttribute('icon-padding') ?? d.iconPadding,\n padding: resolvePadding(el, d.padding),\n fontSize: el.getAttribute('font-size') ?? d.fontSize,\n color: el.getAttribute('color') ?? d.color,\n borderRadius: el.getAttribute('border-radius') ?? d.borderRadius,\n },\n };\n}\n\nfunction parseMenuBlock(el: Element): Block {\n const d = MJML_DEFAULTS.menu;\n const editorDefaults = DEFAULT_BLOCK_PROPERTIES.menu;\n\n const items: MenuItem[] = [];\n const linkEls = el.querySelectorAll('mj-navbar-link');\n for (let i = 0; i < linkEls.length; i++) {\n const child = linkEls[i];\n items.push({\n text: child.textContent?.trim() ?? 'Link',\n href: child.getAttribute('href') ?? '#',\n });\n }\n\n // Read color/font from first link element if present\n const firstLink = linkEls.length > 0 ? linkEls[0] : null;\n\n return {\n id: generateBlockId(),\n type: 'menu',\n properties: {\n items: items.length > 0 ? items : editorDefaults.items,\n align: el.getAttribute('align') ?? d.align,\n fontFamily: firstLink?.getAttribute('font-family') ?? d.fontFamily,\n fontSize: firstLink?.getAttribute('font-size') ?? d.fontSize,\n color: firstLink?.getAttribute('color') ?? d.color,\n padding: resolvePadding(el, d.padding),\n hamburger: el.getAttribute('hamburger') === 'hamburger',\n iconColor: el.getAttribute('ico-color') ?? editorDefaults.iconColor,\n },\n };\n}\n",".toolbar {\n display: flex;\n align-items: center;\n height: var(--ee-toolbar-height);\n padding: 0 var(--ee-space-lg);\n background: var(--ee-bg-toolbar);\n border-bottom: 1px solid var(--ee-border-color);\n gap: var(--ee-space-sm);\n flex-shrink: 0;\n}\n\n.toolbarGroup {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.toolbarSeparator {\n width: 1px;\n height: 24px;\n background: var(--ee-border-color);\n margin: 0 var(--ee-space-sm);\n}\n\n.toolbarSpacer {\n flex: 1;\n}\n\n.toolbarBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-xs);\n padding: 6px 10px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n background: transparent;\n border: 1px solid transparent;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n white-space: nowrap;\n}\n\n.toolbarBtn:hover {\n background: var(--ee-bg-hover);\n color: var(--ee-text-primary);\n border-color: var(--ee-border-color);\n}\n\n.toolbarBtn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.toolbarBtnActive {\n background: var(--ee-bg-selected);\n color: var(--ee-color-primary);\n border-color: var(--ee-color-primary);\n}\n\n.toolbarBtnPrimary {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.toolbarBtnPrimary:hover {\n background: var(--ee-color-primary-hover);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary-hover);\n}\n\n/* Tab bar within toolbar */\n.tabBar {\n display: flex;\n gap: 2px;\n background: var(--ee-bg-app);\n border-radius: var(--ee-border-radius);\n padding: 2px;\n}\n\n.tabBtn {\n padding: 4px 12px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n background: transparent;\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.tabBtn:hover {\n color: var(--ee-text-primary);\n}\n\n.tabBtnActive {\n background: var(--ee-bg-panel);\n color: var(--ee-text-primary);\n box-shadow: var(--ee-shadow-sm);\n}\n\n/* Panel toggle buttons (visible only on narrow screens via editor.module.css) */\n.panelToggleBtn {\n composes: toolbarBtn;\n font-size: var(--ee-font-size-lg);\n padding: 4px 8px;\n line-height: 1;\n}\n\n.panelToggleBtnActive {\n background: var(--ee-bg-selected);\n color: var(--ee-color-primary);\n border-color: var(--ee-color-primary);\n}\n\n/* Export dropdown */\n.exportWrapper {\n position: relative;\n}\n\n.exportDropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n z-index: var(--ee-z-dropdown);\n min-width: 120px;\n overflow: hidden;\n}\n\n.exportDropdownItem {\n display: block;\n width: 100%;\n padding: 8px 16px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n color: var(--ee-text-primary);\n background: none;\n border: none;\n text-align: left;\n cursor: pointer;\n transition: background var(--ee-transition-fast);\n}\n\n.exportDropdownItem:hover {\n background: var(--ee-bg-hover);\n}\n\n/* Rich text toolbar */\n.richTextToolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: var(--ee-space-xs) var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-sm);\n flex-wrap: wrap;\n}\n\n.richTextBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n font-size: var(--ee-font-size-sm);\n background: transparent;\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.richTextBtn:hover {\n background: var(--ee-bg-hover);\n color: var(--ee-text-primary);\n}\n\n.richTextBtnActive {\n background: var(--ee-bg-selected);\n color: var(--ee-color-primary);\n}\n\n.richTextSeparator {\n width: 1px;\n height: 20px;\n background: var(--ee-border-color);\n margin: 0 2px;\n}\n\n/* Rich text select controls */\n.richTextSelect {\n height: 28px;\n padding: 0 4px;\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n cursor: pointer;\n max-width: 110px;\n}\n\n.richTextSelect:focus {\n border-color: var(--ee-border-focus);\n}\n\n.richTextSelectSmall {\n composes: richTextSelect;\n max-width: 64px;\n}\n\n/* Rich text inline color picker */\n.richTextColorWrapper {\n position: relative;\n}\n\n.richTextColorLabel {\n font-weight: var(--ee-font-weight-semibold);\n font-size: var(--ee-font-size-sm);\n}\n\n.richTextColorIndicator {\n display: block;\n width: 16px;\n height: 3px;\n border-radius: 1px;\n margin-top: 1px;\n}\n\n.richTextColorDropdown {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 4px;\n padding: var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n z-index: var(--ee-z-dropdown);\n min-width: 176px;\n}\n\n.richTextColorGrid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 4px;\n margin-bottom: var(--ee-space-sm);\n}\n\n.richTextColorSwatch {\n width: 24px;\n height: 24px;\n border-radius: 3px;\n border: 2px solid transparent;\n cursor: pointer;\n padding: 0;\n transition: all var(--ee-transition-fast);\n}\n\n.richTextColorSwatch:hover {\n transform: scale(1.2);\n border-color: var(--ee-border-color-strong);\n}\n\n.richTextColorActions {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n border-top: 1px solid var(--ee-border-color);\n padding-top: var(--ee-space-sm);\n}\n\n.richTextColorInput {\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid var(--ee-border-color);\n border-radius: 3px;\n cursor: pointer;\n background: none;\n}\n\n.richTextColorClearBtn {\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n color: var(--ee-text-secondary);\n background: transparent;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n padding: 3px 8px;\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.richTextColorClearBtn:hover {\n background: var(--ee-bg-hover);\n color: var(--ee-text-primary);\n}\n\n/* Link editor popover */\n.richTextLinkDropdown {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 4px;\n padding: var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n z-index: var(--ee-z-dropdown);\n min-width: 260px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.richTextLinkLabel {\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-secondary);\n}\n\n.richTextLinkInput {\n width: 100%;\n padding: 6px 8px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n box-sizing: border-box;\n}\n\n.richTextLinkInput:focus {\n border-color: var(--ee-border-focus);\n}\n\n.richTextLinkError {\n color: var(--ee-color-danger, #dc2626);\n font-size: 11px;\n margin-bottom: 4px;\n}\n\n.richTextLinkActions {\n display: flex;\n gap: 6px;\n}\n\n.richTextLinkApply {\n flex: 1;\n padding: 4px 10px;\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-inverse);\n background: var(--ee-color-primary);\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: background var(--ee-transition-fast);\n}\n\n.richTextLinkApply:hover {\n background: var(--ee-color-primary-hover);\n}\n\n.richTextLinkRemove {\n padding: 4px 10px;\n font-size: var(--ee-font-size-xs);\n font-family: var(--ee-font-family);\n color: var(--ee-color-danger, #ef4444);\n background: transparent;\n border: 1px solid var(--ee-color-danger, #ef4444);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.richTextLinkRemove:hover {\n background: var(--ee-color-danger, #ef4444);\n color: var(--ee-text-inverse);\n}\n\n",".editorWrapper {\n height: 100%;\n min-height: 0;\n}\n\n.editorContainer {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 500px;\n font-family: var(--ee-font-family);\n font-size: var(--ee-font-size-base);\n color: var(--ee-text-primary);\n background: var(--ee-bg-app);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-lg);\n overflow: hidden;\n}\n\n.editorContainer:focus {\n outline: none;\n}\n\n.editorBody {\n display: flex;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.editorPanel {\n min-height: 0;\n max-height: 100%;\n}\n\n.sidebarPanel {\n width: var(--ee-sidebar-width);\n border-right: 1px solid var(--ee-border-color);\n background: var(--ee-bg-panel);\n overflow-y: auto;\n flex-shrink: 0;\n}\n\n.canvasPanel {\n flex: 1;\n min-width: 0;\n background: var(--ee-bg-canvas);\n overflow-y: auto;\n}\n\n.propertiesPanel {\n width: var(--ee-properties-width);\n border-left: 1px solid var(--ee-border-color);\n background: var(--ee-bg-panel);\n overflow-y: auto;\n flex-shrink: 0;\n}\n\n/* Source tab split layout */\n.sourceLayout {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.sourcePane {\n flex: 1;\n min-width: 0;\n}\n\n.sourcePaneDivider {\n flex: 1;\n min-width: 0;\n border-left: 1px solid var(--ee-border-color);\n}\n\n/* Panel toggle buttons — hidden on desktop, shown on narrow screens */\n.panelToggle {\n display: none;\n}\n\n/* Overlay backdrop */\n.panelOverlay {\n display: none;\n}\n\n/* ---- Responsive: tablet / narrow screens ---- */\n@media (max-width: 1023px) {\n .editorBody {\n position: relative;\n }\n\n .sidebarPanel {\n display: none;\n }\n\n .propertiesPanel {\n display: none;\n }\n\n .panelToggle {\n display: flex;\n }\n\n /* Sidebar overlay (open state) */\n .sidebarPanel.sidebarOpen {\n display: block;\n position: absolute;\n z-index: var(--ee-z-overlay);\n left: 0;\n top: 0;\n bottom: 0;\n box-shadow: var(--ee-shadow-lg);\n }\n\n /* Properties overlay (open state) */\n .propertiesPanel.propertiesOpen {\n display: block;\n position: absolute;\n z-index: var(--ee-z-overlay);\n right: 0;\n top: 0;\n bottom: 0;\n box-shadow: var(--ee-shadow-lg);\n }\n\n /* Backdrop when a panel is open */\n .panelOverlay.panelOverlayVisible {\n display: block;\n position: absolute;\n top: 0; right: 0; bottom: 0; left: 0;\n background: var(--ee-overlay-backdrop);\n z-index: calc(var(--ee-z-overlay) - 1);\n }\n}\n\n/* ---- Responsive: mobile ---- */\n@media (max-width: 767px) {\n .editorContainer {\n min-height: 400px;\n }\n}\n","import React, { useCallback } from 'react';\nimport { BlockPalette } from './BlockPalette';\nimport { VariableList } from './VariableList';\nimport { AddVariableForm } from './AddVariableForm';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport { COLUMN_LAYOUTS } from '../../constants';\nimport type { BlockDefinition } from '../../constants';\nimport { createSection } from '../../utils/factory';\nimport styles from '../../styles/sidebar.module.css';\n\ninterface SidebarProps {\n blockDefinitions?: BlockDefinition[];\n}\n\nexport function Sidebar({ blockDefinitions }: SidebarProps) {\n const dispatch = useEditorDispatch();\n\n const handleAddSection = useCallback(\n (widths: string[]) => {\n dispatch({ type: 'ADD_SECTION', payload: { section: createSection(widths) } });\n },\n [dispatch],\n );\n\n return (\n <div className={`ee-sidebar ${styles.sidebar}`}>\n <h3 className={`ee-sidebar-title ${styles.sectionTitle}`}>Variables</h3>\n <VariableList />\n <div className={styles.addVariableSection}>\n <AddVariableForm />\n </div>\n\n <h3 className={`ee-sidebar-title ${styles.sectionTitle}`}>Blocks</h3>\n <BlockPalette blockDefinitions={blockDefinitions} />\n\n <h3 className={`ee-sidebar-title ${styles.sectionTitle}`}>Layouts</h3>\n <div className={`ee-layout-section ${styles.layoutSection}`}>\n {COLUMN_LAYOUTS.map((layout) => (\n <div\n key={layout.label}\n className={`ee-layout-option ${styles.layoutOption}`}\n onClick={() => handleAddSection(layout.widths)}\n >\n <div className={`ee-layout-preview ${styles.layoutPreview}`}>\n {layout.widths.map((w, i) => (\n <div\n key={i}\n className={`ee-layout-column ${styles.layoutColumn}`}\n style={{ width: w }}\n />\n ))}\n </div>\n <span className={`ee-layout-label ${styles.layoutLabel}`}>{layout.label}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport { BLOCK_DEFINITIONS } from '../../constants';\nimport type { BlockDefinition } from '../../constants';\nimport { setBlockTypeDragData } from '../../utils/dnd';\nimport type { BlockType } from '../../types';\nimport { useEditorDispatch, useTemplateContext } from '../../context/EditorContext';\nimport { createSection, createBlock } from '../../utils/factory';\nimport styles from '../../styles/sidebar.module.css';\n\ninterface BlockPaletteProps {\n blockDefinitions?: BlockDefinition[];\n}\n\nexport const BlockPalette = React.memo(function BlockPalette({ blockDefinitions }: BlockPaletteProps) {\n const defs = blockDefinitions ?? BLOCK_DEFINITIONS;\n const dispatch = useEditorDispatch();\n const { template } = useTemplateContext();\n\n const handleDragStart = useCallback(\n (type: BlockType, e: React.DragEvent) => {\n setBlockTypeDragData(e, type);\n },\n [],\n );\n\n const handleKeyboardAdd = useCallback(\n (type: BlockType) => {\n let targetSection = template.sections[template.sections.length - 1];\n if (!targetSection) {\n targetSection = createSection();\n dispatch({ type: 'ADD_SECTION', payload: { section: targetSection } });\n }\n const column = targetSection.columns[0];\n const block = createBlock(type);\n dispatch({\n type: 'ADD_BLOCK_AND_SELECT',\n payload: { sectionId: targetSection.id, columnId: column.id, block },\n });\n },\n [dispatch, template.sections],\n );\n\n return (\n <div className={`ee-block-palette ${styles.blockPalette}`} role=\"list\" aria-label=\"Available blocks\">\n {defs.map((def) => (\n <div\n key={def.type}\n data-block-type={def.type}\n className={`ee-palette-item ee-palette-item--${def.type} ${styles.blockCard}`}\n draggable\n onDragStart={(e) => handleDragStart(def.type, e)}\n title={def.description}\n role=\"listitem\"\n aria-label={`${def.label} block - drag or press Enter to add`}\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleKeyboardAdd(def.type);\n }\n }}\n >\n <span className={`ee-palette-icon ${styles.blockCardIcon}`} aria-hidden=\"true\">{def.icon}</span>\n <span className={`ee-palette-label ${styles.blockCardLabel}`}>{def.label}</span>\n </div>\n ))}\n </div>\n );\n});\n","import type { BlockType } from '../types';\n\nexport const DND_TYPES = {\n BLOCK_TYPE: 'application/x-block-type',\n BLOCK_ID: 'application/x-block-id',\n SECTION_ID: 'application/x-section-id',\n COLUMN_ID: 'application/x-column-id',\n SECTION_MOVE: 'application/x-section-move',\n} as const;\n\nexport function setBlockTypeDragData(e: React.DragEvent, type: BlockType): void {\n e.dataTransfer.setData(DND_TYPES.BLOCK_TYPE, type);\n e.dataTransfer.effectAllowed = 'copy';\n}\n\nexport function setBlockMoveDragData(\n e: React.DragEvent,\n blockId: string,\n sectionId: string,\n columnId: string,\n): void {\n e.dataTransfer.setData(DND_TYPES.BLOCK_ID, blockId);\n e.dataTransfer.setData(DND_TYPES.SECTION_ID, sectionId);\n e.dataTransfer.setData(DND_TYPES.COLUMN_ID, columnId);\n e.dataTransfer.effectAllowed = 'move';\n}\n\nexport function getBlockTypeFromDrop(e: React.DragEvent): BlockType | null {\n const type = e.dataTransfer.getData(DND_TYPES.BLOCK_TYPE);\n return (type as BlockType) || null;\n}\n\nexport function getBlockMoveFromDrop(e: React.DragEvent): {\n blockId: string;\n sectionId: string;\n columnId: string;\n} | null {\n const blockId = e.dataTransfer.getData(DND_TYPES.BLOCK_ID);\n const sectionId = e.dataTransfer.getData(DND_TYPES.SECTION_ID);\n const columnId = e.dataTransfer.getData(DND_TYPES.COLUMN_ID);\n if (!blockId) return null;\n return { blockId, sectionId, columnId };\n}\n\nexport function setSectionMoveDragData(e: React.DragEvent, sectionId: string): void {\n e.dataTransfer.setData(DND_TYPES.SECTION_MOVE, sectionId);\n e.dataTransfer.effectAllowed = 'move';\n}\n\nexport function getSectionMoveFromDrop(e: React.DragEvent): string | null {\n return e.dataTransfer.getData(DND_TYPES.SECTION_MOVE) || null;\n}\n\nexport function isSectionDrop(e: React.DragEvent): boolean {\n return e.dataTransfer.types.includes(DND_TYPES.SECTION_MOVE);\n}\n\nexport function isDropAllowed(e: React.DragEvent): boolean {\n return (\n e.dataTransfer.types.includes(DND_TYPES.BLOCK_TYPE) ||\n e.dataTransfer.types.includes(DND_TYPES.BLOCK_ID)\n );\n}\n",".sidebar {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n.sectionTitle {\n font-size: var(--ee-font-size-sm);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: var(--ee-space-md) var(--ee-space-lg);\n margin: 0;\n border-bottom: 1px solid var(--ee-border-color);\n}\n\n/* Block Palette */\n.blockPalette {\n padding: var(--ee-space-sm);\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--ee-space-sm);\n}\n\n.blockCard {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--ee-space-xs);\n padding: var(--ee-space-md) var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n cursor: grab;\n transition: all var(--ee-transition-fast);\n user-select: none;\n}\n\n.blockCard:hover {\n border-color: var(--ee-border-focus);\n background: var(--ee-bg-selected);\n box-shadow: var(--ee-shadow-sm);\n}\n\n.blockCard:active {\n cursor: grabbing;\n opacity: 0.7;\n}\n\n.blockCardIcon {\n font-size: 20px;\n line-height: 1;\n}\n\n.blockCardLabel {\n font-size: var(--ee-font-size-sm);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-primary);\n}\n\n/* Variable List */\n.variableList {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n}\n\n.variableHint {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-muted);\n margin: 0 0 var(--ee-space-sm) 0;\n line-height: 1.4;\n font-style: italic;\n}\n\n.variableGroup {\n margin-bottom: var(--ee-space-md);\n}\n\n.variableGroupTitle {\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-muted);\n margin: 0 0 var(--ee-space-xs) 0;\n text-transform: uppercase;\n}\n\n.variableChips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--ee-space-xs);\n}\n\n.variableChip {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 2px 8px;\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-medium);\n background: var(--ee-variable-bg);\n color: var(--ee-variable-color);\n border: 1px solid var(--ee-variable-border);\n border-radius: 12px;\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n white-space: nowrap;\n}\n\n.variableChip:hover {\n background: var(--ee-color-primary-light);\n border-color: var(--ee-color-primary);\n transform: translateY(-1px);\n box-shadow: var(--ee-shadow-sm);\n}\n\n.variableChip:active {\n transform: translateY(0);\n box-shadow: none;\n}\n\n.variableChipInserted {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n transition: all 0.15s ease;\n}\n\n.variableChipCustom {\n background: var(--ee-color-success-light);\n color: var(--ee-color-success-text);\n border-color: var(--ee-color-success-border);\n}\n\n.variableChipCustom:hover {\n background: var(--ee-color-success-light-hover);\n border-color: var(--ee-color-success);\n}\n\n.variableChipDelete {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n margin-left: 2px;\n padding: 0;\n font-size: 9px;\n line-height: 1;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n color: inherit;\n opacity: 0.5;\n transition: all var(--ee-transition-fast);\n}\n\n.variableChipDelete:hover {\n opacity: 1;\n background: var(--ee-overlay-subtle);\n}\n\n.variableChipIcon {\n font-size: 11px;\n}\n\n/* Add Variable */\n.addVariableSection {\n padding: var(--ee-space-xs) var(--ee-space-lg) var(--ee-space-lg);\n}\n\n.addVariableBtn {\n width: 100%;\n padding: 6px 12px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-color-primary);\n background: transparent;\n border: 1px dashed var(--ee-color-primary);\n border-radius: var(--ee-border-radius);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.addVariableBtn:hover {\n background: var(--ee-color-primary-light);\n}\n\n.addVariableForm {\n display: flex;\n flex-direction: column;\n gap: var(--ee-space-sm);\n padding: var(--ee-space-md);\n background: var(--ee-bg-hover);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n}\n\n.addVariableField {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.addVariableLabel {\n font-size: 10px;\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.addVariableInput {\n width: 100%;\n padding: 5px 8px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n box-sizing: border-box;\n transition: border-color var(--ee-transition-fast);\n}\n\n.addVariableInput:focus {\n border-color: var(--ee-border-focus);\n box-shadow: var(--ee-shadow-focus);\n}\n\n.addVariableError {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-color-danger);\n padding: 2px 0;\n}\n\n.addVariableActions {\n display: flex;\n gap: var(--ee-space-sm);\n justify-content: flex-end;\n padding-top: var(--ee-space-xs);\n}\n\n.addVariableCancelBtn {\n padding: 4px 12px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n color: var(--ee-text-secondary);\n background: transparent;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.addVariableCancelBtn:hover {\n background: var(--ee-bg-hover);\n}\n\n.addVariableSubmitBtn {\n padding: 4px 16px;\n font-size: var(--ee-font-size-sm);\n font-family: var(--ee-font-family);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-inverse);\n background: var(--ee-color-primary);\n border: 1px solid var(--ee-color-primary);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.addVariableSubmitBtn:hover {\n background: var(--ee-color-primary-hover);\n}\n\n/* Layout section */\n.layoutSection {\n padding: var(--ee-space-sm) var(--ee-space-lg);\n}\n\n.layoutOption {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n padding: var(--ee-space-sm) var(--ee-space-md);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n cursor: pointer;\n margin-bottom: var(--ee-space-xs);\n transition: all var(--ee-transition-fast);\n}\n\n.layoutOption:hover {\n border-color: var(--ee-border-focus);\n background: var(--ee-bg-selected);\n}\n\n.layoutPreview {\n display: flex;\n gap: 2px;\n flex: 1;\n height: 20px;\n}\n\n.layoutColumn {\n background: var(--ee-color-primary-light);\n border: 1px solid var(--ee-color-primary);\n border-radius: 2px;\n height: 100%;\n}\n\n.layoutLabel {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-secondary);\n white-space: nowrap;\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useEditorVariables } from '../../context/EditorContext';\nimport { groupVariables } from '../../utils/variables';\nimport styles from '../../styles/sidebar.module.css';\n\nexport function VariableList() {\n const { variables, customVariables, insertVariable, removeCustomVariable } = useEditorVariables();\n const [flashKey, setFlashKey] = useState<string | null>(null);\n const flashTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Cleanup flash timer on unmount\n useEffect(() => {\n return () => {\n if (flashTimerRef.current !== null) clearTimeout(flashTimerRef.current);\n };\n }, []);\n\n const customKeys = new Set(customVariables.map((v) => v.key));\n\n const handleChipClick = useCallback(\n (key: string) => {\n const inserted = insertVariable(key);\n if (inserted) {\n setFlashKey(key);\n if (flashTimerRef.current !== null) clearTimeout(flashTimerRef.current);\n flashTimerRef.current = setTimeout(() => {\n flashTimerRef.current = null;\n setFlashKey(null);\n }, 400);\n }\n },\n [insertVariable],\n );\n\n const handleDelete = useCallback(\n (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n removeCustomVariable(key);\n },\n [removeCustomVariable],\n );\n\n if (variables.length === 0) {\n return (\n <div className={`ee-variable-list ${styles.variableList}`}>\n <p className={`ee-variable-hint ${styles.variableHint}`}>\n No variables yet. Add one below.\n </p>\n </div>\n );\n }\n\n const grouped = groupVariables(variables);\n\n return (\n <div className={`ee-variable-list ${styles.variableList}`}>\n <p className={`ee-variable-hint ${styles.variableHint}`}>\n Click to insert at cursor, or drag into text.\n </p>\n {Array.from(grouped.entries()).map(([group, vars]) => (\n <div key={group} className={`ee-variable-group ${styles.variableGroup}`}>\n <h4 className={`ee-variable-group-title ${styles.variableGroupTitle}`}>{group}</h4>\n <div className={`ee-variable-chips ${styles.variableChips}`}>\n {vars.map((v) => (\n <span\n key={v.key}\n className={`ee-variable-chip ${styles.variableChip} ${flashKey === v.key ? styles.variableChipInserted : ''} ${customKeys.has(v.key) ? styles.variableChipCustom : ''}`}\n title={`Click to insert${v.sample ? ` • Sample: ${v.sample}` : ''}${customKeys.has(v.key) ? ' • Custom variable' : ''}`}\n onClick={() => handleChipClick(v.key)}\n draggable\n onDragStart={(e) => {\n e.dataTransfer.setData('text/plain', `{{ ${v.key} }}`);\n e.dataTransfer.setData('application/x-variable-key', v.key);\n }}\n >\n {v.icon && <span className={`ee-variable-chip-icon ${styles.variableChipIcon}`}>{v.icon}</span>}\n {v.label ?? v.key}\n {customKeys.has(v.key) && (\n <button\n className={`ee-variable-chip-delete ${styles.variableChipDelete}`}\n onClick={(e) => handleDelete(v.key, e)}\n title=\"Remove variable\"\n >\n x\n </button>\n )}\n </span>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import type { Variable } from '../types';\n\nconst VARIABLE_REGEX = /\\{\\{\\s*([^}]+?)\\s*\\}\\}/g;\n\nexport function extractVariableKeys(text: string): string[] {\n const seen = new Set<string>();\n const keys: string[] = [];\n for (const match of text.matchAll(VARIABLE_REGEX)) {\n const key = match[1].trim();\n if (!seen.has(key)) {\n seen.add(key);\n keys.push(key);\n }\n }\n return keys;\n}\n\nexport function replaceVariables(\n text: string,\n variables: Variable[],\n useSample = true,\n): string {\n return text.replace(VARIABLE_REGEX, (_match, key: string) => {\n const trimmedKey = key.trim();\n const variable = variables.find((v) => v.key === trimmedKey);\n if (!variable) return `{{ ${trimmedKey} }}`;\n return useSample && variable.sample ? variable.sample : `{{ ${trimmedKey} }}`;\n });\n}\n\nexport function groupVariables(variables: Variable[]): Map<string, Variable[]> {\n const groups = new Map<string, Variable[]>();\n for (const variable of variables) {\n const group = variable.group ?? 'General';\n const existing = groups.get(group) ?? [];\n existing.push(variable);\n groups.set(group, existing);\n }\n return groups;\n}\n","import React, { useState, useCallback } from 'react';\nimport { useEditorVariables } from '../../context/EditorContext';\nimport styles from '../../styles/sidebar.module.css';\n\nexport function AddVariableForm() {\n const { variables, addCustomVariable } = useEditorVariables();\n const [isOpen, setIsOpen] = useState(false);\n const [key, setKey] = useState('');\n const [label, setLabel] = useState('');\n const [group, setGroup] = useState('Custom');\n const [error, setError] = useState<string | null>(null);\n\n const resetForm = useCallback(() => {\n setKey('');\n setLabel('');\n setGroup('Custom');\n setError(null);\n }, []);\n\n const handleSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedKey = key.trim().toLowerCase().replace(/\\s+/g, '_').replace(/[^a-z0-9_]/g, '');\n if (!trimmedKey) {\n setError('Variable key is required');\n return;\n }\n\n if (variables.some((v) => v.key === trimmedKey)) {\n setError(`Variable \"${trimmedKey}\" already exists`);\n return;\n }\n\n addCustomVariable({\n key: trimmedKey,\n label: label.trim() || trimmedKey,\n group: group.trim() || 'Custom',\n });\n\n resetForm();\n setIsOpen(false);\n },\n [key, label, group, variables, addCustomVariable, resetForm],\n );\n\n const handleCancel = useCallback(() => {\n resetForm();\n setIsOpen(false);\n }, [resetForm]);\n\n if (!isOpen) {\n return (\n <button\n className={`ee-add-variable-btn ${styles.addVariableBtn}`}\n onClick={() => setIsOpen(true)}\n >\n + Add Variable\n </button>\n );\n }\n\n return (\n <form className={`ee-add-variable-form ${styles.addVariableForm}`} onSubmit={handleSubmit}>\n <div className={`ee-add-variable-field ${styles.addVariableField}`}>\n <label className={`ee-add-variable-label ${styles.addVariableLabel}`}>Key *</label>\n <input\n className={`ee-add-variable-input ${styles.addVariableInput}`}\n value={key}\n onChange={(e) => {\n setKey(e.target.value);\n setError(null);\n }}\n placeholder=\"e.g. coupon_code\"\n autoFocus\n />\n </div>\n <div className={`ee-add-variable-field ${styles.addVariableField}`}>\n <label className={`ee-add-variable-label ${styles.addVariableLabel}`}>Label</label>\n <input\n className={`ee-add-variable-input ${styles.addVariableInput}`}\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder=\"e.g. Coupon Code\"\n />\n </div>\n <div className={`ee-add-variable-field ${styles.addVariableField}`}>\n <label className={`ee-add-variable-label ${styles.addVariableLabel}`}>Group</label>\n <input\n className={`ee-add-variable-input ${styles.addVariableInput}`}\n value={group}\n onChange={(e) => setGroup(e.target.value)}\n placeholder=\"Custom\"\n />\n </div>\n {error && <div className={`ee-add-variable-error ${styles.addVariableError}`}>{error}</div>}\n <div className={`ee-add-variable-actions ${styles.addVariableActions}`}>\n <button type=\"button\" className={`ee-add-variable-cancel ${styles.addVariableCancelBtn}`} onClick={handleCancel}>\n Cancel\n </button>\n <button type=\"submit\" className={`ee-add-variable-submit ${styles.addVariableSubmitBtn}`}>\n Add\n </button>\n </div>\n </form>\n );\n}\n","import React, { useCallback, useState } from 'react';\nimport { Section } from './Section';\nimport { SectionDropZone } from './SectionDropZone';\nimport { useTemplateContext, useEditorDispatch } from '../../context/EditorContext';\nimport { createSection, createSectionWithBlock } from '../../utils/factory';\nimport { isDropAllowed, getBlockTypeFromDrop } from '../../utils/dnd';\nimport styles from '../../styles/canvas.module.css';\n\nexport const Canvas = React.memo(function Canvas() {\n const { template } = useTemplateContext();\n const dispatch = useEditorDispatch();\n const [isDragOver, setIsDragOver] = useState(false);\n\n const handleAddSection = useCallback(() => {\n dispatch({ type: 'ADD_SECTION', payload: { section: createSection() } });\n }, [dispatch]);\n\n const handleCanvasClick = useCallback(() => {\n dispatch({ type: 'DESELECT_ALL' });\n }, [dispatch]);\n\n const handleBodyDragOver = useCallback((e: React.DragEvent) => {\n if (!isDropAllowed(e)) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n setIsDragOver(true);\n }, []);\n\n const handleBodyDragLeave = useCallback((e: React.DragEvent) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom) {\n return;\n }\n setIsDragOver(false);\n }, []);\n\n const handleBodyDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragOver(false);\n\n const blockType = getBlockTypeFromDrop(e);\n if (!blockType) return;\n\n const section = createSectionWithBlock(blockType);\n const column = section.columns[0];\n const block = column.blocks[0];\n\n dispatch({ type: 'ADD_SECTION', payload: { section } });\n dispatch({\n type: 'SELECT_BLOCK',\n payload: { sectionId: section.id, columnId: column.id, blockId: block.id },\n });\n // Note: ADD_SECTION must happen first so the section exists before selection.\n // These are both cheap (SELECT_BLOCK is UI-only, no history push).\n },\n [dispatch],\n );\n\n return (\n <div className={`ee-canvas-wrapper ${styles.canvasWrapper}`} onClick={handleCanvasClick} role=\"main\" aria-label=\"Email canvas\">\n <div\n className={`ee-canvas-body ${styles.canvasBody} ${isDragOver ? styles.canvasBodyDragOver : ''}`}\n style={{\n width: template.globalStyles.width,\n backgroundColor: template.globalStyles.backgroundColor,\n fontFamily: template.globalStyles.fontFamily,\n }}\n onClick={(e) => e.stopPropagation()}\n onDragOver={handleBodyDragOver}\n onDragLeave={handleBodyDragLeave}\n onDrop={handleBodyDrop}\n aria-label=\"Email content area\"\n >\n {template.sections.map((section, index) => (\n <React.Fragment key={section.id}>\n <SectionDropZone index={index} />\n <Section section={section} />\n </React.Fragment>\n ))}\n {template.sections.length > 0 && (\n <SectionDropZone index={template.sections.length} />\n )}\n <button className={`ee-add-section ${styles.addSectionBtn}`} onClick={handleAddSection} aria-label=\"Add new section\">\n + Add Section\n </button>\n </div>\n </div>\n );\n});\n","import React, { useCallback, useState } from 'react';\nimport type { Section as SectionType } from '../../types';\nimport { Column } from './Column';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { useSelectionContext, useEditorDispatch, useTemplateContext } from '../../context/EditorContext';\nimport { setSectionMoveDragData } from '../../utils/dnd';\nimport styles from '../../styles/canvas.module.css';\n\ninterface SectionProps {\n section: SectionType;\n}\n\nexport const Section = React.memo(function Section({ section }: SectionProps) {\n const selection = useSelectionContext();\n const dispatch = useEditorDispatch();\n const { template } = useTemplateContext();\n const isSelected = selection.sectionId === section.id && !selection.blockId;\n const [showRemoveConfirm, setShowRemoveConfirm] = useState(false);\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n dispatch({ type: 'SELECT_SECTION', payload: { sectionId: section.id } });\n },\n [dispatch, section.id],\n );\n\n const handleRemove = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n setShowRemoveConfirm(true);\n },\n [],\n );\n\n const handleConfirmRemove = useCallback(() => {\n dispatch({ type: 'REMOVE_SECTION', payload: { sectionId: section.id } });\n setShowRemoveConfirm(false);\n }, [dispatch, section.id]);\n\n const handleDuplicate = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n dispatch({ type: 'DUPLICATE_SECTION', payload: { sectionId: section.id } });\n },\n [dispatch, section.id],\n );\n\n const handleDragStart = useCallback(\n (e: React.DragEvent) => {\n setSectionMoveDragData(e, section.id);\n },\n [section.id],\n );\n\n const handleDragKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n e.preventDefault();\n e.stopPropagation();\n const sections = template.sections;\n const currentIndex = sections.findIndex((s) => s.id === section.id);\n if (currentIndex === -1) return;\n const toIndex = e.key === 'ArrowUp' ? currentIndex - 1 : currentIndex + 1;\n if (toIndex < 0 || toIndex >= sections.length) return;\n dispatch({ type: 'MOVE_SECTION', payload: { sectionId: section.id, toIndex } });\n },\n [dispatch, section.id, template.sections],\n );\n\n return (\n <div\n className={`ee-section ${isSelected ? 'ee-section--selected' : ''} ${section.properties.fullWidth ? 'ee-section--full-width' : ''} ${styles.section} ${isSelected ? styles.sectionSelected : ''} ${section.properties.fullWidth ? styles.sectionFullWidth : ''}`}\n style={{\n backgroundColor: section.properties.backgroundColor,\n padding: section.properties.padding,\n borderRadius: section.properties.borderRadius,\n backgroundImage: section.properties.backgroundImage ? `url(${section.properties.backgroundImage})` : undefined,\n backgroundSize: section.properties.backgroundSize || undefined,\n backgroundRepeat: section.properties.backgroundRepeat || undefined,\n }}\n onClick={handleClick}\n role=\"region\"\n aria-label={`Email section${isSelected ? ' (selected)' : ''}`}\n aria-selected={isSelected}\n >\n <div className={`ee-section-actions ${styles.sectionOverlay}`} role=\"group\" aria-label=\"Section actions\">\n <span\n className={`ee-section-drag ${styles.sectionDragHandle}`}\n draggable\n onDragStart={handleDragStart}\n onKeyDown={handleDragKeyDown}\n title=\"Drag to reorder (or use Arrow keys)\"\n role=\"button\"\n aria-label=\"Reorder section with Arrow Up/Down keys\"\n tabIndex={0}\n >\n ⠿\n </span>\n <button\n className={`ee-section-duplicate ${styles.sectionBtn} ${styles.sectionBtnDuplicate}`}\n onClick={handleDuplicate}\n title=\"Duplicate section\"\n aria-label=\"Duplicate section\"\n >\n ⧉\n </button>\n <button\n className={`ee-section-remove ${styles.sectionBtn}`}\n onClick={handleRemove}\n title=\"Remove section\"\n aria-label=\"Remove section\"\n >\n x\n </button>\n </div>\n <div className={styles.sectionContent}>\n {section.columns.map((column) => (\n <Column key={column.id} column={column} sectionId={section.id} />\n ))}\n </div>\n {showRemoveConfirm && (\n <ConfirmDialog\n title=\"Remove Section\"\n message=\"Are you sure you want to remove this section and all its contents? This action can be undone with Ctrl+Z.\"\n onConfirm={handleConfirmRemove}\n onCancel={() => setShowRemoveConfirm(false)}\n />\n )}\n </div>\n );\n});\n","import React, { useCallback, useState } from 'react';\nimport type { Column as ColumnType } from '../../types';\nimport { BlockRenderer } from './BlockRenderer';\nimport { DropZone } from './DropZone';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { useSelectionContext, useEditorDispatch } from '../../context/EditorContext';\nimport {\n setBlockMoveDragData,\n isDropAllowed,\n getBlockTypeFromDrop,\n getBlockMoveFromDrop,\n DND_TYPES,\n} from '../../utils/dnd';\nimport { generateBlockId } from '../../utils/id';\nimport { DEFAULT_BLOCK_PROPERTIES } from '../../constants';\nimport styles from '../../styles/canvas.module.css';\n\ninterface ColumnProps {\n column: ColumnType;\n sectionId: string;\n}\n\n/** Read block ID and index from a block wrapper element's data attributes */\nfunction getBlockData(e: React.SyntheticEvent): { blockId: string; index: number } | null {\n const el = (e.currentTarget as HTMLElement);\n const blockId = el.dataset.blockId;\n const index = el.dataset.blockIndex;\n if (!blockId || index === undefined) return null;\n return { blockId, index: Number(index) };\n}\n\nexport const Column = React.memo(function Column({ column, sectionId }: ColumnProps) {\n const selection = useSelectionContext();\n const dispatch = useEditorDispatch();\n const [blockToRemove, setBlockToRemove] = useState<string | null>(null);\n\n const confirmRemoveBlock = useCallback(\n (blockId: string) => {\n setBlockToRemove(blockId);\n },\n [],\n );\n\n const handleConfirmRemove = useCallback(() => {\n if (blockToRemove) {\n dispatch({\n type: 'REMOVE_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: blockToRemove },\n });\n setBlockToRemove(null);\n }\n }, [dispatch, sectionId, column.id, blockToRemove]);\n\n // Single click handler — reads blockId from data attribute\n const handleBlockClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const data = getBlockData(e);\n if (!data) return;\n dispatch({\n type: 'SELECT_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: data.blockId },\n });\n },\n [dispatch, sectionId, column.id],\n );\n\n // Action button handlers use event delegation — walk up to find block wrapper\n const handleRemoveClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const wrapper = (e.currentTarget as HTMLElement).closest('[data-block-id]') as HTMLElement | null;\n if (wrapper?.dataset.blockId) confirmRemoveBlock(wrapper.dataset.blockId);\n },\n [confirmRemoveBlock],\n );\n\n const handleDuplicateClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const wrapper = (e.currentTarget as HTMLElement).closest('[data-block-id]') as HTMLElement | null;\n if (wrapper?.dataset.blockId) {\n dispatch({\n type: 'DUPLICATE_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: wrapper.dataset.blockId },\n });\n }\n },\n [dispatch, sectionId, column.id],\n );\n\n const handleBlockDragStart = useCallback(\n (e: React.DragEvent) => {\n const data = getBlockData(e);\n if (!data) return;\n setBlockMoveDragData(e, data.blockId, sectionId, column.id);\n },\n [sectionId, column.id],\n );\n\n // Block-level drop detection: determines top/bottom half for precise insertion\n const [dropTarget, setDropTarget] = useState<{\n blockId: string;\n position: 'before' | 'after';\n } | null>(null);\n\n const handleBlockDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!isDropAllowed(e)) return;\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.dropEffect = e.dataTransfer.types.includes(DND_TYPES.BLOCK_ID)\n ? 'move'\n : 'copy';\n const data = getBlockData(e);\n if (!data) return;\n const rect = e.currentTarget.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position: 'before' | 'after' = e.clientY < midY ? 'before' : 'after';\n setDropTarget((prev) => {\n if (prev?.blockId === data.blockId && prev?.position === position) return prev;\n return { blockId: data.blockId, position };\n });\n },\n [],\n );\n\n const handleBlockDragLeave = useCallback((e: React.DragEvent) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX >= rect.left &&\n clientX <= rect.right &&\n clientY >= rect.top &&\n clientY <= rect.bottom\n ) {\n return;\n }\n setDropTarget(null);\n }, []);\n\n const handleBlockDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDropTarget(null);\n\n const data = getBlockData(e);\n if (!data) return;\n const rect = e.currentTarget.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const insertIndex = e.clientY < midY ? data.index : data.index + 1;\n\n const blockType = getBlockTypeFromDrop(e);\n if (blockType) {\n const newBlock = {\n id: generateBlockId(),\n type: blockType,\n properties: JSON.parse(JSON.stringify(DEFAULT_BLOCK_PROPERTIES[blockType])),\n };\n dispatch({\n type: 'ADD_BLOCK_AND_SELECT',\n payload: { sectionId, columnId: column.id, block: newBlock, index: insertIndex },\n });\n return;\n }\n\n const moveData = getBlockMoveFromDrop(e);\n if (moveData) {\n dispatch({\n type: 'MOVE_BLOCK',\n payload: {\n fromSectionId: moveData.sectionId,\n fromColumnId: moveData.columnId,\n blockId: moveData.blockId,\n toSectionId: sectionId,\n toColumnId: column.id,\n toIndex: insertIndex,\n },\n });\n }\n },\n [dispatch, sectionId, column.id],\n );\n\n const handleBlockKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if (target.isContentEditable || target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {\n return;\n }\n const data = getBlockData(e);\n if (!data) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n dispatch({\n type: 'SELECT_BLOCK',\n payload: { sectionId, columnId: column.id, blockId: data.blockId },\n });\n } else if (e.key === 'Delete' || e.key === 'Backspace') {\n e.preventDefault();\n e.stopPropagation();\n confirmRemoveBlock(data.blockId);\n }\n },\n [dispatch, sectionId, column.id, confirmRemoveBlock],\n );\n\n if (column.blocks.length === 0) {\n return (\n <div className={`ee-column ${styles.column}`} style={{ width: column.width }}>\n <DropZone\n sectionId={sectionId}\n columnId={column.id}\n index={0}\n emptyPlaceholder\n />\n </div>\n );\n }\n\n return (\n <div className={`ee-column ${styles.column}`} style={{ width: column.width }}>\n {column.blocks.map((block, index) => (\n <React.Fragment key={block.id}>\n <DropZone sectionId={sectionId} columnId={column.id} index={index} />\n <div\n data-block-type={block.type}\n data-block-id={block.id}\n data-block-index={index}\n className={[\n 'ee-block',\n `ee-block--${block.type}`,\n selection.blockId === block.id && 'ee-block--selected',\n styles.blockWrapper,\n selection.blockId === block.id && styles.blockSelected,\n dropTarget?.blockId === block.id &&\n dropTarget.position === 'before' &&\n styles.blockDropBefore,\n dropTarget?.blockId === block.id &&\n dropTarget.position === 'after' &&\n styles.blockDropAfter,\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={handleBlockClick}\n draggable\n onDragStart={handleBlockDragStart}\n onDragOver={handleBlockDragOver}\n onDragLeave={handleBlockDragLeave}\n onDrop={handleBlockDrop}\n onKeyDown={handleBlockKeyDown}\n role=\"button\"\n aria-label={`${block.type} block${selection.blockId === block.id ? ' (selected)' : ''}`}\n aria-selected={selection.blockId === block.id}\n tabIndex={0}\n >\n <div className={`ee-block-actions ${styles.blockOverlay}`} role=\"group\" aria-label=\"Block actions\">\n <button\n className={`ee-block-duplicate ${styles.blockBtn} ${styles.blockBtnDuplicate}`}\n onClick={handleDuplicateClick}\n title=\"Duplicate block\"\n aria-label=\"Duplicate block\"\n >\n ⧉\n </button>\n <button\n className={`ee-block-remove ${styles.blockBtn}`}\n onClick={handleRemoveClick}\n title=\"Remove block\"\n aria-label=\"Remove block\"\n >\n x\n </button>\n </div>\n <BlockRenderer block={block} />\n </div>\n </React.Fragment>\n ))}\n <DropZone\n sectionId={sectionId}\n columnId={column.id}\n index={column.blocks.length}\n />\n {blockToRemove && (\n <ConfirmDialog\n title=\"Remove Block\"\n message=\"Are you sure you want to remove this block? This action can be undone with Ctrl+Z.\"\n onConfirm={handleConfirmRemove}\n onCancel={() => setBlockToRemove(null)}\n />\n )}\n </div>\n );\n});\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { blockRendererRegistry, registerBlockRenderer } from '../../registry';\nimport { ErrorBoundary } from '../ErrorBoundary';\nimport { TextBlock } from './blocks/TextBlock';\nimport { ButtonBlock } from './blocks/ButtonBlock';\nimport { ImageBlock } from './blocks/ImageBlock';\nimport { DividerBlock } from './blocks/DividerBlock';\nimport { SpacerBlock } from './blocks/SpacerBlock';\nimport { SocialBlock } from './blocks/SocialBlock';\nimport { HtmlBlock } from './blocks/HtmlBlock';\nimport { VideoBlock } from './blocks/VideoBlock';\nimport { HeadingBlock } from './blocks/HeadingBlock';\nimport { CountdownBlock } from './blocks/CountdownBlock';\nimport { MenuBlock } from './blocks/MenuBlock';\nimport { HeroBlock } from './blocks/HeroBlock';\n\n// Register built-in block renderers\nregisterBlockRenderer('text', TextBlock);\nregisterBlockRenderer('button', ButtonBlock);\nregisterBlockRenderer('image', ImageBlock);\nregisterBlockRenderer('divider', DividerBlock);\nregisterBlockRenderer('spacer', SpacerBlock);\nregisterBlockRenderer('social', SocialBlock);\nregisterBlockRenderer('html', HtmlBlock);\nregisterBlockRenderer('video', VideoBlock);\nregisterBlockRenderer('heading', HeadingBlock);\nregisterBlockRenderer('countdown', CountdownBlock);\nregisterBlockRenderer('menu', MenuBlock);\nregisterBlockRenderer('hero', HeroBlock);\n\ninterface BlockRendererProps {\n block: Block;\n}\n\nexport const BlockRenderer = React.memo(function BlockRenderer({ block }: BlockRendererProps) {\n const Component = blockRendererRegistry[block.type];\n if (!Component) return null;\n return (\n <ErrorBoundary>\n <Component block={block} />\n </ErrorBoundary>\n );\n});\n","import React, { useCallback, useRef, useState, useEffect, useReducer, useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport { useEditorDispatch, useMethodsContext } from '../../../context/EditorContext';\nimport { TipTapEditor } from '../../../tiptap/TipTapEditor';\nimport { RichTextToolbar } from '../../Toolbar/RichTextToolbar';\nimport type { Editor } from '@tiptap/core';\nimport styles from '../../../styles/blocks.module.css';\nimport tiptapStyles from '../../../styles/tiptap.module.css';\n\ninterface TextBlockProps {\n block: Block;\n}\n\nconst TextBlockInner = function TextBlock({ block }: TextBlockProps) {\n const dispatch = useEditorDispatch();\n const { setActiveEditor } = useMethodsContext();\n const editorRef = useRef<Editor | null>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const blurTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n // Track the editor instance in state so the effect has a proper dependency\n const [editorInstance, setEditorInstance] = useState<Editor | null>(null);\n\n // Force toolbar re-render when editor formatting state changes (selection/transaction)\n const [, forceToolbarUpdate] = useReducer((c: number) => c + 1, 0);\n\n useEffect(() => {\n if (!editorInstance) return;\n\n const onStateChange = () => forceToolbarUpdate();\n editorInstance.on('selectionUpdate', onStateChange);\n editorInstance.on('transaction', onStateChange);\n\n return () => {\n editorInstance.off('selectionUpdate', onStateChange);\n editorInstance.off('transaction', onStateChange);\n };\n }, [editorInstance]);\n\n const handleUpdate = useCallback(\n (html: string) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: { blockId: block.id, properties: { content: html } },\n });\n },\n [dispatch, block.id],\n );\n\n const handleFocus = useCallback(() => {\n setActiveEditor(editorRef.current);\n setIsFocused(true);\n }, [setActiveEditor]);\n\n // Cleanup blur timer on unmount\n useEffect(() => {\n return () => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n };\n }, []);\n\n const handleBlur = useCallback(() => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n blurTimerRef.current = setTimeout(() => {\n blurTimerRef.current = null;\n const activeEl = document.activeElement;\n if (wrapperRef.current && wrapperRef.current.contains(activeEl)) {\n return;\n }\n if (editorRef.current && !editorRef.current.isFocused) {\n setActiveEditor(null);\n setIsFocused(false);\n }\n }, 200);\n }, [setActiveEditor]);\n\n const handleEditorRef = useCallback((editor: Editor | null) => {\n editorRef.current = editor;\n setEditorInstance(editor);\n }, []);\n\n const p = block.properties;\n const wrapperStyle = useMemo(() => ({\n fontFamily: p.fontFamily,\n fontSize: p.fontSize,\n color: p.color,\n lineHeight: p.lineHeight,\n padding: p.padding,\n fontWeight: p.fontWeight,\n textTransform: p.textTransform,\n letterSpacing: p.letterSpacing,\n }), [p.fontFamily, p.fontSize, p.color, p.lineHeight, p.padding, p.fontWeight, p.textTransform, p.letterSpacing]);\n\n return (\n <div className={`ee-block-text ${styles.textBlock}`} ref={wrapperRef}>\n {isFocused && editorRef.current && (\n <div className={styles.textBlockToolbar}>\n <RichTextToolbar editor={editorRef.current} />\n </div>\n )}\n <div style={wrapperStyle}>\n <TipTapEditor\n content={block.properties.content}\n onUpdate={handleUpdate}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className={tiptapStyles.tiptapWrapper}\n editorRef={handleEditorRef}\n placeholder=\"Edit this text...\"\n />\n </div>\n </div>\n );\n};\n\nexport const TextBlock = React.memo(TextBlockInner);\n","import React, { useMemo, useEffect, useRef } from 'react';\nimport { useEditor as useTipTapEditor, EditorContent } from '@tiptap/react';\nimport type { Editor } from '@tiptap/core';\nimport { getExtensions } from './extensions';\nimport { cleanPastedHTML } from './pasteClean';\n\nexport interface TipTapEditorProps {\n content: string;\n onUpdate: (html: string) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n editable?: boolean;\n className?: string;\n editorRef?: (editor: Editor | null) => void;\n placeholder?: string;\n}\n\nexport function TipTapEditor({\n content,\n onUpdate,\n onFocus,\n onBlur,\n editable = true,\n className,\n editorRef,\n placeholder,\n}: TipTapEditorProps) {\n // Memoize extensions to prevent TipTap editor re-creation on every render\n const extensions = useMemo(() => getExtensions(placeholder), [placeholder]);\n\n // Use refs for callbacks to avoid stale closures in TipTap event handlers\n const onUpdateRef = useRef(onUpdate);\n onUpdateRef.current = onUpdate;\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n const editorRefCb = useRef(editorRef);\n editorRefCb.current = editorRef;\n\n const editor = useTipTapEditor({\n extensions,\n content,\n editable,\n editorProps: {\n transformPastedHTML(html) {\n return cleanPastedHTML(html);\n },\n },\n onUpdate: ({ editor: e }) => {\n onUpdateRef.current(e.getHTML());\n },\n onFocus: () => onFocusRef.current?.(),\n onBlur: () => onBlurRef.current?.(),\n onCreate: ({ editor: e }) => {\n editorRefCb.current?.(e);\n },\n onDestroy: () => {\n editorRefCb.current?.(null);\n },\n });\n\n // Sync content from external changes (undo/redo, loadJSON, loadMJML)\n // Only update if the editor is not focused (user is not actively editing)\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n if (editor.isFocused) return;\n const currentHTML = editor.getHTML();\n if (currentHTML !== content) {\n editor.commands.setContent(content, false);\n }\n }, [editor, content]);\n\n return (\n <div className={className}>\n <EditorContent editor={editor} />\n </div>\n );\n}\n\nexport { useTipTapEditor };\n","import StarterKit from '@tiptap/starter-kit';\nimport Underline from '@tiptap/extension-underline';\nimport TextAlign from '@tiptap/extension-text-align';\nimport TextStyle from '@tiptap/extension-text-style';\nimport Color from '@tiptap/extension-color';\nimport Highlight from '@tiptap/extension-highlight';\nimport Link from '@tiptap/extension-link';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport { VariableNode } from './VariableNode';\nimport { FontSize } from './FontSize';\nimport { FontFamily } from './FontFamily';\n\nexport function getExtensions(placeholder?: string) {\n return [\n StarterKit.configure({\n history: false,\n }),\n Underline,\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n alignments: ['left', 'center', 'right', 'justify'],\n }),\n TextStyle,\n Color,\n FontSize,\n FontFamily,\n Highlight.configure({\n multicolor: true,\n }),\n Link.configure({\n openOnClick: false,\n HTMLAttributes: {\n rel: 'noopener noreferrer',\n target: '_blank',\n },\n }),\n Placeholder.configure({\n placeholder: placeholder ?? 'Type something...',\n }),\n VariableNode,\n ];\n}\n","import { Node, mergeAttributes } from '@tiptap/core';\n\nexport interface VariableNodeAttrs {\n key: string;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n variableNode: {\n insertVariable: (key: string) => ReturnType;\n };\n }\n}\n\nexport const VariableNode = Node.create({\n name: 'variable',\n group: 'inline',\n inline: true,\n atom: true,\n\n addAttributes() {\n return {\n key: {\n default: '',\n parseHTML: (element: HTMLElement) => element.getAttribute('data-variable-key'),\n renderHTML: (attributes: Record<string, any>) => ({\n 'data-variable-key': attributes.key,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-variable-key]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'span',\n mergeAttributes(HTMLAttributes, {\n class: 'ee-variable-chip',\n contenteditable: 'false',\n }),\n `{{ ${HTMLAttributes['data-variable-key']} }}`,\n ];\n },\n\n addCommands() {\n return {\n insertVariable:\n (key: string) =>\n ({ commands }) => {\n return commands.insertContent({\n type: this.name,\n attrs: { key },\n });\n },\n };\n },\n});\n","import { Extension } from '@tiptap/core';\nimport '@tiptap/extension-text-style';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n fontSize: {\n setFontSize: (size: string) => ReturnType;\n unsetFontSize: () => ReturnType;\n };\n }\n}\n\nexport const FontSize = Extension.create({\n name: 'fontSize',\n\n addOptions() {\n return {\n types: ['textStyle'],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontSize: {\n default: null,\n parseHTML: (element: HTMLElement) => element.style.fontSize || null,\n renderHTML: (attributes: Record<string, any>) => {\n if (!attributes.fontSize) return {};\n return { style: `font-size: ${attributes.fontSize}` };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontSize:\n (fontSize: string) =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontSize }).run();\n },\n unsetFontSize:\n () =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontSize: null }).removeEmptyTextStyle().run();\n },\n };\n },\n});\n","import { Extension } from '@tiptap/core';\nimport '@tiptap/extension-text-style';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n fontFamily: {\n setFontFamily: (fontFamily: string) => ReturnType;\n unsetFontFamily: () => ReturnType;\n };\n }\n}\n\nexport const FontFamily = Extension.create({\n name: 'fontFamily',\n\n addOptions() {\n return {\n types: ['textStyle'],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontFamily: {\n default: null,\n parseHTML: (element: HTMLElement) => element.style.fontFamily?.replace(/['\"]/g, '') || null,\n renderHTML: (attributes: Record<string, any>) => {\n if (!attributes.fontFamily) return {};\n return { style: `font-family: ${attributes.fontFamily}` };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontFamily:\n (fontFamily: string) =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontFamily }).run();\n },\n unsetFontFamily:\n () =>\n ({ chain }) => {\n return chain().setMark('textStyle', { fontFamily: null }).removeEmptyTextStyle().run();\n },\n };\n },\n});\n","/**\n * Sanitize pasted HTML for email safety.\n *\n * Strips Google Docs / Word / web junk and only keeps email-safe\n * tags and a small set of inline styles that TipTap understands.\n */\n\n/** Tags that are safe in email content */\nconst ALLOWED_TAGS = new Set([\n 'p', 'br', 'b', 'strong', 'i', 'em', 'u', 's', 'a', 'span',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li', 'blockquote',\n 'table', 'thead', 'tbody', 'tr', 'td', 'th',\n 'hr', 'div', 'sup', 'sub',\n]);\n\n/** CSS properties that are meaningful in email + TipTap */\nconst ALLOWED_STYLE_PROPS = new Set([\n 'color',\n 'background-color',\n 'font-size',\n 'font-family',\n 'font-weight',\n 'font-style',\n 'text-decoration',\n 'text-align',\n]);\n\n/** Tags that should be removed entirely (including their content) */\nconst REMOVE_WITH_CONTENT = new Set([\n 'style', 'script', 'meta', 'link', 'title', 'head',\n]);\n\nexport function cleanPastedHTML(html: string): string {\n // Strip MS Office / Google Docs conditional comments\n let cleaned = html\n .replace(/<!--\\[if[\\s\\S]*?<!\\[endif\\]-->/gi, '')\n .replace(/<!--[\\s\\S]*?-->/g, '');\n\n // Strip XML namespaced tags (Word's <o:p>, <v:shape>, etc.)\n cleaned = cleaned.replace(/<\\/?[a-z]+:[^>]*>/gi, '');\n\n // Parse into DOM for structured cleaning\n const parser = new DOMParser();\n const doc = parser.parseFromString(cleaned, 'text/html');\n\n cleanNode(doc.body);\n removeEmptyWrappers(doc.body);\n\n return doc.body.innerHTML;\n}\n\nfunction cleanNode(node: Node): void {\n const children = Array.from(node.childNodes);\n\n for (const child of children) {\n if (child.nodeType === Node.COMMENT_NODE) {\n node.removeChild(child);\n continue;\n }\n\n if (child.nodeType === Node.ELEMENT_NODE) {\n const el = child as HTMLElement;\n const tag = el.tagName.toLowerCase();\n\n // Remove tags that should disappear with their content\n if (REMOVE_WITH_CONTENT.has(tag)) {\n node.removeChild(child);\n continue;\n }\n\n // Remove base64 images (too heavy for email)\n if (tag === 'img') {\n const src = el.getAttribute('src') ?? '';\n if (src.startsWith('data:')) {\n node.removeChild(child);\n continue;\n }\n }\n\n if (!ALLOWED_TAGS.has(tag)) {\n // Unwrap: replace element with its children\n const frag = document.createDocumentFragment();\n while (el.firstChild) {\n frag.appendChild(el.firstChild);\n }\n node.replaceChild(frag, child);\n // Re-process from parent since structure changed\n cleanNode(node);\n return;\n }\n\n // Clean attributes: remove everything except href, src, alt, target, rel\n const attrs = Array.from(el.attributes);\n for (const attr of attrs) {\n const name = attr.name.toLowerCase();\n if (name === 'style') continue; // handle below\n if (name === 'href' || name === 'src' || name === 'alt' || name === 'target' || name === 'rel') {\n continue;\n }\n el.removeAttribute(attr.name);\n }\n\n // Sanitize href\n if (el.hasAttribute('href')) {\n const href = el.getAttribute('href') ?? '';\n if (href.toLowerCase().startsWith('javascript:')) {\n el.setAttribute('href', '#');\n }\n }\n\n // Clean inline styles: keep only email-safe properties\n cleanStyles(el);\n\n // Fix Google Docs pattern: <b style=\"font-weight:normal\"> → unwrap\n if ((tag === 'b' || tag === 'strong') && el.style.fontWeight && isNormalWeight(el.style.fontWeight)) {\n el.style.removeProperty('font-weight');\n const frag = document.createDocumentFragment();\n while (el.firstChild) {\n frag.appendChild(el.firstChild);\n }\n node.replaceChild(frag, child);\n cleanNode(node);\n return;\n }\n\n // Recurse\n cleanNode(child);\n }\n }\n}\n\nfunction cleanStyles(el: HTMLElement): void {\n const style = el.getAttribute('style');\n if (!style) return;\n\n const kept: string[] = [];\n // Parse style string into individual declarations\n const declarations = style.split(';');\n for (const decl of declarations) {\n const colonIdx = decl.indexOf(':');\n if (colonIdx === -1) continue;\n const prop = decl.substring(0, colonIdx).trim().toLowerCase();\n const value = decl.substring(colonIdx + 1).trim();\n if (ALLOWED_STYLE_PROPS.has(prop) && value) {\n kept.push(`${prop}: ${value}`);\n }\n }\n\n if (kept.length > 0) {\n el.setAttribute('style', kept.join('; '));\n } else {\n el.removeAttribute('style');\n }\n}\n\nfunction isNormalWeight(weight: string): boolean {\n const w = weight.toLowerCase().trim();\n return w === 'normal' || w === '400';\n}\n\n/** Remove empty span/div wrappers that carry no meaning */\nfunction removeEmptyWrappers(node: Node): void {\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\n const el = child as HTMLElement;\n const tag = el.tagName.toLowerCase();\n\n removeEmptyWrappers(el);\n\n // Empty span/div with no attributes and only whitespace/children\n if ((tag === 'span' || tag === 'div') && el.attributes.length === 0) {\n const frag = document.createDocumentFragment();\n while (el.firstChild) {\n frag.appendChild(el.firstChild);\n }\n node.replaceChild(frag, child);\n }\n }\n}\n","import React, { useState, useCallback, useRef, useEffect } from 'react';\nimport type { Editor } from '@tiptap/core';\nimport { useEditorFonts } from '../../context/EditorContext';\nimport { isSafeURL } from '../../utils/sanitize';\nimport { COLOR_PRESETS } from '../../constants';\nimport styles from '../../styles/toolbar.module.css';\n\ninterface RichTextToolbarProps {\n editor: Editor | null;\n}\n\n/** Prevent mousedown on buttons only so editor keeps focus, but allow selects to work natively */\nfunction preventBlur(e: React.MouseEvent) {\n const target = e.target as HTMLElement;\n const tag = target.tagName.toLowerCase();\n // Allow native behavior for select, option, and color input\n if (tag === 'select' || tag === 'option' || (tag === 'input' && (target as HTMLInputElement).type === 'color')) {\n return;\n }\n e.preventDefault();\n}\n\nexport const RichTextToolbar = React.memo(function RichTextToolbar({ editor }: RichTextToolbarProps) {\n if (!editor) return null;\n\n return (\n <div className={`ee-richtext-toolbar ${styles.richTextToolbar}`} onMouseDown={preventBlur}>\n {/* Font Family */}\n <FontFamilySelect editor={editor} />\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Font Size */}\n <FontSizeSelect editor={editor} />\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Bold / Italic / Underline */}\n <button\n className={`ee-richtext-btn ee-richtext-bold ${styles.richTextBtn} ${editor.isActive('bold') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleBold().run()}\n title=\"Bold (Ctrl+B)\"\n aria-label=\"Bold (Ctrl+B)\"\n aria-pressed={editor.isActive('bold')}\n >\n <strong>B</strong>\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-italic ${styles.richTextBtn} ${editor.isActive('italic') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleItalic().run()}\n title=\"Italic (Ctrl+I)\"\n aria-label=\"Italic (Ctrl+I)\"\n aria-pressed={editor.isActive('italic')}\n >\n <em>I</em>\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-underline ${styles.richTextBtn} ${editor.isActive('underline') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleUnderline().run()}\n title=\"Underline (Ctrl+U)\"\n aria-label=\"Underline (Ctrl+U)\"\n aria-pressed={editor.isActive('underline')}\n >\n <u>U</u>\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-strike ${styles.richTextBtn} ${editor.isActive('strike') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleStrike().run()}\n title=\"Strikethrough (Ctrl+Shift+X)\"\n aria-label=\"Strikethrough (Ctrl+Shift+X)\"\n aria-pressed={editor.isActive('strike')}\n >\n <s>S</s>\n </button>\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Text Color */}\n <InlineColorPicker\n editor={editor}\n type=\"color\"\n title=\"Text Color\"\n label=\"A\"\n />\n\n {/* Highlight Color */}\n <InlineColorPicker\n editor={editor}\n type=\"highlight\"\n title=\"Highlight\"\n label=\"H\"\n />\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Alignment */}\n <button\n className={`ee-richtext-btn ee-richtext-align-left ${styles.richTextBtn} ${editor.isActive({ textAlign: 'left' }) ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().setTextAlign('left').run()}\n title=\"Align Left\"\n aria-label=\"Align Left\"\n aria-pressed={editor.isActive({ textAlign: 'left' })}\n >\n L\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-align-center ${styles.richTextBtn} ${editor.isActive({ textAlign: 'center' }) ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().setTextAlign('center').run()}\n title=\"Align Center\"\n aria-label=\"Align Center\"\n aria-pressed={editor.isActive({ textAlign: 'center' })}\n >\n C\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-align-right ${styles.richTextBtn} ${editor.isActive({ textAlign: 'right' }) ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().setTextAlign('right').run()}\n title=\"Align Right\"\n aria-label=\"Align Right\"\n aria-pressed={editor.isActive({ textAlign: 'right' })}\n >\n R\n </button>\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Lists */}\n <button\n className={`ee-richtext-btn ee-richtext-bullet-list ${styles.richTextBtn} ${editor.isActive('bulletList') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleBulletList().run()}\n title=\"Bullet List\"\n aria-label=\"Bullet List\"\n aria-pressed={editor.isActive('bulletList')}\n >\n &#8226;\n </button>\n <button\n className={`ee-richtext-btn ee-richtext-ordered-list ${styles.richTextBtn} ${editor.isActive('orderedList') ? styles.richTextBtnActive : ''}`}\n onClick={() => editor.chain().focus().toggleOrderedList().run()}\n title=\"Ordered List\"\n aria-label=\"Ordered List\"\n aria-pressed={editor.isActive('orderedList')}\n >\n 1.\n </button>\n\n <div className={`ee-richtext-separator ${styles.richTextSeparator}`} />\n\n {/* Link */}\n <InlineLinkEditor editor={editor} />\n\n {/* Clear formatting */}\n <button\n className={`ee-richtext-btn ee-richtext-clear ${styles.richTextBtn}`}\n onClick={() => editor.chain().focus().unsetAllMarks().run()}\n title=\"Clear Formatting\"\n aria-label=\"Clear Formatting\"\n >\n &#10006;\n </button>\n </div>\n );\n});\n\n// ---- Font Family Select ----\n\nfunction FontFamilySelect({ editor }: { editor: Editor }) {\n const { fontFamilies } = useEditorFonts();\n const currentFont = editor.getAttributes('textStyle').fontFamily || '';\n\n // Include current font if it's not in the predefined list\n const fonts = fontFamilies.slice();\n if (currentFont && !fonts.some((f) => f.toLowerCase() === currentFont.toLowerCase())) {\n fonts.push(currentFont);\n }\n\n return (\n <select\n className={`ee-richtext-font-select ${styles.richTextSelect}`}\n value={currentFont}\n onChange={(e) => {\n const value = e.target.value;\n if (value) {\n editor.chain().focus().setFontFamily(value).run();\n } else {\n editor.chain().focus().unsetFontFamily().run();\n }\n }}\n title=\"Font Family\"\n >\n <option value=\"\">Default</option>\n {fonts.map((font) => (\n <option key={font} value={font} style={{ fontFamily: font }}>\n {font.split(',')[0].trim()}\n </option>\n ))}\n </select>\n );\n}\n\n// ---- Font Size Select ----\n\nfunction FontSizeSelect({ editor }: { editor: Editor }) {\n const { fontSizes } = useEditorFonts();\n const currentSize = editor.getAttributes('textStyle').fontSize || '';\n\n // Build size list, including current size if it's not in the predefined list\n const sizes = fontSizes.slice();\n if (currentSize && !sizes.includes(currentSize)) {\n sizes.push(currentSize);\n sizes.sort((a, b) => parseInt(a, 10) - parseInt(b, 10));\n }\n\n return (\n <select\n className={`ee-richtext-size-select ${styles.richTextSelectSmall}`}\n value={currentSize}\n onChange={(e) => {\n const value = e.target.value;\n if (value) {\n editor.chain().focus().setFontSize(value).run();\n } else {\n editor.chain().focus().unsetFontSize().run();\n }\n }}\n title=\"Font Size\"\n >\n <option value=\"\">Size</option>\n {sizes.map((size) => (\n <option key={size} value={size}>\n {parseInt(size, 10)}\n </option>\n ))}\n </select>\n );\n}\n\n// ---- Inline Color Picker ----\n\ninterface InlineColorPickerProps {\n editor: Editor;\n type: 'color' | 'highlight';\n title: string;\n label: string;\n}\n\n// ---- Inline Link Editor ----\n\nfunction InlineLinkEditor({ editor }: { editor: Editor }) {\n const [isOpen, setIsOpen] = useState(false);\n const [url, setUrl] = useState('');\n const wrapperRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const isActive = editor.isActive('link');\n const currentHref = editor.getAttributes('link').href || '';\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const handleOpen = useCallback(() => {\n setUrl(currentHref);\n setUrlError('');\n setIsOpen(true);\n setTimeout(() => inputRef.current?.focus(), 50);\n }, [currentHref]);\n\n const [urlError, setUrlError] = useState('');\n\n const handleApply = useCallback(() => {\n const trimmed = url.trim();\n if (trimmed) {\n if (!isSafeURL(trimmed)) {\n setUrlError('Only http, https, mailto, and tel URLs are allowed');\n return;\n }\n setUrlError('');\n editor.chain().focus().setLink({ href: trimmed }).run();\n }\n setIsOpen(false);\n }, [editor, url]);\n\n const handleRemove = useCallback(() => {\n editor.chain().focus().unsetLink().run();\n setIsOpen(false);\n setUrl('');\n }, [editor]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleApply();\n } else if (e.key === 'Escape') {\n setIsOpen(false);\n }\n },\n [handleApply],\n );\n\n return (\n <div className={`ee-richtext-link ${styles.richTextColorWrapper}`} ref={wrapperRef}>\n <button\n className={`ee-richtext-btn ee-richtext-link-btn ${styles.richTextBtn} ${isActive ? styles.richTextBtnActive : ''}`}\n onClick={handleOpen}\n title=\"Link\"\n aria-label=\"Link\"\n aria-pressed={isActive}\n >\n &#128279;\n </button>\n {isOpen && (\n <div className={`ee-richtext-link-dropdown ${styles.richTextLinkDropdown}`}>\n <label className={`ee-richtext-link-label ${styles.richTextLinkLabel}`}>URL</label>\n <input\n ref={inputRef}\n className={`ee-richtext-link-input ${styles.richTextLinkInput}`}\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"https://, mailto:, or tel:\"\n />\n {urlError && <div className={`ee-richtext-link-error ${styles.richTextLinkError}`}>{urlError}</div>}\n <div className={`ee-richtext-link-actions ${styles.richTextLinkActions}`}>\n <button className={`ee-richtext-link-apply ${styles.richTextLinkApply}`} onClick={handleApply}>\n Apply\n </button>\n {isActive && (\n <button className={`ee-richtext-link-remove ${styles.richTextLinkRemove}`} onClick={handleRemove}>\n Remove\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction InlineColorPicker({ editor, type, title, label }: InlineColorPickerProps) {\n const [isOpen, setIsOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const currentColor =\n type === 'color'\n ? editor.getAttributes('textStyle').color || '#000000'\n : editor.getAttributes('highlight').color || '';\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const applyColor = useCallback(\n (color: string) => {\n if (type === 'color') {\n editor.chain().focus().setColor(color).run();\n } else {\n editor.chain().focus().toggleHighlight({ color }).run();\n }\n setIsOpen(false);\n },\n [editor, type],\n );\n\n const clearColor = useCallback(() => {\n if (type === 'color') {\n editor.chain().focus().unsetColor().run();\n } else {\n editor.chain().focus().unsetHighlight().run();\n }\n setIsOpen(false);\n }, [editor, type]);\n\n const indicatorColor = type === 'color' ? currentColor : (currentColor || 'transparent');\n\n return (\n <div className={`ee-richtext-color ee-richtext-color--${type} ${styles.richTextColorWrapper}`} ref={wrapperRef}>\n <button\n className={`ee-richtext-btn ee-richtext-color-btn ${styles.richTextBtn}`}\n onClick={() => setIsOpen(!isOpen)}\n title={title}\n aria-label={title}\n aria-expanded={isOpen}\n >\n <span className={`ee-richtext-color-label ${styles.richTextColorLabel}`}>{label}</span>\n <span\n className={`ee-richtext-color-indicator ${styles.richTextColorIndicator}`}\n style={{ backgroundColor: indicatorColor }}\n />\n </button>\n {isOpen && (\n <div className={`ee-richtext-color-dropdown ${styles.richTextColorDropdown}`}>\n <div className={`ee-richtext-color-grid ${styles.richTextColorGrid}`}>\n {COLOR_PRESETS.map((color) => (\n <button\n key={color}\n className={`ee-richtext-color-swatch ${styles.richTextColorSwatch}`}\n style={{ backgroundColor: color }}\n onClick={() => applyColor(color)}\n title={color}\n />\n ))}\n </div>\n <div className={`ee-richtext-color-actions ${styles.richTextColorActions}`}>\n <input\n type=\"color\"\n value={currentColor || '#000000'}\n onChange={(e) => applyColor(e.target.value)}\n className={`ee-richtext-color-input ${styles.richTextColorInput}`}\n title=\"Custom color\"\n />\n <button\n className={`ee-richtext-color-clear ${styles.richTextColorClearBtn}`}\n onClick={clearColor}\n >\n Clear\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n","/* Text Block */\n.textBlock {\n min-height: 24px;\n cursor: text;\n position: relative;\n}\n\n.textBlockToolbar {\n position: sticky;\n top: 0;\n z-index: var(--ee-z-block-toolbar);\n margin-bottom: 4px;\n}\n\n/* Button Block */\n.buttonBlock {\n display: flex;\n padding: 10px 25px;\n}\n\n.buttonBlockLeft {\n justify-content: flex-start;\n}\n\n.buttonBlockCenter {\n justify-content: center;\n}\n\n.buttonBlockRight {\n justify-content: flex-end;\n}\n\n.buttonPreview {\n display: inline-block;\n padding: 12px 24px;\n font-weight: var(--ee-font-weight-medium);\n text-decoration: none;\n cursor: pointer;\n text-align: center;\n line-height: 1.4;\n border: none;\n}\n\n/* Image Block */\n.imageBlock {\n display: flex;\n padding: 10px 25px;\n}\n\n.imageBlockLeft {\n justify-content: flex-start;\n}\n\n.imageBlockCenter {\n justify-content: center;\n}\n\n.imageBlockRight {\n justify-content: flex-end;\n}\n\n.imagePreview {\n max-width: 100%;\n height: auto;\n display: block;\n}\n\n.imagePlaceholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n width: 100%;\n min-height: 120px;\n background: var(--ee-bg-app);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.imagePlaceholder:hover {\n border-color: var(--ee-color-primary);\n color: var(--ee-color-primary);\n background: var(--ee-color-primary-light);\n}\n\n.imagePlaceholderIcon {\n font-size: 32px;\n}\n\n.imageUploading {\n position: relative;\n}\n\n.imageProgress {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 4px;\n background: var(--ee-color-primary);\n border-radius: 2px;\n transition: width 200ms ease;\n}\n\n.imageError {\n color: var(--ee-color-danger);\n font-size: var(--ee-font-size-xs);\n padding: var(--ee-space-xs);\n text-align: center;\n}\n\n/* Divider Block */\n.dividerBlock {\n display: flex;\n align-items: center;\n}\n\n.dividerLine {\n height: 0;\n border: none;\n margin: 0;\n}\n\n/* Spacer Block */\n.spacerBlock {\n position: relative;\n background: repeating-linear-gradient(\n 45deg,\n transparent,\n transparent 5px,\n var(--ee-bg-app) 5px,\n var(--ee-bg-app) 10px\n );\n opacity: 0.5;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.spacerLabel {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-muted);\n background: var(--ee-bg-panel);\n padding: 2px 6px;\n border-radius: 3px;\n}\n\n/* Social Block */\n.socialBlock {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n min-height: 30px;\n}\n\n.socialElement {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.socialIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: bold;\n line-height: 1;\n flex-shrink: 0;\n}\n\n.socialLabel {\n white-space: nowrap;\n}\n\n.socialElementsContainer {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.socialElementItem {\n padding: 8px;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-app);\n}\n\n/* HTML Block */\n.htmlBlock {\n min-height: 24px;\n position: relative;\n}\n\n.htmlPlaceholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n width: 100%;\n min-height: 80px;\n background: var(--ee-bg-app);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n font-family: monospace;\n}\n\n/* Video Block */\n.videoBlock {\n display: flex;\n padding: 10px 25px;\n}\n\n.videoBlockLeft {\n justify-content: flex-start;\n}\n\n.videoBlockCenter {\n justify-content: center;\n}\n\n.videoBlockRight {\n justify-content: flex-end;\n}\n\n.videoPreview {\n position: relative;\n display: inline-block;\n max-width: 100%;\n}\n\n.playOverlay {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 60px;\n height: 60px;\n background: var(--ee-overlay-dark);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--ee-text-inverse);\n font-size: 24px;\n pointer-events: none;\n}\n\n.videoPlaceholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n width: 100%;\n min-height: 120px;\n background: var(--ee-bg-app);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n}\n\n/* Heading Block */\n.headingBlock {\n min-height: 24px;\n cursor: text;\n position: relative;\n}\n\n/* Countdown Block */\n.countdownBlock {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.countdownLabel {\n font-size: 14px;\n font-weight: 500;\n}\n\n.countdownDigits {\n display: flex;\n gap: 12px;\n}\n\n.countdownUnit {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.countdownDigitBox {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 56px;\n padding: 8px 12px;\n border-radius: 6px;\n font-weight: bold;\n font-variant-numeric: tabular-nums;\n}\n\n.countdownUnitLabel {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Menu Block */\n.menuBlock {\n display: flex;\n}\n\n.menuItems {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.menuItem {\n padding: 6px 12px;\n text-decoration: none;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.menuItemsContainer {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.menuItemEntry {\n padding: 8px;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-app);\n}\n\n/* Hero Block */\n.heroBlock {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n min-height: 80px;\n}\n\n.heroHeading {\n margin: 0;\n font-weight: bold;\n line-height: 1.2;\n}\n\n.heroSubtext {\n margin: 0;\n line-height: 1.5;\n}\n\n.heroButton {\n display: inline-block;\n padding: 12px 28px;\n font-weight: 600;\n font-size: 16px;\n text-decoration: none;\n cursor: pointer;\n}\n",".tiptapWrapper {\n position: relative;\n}\n\n.tiptapWrapper :global(.ProseMirror) {\n outline: none;\n min-height: 24px;\n padding: 4px;\n word-break: break-word;\n}\n\n.tiptapWrapper :global(.ProseMirror) p {\n margin: 0 0 0.5em 0;\n}\n\n.tiptapWrapper :global(.ProseMirror) p:last-child {\n margin-bottom: 0;\n}\n\n.tiptapWrapper :global(.ProseMirror) h1,\n.tiptapWrapper :global(.ProseMirror) h2,\n.tiptapWrapper :global(.ProseMirror) h3,\n.tiptapWrapper :global(.ProseMirror) h4 {\n margin: 0 0 0.5em 0;\n line-height: 1.3;\n}\n\n.tiptapWrapper :global(.ProseMirror) ul,\n.tiptapWrapper :global(.ProseMirror) ol {\n margin: 0 0 0.5em 0;\n padding-left: 1.5em;\n}\n\n.tiptapWrapper :global(.ProseMirror) blockquote {\n border-left: 3px solid var(--ee-border-color-strong);\n margin: 0 0 0.5em 0;\n padding-left: 1em;\n color: var(--ee-text-secondary);\n}\n\n.tiptapWrapper :global(.ProseMirror) a {\n color: var(--ee-text-link);\n text-decoration: underline;\n}\n\n/* Variable chips in TipTap */\n.tiptapWrapper :global(.ee-variable-chip) {\n display: inline-flex;\n align-items: center;\n padding: 1px 6px;\n margin: 0 1px;\n font-size: inherit;\n font-family: inherit;\n font-weight: inherit;\n font-style: inherit;\n background: var(--ee-variable-bg);\n color: var(--ee-variable-color);\n border: 1px solid var(--ee-variable-border);\n border-radius: var(--ee-border-radius-sm);\n vertical-align: baseline;\n user-select: none;\n white-space: nowrap;\n}\n\n/* Focus styling */\n.tiptapWrapper :global(.ProseMirror-focused) {\n outline: none;\n}\n\n/* Placeholder — uses TipTap Placeholder extension's data-placeholder attribute */\n.tiptapWrapper :global(.ProseMirror) :global(.is-editor-empty):first-child::before {\n content: attr(data-placeholder);\n float: left;\n color: var(--ee-text-muted);\n pointer-events: none;\n height: 0;\n font-style: italic;\n opacity: 0.6;\n}\n","import React, { useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface ButtonBlockProps {\n block: Block;\n}\n\nexport const ButtonBlock = React.memo(function ButtonBlock({ block }: ButtonBlockProps) {\n const p = block.properties;\n const alignClass =\n p.align === 'left'\n ? styles.buttonBlockLeft\n : p.align === 'right'\n ? styles.buttonBlockRight\n : styles.buttonBlockCenter;\n\n const outerStyle = useMemo(() => ({ padding: p.padding }), [p.padding]);\n const buttonStyle = useMemo(() => ({\n backgroundColor: p.backgroundColor,\n color: p.color,\n fontFamily: p.fontFamily,\n fontSize: p.fontSize,\n borderRadius: p.borderRadius,\n padding: p.innerPadding,\n width: p.width !== 'auto' ? p.width : undefined,\n fontWeight: p.fontWeight,\n textTransform: p.textTransform,\n letterSpacing: p.letterSpacing,\n }), [p.backgroundColor, p.color, p.fontFamily, p.fontSize, p.borderRadius, p.innerPadding, p.width, p.fontWeight, p.textTransform, p.letterSpacing]);\n\n return (\n <div className={`ee-block-button ${styles.buttonBlock} ${alignClass}`} style={outerStyle}>\n <span\n className={styles.buttonPreview}\n style={buttonStyle}\n >\n {p.text}\n </span>\n </div>\n );\n});\n","import React, { useCallback, useRef } from 'react';\nimport type { Block } from '../../../types';\nimport { useEditorDispatch, useConfigContext } from '../../../context/EditorContext';\nimport { useImageUpload } from '../../ImageUpload/useImageUpload';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface ImageBlockProps {\n block: Block;\n}\n\nconst ImageBlockInner = function ImageBlock({ block }: ImageBlockProps) {\n const dispatch = useEditorDispatch();\n const { imageUploadAdapter } = useConfigContext();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const p = block.properties;\n\n const { upload, status } = useImageUpload({\n adapter: imageUploadAdapter,\n blockId: block.id,\n onSuccess: (result) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: {\n blockId: block.id,\n properties: {\n src: result.url,\n alt: result.alt ?? p.alt,\n width: result.width ? `${result.width}px` : p.width,\n },\n },\n });\n },\n });\n\n const alignClass =\n p.align === 'left'\n ? styles.imageBlockLeft\n : p.align === 'right'\n ? styles.imageBlockRight\n : styles.imageBlockCenter;\n\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n await upload(file);\n },\n [upload],\n );\n\n const handlePlaceholderClick = useCallback(() => {\n fileInputRef.current?.click();\n }, []);\n\n return (\n <div className={`ee-block-image ${styles.imageBlock} ${alignClass}`} style={{ padding: p.padding }}>\n {p.src ? (\n <img\n src={p.src}\n alt={p.alt}\n className={styles.imagePreview}\n style={{\n width: p.width,\n height: p.height !== 'auto' ? p.height : undefined,\n }}\n />\n ) : (\n <div className={styles.imagePlaceholder} onClick={handlePlaceholderClick}>\n <span className={styles.imagePlaceholderIcon}>+</span>\n <span>{status === 'uploading' ? 'Uploading...' : 'Click to upload image'}</span>\n </div>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n />\n </div>\n );\n};\n\nexport const ImageBlock = React.memo(ImageBlockInner);\n","import { useState, useCallback, useRef } from 'react';\nimport type { ImageUploadAdapter, UploadResult } from '../../types';\n\nexport type UploadStatus = 'idle' | 'uploading' | 'success' | 'error';\n\ninterface UseImageUploadOptions {\n adapter?: ImageUploadAdapter;\n blockId: string;\n onSuccess?: (result: UploadResult) => void;\n onError?: (error: string) => void;\n}\n\ninterface UseImageUploadReturn {\n status: UploadStatus;\n progress: number;\n error: string | null;\n upload: (file: File) => Promise<UploadResult | null>;\n cancel: () => void;\n browse: () => Promise<UploadResult | null>;\n reset: () => void;\n}\n\nexport function useImageUpload({\n adapter,\n blockId,\n onSuccess,\n onError,\n}: UseImageUploadOptions): UseImageUploadReturn {\n const [status, setStatus] = useState<UploadStatus>('idle');\n const [progress, setProgress] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const controllerRef = useRef<AbortController | null>(null);\n\n const upload = useCallback(\n async (file: File): Promise<UploadResult | null> => {\n if (!adapter) {\n setError('No upload adapter configured');\n setStatus('error');\n return null;\n }\n\n // Validate file\n if (adapter.validate) {\n const validationError = adapter.validate(file);\n if (validationError) {\n setError(validationError);\n setStatus('error');\n onError?.(validationError);\n return null;\n }\n }\n\n // Start upload\n controllerRef.current = new AbortController();\n setStatus('uploading');\n setProgress(0);\n setError(null);\n\n try {\n const result = await adapter.upload(file, {\n context: 'block',\n blockId,\n signal: controllerRef.current.signal,\n });\n\n setStatus('success');\n setProgress(100);\n onSuccess?.(result);\n return result;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n setStatus('idle');\n setProgress(0);\n return null;\n }\n const errorMessage = (err as Error).message || 'Upload failed';\n setError(errorMessage);\n setStatus('error');\n onError?.(errorMessage);\n return null;\n }\n },\n [adapter, blockId, onSuccess, onError],\n );\n\n const cancel = useCallback(() => {\n controllerRef.current?.abort();\n setStatus('idle');\n setProgress(0);\n }, []);\n\n const browse = useCallback(async (): Promise<UploadResult | null> => {\n if (!adapter?.browse) return null;\n try {\n const result = await adapter.browse();\n if (result) {\n onSuccess?.(result);\n }\n return result;\n } catch {\n return null;\n }\n }, [adapter, onSuccess]);\n\n const reset = useCallback(() => {\n setStatus('idle');\n setProgress(0);\n setError(null);\n }, []);\n\n return { status, progress, error, upload, cancel, browse, reset };\n}\n","import React, { useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface DividerBlockProps {\n block: Block;\n}\n\nexport const DividerBlock = React.memo(function DividerBlock({ block }: DividerBlockProps) {\n const p = block.properties;\n\n const outerStyle = useMemo(() => ({ padding: p.padding }), [p.padding]);\n const hrStyle = useMemo(() => ({\n width: p.width,\n borderTop: `${p.borderWidth} ${p.borderStyle} ${p.borderColor}`,\n }), [p.width, p.borderWidth, p.borderStyle, p.borderColor]);\n\n return (\n <div className={`ee-block-divider ${styles.dividerBlock}`} style={outerStyle}>\n <hr\n className={styles.dividerLine}\n style={hrStyle}\n />\n </div>\n );\n});\n","import React from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface SpacerBlockProps {\n block: Block;\n}\n\nexport const SpacerBlock = React.memo(function SpacerBlock({ block }: SpacerBlockProps) {\n const p = block.properties;\n\n return (\n <div className={`ee-block-spacer ${styles.spacerBlock}`} style={{ height: p.height }}>\n <span className={styles.spacerLabel}>{p.height}</span>\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport type { Block, SocialElement } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface SocialBlockProps {\n block: Block;\n}\n\nconst PLATFORM_COLORS: Record<string, string> = {\n facebook: '#3b5998',\n twitter: '#1da1f2',\n instagram: '#e1306c',\n linkedin: '#0077b5',\n youtube: '#ff0000',\n github: '#333333',\n pinterest: '#bd081c',\n snapchat: '#fffc00',\n tiktok: '#000000',\n web: '#4caf50',\n};\n\nexport const SocialBlock = React.memo(function SocialBlock({ block }: SocialBlockProps) {\n const p = block.properties;\n const isVertical = p.mode === 'vertical';\n\n const alignStyle =\n p.align === 'left'\n ? 'flex-start'\n : p.align === 'right'\n ? 'flex-end'\n : 'center';\n\n const iconSizeNum = parseInt(p.iconSize, 10) || 20;\n\n const wrapperStyle = useMemo(() => ({\n padding: p.padding,\n justifyContent: alignStyle,\n flexDirection: (isVertical ? 'column' : 'row') as React.CSSProperties['flexDirection'],\n alignItems: isVertical ? alignStyle : 'center',\n }), [p.padding, alignStyle, isVertical]);\n\n const elementPaddingStyle = useMemo(() => ({\n padding: p.iconPadding,\n }), [p.iconPadding]);\n\n const labelStyle = useMemo(() => ({\n fontSize: p.fontSize, color: p.color,\n }), [p.fontSize, p.color]);\n\n return (\n <div\n className={`ee-block-social ${styles.socialBlock}`}\n style={wrapperStyle}\n >\n {p.elements.map((element: SocialElement) => {\n const bgColor = element.backgroundColor || PLATFORM_COLORS[element.name] || '#999999';\n const initial = element.name.charAt(0).toUpperCase();\n\n return (\n <div\n key={`${element.name}-${element.href}`}\n className={styles.socialElement}\n style={elementPaddingStyle}\n >\n <span\n className={styles.socialIcon}\n style={{\n width: iconSizeNum,\n height: iconSizeNum,\n backgroundColor: bgColor,\n borderRadius: p.borderRadius,\n color: element.color || '#ffffff',\n fontSize: Math.max(10, iconSizeNum * 0.5),\n }}\n >\n {initial}\n </span>\n {element.content && (\n <span\n className={styles.socialLabel}\n style={labelStyle}\n >\n {element.content}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport DOMPurify from 'dompurify';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface HtmlBlockProps {\n block: Block;\n}\n\nexport const HtmlBlock = React.memo(function HtmlBlock({ block }: HtmlBlockProps) {\n const p = block.properties;\n\n const sanitizedContent = useMemo(() => {\n if (!p.content) return '';\n return DOMPurify.sanitize(p.content, {\n ADD_TAGS: ['table', 'thead', 'tbody', 'tr', 'td', 'th'],\n ADD_ATTR: ['style', 'class', 'align', 'valign', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'colspan', 'rowspan', 'width', 'height'],\n });\n }, [p.content]);\n\n if (!p.content) {\n return (\n <div className={`ee-block-html ${styles.htmlBlock}`} style={{ padding: p.padding }}>\n <div className={styles.htmlPlaceholder}>\n <span>&lt;/&gt;</span>\n <span>Raw HTML Block</span>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`ee-block-html ${styles.htmlBlock}`}\n style={{ padding: p.padding }}\n dangerouslySetInnerHTML={{ __html: sanitizedContent }}\n />\n );\n});\n","import React from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface VideoBlockProps {\n block: Block;\n}\n\nexport const VideoBlock = React.memo(function VideoBlock({ block }: VideoBlockProps) {\n const p = block.properties;\n const alignClass = p.align === 'left' ? styles.videoBlockLeft\n : p.align === 'right' ? styles.videoBlockRight\n : styles.videoBlockCenter;\n\n const thumbnailUrl = p.thumbnailUrl || getAutoThumbnail(p.src);\n\n if (!thumbnailUrl && !p.src) {\n return (\n <div className={`ee-block-video ${styles.videoBlock} ${alignClass}`} style={{ padding: p.padding }}>\n <div className={styles.videoPlaceholder}>\n <span style={{ fontSize: '32px' }}>&#9654;</span>\n <span>Video Block</span>\n </div>\n </div>\n );\n }\n\n return (\n <div className={`ee-block-video ${styles.videoBlock} ${alignClass}`} style={{ padding: p.padding }}>\n <div className={styles.videoPreview}>\n {thumbnailUrl ? (\n <img src={thumbnailUrl} alt={p.alt} style={{ maxWidth: '100%', display: 'block' }} />\n ) : (\n <div className={styles.videoPlaceholder}>\n <span style={{ fontSize: '32px' }}>&#9654;</span>\n <span>No thumbnail</span>\n </div>\n )}\n <div className={styles.playOverlay}>&#9654;</div>\n </div>\n </div>\n );\n});\n\nfunction getAutoThumbnail(url: string): string {\n if (!url) return '';\n // YouTube\n const ytMatch = url.match(/(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/);\n if (ytMatch) return `https://img.youtube.com/vi/${ytMatch[1]}/hqdefault.jpg`;\n // Vimeo — can't auto-generate without API, return empty\n return '';\n}\n","import React, { useCallback, useRef, useState, useEffect, useReducer, useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport { useEditorDispatch, useMethodsContext } from '../../../context/EditorContext';\nimport { TipTapEditor } from '../../../tiptap/TipTapEditor';\nimport { RichTextToolbar } from '../../Toolbar/RichTextToolbar';\nimport type { Editor } from '@tiptap/core';\nimport styles from '../../../styles/blocks.module.css';\nimport tiptapStyles from '../../../styles/tiptap.module.css';\n\ninterface HeadingBlockProps {\n block: Block;\n}\n\nconst HEADING_FONT_SIZES: Record<string, string> = {\n h1: '36px',\n h2: '28px',\n h3: '22px',\n h4: '18px',\n};\n\nconst HeadingBlockInner = function HeadingBlock({ block }: HeadingBlockProps) {\n const dispatch = useEditorDispatch();\n const { setActiveEditor } = useMethodsContext();\n const editorRef = useRef<Editor | null>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const blurTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n // Track the editor instance in state so the effect has a proper dependency\n const [editorInstance, setEditorInstance] = useState<Editor | null>(null);\n\n // Force toolbar re-render when editor formatting state changes (selection/transaction)\n const [, forceToolbarUpdate] = useReducer((c: number) => c + 1, 0);\n\n useEffect(() => {\n if (!editorInstance) return;\n\n const onStateChange = () => forceToolbarUpdate();\n editorInstance.on('selectionUpdate', onStateChange);\n editorInstance.on('transaction', onStateChange);\n\n return () => {\n editorInstance.off('selectionUpdate', onStateChange);\n editorInstance.off('transaction', onStateChange);\n };\n }, [editorInstance]);\n\n const handleUpdate = useCallback(\n (html: string) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: { blockId: block.id, properties: { content: html } },\n });\n },\n [dispatch, block.id],\n );\n\n const handleFocus = useCallback(() => {\n setActiveEditor(editorRef.current);\n setIsFocused(true);\n }, [setActiveEditor]);\n\n // Cleanup blur timer on unmount\n useEffect(() => {\n return () => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n };\n }, []);\n\n const handleBlur = useCallback(() => {\n if (blurTimerRef.current !== null) clearTimeout(blurTimerRef.current);\n blurTimerRef.current = setTimeout(() => {\n blurTimerRef.current = null;\n const activeEl = document.activeElement;\n if (wrapperRef.current && wrapperRef.current.contains(activeEl)) {\n return;\n }\n if (editorRef.current && !editorRef.current.isFocused) {\n setActiveEditor(null);\n setIsFocused(false);\n }\n }, 200);\n }, [setActiveEditor]);\n\n const handleEditorRef = useCallback((editor: Editor | null) => {\n editorRef.current = editor;\n setEditorInstance(editor);\n }, []);\n\n const p = block.properties;\n const fontSize = p.fontSize || HEADING_FONT_SIZES[p.level] || '28px';\n\n const wrapperStyle = useMemo(() => ({\n fontFamily: p.fontFamily,\n fontSize,\n color: p.color,\n lineHeight: p.lineHeight,\n padding: p.padding,\n fontWeight: p.fontWeight,\n textTransform: p.textTransform,\n letterSpacing: p.letterSpacing,\n }), [p.fontFamily, fontSize, p.color, p.lineHeight, p.padding, p.fontWeight, p.textTransform, p.letterSpacing]);\n\n return (\n <div className={`ee-block-heading ${styles.headingBlock}`} ref={wrapperRef}>\n {isFocused && editorRef.current && (\n <div className={styles.textBlockToolbar}>\n <RichTextToolbar editor={editorRef.current} />\n </div>\n )}\n <div style={wrapperStyle}>\n <TipTapEditor\n content={p.content}\n onUpdate={handleUpdate}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className={tiptapStyles.tiptapWrapper}\n editorRef={handleEditorRef}\n placeholder=\"Enter heading...\"\n />\n </div>\n </div>\n );\n};\n\nexport const HeadingBlock = React.memo(HeadingBlockInner);\n","import React, { useState, useEffect, useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface CountdownBlockProps {\n block: Block;\n}\n\nfunction getTimeRemaining(targetDate: string) {\n const total = Math.max(0, new Date(targetDate).getTime() - Date.now());\n return {\n days: Math.floor(total / (1000 * 60 * 60 * 24)),\n hours: Math.floor((total / (1000 * 60 * 60)) % 24),\n minutes: Math.floor((total / (1000 * 60)) % 60),\n seconds: Math.floor((total / 1000) % 60),\n };\n}\n\nexport const CountdownBlock = React.memo(function CountdownBlock({ block }: CountdownBlockProps) {\n const p = block.properties;\n const [time, setTime] = useState(() => getTimeRemaining(p.targetDate));\n\n useEffect(() => {\n setTime(getTimeRemaining(p.targetDate));\n const interval = setInterval(() => {\n setTime(getTimeRemaining(p.targetDate));\n }, 1000);\n return () => clearInterval(interval);\n }, [p.targetDate]);\n\n const units = [\n { value: time.days, label: 'Days' },\n { value: time.hours, label: 'Hours' },\n { value: time.minutes, label: 'Minutes' },\n { value: time.seconds, label: 'Seconds' },\n ];\n\n const alignStyle =\n p.align === 'left'\n ? 'flex-start'\n : p.align === 'right'\n ? 'flex-end'\n : 'center';\n\n const wrapperStyle = useMemo(() => ({\n padding: p.padding, justifyContent: alignStyle,\n }), [p.padding, alignStyle]);\n\n const labelStyle = useMemo(() => ({\n color: p.labelColor, textAlign: p.align as React.CSSProperties['textAlign'],\n }), [p.labelColor, p.align]);\n\n const digitsContainerStyle = useMemo(() => ({\n justifyContent: alignStyle,\n }), [alignStyle]);\n\n const digitBoxStyle = useMemo(() => ({\n backgroundColor: p.digitBackgroundColor,\n color: p.digitColor,\n fontSize: p.fontSize,\n }), [p.digitBackgroundColor, p.digitColor, p.fontSize]);\n\n const unitLabelStyle = useMemo(() => ({\n color: p.labelColor,\n }), [p.labelColor]);\n\n return (\n <div className={`ee-block-countdown ${styles.countdownBlock}`} style={wrapperStyle}>\n {p.label && (\n <div className={styles.countdownLabel} style={labelStyle}>\n {p.label}\n </div>\n )}\n <div className={styles.countdownDigits} style={digitsContainerStyle}>\n {units.map((unit) => (\n <div key={unit.label} className={styles.countdownUnit}>\n <div\n className={styles.countdownDigitBox}\n style={digitBoxStyle}\n >\n {String(unit.value).padStart(2, '0')}\n </div>\n <div className={styles.countdownUnitLabel} style={unitLabelStyle}>\n {unit.label}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport type { Block, MenuItem } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface MenuBlockProps {\n block: Block;\n}\n\nexport const MenuBlock = React.memo(function MenuBlock({ block }: MenuBlockProps) {\n const p = block.properties;\n\n const alignStyle =\n p.align === 'left'\n ? 'flex-start'\n : p.align === 'right'\n ? 'flex-end'\n : 'center';\n\n const wrapperStyle = useMemo(() => ({\n padding: p.padding, justifyContent: alignStyle,\n }), [p.padding, alignStyle]);\n\n const itemsStyle = useMemo(() => ({\n justifyContent: alignStyle,\n }), [alignStyle]);\n\n const itemStyle = useMemo(() => ({\n fontFamily: p.fontFamily,\n fontSize: p.fontSize,\n color: p.color,\n }), [p.fontFamily, p.fontSize, p.color]);\n\n return (\n <div className={`ee-block-menu ${styles.menuBlock}`} style={wrapperStyle}>\n <div className={styles.menuItems} style={itemsStyle}>\n {p.items.map((item: MenuItem) => (\n <span\n key={`${item.text}-${item.href}`}\n className={styles.menuItem}\n style={itemStyle}\n >\n {item.text}\n </span>\n ))}\n </div>\n </div>\n );\n});\n","import React, { useMemo } from 'react';\nimport type { Block } from '../../../types';\nimport styles from '../../../styles/blocks.module.css';\n\ninterface HeroBlockProps {\n block: Block;\n}\n\nexport const HeroBlock = React.memo(function HeroBlock({ block }: HeroBlockProps) {\n const p = block.properties;\n\n const containerStyle = useMemo<React.CSSProperties>(() => ({\n padding: p.padding,\n textAlign: p.align,\n backgroundColor: p.backgroundColor || undefined,\n backgroundImage: p.backgroundImage ? `url(${p.backgroundImage})` : undefined,\n backgroundSize: p.backgroundImage ? 'cover' : undefined,\n backgroundPosition: p.backgroundImage ? 'center' : undefined,\n backgroundRepeat: p.backgroundImage ? 'no-repeat' : undefined,\n }), [p.padding, p.align, p.backgroundColor, p.backgroundImage]);\n\n const headingStyle = useMemo(() => ({\n color: p.headingColor,\n fontSize: p.headingFontSize,\n }), [p.headingColor, p.headingFontSize]);\n\n const subtextStyle = useMemo(() => ({\n color: p.subtextColor,\n fontSize: p.subtextFontSize,\n }), [p.subtextColor, p.subtextFontSize]);\n\n const buttonStyle = useMemo(() => ({\n backgroundColor: p.buttonBackgroundColor,\n color: p.buttonColor,\n borderRadius: p.buttonBorderRadius,\n }), [p.buttonBackgroundColor, p.buttonColor, p.buttonBorderRadius]);\n\n return (\n <div className={`ee-block-hero ${styles.heroBlock}`} style={containerStyle}>\n {p.heading && (\n <h2\n className={styles.heroHeading}\n style={headingStyle}\n >\n {p.heading}\n </h2>\n )}\n {p.subtext && (\n <p\n className={styles.heroSubtext}\n style={subtextStyle}\n >\n {p.subtext}\n </p>\n )}\n {p.buttonText && (\n <span\n className={styles.heroButton}\n style={buttonStyle}\n >\n {p.buttonText}\n </span>\n )}\n </div>\n );\n});\n","import React, { useState, useCallback, useRef } from 'react';\nimport { isDropAllowed, getBlockTypeFromDrop, getBlockMoveFromDrop, DND_TYPES } from '../../utils/dnd';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport { generateBlockId } from '../../utils/id';\nimport { DEFAULT_BLOCK_PROPERTIES } from '../../constants';\nimport styles from '../../styles/canvas.module.css';\n\ninterface DropZoneProps {\n sectionId: string;\n columnId: string;\n index: number;\n /** Render as a full-size empty column placeholder */\n emptyPlaceholder?: boolean;\n}\n\nexport const DropZone = React.memo(function DropZone({ sectionId, columnId, index, emptyPlaceholder }: DropZoneProps) {\n const dispatch = useEditorDispatch();\n const [isOver, setIsOver] = useState(false);\n const isOverRef = useRef(false);\n\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!isDropAllowed(e)) return;\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.dropEffect = e.dataTransfer.types.includes(DND_TYPES.BLOCK_ID) ? 'move' : 'copy';\n if (!isOverRef.current) {\n isOverRef.current = true;\n setIsOver(true);\n }\n },\n [],\n );\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n // Only trigger leave if we actually left this element\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX >= rect.left &&\n clientX <= rect.right &&\n clientY >= rect.top &&\n clientY <= rect.bottom\n ) {\n return;\n }\n isOverRef.current = false;\n setIsOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n isOverRef.current = false;\n setIsOver(false);\n\n // Check for new block from palette\n const blockType = getBlockTypeFromDrop(e);\n if (blockType) {\n const block = {\n id: generateBlockId(),\n type: blockType,\n properties: JSON.parse(JSON.stringify(DEFAULT_BLOCK_PROPERTIES[blockType])),\n };\n dispatch({\n type: 'ADD_BLOCK_AND_SELECT',\n payload: { sectionId, columnId, block, index },\n });\n return;\n }\n\n // Check for block move\n const moveData = getBlockMoveFromDrop(e);\n if (moveData) {\n dispatch({\n type: 'MOVE_BLOCK',\n payload: {\n fromSectionId: moveData.sectionId,\n fromColumnId: moveData.columnId,\n blockId: moveData.blockId,\n toSectionId: sectionId,\n toColumnId: columnId,\n toIndex: index,\n },\n });\n }\n },\n [dispatch, sectionId, columnId, index],\n );\n\n if (emptyPlaceholder) {\n return (\n <div\n className={`ee-drop-zone ee-drop-zone--empty ${styles.emptyColumn} ${isOver ? styles.emptyColumnActive : ''}`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isOver ? 'Release to drop' : 'Drag blocks here'}\n </div>\n );\n }\n\n return (\n <div\n className={`ee-drop-zone ${styles.dropZone} ${isOver ? styles.dropZoneActive : ''}`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isOver && <div className={styles.dropZoneLabel}>Drop here</div>}\n </div>\n );\n});\n",".canvasWrapper {\n display: flex;\n justify-content: center;\n padding: var(--ee-space-xl);\n}\n\n.canvasBody {\n width: 600px;\n min-height: 400px;\n background: var(--ee-bg-email-body);\n box-shadow: var(--ee-shadow-lg);\n border-radius: var(--ee-border-radius);\n position: relative;\n transition: box-shadow var(--ee-transition-fast);\n}\n\n.canvasBodyDragOver {\n box-shadow: var(--ee-shadow-lg), 0 0 0 3px var(--ee-dropzone-color);\n}\n\n/* Section */\n.section {\n position: relative;\n border: 1px solid transparent;\n transition: border-color var(--ee-transition-fast);\n cursor: pointer;\n}\n\n.section:hover {\n border-color: var(--ee-border-color-strong);\n}\n\n.section.sectionSelected,\n.sectionSelected:hover {\n border-color: var(--ee-border-selected);\n}\n\n.sectionFullWidth {\n border-left: 3px solid var(--ee-color-primary);\n}\n\n.sectionOverlay {\n position: absolute;\n top: -1px;\n right: -1px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity var(--ee-transition-fast);\n z-index: var(--ee-z-block-overlay);\n}\n\n.section:hover .sectionOverlay {\n opacity: 1;\n}\n\n.sectionBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n font-size: 12px;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.sectionBtn:hover {\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-danger);\n}\n\n.sectionBtnDuplicate:hover {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.sectionDragHandle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n cursor: grab;\n font-size: 14px;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n user-select: none;\n line-height: 1;\n}\n\n.sectionDragHandle:hover {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.sectionDragHandle:active {\n cursor: grabbing;\n}\n\n.sectionContent {\n display: flex;\n min-height: 40px;\n}\n\n/* Column */\n.column {\n flex: 1;\n min-height: 40px;\n padding: 2px;\n position: relative;\n}\n\n/* Block */\n.blockWrapper {\n position: relative;\n border: 1px solid transparent;\n border-radius: var(--ee-border-radius-sm);\n transition: all var(--ee-transition-fast);\n cursor: pointer;\n}\n\n.blockWrapper:hover {\n border-color: var(--ee-border-color-strong);\n}\n\n.blockWrapper.blockSelected,\n.blockSelected:hover {\n border-color: var(--ee-border-selected);\n box-shadow: var(--ee-shadow-focus);\n}\n\n.blockOverlay {\n position: absolute;\n top: -1px;\n right: -1px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity var(--ee-transition-fast);\n z-index: var(--ee-z-block-overlay);\n}\n\n.blockWrapper:hover .blockOverlay {\n opacity: 1;\n}\n\n.blockBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: 3px;\n cursor: pointer;\n font-size: 10px;\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.blockBtn:hover {\n background: var(--ee-color-danger);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-danger);\n}\n\n.blockBtnDuplicate:hover {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.blockWrapper.blockDropBefore {\n box-shadow: 0 -2px 0 0 var(--ee-color-primary);\n}\n\n.blockWrapper.blockDropAfter {\n box-shadow: 0 2px 0 0 var(--ee-color-primary);\n}\n\n/* Drop Zone */\n.dropZone {\n min-height: 2px;\n padding: 4px 0;\n transition: all var(--ee-transition-fast);\n position: relative;\n margin: 0 4px;\n}\n\n.dropZoneActive {\n min-height: var(--ee-dropzone-height-active);\n background: var(--ee-dropzone-bg);\n border: 2px dashed var(--ee-dropzone-color);\n border-radius: var(--ee-border-radius-sm);\n}\n\n.dropZoneLabel {\n position: absolute;\n top: 0; right: 0; bottom: 0; left: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--ee-font-size-xs);\n color: var(--ee-dropzone-color);\n font-weight: var(--ee-font-weight-medium);\n}\n\n/* Empty column */\n.emptyColumn {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100px;\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n margin: var(--ee-space-sm);\n transition: all var(--ee-transition-fast);\n cursor: default;\n}\n\n.emptyColumnActive {\n border-color: var(--ee-dropzone-color);\n background: var(--ee-dropzone-bg);\n color: var(--ee-dropzone-color);\n font-weight: var(--ee-font-weight-medium);\n}\n\n/* Section Drop Zone */\n.sectionDropZone {\n min-height: 2px;\n transition: all var(--ee-transition-fast);\n position: relative;\n}\n\n.sectionDropZoneActive {\n min-height: 40px;\n background: var(--ee-dropzone-bg);\n border: 2px dashed var(--ee-dropzone-color);\n border-radius: var(--ee-border-radius-sm);\n margin: 2px 4px;\n}\n\n.sectionDropZoneLabel {\n position: absolute;\n top: 0; right: 0; bottom: 0; left: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--ee-font-size-xs);\n color: var(--ee-dropzone-color);\n font-weight: var(--ee-font-weight-medium);\n}\n\n/* Add section button */\n.addSectionBtn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--ee-space-sm);\n padding: var(--ee-space-md);\n margin: var(--ee-space-sm) var(--ee-space-lg);\n border: 2px dashed var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n background: transparent;\n color: var(--ee-text-secondary);\n font-size: var(--ee-font-size-sm);\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n width: calc(100% - 2 * var(--ee-space-lg));\n}\n\n.addSectionBtn:hover {\n border-color: var(--ee-color-primary);\n color: var(--ee-color-primary);\n background: var(--ee-color-primary-light);\n}\n","import React, { useState, useCallback, useRef } from 'react';\nimport { isSectionDrop, getSectionMoveFromDrop } from '../../utils/dnd';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport styles from '../../styles/canvas.module.css';\n\ninterface SectionDropZoneProps {\n index: number;\n}\n\nexport const SectionDropZone = React.memo(function SectionDropZone({ index }: SectionDropZoneProps) {\n const dispatch = useEditorDispatch();\n const [isOver, setIsOver] = useState(false);\n const isOverRef = useRef(false);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n if (!isSectionDrop(e)) return;\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.dropEffect = 'move';\n if (!isOverRef.current) {\n isOverRef.current = true;\n setIsOver(true);\n }\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX >= rect.left &&\n clientX <= rect.right &&\n clientY >= rect.top &&\n clientY <= rect.bottom\n ) {\n return;\n }\n isOverRef.current = false;\n setIsOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n isOverRef.current = false;\n setIsOver(false);\n\n const sectionId = getSectionMoveFromDrop(e);\n if (!sectionId) return;\n\n dispatch({\n type: 'MOVE_SECTION',\n payload: { sectionId, toIndex: index },\n });\n },\n [dispatch, index],\n );\n\n return (\n <div\n className={`ee-section-drop-zone ${styles.sectionDropZone} ${isOver ? styles.sectionDropZoneActive : ''}`}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isOver && <div className={styles.sectionDropZoneLabel}>Move section here</div>}\n </div>\n );\n});\n","import React, { useCallback } from 'react';\nimport type { Section } from '../../types';\nimport { useEditorDispatch } from '../../context/EditorContext';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst BG_SIZE_OPTIONS = [\n { value: 'cover', label: 'Cover' }, { value: 'contain', label: 'Contain' }, { value: 'auto', label: 'Auto' },\n];\n\nconst BG_REPEAT_OPTIONS = [\n { value: 'no-repeat', label: 'No Repeat' }, { value: 'repeat', label: 'Repeat' },\n { value: 'repeat-x', label: 'Repeat X' }, { value: 'repeat-y', label: 'Repeat Y' },\n];\n\ninterface SectionPropertiesProps {\n section: Section;\n}\n\nexport function SectionProperties({ section }: SectionPropertiesProps) {\n const dispatch = useEditorDispatch();\n const { properties } = section;\n\n const update = useCallback(\n (props: Record<string, any>) => {\n dispatch({ type: 'UPDATE_SECTION', payload: { sectionId: section.id, properties: props } });\n },\n [dispatch, section.id],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"color\" label=\"Background Color\" value={properties.backgroundColor} onChange={(v) => update({ backgroundColor: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={properties.padding} onChange={(v) => update({ padding: v })} />\n <PropertyField type=\"text\" label=\"Border Radius\" value={properties.borderRadius} onChange={(v) => update({ borderRadius: v })} />\n <PropertyField type=\"toggle\" label=\"Full Width\" value={properties.fullWidth || false} onChange={(v) => update({ fullWidth: v })} />\n <FieldSeparator />\n <PropertyField type=\"text\" label=\"Background Image URL\" value={properties.backgroundImage || ''} onChange={(v) => update({ backgroundImage: v })} placeholder=\"https://...\" />\n <PropertyField type=\"select\" label=\"Background Size\" value={properties.backgroundSize || 'cover'} onChange={(v) => update({ backgroundSize: v })} options={BG_SIZE_OPTIONS} />\n <PropertyField type=\"select\" label=\"Background Repeat\" value={properties.backgroundRepeat || 'no-repeat'} onChange={(v) => update({ backgroundRepeat: v })} options={BG_REPEAT_OPTIONS} />\n </div>\n );\n}\n","import React from 'react';\nimport { ColorPicker } from './controls/ColorPicker';\nimport { PaddingInput } from './controls/PaddingInput';\nimport { AlignmentPicker } from './controls/AlignmentPicker';\nimport { FontPicker } from './controls/FontPicker';\nimport { SliderInput } from './controls/SliderInput';\nimport { LinkInput } from './controls/LinkInput';\nimport styles from '../../styles/properties.module.css';\n\ninterface SelectOption {\n value: string;\n label: string;\n}\n\ntype PropertyFieldProps =\n | { type: 'color'; label: string; value: string; onChange: (v: string) => void }\n | { type: 'text'; label: string; value: string; onChange: (v: string) => void; placeholder?: string }\n | { type: 'textarea'; label: string; value: string; onChange: (v: string) => void; placeholder?: string; rows?: number; code?: boolean }\n | { type: 'select'; label: string; value: string; onChange: (v: string) => void; options: SelectOption[] }\n | { type: 'padding'; label: string; value: string; onChange: (v: string) => void }\n | { type: 'alignment'; label: string; value: string; onChange: (v: string) => void; options?: string[] }\n | { type: 'slider'; label: string; value: number; onChange: (v: number) => void; min: number; max: number; step?: number; unit?: string }\n | { type: 'toggle'; label: string; value: boolean; onChange: (v: boolean) => void }\n | { type: 'font'; label: string; value: string; onChange: (v: string) => void }\n | { type: 'link'; label: string; value: string; onChange: (v: string) => void };\n\n/**\n * Declarative property field that renders the appropriate control.\n * Reduces per-panel boilerplate from repeated JSX to a single component.\n * Wrapped in React.memo to prevent cascading re-renders when sibling fields change.\n */\nexport const PropertyField = React.memo(function PropertyField(props: PropertyFieldProps) {\n switch (props.type) {\n case 'color':\n return <ColorPicker label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'padding':\n return <PaddingInput label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'alignment':\n return <AlignmentPicker label={props.label} value={props.value} onChange={props.onChange} options={props.options} />;\n\n case 'font':\n return <FontPicker label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'link':\n return <LinkInput label={props.label} value={props.value} onChange={props.onChange} />;\n\n case 'slider':\n return (\n <SliderInput\n label={props.label}\n value={props.value}\n min={props.min}\n max={props.max}\n step={props.step}\n unit={props.unit}\n onChange={props.onChange}\n />\n );\n\n case 'toggle':\n return (\n <div className={styles.fieldGroup}>\n <label className={`ee-checkbox-label ${styles.checkboxLabel}`}>\n <input\n type=\"checkbox\"\n checked={props.value}\n onChange={(e) => props.onChange(e.target.checked)}\n />\n {props.label}\n </label>\n </div>\n );\n\n case 'select':\n return (\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>{props.label}</label>\n <select\n className={styles.fieldSelect}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n >\n {props.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n );\n\n case 'textarea':\n return (\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>{props.label}</label>\n <textarea\n className={props.code ? `ee-code-textarea ${styles.fieldTextareaCode}` : styles.fieldTextarea}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n placeholder={props.placeholder}\n rows={props.rows ?? 3}\n />\n </div>\n );\n\n case 'text':\n default:\n return (\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>{props.label}</label>\n <input\n className={styles.fieldInput}\n value={props.value}\n onChange={(e) => props.onChange(e.target.value)}\n placeholder={props.placeholder}\n />\n </div>\n );\n }\n});\n\n/** Visual separator between field groups */\nexport function FieldSeparator() {\n return <div className={styles.separator} />;\n}\n","import React, { useState, useCallback, useRef, useEffect } from 'react';\nimport { COLOR_PRESETS } from '../../../constants';\nimport styles from '../../../styles/properties.module.css';\n\ninterface ColorPickerProps {\n label: string;\n value: string;\n onChange: (color: string) => void;\n}\n\nexport function ColorPicker({ label, value, onChange }: ColorPickerProps) {\n const [isOpen, setIsOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n const handlePresetClick = useCallback(\n (color: string) => {\n onChange(color);\n setIsOpen(false);\n },\n [onChange],\n );\n\n const isHex = /^#[0-9a-fA-F]{6}$/.test(value);\n\n return (\n <div className={`ee-field-group ee-color-picker ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.colorPickerWrapper} ref={wrapperRef}>\n <div\n className={styles.colorPickerTrigger}\n onClick={() => setIsOpen(!isOpen)}\n >\n <div\n className={`${styles.colorSwatch} ${value === 'transparent' ? styles.colorSwatchTransparent : ''}`}\n style={value !== 'transparent' ? { backgroundColor: value || 'transparent' } : undefined}\n />\n <span className={styles.colorValue}>{value || 'transparent'}</span>\n </div>\n {isOpen && (\n <div className={styles.colorPresets}>\n <button\n className={`ee-color-preset-transparent ${styles.colorPresetBtn} ${styles.colorPresetBtnTransparent} ${styles.colorPresetBtnFull} ${\n value === 'transparent' ? styles.colorPresetBtnActive : ''\n }`}\n onClick={() => handlePresetClick('transparent')}\n title=\"transparent\"\n >\n Transparent\n </button>\n {COLOR_PRESETS.map((color) => (\n <button\n key={color}\n className={`${styles.colorPresetBtn} ${\n color === value ? styles.colorPresetBtnActive : ''\n }`}\n style={{ backgroundColor: color }}\n onClick={() => handlePresetClick(color)}\n title={color}\n />\n ))}\n <input\n type=\"color\"\n className={`ee-color-native-input ${styles.colorNativeInput}`}\n value={isHex ? value : '#ffffff'}\n onChange={(e) => onChange(e.target.value)}\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n",".propertiesPanel {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n.propertiesHeader {\n padding: var(--ee-space-md) var(--ee-space-lg);\n border-bottom: 1px solid var(--ee-border-color);\n font-size: var(--ee-font-size-sm);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.propertiesBody {\n padding: var(--ee-space-md) var(--ee-space-lg);\n display: flex;\n flex-direction: column;\n gap: var(--ee-space-md);\n}\n\n.emptyProperties {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: var(--ee-text-muted);\n font-size: var(--ee-font-size-sm);\n text-align: center;\n padding: var(--ee-space-lg);\n}\n\n.fieldHint {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-muted);\n background: var(--ee-bg-hover);\n padding: var(--ee-space-sm) var(--ee-space-md);\n border-radius: var(--ee-border-radius-sm);\n margin: 0;\n line-height: 1.4;\n}\n\n/* Form controls */\n.fieldGroup {\n display: flex;\n flex-direction: column;\n gap: var(--ee-space-xs);\n}\n\n.fieldLabel {\n font-size: var(--ee-font-size-xs);\n font-weight: var(--ee-font-weight-medium);\n color: var(--ee-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.fieldInput {\n width: 100%;\n padding: 6px 8px;\n font-size: var(--ee-font-size-md);\n font-family: var(--ee-font-family);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n outline: none;\n transition: border-color var(--ee-transition-fast);\n box-sizing: border-box;\n}\n\n.fieldInput:focus {\n border-color: var(--ee-border-focus);\n box-shadow: var(--ee-shadow-focus);\n}\n\n.fieldTextarea {\n composes: fieldInput;\n resize: vertical;\n min-height: 60px;\n}\n\n.fieldSelect {\n composes: fieldInput;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M3 5l3 3 3-3z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 8px center;\n padding-right: 24px;\n}\n\n.fieldRow {\n display: flex;\n gap: var(--ee-space-sm);\n align-items: center;\n}\n\n.fieldHalf {\n flex: 1;\n}\n\n/* Color Picker */\n.colorPickerWrapper {\n position: relative;\n}\n\n.colorPickerTrigger {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n padding: 6px 8px;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n cursor: pointer;\n width: 100%;\n box-sizing: border-box;\n}\n\n.colorSwatch {\n width: 20px;\n height: 20px;\n border-radius: 3px;\n border: 1px solid var(--ee-border-color);\n flex-shrink: 0;\n}\n\n.colorValue {\n font-size: var(--ee-font-size-sm);\n color: var(--ee-text-primary);\n font-family: monospace;\n}\n\n.colorPresets {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 4px;\n padding: var(--ee-space-sm);\n background: var(--ee-bg-panel);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n box-shadow: var(--ee-shadow-md);\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: var(--ee-z-dropdown);\n margin-top: 4px;\n}\n\n.colorPresetBtn {\n width: 28px;\n height: 28px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: all var(--ee-transition-fast);\n}\n\n.colorPresetBtn:hover {\n transform: scale(1.15);\n}\n\n.colorPresetBtnActive {\n border-color: var(--ee-color-primary);\n}\n\n.colorPresetBtnTransparent {\n background: repeating-conic-gradient(var(--ee-border-color-strong) 0% 25%, var(--ee-bg-panel) 0% 50%) 0 0 / 12px 12px;\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-secondary);\n font-weight: var(--ee-font-weight-medium);\n height: 24px;\n}\n\n.colorSwatchTransparent {\n background: repeating-conic-gradient(var(--ee-border-color-strong) 0% 25%, var(--ee-bg-panel) 0% 50%) 0 0 / 8px 8px;\n}\n\n/* Padding Input */\n.paddingGrid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--ee-space-xs);\n}\n\n.paddingField {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.paddingLabel {\n font-size: 10px;\n color: var(--ee-text-muted);\n text-align: center;\n}\n\n.paddingInput {\n composes: fieldInput;\n text-align: center;\n padding: 4px;\n font-size: var(--ee-font-size-xs);\n}\n\n/* Alignment Picker */\n.alignmentPicker {\n display: flex;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n overflow: hidden;\n}\n\n.alignmentBtn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n background: var(--ee-bg-input);\n border: none;\n border-right: 1px solid var(--ee-border-color);\n cursor: pointer;\n font-size: var(--ee-font-size-sm);\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.alignmentBtn:last-child {\n border-right: none;\n}\n\n.alignmentBtn:hover {\n background: var(--ee-bg-hover);\n}\n\n.alignmentBtnActive {\n background: var(--ee-color-primary) !important;\n color: var(--ee-text-inverse);\n}\n\n/* Slider Input */\n.sliderWrapper {\n display: flex;\n align-items: center;\n gap: var(--ee-space-sm);\n}\n\n.sliderInput {\n flex: 1;\n height: 4px;\n appearance: none;\n background: var(--ee-border-color);\n border-radius: 2px;\n outline: none;\n}\n\n.sliderInput::-webkit-slider-thumb {\n appearance: none;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--ee-color-primary);\n cursor: pointer;\n}\n\n.sliderInput::-moz-range-thumb {\n width: 14px;\n height: 14px;\n border: none;\n border-radius: 50%;\n background: var(--ee-color-primary);\n cursor: pointer;\n}\n\n.sliderValue {\n font-size: var(--ee-font-size-xs);\n color: var(--ee-text-secondary);\n min-width: 36px;\n text-align: right;\n font-family: monospace;\n}\n\n/* Item action buttons (move up/down, remove) in list editors */\n.itemActionBtn {\n padding: 4px 6px;\n cursor: pointer;\n border: 1px solid var(--ee-border-color);\n border-radius: 3px;\n background: var(--ee-bg-input);\n}\n\n.itemActionBtnDanger {\n composes: itemActionBtn;\n color: var(--ee-color-danger);\n}\n\n/* Add item button (e.g. \"+ Add Item\", \"+ Add Element\") */\n.addItemBtn {\n margin-top: 8px;\n padding: 6px 12px;\n cursor: pointer;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius-sm);\n background: var(--ee-bg-input);\n font-size: var(--ee-font-size-sm);\n width: 100%;\n}\n\n/* Input that stretches to fill remaining row space */\n.fieldInputFlex {\n composes: fieldInput;\n flex: 1;\n}\n\n/* Flex row for link-type input combos */\n.fieldRowCompact {\n display: flex;\n gap: 4px;\n}\n\n.fieldSelectNarrow {\n composes: fieldSelect;\n width: 90px;\n flex-shrink: 0;\n}\n\n/* Monospace textarea for code/HTML editing */\n.fieldTextareaCode {\n composes: fieldInput;\n font-family: monospace;\n font-size: 12px;\n resize: vertical;\n}\n\n/* Upload-style button with centered text */\n.fieldBtnUpload {\n composes: fieldInput;\n cursor: pointer;\n text-align: center;\n}\n\n.fieldBtnUploadDisabled {\n composes: fieldBtnUpload;\n cursor: wait;\n}\n\n/* Validation error message */\n.validationError {\n color: var(--ee-color-danger);\n font-size: var(--ee-font-size-xs);\n margin-top: 2px;\n}\n\n/* Spacing helper for stacked inputs within a list item */\n.fieldInputStacked {\n composes: fieldInput;\n margin-top: 4px;\n}\n\n/* Checkbox label inline */\n.checkboxLabel {\n composes: fieldLabel;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Color picker grid overrides */\n.colorPresetBtnFull {\n grid-column: 1 / -1;\n width: 100%;\n}\n\n.colorNativeInput {\n width: 100%;\n grid-column: 1 / -1;\n height: 28px;\n cursor: pointer;\n border: none;\n}\n\n/* Separator */\n.separator {\n height: 1px;\n background: var(--ee-border-color);\n margin: var(--ee-space-xs) 0;\n}\n","import React, { useCallback, useMemo } from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ninterface PaddingInputProps {\n label: string;\n value: string;\n onChange: (padding: string) => void;\n}\n\nfunction parsePadding(value: string): [string, string, string, string] {\n const parts = value.split(/\\s+/).map((p) => p.trim()).filter(Boolean);\n switch (parts.length) {\n case 1:\n return [parts[0], parts[0], parts[0], parts[0]];\n case 2:\n return [parts[0], parts[1], parts[0], parts[1]];\n case 3:\n return [parts[0], parts[1], parts[2], parts[1]];\n case 4:\n return [parts[0], parts[1], parts[2], parts[3]];\n default:\n return ['0px', '0px', '0px', '0px'];\n }\n}\n\nexport function PaddingInput({ label, value, onChange }: PaddingInputProps) {\n const [top, right, bottom, left] = useMemo(() => parsePadding(value), [value]);\n\n const handleChange = useCallback(\n (position: 'top' | 'right' | 'bottom' | 'left', newVal: string) => {\n const parts = parsePadding(value);\n const idx = { top: 0, right: 1, bottom: 2, left: 3 }[position];\n parts[idx] = newVal || '0px';\n onChange(parts.join(' '));\n },\n [value, onChange],\n );\n\n return (\n <div className={`ee-field-group ee-padding ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.paddingGrid}>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Top</span>\n <input\n className={styles.paddingInput}\n value={top}\n onChange={(e) => handleChange('top', e.target.value)}\n />\n </div>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Right</span>\n <input\n className={styles.paddingInput}\n value={right}\n onChange={(e) => handleChange('right', e.target.value)}\n />\n </div>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Bottom</span>\n <input\n className={styles.paddingInput}\n value={bottom}\n onChange={(e) => handleChange('bottom', e.target.value)}\n />\n </div>\n <div className={styles.paddingField}>\n <span className={styles.paddingLabel}>Left</span>\n <input\n className={styles.paddingInput}\n value={left}\n onChange={(e) => handleChange('left', e.target.value)}\n />\n </div>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ninterface AlignmentPickerProps {\n label: string;\n value: string;\n onChange: (align: string) => void;\n options?: string[];\n}\n\nconst ALIGN_ICONS: Record<string, string> = {\n left: '\\u2261',\n center: '\\u2261',\n right: '\\u2261',\n justify: '\\u2261',\n};\n\nexport function AlignmentPicker({\n label,\n value,\n onChange,\n options = ['left', 'center', 'right'],\n}: AlignmentPickerProps) {\n return (\n <div className={`ee-field-group ee-alignment ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.alignmentPicker}>\n {options.map((option) => (\n <button\n key={option}\n className={`${styles.alignmentBtn} ${\n value === option ? styles.alignmentBtnActive : ''\n }`}\n onClick={() => onChange(option)}\n title={option.charAt(0).toUpperCase() + option.slice(1)}\n >\n {option.charAt(0).toUpperCase()}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { FONT_OPTIONS } from '../../../constants';\nimport styles from '../../../styles/properties.module.css';\n\ninterface FontPickerProps {\n label: string;\n value: string;\n onChange: (font: string) => void;\n}\n\nexport function FontPicker({ label, value, onChange }: FontPickerProps) {\n return (\n <div className={`ee-field-group ee-font-picker ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <select\n className={styles.fieldSelect}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n >\n {FONT_OPTIONS.map((font) => (\n <option key={font} value={font} style={{ fontFamily: font }}>\n {font.split(',')[0].trim()}\n </option>\n ))}\n </select>\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ninterface SliderInputProps {\n label: string;\n value: number;\n min: number;\n max: number;\n step?: number;\n unit?: string;\n onChange: (value: number) => void;\n}\n\nexport function SliderInput({\n label,\n value,\n min,\n max,\n step = 1,\n unit = 'px',\n onChange,\n}: SliderInputProps) {\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(Number(e.target.value));\n },\n [onChange],\n );\n\n return (\n <div className={`ee-field-group ee-slider ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.sliderWrapper}>\n <input\n type=\"range\"\n className={styles.sliderInput}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleChange}\n />\n <span className={styles.sliderValue}>\n {value}{unit}\n </span>\n </div>\n </div>\n );\n}\n","import React, { useState, useCallback, useEffect, useMemo } from 'react';\nimport styles from '../../../styles/properties.module.css';\n\ntype LinkType = 'url' | 'email' | 'phone';\n\nfunction validateLink(value: string, type: LinkType): string | null {\n if (!value) return null;\n if (type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n return 'Invalid email address';\n }\n if (type === 'phone' && !/^[+\\d][\\d\\s\\-().]{4,}$/.test(value)) {\n return 'Invalid phone number';\n }\n if (type === 'url' && value && !/^(https?:\\/\\/|\\/|#)/.test(value)) {\n return 'URL should start with https://';\n }\n return null;\n}\n\ninterface LinkInputProps {\n label: string;\n value: string;\n onChange: (href: string) => void;\n}\n\nfunction detectType(href: string): LinkType {\n if (href.startsWith('mailto:')) return 'email';\n if (href.startsWith('tel:')) return 'phone';\n return 'url';\n}\n\nfunction stripPrefix(href: string, type: LinkType): string {\n if (type === 'email') return href.replace(/^mailto:/, '');\n if (type === 'phone') return href.replace(/^tel:/, '');\n return href;\n}\n\nfunction addPrefix(value: string, type: LinkType): string {\n if (type === 'email' && value && !value.startsWith('mailto:')) return `mailto:${value}`;\n if (type === 'phone' && value && !value.startsWith('tel:')) return `tel:${value}`;\n return value;\n}\n\nexport function LinkInput({ label, value, onChange }: LinkInputProps) {\n const [type, setType] = useState<LinkType>(() => detectType(value));\n const [rawValue, setRawValue] = useState(() => stripPrefix(value, detectType(value)));\n const validationError = useMemo(() => validateLink(rawValue, type), [rawValue, type]);\n\n useEffect(() => {\n const detected = detectType(value);\n setType(detected);\n setRawValue(stripPrefix(value, detected));\n }, [value]);\n\n const handleTypeChange = useCallback(\n (newType: LinkType) => {\n setType(newType);\n onChange(addPrefix(rawValue, newType));\n },\n [rawValue, onChange],\n );\n\n const handleValueChange = useCallback(\n (newValue: string) => {\n setRawValue(newValue);\n onChange(addPrefix(newValue, type));\n },\n [type, onChange],\n );\n\n const placeholder = type === 'email' ? 'user@example.com'\n : type === 'phone' ? '+1234567890'\n : 'https://';\n\n return (\n <div className={`ee-field-group ee-link-input ${styles.fieldGroup}`}>\n <label className={styles.fieldLabel}>{label}</label>\n <div className={styles.fieldRowCompact}>\n <select\n className={styles.fieldSelectNarrow}\n value={type}\n onChange={(e) => handleTypeChange(e.target.value as LinkType)}\n >\n <option value=\"url\">URL</option>\n <option value=\"email\">Email</option>\n <option value=\"phone\">Phone</option>\n </select>\n <input\n className={styles.fieldInputFlex}\n value={rawValue}\n onChange={(e) => handleValueChange(e.target.value)}\n placeholder={placeholder}\n aria-label={label}\n aria-invalid={!!validationError}\n />\n </div>\n {validationError && (\n <span className={`ee-validation-error ${styles.validationError}`} role=\"alert\">\n {validationError}\n </span>\n )}\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { HeadMetadata } from '../../types';\nimport { useTemplateContext, useEditorDispatch } from '../../context/EditorContext';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nexport function HeadMetadataProperties() {\n const { template } = useTemplateContext();\n const dispatch = useEditorDispatch();\n const metadata = template.headMetadata ?? { title: '', previewText: '', headStyles: [] };\n\n const update = useCallback(\n (props: Partial<HeadMetadata>) => {\n dispatch({ type: 'UPDATE_HEAD_METADATA', payload: props });\n },\n [dispatch],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Email Title\" value={metadata.title} onChange={(v) => update({ title: v })} placeholder=\"Email title (mj-title)\" />\n <PropertyField type=\"text\" label=\"Preview Text\" value={metadata.previewText} onChange={(v) => update({ previewText: v })} placeholder=\"Preview text shown in inbox (mj-preview)\" />\n <PropertyField\n type=\"textarea\"\n label=\"Custom Styles\"\n value={metadata.headStyles.join('\\n\\n')}\n onChange={(v) => {\n const headStyles = v.trim() ? [v] : [];\n update({ headStyles });\n }}\n placeholder=\"Custom CSS (mj-style)\"\n rows={6}\n code\n />\n </div>\n );\n}\n","import { useCallback } from 'react';\nimport type { BlockProperties } from '../types';\nimport { useEditorDispatch } from '../context/EditorContext';\n\n/**\n * Hook that returns a memoized `update` function for dispatching UPDATE_BLOCK.\n * Eliminates the repeated useCallback + dispatch boilerplate in every property panel.\n *\n * Accepts `Record<string, unknown>` to avoid `as any` casts when PropertyField\n * onChange returns a plain string for select/alignment values.\n */\nexport function useBlockUpdate(blockId: string) {\n const dispatch = useEditorDispatch();\n\n const update = useCallback(\n (properties: Partial<BlockProperties> | Record<string, unknown>) => {\n dispatch({\n type: 'UPDATE_BLOCK',\n payload: { blockId, properties: properties as Partial<BlockProperties> },\n });\n },\n [dispatch, blockId],\n );\n\n return update;\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface TextPropertiesProps {\n block: Block;\n}\n\nexport function TextProperties({ block }: TextPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <p className={styles.fieldHint}>\n Use the inline toolbar above the text block to format font, size, color, and alignment.\n </p>\n <PropertyField type=\"text\" label=\"Line Height\" value={p.lineHeight} onChange={(v) => update({ lineHeight: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst FONT_WEIGHT_OPTIONS = [\n { value: 'normal', label: 'Normal' }, { value: 'bold', label: 'Bold' },\n { value: '100', label: '100' }, { value: '200', label: '200' },\n { value: '300', label: '300' }, { value: '400', label: '400' },\n { value: '500', label: '500' }, { value: '600', label: '600' },\n { value: '700', label: '700' }, { value: '800', label: '800' },\n { value: '900', label: '900' },\n];\n\nconst TEXT_TRANSFORM_OPTIONS = [\n { value: 'none', label: 'None' }, { value: 'uppercase', label: 'Uppercase' },\n { value: 'lowercase', label: 'Lowercase' }, { value: 'capitalize', label: 'Capitalize' },\n];\n\ninterface ButtonPropertiesProps {\n block: Block;\n}\n\nexport function ButtonProperties({ block }: ButtonPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Button Text\" value={p.text} onChange={(v) => update({ text: v })} />\n <PropertyField type=\"link\" label=\"Link URL\" value={p.href} onChange={(v) => update({ href: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Background Color\" value={p.backgroundColor} onChange={(v) => update({ backgroundColor: v })} />\n <PropertyField type=\"color\" label=\"Text Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"font\" label=\"Font Family\" value={p.fontFamily} onChange={(v) => update({ fontFamily: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"text\" label=\"Border Radius\" value={p.borderRadius} onChange={(v) => update({ borderRadius: v })} />\n <PropertyField type=\"text\" label=\"Width\" value={p.width} onChange={(v) => update({ width: v })} placeholder=\"auto\" />\n <PropertyField type=\"select\" label=\"Font Weight\" value={p.fontWeight || 'normal'} onChange={(v) => update({ fontWeight: v })} options={FONT_WEIGHT_OPTIONS} />\n <PropertyField type=\"select\" label=\"Text Transform\" value={p.textTransform || 'none'} onChange={(v) => update({ textTransform: v })} options={TEXT_TRANSFORM_OPTIONS} />\n <PropertyField type=\"text\" label=\"Letter Spacing\" value={p.letterSpacing || 'normal'} onChange={(v) => update({ letterSpacing: v })} placeholder=\"normal\" />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Outer Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <PropertyField type=\"padding\" label=\"Inner Padding\" value={p.innerPadding} onChange={(v) => update({ innerPadding: v })} />\n </div>\n );\n}\n","import React, { useCallback, useRef } from 'react';\nimport type { Block } from '../../types';\nimport { useImageAdapter } from '../../context/EditorContext';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { useImageUpload } from '../ImageUpload/useImageUpload';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface ImagePropertiesProps {\n block: Block;\n}\n\nexport function ImageProperties({ block }: ImagePropertiesProps) {\n const update = useBlockUpdate(block.id);\n const { imageUploadAdapter } = useImageAdapter();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const p = block.properties;\n\n const { upload, status, error } = useImageUpload({\n adapter: imageUploadAdapter,\n blockId: block.id,\n onSuccess: (result) => {\n update({\n src: result.url,\n alt: result.alt ?? p.alt,\n width: result.width ? `${result.width}px` : p.width,\n });\n },\n });\n\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n await upload(file);\n },\n [upload],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Image URL\" value={p.src} onChange={(v) => update({ src: v })} placeholder=\"https://...\" />\n {imageUploadAdapter && (\n <div className={styles.fieldGroup}>\n <button\n className={`ee-upload-btn ${status === 'uploading' ? styles.fieldBtnUploadDisabled : styles.fieldBtnUpload}`}\n onClick={() => fileInputRef.current?.click()}\n disabled={status === 'uploading'}\n >\n {status === 'uploading' ? 'Uploading...' : 'Upload Image'}\n </button>\n {error && <span className={`ee-upload-error ${styles.validationError}`}>{error}</span>}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n />\n </div>\n )}\n <PropertyField type=\"text\" label=\"Alt Text\" value={p.alt} onChange={(v) => update({ alt: v })} placeholder=\"Image description\" />\n <PropertyField type=\"link\" label=\"Link URL\" value={p.href} onChange={(v) => update({ href: v })} />\n <FieldSeparator />\n <div className={styles.fieldRow}>\n <div className={styles.fieldHalf}>\n <PropertyField type=\"text\" label=\"Width\" value={p.width} onChange={(v) => update({ width: v })} />\n </div>\n <div className={styles.fieldHalf}>\n <PropertyField type=\"text\" label=\"Height\" value={p.height} onChange={(v) => update({ height: v })} />\n </div>\n </div>\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <PropertyField type=\"toggle\" label=\"Fluid on Mobile\" value={p.fluidOnMobile} onChange={(v) => update({ fluidOnMobile: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst BORDER_STYLE_OPTIONS = [\n { value: 'solid', label: 'Solid' },\n { value: 'dashed', label: 'Dashed' },\n { value: 'dotted', label: 'Dotted' },\n];\n\ninterface DividerPropertiesProps {\n block: Block;\n}\n\nexport function DividerProperties({ block }: DividerPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"color\" label=\"Border Color\" value={p.borderColor} onChange={(v) => update({ borderColor: v })} />\n <PropertyField type=\"text\" label=\"Border Width\" value={p.borderWidth} onChange={(v) => update({ borderWidth: v })} />\n <PropertyField type=\"select\" label=\"Border Style\" value={p.borderStyle} onChange={(v) => update({ borderStyle: v })} options={BORDER_STYLE_OPTIONS} />\n <PropertyField type=\"text\" label=\"Width\" value={p.width} onChange={(v) => update({ width: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface SpacerPropertiesProps {\n block: Block;\n}\n\nexport function SpacerProperties({ block }: SpacerPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n const heightNum = parseInt(p.height, 10) || 20;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"slider\" label=\"Height\" value={heightNum} min={5} max={200} step={5} unit=\"px\" onChange={(v) => update({ height: `${v}px` })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block, SocialElement } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { generateId } from '../../utils/id';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\nimport blockStyles from '../../styles/blocks.module.css';\n\nconst MODE_OPTIONS = [\n { value: 'horizontal', label: 'Horizontal' }, { value: 'vertical', label: 'Vertical' },\n];\n\ninterface SocialPropertiesProps {\n block: Block;\n}\n\nexport function SocialProperties({ block }: SocialPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n const updateElement = useCallback(\n (index: number, changes: Partial<SocialElement>) => {\n const elements = [...block.properties.elements];\n elements[index] = { ...elements[index], ...changes };\n update({ elements });\n },\n [block.properties.elements, update],\n );\n\n const addElement = useCallback(() => {\n const elements = [...block.properties.elements, { id: generateId('se'), name: 'web', href: '#' }];\n update({ elements });\n }, [block.properties.elements, update]);\n\n const removeElement = useCallback(\n (index: number) => {\n const elements = block.properties.elements.filter((_: any, i: number) => i !== index);\n update({ elements });\n },\n [block.properties.elements, update],\n );\n\n const moveElement = useCallback(\n (index: number, direction: -1 | 1) => {\n const elements = [...block.properties.elements];\n const newIndex = index + direction;\n if (newIndex < 0 || newIndex >= elements.length) return;\n [elements[index], elements[newIndex]] = [elements[newIndex], elements[index]];\n update({ elements });\n },\n [block.properties.elements, update],\n );\n\n if (!narrowBlock(block, 'social')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"select\" label=\"Mode\" value={p.mode} onChange={(v) => update({ mode: v })} options={MODE_OPTIONS} />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"text\" label=\"Icon Size\" value={p.iconSize} onChange={(v) => update({ iconSize: v })} />\n <PropertyField type=\"text\" label=\"Icon Padding\" value={p.iconPadding} onChange={(v) => update({ iconPadding: v })} />\n <PropertyField type=\"text\" label=\"Border Radius\" value={p.borderRadius} onChange={(v) => update({ borderRadius: v })} />\n <PropertyField type=\"color\" label=\"Text Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <FieldSeparator />\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Social Elements</label>\n <div className={blockStyles.socialElementsContainer}>\n {p.elements.map((element: SocialElement, index: number) => (\n <div key={element.id ?? `se-${index}`} className={blockStyles.socialElementItem}>\n <div className={styles.fieldRow}>\n <select\n className={`${styles.fieldSelect} ${styles.fieldInputFlex}`}\n value={element.name}\n onChange={(e) => updateElement(index, { name: e.target.value })}\n >\n <option value=\"facebook\">Facebook</option>\n <option value=\"twitter\">Twitter</option>\n <option value=\"instagram\">Instagram</option>\n <option value=\"linkedin\">LinkedIn</option>\n <option value=\"youtube\">YouTube</option>\n <option value=\"github\">GitHub</option>\n <option value=\"pinterest\">Pinterest</option>\n <option value=\"snapchat\">Snapchat</option>\n <option value=\"tiktok\">TikTok</option>\n <option value=\"web\">Web</option>\n </select>\n <button className={`ee-item-move-up ${styles.itemActionBtn}`} onClick={() => moveElement(index, -1)} disabled={index === 0} title=\"Move up\">↑</button>\n <button className={`ee-item-move-down ${styles.itemActionBtn}`} onClick={() => moveElement(index, 1)} disabled={index === p.elements.length - 1} title=\"Move down\">↓</button>\n <button className={`ee-item-remove ${styles.itemActionBtnDanger}`} onClick={() => removeElement(index)} title=\"Remove\">×</button>\n </div>\n <input\n className={styles.fieldInputStacked}\n value={element.href}\n onChange={(e) => updateElement(index, { href: e.target.value })}\n placeholder=\"URL\"\n />\n <input\n className={styles.fieldInputStacked}\n value={element.content || ''}\n onChange={(e) => updateElement(index, { content: e.target.value })}\n placeholder=\"Label (optional)\"\n />\n </div>\n ))}\n </div>\n <button className={`ee-add-item ${styles.addItemBtn}`} onClick={addElement}>+ Add Element</button>\n </div>\n </div>\n );\n}\n","// ---- Block Types ----\n\nexport type BlockType = 'text' | 'button' | 'image' | 'divider' | 'spacer' | 'social' | 'html' | 'video' | 'heading' | 'countdown' | 'menu' | 'hero';\n\nexport interface TextBlockProperties {\n content: string; // TipTap JSON string\n fontFamily: string;\n fontSize: string;\n color: string;\n lineHeight: string;\n padding: string;\n align: 'left' | 'center' | 'right' | 'justify';\n fontWeight: string;\n textTransform: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n letterSpacing: string;\n}\n\nexport interface ButtonBlockProperties {\n text: string;\n href: string;\n backgroundColor: string;\n color: string;\n fontFamily: string;\n fontSize: string;\n borderRadius: string;\n padding: string;\n innerPadding: string;\n align: 'left' | 'center' | 'right';\n width: string;\n fontWeight: string;\n textTransform: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n letterSpacing: string;\n}\n\nexport interface ImageBlockProperties {\n src: string;\n alt: string;\n href: string;\n width: string;\n height: string;\n padding: string;\n align: 'left' | 'center' | 'right';\n fluidOnMobile: boolean;\n}\n\nexport interface DividerBlockProperties {\n borderColor: string;\n borderWidth: string;\n borderStyle: 'solid' | 'dashed' | 'dotted';\n padding: string;\n width: string;\n}\n\nexport interface SpacerBlockProperties {\n height: string;\n}\n\nexport interface SocialElement {\n id?: string;\n name: string;\n href: string;\n src?: string;\n content?: string;\n backgroundColor?: string;\n color?: string;\n}\n\nexport interface SocialBlockProperties {\n elements: SocialElement[];\n mode: 'horizontal' | 'vertical';\n align: 'left' | 'center' | 'right';\n iconSize: string;\n iconPadding: string;\n padding: string;\n fontSize: string;\n color: string;\n borderRadius: string;\n}\n\nexport interface HtmlBlockProperties {\n content: string;\n padding: string;\n}\n\nexport interface VideoBlockProperties {\n src: string;\n thumbnailUrl: string;\n alt: string;\n padding: string;\n align: 'left' | 'center' | 'right';\n}\n\nexport interface HeadingBlockProperties {\n content: string;\n level: 'h1' | 'h2' | 'h3' | 'h4';\n fontFamily: string;\n fontSize: string;\n color: string;\n lineHeight: string;\n fontWeight: string;\n padding: string;\n align: 'left' | 'center' | 'right' | 'justify';\n textTransform: 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n letterSpacing: string;\n}\n\nexport interface CountdownBlockProperties {\n targetDate: string;\n label: string;\n digitBackgroundColor: string;\n digitColor: string;\n labelColor: string;\n fontSize: string;\n padding: string;\n align: 'left' | 'center' | 'right';\n}\n\nexport interface MenuItem {\n id?: string;\n text: string;\n href: string;\n}\n\nexport interface MenuBlockProperties {\n items: MenuItem[];\n align: 'left' | 'center' | 'right';\n fontFamily: string;\n fontSize: string;\n color: string;\n padding: string;\n hamburger: boolean;\n iconColor: string;\n}\n\nexport interface HeroBlockProperties {\n heading: string;\n subtext: string;\n buttonText: string;\n buttonHref: string;\n headingColor: string;\n headingFontSize: string;\n subtextColor: string;\n subtextFontSize: string;\n buttonBackgroundColor: string;\n buttonColor: string;\n buttonBorderRadius: string;\n align: 'left' | 'center' | 'right';\n padding: string;\n backgroundImage: string;\n backgroundColor: string;\n}\n\nexport type BlockProperties =\n | TextBlockProperties\n | ButtonBlockProperties\n | ImageBlockProperties\n | DividerBlockProperties\n | SpacerBlockProperties\n | SocialBlockProperties\n | HtmlBlockProperties\n | VideoBlockProperties\n | HeadingBlockProperties\n | CountdownBlockProperties\n | MenuBlockProperties\n | HeroBlockProperties;\n\nexport interface BlockPropertiesMap {\n text: TextBlockProperties;\n button: ButtonBlockProperties;\n image: ImageBlockProperties;\n divider: DividerBlockProperties;\n spacer: SpacerBlockProperties;\n social: SocialBlockProperties;\n html: HtmlBlockProperties;\n video: VideoBlockProperties;\n heading: HeadingBlockProperties;\n countdown: CountdownBlockProperties;\n menu: MenuBlockProperties;\n hero: HeroBlockProperties;\n}\n\nexport interface Block<T extends BlockType = BlockType> {\n id: string;\n type: T;\n properties: Record<string, any>;\n}\n\n/** A Block with type-safe properties, returned by narrowBlock */\nexport interface TypedBlock<T extends BlockType> extends Block<T> {\n properties: BlockPropertiesMap[T];\n}\n\n/** Narrow a Block to a specific type for type-safe property access */\nexport function narrowBlock<T extends BlockType>(block: Block, type: T): block is TypedBlock<T> {\n return block.type === type;\n}\n\n// ---- Layout ----\n\nexport interface Column {\n id: string;\n width: string;\n blocks: Block[];\n}\n\nexport interface SectionProperties {\n backgroundColor: string;\n padding: string;\n borderRadius: string;\n fullWidth: boolean;\n backgroundImage?: string;\n backgroundSize?: string;\n backgroundRepeat?: string;\n}\n\nexport interface Section {\n id: string;\n columns: Column[];\n properties: SectionProperties;\n}\n\n// ---- Template ----\n\nexport interface GlobalStyles {\n backgroundColor: string;\n width: number;\n fontFamily: string;\n}\n\nexport interface HeadMetadata {\n title: string;\n previewText: string;\n headStyles: string[];\n}\n\nexport interface EmailTemplate {\n sections: Section[];\n globalStyles: GlobalStyles;\n headMetadata?: HeadMetadata;\n}\n\n// ---- Variables ----\n\nexport interface Variable {\n key: string;\n icon?: string;\n sample?: string;\n label?: string;\n group?: string;\n}\n\nexport interface VariableChipStyle {\n backgroundColor: string;\n color: string;\n borderColor: string;\n fontSize: string;\n borderRadius: string;\n}\n\n// ---- Persistence ----\n\nexport interface PersistenceAdapter {\n save(key: string, template: EmailTemplate): void | Promise<void>;\n load(key: string): EmailTemplate | null | Promise<EmailTemplate | null>;\n remove(key: string): void | Promise<void>;\n}\n\n// ---- Image Upload ----\n\nexport interface UploadOptions {\n context: string;\n blockId: string;\n signal: AbortSignal;\n}\n\nexport interface UploadResult {\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n}\n\nexport interface BrowseResult {\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n}\n\nexport interface TransformOptions {\n width: number;\n height?: number;\n fit: string;\n format: string;\n quality: number;\n}\n\nexport interface ImageUploadAdapter {\n upload: (file: File, opts?: UploadOptions) => Promise<UploadResult>;\n browse?: () => Promise<BrowseResult | null>;\n delete?: (url: string) => Promise<void>;\n validate?: (file: File) => string | null;\n transform?: (url: string, opts: TransformOptions) => string;\n}\n\n// ---- Editor ----\n\nexport type ActiveTab = 'visual' | 'source' | 'preview';\n\nexport interface SelectionState {\n sectionId: string | null;\n columnId: string | null;\n blockId: string | null;\n}\n\nexport interface EditorState {\n template: EmailTemplate;\n selection: SelectionState;\n activeTab: ActiveTab;\n history: EmailTemplate[];\n historyIndex: number;\n isDirty: boolean;\n blockIndex: Map<string, { sectionId: string; columnId: string }>;\n}\n\n// ---- Editor Actions ----\n\nexport type EditorAction =\n | { type: 'SET_TEMPLATE'; payload: EmailTemplate }\n | { type: 'ADD_SECTION'; payload: { section: Section; index?: number } }\n | { type: 'REMOVE_SECTION'; payload: { sectionId: string } }\n | { type: 'MOVE_SECTION'; payload: { sectionId: string; toIndex: number } }\n | { type: 'UPDATE_SECTION'; payload: { sectionId: string; properties: Partial<SectionProperties> } }\n | { type: 'ADD_BLOCK'; payload: { sectionId: string; columnId: string; block: Block; index?: number } }\n | { type: 'REMOVE_BLOCK'; payload: { sectionId: string; columnId: string; blockId: string } }\n | { type: 'MOVE_BLOCK'; payload: { fromSectionId: string; fromColumnId: string; blockId: string; toSectionId: string; toColumnId: string; toIndex: number } }\n | { type: 'UPDATE_BLOCK'; payload: { blockId: string; properties: Partial<BlockProperties> } }\n | { type: 'SELECT_BLOCK'; payload: { sectionId: string; columnId: string; blockId: string } | null }\n | { type: 'SELECT_SECTION'; payload: { sectionId: string } | null }\n | { type: 'SET_ACTIVE_TAB'; payload: ActiveTab }\n | { type: 'UPDATE_GLOBAL_STYLES'; payload: Partial<GlobalStyles> }\n | { type: 'UPDATE_HEAD_METADATA'; payload: Partial<HeadMetadata> }\n | { type: 'DUPLICATE_BLOCK'; payload: { sectionId: string; columnId: string; blockId: string } }\n | { type: 'DUPLICATE_SECTION'; payload: { sectionId: string } }\n | { type: 'ADD_BLOCK_AND_SELECT'; payload: { sectionId: string; columnId: string; block: Block; index?: number } }\n | { type: 'ADD_SECTION_WITH_BLOCK'; payload: { section: Section; block: Block; index?: number } }\n | { type: 'DESELECT_ALL' }\n | { type: 'UNDO' }\n | { type: 'REDO' }\n | { type: 'PUSH_HISTORY' };\n\n// ---- Props ----\n\nexport interface EmailEditorProps {\n initialTemplate?: EmailTemplate;\n initialMJML?: string;\n variables?: Variable[];\n imageUploadAdapter?: ImageUploadAdapter;\n onChange?: (template: EmailTemplate) => void;\n onSave?: (mjml: string, html: string) => void;\n onReady?: () => void;\n /** Called when custom variables are added or removed by the user. Receives all custom variables. */\n onVariablesChange?: (customVariables: Variable[]) => void;\n /** Custom font family options for the rich text toolbar. Falls back to FONT_OPTIONS constant. */\n fontFamilies?: string[];\n /** Custom font size options for the rich text toolbar (e.g. ['12px', '14px', '16px']). Falls back to DEFAULT_FONT_SIZES constant. */\n fontSizes?: string[];\n /** Custom block definitions for the sidebar palette. Override icons, labels, descriptions, or hide specific blocks. Falls back to BLOCK_DEFINITIONS constant. */\n blockDefinitions?: import('./constants').BlockDefinition[];\n /** Key for auto-persisting the template. Different keys allow multiple editor instances to coexist. */\n persistenceKey?: string;\n /** Custom persistence adapter. Defaults to localStorage when persistenceKey is set. */\n persistenceAdapter?: PersistenceAdapter;\n className?: string;\n style?: React.CSSProperties;\n\n // Event callbacks for host app integration\n /** Called when a block is added to the template */\n onBlockAdd?: (block: Block, sectionId: string, columnId: string) => void;\n /** Called when a block is removed from the template */\n onBlockRemove?: (blockId: string, sectionId: string, columnId: string) => void;\n /** Called when block properties are updated */\n onBlockUpdate?: (blockId: string, properties: Partial<BlockProperties>) => void;\n /** Called when a block is moved to a new position */\n onBlockMove?: (blockId: string, toSectionId: string, toColumnId: string, toIndex: number) => void;\n /** Called when a section is added to the template */\n onSectionAdd?: (section: Section, index?: number) => void;\n /** Called when a section is removed from the template */\n onSectionRemove?: (sectionId: string) => void;\n /** Called when a section is moved to a new position */\n onSectionMove?: (sectionId: string, toIndex: number) => void;\n /** Called when the selection changes */\n onSelectionChange?: (selection: SelectionState) => void;\n /** Called when a template is loaded via SET_TEMPLATE */\n onTemplateLoad?: (template: EmailTemplate) => void;\n /** Called when history state changes (undo/redo) */\n onHistoryChange?: (canUndo: boolean, canRedo: boolean) => void;\n}\n\nexport interface EmailEditorRef {\n getMJML: () => string;\n getHTML: () => Promise<string>;\n getJSON: () => EmailTemplate;\n loadMJML: (source: string) => void;\n loadJSON: (template: EmailTemplate) => void;\n insertBlock: (type: BlockType, sectionIdx?: number) => void;\n getVariables: () => string[];\n undo: () => void;\n redo: () => void;\n reset: () => void;\n exportPDF: () => Promise<void>;\n /** Remove persisted template data for the current persistenceKey. No-op if no key is set. */\n clearPersisted: () => void;\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface HtmlPropertiesProps {\n block: Block;\n}\n\nexport function HtmlProperties({ block }: HtmlPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"textarea\" label=\"HTML Content\" value={p.content} onChange={(v) => update({ content: v })} placeholder=\"<p>Enter raw HTML here...</p>\" rows={10} code />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block, VideoBlockProperties } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface VideoPropertiesProps {\n block: Block;\n}\n\nfunction getAutoThumbnail(url: string): string {\n if (!url) return '';\n const ytMatch = url.match(/(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/);\n if (ytMatch) return `https://img.youtube.com/vi/${ytMatch[1]}/hqdefault.jpg`;\n return '';\n}\n\nexport function VideoProperties({ block }: VideoPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n const handleVideoUrlChange = useCallback(\n (src: string) => {\n const updates: Partial<VideoBlockProperties> = { src };\n if (!p.thumbnailUrl) {\n const auto = getAutoThumbnail(src);\n if (auto) updates.thumbnailUrl = auto;\n }\n update(updates);\n },\n [update, p.thumbnailUrl],\n );\n\n const handleAutoThumbnail = useCallback(() => {\n const auto = getAutoThumbnail(p.src);\n if (auto) update({ thumbnailUrl: auto });\n }, [update, p.src]);\n\n return (\n <div className={styles.propertiesBody}>\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Video URL</label>\n <input\n className={styles.fieldInput}\n value={p.src}\n onChange={(e) => handleVideoUrlChange(e.target.value)}\n placeholder=\"https://youtube.com/watch?v=...\"\n />\n </div>\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Thumbnail URL</label>\n <input\n className={styles.fieldInput}\n value={p.thumbnailUrl}\n onChange={(e) => update({ thumbnailUrl: e.target.value })}\n placeholder=\"https://...\"\n />\n {p.src && (\n <button\n className={`ee-auto-thumbnail ${styles.fieldBtnUpload} ${styles.fieldInputStacked}`}\n onClick={handleAutoThumbnail}\n >\n Auto-generate from URL\n </button>\n )}\n </div>\n <PropertyField type=\"text\" label=\"Alt Text\" value={p.alt} onChange={(v) => update({ alt: v })} placeholder=\"Video description\" />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\nconst LEVEL_OPTIONS = [\n { value: 'h1', label: 'H1' }, { value: 'h2', label: 'H2' },\n { value: 'h3', label: 'H3' }, { value: 'h4', label: 'H4' },\n];\n\nconst FONT_WEIGHT_OPTIONS = [\n { value: 'normal', label: 'Normal' }, { value: 'bold', label: 'Bold' },\n { value: '100', label: '100' }, { value: '200', label: '200' },\n { value: '300', label: '300' }, { value: '400', label: '400' },\n { value: '500', label: '500' }, { value: '600', label: '600' },\n { value: '700', label: '700' }, { value: '800', label: '800' },\n { value: '900', label: '900' },\n];\n\nconst TEXT_TRANSFORM_OPTIONS = [\n { value: 'none', label: 'None' }, { value: 'uppercase', label: 'Uppercase' },\n { value: 'lowercase', label: 'Lowercase' }, { value: 'capitalize', label: 'Capitalize' },\n];\n\nconst LEVEL_DEFAULTS: Record<string, { fontSize: string; lineHeight: string }> = {\n h1: { fontSize: '36px', lineHeight: '1.2' },\n h2: { fontSize: '28px', lineHeight: '1.3' },\n h3: { fontSize: '22px', lineHeight: '1.3' },\n h4: { fontSize: '18px', lineHeight: '1.4' },\n};\n\ninterface HeadingPropertiesProps {\n block: Block;\n}\n\nexport function HeadingProperties({ block }: HeadingPropertiesProps) {\n const update = useBlockUpdate(block.id);\n const p = block.properties;\n\n const handleLevelChange = useCallback(\n (level: string) => {\n const defaults = LEVEL_DEFAULTS[level] || LEVEL_DEFAULTS.h2;\n update({ level: level, fontSize: defaults.fontSize, lineHeight: defaults.lineHeight });\n },\n [update],\n );\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"select\" label=\"Heading Level\" value={p.level} onChange={handleLevelChange} options={LEVEL_OPTIONS} />\n <FieldSeparator />\n <PropertyField type=\"font\" label=\"Font Family\" value={p.fontFamily} onChange={(v) => update({ fontFamily: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"color\" label=\"Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"text\" label=\"Line Height\" value={p.lineHeight} onChange={(v) => update({ lineHeight: v })} />\n <PropertyField type=\"select\" label=\"Font Weight\" value={p.fontWeight || 'bold'} onChange={(v) => update({ fontWeight: v })} options={FONT_WEIGHT_OPTIONS} />\n <PropertyField type=\"select\" label=\"Text Transform\" value={p.textTransform || 'none'} onChange={(v) => update({ textTransform: v })} options={TEXT_TRANSFORM_OPTIONS} />\n <PropertyField type=\"text\" label=\"Letter Spacing\" value={p.letterSpacing || 'normal'} onChange={(v) => update({ letterSpacing: v })} placeholder=\"normal\" />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface CountdownPropertiesProps {\n block: Block;\n}\n\nexport function CountdownProperties({ block }: CountdownPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n if (!narrowBlock(block, 'countdown')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Target Date</label>\n <input\n className={styles.fieldInput}\n type=\"datetime-local\"\n value={p.targetDate}\n onChange={(e) => update({ targetDate: e.target.value })}\n />\n </div>\n <PropertyField type=\"text\" label=\"Label\" value={p.label} onChange={(v) => update({ label: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Digit Background\" value={p.digitBackgroundColor} onChange={(v) => update({ digitBackgroundColor: v })} />\n <PropertyField type=\"color\" label=\"Digit Color\" value={p.digitColor} onChange={(v) => update({ digitColor: v })} />\n <PropertyField type=\"color\" label=\"Label Color\" value={p.labelColor} onChange={(v) => update({ labelColor: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n </div>\n );\n}\n","import React, { useCallback } from 'react';\nimport type { Block, MenuItem } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { generateId } from '../../utils/id';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\nimport blockStyles from '../../styles/blocks.module.css';\n\nconst HAMBURGER_OPTIONS = [\n { value: 'false', label: 'Off' }, { value: 'true', label: 'On' },\n];\n\ninterface MenuPropertiesProps {\n block: Block;\n}\n\nexport function MenuProperties({ block }: MenuPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n const updateItem = useCallback(\n (index: number, changes: Partial<MenuItem>) => {\n const items = [...block.properties.items];\n items[index] = { ...items[index], ...changes };\n update({ items });\n },\n [block.properties.items, update],\n );\n\n const addItem = useCallback(() => {\n const items = [...block.properties.items, { id: generateId('mi'), text: 'Link', href: '#' }];\n update({ items });\n }, [block.properties.items, update]);\n\n const removeItem = useCallback(\n (index: number) => {\n const items = block.properties.items.filter((_: any, i: number) => i !== index);\n update({ items });\n },\n [block.properties.items, update],\n );\n\n const moveItem = useCallback(\n (index: number, direction: -1 | 1) => {\n const items = [...block.properties.items];\n const newIndex = index + direction;\n if (newIndex < 0 || newIndex >= items.length) return;\n [items[index], items[newIndex]] = [items[newIndex], items[index]];\n update({ items });\n },\n [block.properties.items, update],\n );\n\n if (!narrowBlock(block, 'menu')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"font\" label=\"Font Family\" value={p.fontFamily} onChange={(v) => update({ fontFamily: v })} />\n <PropertyField type=\"text\" label=\"Font Size\" value={p.fontSize} onChange={(v) => update({ fontSize: v })} />\n <PropertyField type=\"color\" label=\"Text Color\" value={p.color} onChange={(v) => update({ color: v })} />\n <PropertyField type=\"select\" label=\"Hamburger Mode\" value={p.hamburger ? 'true' : 'false'} onChange={(v) => update({ hamburger: v === 'true' })} options={HAMBURGER_OPTIONS} />\n {p.hamburger && (\n <PropertyField type=\"color\" label=\"Icon Color\" value={p.iconColor} onChange={(v) => update({ iconColor: v })} />\n )}\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <FieldSeparator />\n <div className={styles.fieldGroup}>\n <label className={styles.fieldLabel}>Menu Items</label>\n <div className={blockStyles.menuItemsContainer}>\n {p.items.map((item: MenuItem, index: number) => (\n <div key={item.id ?? `mi-${index}`} className={blockStyles.menuItemEntry}>\n <div className={styles.fieldRow}>\n <input\n className={styles.fieldInputFlex}\n value={item.text}\n onChange={(e) => updateItem(index, { text: e.target.value })}\n placeholder=\"Label\"\n />\n <button className={`ee-item-move-up ${styles.itemActionBtn}`} onClick={() => moveItem(index, -1)} disabled={index === 0} title=\"Move up\">↑</button>\n <button className={`ee-item-move-down ${styles.itemActionBtn}`} onClick={() => moveItem(index, 1)} disabled={index === p.items.length - 1} title=\"Move down\">↓</button>\n <button className={`ee-item-remove ${styles.itemActionBtnDanger}`} onClick={() => removeItem(index)} title=\"Remove\">×</button>\n </div>\n <input\n className={styles.fieldInputStacked}\n value={item.href}\n onChange={(e) => updateItem(index, { href: e.target.value })}\n placeholder=\"URL\"\n />\n </div>\n ))}\n </div>\n <button className={`ee-add-item ${styles.addItemBtn}`} onClick={addItem}>+ Add Item</button>\n </div>\n </div>\n );\n}\n","import React, { useCallback, useRef } from 'react';\nimport { useImageUpload } from './useImageUpload';\nimport { useImageAdapter } from '../../context/EditorContext';\nimport styles from '../../styles/blocks.module.css';\n\ninterface ImageUploaderProps {\n blockId: string;\n onUploadComplete: (url: string, alt?: string) => void;\n}\n\nexport function ImageUploader({ blockId, onUploadComplete }: ImageUploaderProps) {\n const { imageUploadAdapter } = useImageAdapter();\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const { status, progress, error, upload, cancel } = useImageUpload({\n adapter: imageUploadAdapter,\n blockId,\n onSuccess: (result) => {\n onUploadComplete(result.url, result.alt);\n },\n });\n\n const handleFileChange = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n await upload(file);\n }\n },\n [upload],\n );\n\n const handleClick = useCallback(() => {\n fileInputRef.current?.click();\n }, []);\n\n return (\n <div>\n {status === 'uploading' ? (\n <div className={`ee-image-uploading ${styles.imageUploading}`}>\n <div className={`ee-image-placeholder ${styles.imagePlaceholder}`}>\n <span>Uploading... {Math.round(progress)}%</span>\n <button className=\"ee-upload-cancel\" onClick={cancel}>\n Cancel\n </button>\n </div>\n <div className={`ee-image-progress ${styles.imageProgress}`} style={{ width: `${progress}%` }} />\n </div>\n ) : (\n <div className={`ee-image-placeholder ${styles.imagePlaceholder}`} onClick={handleClick}>\n <span className={`ee-image-placeholder-icon ${styles.imagePlaceholderIcon}`}>+</span>\n <span>Click to upload image</span>\n </div>\n )}\n {error && <div className={`ee-image-error ${styles.imageError}`}>{error}</div>}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n </div>\n );\n}\n","import React from 'react';\nimport type { Block } from '../../types';\nimport { narrowBlock } from '../../types';\nimport { useBlockUpdate } from '../../hooks/useBlockUpdate';\nimport { ImageUploader } from '../ImageUpload/ImageUploader';\nimport { PropertyField, FieldSeparator } from './PropertyField';\nimport styles from '../../styles/properties.module.css';\n\ninterface HeroPropertiesProps {\n block: Block;\n}\n\nexport function HeroProperties({ block }: HeroPropertiesProps) {\n const update = useBlockUpdate(block.id);\n\n if (!narrowBlock(block, 'hero')) return null;\n const p = block.properties;\n\n return (\n <div className={styles.propertiesBody}>\n <PropertyField type=\"text\" label=\"Heading\" value={p.heading} onChange={(v) => update({ heading: v })} />\n <PropertyField type=\"textarea\" label=\"Subtext\" value={p.subtext} onChange={(v) => update({ subtext: v })} rows={3} />\n <FieldSeparator />\n <PropertyField type=\"text\" label=\"Button Text\" value={p.buttonText} onChange={(v) => update({ buttonText: v })} />\n <PropertyField type=\"link\" label=\"Button Link\" value={p.buttonHref} onChange={(v) => update({ buttonHref: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Heading Color\" value={p.headingColor} onChange={(v) => update({ headingColor: v })} />\n <PropertyField type=\"text\" label=\"Heading Font Size\" value={p.headingFontSize} onChange={(v) => update({ headingFontSize: v })} />\n <PropertyField type=\"color\" label=\"Subtext Color\" value={p.subtextColor} onChange={(v) => update({ subtextColor: v })} />\n <PropertyField type=\"text\" label=\"Subtext Font Size\" value={p.subtextFontSize} onChange={(v) => update({ subtextFontSize: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Button Background\" value={p.buttonBackgroundColor} onChange={(v) => update({ buttonBackgroundColor: v })} />\n <PropertyField type=\"color\" label=\"Button Text Color\" value={p.buttonColor} onChange={(v) => update({ buttonColor: v })} />\n <PropertyField type=\"text\" label=\"Button Border Radius\" value={p.buttonBorderRadius} onChange={(v) => update({ buttonBorderRadius: v })} />\n <PropertyField type=\"alignment\" label=\"Alignment\" value={p.align} onChange={(v) => update({ align: v })} />\n <PropertyField type=\"padding\" label=\"Padding\" value={p.padding} onChange={(v) => update({ padding: v })} />\n <FieldSeparator />\n <PropertyField type=\"color\" label=\"Background Color\" value={p.backgroundColor} onChange={(v) => update({ backgroundColor: v })} />\n <PropertyField type=\"text\" label=\"Background Image URL\" value={p.backgroundImage} onChange={(v) => update({ backgroundImage: v })} placeholder=\"https://example.com/image.jpg\" />\n {!p.backgroundImage && (\n <ImageUploader\n blockId={block.id}\n onUploadComplete={(url) => update({ backgroundImage: url })}\n />\n )}\n {p.backgroundImage && (\n <div className={styles.fieldGroup}>\n <button\n className={`ee-remove-bg ${styles.fieldBtnUpload}`}\n onClick={() => update({ backgroundImage: '' })}\n >\n Remove Background Image\n </button>\n </div>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { Block, BlockType } from '../../types';\nimport { useSelectedBlock, useSelectedSection } from '../../context/EditorContext';\nimport { blockPropertiesRegistry } from '../../registry';\nimport { SectionProperties } from './SectionProperties';\nimport { HeadMetadataProperties } from './HeadMetadataProperties';\nimport { TextProperties } from './TextProperties';\nimport { ButtonProperties } from './ButtonProperties';\nimport { ImageProperties } from './ImageProperties';\nimport { DividerProperties } from './DividerProperties';\nimport { SpacerProperties } from './SpacerProperties';\nimport { SocialProperties } from './SocialProperties';\nimport { HtmlProperties } from './HtmlProperties';\nimport { VideoProperties } from './VideoProperties';\nimport { HeadingProperties } from './HeadingProperties';\nimport { CountdownProperties } from './CountdownProperties';\nimport { MenuProperties } from './MenuProperties';\nimport { HeroProperties } from './HeroProperties';\nimport styles from '../../styles/properties.module.css';\n\ntype BlockPanelComponent = React.ComponentType<{ block: Block }>;\n\n/** Static lookup for built-in block property panels — no module-level side effects */\nconst BUILT_IN_PANELS: Record<string, BlockPanelComponent> = {\n text: TextProperties as BlockPanelComponent,\n button: ButtonProperties as BlockPanelComponent,\n image: ImageProperties as BlockPanelComponent,\n divider: DividerProperties as BlockPanelComponent,\n spacer: SpacerProperties as BlockPanelComponent,\n social: SocialProperties as BlockPanelComponent,\n html: HtmlProperties as BlockPanelComponent,\n video: VideoProperties as BlockPanelComponent,\n heading: HeadingProperties as BlockPanelComponent,\n countdown: CountdownProperties as BlockPanelComponent,\n menu: MenuProperties as BlockPanelComponent,\n hero: HeroProperties as BlockPanelComponent,\n};\n\nfunction getBlockPanel(type: string): BlockPanelComponent | undefined {\n // Custom-registered panels take precedence over built-in ones\n return blockPropertiesRegistry[type] ?? BUILT_IN_PANELS[type];\n}\n\nexport function PropertiesPanel() {\n const selectedBlock = useSelectedBlock();\n const selectedSection = useSelectedSection();\n\n if (selectedBlock) {\n const title = selectedBlock.type.charAt(0).toUpperCase() + selectedBlock.type.slice(1);\n const Component = getBlockPanel(selectedBlock.type);\n return (\n <div className={`ee-properties-panel ${styles.propertiesPanel}`}>\n <div className={`ee-properties-header ${styles.propertiesHeader}`}>{title} Properties</div>\n {Component ? <Component block={selectedBlock} /> : null}\n </div>\n );\n }\n\n if (selectedSection) {\n return (\n <div className={`ee-properties-panel ${styles.propertiesPanel}`}>\n <div className={`ee-properties-header ${styles.propertiesHeader}`}>Section Properties</div>\n <SectionProperties section={selectedSection} />\n </div>\n );\n }\n\n return (\n <div className={`ee-properties-panel ${styles.propertiesPanel}`}>\n <div className={`ee-properties-header ${styles.propertiesHeader}`}>Email Settings</div>\n <HeadMetadataProperties />\n </div>\n );\n}\n","import { useEffect, useState, useRef } from 'react';\nimport { useTemplateContext } from '../../context/EditorContext';\nimport { generateMJML } from '../../mjml/generator';\nimport { compileMJMLToHTML } from '../../mjml/compiler';\nimport styles from '../../styles/preview.module.css';\n\ntype PreviewMode = 'desktop' | 'mobile';\n\nconst PREVIEW_WIDTHS: Record<PreviewMode, number> = {\n desktop: 600,\n mobile: 375,\n};\n\nexport function PreviewPanel() {\n const { template } = useTemplateContext();\n const [html, setHtml] = useState('');\n const [previewMode, setPreviewMode] = useState<PreviewMode>('desktop');\n const iframeRef = useRef<HTMLIFrameElement>(null);\n\n // Debounce preview compilation to avoid excessive recompilations during rapid edits\n useEffect(() => {\n let cancelled = false;\n const timer = setTimeout(() => {\n async function compile() {\n const mjml = generateMJML(template);\n const result = await compileMJMLToHTML(mjml);\n if (!cancelled) {\n setHtml(result.html);\n }\n }\n compile();\n }, 300);\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [template]);\n\n useEffect(() => {\n if (iframeRef.current && html) {\n const doc = iframeRef.current.contentDocument;\n if (doc) {\n doc.open();\n doc.write(html);\n doc.close();\n }\n }\n }, [html]);\n\n return (\n <div className={`ee-preview ${styles.preview}`}>\n <div className={`ee-preview-toggles ${styles.previewToggles}`} role=\"group\" aria-label=\"Preview size\">\n <button\n className={`ee-preview-toggle ee-preview-toggle--desktop ${styles.previewToggle} ${styles.previewToggleDesktop} ${previewMode === 'desktop' ? `ee-preview-toggle--active ${styles.previewToggleActive}` : ''}`}\n onClick={() => setPreviewMode('desktop')}\n aria-pressed={previewMode === 'desktop'}\n aria-label=\"Desktop preview\"\n >\n Desktop\n </button>\n <button\n className={`ee-preview-toggle ee-preview-toggle--mobile ${styles.previewToggle} ${styles.previewToggleMobile} ${previewMode === 'mobile' ? `ee-preview-toggle--active ${styles.previewToggleActive}` : ''}`}\n onClick={() => setPreviewMode('mobile')}\n aria-pressed={previewMode === 'mobile'}\n aria-label=\"Mobile preview\"\n >\n Mobile\n </button>\n </div>\n <div className={`ee-preview-container ${styles.previewContainer}`}>\n <iframe\n className={`ee-preview-iframe ${styles.previewIframe}`}\n ref={iframeRef}\n title=\"Email Preview\"\n style={{ width: PREVIEW_WIDTHS[previewMode] }}\n sandbox=\"allow-same-origin\"\n />\n </div>\n </div>\n );\n}\n",".preview {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n}\n\n.previewToggles {\n display: flex;\n justify-content: center;\n gap: 0;\n padding: 12px 24px 0;\n}\n\n.previewToggle {\n padding: 6px 16px;\n border: 1px solid var(--ee-border-color);\n background: var(--ee-bg-panel);\n cursor: pointer;\n font-size: var(--ee-font-size-md);\n color: var(--ee-text-secondary);\n transition: all var(--ee-transition-fast);\n}\n\n.previewToggleActive {\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border-color: var(--ee-color-primary);\n}\n\n.previewToggleDesktop {\n border-radius: var(--ee-border-radius-sm) 0 0 var(--ee-border-radius-sm);\n}\n\n.previewToggleMobile {\n border-radius: 0 var(--ee-border-radius-sm) var(--ee-border-radius-sm) 0;\n border-left: none;\n}\n\n.previewContainer {\n flex: 1;\n display: flex;\n justify-content: center;\n padding: 24px;\n box-sizing: border-box;\n}\n\n.previewIframe {\n height: 100%;\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n background: var(--ee-bg-panel);\n transition: width var(--ee-transition-normal);\n}\n","import React, { useState, useCallback, useEffect } from 'react';\nimport { useTemplateContext, useEditorDispatch } from '../../context/EditorContext';\nimport { generateMJML } from '../../mjml/generator';\nimport { parseMJML } from '../../mjml/parser';\nimport styles from '../../styles/source-editor.module.css';\n\nexport function SourceEditor() {\n const { template } = useTemplateContext();\n const dispatch = useEditorDispatch();\n const [source, setSource] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n setSource(generateMJML(template));\n }, [template]);\n\n const handleApply = useCallback(() => {\n try {\n const template = parseMJML(source);\n dispatch({ type: 'SET_TEMPLATE', payload: template });\n setError(null);\n } catch (err) {\n setError((err as Error).message);\n }\n }, [source, dispatch]);\n\n return (\n <div className={`ee-source-editor ${styles.sourceEditor}`}>\n <div className={`ee-source-header ${styles.sourceHeader}`}>\n <span className={`ee-source-label ${styles.sourceLabel}`}>\n MJML Source\n </span>\n <button\n className={`ee-source-apply ${styles.sourceApply}`}\n onClick={handleApply}\n >\n Apply Changes\n </button>\n </div>\n {error && (\n <div className={`ee-source-error ${styles.sourceError}`}>\n {error}\n </div>\n )}\n <textarea\n className={`ee-source-textarea ${styles.sourceTextarea}`}\n value={source}\n onChange={(e) => setSource(e.target.value)}\n spellCheck={false}\n />\n </div>\n );\n}\n",".sourceEditor {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: var(--ee-space-lg);\n gap: var(--ee-space-sm);\n box-sizing: border-box;\n}\n\n.sourceHeader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.sourceLabel {\n font-size: var(--ee-font-size-md);\n font-weight: var(--ee-font-weight-semibold);\n color: var(--ee-text-secondary);\n}\n\n.sourceApply {\n padding: 6px 16px;\n font-size: var(--ee-font-size-md);\n font-weight: var(--ee-font-weight-medium);\n background: var(--ee-color-primary);\n color: var(--ee-text-inverse);\n border: none;\n border-radius: var(--ee-border-radius-sm);\n cursor: pointer;\n}\n\n.sourceError {\n padding: var(--ee-space-sm);\n font-size: var(--ee-font-size-sm);\n color: var(--ee-color-danger);\n background: var(--ee-color-danger-light);\n border-radius: var(--ee-border-radius-sm);\n}\n\n.sourceTextarea {\n flex: 1;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: var(--ee-font-size-md);\n line-height: 1.5;\n padding: var(--ee-space-md);\n border: 1px solid var(--ee-border-color);\n border-radius: var(--ee-border-radius);\n resize: none;\n outline: none;\n background: var(--ee-bg-input);\n color: var(--ee-text-primary);\n tab-size: 2;\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","properties","import_jsx_runtime","React","Toolbar","template","import_react","import_react","import_jsx_runtime","React","BlockPalette","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_react","import_react","import_react","import_react","import_extension_text_style","import_core","import_core","import_extension_text_style","StarterKit","Underline","TextAlign","TextStyle","Color","Highlight","Link","Placeholder","ALLOWED_TAGS","import_jsx_runtime","useTipTapEditor","import_react","import_jsx_runtime","React","RichTextToolbar","import_jsx_runtime","TextBlock","React","import_react","import_jsx_runtime","React","ButtonBlock","import_react","import_react","import_jsx_runtime","ImageBlock","React","import_react","import_jsx_runtime","React","DividerBlock","import_react","import_jsx_runtime","React","SpacerBlock","import_react","import_jsx_runtime","React","SocialBlock","import_react","import_jsx_runtime","React","HtmlBlock","DOMPurify","import_react","import_jsx_runtime","React","VideoBlock","getAutoThumbnail","import_react","import_jsx_runtime","HeadingBlock","React","import_react","import_jsx_runtime","React","CountdownBlock","import_react","import_jsx_runtime","React","MenuBlock","import_react","import_jsx_runtime","React","HeroBlock","import_jsx_runtime","TextBlock","ImageBlock","HeadingBlock","React","BlockRenderer","Component","import_react","import_jsx_runtime","React","DropZone","import_jsx_runtime","React","Column","import_jsx_runtime","React","Section","import_react","import_jsx_runtime","React","SectionDropZone","import_jsx_runtime","React","Canvas","import_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","React","PropertyField","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","getAutoThumbnail","import_react","import_jsx_runtime","FONT_WEIGHT_OPTIONS","TEXT_TRANSFORM_OPTIONS","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Component","import_react","import_jsx_runtime","import_react","import_jsx_runtime","template","import_jsx_runtime","EditorInner","EmailEditor"]}