@yurikilian/lex4 0.1.2 → 0.2.0

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.
Files changed (79) hide show
  1. package/README.md +236 -20
  2. package/dist/ast/block-mapper.d.ts +24 -0
  3. package/dist/ast/block-mapper.d.ts.map +1 -0
  4. package/dist/ast/content-mapper.d.ts +16 -0
  5. package/dist/ast/content-mapper.d.ts.map +1 -0
  6. package/dist/ast/document-serializer.d.ts +11 -0
  7. package/dist/ast/document-serializer.d.ts.map +1 -0
  8. package/dist/ast/index.d.ts +9 -0
  9. package/dist/ast/index.d.ts.map +1 -0
  10. package/dist/ast/inline-mapper.d.ts +41 -0
  11. package/dist/ast/inline-mapper.d.ts.map +1 -0
  12. package/dist/ast/payload-builder.d.ts +18 -0
  13. package/dist/ast/payload-builder.d.ts.map +1 -0
  14. package/dist/ast/types.d.ts +112 -0
  15. package/dist/ast/types.d.ts.map +1 -0
  16. package/dist/components/EditorSidebar.d.ts +1 -0
  17. package/dist/components/EditorSidebar.d.ts.map +1 -1
  18. package/dist/components/HistorySidebar.d.ts.map +1 -1
  19. package/dist/components/Lex4Editor.d.ts +9 -1
  20. package/dist/components/Lex4Editor.d.ts.map +1 -1
  21. package/dist/components/PageBody.d.ts +1 -2
  22. package/dist/components/PageBody.d.ts.map +1 -1
  23. package/dist/components/PageFooter.d.ts.map +1 -1
  24. package/dist/components/PageHeader.d.ts.map +1 -1
  25. package/dist/components/Toolbar.d.ts.map +1 -1
  26. package/dist/components/VariablePanel.d.ts +15 -0
  27. package/dist/components/VariablePanel.d.ts.map +1 -0
  28. package/dist/components/VariablePicker.d.ts +14 -0
  29. package/dist/components/VariablePicker.d.ts.map +1 -0
  30. package/dist/extensions/ast-extension.d.ts +16 -0
  31. package/dist/extensions/ast-extension.d.ts.map +1 -0
  32. package/dist/extensions/extension-context.d.ts +29 -0
  33. package/dist/extensions/extension-context.d.ts.map +1 -0
  34. package/dist/extensions/index.d.ts +6 -0
  35. package/dist/extensions/index.d.ts.map +1 -0
  36. package/dist/extensions/types.d.ts +74 -0
  37. package/dist/extensions/types.d.ts.map +1 -0
  38. package/dist/extensions/variables-extension.d.ts +31 -0
  39. package/dist/extensions/variables-extension.d.ts.map +1 -0
  40. package/dist/i18n/context.d.ts +28 -0
  41. package/dist/i18n/context.d.ts.map +1 -0
  42. package/dist/i18n/defaults.d.ts +3 -0
  43. package/dist/i18n/defaults.d.ts.map +1 -0
  44. package/dist/i18n/index.d.ts +4 -0
  45. package/dist/i18n/index.d.ts.map +1 -0
  46. package/dist/i18n/types.d.ts +82 -0
  47. package/dist/i18n/types.d.ts.map +1 -0
  48. package/dist/index.d.ts +10 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/lex4-editor.cjs +1113 -101
  51. package/dist/lex4-editor.cjs.map +1 -1
  52. package/dist/lex4-editor.js +1116 -104
  53. package/dist/lex4-editor.js.map +1 -1
  54. package/dist/lexical/editor-setup.d.ts +5 -1
  55. package/dist/lexical/editor-setup.d.ts.map +1 -1
  56. package/dist/lexical/plugins/font-plugin.d.ts +1 -1
  57. package/dist/lexical/plugins/font-plugin.d.ts.map +1 -1
  58. package/dist/lexical/plugins/font-size-plugin.d.ts +19 -0
  59. package/dist/lexical/plugins/font-size-plugin.d.ts.map +1 -0
  60. package/dist/lexical/plugins/index.d.ts +2 -0
  61. package/dist/lexical/plugins/index.d.ts.map +1 -1
  62. package/dist/style.css +532 -160
  63. package/dist/types/editor-handle.d.ts +14 -0
  64. package/dist/types/editor-handle.d.ts.map +1 -0
  65. package/dist/types/editor-props.d.ts +23 -0
  66. package/dist/types/editor-props.d.ts.map +1 -1
  67. package/dist/variables/index.d.ts +5 -0
  68. package/dist/variables/index.d.ts.map +1 -0
  69. package/dist/variables/types.d.ts +26 -0
  70. package/dist/variables/types.d.ts.map +1 -0
  71. package/dist/variables/variable-commands.d.ts +11 -0
  72. package/dist/variables/variable-commands.d.ts.map +1 -0
  73. package/dist/variables/variable-context.d.ts +21 -0
  74. package/dist/variables/variable-context.d.ts.map +1 -0
  75. package/dist/variables/variable-node.d.ts +34 -0
  76. package/dist/variables/variable-node.d.ts.map +1 -0
  77. package/dist/variables/variable-plugin.d.ts +8 -0
  78. package/dist/variables/variable-plugin.d.ts.map +1 -0
  79. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"lex4-editor.js","sources":["../src/types/document.ts","../src/context/document-context.ts","../src/constants/dimensions.ts","../src/utils/debug.ts","../src/context/document-reducer.ts","../src/utils/history-manager.ts","../src/context/document-provider.tsx","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/defaultAttributes.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/context.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/Icon.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/createLucideIcon.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/bold.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/copy-plus.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/eraser.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/hash.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/italic.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list-indent-decrease.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list-indent-increase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list-ordered.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/panel-right.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/redo-2.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/strikethrough.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-center.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-end.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-justify.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-start.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/trash-2.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/underline.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/undo-2.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/x.js","../src/components/EditorSidebar.tsx","../src/components/HistorySidebar.tsx","../src/components/HeaderFooterToggle.tsx","../src/components/HeaderFooterActions.tsx","../src/lexical/plugins/font-plugin.tsx","../src/lexical/commands/format-commands.ts","../src/lexical/commands/list-commands.ts","../src/components/Toolbar.tsx","../src/constants/page-layout.ts","../src/utils/editor-state-utils.ts","../src/hooks/use-pagination.ts","../src/lexical/theme.ts","../src/lexical/editor-setup.ts","../src/lexical/plugins/tab-indent-plugin.tsx","../src/lexical/plugins/paragraph-indent-plugin.tsx","../src/lexical/plugins/paste-plugin.tsx","../src/lexical/plugins/active-editor-plugin.tsx","../src/lexical/plugins/overflow-plugin.tsx","../src/lexical/plugins/history-capture-plugin.tsx","../src/lexical/plugins/page-boundary-plugin.tsx","../src/components/PageBody.tsx","../src/lexical/plugins/height-limit-plugin.tsx","../src/components/PageHeader.tsx","../src/components/PageFooter.tsx","../src/components/PageView.tsx","../src/components/DocumentView.tsx","../src/components/Lex4Editor.tsx","../src/hooks/use-overflow-detection.ts","../src/hooks/use-header-footer.ts"],"sourcesContent":["import type { SerializedEditorState } from 'lexical';\n\nexport type PageCounterMode = 'none' | 'header' | 'footer' | 'both';\n\nexport interface PageChromeTemplate {\n headerState: SerializedEditorState | null;\n footerState: SerializedEditorState | null;\n headerHeight: number;\n footerHeight: number;\n}\n\n/** State for a single page in the document */\nexport interface PageState {\n id: string;\n bodyState: SerializedEditorState | null;\n headerState: SerializedEditorState | null;\n footerState: SerializedEditorState | null;\n headerHeight: number;\n footerHeight: number;\n /** Incremented on external body state changes (reflow/undo) to force editor remount */\n bodySyncVersion: number;\n /** Incremented on external header state changes (copy/clear) to force editor remount */\n headerSyncVersion: number;\n /** Incremented on external footer state changes (copy/clear) to force editor remount */\n footerSyncVersion: number;\n}\n\n/** Top-level document state */\nexport interface Lex4Document {\n pages: PageState[];\n headerFooterEnabled: boolean;\n pageCounterMode: PageCounterMode;\n defaultHeaderState: SerializedEditorState | null;\n defaultFooterState: SerializedEditorState | null;\n defaultHeaderHeight: number;\n defaultFooterHeight: number;\n}\n\n/** Creates a default empty page */\nexport function createEmptyPage(id?: string): PageState {\n return {\n id: id ?? crypto.randomUUID(),\n bodyState: null,\n headerState: null,\n footerState: null,\n headerHeight: 0,\n footerHeight: 0,\n bodySyncVersion: 0,\n headerSyncVersion: 0,\n footerSyncVersion: 0,\n };\n}\n\n/** Creates a new page that inherits header/footer chrome from a document default template. */\nexport function createPageFromTemplate(template?: PageChromeTemplate): PageState {\n return {\n ...createEmptyPage(),\n headerState: template?.headerState ?? null,\n footerState: template?.footerState ?? null,\n headerHeight: template?.headerHeight ?? 0,\n footerHeight: template?.footerHeight ?? 0,\n };\n}\n\n/** Creates a default empty document */\nexport function createEmptyDocument(): Lex4Document {\n return {\n pages: [createEmptyPage()],\n headerFooterEnabled: false,\n pageCounterMode: 'none',\n defaultHeaderState: null,\n defaultFooterState: null,\n defaultHeaderHeight: 0,\n defaultFooterHeight: 0,\n };\n}\n","import { createContext, useContext } from 'react';\nimport type { Lex4Document, PageCounterMode } from '../types/document';\nimport type { LexicalEditor } from 'lexical';\nimport type {\n CaretPosition,\n CaretSelection,\n HistoryActionDescriptor,\n HistoryEntry,\n} from '../types/history';\n\n/** All actions the document reducer can handle */\nexport type DocumentAction =\n | { type: 'ADD_PAGE'; afterIndex?: number; page?: import('../types/document').PageState }\n | { type: 'REMOVE_PAGE'; pageId: string }\n | { type: 'UPDATE_PAGE_BODY'; pageId: string; bodyState: import('lexical').SerializedEditorState | null }\n | {\n type: 'UPDATE_PAGE_HEADER_CONTENT';\n pageId: string;\n headerState: import('lexical').SerializedEditorState | null;\n height: number;\n }\n | {\n type: 'UPDATE_PAGE_FOOTER_CONTENT';\n pageId: string;\n footerState: import('lexical').SerializedEditorState | null;\n height: number;\n }\n | { type: 'UPDATE_PAGE_HEADER'; pageId: string; headerState: import('lexical').SerializedEditorState | null }\n | { type: 'UPDATE_PAGE_FOOTER'; pageId: string; footerState: import('lexical').SerializedEditorState | null }\n | { type: 'SET_HEADER_FOOTER_ENABLED'; enabled: boolean }\n | { type: 'SET_PAGE_COUNTER_MODE'; mode: PageCounterMode }\n | { type: 'COPY_HEADER_TO_ALL'; sourcePageId: string }\n | { type: 'COPY_FOOTER_TO_ALL'; sourcePageId: string }\n | { type: 'CLEAR_HEADER'; pageId: string }\n | { type: 'CLEAR_FOOTER'; pageId: string }\n | { type: 'CLEAR_ALL_HEADERS' }\n | { type: 'CLEAR_ALL_FOOTERS' }\n | { type: 'CLEAR_DOCUMENT_CONTENT' }\n | { type: 'SET_HEADER_HEIGHT'; pageId: string; height: number }\n | { type: 'SET_FOOTER_HEIGHT'; pageId: string; height: number }\n | { type: 'SET_DOCUMENT'; document: Lex4Document };\n\n/** Registry of page editors for direct cross-page content manipulation */\nexport interface EditorRegistry {\n register(pageId: string, editor: LexicalEditor): void;\n unregister(pageId: string): void;\n get(pageId: string): LexicalEditor | undefined;\n all(): LexicalEditor[];\n}\n\n/** Shape of the document context value */\nexport interface DocumentContextValue {\n document: Lex4Document;\n dispatch: React.Dispatch<DocumentAction>;\n activePageId: string | null;\n setActivePageId: (id: string | null) => void;\n activeEditor: LexicalEditor | null;\n setActiveEditor: (editor: LexicalEditor | null, caretPosition?: CaretPosition | null) => void;\n consumePendingCaretPosition: (caretPosition: CaretPosition) => CaretSelection | null | undefined;\n consumePendingFocusAtEnd: (caretPosition: CaretPosition) => boolean;\n requestFocusAtEnd: (caretPosition: CaretPosition) => void;\n focusAtEndVersion: number;\n globalSelectionActive: boolean;\n setGlobalSelectionActive: (active: boolean) => void;\n historyEntries: HistoryEntry[];\n historyCursor: number;\n canUndo: boolean;\n canRedo: boolean;\n queueHistoryAction: (action: HistoryActionDescriptor | null) => void;\n runHistoryAction: (action: HistoryActionDescriptor, callback: () => void) => void;\n jumpToHistoryEntry: (entryIndex: number) => void;\n clearHistory: (reason?: string) => void;\n historySidebarOpen: boolean;\n setHistorySidebarOpen: (open: boolean) => void;\n undo: () => void;\n redo: () => void;\n editorRegistry: EditorRegistry;\n}\n\nexport const DocumentContext = createContext<DocumentContextValue | null>(null);\n\n/** Hook to access the document context. Throws if used outside provider. */\nexport function useDocument(): DocumentContextValue {\n const ctx = useContext(DocumentContext);\n if (!ctx) {\n throw new Error('useDocument must be used within a DocumentProvider');\n }\n return ctx;\n}\n","/**\n * A4 page dimensions and layout constants.\n *\n * All values derived from the A4 standard (210mm × 297mm)\n * converted to CSS pixels at 96 DPI.\n */\n\nexport const A4_WIDTH_MM = 210;\nexport const A4_HEIGHT_MM = 297;\n\n/** CSS pixels per millimeter at 96 DPI */\nexport const PX_PER_MM = 96 / 25.4;\n\n/** A4 width in CSS pixels (≈794px) */\nexport const A4_WIDTH_PX = Math.round(A4_WIDTH_MM * PX_PER_MM);\n\n/** A4 height in CSS pixels (≈1123px) */\nexport const A4_HEIGHT_PX = Math.round(A4_HEIGHT_MM * PX_PER_MM);\n\n/** Default page margin in CSS pixels (≈10.6mm each side) */\nexport const PAGE_MARGIN_PX = 40;\n\n/** Maximum header height as a ratio of page height */\nexport const MAX_HEADER_RATIO = 0.2;\n\n/** Maximum footer height as a ratio of page height */\nexport const MAX_FOOTER_RATIO = 0.2;\n\n/** Maximum header height in CSS pixels */\nexport const MAX_HEADER_HEIGHT_PX = Math.round(A4_HEIGHT_PX * MAX_HEADER_RATIO);\n\n/** Maximum footer height in CSS pixels */\nexport const MAX_FOOTER_HEIGHT_PX = Math.round(A4_HEIGHT_PX * MAX_FOOTER_RATIO);\n","/**\n * Lex4 Debug Logger\n *\n * Zero-cost when disabled. Enable in the browser console:\n *\n * localStorage.setItem('lex4:debug', '*') // all channels\n * localStorage.setItem('lex4:debug', 'overflow,reducer') // specific channels\n * window.__LEX4_DEBUG__ = true // all channels (session only)\n *\n * Disable:\n * localStorage.removeItem('lex4:debug')\n * window.__LEX4_DEBUG__ = false\n *\n * Channels:\n * reducer — every dispatched action and resulting state\n * overflow — overflow detection, measurement, split decisions\n * registry — editor registry register/unregister/get\n * page — page creation, initial state loading, body changes\n * toolbar — formatting command dispatches\n * header — header height changes, content changes\n * footer — footer height changes, content changes\n * focus — editor focus changes, active editor/page tracking\n */\n\nexport type DebugChannel =\n | 'reducer'\n | 'overflow'\n | 'registry'\n | 'page'\n | 'toolbar'\n | 'header'\n | 'footer'\n | 'focus';\n\nconst CHANNEL_COLORS: Record<DebugChannel, string> = {\n reducer: '#e91e63',\n overflow: '#ff5722',\n registry: '#9c27b0',\n page: '#2196f3',\n toolbar: '#4caf50',\n header: '#ff9800',\n footer: '#795548',\n focus: '#607d8b',\n};\n\ndeclare global {\n interface Window {\n __LEX4_DEBUG__?: boolean | string;\n }\n}\n\nfunction getFlag(): string | boolean | null {\n if (typeof window === 'undefined') return null;\n\n const win = (window as Window).__LEX4_DEBUG__;\n if (win !== undefined && win !== null) return win;\n\n if (typeof localStorage !== 'undefined') {\n return localStorage.getItem('lex4:debug');\n }\n\n return null;\n}\n\nfunction isEnabled(channel: DebugChannel): boolean {\n const flag = getFlag();\n if (!flag) return false;\n if (flag === true || flag === '*' || flag === 'true') return true;\n\n if (typeof flag === 'string') {\n return flag.split(',').some(s => s.trim() === channel);\n }\n\n return false;\n}\n\n/**\n * Log a debug message on the given channel.\n * No-ops instantly when the channel is disabled.\n */\nexport function debug(channel: DebugChannel, message: string, ...data: unknown[]): void {\n if (!isEnabled(channel)) return;\n\n const color = CHANNEL_COLORS[channel];\n const prefix = `%c[lex4:${channel}]`;\n const style = `color: ${color}; font-weight: bold;`;\n\n if (data.length > 0) {\n console.log(prefix, style, message, ...data);\n } else {\n console.log(prefix, style, message);\n }\n}\n\n/**\n * Log a warning on the given channel.\n */\nexport function debugWarn(channel: DebugChannel, message: string, ...data: unknown[]): void {\n if (!isEnabled(channel)) return;\n\n const color = CHANNEL_COLORS[channel];\n const prefix = `%c[lex4:${channel}]`;\n const style = `color: ${color}; font-weight: bold;`;\n\n if (data.length > 0) {\n console.warn(prefix, style, message, ...data);\n } else {\n console.warn(prefix, style, message);\n }\n}\n\n/** Short-id helper: first 8 chars of a UUID for readable logs */\nexport function shortId(id: string): string {\n return id.substring(0, 8);\n}\n","import type { Lex4Document } from '../types/document';\nimport { createEmptyPage } from '../types/document';\nimport type { DocumentAction } from './document-context';\nimport { MAX_HEADER_HEIGHT_PX, MAX_FOOTER_HEIGHT_PX } from '../constants/dimensions';\nimport { debug, shortId } from '../utils/debug';\n\nfunction serializedStateChanged(\n current: import('lexical').SerializedEditorState | null,\n next: import('lexical').SerializedEditorState | null,\n): boolean {\n return JSON.stringify(current) !== JSON.stringify(next);\n}\n\nfunction withExternalSyncVersions(\n currentDocument: Lex4Document,\n nextDocument: Lex4Document,\n): Lex4Document {\n const currentPages = new Map(currentDocument.pages.map(page => [page.id, page]));\n\n return {\n ...nextDocument,\n pages: nextDocument.pages.map(nextPage => {\n const currentPage = currentPages.get(nextPage.id);\n if (!currentPage) {\n return nextPage;\n }\n\n const bodyChanged = serializedStateChanged(currentPage.bodyState, nextPage.bodyState);\n const headerChanged =\n currentPage.headerHeight !== nextPage.headerHeight ||\n serializedStateChanged(currentPage.headerState, nextPage.headerState);\n const footerChanged =\n currentPage.footerHeight !== nextPage.footerHeight ||\n serializedStateChanged(currentPage.footerState, nextPage.footerState);\n\n return {\n ...nextPage,\n bodySyncVersion: bodyChanged ? currentPage.bodySyncVersion + 1 : currentPage.bodySyncVersion,\n headerSyncVersion: headerChanged ? currentPage.headerSyncVersion + 1 : currentPage.headerSyncVersion,\n footerSyncVersion: footerChanged ? currentPage.footerSyncVersion + 1 : currentPage.footerSyncVersion,\n };\n }),\n };\n}\n\n/**\n * Pure reducer for document state.\n * Handles all page-level and document-level mutations.\n */\nexport function documentReducer(state: Lex4Document, action: DocumentAction): Lex4Document {\n switch (action.type) {\n case 'ADD_PAGE': {\n const newPage = action.page ?? createEmptyPage();\n const pages = [...state.pages];\n const insertAt = action.afterIndex !== undefined ? action.afterIndex + 1 : pages.length;\n pages.splice(insertAt, 0, newPage);\n const hasBody = !!(action.page?.bodyState?.root?.children?.length);\n debug('reducer', `ADD_PAGE id=${shortId(newPage.id)} at=${insertAt} withBody=${hasBody} totalPages=${pages.length}`);\n return { ...state, pages };\n }\n\n case 'REMOVE_PAGE': {\n if (state.pages.length <= 1) {\n debug('reducer', `REMOVE_PAGE id=${shortId(action.pageId)} — skipped (last page)`);\n return state;\n }\n debug('reducer', `REMOVE_PAGE id=${shortId(action.pageId)} remaining=${state.pages.length - 1}`);\n return {\n ...state,\n pages: state.pages.filter(p => p.id !== action.pageId),\n };\n }\n\n case 'UPDATE_PAGE_BODY': {\n const childCount = action.bodyState?.root?.children?.length ?? 0;\n debug('reducer', `UPDATE_PAGE_BODY id=${shortId(action.pageId)} children=${childCount}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, bodyState: action.bodyState } : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_HEADER': {\n debug('reducer', `UPDATE_PAGE_HEADER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, headerState: action.headerState } : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_HEADER_CONTENT': {\n const clamped = Math.min(action.height, MAX_HEADER_HEIGHT_PX);\n debug('reducer', `UPDATE_PAGE_HEADER_CONTENT id=${shortId(action.pageId)} height=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, headerState: action.headerState, headerHeight: clamped }\n : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_FOOTER': {\n debug('reducer', `UPDATE_PAGE_FOOTER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, footerState: action.footerState } : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_FOOTER_CONTENT': {\n const clamped = Math.min(action.height, MAX_FOOTER_HEIGHT_PX);\n debug('reducer', `UPDATE_PAGE_FOOTER_CONTENT id=${shortId(action.pageId)} height=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, footerState: action.footerState, footerHeight: clamped }\n : p,\n ),\n };\n }\n\n case 'SET_HEADER_FOOTER_ENABLED': {\n debug('reducer', `SET_HEADER_FOOTER_ENABLED enabled=${action.enabled}`);\n return { ...state, headerFooterEnabled: action.enabled };\n }\n\n case 'SET_PAGE_COUNTER_MODE': {\n debug('reducer', `SET_PAGE_COUNTER_MODE mode=${action.mode}`);\n return { ...state, pageCounterMode: action.mode };\n }\n\n case 'COPY_HEADER_TO_ALL': {\n debug('reducer', `COPY_HEADER_TO_ALL from=${shortId(action.sourcePageId)}`);\n const source = state.pages.find(p => p.id === action.sourcePageId);\n if (!source) return state;\n return {\n ...state,\n defaultHeaderState: source.headerState,\n defaultHeaderHeight: source.headerHeight,\n pages: state.pages.map(p => ({\n ...p,\n headerState: source.headerState,\n headerHeight: source.headerHeight,\n headerSyncVersion: p.headerSyncVersion + 1,\n })),\n };\n }\n\n case 'COPY_FOOTER_TO_ALL': {\n debug('reducer', `COPY_FOOTER_TO_ALL from=${shortId(action.sourcePageId)}`);\n const source = state.pages.find(p => p.id === action.sourcePageId);\n if (!source) return state;\n return {\n ...state,\n defaultFooterState: source.footerState,\n defaultFooterHeight: source.footerHeight,\n pages: state.pages.map(p => ({\n ...p,\n footerState: source.footerState,\n footerHeight: source.footerHeight,\n footerSyncVersion: p.footerSyncVersion + 1,\n })),\n };\n }\n\n case 'CLEAR_HEADER': {\n debug('reducer', `CLEAR_HEADER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, headerState: null, headerHeight: 0, headerSyncVersion: p.headerSyncVersion + 1 }\n : p,\n ),\n };\n }\n\n case 'CLEAR_FOOTER': {\n debug('reducer', `CLEAR_FOOTER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, footerState: null, footerHeight: 0, footerSyncVersion: p.footerSyncVersion + 1 }\n : p,\n ),\n };\n }\n\n case 'CLEAR_ALL_HEADERS': {\n debug('reducer', 'CLEAR_ALL_HEADERS');\n return {\n ...state,\n defaultHeaderState: null,\n defaultHeaderHeight: 0,\n pages: state.pages.map(p => ({\n ...p, headerState: null, headerHeight: 0, headerSyncVersion: p.headerSyncVersion + 1,\n })),\n };\n }\n\n case 'CLEAR_ALL_FOOTERS': {\n debug('reducer', 'CLEAR_ALL_FOOTERS');\n return {\n ...state,\n defaultFooterState: null,\n defaultFooterHeight: 0,\n pages: state.pages.map(p => ({\n ...p, footerState: null, footerHeight: 0, footerSyncVersion: p.footerSyncVersion + 1,\n })),\n };\n }\n\n case 'CLEAR_DOCUMENT_CONTENT': {\n debug('reducer', 'CLEAR_DOCUMENT_CONTENT');\n const firstPage = state.pages[0];\n return {\n ...state,\n pages: [{\n ...createEmptyPage(firstPage?.id),\n headerState: firstPage?.headerState ?? null,\n footerState: firstPage?.footerState ?? null,\n headerHeight: firstPage?.headerHeight ?? 0,\n footerHeight: firstPage?.footerHeight ?? 0,\n bodySyncVersion: (firstPage?.bodySyncVersion ?? 0) + 1,\n headerSyncVersion: firstPage?.headerSyncVersion ?? 0,\n footerSyncVersion: firstPage?.footerSyncVersion ?? 0,\n }],\n };\n }\n\n case 'SET_HEADER_HEIGHT': {\n const clamped = Math.min(action.height, MAX_HEADER_HEIGHT_PX);\n debug('header', `SET_HEADER_HEIGHT id=${shortId(action.pageId)} raw=${action.height} clamped=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, headerHeight: clamped } : p,\n ),\n };\n }\n\n case 'SET_FOOTER_HEIGHT': {\n const clamped = Math.min(action.height, MAX_FOOTER_HEIGHT_PX);\n debug('footer', `SET_FOOTER_HEIGHT id=${shortId(action.pageId)} raw=${action.height} clamped=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, footerHeight: clamped } : p,\n ),\n };\n }\n\n case 'SET_DOCUMENT': {\n debug('reducer', `SET_DOCUMENT pages=${action.document.pages.length}`);\n return withExternalSyncVersions(state, action.document);\n }\n\n default:\n return state;\n }\n}\n","import type { Lex4Document } from '../types/document';\nimport type {\n CaretPosition,\n CaretSelection,\n HistoryActionDescriptor,\n HistoryEntry,\n HistoryState,\n} from '../types/history';\n\nexport const MAX_HISTORY_ACTIONS = 100;\n\nfunction cloneSnapshot(document: Lex4Document): Lex4Document {\n return structuredClone(document);\n}\n\nfunction createHistoryEntry(\n document: Lex4Document,\n descriptor: HistoryActionDescriptor,\n undoSnapshot: Lex4Document,\n caretPosition: CaretPosition | null,\n caretSelection: CaretSelection | null,\n undoCaretPosition: CaretPosition | null,\n undoCaretSelection: CaretSelection | null,\n): HistoryEntry {\n return {\n ...descriptor,\n id: crypto.randomUUID(),\n snapshot: cloneSnapshot(document),\n undoSnapshot: cloneSnapshot(undoSnapshot),\n timestamp: new Date().toISOString(),\n caretPosition,\n caretSelection,\n undoCaretPosition,\n undoCaretSelection,\n };\n}\n\nexport function createHistoryState(\n document: Lex4Document,\n baseCaretPosition: CaretPosition | null = null,\n): HistoryState {\n return {\n baseSnapshot: cloneSnapshot(document),\n baseCaretPosition,\n entries: [],\n cursor: 0,\n };\n}\n\nexport function getHistorySnapshot(history: HistoryState, cursor = history.cursor): Lex4Document {\n if (cursor <= 0) {\n return cloneSnapshot(history.baseSnapshot);\n }\n\n return cloneSnapshot(history.entries[cursor - 1].snapshot);\n}\n\nexport function clearHistoryState(\n document: Lex4Document,\n baseCaretPosition: CaretPosition | null = null,\n): HistoryState {\n return createHistoryState(document, baseCaretPosition);\n}\n\nexport function recordHistoryEntry(\n history: HistoryState,\n nextDocument: Lex4Document,\n descriptor: HistoryActionDescriptor,\n undoSnapshot: Lex4Document,\n caretPosition: CaretPosition | null,\n caretSelection: CaretSelection | null,\n undoCaretPosition: CaretPosition | null,\n undoCaretSelection: CaretSelection | null,\n): HistoryState {\n const entries = history.entries.slice(0, history.cursor);\n entries.push(createHistoryEntry(\n nextDocument,\n descriptor,\n undoSnapshot,\n caretPosition,\n caretSelection,\n undoCaretPosition,\n undoCaretSelection,\n ));\n\n let baseSnapshot = cloneSnapshot(history.baseSnapshot);\n let baseCaretPosition = history.baseCaretPosition;\n let trimmedEntries = entries;\n\n if (trimmedEntries.length > MAX_HISTORY_ACTIONS) {\n baseSnapshot = cloneSnapshot(trimmedEntries[1].undoSnapshot);\n baseCaretPosition = trimmedEntries[1].undoCaretPosition;\n trimmedEntries = trimmedEntries.slice(1);\n }\n\n return {\n baseSnapshot,\n baseCaretPosition,\n entries: trimmedEntries,\n cursor: trimmedEntries.length,\n };\n}\n\nexport function undoHistory(\n history: HistoryState,\n): {\n history: HistoryState;\n document: Lex4Document;\n caretPosition: CaretPosition | null;\n caretSelection: CaretSelection | null;\n} | null {\n if (history.cursor === 0) {\n return null;\n }\n\n const cursor = history.cursor - 1;\n const nextHistory: HistoryState = {\n ...history,\n cursor,\n };\n\n return {\n history: nextHistory,\n document: cloneSnapshot(history.entries[history.cursor - 1].undoSnapshot),\n caretPosition: history.entries[history.cursor - 1].undoCaretPosition,\n caretSelection: history.entries[history.cursor - 1].undoCaretSelection,\n };\n}\n\nexport function redoHistory(\n history: HistoryState,\n): {\n history: HistoryState;\n document: Lex4Document;\n caretPosition: CaretPosition | null;\n caretSelection: CaretSelection | null;\n} | null {\n if (history.cursor >= history.entries.length) {\n return null;\n }\n\n const cursor = history.cursor + 1;\n const nextHistory: HistoryState = {\n ...history,\n cursor,\n };\n\n return {\n history: nextHistory,\n document: getHistorySnapshot(nextHistory),\n caretPosition: nextHistory.entries[cursor - 1]?.caretPosition ?? nextHistory.baseCaretPosition,\n caretSelection: nextHistory.entries[cursor - 1]?.caretSelection ?? null,\n };\n}\n\nexport function jumpToHistoryEntry(\n history: HistoryState,\n entryIndex: number,\n): {\n history: HistoryState;\n document: Lex4Document;\n caretPosition: CaretPosition | null;\n caretSelection: CaretSelection | null;\n} | null {\n if (entryIndex < 0 || entryIndex >= history.entries.length) {\n return null;\n }\n\n const nextHistory: HistoryState = {\n ...history,\n cursor: entryIndex + 1,\n };\n\n return {\n history: nextHistory,\n document: getHistorySnapshot(nextHistory),\n caretPosition: nextHistory.entries[nextHistory.cursor - 1]?.caretPosition ?? nextHistory.baseCaretPosition,\n caretSelection: nextHistory.entries[nextHistory.cursor - 1]?.caretSelection ?? null,\n };\n}\n","import React, { useReducer, useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport type { Lex4Document } from '../types/document';\nimport type {\n CaretPosition,\n CaretSelection,\n HistoryActionDescriptor,\n HistoryState,\n} from '../types/history';\nimport { $createRangeSelectionFromDom, $getRoot, $getSelection, $isRangeSelection } from 'lexical';\nimport type { LexicalEditor } from 'lexical';\nimport { createEmptyDocument } from '../types/document';\nimport { DocumentContext, type DocumentAction, type EditorRegistry } from './document-context';\nimport { documentReducer } from './document-reducer';\nimport {\n clearHistoryState,\n createHistoryState,\n jumpToHistoryEntry,\n recordHistoryEntry,\n redoHistory,\n undoHistory,\n} from '../utils/history-manager';\n\ninterface DocumentProviderProps {\n initialDocument?: Lex4Document;\n onDocumentChange?: (doc: Lex4Document) => void;\n children: React.ReactNode;\n}\n\nconst HISTORY_RESTORE_SUPPRESSION_MS = 100;\nconst HISTORY_BATCH_FLUSH_MS = 16;\n\nfunction cloneDocumentSnapshot(document: Lex4Document): Lex4Document {\n return structuredClone(document);\n}\n\nfunction captureUndoSnapshot(\n document: Lex4Document,\n activeEditor: LexicalEditor | null,\n caretPosition: CaretPosition | null,\n): Lex4Document {\n const snapshot = cloneDocumentSnapshot(document);\n if (!activeEditor || !caretPosition) {\n return snapshot;\n }\n\n const page = snapshot.pages.find(candidate => candidate.id === caretPosition.pageId);\n if (!page) {\n return snapshot;\n }\n\n const editorState = activeEditor.getEditorState().toJSON();\n if (caretPosition.region === 'body') {\n page.bodyState = editorState;\n } else if (caretPosition.region === 'header') {\n page.headerState = editorState;\n } else {\n page.footerState = editorState;\n }\n\n return snapshot;\n}\n\nfunction captureCaretSelection(editor: LexicalEditor | null): CaretSelection | null {\n if (!editor) {\n return null;\n }\n\n const rootElement = editor.getRootElement();\n const domSelection = window.getSelection();\n const selectionInRoot = (node: Node | null) =>\n !!node && !!rootElement && (node === rootElement || rootElement.contains(node));\n const getTextOffset = (node: Node, offset: number) => {\n if (!rootElement) {\n return 0;\n }\n\n const range = document.createRange();\n range.setStart(rootElement, 0);\n range.setEnd(node, offset);\n return range.toString().length;\n };\n\n let caretSelection: CaretSelection | null = null;\n editor.getEditorState().read(() => {\n const selection = $createRangeSelectionFromDom(window.getSelection(), editor) ?? $getSelection();\n if (!$isRangeSelection(selection)) {\n return;\n }\n\n caretSelection = {\n anchor: {\n key: selection.anchor.key,\n offset: selection.anchor.offset,\n type: selection.anchor.type,\n },\n focus: {\n key: selection.focus.key,\n offset: selection.focus.offset,\n type: selection.focus.type,\n },\n anchorTextOffset:\n domSelection && selectionInRoot(domSelection.anchorNode)\n ? getTextOffset(domSelection.anchorNode!, domSelection.anchorOffset)\n : 0,\n focusTextOffset:\n domSelection && selectionInRoot(domSelection.focusNode)\n ? getTextOffset(domSelection.focusNode!, domSelection.focusOffset)\n : 0,\n format: selection.format,\n style: selection.style,\n };\n });\n\n return caretSelection;\n}\n\nfunction getPageNumber(document: Lex4Document, pageId?: string): number | null {\n if (!pageId) {\n return null;\n }\n\n const index = document.pages.findIndex(page => page.id === pageId);\n return index >= 0 ? index + 1 : null;\n}\n\nfunction describeAction(\n action: DocumentAction,\n document: Lex4Document,\n): HistoryActionDescriptor {\n switch (action.type) {\n case 'UPDATE_PAGE_BODY': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Edited body - Page ${pageNumber}` : 'Edited body',\n source: 'body',\n pageId: action.pageId,\n region: 'body',\n };\n }\n case 'UPDATE_PAGE_HEADER':\n case 'UPDATE_PAGE_HEADER_CONTENT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Edited header - Page ${pageNumber}` : 'Edited header',\n source: 'header',\n pageId: action.pageId,\n region: 'header',\n };\n }\n case 'UPDATE_PAGE_FOOTER':\n case 'UPDATE_PAGE_FOOTER_CONTENT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Edited footer - Page ${pageNumber}` : 'Edited footer',\n source: 'footer',\n pageId: action.pageId,\n region: 'footer',\n };\n }\n case 'SET_HEADER_FOOTER_ENABLED':\n return {\n label: action.enabled ? 'Enabled headers and footers' : 'Disabled headers and footers',\n source: 'document',\n region: 'document',\n };\n case 'SET_PAGE_COUNTER_MODE':\n return {\n label: `Page counter set to ${action.mode}`,\n source: 'document',\n region: 'document',\n };\n case 'COPY_HEADER_TO_ALL':\n return {\n label: 'Copied header to all pages',\n source: 'toolbar',\n pageId: action.sourcePageId,\n region: 'header',\n };\n case 'COPY_FOOTER_TO_ALL':\n return {\n label: 'Copied footer to all pages',\n source: 'toolbar',\n pageId: action.sourcePageId,\n region: 'footer',\n };\n case 'CLEAR_HEADER': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Cleared header - Page ${pageNumber}` : 'Cleared header',\n source: 'toolbar',\n pageId: action.pageId,\n region: 'header',\n };\n }\n case 'CLEAR_FOOTER': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Cleared footer - Page ${pageNumber}` : 'Cleared footer',\n source: 'toolbar',\n pageId: action.pageId,\n region: 'footer',\n };\n }\n case 'CLEAR_ALL_HEADERS':\n return {\n label: 'Cleared all headers',\n source: 'toolbar',\n region: 'header',\n };\n case 'CLEAR_ALL_FOOTERS':\n return {\n label: 'Cleared all footers',\n source: 'toolbar',\n region: 'footer',\n };\n case 'CLEAR_DOCUMENT_CONTENT':\n return {\n label: 'Cleared document body',\n source: 'document',\n region: 'document',\n };\n case 'SET_HEADER_HEIGHT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Resized header - Page ${pageNumber}` : 'Resized header',\n source: 'header',\n pageId: action.pageId,\n region: 'header',\n };\n }\n case 'SET_FOOTER_HEIGHT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Resized footer - Page ${pageNumber}` : 'Resized footer',\n source: 'footer',\n pageId: action.pageId,\n region: 'footer',\n };\n }\n case 'ADD_PAGE':\n return {\n label: 'Added page',\n source: 'overflow',\n region: 'document',\n };\n case 'REMOVE_PAGE':\n return {\n label: 'Removed page',\n source: 'overflow',\n region: 'document',\n };\n case 'SET_DOCUMENT':\n return {\n label: 'Document reflow',\n source: 'overflow',\n region: 'document',\n };\n default:\n return {\n label: 'Updated document',\n source: 'document',\n region: 'document',\n };\n }\n}\n\nfunction documentsAreEqual(current: Lex4Document, next: Lex4Document): boolean {\n return JSON.stringify(current) === JSON.stringify(next);\n}\n\nexport const DocumentProvider: React.FC<DocumentProviderProps> = ({\n initialDocument,\n onDocumentChange,\n children,\n}) => {\n const initialSnapshot = initialDocument ?? createEmptyDocument();\n const [document, baseDispatch] = useReducer(documentReducer, initialSnapshot);\n const [historyState, setHistoryState] = useState<HistoryState>(() => createHistoryState(initialSnapshot));\n const documentRef = useRef(document);\n const historyStateRef = useRef(historyState);\n const [activePageId, setActivePageIdRaw] = useState<string | null>(\n initialSnapshot.pages[0]?.id ?? null,\n );\n const activePageIdRef = useRef<string | null>(initialSnapshot.pages[0]?.id ?? null);\n const [globalSelectionActive, setGlobalSelectionActive] = useState(false);\n const [historySidebarOpen, setHistorySidebarOpen] = useState(true);\n const [focusAtEndVersion, setFocusAtEndVersion] = useState(0);\n const activeEditorRef = useRef<LexicalEditor | null>(null);\n const activeCaretPositionRef = useRef<CaretPosition | null>(null);\n const pendingCaretPositionRef = useRef<CaretPosition | null>(null);\n const pendingCaretSelectionRef = useRef<CaretSelection | null>(null);\n const pendingFocusAtEndRef = useRef<CaretPosition | null>(null);\n const [, forceUpdate] = useState(0);\n const historySuppressedRef = useRef(false);\n const historyReleaseTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const historyFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingHistoryActionRef = useRef<HistoryActionDescriptor | null>(null);\n const pendingUndoSnapshotRef = useRef<Lex4Document | null>(null);\n const pendingUndoCaretPositionRef = useRef<CaretPosition | null>(null);\n const pendingUndoCaretSelectionRef = useRef<CaretSelection | null>(null);\n const historyBatchRef = useRef<{\n descriptor: HistoryActionDescriptor;\n nextDocument: Lex4Document | null;\n undoSnapshot: Lex4Document | null;\n undoCaretPosition: CaretPosition | null;\n undoCaretSelection: CaretSelection | null;\n hasMutation: boolean;\n } | null>(null);\n\n const editorMapRef = useRef(new Map<string, LexicalEditor>());\n const editorRegistry: EditorRegistry = useMemo(() => ({\n register: (pageId: string, editor: LexicalEditor) => {\n editorMapRef.current.set(pageId, editor);\n },\n unregister: (pageId: string) => {\n editorMapRef.current.delete(pageId);\n },\n get: (pageId: string) => editorMapRef.current.get(pageId),\n all: () => Array.from(editorMapRef.current.values()),\n }), []);\n\n const setActivePageId = useCallback((id: string | null) => {\n activePageIdRef.current = id;\n setActivePageIdRaw(id);\n }, []);\n\n const setActiveEditor = useCallback((\n editor: LexicalEditor | null,\n caretPosition: CaretPosition | null = null,\n ) => {\n activeEditorRef.current = editor;\n activeCaretPositionRef.current = caretPosition;\n forceUpdate(n => n + 1);\n }, []);\n\n const focusEditorAtEnd = useCallback((editor: LexicalEditor, caretPosition: CaretPosition) => {\n requestAnimationFrame(() => {\n setActivePageId(caretPosition.pageId);\n setActiveEditor(editor, caretPosition);\n editor.focus(() => {\n editor.update(() => {\n $getRoot().selectEnd();\n });\n });\n });\n }, [setActiveEditor, setActivePageId]);\n\n const consumePendingCaretPosition = useCallback((caretPosition: CaretPosition) => {\n const pendingCaretPosition = pendingCaretPositionRef.current;\n if (\n !pendingCaretPosition\n || pendingCaretPosition.pageId !== caretPosition.pageId\n || pendingCaretPosition.region !== caretPosition.region\n ) {\n return undefined;\n }\n\n pendingCaretPositionRef.current = null;\n const pendingCaretSelection = pendingCaretSelectionRef.current;\n pendingCaretSelectionRef.current = null;\n return pendingCaretSelection;\n }, []);\n\n const consumePendingFocusAtEnd = useCallback((caretPosition: CaretPosition) => {\n const pendingFocusAtEnd = pendingFocusAtEndRef.current;\n if (\n !pendingFocusAtEnd\n || pendingFocusAtEnd.pageId !== caretPosition.pageId\n || pendingFocusAtEnd.region !== caretPosition.region\n ) {\n return false;\n }\n\n pendingFocusAtEndRef.current = null;\n return true;\n }, []);\n\n const requestFocusAtEnd = useCallback((caretPosition: CaretPosition) => {\n pendingCaretPositionRef.current = null;\n pendingCaretSelectionRef.current = null;\n\n if (caretPosition.region === 'body') {\n const editor = editorRegistry.get(caretPosition.pageId);\n if (editor) {\n pendingFocusAtEndRef.current = null;\n focusEditorAtEnd(editor, caretPosition);\n return;\n }\n }\n\n pendingFocusAtEndRef.current = caretPosition;\n setFocusAtEndVersion(version => version + 1);\n }, [editorRegistry, focusEditorAtEnd]);\n\n const flushHistoryBatch = useCallback(() => {\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n historyFlushTimerRef.current = null;\n }\n\n const batch = historyBatchRef.current;\n historyBatchRef.current = null;\n pendingHistoryActionRef.current = null;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n\n if (!batch || historySuppressedRef.current || !batch.hasMutation || !batch.nextDocument) {\n return;\n }\n\n const undoSnapshot = batch.undoSnapshot ?? batch.nextDocument;\n\n setHistoryState(previousHistory => {\n const nextHistory = recordHistoryEntry(\n previousHistory,\n batch.nextDocument as Lex4Document,\n batch.descriptor,\n undoSnapshot,\n activeCaretPositionRef.current,\n captureCaretSelection(activeEditorRef.current),\n batch.undoCaretPosition,\n batch.undoCaretSelection,\n );\n historyStateRef.current = nextHistory;\n return nextHistory;\n });\n }, []);\n\n const scheduleHistoryBatchFlush = useCallback(() => {\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n }\n\n historyFlushTimerRef.current = setTimeout(() => {\n flushHistoryBatch();\n }, HISTORY_BATCH_FLUSH_MS);\n }, [flushHistoryBatch]);\n\n const queueHistoryAction = useCallback((action: HistoryActionDescriptor | null) => {\n pendingHistoryActionRef.current = action;\n pendingUndoSnapshotRef.current = action\n ? captureUndoSnapshot(\n documentRef.current,\n activeEditorRef.current,\n activeCaretPositionRef.current,\n )\n : null;\n pendingUndoCaretPositionRef.current = action ? activeCaretPositionRef.current : null;\n pendingUndoCaretSelectionRef.current = action ? captureCaretSelection(activeEditorRef.current) : null;\n }, []);\n\n const runHistoryAction = useCallback((action: HistoryActionDescriptor, callback: () => void) => {\n if (historyBatchRef.current) {\n callback();\n return;\n }\n\n historyBatchRef.current = {\n descriptor: action,\n nextDocument: null,\n undoSnapshot: captureUndoSnapshot(\n documentRef.current,\n activeEditorRef.current,\n activeCaretPositionRef.current,\n ),\n undoCaretPosition: activeCaretPositionRef.current,\n undoCaretSelection: captureCaretSelection(activeEditorRef.current),\n hasMutation: false,\n };\n\n pendingHistoryActionRef.current = action;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n\n try {\n callback();\n } finally {\n scheduleHistoryBatchFlush();\n }\n }, [scheduleHistoryBatchFlush]);\n\n const suppressHistoryTemporarily = useCallback(() => {\n historySuppressedRef.current = true;\n pendingHistoryActionRef.current = null;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n historyBatchRef.current = null;\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n historyFlushTimerRef.current = null;\n }\n if (historyReleaseTimerRef.current) {\n clearTimeout(historyReleaseTimerRef.current);\n }\n historyReleaseTimerRef.current = setTimeout(() => {\n historySuppressedRef.current = false;\n historyReleaseTimerRef.current = null;\n }, HISTORY_RESTORE_SUPPRESSION_MS);\n }, []);\n\n const dispatch = useCallback((action: DocumentAction) => {\n const currentDocument = documentRef.current;\n const nextDocument = documentReducer(currentDocument, action);\n const changed = !documentsAreEqual(currentDocument, nextDocument);\n const suppressPassiveBodyHistory =\n action.type === 'UPDATE_PAGE_BODY'\n && action.pageId !== activePageIdRef.current\n && !historyBatchRef.current\n && !pendingHistoryActionRef.current;\n\n documentRef.current = nextDocument;\n\n if (changed && !historySuppressedRef.current && !suppressPassiveBodyHistory) {\n if (historyBatchRef.current) {\n historyBatchRef.current.nextDocument = cloneDocumentSnapshot(nextDocument);\n historyBatchRef.current.hasMutation = true;\n scheduleHistoryBatchFlush();\n } else if (pendingHistoryActionRef.current) {\n historyBatchRef.current = {\n descriptor: pendingHistoryActionRef.current,\n nextDocument: cloneDocumentSnapshot(nextDocument),\n undoSnapshot: pendingUndoSnapshotRef.current,\n undoCaretPosition: pendingUndoCaretPositionRef.current,\n undoCaretSelection: pendingUndoCaretSelectionRef.current,\n hasMutation: true,\n };\n scheduleHistoryBatchFlush();\n } else {\n const descriptor = describeAction(action, currentDocument);\n setHistoryState(previousHistory => {\n const nextHistory = recordHistoryEntry(\n previousHistory,\n nextDocument,\n descriptor,\n captureUndoSnapshot(\n currentDocument,\n activeEditorRef.current,\n activeCaretPositionRef.current,\n ),\n activeCaretPositionRef.current,\n captureCaretSelection(activeEditorRef.current),\n activeCaretPositionRef.current,\n captureCaretSelection(activeEditorRef.current),\n );\n historyStateRef.current = nextHistory;\n return nextHistory;\n });\n }\n } else {\n pendingHistoryActionRef.current = null;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n }\n\n baseDispatch(action);\n }, [scheduleHistoryBatchFlush]);\n\n const restoreDocument = useCallback((\n snapshot: Lex4Document,\n caretPosition: CaretPosition | null,\n caretSelection: CaretSelection | null,\n ) => {\n suppressHistoryTemporarily();\n pendingCaretPositionRef.current = caretPosition;\n pendingCaretSelectionRef.current = caretSelection;\n activeEditorRef.current = null;\n activeCaretPositionRef.current = caretPosition;\n forceUpdate(n => n + 1);\n documentRef.current = cloneDocumentSnapshot(snapshot);\n baseDispatch({ type: 'SET_DOCUMENT', document: cloneDocumentSnapshot(snapshot) });\n }, [suppressHistoryTemporarily]);\n\n const undo = useCallback(() => {\n flushHistoryBatch();\n const result = undoHistory(historyStateRef.current);\n if (!result) {\n return;\n }\n\n historyStateRef.current = result.history;\n setHistoryState(result.history);\n restoreDocument(result.document, result.caretPosition, result.caretSelection);\n }, [flushHistoryBatch, restoreDocument]);\n\n const redo = useCallback(() => {\n flushHistoryBatch();\n const result = redoHistory(historyStateRef.current);\n if (!result) {\n return;\n }\n\n historyStateRef.current = result.history;\n setHistoryState(result.history);\n restoreDocument(result.document, result.caretPosition, result.caretSelection);\n }, [flushHistoryBatch, restoreDocument]);\n\n const clearHistory = useCallback(() => {\n flushHistoryBatch();\n const nextHistory = clearHistoryState(documentRef.current, activeCaretPositionRef.current);\n historyStateRef.current = nextHistory;\n setHistoryState(nextHistory);\n }, [flushHistoryBatch]);\n\n const handleJumpToHistoryEntry = useCallback((entryIndex: number) => {\n flushHistoryBatch();\n const result = jumpToHistoryEntry(historyStateRef.current, entryIndex);\n if (!result) {\n return;\n }\n\n historyStateRef.current = result.history;\n setHistoryState(result.history);\n restoreDocument(result.document, result.caretPosition, result.caretSelection);\n }, [flushHistoryBatch, restoreDocument]);\n\n useEffect(() => {\n documentRef.current = document;\n onDocumentChange?.(document);\n }, [document, onDocumentChange]);\n\n useEffect(() => {\n historyStateRef.current = historyState;\n }, [historyState]);\n\n useEffect(() => {\n const firstPageId = document.pages[0]?.id ?? null;\n const activePageStillExists = activePageId !== null\n && document.pages.some(page => page.id === activePageId);\n\n if (!activePageStillExists) {\n activePageIdRef.current = firstPageId;\n setActivePageIdRaw(firstPageId);\n activeEditorRef.current = null;\n activeCaretPositionRef.current = null;\n forceUpdate(n => n + 1);\n }\n }, [activePageId, document.pages]);\n\n useEffect(\n () => () => {\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n }\n if (historyReleaseTimerRef.current) {\n clearTimeout(historyReleaseTimerRef.current);\n }\n },\n [],\n );\n\n return (\n <DocumentContext.Provider value={{\n document,\n dispatch,\n activePageId,\n setActivePageId,\n activeEditor: activeEditorRef.current,\n consumePendingCaretPosition,\n consumePendingFocusAtEnd,\n requestFocusAtEnd,\n focusAtEndVersion,\n setActiveEditor,\n globalSelectionActive,\n setGlobalSelectionActive,\n historyEntries: historyState.entries,\n historyCursor: historyState.cursor,\n canUndo: historyState.cursor > 0,\n canRedo: historyState.cursor < historyState.entries.length,\n queueHistoryAction,\n runHistoryAction,\n jumpToHistoryEntry: handleJumpToHistoryEntry,\n clearHistory,\n historySidebarOpen,\n setHistorySidebarOpen,\n undo,\n redo,\n editorRegistry,\n }}>\n {children}\n </DocumentContext.Provider>\n );\n};\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.js';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.js.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { createContext, useContext, useMemo, createElement } from 'react';\n\nconst LucideContext = createContext({});\nfunction LucideProvider({\n children,\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n className\n}) {\n const value = useMemo(\n () => ({\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n className\n }),\n [size, color, strokeWidth, absoluteStrokeWidth, className]\n );\n return createElement(LucideContext.Provider, { value }, children);\n}\nconst useLucideContext = () => useContext(LucideContext);\n\nexport { LucideProvider, useLucideContext };\n//# sourceMappingURL=context.js.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.js';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { useLucideContext } from './context.js';\n\nconst Icon = forwardRef(\n ({ color, size, strokeWidth, absoluteStrokeWidth, className = \"\", children, iconNode, ...rest }, ref) => {\n const {\n size: contextSize = 24,\n strokeWidth: contextStrokeWidth = 2,\n absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,\n color: contextColor = \"currentColor\",\n className: contextClass = \"\"\n } = useLucideContext() ?? {};\n const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;\n return createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size ?? contextSize ?? defaultAttributes.width,\n height: size ?? contextSize ?? defaultAttributes.height,\n stroke: color ?? contextColor,\n strokeWidth: calculatedStrokeWidth,\n className: mergeClasses(\"lucide\", contextClass, className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n );\n }\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { toKebabCase } from './shared/src/utils/toKebabCase.js';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8\", key: \"mg9rjx\" }\n ]\n];\nconst Bold = createLucideIcon(\"bold\", __iconNode);\n\nexport { __iconNode, Bold as default };\n//# sourceMappingURL=bold.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"15\", x2: \"15\", y1: \"12\", y2: \"18\", key: \"1p7wdc\" }],\n [\"line\", { x1: \"12\", x2: \"18\", y1: \"15\", y2: \"15\", key: \"1nscbv\" }],\n [\"rect\", { width: \"14\", height: \"14\", x: \"8\", y: \"8\", rx: \"2\", ry: \"2\", key: \"17jyea\" }],\n [\"path\", { d: \"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\", key: \"zix9uf\" }]\n];\nconst CopyPlus = createLucideIcon(\"copy-plus\", __iconNode);\n\nexport { __iconNode, CopyPlus as default };\n//# sourceMappingURL=copy-plus.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21\",\n key: \"g5wo59\"\n }\n ],\n [\"path\", { d: \"m5.082 11.09 8.828 8.828\", key: \"1wx5vj\" }]\n];\nconst Eraser = createLucideIcon(\"eraser\", __iconNode);\n\nexport { __iconNode, Eraser as default };\n//# sourceMappingURL=eraser.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"9\", y2: \"9\", key: \"4lhtct\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"15\", y2: \"15\", key: \"vyu0kd\" }],\n [\"line\", { x1: \"10\", x2: \"8\", y1: \"3\", y2: \"21\", key: \"1ggp8o\" }],\n [\"line\", { x1: \"16\", x2: \"14\", y1: \"3\", y2: \"21\", key: \"weycgp\" }]\n];\nconst Hash = createLucideIcon(\"hash\", __iconNode);\n\nexport { __iconNode, Hash as default };\n//# sourceMappingURL=hash.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"19\", x2: \"10\", y1: \"4\", y2: \"4\", key: \"15jd3p\" }],\n [\"line\", { x1: \"14\", x2: \"5\", y1: \"20\", y2: \"20\", key: \"bu0au3\" }],\n [\"line\", { x1: \"15\", x2: \"9\", y1: \"4\", y2: \"20\", key: \"uljnxc\" }]\n];\nconst Italic = createLucideIcon(\"italic\", __iconNode);\n\nexport { __iconNode, Italic as default };\n//# sourceMappingURL=italic.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H11\", key: \"us1j55\" }],\n [\"path\", { d: \"M21 12H11\", key: \"wd7e0v\" }],\n [\"path\", { d: \"M21 19H11\", key: \"saa85w\" }],\n [\"path\", { d: \"m7 8-4 4 4 4\", key: \"o5hrat\" }]\n];\nconst ListIndentDecrease = createLucideIcon(\"list-indent-decrease\", __iconNode);\n\nexport { __iconNode, ListIndentDecrease as default };\n//# sourceMappingURL=list-indent-decrease.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H11\", key: \"us1j55\" }],\n [\"path\", { d: \"M21 12H11\", key: \"wd7e0v\" }],\n [\"path\", { d: \"M21 19H11\", key: \"saa85w\" }],\n [\"path\", { d: \"m3 8 4 4-4 4\", key: \"1a3j6y\" }]\n];\nconst ListIndentIncrease = createLucideIcon(\"list-indent-increase\", __iconNode);\n\nexport { __iconNode, ListIndentIncrease as default };\n//# sourceMappingURL=list-indent-increase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 5h10\", key: \"1cz7ny\" }],\n [\"path\", { d: \"M11 12h10\", key: \"1438ji\" }],\n [\"path\", { d: \"M11 19h10\", key: \"11t30w\" }],\n [\"path\", { d: \"M4 4h1v5\", key: \"10yrso\" }],\n [\"path\", { d: \"M4 9h2\", key: \"r1h2o0\" }],\n [\"path\", { d: \"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02\", key: \"xtkcd5\" }]\n];\nconst ListOrdered = createLucideIcon(\"list-ordered\", __iconNode);\n\nexport { __iconNode, ListOrdered as default };\n//# sourceMappingURL=list-ordered.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 5h.01\", key: \"18ugdj\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M3 19h.01\", key: \"noohij\" }],\n [\"path\", { d: \"M8 5h13\", key: \"1pao27\" }],\n [\"path\", { d: \"M8 12h13\", key: \"1za7za\" }],\n [\"path\", { d: \"M8 19h13\", key: \"m83p4d\" }]\n];\nconst List = createLucideIcon(\"list\", __iconNode);\n\nexport { __iconNode, List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n];\nconst PanelRight = createLucideIcon(\"panel-right\", __iconNode);\n\nexport { __iconNode, PanelRight as default };\n//# sourceMappingURL=panel-right.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m15 14 5-5-5-5\", key: \"12vg1m\" }],\n [\"path\", { d: \"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13\", key: \"6uklza\" }]\n];\nconst Redo2 = createLucideIcon(\"redo-2\", __iconNode);\n\nexport { __iconNode, Redo2 as default };\n//# sourceMappingURL=redo-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M16 4H9a3 3 0 0 0-2.83 4\", key: \"43sutm\" }],\n [\"path\", { d: \"M14 12a4 4 0 0 1 0 8H6\", key: \"nlfj13\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"12\", y2: \"12\", key: \"1e0a9i\" }]\n];\nconst Strikethrough = createLucideIcon(\"strikethrough\", __iconNode);\n\nexport { __iconNode, Strikethrough as default };\n//# sourceMappingURL=strikethrough.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H3\", key: \"1fi0y6\" }],\n [\"path\", { d: \"M17 12H7\", key: \"16if0g\" }],\n [\"path\", { d: \"M19 19H5\", key: \"vjpgq2\" }]\n];\nconst TextAlignCenter = createLucideIcon(\"text-align-center\", __iconNode);\n\nexport { __iconNode, TextAlignCenter as default };\n//# sourceMappingURL=text-align-center.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H3\", key: \"1fi0y6\" }],\n [\"path\", { d: \"M21 12H9\", key: \"dn1m92\" }],\n [\"path\", { d: \"M21 19H7\", key: \"4cu937\" }]\n];\nconst TextAlignEnd = createLucideIcon(\"text-align-end\", __iconNode);\n\nexport { __iconNode, TextAlignEnd as default };\n//# sourceMappingURL=text-align-end.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 5h18\", key: \"1u36vt\" }],\n [\"path\", { d: \"M3 12h18\", key: \"1i2n21\" }],\n [\"path\", { d: \"M3 19h18\", key: \"awlh7x\" }]\n];\nconst TextAlignJustify = createLucideIcon(\"text-align-justify\", __iconNode);\n\nexport { __iconNode, TextAlignJustify as default };\n//# sourceMappingURL=text-align-justify.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H3\", key: \"1fi0y6\" }],\n [\"path\", { d: \"M15 12H3\", key: \"6jk70r\" }],\n [\"path\", { d: \"M17 19H3\", key: \"z6ezky\" }]\n];\nconst TextAlignStart = createLucideIcon(\"text-align-start\", __iconNode);\n\nexport { __iconNode, TextAlignStart as default };\n//# sourceMappingURL=text-align-start.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M6 4v6a6 6 0 0 0 12 0V4\", key: \"9kb039\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"20\", y2: \"20\", key: \"nun2al\" }]\n];\nconst Underline = createLucideIcon(\"underline\", __iconNode);\n\nexport { __iconNode, Underline as default };\n//# sourceMappingURL=underline.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M9 14 4 9l5-5\", key: \"102s5s\" }],\n [\"path\", { d: \"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\", key: \"f3b9sd\" }]\n];\nconst Undo2 = createLucideIcon(\"undo-2\", __iconNode);\n\nexport { __iconNode, Undo2 as default };\n//# sourceMappingURL=undo-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n];\nconst X = createLucideIcon(\"x\", __iconNode);\n\nexport { __iconNode, X as default };\n//# sourceMappingURL=x.js.map\n","import React from 'react';\nimport { X } from 'lucide-react';\n\ninterface EditorSidebarProps {\n title: string;\n subtitle?: string;\n open: boolean;\n onClose?: () => void;\n headerActions?: React.ReactNode;\n children: React.ReactNode;\n}\n\nexport const EditorSidebar: React.FC<EditorSidebarProps> = ({\n title,\n subtitle,\n open,\n onClose,\n headerActions,\n children,\n}) => {\n if (!open) {\n return null;\n }\n\n return (\n <aside\n className=\"flex h-full w-[320px] shrink-0 flex-col border-l border-gray-200 bg-white\"\n data-testid=\"editor-sidebar\"\n >\n <div className=\"flex items-start justify-between border-b border-gray-200 px-3 py-2.5\">\n <div>\n <h2 className=\"text-xs font-semibold text-gray-900\">{title}</h2>\n {subtitle && (\n <p className=\"mt-0.5 text-xs text-gray-500\">{subtitle}</p>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n {headerActions}\n {onClose && (\n <button\n type=\"button\"\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-400\n transition-colors hover:bg-gray-100 hover:text-gray-600\"\n data-testid=\"close-editor-sidebar\"\n onClick={onClose}\n aria-label=\"Close sidebar\"\n >\n <X size={14} />\n </button>\n )}\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {children}\n </div>\n </aside>\n );\n};\n","import React from 'react';\nimport { Trash2 } from 'lucide-react';\nimport { useDocument } from '../context/document-context';\nimport { EditorSidebar } from './EditorSidebar';\n\nfunction formatTimestamp(timestamp: string): string {\n const date = new Date(timestamp);\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nexport const HistorySidebar: React.FC = () => {\n const {\n clearHistory,\n historyEntries,\n historyCursor,\n historySidebarOpen,\n jumpToHistoryEntry,\n setHistorySidebarOpen,\n } = useDocument();\n\n const visibleEntries = historyEntries.slice().reverse();\n\n const headerActions = (\n <button\n type=\"button\"\n title=\"Clear History\"\n aria-label=\"Clear History\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => clearHistory('manual')}\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-400\n transition-colors hover:bg-gray-100 hover:text-gray-600\"\n data-testid=\"clear-history\"\n >\n <Trash2 size={13} />\n </button>\n );\n\n return (\n <EditorSidebar\n title=\"History\"\n subtitle=\"Word-style session history (last 100 actions)\"\n open={historySidebarOpen}\n onClose={() => setHistorySidebarOpen(false)}\n headerActions={headerActions}\n >\n {visibleEntries.length === 0 ? (\n <div\n className=\"px-3 py-4 text-xs text-gray-500\"\n data-testid=\"history-empty\"\n >\n No history yet.\n </div>\n ) : (\n <ol className=\"divide-y divide-gray-100\" data-testid=\"history-entry-list\">\n {visibleEntries.map((entry, reversedIndex) => {\n const actualIndex = historyEntries.length - reversedIndex - 1;\n const isCurrent = actualIndex === historyCursor - 1;\n\n return (\n <li key={entry.id}>\n <button\n type=\"button\"\n className={`w-full px-3 py-2 text-left transition-colors ${\n isCurrent ? 'bg-blue-50' : 'bg-white hover:bg-gray-50'\n }`}\n data-testid={`history-entry-${actualIndex}`}\n data-history-current={isCurrent ? 'true' : 'false'}\n onClick={() => jumpToHistoryEntry(actualIndex)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className={`text-xs ${isCurrent ? 'font-semibold text-blue-700' : 'text-gray-900'}`}>\n {entry.label}\n </div>\n <div className=\"mt-0.5 text-xs text-gray-400\">\n {entry.source}\n </div>\n </div>\n <div className=\"shrink-0 text-xs text-gray-400\">\n {formatTimestamp(entry.timestamp)}\n </div>\n </div>\n </button>\n </li>\n );\n })}\n </ol>\n )}\n </EditorSidebar>\n );\n};\n","import React from 'react';\n\ninterface HeaderFooterToggleProps {\n enabled: boolean;\n onToggle: (enabled: boolean) => void;\n}\n\nexport const HeaderFooterToggle: React.FC<HeaderFooterToggleProps> = ({\n enabled,\n onToggle,\n}) => {\n return (\n <label\n className=\"flex items-center gap-1.5 cursor-pointer select-none\"\n data-testid=\"header-footer-toggle\"\n >\n <span className=\"text-xs font-medium text-gray-600\">\n Headers & Footers\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={enabled}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onToggle(!enabled)}\n className={`\n relative inline-flex h-4 w-7 items-center rounded-full\n transition-colors duration-200\n ${enabled ? 'bg-blue-500' : 'bg-gray-300'}\n `}\n data-testid=\"header-footer-switch\"\n >\n <span\n className={`\n inline-block h-3 w-3 rounded-full bg-white shadow-sm\n transition-transform duration-200\n ${enabled ? 'translate-x-3.5' : 'translate-x-0.5'}\n `}\n />\n </button>\n </label>\n );\n};\n","import React from 'react';\nimport {\n Hash,\n CopyPlus,\n Eraser,\n Trash2,\n} from 'lucide-react';\nimport type { PageCounterMode } from '../types/document';\n\ninterface HeaderFooterActionsProps {\n activePageId: string | null;\n pageCounterMode: PageCounterMode;\n onPageCounterModeChange: (mode: PageCounterMode) => void;\n onCopyHeaderToAll: () => void;\n onCopyFooterToAll: () => void;\n onClearHeader: () => void;\n onClearFooter: () => void;\n onClearAllHeaders: () => void;\n onClearAllFooters: () => void;\n}\n\nexport const HeaderFooterActions: React.FC<HeaderFooterActionsProps> = ({\n activePageId,\n pageCounterMode,\n onPageCounterModeChange,\n onCopyHeaderToAll,\n onCopyFooterToAll,\n onClearHeader,\n onClearFooter,\n onClearAllHeaders,\n onClearAllFooters,\n}) => {\n const hasActivePage = activePageId !== null;\n const handlePageCounterModeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\n const nextMode = event.target.value;\n if (nextMode === 'none' || nextMode === 'header' || nextMode === 'footer' || nextMode === 'both') {\n onPageCounterModeChange(nextMode);\n }\n };\n\n return (\n <div\n className=\"flex flex-wrap items-center gap-2 text-xs\"\n data-testid=\"header-footer-actions\"\n >\n <label className=\"flex items-center gap-1 text-gray-500\" htmlFor=\"page-counter-mode\">\n <Hash size={13} className=\"text-gray-400\" />\n <select\n id=\"page-counter-mode\"\n className=\"h-6 rounded border border-gray-200 bg-white px-1.5 text-xs text-gray-600\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400\"\n data-testid=\"page-counter-mode\"\n value={pageCounterMode}\n onChange={handlePageCounterModeChange}\n >\n <option value=\"none\">None</option>\n <option value=\"header\">Header</option>\n <option value=\"footer\">Footer</option>\n <option value=\"both\">Both</option>\n </select>\n </label>\n\n <ActionDivider />\n\n <span className=\"text-gray-400 font-medium\">Header</span>\n <ActionIconButton\n title=\"Copy header to all pages\"\n icon={<CopyPlus size={13} />}\n onClick={onCopyHeaderToAll}\n disabled={!hasActivePage}\n testId=\"copy-header-all\"\n />\n <ActionIconButton\n title=\"Clear header on this page\"\n icon={<Eraser size={13} />}\n onClick={onClearHeader}\n disabled={!hasActivePage}\n testId=\"clear-header\"\n />\n <ActionIconButton\n title=\"Clear all headers\"\n icon={<Trash2 size={13} />}\n onClick={onClearAllHeaders}\n testId=\"clear-all-headers\"\n />\n\n <ActionDivider />\n\n <span className=\"text-gray-400 font-medium\">Footer</span>\n <ActionIconButton\n title=\"Copy footer to all pages\"\n icon={<CopyPlus size={13} />}\n onClick={onCopyFooterToAll}\n disabled={!hasActivePage}\n testId=\"copy-footer-all\"\n />\n <ActionIconButton\n title=\"Clear footer on this page\"\n icon={<Eraser size={13} />}\n onClick={onClearFooter}\n disabled={!hasActivePage}\n testId=\"clear-footer\"\n />\n <ActionIconButton\n title=\"Clear all footers\"\n icon={<Trash2 size={13} />}\n onClick={onClearAllFooters}\n testId=\"clear-all-footers\"\n />\n </div>\n );\n};\n\ninterface ActionIconButtonProps {\n title: string;\n icon: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n testId: string;\n}\n\nconst ActionIconButton: React.FC<ActionIconButtonProps> = ({ title, icon, onClick, disabled, testId }) => (\n <button\n type=\"button\"\n title={title}\n aria-label={title}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n disabled={disabled}\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-500 transition-colors\n hover:bg-gray-200/60 hover:text-gray-700\n disabled:cursor-not-allowed disabled:text-gray-300\"\n data-testid={testId}\n >\n {icon}\n </button>\n);\n\nconst ActionDivider: React.FC = () => (\n <div className=\"mx-0.5 h-4 w-px bg-gray-300/60\" />\n);\n","import React, { useCallback, useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n COMMAND_PRIORITY_LOW,\n SELECTION_CHANGE_COMMAND,\n type LexicalEditor,\n} from 'lexical';\n\nconst SUPPORTED_FONTS = [\n 'Times New Roman',\n 'Arial',\n 'Calibri',\n 'Georgia',\n 'Courier New',\n] as const;\n\nexport type FontFamily = (typeof SUPPORTED_FONTS)[number];\n\nexport { SUPPORTED_FONTS };\n\n/**\n * Applies a font family to the current text selection by setting\n * inline CSS style on each selected text node.\n */\nexport function applyFontFamily(editor: LexicalEditor, fontFamily: FontFamily): void {\n editor.update(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const nodes = selection.getNodes();\n for (const node of nodes) {\n if ($isTextNode(node)) {\n node.setStyle(`font-family: ${fontFamily}`);\n }\n }\n });\n}\n\ninterface FontPluginProps {\n onFontChange?: (font: string) => void;\n}\n\n/**\n * FontPlugin — tracks the current selection's font and exposes a callback\n * for the toolbar to display the active font.\n */\nexport const FontPlugin: React.FC<FontPluginProps> = ({ onFontChange }) => {\n const [editor] = useLexicalComposerContext();\n\n const reportFont = useCallback(() => {\n editor.getEditorState().read(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const node = selection.getNodes()[0];\n if ($isTextNode(node)) {\n const style = node.getStyle();\n const match = style.match(/font-family:\\s*([^;]+)/);\n onFontChange?.(match ? match[1].trim() : 'Arial');\n }\n });\n }, [editor, onFontChange]);\n\n useEffect(() => {\n return editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n reportFont();\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [editor, reportFont]);\n\n return null;\n};\n","import {\n FORMAT_TEXT_COMMAND,\n type LexicalEditor,\n type TextFormatType,\n} from 'lexical';\nimport { FORMAT_ELEMENT_COMMAND, type ElementFormatType } from 'lexical';\n\n/**\n * Dispatches a text formatting command to the given Lexical editor.\n */\nexport function toggleFormat(editor: LexicalEditor, format: TextFormatType): void {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);\n}\n\nexport function toggleBold(editor: LexicalEditor): void {\n toggleFormat(editor, 'bold');\n}\n\nexport function toggleItalic(editor: LexicalEditor): void {\n toggleFormat(editor, 'italic');\n}\n\nexport function toggleUnderline(editor: LexicalEditor): void {\n toggleFormat(editor, 'underline');\n}\n\nexport function toggleStrikethrough(editor: LexicalEditor): void {\n toggleFormat(editor, 'strikethrough');\n}\n\n/**\n * Dispatches an element alignment command.\n */\nexport function setAlignment(editor: LexicalEditor, alignment: ElementFormatType): void {\n editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, alignment);\n}\n","import {\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list';\nimport {\n INDENT_CONTENT_COMMAND,\n OUTDENT_CONTENT_COMMAND,\n type LexicalEditor,\n} from 'lexical';\n\nexport type ListType = 'number' | 'bullet';\n\n/**\n * Inserts a list of the given type into the editor.\n */\nexport function insertList(editor: LexicalEditor, type: ListType): void {\n if (type === 'number') {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n }\n}\n\n/**\n * Removes the current list formatting.\n */\nexport function removeList(editor: LexicalEditor): void {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n}\n\n/**\n * Indents the current selection.\n *\n * Paragraphs are rendered as first-line indents by the paragraph indent plugin,\n * while list items keep Lexical's native nesting behavior.\n */\nexport function indentContent(editor: LexicalEditor): void {\n editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined);\n}\n\n/**\n * Outdents the current selection.\n *\n * Paragraphs are rendered as first-line indents by the paragraph indent plugin,\n * while list items keep Lexical's native un-nesting behavior.\n */\nexport function outdentContent(editor: LexicalEditor): void {\n editor.dispatchCommand(OUTDENT_CONTENT_COMMAND, undefined);\n}\n","import React, { useCallback } from 'react';\nimport { $selectAll, type LexicalEditor } from 'lexical';\nimport {\n Undo2,\n Redo2,\n Bold,\n Italic,\n Underline,\n Strikethrough,\n AlignLeft,\n AlignCenter,\n AlignRight,\n AlignJustify,\n ListOrdered,\n List,\n IndentIncrease,\n IndentDecrease,\n PanelRight,\n} from 'lucide-react';\nimport { useDocument } from '../context/document-context';\nimport { HeaderFooterToggle } from './HeaderFooterToggle';\nimport { HeaderFooterActions } from './HeaderFooterActions';\nimport type { PageCounterMode } from '../types/document';\nimport { SUPPORTED_FONTS } from '../lexical/plugins/font-plugin';\nimport { applyFontFamily, type FontFamily } from '../lexical/plugins/font-plugin';\nimport { toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, setAlignment } from '../lexical/commands/format-commands';\nimport { insertList, indentContent, outdentContent } from '../lexical/commands/list-commands';\nimport { debug } from '../utils/debug';\n\nexport const Toolbar: React.FC = () => {\n const {\n document,\n dispatch,\n activePageId,\n activeEditor,\n canRedo,\n canUndo,\n editorRegistry,\n globalSelectionActive,\n historySidebarOpen,\n redo,\n runHistoryAction,\n setHistorySidebarOpen,\n undo,\n } = useDocument();\n\n const withBodySelection = useCallback(\n (editor: LexicalEditor, action: (targetEditor: LexicalEditor) => void) => {\n editor.update(() => {\n $selectAll();\n });\n action(editor);\n },\n [],\n );\n\n const applyToBodyEditors = useCallback(\n (action: (targetEditor: LexicalEditor) => void) => {\n const targetEditors = globalSelectionActive\n ? editorRegistry.all()\n : activeEditor\n ? [activeEditor]\n : [];\n\n targetEditors.forEach(editor => {\n if (globalSelectionActive) {\n withBodySelection(editor, action);\n } else {\n action(editor);\n }\n });\n },\n [activeEditor, editorRegistry, globalSelectionActive, withBodySelection],\n );\n\n const runToolbarAction = useCallback(\n (label: string, callback: () => void) => {\n runHistoryAction(\n {\n label,\n source: 'toolbar',\n region: 'document',\n },\n callback,\n );\n },\n [runHistoryAction],\n );\n\n const handleToggle = (enabled: boolean) => {\n runToolbarAction(\n enabled ? 'Enabled headers and footers' : 'Disabled headers and footers',\n () => {\n dispatch({ type: 'SET_HEADER_FOOTER_ENABLED', enabled });\n },\n );\n };\n\n const handleCopyHeaderToAll = () => {\n if (activePageId) {\n runToolbarAction('Copied header to all pages', () => {\n dispatch({ type: 'COPY_HEADER_TO_ALL', sourcePageId: activePageId });\n });\n }\n };\n const handleCopyFooterToAll = () => {\n if (activePageId) {\n runToolbarAction('Copied footer to all pages', () => {\n dispatch({ type: 'COPY_FOOTER_TO_ALL', sourcePageId: activePageId });\n });\n }\n };\n const handleClearHeader = () => {\n if (activePageId) {\n runToolbarAction('Cleared header', () => {\n dispatch({ type: 'CLEAR_HEADER', pageId: activePageId });\n });\n }\n };\n const handleClearFooter = () => {\n if (activePageId) {\n runToolbarAction('Cleared footer', () => {\n dispatch({ type: 'CLEAR_FOOTER', pageId: activePageId });\n });\n }\n };\n const handleClearAllHeaders = () => runToolbarAction('Cleared all headers', () => {\n dispatch({ type: 'CLEAR_ALL_HEADERS' });\n });\n const handleClearAllFooters = () => runToolbarAction('Cleared all footers', () => {\n dispatch({ type: 'CLEAR_ALL_FOOTERS' });\n });\n const handlePageCounterModeChange = useCallback((mode: PageCounterMode) => {\n runToolbarAction(`Page counter set to ${mode}`, () => {\n dispatch({ type: 'SET_PAGE_COUNTER_MODE', mode });\n });\n }, [dispatch, runToolbarAction]);\n\n const handleBold = useCallback(() => {\n debug('toolbar', `bold (globalSelection=${globalSelectionActive}, editors=${editorRegistry.all().length}, hasEditor=${!!activeEditor})`);\n runToolbarAction('Bold applied', () => {\n applyToBodyEditors(toggleBold);\n });\n }, [activeEditor, applyToBodyEditors, editorRegistry, globalSelectionActive, runToolbarAction]);\n\n const handleItalic = useCallback(() => {\n debug('toolbar', `italic (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);\n runToolbarAction('Italic applied', () => {\n applyToBodyEditors(toggleItalic);\n });\n }, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction]);\n\n const handleUnderline = useCallback(() => {\n debug('toolbar', `underline (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);\n runToolbarAction('Underline applied', () => {\n applyToBodyEditors(toggleUnderline);\n });\n }, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction]);\n\n const handleStrikethrough = useCallback(() => {\n debug('toolbar', `strikethrough (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);\n runToolbarAction('Strikethrough applied', () => {\n applyToBodyEditors(toggleStrikethrough);\n });\n }, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction]);\n\n const handleAlignLeft = useCallback(() => {\n runToolbarAction('Aligned left', () => {\n applyToBodyEditors(editor => setAlignment(editor, 'left'));\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleAlignCenter = useCallback(() => {\n runToolbarAction('Aligned center', () => {\n applyToBodyEditors(editor => setAlignment(editor, 'center'));\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleAlignRight = useCallback(() => {\n runToolbarAction('Aligned right', () => {\n applyToBodyEditors(editor => setAlignment(editor, 'right'));\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleAlignJustify = useCallback(() => {\n runToolbarAction('Justified text', () => {\n applyToBodyEditors(editor => setAlignment(editor, 'justify'));\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleListNumber = useCallback(() => {\n runToolbarAction('Inserted numbered list', () => {\n applyToBodyEditors(editor => insertList(editor, 'number'));\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleListBullet = useCallback(() => {\n runToolbarAction('Inserted bullet list', () => {\n applyToBodyEditors(editor => insertList(editor, 'bullet'));\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleIndent = useCallback(() => {\n runToolbarAction('Indented content', () => {\n applyToBodyEditors(indentContent);\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleOutdent = useCallback(() => {\n runToolbarAction('Outdented content', () => {\n applyToBodyEditors(outdentContent);\n });\n }, [applyToBodyEditors, runToolbarAction]);\n\n const handleFontChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n runToolbarAction(`Font changed to ${e.target.value}`, () => {\n applyToBodyEditors(editor => applyFontFamily(editor, e.target.value as FontFamily));\n });\n },\n [applyToBodyEditors, runToolbarAction],\n );\n\n return (\n <div\n className=\"lex4-toolbar sticky top-0 z-10 bg-white border-b border-gray-200\"\n data-testid=\"toolbar\"\n >\n <div className=\"flex items-center gap-1 px-2 py-1.5\">\n <div className=\"flex items-center gap-0.5\" data-testid=\"history-controls\">\n <ToolbarIconButton\n title=\"Undo\"\n testId=\"btn-undo\"\n disabled={!canUndo}\n onClick={undo}\n >\n <Undo2 size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton\n title=\"Redo\"\n testId=\"btn-redo\"\n disabled={!canRedo}\n onClick={redo}\n >\n <Redo2 size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <select\n className=\"h-7 rounded border border-gray-200 bg-white px-2 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400\"\n data-testid=\"font-selector\"\n defaultValue=\"Arial\"\n onChange={handleFontChange}\n >\n {SUPPORTED_FONTS.map(font => (\n <option key={font} value={font} style={{ fontFamily: font }}>\n {font}\n </option>\n ))}\n </select>\n\n <Divider />\n\n <div className=\"flex items-center gap-0.5\" data-testid=\"format-group\">\n <ToolbarIconButton title=\"Bold (Ctrl+B)\" testId=\"btn-bold\" onClick={handleBold}>\n <Bold size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Italic (Ctrl+I)\" testId=\"btn-italic\" onClick={handleItalic}>\n <Italic size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Underline (Ctrl+U)\" testId=\"btn-underline\" onClick={handleUnderline}>\n <Underline size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Strikethrough\" testId=\"btn-strike\" onClick={handleStrikethrough}>\n <Strikethrough size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <div className=\"flex items-center gap-0.5\" data-testid=\"align-group\">\n <ToolbarIconButton title=\"Align Left\" testId=\"btn-align-left\" onClick={handleAlignLeft}>\n <AlignLeft size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Align Center\" testId=\"btn-align-center\" onClick={handleAlignCenter}>\n <AlignCenter size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Align Right\" testId=\"btn-align-right\" onClick={handleAlignRight}>\n <AlignRight size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Justify\" testId=\"btn-align-justify\" onClick={handleAlignJustify}>\n <AlignJustify size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <div className=\"flex items-center gap-0.5\" data-testid=\"list-group\">\n <ToolbarIconButton title=\"Numbered List\" testId=\"btn-list-number\" onClick={handleListNumber}>\n <ListOrdered size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Bullet List\" testId=\"btn-list-bullet\" onClick={handleListBullet}>\n <List size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Indent\" testId=\"btn-indent\" onClick={handleIndent}>\n <IndentIncrease size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title=\"Outdent\" testId=\"btn-outdent\" onClick={handleOutdent}>\n <IndentDecrease size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <HeaderFooterToggle\n enabled={document.headerFooterEnabled}\n onToggle={handleToggle}\n />\n\n {document.headerFooterEnabled && (\n <>\n <Divider />\n <HeaderFooterActions\n activePageId={activePageId}\n pageCounterMode={document.pageCounterMode}\n onPageCounterModeChange={handlePageCounterModeChange}\n onCopyHeaderToAll={handleCopyHeaderToAll}\n onCopyFooterToAll={handleCopyFooterToAll}\n onClearHeader={handleClearHeader}\n onClearFooter={handleClearFooter}\n onClearAllHeaders={handleClearAllHeaders}\n onClearAllFooters={handleClearAllFooters}\n />\n </>\n )}\n\n <div className=\"ml-auto flex items-center\">\n <ToolbarIconButton\n title={historySidebarOpen ? 'Close History' : 'Open History'}\n testId=\"toggle-history-sidebar\"\n active={historySidebarOpen}\n onClick={() => setHistorySidebarOpen(!historySidebarOpen)}\n >\n <PanelRight size={15} />\n </ToolbarIconButton>\n </div>\n </div>\n </div>\n );\n};\n\ninterface ToolbarIconButtonProps {\n title: string;\n testId: string;\n disabled?: boolean;\n active?: boolean;\n onClick?: () => void;\n children: React.ReactNode;\n}\n\nconst ToolbarIconButton: React.FC<ToolbarIconButtonProps> = ({\n title,\n testId,\n disabled = false,\n active = false,\n onClick,\n children,\n}) => (\n <button\n type=\"button\"\n title={title}\n aria-label={title}\n disabled={disabled}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n className={`\n flex h-7 w-7 items-center justify-center rounded transition-colors\n ${disabled\n ? 'cursor-not-allowed text-gray-300'\n : active\n ? 'bg-blue-50 text-blue-600'\n : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'}\n `}\n data-testid={testId}\n >\n {children}\n </button>\n);\n\nconst Divider: React.FC = () => (\n <div className=\"mx-0.5 h-5 w-px bg-gray-200\" />\n);","import {\n A4_HEIGHT_PX,\n PAGE_MARGIN_PX,\n} from './dimensions';\n\n/**\n * Computes the available body height for a page, accounting for\n * header/footer heights and page margins.\n */\nexport function computeBodyHeight(\n headerHeight: number,\n footerHeight: number,\n): number {\n const verticalMargins = PAGE_MARGIN_PX * 2;\n return A4_HEIGHT_PX - headerHeight - footerHeight - verticalMargins;\n}\n\n/**\n * Computes the content area height based on whether\n * headers/footers are enabled.\n */\nexport function computeContentAreaHeight(\n headerFooterEnabled: boolean,\n headerHeight: number,\n footerHeight: number,\n): number {\n if (!headerFooterEnabled) {\n return computeBodyHeight(0, 0);\n }\n return computeBodyHeight(headerHeight, footerHeight);\n}\n","import type { SerializedEditorState, SerializedLexicalNode } from 'lexical';\n\n/**\n * Utilities for splitting and merging Lexical editor states.\n *\n * A SerializedEditorState has shape:\n * { root: { children: [...], type: \"root\", ... } }\n *\n * Content flow between pages is achieved by manipulating\n * the root.children array — extracting, splitting, merging\n * top-level block nodes.\n */\n\n/** Extract all top-level nodes from a serialized editor state */\nexport function getTopLevelNodes(state: SerializedEditorState | null): SerializedLexicalNode[] {\n if (!state) return [];\n return (state.root as any).children ?? [];\n}\n\n/** Count top-level nodes in a serialized editor state */\nexport function countTopLevelNodes(state: SerializedEditorState | null): number {\n return getTopLevelNodes(state).length;\n}\n\n/**\n * Create a SerializedEditorState from a list of top-level nodes.\n * Uses a standard root wrapper.\n */\nexport function createEditorStateFromNodes(\n nodes: SerializedLexicalNode[],\n): SerializedEditorState {\n return {\n root: {\n children: nodes,\n direction: null,\n format: '',\n indent: 0,\n type: 'root',\n version: 1,\n },\n } as SerializedEditorState;\n}\n\n/**\n * Split a serialized editor state at a given node index.\n *\n * Returns [before, after] where:\n * - before contains nodes 0..splitIndex-1\n * - after contains nodes splitIndex..end\n */\nexport function splitEditorState(\n state: SerializedEditorState | null,\n splitIndex: number,\n): [SerializedEditorState | null, SerializedEditorState | null] {\n const nodes = getTopLevelNodes(state);\n\n if (splitIndex <= 0) {\n return [null, state];\n }\n if (splitIndex >= nodes.length) {\n return [state, null];\n }\n\n const before = nodes.slice(0, splitIndex);\n const after = nodes.slice(splitIndex);\n\n return [\n before.length > 0 ? createEditorStateFromNodes(before) : null,\n after.length > 0 ? createEditorStateFromNodes(after) : null,\n ];\n}\n\n/**\n * Merge two serialized editor states by concatenating their top-level nodes.\n * Returns a new state with all nodes from both states.\n */\nexport function mergeEditorStates(\n stateA: SerializedEditorState | null,\n stateB: SerializedEditorState | null,\n): SerializedEditorState | null {\n const nodesA = getTopLevelNodes(stateA);\n const nodesB = getTopLevelNodes(stateB);\n\n const all = [...nodesA, ...nodesB];\n if (all.length === 0) return null;\n\n return createEditorStateFromNodes(all);\n}\n\n/**\n * Append nodes to the end of a serialized editor state.\n */\nexport function appendNodes(\n state: SerializedEditorState | null,\n nodes: SerializedLexicalNode[],\n): SerializedEditorState {\n const existing = getTopLevelNodes(state);\n return createEditorStateFromNodes([...existing, ...nodes]);\n}\n\n/**\n * Remove the last N nodes from a serialized editor state.\n * Returns [trimmedState, removedNodes].\n */\nexport function removeLastNodes(\n state: SerializedEditorState | null,\n count: number,\n): [SerializedEditorState | null, SerializedLexicalNode[]] {\n const nodes = getTopLevelNodes(state);\n if (count >= nodes.length) {\n return [null, [...nodes]];\n }\n\n const kept = nodes.slice(0, nodes.length - count);\n const removed = nodes.slice(nodes.length - count);\n\n return [\n kept.length > 0 ? createEditorStateFromNodes(kept) : null,\n removed,\n ];\n}\n\n/**\n * Remove the first N nodes from a serialized editor state.\n * Returns [removedNodes, remainingState].\n */\nexport function removeFirstNodes(\n state: SerializedEditorState | null,\n count: number,\n): [SerializedLexicalNode[], SerializedEditorState | null] {\n const nodes = getTopLevelNodes(state);\n if (count >= nodes.length) {\n return [[...nodes], null];\n }\n\n const removed = nodes.slice(0, count);\n const remaining = nodes.slice(count);\n\n return [\n removed,\n remaining.length > 0 ? createEditorStateFromNodes(remaining) : null,\n ];\n}\n","import { useCallback, useRef } from 'react';\nimport type { SerializedEditorState } from 'lexical';\nimport type { DocumentAction } from '../context/document-context';\nimport { computeBodyHeight } from '../constants/page-layout';\nimport {\n getTopLevelNodes,\n splitEditorState,\n mergeEditorStates,\n createEditorStateFromNodes,\n} from '../utils/editor-state-utils';\nimport type { Lex4Document, PageState } from '../types/document';\nimport { createEmptyPage, createPageFromTemplate } from '../types/document';\n\n/**\n * usePagination — Orchestrates content flow between pages.\n *\n * When a page body overflows, this hook:\n * 1. Measures which nodes fit within the body height\n * 2. Splits the editor state at the overflow point\n * 3. Moves overflow content to the next page (creating it if needed)\n * 4. Cascades forward through all subsequent pages\n *\n * When a page body underflows (content deleted), it:\n * 1. Checks if the next page has content that fits\n * 2. Pulls content back from the next page\n * 3. Removes empty trailing pages\n */\nexport function usePagination(\n document: Lex4Document,\n dispatch: React.Dispatch<DocumentAction>,\n) {\n const reflowingRef = useRef(false);\n const pendingReflowRef = useRef(false);\n\n /**\n * Estimate how many top-level nodes fit within a given pixel height.\n *\n * Since we don't have DOM measurements at this point (the nodes may not\n * be rendered yet), we use a heuristic: assume each top-level paragraph\n * is approximately 24px (one line of text). This is imperfect but\n * provides a reasonable starting split point. The ResizeObserver in\n * PageBody will trigger another reflow if the estimate was wrong.\n */\n const estimateNodesFitting = useCallback(\n (\n state: SerializedEditorState | null,\n bodyHeight: number,\n ): number => {\n const nodes = getTopLevelNodes(state);\n if (nodes.length === 0) return 0;\n\n const estimatedLineHeight = 24;\n let usedHeight = 0;\n let fitCount = 0;\n\n for (const _node of nodes) {\n usedHeight += estimatedLineHeight;\n if (usedHeight > bodyHeight) break;\n fitCount++;\n }\n\n // At least one node must stay on the current page\n return Math.max(1, fitCount);\n },\n [],\n );\n\n /**\n * Handle overflow on a specific page.\n * Splits content and pushes overflow to the next page.\n */\n const handlePageOverflow = useCallback(\n (pageIndex: number) => {\n if (reflowingRef.current) {\n pendingReflowRef.current = true;\n return;\n }\n\n reflowingRef.current = true;\n\n try {\n const pages = document.pages;\n const page = pages[pageIndex];\n if (!page) return;\n\n const headerH = document.headerFooterEnabled ? page.headerHeight : 0;\n const footerH = document.headerFooterEnabled ? page.footerHeight : 0;\n const bodyHeight = computeBodyHeight(headerH, footerH);\n\n const nodes = getTopLevelNodes(page.bodyState);\n if (nodes.length <= 1) return; // Can't split a single node\n\n const fitCount = estimateNodesFitting(page.bodyState, bodyHeight);\n if (fitCount >= nodes.length) return; // Everything fits\n\n const [keepState, overflowState] = splitEditorState(page.bodyState, fitCount);\n\n if (!overflowState) return; // Nothing to overflow\n\n // Get or create the next page\n const nextPage = pages[pageIndex + 1];\n if (nextPage) {\n // Merge overflow into the beginning of the next page\n const mergedBody = mergeEditorStates(overflowState, nextPage.bodyState);\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: pages.map((p, i) => {\n if (i === pageIndex) return { ...p, bodyState: keepState };\n if (i === pageIndex + 1) return { ...p, bodyState: mergedBody };\n return p;\n }),\n },\n });\n } else {\n // Create a new page with overflow content\n const newPage: PageState = {\n ...createPageFromTemplate({\n headerState: document.defaultHeaderState,\n footerState: document.defaultFooterState,\n headerHeight: document.defaultHeaderHeight,\n footerHeight: document.defaultFooterHeight,\n }),\n bodyState: overflowState,\n };\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: [\n ...pages.map((p, i) =>\n i === pageIndex ? { ...p, bodyState: keepState } : p,\n ),\n newPage,\n ],\n },\n });\n }\n } finally {\n reflowingRef.current = false;\n\n if (pendingReflowRef.current) {\n pendingReflowRef.current = false;\n // Schedule another reflow on next tick\n setTimeout(() => handlePageOverflow(pageIndex), 0);\n }\n }\n },\n [document, dispatch, estimateNodesFitting],\n );\n\n /**\n * Handle underflow — try to pull content from the next page.\n */\n const handlePageUnderflow = useCallback(\n (pageIndex: number) => {\n if (reflowingRef.current) return;\n\n const pages = document.pages;\n const page = pages[pageIndex];\n const nextPage = pages[pageIndex + 1];\n\n if (!page || !nextPage) return;\n\n const nextNodes = getTopLevelNodes(nextPage.bodyState);\n if (nextNodes.length === 0) {\n // Next page is empty — remove it (unless it's the only page)\n if (pages.length > 1) {\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: pages.filter((_, i) => i !== pageIndex + 1),\n },\n });\n }\n return;\n }\n\n // Try to pull the first node from the next page\n const headerH = document.headerFooterEnabled ? page.headerHeight : 0;\n const footerH = document.headerFooterEnabled ? page.footerHeight : 0;\n const bodyHeight = computeBodyHeight(headerH, footerH);\n\n const currentNodes = getTopLevelNodes(page.bodyState);\n const estimatedCurrentHeight = currentNodes.length * 24;\n const remainingSpace = bodyHeight - estimatedCurrentHeight;\n\n if (remainingSpace > 24) {\n // Pull the first node from next page\n const [pulled, remaining] = [nextNodes.slice(0, 1), nextNodes.slice(1)];\n\n const updatedCurrent = mergeEditorStates(\n page.bodyState,\n createEditorStateFromNodes(pulled),\n );\n const updatedNext =\n remaining.length > 0 ? createEditorStateFromNodes(remaining) : null;\n\n const newPages = pages.map((p, i) => {\n if (i === pageIndex) return { ...p, bodyState: updatedCurrent };\n if (i === pageIndex + 1) return { ...p, bodyState: updatedNext };\n return p;\n });\n\n // Remove empty trailing pages\n while (newPages.length > 1) {\n const last = newPages[newPages.length - 1];\n if (getTopLevelNodes(last.bodyState).length === 0) {\n newPages.pop();\n } else {\n break;\n }\n }\n\n dispatch({\n type: 'SET_DOCUMENT',\n document: { ...document, pages: newPages },\n });\n }\n },\n [document, dispatch],\n );\n\n /**\n * Full document reflow — recalculate all pages from scratch.\n * Used after toggle changes or major content operations.\n */\n const reflowAll = useCallback(() => {\n if (reflowingRef.current) return;\n reflowingRef.current = true;\n\n try {\n const pages = document.pages;\n\n // Collect all body content across all pages\n const allNodes = pages.flatMap(p => getTopLevelNodes(p.bodyState));\n if (allNodes.length === 0) {\n // Ensure at least one page\n if (pages.length !== 1) {\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: [pages[0] ?? createEmptyPage()],\n },\n });\n }\n return;\n }\n\n // Distribute nodes across pages\n const newPages: PageState[] = [];\n let remainingNodes = [...allNodes];\n let pageIdx = 0;\n\n while (remainingNodes.length > 0) {\n const existingPage = pages[pageIdx];\n const headerH = document.headerFooterEnabled\n ? (existingPage?.headerHeight ?? 0)\n : 0;\n const footerH = document.headerFooterEnabled\n ? (existingPage?.footerHeight ?? 0)\n : 0;\n const bodyHeight = computeBodyHeight(headerH, footerH);\n const estimatedLineHeight = 24;\n const maxNodes = Math.max(1, Math.floor(bodyHeight / estimatedLineHeight));\n\n const pageNodes = remainingNodes.slice(0, maxNodes);\n remainingNodes = remainingNodes.slice(maxNodes);\n\n const basePage = existingPage ?? createPageFromTemplate({\n headerState: document.defaultHeaderState,\n footerState: document.defaultFooterState,\n headerHeight: document.defaultHeaderHeight,\n footerHeight: document.defaultFooterHeight,\n });\n newPages.push({\n ...basePage,\n bodyState: createEditorStateFromNodes(pageNodes),\n });\n\n pageIdx++;\n }\n\n dispatch({\n type: 'SET_DOCUMENT',\n document: { ...document, pages: newPages },\n });\n } finally {\n reflowingRef.current = false;\n }\n }, [document, dispatch]);\n\n return {\n handlePageOverflow,\n handlePageUnderflow,\n reflowAll,\n };\n}\n","import type { EditorThemeClasses } from 'lexical';\n\n/**\n * Lexical theme configuration — maps Lexical CSS class names\n * to Tailwind-compatible class strings for consistent styling.\n */\nexport const lexicalTheme: EditorThemeClasses = {\n root: 'lex4-root outline-none',\n paragraph: 'lex4-paragraph mb-1',\n heading: {\n h1: 'text-3xl font-bold mb-2',\n h2: 'text-2xl font-bold mb-2',\n h3: 'text-xl font-semibold mb-1',\n h4: 'text-lg font-semibold mb-1',\n h5: 'text-base font-medium mb-1',\n },\n text: {\n bold: 'font-bold',\n italic: 'italic',\n underline: 'underline',\n strikethrough: 'line-through',\n underlineStrikethrough: 'underline line-through',\n },\n list: {\n nested: {\n listitem: 'list-none',\n },\n ol: 'list-decimal ml-6',\n ul: 'list-disc ml-6',\n listitem: 'lex4-listitem',\n listitemChecked: 'lex4-listitem-checked',\n listitemUnchecked: 'lex4-listitem-unchecked',\n },\n quote: 'border-l-4 border-gray-300 pl-4 italic text-gray-600',\n};\n","import type { InitialConfigType } from '@lexical/react/LexicalComposer';\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text';\nimport { ListNode, ListItemNode } from '@lexical/list';\n\nimport { lexicalTheme } from './theme';\n\nexport type EditorMode = 'body' | 'header' | 'footer';\n\n/**\n * Creates a Lexical editor configuration for the given mode.\n *\n * Each mode gets its own namespace to avoid conflicts when\n * multiple Lexical editors coexist on the same page.\n */\nexport function createEditorConfig(\n mode: EditorMode,\n pageId?: string,\n): InitialConfigType {\n const namespace = pageId ? `lex4-${mode}-${pageId}` : `lex4-${mode}`;\n\n return {\n namespace,\n theme: lexicalTheme,\n nodes: [HeadingNode, QuoteNode, ListNode, ListItemNode],\n onError: (error: Error) => {\n console.error(`[Lex4 ${mode} editor error]`, error);\n },\n };\n}\n","import React, { useCallback } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { COMMAND_PRIORITY_LOW, KEY_TAB_COMMAND } from 'lexical';\nimport { indentContent, outdentContent } from '../commands/list-commands';\n\n/**\n * TabIndentPlugin — handles Tab and Shift+Tab for indentation shortcuts.\n *\n * List items use Lexical's native nesting behavior. Regular paragraphs use the\n * editor's first-line indent behavior.\n */\nexport const TabIndentPlugin: React.FC = () => {\n const [editor] = useLexicalComposerContext();\n\n const handleTab = useCallback(\n (event: KeyboardEvent) => {\n event.preventDefault();\n if (event.shiftKey) {\n outdentContent(editor);\n } else {\n indentContent(editor);\n }\n return true;\n },\n [editor],\n );\n\n React.useEffect(() => {\n return editor.registerCommand(KEY_TAB_COMMAND, handleTab, COMMAND_PRIORITY_LOW);\n }, [editor, handleTab]);\n\n return null;\n};\n","import React, { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { $getRoot, $isElementNode, $isParagraphNode, type ElementNode } from 'lexical';\n\nconst FIRST_LINE_INDENT_PX = 40;\n\nfunction visitElements(node: ElementNode, callback: (element: ElementNode) => void): void {\n callback(node);\n\n for (const child of node.getChildren()) {\n if ($isElementNode(child)) {\n visitElements(child, callback);\n }\n }\n}\n\n/**\n * Applies first-line paragraph indentation in the DOM while leaving\n * Lexical's serialized paragraph indent levels intact.\n */\nexport const ParagraphIndentPlugin: React.FC = () => {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const syncParagraphIndents = () => editor.getEditorState().read(() => {\n visitElements($getRoot(), node => {\n if (!$isParagraphNode(node)) {\n return;\n }\n\n const element = editor.getElementByKey(node.getKey());\n if (!(element instanceof HTMLElement)) {\n return;\n }\n\n const indent = node.getIndent();\n element.style.paddingInlineStart = '0px';\n element.style.textIndent = indent > 0 ? `${indent * FIRST_LINE_INDENT_PX}px` : '';\n });\n });\n\n syncParagraphIndents();\n\n return editor.registerUpdateListener(() => {\n syncParagraphIndents();\n });\n }, [editor]);\n\n return null;\n};\n","import React from 'react';\n\n/**\n * PastePlugin — placeholder for paste normalization.\n *\n * Overflow detection after paste is handled by the OverflowPlugin\n * which monitors content size changes via ResizeObserver.\n */\nexport const PastePlugin: React.FC = () => {\n return null;\n};\n","import { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $createRangeSelectionFromDom,\n $getRoot,\n $setSelection,\n COMMAND_PRIORITY_LOW,\n FOCUS_COMMAND,\n} from 'lexical';\nimport type { LexicalEditor } from 'lexical';\nimport { useDocument } from '../../context/document-context';\nimport type { CaretPosition } from '../../types/history';\nimport { debug } from '../../utils/debug';\n\ninterface ActiveEditorPluginProps {\n pageId: string;\n region: CaretPosition['region'];\n onFocus?: (editor: LexicalEditor) => void;\n}\n\nfunction resolveTextOffset(root: HTMLElement, targetOffset: number): { node: Node; offset: number } {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n let remaining = targetOffset;\n let currentNode = walker.nextNode();\n let lastTextNode: Node | null = null;\n\n while (currentNode) {\n const textLength = currentNode.textContent?.length ?? 0;\n if (remaining <= textLength) {\n return { node: currentNode, offset: remaining };\n }\n\n remaining -= textLength;\n lastTextNode = currentNode;\n currentNode = walker.nextNode();\n }\n\n if (lastTextNode) {\n return {\n node: lastTextNode,\n offset: lastTextNode.textContent?.length ?? 0,\n };\n }\n\n return {\n node: root,\n offset: root.childNodes.length,\n };\n}\n\n/**\n * ActiveEditorPlugin — Registers the editor in the document context on focus.\n *\n * This enables the toolbar to dispatch commands (bold, italic, etc.)\n * to whichever editor the user is currently editing.\n */\nexport const ActiveEditorPlugin: React.FC<ActiveEditorPluginProps> = ({\n pageId,\n region,\n onFocus,\n}) => {\n const [editor] = useLexicalComposerContext();\n const {\n consumePendingCaretPosition,\n consumePendingFocusAtEnd,\n focusAtEndVersion,\n setActiveEditor,\n setActivePageId,\n } = useDocument();\n\n useEffect(() => {\n const caretPosition: CaretPosition = { pageId, region };\n const selectionToRestore = consumePendingCaretPosition(caretPosition);\n if (selectionToRestore === undefined) {\n return;\n }\n\n requestAnimationFrame(() => {\n setActivePageId(pageId);\n setActiveEditor(editor, caretPosition);\n editor.focus();\n if (!selectionToRestore) {\n return;\n }\n\n requestAnimationFrame(() => {\n const rootElement = editor.getRootElement();\n const domSelection = window.getSelection();\n if (!rootElement || !domSelection) {\n return;\n }\n\n const anchorPoint = resolveTextOffset(rootElement, selectionToRestore.anchorTextOffset);\n const focusPoint = resolveTextOffset(rootElement, selectionToRestore.focusTextOffset);\n const range = document.createRange();\n range.setStart(anchorPoint.node, anchorPoint.offset);\n range.setEnd(focusPoint.node, focusPoint.offset);\n\n domSelection.removeAllRanges();\n domSelection.addRange(range);\n\n editor.update(() => {\n const nextSelection = $createRangeSelectionFromDom(window.getSelection(), editor);\n if (nextSelection) {\n $setSelection(nextSelection);\n }\n });\n });\n });\n }, [consumePendingCaretPosition, editor, pageId, region, setActiveEditor, setActivePageId]);\n\n useEffect(() => {\n const caretPosition: CaretPosition = { pageId, region };\n if (!consumePendingFocusAtEnd(caretPosition)) {\n return;\n }\n\n requestAnimationFrame(() => {\n setActivePageId(pageId);\n setActiveEditor(editor, caretPosition);\n editor.focus(() => {\n editor.update(() => {\n $getRoot().selectEnd();\n });\n });\n });\n }, [\n consumePendingFocusAtEnd,\n editor,\n focusAtEndVersion,\n pageId,\n region,\n setActiveEditor,\n setActivePageId,\n ]);\n\n useEffect(() => {\n return editor.registerCommand(\n FOCUS_COMMAND,\n () => {\n debug('focus', `editor focused (ns=${editor.getKey()})`);\n setActivePageId(pageId);\n setActiveEditor(editor, { pageId, region });\n onFocus?.(editor);\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [editor, onFocus, pageId, region, setActiveEditor, setActivePageId]);\n\n return null;\n};\n","import { useEffect, useRef } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getRoot,\n $isElementNode,\n type LexicalNode,\n type SerializedEditorState,\n type SerializedLexicalNode,\n} from 'lexical';\nimport { debug, debugWarn } from '../../utils/debug';\n\n/**\n * Recursively serializes a Lexical node and all its children.\n * ElementNode.exportJSON() returns children: [] by default —\n * the recursive walk must be done manually.\n */\nfunction serializeNodeTree(node: LexicalNode): SerializedLexicalNode {\n const json = node.exportJSON();\n if ($isElementNode(node)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (json as any).children = node.getChildren().map(serializeNodeTree);\n }\n return json;\n}\n\ninterface OverflowPluginProps {\n /** Called with the serialized overflow content that must go to the next page */\n onOverflow: (\n overflowContent: SerializedEditorState,\n cause: 'paste' | 'content',\n ) => void;\n}\n\n/** Debounce delay for typing-triggered overflow checks (ms) */\nconst OVERFLOW_DEBOUNCE_MS = 300;\n\n/**\n * OverflowPlugin — Detects content overflow inside a Lexical editor\n * and automatically extracts overflow nodes.\n *\n * Uses registerRootListener to reliably get the root element (handles\n * the case where the root is not yet available on first render).\n *\n * Measures child element positions via getBoundingClientRect() relative\n * to the container, which works regardless of CSS overflow settings.\n *\n * Debounces overflow checks during normal typing (300ms) to avoid\n * extracting only the empty trailing paragraph. Paste and external\n * state changes (e.g. setEditorState) trigger immediate checks.\n */\nexport const OverflowPlugin: React.FC<OverflowPluginProps> = ({\n onOverflow,\n}) => {\n const [editor] = useLexicalComposerContext();\n const processingRef = useRef(false);\n const onOverflowRef = useRef(onOverflow);\n onOverflowRef.current = onOverflow;\n\n useEffect(() => {\n let observer: ResizeObserver | null = null;\n let unregisterUpdateListener: (() => void) | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const checkOverflow = (\n rootElement: HTMLElement,\n container: HTMLElement,\n cause: 'paste' | 'content',\n ) => {\n if (processingRef.current) return;\n\n const availableHeight = container.clientHeight;\n if (availableHeight <= 0) return;\n\n // Use scrollHeight for reliable overflow detection — unaffected by\n // scroll position (getBoundingClientRect is affected when the browser\n // scrolls overflow:hidden containers to follow the cursor after paste).\n const contentHeight = rootElement.scrollHeight;\n\n // No overflow if all content fits (+2px tolerance for sub-pixel rounding)\n if (contentHeight <= availableHeight + 2) return;\n\n const children = Array.from(rootElement.children) as HTMLElement[];\n if (children.length === 0) return;\n\n if (children.length <= 1) {\n debug('overflow', `single block overflows (content=${contentHeight}px > available=${availableHeight}px) — cannot split`);\n return;\n }\n\n processingRef.current = true;\n\n debug('overflow', `OVERFLOW detected: content=${contentHeight}px available=${availableHeight}px children=${children.length}`);\n\n // Find the first child whose bottom exceeds the available height.\n // Uses offsetTop (relative to offsetParent, unaffected by scroll)\n // instead of getBoundingClientRect (which shifts with scroll).\n let splitIndex = children.length;\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n const childBottom = child.offsetTop + child.offsetHeight;\n\n if (childBottom > availableHeight && i > 0) {\n splitIndex = i;\n debug('overflow', `split at index ${i} (childBottom=${childBottom}px > ${availableHeight}px)`);\n break;\n }\n }\n\n if (splitIndex >= children.length) {\n debugWarn('overflow', 'no valid split point found — all children fit individually');\n processingRef.current = false;\n return;\n }\n\n editor.update(\n () => {\n const root = $getRoot();\n const allChildren = root.getChildren();\n\n if (splitIndex >= allChildren.length) {\n debugWarn('overflow', `splitIndex=${splitIndex} >= Lexical children=${allChildren.length} — mismatch`);\n processingRef.current = false;\n return;\n }\n\n const overflowNodes: SerializedLexicalNode[] = [];\n const toRemove = allChildren.slice(splitIndex);\n\n for (const node of toRemove) {\n overflowNodes.push(serializeNodeTree(node));\n }\n\n for (const node of toRemove) {\n node.remove();\n }\n\n debug('overflow', `extracted ${overflowNodes.length} overflow nodes, kept ${splitIndex} nodes on current page`);\n\n const overflowState: SerializedEditorState = {\n root: {\n children: overflowNodes,\n direction: null,\n format: '',\n indent: 0,\n type: 'root',\n version: 1,\n },\n } as SerializedEditorState;\n\n setTimeout(() => {\n onOverflowRef.current(overflowState, cause);\n processingRef.current = false;\n }, 0);\n },\n { tag: 'overflow-split' },\n );\n };\n\n const setupObservers = (rootElement: HTMLElement) => {\n // Clean up any previous observers\n if (observer) observer.disconnect();\n if (unregisterUpdateListener) unregisterUpdateListener();\n if (debounceTimer) clearTimeout(debounceTimer);\n\n const container = rootElement.closest('.lex4-page-body') as HTMLElement | null;\n if (!container) {\n debugWarn('overflow', 'no .lex4-page-body container found');\n return;\n }\n\n debug('overflow', `observers attached (ns=${editor.getKey()})`);\n\n const immediateCheck = () => {\n requestAnimationFrame(() => checkOverflow(rootElement, container, 'content'));\n };\n\n const pasteCheck = () => {\n requestAnimationFrame(() => checkOverflow(rootElement, container, 'paste'));\n };\n\n const debouncedCheck = () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(immediateCheck, OVERFLOW_DEBOUNCE_MS);\n };\n\n // ResizeObserver fires on actual layout changes — debounce to\n // avoid constant checks during typing\n observer = new ResizeObserver(debouncedCheck);\n observer.observe(rootElement);\n observer.observe(container);\n\n unregisterUpdateListener = editor.registerUpdateListener(({ tags }) => {\n if (tags.has('overflow-split')) return;\n\n // Paste and external state changes trigger immediate overflow check.\n // Normal typing is debounced to avoid extracting only the cursor paragraph.\n if (tags.has('paste')) {\n debug('overflow', `paste check (tags=${Array.from(tags).join(',')})`);\n pasteCheck();\n } else if (tags.has('collaboration') || tags.has('historic')) {\n debug('overflow', `immediate check (tags=${Array.from(tags).join(',')})`);\n immediateCheck();\n } else {\n debouncedCheck();\n }\n });\n\n // Initial check after setup (immediate — handles mount with initial content)\n immediateCheck();\n };\n\n // registerRootListener fires immediately with current root (if any)\n // and again whenever the root element changes — handles the case\n // where getRootElement() returns null on first render\n const unregisterRootListener = editor.registerRootListener(\n (rootElement: HTMLElement | null) => {\n if (rootElement) {\n debug('overflow', `rootListener: root available (ns=${editor.getKey()})`);\n setupObservers(rootElement);\n } else {\n debug('overflow', `rootListener: root detached (ns=${editor.getKey()})`);\n if (observer) observer.disconnect();\n if (unregisterUpdateListener) unregisterUpdateListener();\n if (debounceTimer) clearTimeout(debounceTimer);\n observer = null;\n unregisterUpdateListener = null;\n debounceTimer = null;\n }\n },\n );\n\n return () => {\n unregisterRootListener();\n if (observer) observer.disconnect();\n if (unregisterUpdateListener) unregisterUpdateListener();\n if (debounceTimer) clearTimeout(debounceTimer);\n };\n }, [editor]);\n\n return null;\n};\n","import { useEffect, useMemo } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n COMMAND_PRIORITY_LOW,\n CONTROLLED_TEXT_INSERTION_COMMAND,\n FORMAT_ELEMENT_COMMAND,\n FORMAT_TEXT_COMMAND,\n KEY_BACKSPACE_COMMAND,\n KEY_DELETE_COMMAND,\n KEY_DOWN_COMMAND,\n KEY_ENTER_COMMAND,\n PASTE_COMMAND,\n} from 'lexical';\n\nimport { useDocument } from '../../context/document-context';\nimport type { HistoryActionDescriptor, HistoryRegion } from '../../types/history';\n\ninterface HistoryCapturePluginProps {\n pageId: string;\n region: Exclude<HistoryRegion, 'document'>;\n}\n\nfunction createPageLabel(region: HistoryCapturePluginProps['region'], pageNumber: number | null): string {\n if (region === 'body') {\n return pageNumber ? `Page ${pageNumber}` : 'Body';\n }\n\n const regionLabel = region.charAt(0).toUpperCase() + region.slice(1);\n return pageNumber ? `${regionLabel} Page ${pageNumber}` : regionLabel;\n}\n\nexport const HistoryCapturePlugin: React.FC<HistoryCapturePluginProps> = ({ pageId, region }) => {\n const [editor] = useLexicalComposerContext();\n const { document, queueHistoryAction } = useDocument();\n\n const context = useMemo(() => {\n const pageNumber = document.pages.findIndex(page => page.id === pageId);\n return {\n pageNumber: pageNumber >= 0 ? pageNumber + 1 : null,\n source: region,\n };\n }, [document.pages, pageId, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n CONTROLLED_TEXT_INSERTION_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Typed text'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event: KeyboardEvent) => {\n if (event.metaKey || event.ctrlKey || event.altKey) {\n return false;\n }\n\n if (event.key.length !== 1) {\n return false;\n }\n\n queueHistoryAction(buildDescriptor('Typed text'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n PASTE_COMMAND,\n (event: ClipboardEvent) => {\n const text = event.clipboardData?.getData('text/plain') ?? '';\n if (text.trim().length === 0) {\n return false;\n }\n queueHistoryAction(buildDescriptor('Pasted content'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_ENTER_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Inserted line break'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Deleted backward'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_DELETE_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Deleted forward'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n FORMAT_TEXT_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Formatted text'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n FORMAT_ELEMENT_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Formatted paragraph'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n return null;\n};\n","import { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n COMMAND_PRIORITY_HIGH,\n KEY_BACKSPACE_COMMAND,\n KEY_DELETE_COMMAND,\n KEY_DOWN_COMMAND,\n} from 'lexical';\n\ninterface PageBoundaryPluginProps {\n onBackspaceAtStart: () => void;\n onDeleteAtEnd: () => void;\n onMoveToPreviousPage: () => void;\n onMoveToNextPage: () => void;\n}\n\ninterface CollapsedTextPosition {\n textOffset: number;\n totalTextLength: number;\n}\n\nfunction getCollapsedTextPosition(rootElement: HTMLElement | null): CollapsedTextPosition | null {\n const domSelection = window.getSelection();\n if (!rootElement || !domSelection || domSelection.rangeCount === 0 || !domSelection.isCollapsed) {\n return null;\n }\n\n const range = domSelection.getRangeAt(0);\n if (!rootElement.contains(range.startContainer)) {\n return null;\n }\n\n const offsetRange = document.createRange();\n offsetRange.setStart(rootElement, 0);\n offsetRange.setEnd(range.startContainer, range.startOffset);\n\n const contentRange = document.createRange();\n contentRange.selectNodeContents(rootElement);\n\n return {\n textOffset: offsetRange.toString().length,\n totalTextLength: contentRange.toString().length,\n };\n}\n\nexport const PageBoundaryPlugin: React.FC<PageBoundaryPluginProps> = ({\n onBackspaceAtStart,\n onDeleteAtEnd,\n onMoveToPreviousPage,\n onMoveToNextPage,\n}) => {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n () => {\n const position = getCollapsedTextPosition(editor.getRootElement());\n if (!position || position.textOffset !== 0) {\n return false;\n }\n\n onBackspaceAtStart();\n return true;\n },\n COMMAND_PRIORITY_HIGH,\n ), [editor, onBackspaceAtStart]);\n\n useEffect(() => editor.registerCommand(\n KEY_DELETE_COMMAND,\n () => {\n const position = getCollapsedTextPosition(editor.getRootElement());\n if (!position || position.textOffset !== position.totalTextLength) {\n return false;\n }\n\n onDeleteAtEnd();\n return true;\n },\n COMMAND_PRIORITY_HIGH,\n ), [editor, onDeleteAtEnd]);\n\n useEffect(() => editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event: KeyboardEvent) => {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {\n return false;\n }\n\n const position = getCollapsedTextPosition(editor.getRootElement());\n if (!position) {\n return false;\n }\n\n if ((event.key === 'ArrowLeft' || event.key === 'ArrowUp') && position.textOffset === 0) {\n event.preventDefault();\n onMoveToPreviousPage();\n return true;\n }\n\n if (\n (event.key === 'ArrowRight' || event.key === 'ArrowDown')\n && position.textOffset === position.totalTextLength\n ) {\n event.preventDefault();\n onMoveToNextPage();\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH,\n ), [editor, onMoveToNextPage, onMoveToPreviousPage]);\n\n return null;\n};\n","import React, { useCallback, useEffect, useMemo } from 'react';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { ListPlugin } from '@lexical/react/LexicalListPlugin';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport type { EditorState, SerializedEditorState } from 'lexical';\n\nimport { createEditorConfig } from '../lexical/editor-setup';\nimport { TabIndentPlugin } from '../lexical/plugins/tab-indent-plugin';\nimport { ParagraphIndentPlugin } from '../lexical/plugins/paragraph-indent-plugin';\nimport { PastePlugin } from '../lexical/plugins/paste-plugin';\nimport { ActiveEditorPlugin } from '../lexical/plugins/active-editor-plugin';\nimport { OverflowPlugin } from '../lexical/plugins/overflow-plugin';\nimport { HistoryCapturePlugin } from '../lexical/plugins/history-capture-plugin';\nimport { PageBoundaryPlugin } from '../lexical/plugins/page-boundary-plugin';\nimport { useDocument } from '../context/document-context';\nimport { debug, shortId } from '../utils/debug';\n\ninterface PageBodyProps {\n pageId: string;\n initialBodyState?: SerializedEditorState | null;\n onBodyChange?: (state: SerializedEditorState) => void;\n onOverflow?: (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => void;\n onFocus?: () => void;\n onBackspaceAtStart?: () => void;\n onDeleteAtEnd?: () => void;\n onMoveToPreviousPage?: () => void;\n onMoveToNextPage?: () => void;\n readOnly?: boolean;\n}\n\n/**\n * EditorRegistryPlugin — Registers the editor in the document-level\n * editor registry so other pages can directly push content into it.\n */\nconst EditorRegistryPlugin: React.FC<{ pageId: string }> = ({ pageId }) => {\n const [editor] = useLexicalComposerContext();\n const { editorRegistry } = useDocument();\n\n useEffect(() => {\n editorRegistry.register(pageId, editor);\n debug('registry', `registered editor for page ${shortId(pageId)}`);\n return () => {\n editorRegistry.unregister(pageId);\n debug('registry', `unregistered editor for page ${shortId(pageId)}`);\n };\n }, [editor, pageId, editorRegistry]);\n\n return null;\n};\n\n/**\n * PageBody — Lexical editor instance for one page's body content.\n *\n * Each page gets its own Lexical editor. The OverflowPlugin\n * handles splitting content when it exceeds the available height.\n *\n * When created with initialBodyState (e.g. from overflow), the\n * LexicalComposer is initialized with that content.\n */\nexport const PageBody: React.FC<PageBodyProps> = ({\n pageId,\n initialBodyState,\n onBodyChange,\n onOverflow,\n onFocus,\n onBackspaceAtStart,\n onDeleteAtEnd,\n onMoveToPreviousPage,\n onMoveToNextPage,\n readOnly = false,\n}) => {\n const config = useMemo(\n () => {\n const baseConfig = {\n ...createEditorConfig('body', pageId),\n editable: !readOnly,\n };\n\n // Set initial editor state for new pages with overflow content\n if (initialBodyState) {\n debug('page', `PageBody ${shortId(pageId)}: initializing with ${initialBodyState.root?.children?.length ?? 0} children`);\n return {\n ...baseConfig,\n editorState: JSON.stringify(initialBodyState),\n };\n }\n\n debug('page', `PageBody ${shortId(pageId)}: initializing empty`);\n return baseConfig;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally only use initialBodyState at mount time\n [pageId, readOnly],\n );\n\n const handleChange = useCallback(\n (editorState: EditorState) => {\n const serialized = editorState.toJSON();\n onBodyChange?.(serialized);\n },\n [onBodyChange],\n );\n\n const handleOverflow = useCallback(\n (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => {\n debug('page', `PageBody ${shortId(pageId)}: overflow callback fired with ${overflowContent.root?.children?.length ?? 0} children`);\n onOverflow?.(overflowContent, cause);\n },\n [onOverflow, pageId],\n );\n\n return (\n <div\n className=\"lex4-page-body flex-1 min-h-0 relative\"\n style={{ overflow: 'hidden' }}\n data-testid={`page-body-${pageId}`}\n onFocus={onFocus}\n >\n <LexicalComposer initialConfig={config}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n className=\"outline-none h-full p-0\"\n style={{ overflow: 'visible' }}\n />\n }\n placeholder={\n <div className=\"absolute top-0 left-0 text-gray-400 pointer-events-none select-none\">\n Start typing...\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <ListPlugin />\n <ParagraphIndentPlugin />\n <TabIndentPlugin />\n <PastePlugin />\n <EditorRegistryPlugin pageId={pageId} />\n <ActiveEditorPlugin pageId={pageId} region=\"body\" />\n {!readOnly && <HistoryCapturePlugin pageId={pageId} region=\"body\" />}\n {!readOnly && onBackspaceAtStart && onDeleteAtEnd && onMoveToPreviousPage && onMoveToNextPage && (\n <PageBoundaryPlugin\n onBackspaceAtStart={onBackspaceAtStart}\n onDeleteAtEnd={onDeleteAtEnd}\n onMoveToPreviousPage={onMoveToPreviousPage}\n onMoveToNextPage={onMoveToNextPage}\n />\n )}\n <OverflowPlugin onOverflow={handleOverflow} />\n <OnChangePlugin onChange={handleChange} ignoreSelectionChange />\n </LexicalComposer>\n </div>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { COMMAND_PRIORITY_CRITICAL, KEY_ENTER_COMMAND, PASTE_COMMAND } from 'lexical';\nimport { debug } from '../../utils/debug';\n\n/**\n * HeightLimitPlugin — Prevents editing that would push content beyond\n * a maximum height. Instead of clipping overflow, this plugin reverts\n * any change that makes the editor's scrollHeight exceed maxHeight.\n *\n * Works by:\n * 1. Blocking Enter key when already at max height\n * 2. Saving editor state before each update, reverting if scrollHeight exceeds limit\n * 3. Truncating paste content that would overflow\n */\nexport function HeightLimitPlugin({ maxHeight, channel }: { maxHeight: number; channel: 'header' | 'footer' }) {\n const [editor] = useLexicalComposerContext();\n const lastGoodStateRef = useRef<string | null>(null);\n const isRevertingRef = useRef(false);\n\n useEffect(() => {\n // Save initial state as \"last good\"\n lastGoodStateRef.current = JSON.stringify(editor.getEditorState().toJSON());\n\n // Intercept Enter key when at max height\n const removeEnterCommand = editor.registerCommand(\n KEY_ENTER_COMMAND,\n () => {\n const root = editor.getRootElement();\n if (root && root.scrollHeight >= maxHeight) {\n debug(channel, `blocked Enter — scrollHeight ${root.scrollHeight}px >= max ${maxHeight}px`);\n return true; // Prevent the Enter\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n\n // Intercept paste when at max height\n const removePasteCommand = editor.registerCommand(\n PASTE_COMMAND,\n () => {\n const root = editor.getRootElement();\n if (root && root.scrollHeight >= maxHeight) {\n debug(channel, `blocked paste — scrollHeight ${root.scrollHeight}px >= max ${maxHeight}px`);\n return true; // Prevent the paste\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n\n // After each update, check if content exceeds max height and revert if so\n const removeUpdateListener = editor.registerUpdateListener(({ editorState, prevEditorState }) => {\n if (isRevertingRef.current) return;\n\n const root = editor.getRootElement();\n if (!root) return;\n\n // Use requestAnimationFrame to read DOM after paint\n requestAnimationFrame(() => {\n if (root.scrollHeight > maxHeight) {\n debug(channel, `reverting — scrollHeight ${root.scrollHeight}px > max ${maxHeight}px`);\n const restoreState =\n JSON.stringify(prevEditorState.toJSON()) || lastGoodStateRef.current;\n if (!restoreState) {\n return;\n }\n isRevertingRef.current = true;\n\n editor.setEditorState(editor.parseEditorState(restoreState));\n\n isRevertingRef.current = false;\n } else {\n // Content fits — save as last good state\n lastGoodStateRef.current = JSON.stringify(editorState.toJSON());\n }\n });\n });\n\n return () => {\n removeEnterCommand();\n removePasteCommand();\n removeUpdateListener();\n };\n }, [editor, maxHeight, channel]);\n\n return null;\n}\n","import React, { useCallback, useMemo, useRef } from 'react';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport type { EditorState, SerializedEditorState } from 'lexical';\n\nimport { createEditorConfig } from '../lexical/editor-setup';\nimport { MAX_HEADER_HEIGHT_PX } from '../constants/dimensions';\nimport { ActiveEditorPlugin } from '../lexical/plugins/active-editor-plugin';\nimport { HeightLimitPlugin } from '../lexical/plugins/height-limit-plugin';\nimport { HistoryCapturePlugin } from '../lexical/plugins/history-capture-plugin';\nimport { debug, shortId } from '../utils/debug';\n\ninterface PageHeaderProps {\n pageId: string;\n initialHeaderState?: SerializedEditorState | null;\n pageCounterLabel?: string;\n onHeaderChange?: (state: SerializedEditorState, height: number) => void;\n}\n\n/**\n * PageHeader — Mini Lexical editor for a page's header region.\n *\n * Constrained to MAX_HEADER_HEIGHT_PX. Uses overflow: clip to prevent\n * the browser from scrolling the container to follow the cursor.\n * Remounts via key={syncVersion} when content is copied/cleared externally.\n */\nexport const PageHeader: React.FC<PageHeaderProps> = ({\n pageId,\n initialHeaderState,\n pageCounterLabel,\n onHeaderChange,\n}) => {\n const hasPageCounter = !!pageCounterLabel;\n const config = useMemo(\n () => {\n const baseConfig = createEditorConfig('header', pageId);\n if (initialHeaderState) {\n return { ...baseConfig, editorState: JSON.stringify(initialHeaderState) };\n }\n return baseConfig;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- syncVersion forces remount via key, only used at init\n [pageId],\n );\n\n const contentRef = useRef<HTMLDivElement>(null);\n\n const handleChange = useCallback(\n (editorState: EditorState) => {\n requestAnimationFrame(() => {\n const el = contentRef.current;\n if (el) {\n if (el.scrollHeight > MAX_HEADER_HEIGHT_PX) {\n debug(\n 'header',\n `page ${shortId(pageId)}: skipped external sync at ${el.scrollHeight}px > max ${MAX_HEADER_HEIGHT_PX}px`,\n );\n return;\n }\n const height = Math.min(el.scrollHeight, MAX_HEADER_HEIGHT_PX);\n debug('header', `page ${shortId(pageId)}: height=${height}px (scrollH=${el.scrollHeight})`);\n onHeaderChange?.(editorState.toJSON(), height);\n }\n });\n },\n [onHeaderChange, pageId],\n );\n\n return (\n <div\n className=\"lex4-page-header border-b border-dashed border-gray-200 relative flex-shrink-0\"\n style={{ maxHeight: MAX_HEADER_HEIGHT_PX, overflow: 'clip' }}\n data-testid={`page-header-${pageId}`}\n >\n <LexicalComposer initialConfig={config}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n ref={contentRef}\n className={`outline-none p-2 text-sm text-gray-600 min-h-[24px] ${hasPageCounter ? 'pr-24' : ''}`}\n />\n }\n placeholder={\n <div className={`absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2 text-sm ${hasPageCounter ? 'pr-24' : ''}`}>\n Header\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <ActiveEditorPlugin pageId={pageId} region=\"header\" />\n <HistoryCapturePlugin pageId={pageId} region=\"header\" />\n <HeightLimitPlugin maxHeight={MAX_HEADER_HEIGHT_PX} channel=\"header\" />\n <OnChangePlugin onChange={handleChange} ignoreSelectionChange />\n </LexicalComposer>\n {pageCounterLabel && (\n <div\n className=\"pointer-events-none absolute right-2 top-2 select-none text-xs text-gray-500\"\n data-testid={`page-counter-header-${pageId}`}\n >\n {pageCounterLabel}\n </div>\n )}\n </div>\n );\n};\n","import React, { useCallback, useMemo, useRef } from 'react';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport type { EditorState, SerializedEditorState } from 'lexical';\n\nimport { createEditorConfig } from '../lexical/editor-setup';\nimport { MAX_FOOTER_HEIGHT_PX } from '../constants/dimensions';\nimport { ActiveEditorPlugin } from '../lexical/plugins/active-editor-plugin';\nimport { HeightLimitPlugin } from '../lexical/plugins/height-limit-plugin';\nimport { HistoryCapturePlugin } from '../lexical/plugins/history-capture-plugin';\nimport { debug, shortId } from '../utils/debug';\n\ninterface PageFooterProps {\n pageId: string;\n initialFooterState?: SerializedEditorState | null;\n pageCounterLabel?: string;\n onFooterChange?: (state: SerializedEditorState, height: number) => void;\n}\n\n/**\n * PageFooter — Mini Lexical editor for a page's footer region.\n *\n * Constrained to MAX_FOOTER_HEIGHT_PX. Uses overflow: clip to prevent\n * the browser from scrolling the container to follow the cursor.\n * Remounts via key={syncVersion} when content is copied/cleared externally.\n */\nexport const PageFooter: React.FC<PageFooterProps> = ({\n pageId,\n initialFooterState,\n pageCounterLabel,\n onFooterChange,\n}) => {\n const hasPageCounter = !!pageCounterLabel;\n const config = useMemo(\n () => {\n const baseConfig = createEditorConfig('footer', pageId);\n if (initialFooterState) {\n return { ...baseConfig, editorState: JSON.stringify(initialFooterState) };\n }\n return baseConfig;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- syncVersion forces remount via key, only used at init\n [pageId],\n );\n\n const contentRef = useRef<HTMLDivElement>(null);\n\n const handleChange = useCallback(\n (editorState: EditorState) => {\n requestAnimationFrame(() => {\n const el = contentRef.current;\n if (el) {\n if (el.scrollHeight > MAX_FOOTER_HEIGHT_PX) {\n debug(\n 'footer',\n `page ${shortId(pageId)}: skipped external sync at ${el.scrollHeight}px > max ${MAX_FOOTER_HEIGHT_PX}px`,\n );\n return;\n }\n const height = Math.min(el.scrollHeight, MAX_FOOTER_HEIGHT_PX);\n debug('footer', `page ${shortId(pageId)}: height=${height}px (scrollH=${el.scrollHeight})`);\n onFooterChange?.(editorState.toJSON(), height);\n }\n });\n },\n [onFooterChange, pageId],\n );\n\n return (\n <div\n className=\"lex4-page-footer border-t border-dashed border-gray-200 relative flex-shrink-0\"\n style={{ maxHeight: MAX_FOOTER_HEIGHT_PX, overflow: 'clip' }}\n data-testid={`page-footer-${pageId}`}\n >\n <LexicalComposer initialConfig={config}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n ref={contentRef}\n className={`outline-none p-2 text-sm text-gray-600 min-h-[24px] ${hasPageCounter ? 'pr-24' : ''}`}\n />\n }\n placeholder={\n <div className={`absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2 text-sm ${hasPageCounter ? 'pr-24' : ''}`}>\n Footer\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <ActiveEditorPlugin pageId={pageId} region=\"footer\" />\n <HistoryCapturePlugin pageId={pageId} region=\"footer\" />\n <HeightLimitPlugin maxHeight={MAX_FOOTER_HEIGHT_PX} channel=\"footer\" />\n <OnChangePlugin onChange={handleChange} ignoreSelectionChange />\n </LexicalComposer>\n {pageCounterLabel && (\n <div\n className=\"pointer-events-none absolute right-2 top-2 select-none text-xs text-gray-500\"\n data-testid={`page-counter-footer-${pageId}`}\n >\n {pageCounterLabel}\n </div>\n )}\n </div>\n );\n};\n","import React, { useCallback } from 'react';\nimport { A4_WIDTH_PX, A4_HEIGHT_PX, PAGE_MARGIN_PX } from '../constants/dimensions';\nimport { useDocument } from '../context/document-context';\nimport { PageBody } from './PageBody';\nimport { PageHeader } from './PageHeader';\nimport { PageFooter } from './PageFooter';\nimport type { SerializedEditorState } from 'lexical';\n\ninterface PageViewProps {\n pageId: string;\n pageIndex: number;\n onOverflow?: (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => void;\n onBackspaceAtStart?: (pageIndex: number, pageId: string) => void;\n onDeleteAtEnd?: (pageIndex: number, pageId: string) => void;\n onMoveToPreviousPage?: (pageIndex: number) => void;\n onMoveToNextPage?: (pageIndex: number) => void;\n}\n\n/**\n * PageView — A single A4 page with header, body, and footer regions.\n *\n * Dimensions are always exactly A4 (794 × 1123 px).\n * Header and footer are only rendered when the global toggle is on.\n * Uses CSS flexbox: header/footer are flex-shrink-0, body is flex-1.\n */\nexport const PageView: React.FC<PageViewProps> = React.memo(({\n pageId,\n pageIndex,\n onOverflow,\n onBackspaceAtStart,\n onDeleteAtEnd,\n onMoveToPreviousPage,\n onMoveToNextPage,\n}) => {\n const { document, dispatch, setActivePageId } = useDocument();\n const page = document.pages.find(p => p.id === pageId);\n const showHeaderFooter = document.headerFooterEnabled;\n const pageCounterMode = document.pageCounterMode;\n const pageCounterLabel = `Page ${pageIndex + 1} of ${document.pages.length}`;\n\n if (!page) return null;\n\n const handleBodyChange = useCallback(\n (bodyState: SerializedEditorState) => {\n dispatch({ type: 'UPDATE_PAGE_BODY', pageId, bodyState });\n },\n [dispatch, pageId],\n );\n\n const handleHeaderChange = useCallback(\n (headerState: SerializedEditorState, height: number) => {\n dispatch({ type: 'UPDATE_PAGE_HEADER_CONTENT', pageId, headerState, height });\n },\n [dispatch, pageId],\n );\n\n const handleFooterChange = useCallback(\n (footerState: SerializedEditorState, height: number) => {\n dispatch({ type: 'UPDATE_PAGE_FOOTER_CONTENT', pageId, footerState, height });\n },\n [dispatch, pageId],\n );\n\n const handleFocus = useCallback(() => {\n setActivePageId(pageId);\n }, [setActivePageId, pageId]);\n\n const handleOverflow = useCallback(\n (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => {\n onOverflow?.(overflowContent, cause);\n },\n [onOverflow],\n );\n\n return (\n <div\n className=\"lex4-page bg-white shadow-sm flex flex-col\"\n style={{\n width: A4_WIDTH_PX,\n height: A4_HEIGHT_PX,\n padding: PAGE_MARGIN_PX,\n }}\n data-testid={`page-${pageIndex}`}\n data-page-id={pageId}\n >\n {showHeaderFooter && (\n <PageHeader\n key={`header-${page.headerSyncVersion}`}\n pageId={pageId}\n initialHeaderState={page.headerState}\n pageCounterLabel={pageCounterMode === 'header' || pageCounterMode === 'both' ? pageCounterLabel : undefined}\n onHeaderChange={handleHeaderChange}\n />\n )}\n\n <PageBody\n key={`body-${page.bodySyncVersion}`}\n pageId={pageId}\n initialBodyState={page.bodyState}\n onBodyChange={handleBodyChange}\n onOverflow={handleOverflow}\n onFocus={handleFocus}\n onBackspaceAtStart={() => onBackspaceAtStart?.(pageIndex, pageId)}\n onDeleteAtEnd={() => onDeleteAtEnd?.(pageIndex, pageId)}\n onMoveToPreviousPage={() => onMoveToPreviousPage?.(pageIndex)}\n onMoveToNextPage={() => onMoveToNextPage?.(pageIndex)}\n />\n\n {showHeaderFooter && (\n <PageFooter\n key={`footer-${page.footerSyncVersion}`}\n pageId={pageId}\n initialFooterState={page.footerState}\n pageCounterLabel={pageCounterMode === 'footer' || pageCounterMode === 'both' ? pageCounterLabel : undefined}\n onFooterChange={handleFooterChange}\n />\n )}\n </div>\n );\n});\n\nPageView.displayName = 'PageView';\n","import React, { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { $getRoot } from 'lexical';\nimport type { SerializedEditorState, LexicalEditor } from 'lexical';\n\nimport { useDocument } from '../context/document-context';\nimport { computeBodyHeight } from '../constants/page-layout';\nimport { usePagination } from '../hooks/use-pagination';\nimport { PageView } from './PageView';\nimport { createPageFromTemplate } from '../types/document';\nimport { debug, shortId } from '../utils/debug';\n\n/**\n * DocumentView — Scrollable container rendering all pages vertically.\n *\n * Provides the page-layout visual with pages centered on a gray background\n * with gaps between pages. Handles overflow content from pages by\n * creating new pages or prepending to existing next pages.\n */\nexport const DocumentView: React.FC = () => {\n const {\n document,\n dispatch,\n editorRegistry,\n requestFocusAtEnd,\n runHistoryAction,\n setActiveEditor,\n setActivePageId,\n } = useDocument();\n const { handlePageUnderflow, reflowAll } = usePagination(document, dispatch);\n const previousBodyHeightsRef = useRef<number[] | null>(null);\n const pasteOverflowSequenceRef = useRef(false);\n const pasteOverflowReleaseTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const defaultPageTemplate = useMemo(\n () => ({\n headerState: document.defaultHeaderState,\n footerState: document.defaultFooterState,\n headerHeight: document.defaultHeaderHeight,\n footerHeight: document.defaultFooterHeight,\n }),\n [\n document.defaultFooterHeight,\n document.defaultFooterState,\n document.defaultHeaderHeight,\n document.defaultHeaderState,\n ],\n );\n\n const bodyHeights = useMemo(\n () => document.pages.map(page => computeBodyHeight(\n document.headerFooterEnabled ? page.headerHeight : 0,\n document.headerFooterEnabled ? page.footerHeight : 0,\n )),\n [document.headerFooterEnabled, document.pages],\n );\n\n useEffect(() => {\n const previousBodyHeights = previousBodyHeightsRef.current;\n previousBodyHeightsRef.current = bodyHeights;\n\n if (!previousBodyHeights) {\n return;\n }\n\n const bodySpaceExpanded = bodyHeights.some((height, index) => {\n const previousHeight = previousBodyHeights[index];\n return previousHeight !== undefined && height > previousHeight;\n });\n\n if (bodySpaceExpanded) {\n debug('page', 'body space expanded — running full reflow');\n reflowAll();\n }\n }, [bodyHeights, reflowAll]);\n\n useEffect(\n () => () => {\n if (pasteOverflowReleaseTimerRef.current) {\n clearTimeout(pasteOverflowReleaseTimerRef.current);\n }\n },\n [],\n );\n\n const focusBodyEditor = useCallback(\n (pageId: string, boundary: 'start' | 'end') => {\n let attempts = 0;\n\n const focusWhenReady = () => {\n const editor = editorRegistry.get(pageId);\n if (!editor) {\n if (attempts < 4) {\n attempts += 1;\n requestAnimationFrame(focusWhenReady);\n }\n return;\n }\n\n const caretPosition = { pageId, region: 'body' as const };\n setActivePageId(pageId);\n setActiveEditor(editor as LexicalEditor, caretPosition);\n editor.focus(() => {\n editor.update(() => {\n if (boundary === 'start') {\n $getRoot().selectStart();\n } else {\n $getRoot().selectEnd();\n }\n });\n });\n };\n\n requestAnimationFrame(focusWhenReady);\n },\n [editorRegistry, setActiveEditor, setActivePageId],\n );\n\n const handlePageOverflow = useCallback(\n (\n pageIndex: number,\n overflowContent: SerializedEditorState,\n cause: 'paste' | 'content',\n ) => {\n const nextPageIndex = pageIndex + 1;\n const overflowChildCount = overflowContent.root?.children?.length ?? 0;\n debug('page', `handlePageOverflow: pageIndex=${pageIndex} overflowChildren=${overflowChildCount} totalPages=${document.pages.length}`);\n\n if (cause === 'paste') {\n pasteOverflowSequenceRef.current = true;\n }\n\n if (pasteOverflowSequenceRef.current) {\n if (pasteOverflowReleaseTimerRef.current) {\n clearTimeout(pasteOverflowReleaseTimerRef.current);\n }\n pasteOverflowReleaseTimerRef.current = setTimeout(() => {\n pasteOverflowSequenceRef.current = false;\n pasteOverflowReleaseTimerRef.current = null;\n }, 800);\n }\n\n if (nextPageIndex < document.pages.length) {\n // Prepend overflow content to the next page's editor directly\n const nextPage = document.pages[nextPageIndex];\n const nextEditor = editorRegistry.get(nextPage.id);\n\n if (nextEditor) {\n const currentState = nextEditor.getEditorState().toJSON();\n const existingChildren = currentState.root?.children ?? [];\n const overflowChildren = overflowContent.root?.children ?? [];\n\n debug('page', `prepending ${overflowChildren.length} nodes to existing page ${shortId(nextPage.id)} (had ${existingChildren.length} children)`);\n\n const mergedState: SerializedEditorState = {\n root: {\n ...currentState.root,\n children: [...overflowChildren, ...existingChildren],\n },\n } as SerializedEditorState;\n\n const newEditorState = nextEditor.parseEditorState(JSON.stringify(mergedState));\n nextEditor.setEditorState(newEditorState);\n if (pasteOverflowSequenceRef.current) {\n requestFocusAtEnd({ pageId: nextPage.id, region: 'body' });\n }\n } else {\n debug('page', `editor not found in registry for page ${shortId(nextPage.id)} — falling back to ADD_PAGE`);\n const newPage = createPageFromTemplate(defaultPageTemplate);\n newPage.bodyState = overflowContent;\n runHistoryAction(\n {\n label: 'Overflow created new page',\n source: 'overflow',\n region: 'document',\n },\n () => {\n dispatch({ type: 'ADD_PAGE', afterIndex: pageIndex, page: newPage });\n },\n );\n if (pasteOverflowSequenceRef.current) {\n requestFocusAtEnd({ pageId: newPage.id, region: 'body' });\n }\n }\n } else {\n // Create a new page with the overflow content as initial state\n const newPage = createPageFromTemplate(defaultPageTemplate);\n newPage.bodyState = overflowContent;\n debug('page', `creating new page ${shortId(newPage.id)} with ${overflowChildCount} overflow children`);\n runHistoryAction(\n {\n label: 'Overflow created new page',\n source: 'overflow',\n region: 'document',\n },\n () => {\n dispatch({ type: 'ADD_PAGE', page: newPage });\n },\n );\n if (pasteOverflowSequenceRef.current) {\n requestFocusAtEnd({ pageId: newPage.id, region: 'body' });\n }\n }\n },\n [defaultPageTemplate, document.pages, dispatch, editorRegistry, requestFocusAtEnd, runHistoryAction],\n );\n\n const handleBackspaceAtPageStart = useCallback(\n (pageIndex: number, pageId: string) => {\n if (pageIndex <= 0) {\n return;\n }\n\n const previousPage = document.pages[pageIndex - 1];\n if (!previousPage) {\n return;\n }\n\n runHistoryAction(\n {\n label: `Deleted backward - Page ${pageIndex + 1}`,\n source: 'body',\n pageId,\n region: 'body',\n },\n () => {\n handlePageUnderflow(pageIndex - 1);\n },\n );\n\n focusBodyEditor(previousPage.id, 'end');\n },\n [document.pages, focusBodyEditor, handlePageUnderflow, runHistoryAction],\n );\n\n const handleDeleteAtPageEnd = useCallback(\n (pageIndex: number, pageId: string) => {\n const currentPage = document.pages[pageIndex];\n const nextPage = document.pages[pageIndex + 1];\n if (!currentPage || !nextPage) {\n return;\n }\n\n runHistoryAction(\n {\n label: `Deleted forward - Page ${pageIndex + 1}`,\n source: 'body',\n pageId,\n region: 'body',\n },\n () => {\n handlePageUnderflow(pageIndex);\n },\n );\n\n focusBodyEditor(currentPage.id, 'end');\n },\n [document.pages, focusBodyEditor, handlePageUnderflow, runHistoryAction],\n );\n\n const handleMoveToPreviousPage = useCallback(\n (pageIndex: number) => {\n if (pageIndex <= 0) {\n return;\n }\n\n const previousPage = document.pages[pageIndex - 1];\n if (!previousPage) {\n return;\n }\n\n focusBodyEditor(previousPage.id, 'end');\n },\n [document.pages, focusBodyEditor],\n );\n\n const handleMoveToNextPage = useCallback(\n (pageIndex: number) => {\n const nextPage = document.pages[pageIndex + 1];\n if (!nextPage) {\n return;\n }\n\n focusBodyEditor(nextPage.id, 'start');\n },\n [document.pages, focusBodyEditor],\n );\n\n return (\n <div\n className=\"lex4-document-view flex flex-col items-center gap-8 py-8 min-h-full\"\n data-testid=\"document-view\"\n tabIndex={-1}\n >\n {document.pages.map((page, index) => (\n <PageView\n key={page.id}\n pageId={page.id}\n pageIndex={index}\n onOverflow={(content, cause) => handlePageOverflow(index, content, cause)}\n onBackspaceAtStart={handleBackspaceAtPageStart}\n onDeleteAtEnd={handleDeleteAtPageEnd}\n onMoveToPreviousPage={handleMoveToPreviousPage}\n onMoveToNextPage={handleMoveToNextPage}\n />\n ))}\n </div>\n );\n};\n","import React, { useCallback, useEffect, useRef } from 'react';\nimport type { Lex4EditorProps } from '../types/editor-props';\nimport { DocumentProvider } from '../context/document-provider';\nimport { useDocument } from '../context/document-context';\nimport { HistorySidebar } from './HistorySidebar';\nimport { Toolbar } from './Toolbar';\nimport { DocumentView } from './DocumentView';\nimport '../styles.css';\n\nfunction selectEntireDocument(\n rootElement: HTMLDivElement | null,\n selectionBuffer: HTMLTextAreaElement | null,\n) {\n if (!rootElement || !selectionBuffer) {\n return;\n }\n\n const bodyRoots = Array.from(\n rootElement.querySelectorAll<HTMLElement>('[data-testid^=\"page-body-\"] [data-lexical-editor=\"true\"]'),\n );\n\n if (bodyRoots.length === 0) {\n return;\n }\n\n selectionBuffer.value = bodyRoots\n .map(bodyRoot => bodyRoot.innerText.trim())\n .filter(Boolean)\n .join('\\n');\n selectionBuffer.focus();\n selectionBuffer.select();\n}\n\nconst GLOBAL_SELECTION_BACKGROUND = 'rgb(191, 219, 254)';\nconst GLOBAL_SELECTION_FOREGROUND = 'rgb(30, 64, 175)';\n\nfunction isFormFieldTarget(target: EventTarget | null): boolean {\n const element = target as HTMLElement | null;\n const tagName = element?.tagName;\n return tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT';\n}\n\nconst EditorChrome: React.FC<{\n captureHistoryShortcutsOnWindow: boolean;\n className?: string;\n}> = ({\n captureHistoryShortcutsOnWindow,\n className,\n}) => {\n const {\n document,\n dispatch,\n globalSelectionActive,\n setGlobalSelectionActive,\n undo,\n redo,\n } = useDocument();\n const rootRef = useRef<HTMLDivElement>(null);\n const selectionBufferRef = useRef<HTMLTextAreaElement>(null);\n\n const clearGlobalSelection = useCallback(() => {\n setGlobalSelectionActive(false);\n selectionBufferRef.current?.blur();\n }, [setGlobalSelectionActive]);\n\n const handleHistoryShortcut = useCallback((event: { key: string; metaKey: boolean; ctrlKey: boolean; shiftKey: boolean; preventDefault: () => void; stopPropagation?: () => void }) => {\n const key = event.key.toLowerCase();\n\n if (key === 'z') {\n event.preventDefault();\n event.stopPropagation?.();\n clearGlobalSelection();\n if (event.shiftKey) {\n redo();\n } else {\n undo();\n }\n return true;\n }\n\n if (key === 'y') {\n event.preventDefault();\n event.stopPropagation?.();\n clearGlobalSelection();\n redo();\n return true;\n }\n\n return false;\n }, [clearGlobalSelection, redo, undo]);\n\n const handleKeyDownCapture = useCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement | null;\n const isGlobalSelectionBufferTarget = target === selectionBufferRef.current;\n\n if (!isGlobalSelectionBufferTarget && isFormFieldTarget(target)) {\n return;\n }\n\n const key = event.key.toLowerCase();\n\n if (isGlobalSelectionBufferTarget && (key === 'backspace' || key === 'delete')) {\n event.preventDefault();\n event.stopPropagation();\n dispatch({ type: 'CLEAR_DOCUMENT_CONTENT' });\n clearGlobalSelection();\n return;\n }\n\n const hasModifier = event.metaKey || event.ctrlKey;\n if (!hasModifier) {\n return;\n }\n\n if (key === 'a') {\n event.preventDefault();\n event.stopPropagation();\n requestAnimationFrame(() => {\n const activeElement = window.document.activeElement;\n if (activeElement instanceof HTMLElement && activeElement.isContentEditable) {\n activeElement.blur();\n }\n selectEntireDocument(rootRef.current, selectionBufferRef.current);\n setGlobalSelectionActive(true);\n });\n return;\n }\n\n if (handleHistoryShortcut(event)) {\n return;\n }\n }, [\n dispatch,\n handleHistoryShortcut,\n setGlobalSelectionActive,\n ]);\n\n const handleMouseDownCapture = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n if (!globalSelectionActive) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n const clickedToolbar = target?.closest('[data-testid=\"toolbar\"]');\n\n if (event.target !== selectionBufferRef.current && !clickedToolbar) {\n clearGlobalSelection();\n }\n }, [clearGlobalSelection, globalSelectionActive]);\n\n useEffect(() => {\n const editableRoots =\n rootRef.current?.querySelectorAll<HTMLElement>(\n '[data-testid^=\"page-body-\"] [data-lexical-editor=\"true\"]',\n ) ?? [];\n\n editableRoots.forEach((editableRoot) => {\n editableRoot.style.backgroundColor = globalSelectionActive ? GLOBAL_SELECTION_BACKGROUND : '';\n editableRoot.style.color = globalSelectionActive ? GLOBAL_SELECTION_FOREGROUND : '';\n editableRoot.style.caretColor = globalSelectionActive ? 'transparent' : '';\n });\n }, [globalSelectionActive, document.pages.length]);\n\n useEffect(() => {\n if (!captureHistoryShortcutsOnWindow) {\n return;\n }\n\n const handleWindowKeyDown = (event: KeyboardEvent) => {\n const hasModifier = event.metaKey || event.ctrlKey;\n if (!hasModifier) {\n return;\n }\n\n handleHistoryShortcut(event);\n };\n\n window.addEventListener('keydown', handleWindowKeyDown, { capture: true });\n const handleWindowBeforeInput = (event: InputEvent) => {\n if (event.inputType === 'historyUndo') {\n event.preventDefault();\n clearGlobalSelection();\n undo();\n } else if (event.inputType === 'historyRedo') {\n event.preventDefault();\n clearGlobalSelection();\n redo();\n }\n };\n\n window.addEventListener('beforeinput', handleWindowBeforeInput, { capture: true });\n return () => {\n window.removeEventListener('keydown', handleWindowKeyDown, { capture: true });\n window.removeEventListener('beforeinput', handleWindowBeforeInput, { capture: true });\n };\n }, [captureHistoryShortcutsOnWindow, clearGlobalSelection, handleHistoryShortcut, redo, undo]);\n\n return (\n <div\n ref={rootRef}\n className={`lex4-editor flex flex-col h-full ${className ?? ''}`}\n data-testid=\"lex4-editor\"\n data-global-selection-active={globalSelectionActive ? 'true' : 'false'}\n onKeyDownCapture={handleKeyDownCapture}\n onMouseDownCapture={handleMouseDownCapture}\n >\n <textarea\n ref={selectionBufferRef}\n aria-hidden=\"true\"\n data-testid=\"global-selection-buffer\"\n readOnly\n tabIndex={-1}\n className=\"pointer-events-none fixed -left-[9999px] top-0 h-0 w-0 opacity-0\"\n />\n <Toolbar />\n <div className=\"flex min-h-0 flex-1 overflow-hidden bg-gray-200\">\n <div className=\"min-w-0 flex-1 overflow-auto\">\n <DocumentView />\n </div>\n <HistorySidebar />\n </div>\n </div>\n );\n};\n\n/**\n * Lex4Editor — The main public component.\n *\n * A paginated A4 document editor built on Meta Lexical.\n * Each page is a true discrete A4 page with its own Lexical editor instance.\n */\nexport const Lex4Editor: React.FC<Lex4EditorProps> = ({\n captureHistoryShortcutsOnWindow = true,\n initialDocument,\n onDocumentChange,\n className,\n}) => {\n return (\n <DocumentProvider\n initialDocument={initialDocument}\n onDocumentChange={onDocumentChange}\n >\n <EditorChrome\n captureHistoryShortcutsOnWindow={captureHistoryShortcutsOnWindow}\n className={className}\n />\n </DocumentProvider>\n );\n};\n","import { useCallback, useRef, useEffect } from 'react';\n\n/**\n * useOverflowDetection — Debounced overflow detection for a page body.\n *\n * Watches a contentEditable element and fires `onOverflow` when the\n * content height exceeds the allowed body height. Uses a debounce\n * to avoid firing on every keystroke.\n */\nexport function useOverflowDetection(\n bodyHeight: number,\n onOverflow: (() => void) | undefined,\n debounceMs: number = 100,\n) {\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const observerRef = useRef<ResizeObserver | null>(null);\n\n const check = useCallback(\n (el: HTMLElement) => {\n if (!onOverflow) return;\n if (el.scrollHeight > bodyHeight + 2) {\n // +2 for sub-pixel rounding\n onOverflow();\n }\n },\n [bodyHeight, onOverflow],\n );\n\n const attachRef = useCallback(\n (el: HTMLElement | null) => {\n // Cleanup previous observer\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n\n if (!el || !onOverflow) return;\n\n observerRef.current = new ResizeObserver(() => {\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => check(el), debounceMs);\n });\n observerRef.current.observe(el);\n },\n [check, debounceMs, onOverflow],\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n if (observerRef.current) observerRef.current.disconnect();\n };\n }, []);\n\n return { attachRef };\n}\n","import { useCallback, useRef, useEffect } from 'react';\n\n/**\n * useHeaderFooter — Tracks header/footer height via ResizeObserver\n * and reports changes to the document context.\n *\n * Clamps the reported height to the maximum allowed.\n */\nexport function useHeaderFooter(\n maxHeight: number,\n onHeightChange: (height: number) => void,\n) {\n const observerRef = useRef<ResizeObserver | null>(null);\n const lastHeightRef = useRef<number>(0);\n\n const attachRef = useCallback(\n (el: HTMLElement | null) => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n\n if (!el) return;\n\n const measure = () => {\n const height = Math.min(el.scrollHeight, maxHeight);\n if (height !== lastHeightRef.current) {\n lastHeightRef.current = height;\n onHeightChange(height);\n }\n };\n\n observerRef.current = new ResizeObserver(measure);\n observerRef.current.observe(el);\n\n // Initial measurement\n measure();\n },\n [maxHeight, onHeightChange],\n );\n\n useEffect(() => {\n return () => {\n if (observerRef.current) observerRef.current.disconnect();\n };\n }, []);\n\n return { attachRef };\n}\n"],"names":["document","__iconNode","jumpToHistoryEntry","AlignLeft","AlignCenter","AlignRight","AlignJustify","IndentIncrease","IndentDecrease"],"mappings":"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","x_google_ignoreList":[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]}
1
+ {"version":3,"file":"lex4-editor.js","sources":["../src/types/document.ts","../src/context/document-context.ts","../src/constants/dimensions.ts","../src/utils/debug.ts","../src/context/document-reducer.ts","../src/utils/history-manager.ts","../src/context/document-provider.tsx","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/defaultAttributes.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/context.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/Icon.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/createLucideIcon.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/bold.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/braces.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/copy-plus.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/eraser.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/hash.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/italic.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list-indent-decrease.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list-indent-increase.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list-ordered.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/list.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/panel-right.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/redo-2.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/refresh-cw.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/search.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/strikethrough.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-center.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-end.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-justify.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/text-align-start.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/trash-2.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/underline.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/undo-2.js","../../../node_modules/.pnpm/lucide-react@1.8.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/x.js","../src/i18n/defaults.ts","../src/i18n/context.tsx","../src/components/EditorSidebar.tsx","../src/components/HistorySidebar.tsx","../src/components/HeaderFooterToggle.tsx","../src/components/HeaderFooterActions.tsx","../src/extensions/types.ts","../src/extensions/extension-context.tsx","../src/lexical/plugins/font-plugin.tsx","../src/lexical/plugins/font-size-plugin.tsx","../src/lexical/commands/format-commands.ts","../src/lexical/commands/list-commands.ts","../src/components/Toolbar.tsx","../src/constants/page-layout.ts","../src/utils/editor-state-utils.ts","../src/hooks/use-pagination.ts","../src/lexical/theme.ts","../src/lexical/editor-setup.ts","../src/lexical/plugins/tab-indent-plugin.tsx","../src/lexical/plugins/paragraph-indent-plugin.tsx","../src/lexical/plugins/paste-plugin.tsx","../src/lexical/plugins/active-editor-plugin.tsx","../src/lexical/plugins/overflow-plugin.tsx","../src/lexical/plugins/history-capture-plugin.tsx","../src/lexical/plugins/page-boundary-plugin.tsx","../src/components/PageBody.tsx","../src/lexical/plugins/height-limit-plugin.tsx","../src/components/PageHeader.tsx","../src/components/PageFooter.tsx","../src/components/PageView.tsx","../src/components/DocumentView.tsx","../src/components/Lex4Editor.tsx","../src/hooks/use-overflow-detection.ts","../src/hooks/use-header-footer.ts","../src/ast/types.ts","../src/ast/inline-mapper.ts","../src/ast/block-mapper.ts","../src/ast/content-mapper.ts","../src/ast/document-serializer.ts","../src/ast/payload-builder.ts","../src/extensions/ast-extension.ts","../src/variables/variable-node.tsx","../src/variables/variable-commands.ts","../src/variables/variable-plugin.tsx","../src/variables/variable-context.tsx","../src/components/VariablePicker.tsx","../src/components/VariablePanel.tsx","../src/extensions/variables-extension.tsx"],"sourcesContent":["import type { SerializedEditorState } from 'lexical';\n\nexport type PageCounterMode = 'none' | 'header' | 'footer' | 'both';\n\nexport interface PageChromeTemplate {\n headerState: SerializedEditorState | null;\n footerState: SerializedEditorState | null;\n headerHeight: number;\n footerHeight: number;\n}\n\n/** State for a single page in the document */\nexport interface PageState {\n id: string;\n bodyState: SerializedEditorState | null;\n headerState: SerializedEditorState | null;\n footerState: SerializedEditorState | null;\n headerHeight: number;\n footerHeight: number;\n /** Incremented on external body state changes (reflow/undo) to force editor remount */\n bodySyncVersion: number;\n /** Incremented on external header state changes (copy/clear) to force editor remount */\n headerSyncVersion: number;\n /** Incremented on external footer state changes (copy/clear) to force editor remount */\n footerSyncVersion: number;\n}\n\n/** Top-level document state */\nexport interface Lex4Document {\n pages: PageState[];\n headerFooterEnabled: boolean;\n pageCounterMode: PageCounterMode;\n defaultHeaderState: SerializedEditorState | null;\n defaultFooterState: SerializedEditorState | null;\n defaultHeaderHeight: number;\n defaultFooterHeight: number;\n}\n\n/** Creates a default empty page */\nexport function createEmptyPage(id?: string): PageState {\n return {\n id: id ?? crypto.randomUUID(),\n bodyState: null,\n headerState: null,\n footerState: null,\n headerHeight: 0,\n footerHeight: 0,\n bodySyncVersion: 0,\n headerSyncVersion: 0,\n footerSyncVersion: 0,\n };\n}\n\n/** Creates a new page that inherits header/footer chrome from a document default template. */\nexport function createPageFromTemplate(template?: PageChromeTemplate): PageState {\n return {\n ...createEmptyPage(),\n headerState: template?.headerState ?? null,\n footerState: template?.footerState ?? null,\n headerHeight: template?.headerHeight ?? 0,\n footerHeight: template?.footerHeight ?? 0,\n };\n}\n\n/** Creates a default empty document */\nexport function createEmptyDocument(): Lex4Document {\n return {\n pages: [createEmptyPage()],\n headerFooterEnabled: false,\n pageCounterMode: 'none',\n defaultHeaderState: null,\n defaultFooterState: null,\n defaultHeaderHeight: 0,\n defaultFooterHeight: 0,\n };\n}\n","import { createContext, useContext } from 'react';\nimport type { Lex4Document, PageCounterMode } from '../types/document';\nimport type { LexicalEditor } from 'lexical';\nimport type {\n CaretPosition,\n CaretSelection,\n HistoryActionDescriptor,\n HistoryEntry,\n} from '../types/history';\n\n/** All actions the document reducer can handle */\nexport type DocumentAction =\n | { type: 'ADD_PAGE'; afterIndex?: number; page?: import('../types/document').PageState }\n | { type: 'REMOVE_PAGE'; pageId: string }\n | { type: 'UPDATE_PAGE_BODY'; pageId: string; bodyState: import('lexical').SerializedEditorState | null }\n | {\n type: 'UPDATE_PAGE_HEADER_CONTENT';\n pageId: string;\n headerState: import('lexical').SerializedEditorState | null;\n height: number;\n }\n | {\n type: 'UPDATE_PAGE_FOOTER_CONTENT';\n pageId: string;\n footerState: import('lexical').SerializedEditorState | null;\n height: number;\n }\n | { type: 'UPDATE_PAGE_HEADER'; pageId: string; headerState: import('lexical').SerializedEditorState | null }\n | { type: 'UPDATE_PAGE_FOOTER'; pageId: string; footerState: import('lexical').SerializedEditorState | null }\n | { type: 'SET_HEADER_FOOTER_ENABLED'; enabled: boolean }\n | { type: 'SET_PAGE_COUNTER_MODE'; mode: PageCounterMode }\n | { type: 'COPY_HEADER_TO_ALL'; sourcePageId: string }\n | { type: 'COPY_FOOTER_TO_ALL'; sourcePageId: string }\n | { type: 'CLEAR_HEADER'; pageId: string }\n | { type: 'CLEAR_FOOTER'; pageId: string }\n | { type: 'CLEAR_ALL_HEADERS' }\n | { type: 'CLEAR_ALL_FOOTERS' }\n | { type: 'CLEAR_DOCUMENT_CONTENT' }\n | { type: 'SET_HEADER_HEIGHT'; pageId: string; height: number }\n | { type: 'SET_FOOTER_HEIGHT'; pageId: string; height: number }\n | { type: 'SET_DOCUMENT'; document: Lex4Document };\n\n/** Registry of page editors for direct cross-page content manipulation */\nexport interface EditorRegistry {\n register(pageId: string, editor: LexicalEditor): void;\n unregister(pageId: string): void;\n get(pageId: string): LexicalEditor | undefined;\n all(): LexicalEditor[];\n}\n\n/** Shape of the document context value */\nexport interface DocumentContextValue {\n document: Lex4Document;\n dispatch: React.Dispatch<DocumentAction>;\n activePageId: string | null;\n setActivePageId: (id: string | null) => void;\n activeEditor: LexicalEditor | null;\n setActiveEditor: (editor: LexicalEditor | null, caretPosition?: CaretPosition | null) => void;\n consumePendingCaretPosition: (caretPosition: CaretPosition) => CaretSelection | null | undefined;\n consumePendingFocusAtEnd: (caretPosition: CaretPosition) => boolean;\n requestFocusAtEnd: (caretPosition: CaretPosition) => void;\n focusAtEndVersion: number;\n globalSelectionActive: boolean;\n setGlobalSelectionActive: (active: boolean) => void;\n historyEntries: HistoryEntry[];\n historyCursor: number;\n canUndo: boolean;\n canRedo: boolean;\n queueHistoryAction: (action: HistoryActionDescriptor | null) => void;\n runHistoryAction: (action: HistoryActionDescriptor, callback: () => void) => void;\n jumpToHistoryEntry: (entryIndex: number) => void;\n clearHistory: (reason?: string) => void;\n historySidebarOpen: boolean;\n setHistorySidebarOpen: (open: boolean) => void;\n undo: () => void;\n redo: () => void;\n editorRegistry: EditorRegistry;\n}\n\nexport const DocumentContext = createContext<DocumentContextValue | null>(null);\n\n/** Hook to access the document context. Throws if used outside provider. */\nexport function useDocument(): DocumentContextValue {\n const ctx = useContext(DocumentContext);\n if (!ctx) {\n throw new Error('useDocument must be used within a DocumentProvider');\n }\n return ctx;\n}\n","/**\n * A4 page dimensions and layout constants.\n *\n * All values derived from the A4 standard (210mm × 297mm)\n * converted to CSS pixels at 96 DPI.\n */\n\nexport const A4_WIDTH_MM = 210;\nexport const A4_HEIGHT_MM = 297;\n\n/** CSS pixels per millimeter at 96 DPI */\nexport const PX_PER_MM = 96 / 25.4;\n\n/** A4 width in CSS pixels (≈794px) */\nexport const A4_WIDTH_PX = Math.round(A4_WIDTH_MM * PX_PER_MM);\n\n/** A4 height in CSS pixels (≈1123px) */\nexport const A4_HEIGHT_PX = Math.round(A4_HEIGHT_MM * PX_PER_MM);\n\n/** Default page margin in CSS pixels (≈10.6mm each side) */\nexport const PAGE_MARGIN_PX = 40;\n\n/** Maximum header height as a ratio of page height */\nexport const MAX_HEADER_RATIO = 0.2;\n\n/** Maximum footer height as a ratio of page height */\nexport const MAX_FOOTER_RATIO = 0.2;\n\n/** Maximum header height in CSS pixels */\nexport const MAX_HEADER_HEIGHT_PX = Math.round(A4_HEIGHT_PX * MAX_HEADER_RATIO);\n\n/** Maximum footer height in CSS pixels */\nexport const MAX_FOOTER_HEIGHT_PX = Math.round(A4_HEIGHT_PX * MAX_FOOTER_RATIO);\n","/**\n * Lex4 Debug Logger\n *\n * Zero-cost when disabled. Enable in the browser console:\n *\n * localStorage.setItem('lex4:debug', '*') // all channels\n * localStorage.setItem('lex4:debug', 'overflow,reducer') // specific channels\n * window.__LEX4_DEBUG__ = true // all channels (session only)\n *\n * Disable:\n * localStorage.removeItem('lex4:debug')\n * window.__LEX4_DEBUG__ = false\n *\n * Channels:\n * reducer — every dispatched action and resulting state\n * overflow — overflow detection, measurement, split decisions\n * registry — editor registry register/unregister/get\n * page — page creation, initial state loading, body changes\n * toolbar — formatting command dispatches\n * header — header height changes, content changes\n * footer — footer height changes, content changes\n * focus — editor focus changes, active editor/page tracking\n */\n\nexport type DebugChannel =\n | 'reducer'\n | 'overflow'\n | 'registry'\n | 'page'\n | 'toolbar'\n | 'header'\n | 'footer'\n | 'focus';\n\nconst CHANNEL_COLORS: Record<DebugChannel, string> = {\n reducer: '#e91e63',\n overflow: '#ff5722',\n registry: '#9c27b0',\n page: '#2196f3',\n toolbar: '#4caf50',\n header: '#ff9800',\n footer: '#795548',\n focus: '#607d8b',\n};\n\ndeclare global {\n interface Window {\n __LEX4_DEBUG__?: boolean | string;\n }\n}\n\nfunction getFlag(): string | boolean | null {\n if (typeof window === 'undefined') return null;\n\n const win = (window as Window).__LEX4_DEBUG__;\n if (win !== undefined && win !== null) return win;\n\n if (typeof localStorage !== 'undefined') {\n return localStorage.getItem('lex4:debug');\n }\n\n return null;\n}\n\nfunction isEnabled(channel: DebugChannel): boolean {\n const flag = getFlag();\n if (!flag) return false;\n if (flag === true || flag === '*' || flag === 'true') return true;\n\n if (typeof flag === 'string') {\n return flag.split(',').some(s => s.trim() === channel);\n }\n\n return false;\n}\n\n/**\n * Log a debug message on the given channel.\n * No-ops instantly when the channel is disabled.\n */\nexport function debug(channel: DebugChannel, message: string, ...data: unknown[]): void {\n if (!isEnabled(channel)) return;\n\n const color = CHANNEL_COLORS[channel];\n const prefix = `%c[lex4:${channel}]`;\n const style = `color: ${color}; font-weight: bold;`;\n\n if (data.length > 0) {\n console.log(prefix, style, message, ...data);\n } else {\n console.log(prefix, style, message);\n }\n}\n\n/**\n * Log a warning on the given channel.\n */\nexport function debugWarn(channel: DebugChannel, message: string, ...data: unknown[]): void {\n if (!isEnabled(channel)) return;\n\n const color = CHANNEL_COLORS[channel];\n const prefix = `%c[lex4:${channel}]`;\n const style = `color: ${color}; font-weight: bold;`;\n\n if (data.length > 0) {\n console.warn(prefix, style, message, ...data);\n } else {\n console.warn(prefix, style, message);\n }\n}\n\n/** Short-id helper: first 8 chars of a UUID for readable logs */\nexport function shortId(id: string): string {\n return id.substring(0, 8);\n}\n","import type { Lex4Document } from '../types/document';\nimport { createEmptyPage } from '../types/document';\nimport type { DocumentAction } from './document-context';\nimport { MAX_HEADER_HEIGHT_PX, MAX_FOOTER_HEIGHT_PX } from '../constants/dimensions';\nimport { debug, shortId } from '../utils/debug';\n\nfunction serializedStateChanged(\n current: import('lexical').SerializedEditorState | null,\n next: import('lexical').SerializedEditorState | null,\n): boolean {\n return JSON.stringify(current) !== JSON.stringify(next);\n}\n\nfunction withExternalSyncVersions(\n currentDocument: Lex4Document,\n nextDocument: Lex4Document,\n): Lex4Document {\n const currentPages = new Map(currentDocument.pages.map(page => [page.id, page]));\n\n return {\n ...nextDocument,\n pages: nextDocument.pages.map(nextPage => {\n const currentPage = currentPages.get(nextPage.id);\n if (!currentPage) {\n return nextPage;\n }\n\n const bodyChanged = serializedStateChanged(currentPage.bodyState, nextPage.bodyState);\n const headerChanged =\n currentPage.headerHeight !== nextPage.headerHeight ||\n serializedStateChanged(currentPage.headerState, nextPage.headerState);\n const footerChanged =\n currentPage.footerHeight !== nextPage.footerHeight ||\n serializedStateChanged(currentPage.footerState, nextPage.footerState);\n\n return {\n ...nextPage,\n bodySyncVersion: bodyChanged ? currentPage.bodySyncVersion + 1 : currentPage.bodySyncVersion,\n headerSyncVersion: headerChanged ? currentPage.headerSyncVersion + 1 : currentPage.headerSyncVersion,\n footerSyncVersion: footerChanged ? currentPage.footerSyncVersion + 1 : currentPage.footerSyncVersion,\n };\n }),\n };\n}\n\n/**\n * Pure reducer for document state.\n * Handles all page-level and document-level mutations.\n */\nexport function documentReducer(state: Lex4Document, action: DocumentAction): Lex4Document {\n switch (action.type) {\n case 'ADD_PAGE': {\n const newPage = action.page ?? createEmptyPage();\n const pages = [...state.pages];\n const insertAt = action.afterIndex !== undefined ? action.afterIndex + 1 : pages.length;\n pages.splice(insertAt, 0, newPage);\n const hasBody = !!(action.page?.bodyState?.root?.children?.length);\n debug('reducer', `ADD_PAGE id=${shortId(newPage.id)} at=${insertAt} withBody=${hasBody} totalPages=${pages.length}`);\n return { ...state, pages };\n }\n\n case 'REMOVE_PAGE': {\n if (state.pages.length <= 1) {\n debug('reducer', `REMOVE_PAGE id=${shortId(action.pageId)} — skipped (last page)`);\n return state;\n }\n debug('reducer', `REMOVE_PAGE id=${shortId(action.pageId)} remaining=${state.pages.length - 1}`);\n return {\n ...state,\n pages: state.pages.filter(p => p.id !== action.pageId),\n };\n }\n\n case 'UPDATE_PAGE_BODY': {\n const childCount = action.bodyState?.root?.children?.length ?? 0;\n debug('reducer', `UPDATE_PAGE_BODY id=${shortId(action.pageId)} children=${childCount}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, bodyState: action.bodyState } : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_HEADER': {\n debug('reducer', `UPDATE_PAGE_HEADER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, headerState: action.headerState } : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_HEADER_CONTENT': {\n const clamped = Math.min(action.height, MAX_HEADER_HEIGHT_PX);\n debug('reducer', `UPDATE_PAGE_HEADER_CONTENT id=${shortId(action.pageId)} height=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, headerState: action.headerState, headerHeight: clamped }\n : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_FOOTER': {\n debug('reducer', `UPDATE_PAGE_FOOTER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, footerState: action.footerState } : p,\n ),\n };\n }\n\n case 'UPDATE_PAGE_FOOTER_CONTENT': {\n const clamped = Math.min(action.height, MAX_FOOTER_HEIGHT_PX);\n debug('reducer', `UPDATE_PAGE_FOOTER_CONTENT id=${shortId(action.pageId)} height=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, footerState: action.footerState, footerHeight: clamped }\n : p,\n ),\n };\n }\n\n case 'SET_HEADER_FOOTER_ENABLED': {\n debug('reducer', `SET_HEADER_FOOTER_ENABLED enabled=${action.enabled}`);\n return { ...state, headerFooterEnabled: action.enabled };\n }\n\n case 'SET_PAGE_COUNTER_MODE': {\n debug('reducer', `SET_PAGE_COUNTER_MODE mode=${action.mode}`);\n return { ...state, pageCounterMode: action.mode };\n }\n\n case 'COPY_HEADER_TO_ALL': {\n debug('reducer', `COPY_HEADER_TO_ALL from=${shortId(action.sourcePageId)}`);\n const source = state.pages.find(p => p.id === action.sourcePageId);\n if (!source) return state;\n return {\n ...state,\n defaultHeaderState: source.headerState,\n defaultHeaderHeight: source.headerHeight,\n pages: state.pages.map(p => ({\n ...p,\n headerState: source.headerState,\n headerHeight: source.headerHeight,\n headerSyncVersion: p.headerSyncVersion + 1,\n })),\n };\n }\n\n case 'COPY_FOOTER_TO_ALL': {\n debug('reducer', `COPY_FOOTER_TO_ALL from=${shortId(action.sourcePageId)}`);\n const source = state.pages.find(p => p.id === action.sourcePageId);\n if (!source) return state;\n return {\n ...state,\n defaultFooterState: source.footerState,\n defaultFooterHeight: source.footerHeight,\n pages: state.pages.map(p => ({\n ...p,\n footerState: source.footerState,\n footerHeight: source.footerHeight,\n footerSyncVersion: p.footerSyncVersion + 1,\n })),\n };\n }\n\n case 'CLEAR_HEADER': {\n debug('reducer', `CLEAR_HEADER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, headerState: null, headerHeight: 0, headerSyncVersion: p.headerSyncVersion + 1 }\n : p,\n ),\n };\n }\n\n case 'CLEAR_FOOTER': {\n debug('reducer', `CLEAR_FOOTER id=${shortId(action.pageId)}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId\n ? { ...p, footerState: null, footerHeight: 0, footerSyncVersion: p.footerSyncVersion + 1 }\n : p,\n ),\n };\n }\n\n case 'CLEAR_ALL_HEADERS': {\n debug('reducer', 'CLEAR_ALL_HEADERS');\n return {\n ...state,\n defaultHeaderState: null,\n defaultHeaderHeight: 0,\n pages: state.pages.map(p => ({\n ...p, headerState: null, headerHeight: 0, headerSyncVersion: p.headerSyncVersion + 1,\n })),\n };\n }\n\n case 'CLEAR_ALL_FOOTERS': {\n debug('reducer', 'CLEAR_ALL_FOOTERS');\n return {\n ...state,\n defaultFooterState: null,\n defaultFooterHeight: 0,\n pages: state.pages.map(p => ({\n ...p, footerState: null, footerHeight: 0, footerSyncVersion: p.footerSyncVersion + 1,\n })),\n };\n }\n\n case 'CLEAR_DOCUMENT_CONTENT': {\n debug('reducer', 'CLEAR_DOCUMENT_CONTENT');\n const firstPage = state.pages[0];\n return {\n ...state,\n pages: [{\n ...createEmptyPage(firstPage?.id),\n headerState: firstPage?.headerState ?? null,\n footerState: firstPage?.footerState ?? null,\n headerHeight: firstPage?.headerHeight ?? 0,\n footerHeight: firstPage?.footerHeight ?? 0,\n bodySyncVersion: (firstPage?.bodySyncVersion ?? 0) + 1,\n headerSyncVersion: firstPage?.headerSyncVersion ?? 0,\n footerSyncVersion: firstPage?.footerSyncVersion ?? 0,\n }],\n };\n }\n\n case 'SET_HEADER_HEIGHT': {\n const clamped = Math.min(action.height, MAX_HEADER_HEIGHT_PX);\n debug('header', `SET_HEADER_HEIGHT id=${shortId(action.pageId)} raw=${action.height} clamped=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, headerHeight: clamped } : p,\n ),\n };\n }\n\n case 'SET_FOOTER_HEIGHT': {\n const clamped = Math.min(action.height, MAX_FOOTER_HEIGHT_PX);\n debug('footer', `SET_FOOTER_HEIGHT id=${shortId(action.pageId)} raw=${action.height} clamped=${clamped}`);\n return {\n ...state,\n pages: state.pages.map(p =>\n p.id === action.pageId ? { ...p, footerHeight: clamped } : p,\n ),\n };\n }\n\n case 'SET_DOCUMENT': {\n debug('reducer', `SET_DOCUMENT pages=${action.document.pages.length}`);\n return withExternalSyncVersions(state, action.document);\n }\n\n default:\n return state;\n }\n}\n","import type { Lex4Document } from '../types/document';\nimport type {\n CaretPosition,\n CaretSelection,\n HistoryActionDescriptor,\n HistoryEntry,\n HistoryState,\n} from '../types/history';\n\nexport const MAX_HISTORY_ACTIONS = 100;\n\nfunction cloneSnapshot(document: Lex4Document): Lex4Document {\n return structuredClone(document);\n}\n\nfunction createHistoryEntry(\n document: Lex4Document,\n descriptor: HistoryActionDescriptor,\n undoSnapshot: Lex4Document,\n caretPosition: CaretPosition | null,\n caretSelection: CaretSelection | null,\n undoCaretPosition: CaretPosition | null,\n undoCaretSelection: CaretSelection | null,\n): HistoryEntry {\n return {\n ...descriptor,\n id: crypto.randomUUID(),\n snapshot: cloneSnapshot(document),\n undoSnapshot: cloneSnapshot(undoSnapshot),\n timestamp: new Date().toISOString(),\n caretPosition,\n caretSelection,\n undoCaretPosition,\n undoCaretSelection,\n };\n}\n\nexport function createHistoryState(\n document: Lex4Document,\n baseCaretPosition: CaretPosition | null = null,\n): HistoryState {\n return {\n baseSnapshot: cloneSnapshot(document),\n baseCaretPosition,\n entries: [],\n cursor: 0,\n };\n}\n\nexport function getHistorySnapshot(history: HistoryState, cursor = history.cursor): Lex4Document {\n if (cursor <= 0) {\n return cloneSnapshot(history.baseSnapshot);\n }\n\n return cloneSnapshot(history.entries[cursor - 1].snapshot);\n}\n\nexport function clearHistoryState(\n document: Lex4Document,\n baseCaretPosition: CaretPosition | null = null,\n): HistoryState {\n return createHistoryState(document, baseCaretPosition);\n}\n\nexport function recordHistoryEntry(\n history: HistoryState,\n nextDocument: Lex4Document,\n descriptor: HistoryActionDescriptor,\n undoSnapshot: Lex4Document,\n caretPosition: CaretPosition | null,\n caretSelection: CaretSelection | null,\n undoCaretPosition: CaretPosition | null,\n undoCaretSelection: CaretSelection | null,\n): HistoryState {\n const entries = history.entries.slice(0, history.cursor);\n entries.push(createHistoryEntry(\n nextDocument,\n descriptor,\n undoSnapshot,\n caretPosition,\n caretSelection,\n undoCaretPosition,\n undoCaretSelection,\n ));\n\n let baseSnapshot = cloneSnapshot(history.baseSnapshot);\n let baseCaretPosition = history.baseCaretPosition;\n let trimmedEntries = entries;\n\n if (trimmedEntries.length > MAX_HISTORY_ACTIONS) {\n baseSnapshot = cloneSnapshot(trimmedEntries[1].undoSnapshot);\n baseCaretPosition = trimmedEntries[1].undoCaretPosition;\n trimmedEntries = trimmedEntries.slice(1);\n }\n\n return {\n baseSnapshot,\n baseCaretPosition,\n entries: trimmedEntries,\n cursor: trimmedEntries.length,\n };\n}\n\nexport function undoHistory(\n history: HistoryState,\n): {\n history: HistoryState;\n document: Lex4Document;\n caretPosition: CaretPosition | null;\n caretSelection: CaretSelection | null;\n} | null {\n if (history.cursor === 0) {\n return null;\n }\n\n const cursor = history.cursor - 1;\n const nextHistory: HistoryState = {\n ...history,\n cursor,\n };\n\n return {\n history: nextHistory,\n document: cloneSnapshot(history.entries[history.cursor - 1].undoSnapshot),\n caretPosition: history.entries[history.cursor - 1].undoCaretPosition,\n caretSelection: history.entries[history.cursor - 1].undoCaretSelection,\n };\n}\n\nexport function redoHistory(\n history: HistoryState,\n): {\n history: HistoryState;\n document: Lex4Document;\n caretPosition: CaretPosition | null;\n caretSelection: CaretSelection | null;\n} | null {\n if (history.cursor >= history.entries.length) {\n return null;\n }\n\n const cursor = history.cursor + 1;\n const nextHistory: HistoryState = {\n ...history,\n cursor,\n };\n\n return {\n history: nextHistory,\n document: getHistorySnapshot(nextHistory),\n caretPosition: nextHistory.entries[cursor - 1]?.caretPosition ?? nextHistory.baseCaretPosition,\n caretSelection: nextHistory.entries[cursor - 1]?.caretSelection ?? null,\n };\n}\n\nexport function jumpToHistoryEntry(\n history: HistoryState,\n entryIndex: number,\n): {\n history: HistoryState;\n document: Lex4Document;\n caretPosition: CaretPosition | null;\n caretSelection: CaretSelection | null;\n} | null {\n if (entryIndex < 0 || entryIndex >= history.entries.length) {\n return null;\n }\n\n const nextHistory: HistoryState = {\n ...history,\n cursor: entryIndex + 1,\n };\n\n return {\n history: nextHistory,\n document: getHistorySnapshot(nextHistory),\n caretPosition: nextHistory.entries[nextHistory.cursor - 1]?.caretPosition ?? nextHistory.baseCaretPosition,\n caretSelection: nextHistory.entries[nextHistory.cursor - 1]?.caretSelection ?? null,\n };\n}\n","import React, { useReducer, useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport type { Lex4Document } from '../types/document';\nimport type {\n CaretPosition,\n CaretSelection,\n HistoryActionDescriptor,\n HistoryState,\n} from '../types/history';\nimport { $createRangeSelectionFromDom, $getRoot, $getSelection, $isRangeSelection } from 'lexical';\nimport type { LexicalEditor } from 'lexical';\nimport { createEmptyDocument } from '../types/document';\nimport { DocumentContext, type DocumentAction, type EditorRegistry } from './document-context';\nimport { documentReducer } from './document-reducer';\nimport {\n clearHistoryState,\n createHistoryState,\n jumpToHistoryEntry,\n recordHistoryEntry,\n redoHistory,\n undoHistory,\n} from '../utils/history-manager';\n\ninterface DocumentProviderProps {\n initialDocument?: Lex4Document;\n onDocumentChange?: (doc: Lex4Document) => void;\n children: React.ReactNode;\n}\n\nconst HISTORY_RESTORE_SUPPRESSION_MS = 100;\nconst HISTORY_BATCH_FLUSH_MS = 16;\n\nfunction cloneDocumentSnapshot(document: Lex4Document): Lex4Document {\n return structuredClone(document);\n}\n\nfunction captureUndoSnapshot(\n document: Lex4Document,\n activeEditor: LexicalEditor | null,\n caretPosition: CaretPosition | null,\n): Lex4Document {\n const snapshot = cloneDocumentSnapshot(document);\n if (!activeEditor || !caretPosition) {\n return snapshot;\n }\n\n const page = snapshot.pages.find(candidate => candidate.id === caretPosition.pageId);\n if (!page) {\n return snapshot;\n }\n\n const editorState = activeEditor.getEditorState().toJSON();\n if (caretPosition.region === 'body') {\n page.bodyState = editorState;\n } else if (caretPosition.region === 'header') {\n page.headerState = editorState;\n } else {\n page.footerState = editorState;\n }\n\n return snapshot;\n}\n\nfunction captureCaretSelection(editor: LexicalEditor | null): CaretSelection | null {\n if (!editor) {\n return null;\n }\n\n const rootElement = editor.getRootElement();\n const domSelection = window.getSelection();\n const selectionInRoot = (node: Node | null) =>\n !!node && !!rootElement && (node === rootElement || rootElement.contains(node));\n const getTextOffset = (node: Node, offset: number) => {\n if (!rootElement) {\n return 0;\n }\n\n const range = document.createRange();\n range.setStart(rootElement, 0);\n range.setEnd(node, offset);\n return range.toString().length;\n };\n\n let caretSelection: CaretSelection | null = null;\n editor.getEditorState().read(() => {\n const selection = $createRangeSelectionFromDom(window.getSelection(), editor) ?? $getSelection();\n if (!$isRangeSelection(selection)) {\n return;\n }\n\n caretSelection = {\n anchor: {\n key: selection.anchor.key,\n offset: selection.anchor.offset,\n type: selection.anchor.type,\n },\n focus: {\n key: selection.focus.key,\n offset: selection.focus.offset,\n type: selection.focus.type,\n },\n anchorTextOffset:\n domSelection && selectionInRoot(domSelection.anchorNode)\n ? getTextOffset(domSelection.anchorNode!, domSelection.anchorOffset)\n : 0,\n focusTextOffset:\n domSelection && selectionInRoot(domSelection.focusNode)\n ? getTextOffset(domSelection.focusNode!, domSelection.focusOffset)\n : 0,\n format: selection.format,\n style: selection.style,\n };\n });\n\n return caretSelection;\n}\n\nfunction getPageNumber(document: Lex4Document, pageId?: string): number | null {\n if (!pageId) {\n return null;\n }\n\n const index = document.pages.findIndex(page => page.id === pageId);\n return index >= 0 ? index + 1 : null;\n}\n\nfunction describeAction(\n action: DocumentAction,\n document: Lex4Document,\n): HistoryActionDescriptor {\n switch (action.type) {\n case 'UPDATE_PAGE_BODY': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Edited body - Page ${pageNumber}` : 'Edited body',\n source: 'body',\n pageId: action.pageId,\n region: 'body',\n };\n }\n case 'UPDATE_PAGE_HEADER':\n case 'UPDATE_PAGE_HEADER_CONTENT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Edited header - Page ${pageNumber}` : 'Edited header',\n source: 'header',\n pageId: action.pageId,\n region: 'header',\n };\n }\n case 'UPDATE_PAGE_FOOTER':\n case 'UPDATE_PAGE_FOOTER_CONTENT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Edited footer - Page ${pageNumber}` : 'Edited footer',\n source: 'footer',\n pageId: action.pageId,\n region: 'footer',\n };\n }\n case 'SET_HEADER_FOOTER_ENABLED':\n return {\n label: action.enabled ? 'Enabled headers and footers' : 'Disabled headers and footers',\n source: 'document',\n region: 'document',\n };\n case 'SET_PAGE_COUNTER_MODE':\n return {\n label: `Page counter set to ${action.mode}`,\n source: 'document',\n region: 'document',\n };\n case 'COPY_HEADER_TO_ALL':\n return {\n label: 'Copied header to all pages',\n source: 'toolbar',\n pageId: action.sourcePageId,\n region: 'header',\n };\n case 'COPY_FOOTER_TO_ALL':\n return {\n label: 'Copied footer to all pages',\n source: 'toolbar',\n pageId: action.sourcePageId,\n region: 'footer',\n };\n case 'CLEAR_HEADER': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Cleared header - Page ${pageNumber}` : 'Cleared header',\n source: 'toolbar',\n pageId: action.pageId,\n region: 'header',\n };\n }\n case 'CLEAR_FOOTER': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Cleared footer - Page ${pageNumber}` : 'Cleared footer',\n source: 'toolbar',\n pageId: action.pageId,\n region: 'footer',\n };\n }\n case 'CLEAR_ALL_HEADERS':\n return {\n label: 'Cleared all headers',\n source: 'toolbar',\n region: 'header',\n };\n case 'CLEAR_ALL_FOOTERS':\n return {\n label: 'Cleared all footers',\n source: 'toolbar',\n region: 'footer',\n };\n case 'CLEAR_DOCUMENT_CONTENT':\n return {\n label: 'Cleared document body',\n source: 'document',\n region: 'document',\n };\n case 'SET_HEADER_HEIGHT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Resized header - Page ${pageNumber}` : 'Resized header',\n source: 'header',\n pageId: action.pageId,\n region: 'header',\n };\n }\n case 'SET_FOOTER_HEIGHT': {\n const pageNumber = getPageNumber(document, action.pageId);\n return {\n label: pageNumber ? `Resized footer - Page ${pageNumber}` : 'Resized footer',\n source: 'footer',\n pageId: action.pageId,\n region: 'footer',\n };\n }\n case 'ADD_PAGE':\n return {\n label: 'Added page',\n source: 'overflow',\n region: 'document',\n };\n case 'REMOVE_PAGE':\n return {\n label: 'Removed page',\n source: 'overflow',\n region: 'document',\n };\n case 'SET_DOCUMENT':\n return {\n label: 'Document reflow',\n source: 'overflow',\n region: 'document',\n };\n default:\n return {\n label: 'Updated document',\n source: 'document',\n region: 'document',\n };\n }\n}\n\nfunction documentsAreEqual(current: Lex4Document, next: Lex4Document): boolean {\n return JSON.stringify(current) === JSON.stringify(next);\n}\n\nexport const DocumentProvider: React.FC<DocumentProviderProps> = ({\n initialDocument,\n onDocumentChange,\n children,\n}) => {\n const initialSnapshot = initialDocument ?? createEmptyDocument();\n const [document, baseDispatch] = useReducer(documentReducer, initialSnapshot);\n const [historyState, setHistoryState] = useState<HistoryState>(() => createHistoryState(initialSnapshot));\n const documentRef = useRef(document);\n const historyStateRef = useRef(historyState);\n const [activePageId, setActivePageIdRaw] = useState<string | null>(\n initialSnapshot.pages[0]?.id ?? null,\n );\n const activePageIdRef = useRef<string | null>(initialSnapshot.pages[0]?.id ?? null);\n const [globalSelectionActive, setGlobalSelectionActive] = useState(false);\n const [historySidebarOpen, setHistorySidebarOpen] = useState(true);\n const [focusAtEndVersion, setFocusAtEndVersion] = useState(0);\n const activeEditorRef = useRef<LexicalEditor | null>(null);\n const activeCaretPositionRef = useRef<CaretPosition | null>(null);\n const pendingCaretPositionRef = useRef<CaretPosition | null>(null);\n const pendingCaretSelectionRef = useRef<CaretSelection | null>(null);\n const pendingFocusAtEndRef = useRef<CaretPosition | null>(null);\n const [, forceUpdate] = useState(0);\n const historySuppressedRef = useRef(false);\n const historyReleaseTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const historyFlushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingHistoryActionRef = useRef<HistoryActionDescriptor | null>(null);\n const pendingUndoSnapshotRef = useRef<Lex4Document | null>(null);\n const pendingUndoCaretPositionRef = useRef<CaretPosition | null>(null);\n const pendingUndoCaretSelectionRef = useRef<CaretSelection | null>(null);\n const historyBatchRef = useRef<{\n descriptor: HistoryActionDescriptor;\n nextDocument: Lex4Document | null;\n undoSnapshot: Lex4Document | null;\n undoCaretPosition: CaretPosition | null;\n undoCaretSelection: CaretSelection | null;\n hasMutation: boolean;\n } | null>(null);\n\n const editorMapRef = useRef(new Map<string, LexicalEditor>());\n const editorRegistry: EditorRegistry = useMemo(() => ({\n register: (pageId: string, editor: LexicalEditor) => {\n editorMapRef.current.set(pageId, editor);\n },\n unregister: (pageId: string) => {\n editorMapRef.current.delete(pageId);\n },\n get: (pageId: string) => editorMapRef.current.get(pageId),\n all: () => Array.from(editorMapRef.current.values()),\n }), []);\n\n const setActivePageId = useCallback((id: string | null) => {\n activePageIdRef.current = id;\n setActivePageIdRaw(id);\n }, []);\n\n const setActiveEditor = useCallback((\n editor: LexicalEditor | null,\n caretPosition: CaretPosition | null = null,\n ) => {\n activeEditorRef.current = editor;\n activeCaretPositionRef.current = caretPosition;\n forceUpdate(n => n + 1);\n }, []);\n\n const focusEditorAtEnd = useCallback((editor: LexicalEditor, caretPosition: CaretPosition) => {\n requestAnimationFrame(() => {\n setActivePageId(caretPosition.pageId);\n setActiveEditor(editor, caretPosition);\n editor.focus(() => {\n editor.update(() => {\n $getRoot().selectEnd();\n });\n });\n });\n }, [setActiveEditor, setActivePageId]);\n\n const consumePendingCaretPosition = useCallback((caretPosition: CaretPosition) => {\n const pendingCaretPosition = pendingCaretPositionRef.current;\n if (\n !pendingCaretPosition\n || pendingCaretPosition.pageId !== caretPosition.pageId\n || pendingCaretPosition.region !== caretPosition.region\n ) {\n return undefined;\n }\n\n pendingCaretPositionRef.current = null;\n const pendingCaretSelection = pendingCaretSelectionRef.current;\n pendingCaretSelectionRef.current = null;\n return pendingCaretSelection;\n }, []);\n\n const consumePendingFocusAtEnd = useCallback((caretPosition: CaretPosition) => {\n const pendingFocusAtEnd = pendingFocusAtEndRef.current;\n if (\n !pendingFocusAtEnd\n || pendingFocusAtEnd.pageId !== caretPosition.pageId\n || pendingFocusAtEnd.region !== caretPosition.region\n ) {\n return false;\n }\n\n pendingFocusAtEndRef.current = null;\n return true;\n }, []);\n\n const requestFocusAtEnd = useCallback((caretPosition: CaretPosition) => {\n pendingCaretPositionRef.current = null;\n pendingCaretSelectionRef.current = null;\n\n if (caretPosition.region === 'body') {\n const editor = editorRegistry.get(caretPosition.pageId);\n if (editor) {\n pendingFocusAtEndRef.current = null;\n focusEditorAtEnd(editor, caretPosition);\n return;\n }\n }\n\n pendingFocusAtEndRef.current = caretPosition;\n setFocusAtEndVersion(version => version + 1);\n }, [editorRegistry, focusEditorAtEnd]);\n\n const flushHistoryBatch = useCallback(() => {\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n historyFlushTimerRef.current = null;\n }\n\n const batch = historyBatchRef.current;\n historyBatchRef.current = null;\n pendingHistoryActionRef.current = null;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n\n if (!batch || historySuppressedRef.current || !batch.hasMutation || !batch.nextDocument) {\n return;\n }\n\n const undoSnapshot = batch.undoSnapshot ?? batch.nextDocument;\n\n setHistoryState(previousHistory => {\n const nextHistory = recordHistoryEntry(\n previousHistory,\n batch.nextDocument as Lex4Document,\n batch.descriptor,\n undoSnapshot,\n activeCaretPositionRef.current,\n captureCaretSelection(activeEditorRef.current),\n batch.undoCaretPosition,\n batch.undoCaretSelection,\n );\n historyStateRef.current = nextHistory;\n return nextHistory;\n });\n }, []);\n\n const scheduleHistoryBatchFlush = useCallback(() => {\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n }\n\n historyFlushTimerRef.current = setTimeout(() => {\n flushHistoryBatch();\n }, HISTORY_BATCH_FLUSH_MS);\n }, [flushHistoryBatch]);\n\n const queueHistoryAction = useCallback((action: HistoryActionDescriptor | null) => {\n pendingHistoryActionRef.current = action;\n pendingUndoSnapshotRef.current = action\n ? captureUndoSnapshot(\n documentRef.current,\n activeEditorRef.current,\n activeCaretPositionRef.current,\n )\n : null;\n pendingUndoCaretPositionRef.current = action ? activeCaretPositionRef.current : null;\n pendingUndoCaretSelectionRef.current = action ? captureCaretSelection(activeEditorRef.current) : null;\n }, []);\n\n const runHistoryAction = useCallback((action: HistoryActionDescriptor, callback: () => void) => {\n if (historyBatchRef.current) {\n callback();\n return;\n }\n\n historyBatchRef.current = {\n descriptor: action,\n nextDocument: null,\n undoSnapshot: captureUndoSnapshot(\n documentRef.current,\n activeEditorRef.current,\n activeCaretPositionRef.current,\n ),\n undoCaretPosition: activeCaretPositionRef.current,\n undoCaretSelection: captureCaretSelection(activeEditorRef.current),\n hasMutation: false,\n };\n\n pendingHistoryActionRef.current = action;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n\n try {\n callback();\n } finally {\n scheduleHistoryBatchFlush();\n }\n }, [scheduleHistoryBatchFlush]);\n\n const suppressHistoryTemporarily = useCallback(() => {\n historySuppressedRef.current = true;\n pendingHistoryActionRef.current = null;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n historyBatchRef.current = null;\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n historyFlushTimerRef.current = null;\n }\n if (historyReleaseTimerRef.current) {\n clearTimeout(historyReleaseTimerRef.current);\n }\n historyReleaseTimerRef.current = setTimeout(() => {\n historySuppressedRef.current = false;\n historyReleaseTimerRef.current = null;\n }, HISTORY_RESTORE_SUPPRESSION_MS);\n }, []);\n\n const dispatch = useCallback((action: DocumentAction) => {\n const currentDocument = documentRef.current;\n const nextDocument = documentReducer(currentDocument, action);\n const changed = !documentsAreEqual(currentDocument, nextDocument);\n const suppressPassiveBodyHistory =\n action.type === 'UPDATE_PAGE_BODY'\n && action.pageId !== activePageIdRef.current\n && !historyBatchRef.current\n && !pendingHistoryActionRef.current;\n\n documentRef.current = nextDocument;\n\n if (changed && !historySuppressedRef.current && !suppressPassiveBodyHistory) {\n if (historyBatchRef.current) {\n historyBatchRef.current.nextDocument = cloneDocumentSnapshot(nextDocument);\n historyBatchRef.current.hasMutation = true;\n scheduleHistoryBatchFlush();\n } else if (pendingHistoryActionRef.current) {\n historyBatchRef.current = {\n descriptor: pendingHistoryActionRef.current,\n nextDocument: cloneDocumentSnapshot(nextDocument),\n undoSnapshot: pendingUndoSnapshotRef.current,\n undoCaretPosition: pendingUndoCaretPositionRef.current,\n undoCaretSelection: pendingUndoCaretSelectionRef.current,\n hasMutation: true,\n };\n scheduleHistoryBatchFlush();\n } else {\n const descriptor = describeAction(action, currentDocument);\n setHistoryState(previousHistory => {\n const nextHistory = recordHistoryEntry(\n previousHistory,\n nextDocument,\n descriptor,\n captureUndoSnapshot(\n currentDocument,\n activeEditorRef.current,\n activeCaretPositionRef.current,\n ),\n activeCaretPositionRef.current,\n captureCaretSelection(activeEditorRef.current),\n activeCaretPositionRef.current,\n captureCaretSelection(activeEditorRef.current),\n );\n historyStateRef.current = nextHistory;\n return nextHistory;\n });\n }\n } else {\n pendingHistoryActionRef.current = null;\n pendingUndoSnapshotRef.current = null;\n pendingUndoCaretPositionRef.current = null;\n pendingUndoCaretSelectionRef.current = null;\n }\n\n baseDispatch(action);\n }, [scheduleHistoryBatchFlush]);\n\n const restoreDocument = useCallback((\n snapshot: Lex4Document,\n caretPosition: CaretPosition | null,\n caretSelection: CaretSelection | null,\n ) => {\n suppressHistoryTemporarily();\n pendingCaretPositionRef.current = caretPosition;\n pendingCaretSelectionRef.current = caretSelection;\n activeEditorRef.current = null;\n activeCaretPositionRef.current = caretPosition;\n forceUpdate(n => n + 1);\n documentRef.current = cloneDocumentSnapshot(snapshot);\n baseDispatch({ type: 'SET_DOCUMENT', document: cloneDocumentSnapshot(snapshot) });\n }, [suppressHistoryTemporarily]);\n\n const undo = useCallback(() => {\n flushHistoryBatch();\n const result = undoHistory(historyStateRef.current);\n if (!result) {\n return;\n }\n\n historyStateRef.current = result.history;\n setHistoryState(result.history);\n restoreDocument(result.document, result.caretPosition, result.caretSelection);\n }, [flushHistoryBatch, restoreDocument]);\n\n const redo = useCallback(() => {\n flushHistoryBatch();\n const result = redoHistory(historyStateRef.current);\n if (!result) {\n return;\n }\n\n historyStateRef.current = result.history;\n setHistoryState(result.history);\n restoreDocument(result.document, result.caretPosition, result.caretSelection);\n }, [flushHistoryBatch, restoreDocument]);\n\n const clearHistory = useCallback(() => {\n flushHistoryBatch();\n const nextHistory = clearHistoryState(documentRef.current, activeCaretPositionRef.current);\n historyStateRef.current = nextHistory;\n setHistoryState(nextHistory);\n }, [flushHistoryBatch]);\n\n const handleJumpToHistoryEntry = useCallback((entryIndex: number) => {\n flushHistoryBatch();\n const result = jumpToHistoryEntry(historyStateRef.current, entryIndex);\n if (!result) {\n return;\n }\n\n historyStateRef.current = result.history;\n setHistoryState(result.history);\n restoreDocument(result.document, result.caretPosition, result.caretSelection);\n }, [flushHistoryBatch, restoreDocument]);\n\n useEffect(() => {\n documentRef.current = document;\n onDocumentChange?.(document);\n }, [document, onDocumentChange]);\n\n useEffect(() => {\n historyStateRef.current = historyState;\n }, [historyState]);\n\n useEffect(() => {\n const firstPageId = document.pages[0]?.id ?? null;\n const activePageStillExists = activePageId !== null\n && document.pages.some(page => page.id === activePageId);\n\n if (!activePageStillExists) {\n activePageIdRef.current = firstPageId;\n setActivePageIdRaw(firstPageId);\n activeEditorRef.current = null;\n activeCaretPositionRef.current = null;\n forceUpdate(n => n + 1);\n }\n }, [activePageId, document.pages]);\n\n useEffect(\n () => () => {\n if (historyFlushTimerRef.current) {\n clearTimeout(historyFlushTimerRef.current);\n }\n if (historyReleaseTimerRef.current) {\n clearTimeout(historyReleaseTimerRef.current);\n }\n },\n [],\n );\n\n return (\n <DocumentContext.Provider value={{\n document,\n dispatch,\n activePageId,\n setActivePageId,\n activeEditor: activeEditorRef.current,\n consumePendingCaretPosition,\n consumePendingFocusAtEnd,\n requestFocusAtEnd,\n focusAtEndVersion,\n setActiveEditor,\n globalSelectionActive,\n setGlobalSelectionActive,\n historyEntries: historyState.entries,\n historyCursor: historyState.cursor,\n canUndo: historyState.cursor > 0,\n canRedo: historyState.cursor < historyState.entries.length,\n queueHistoryAction,\n runHistoryAction,\n jumpToHistoryEntry: handleJumpToHistoryEntry,\n clearHistory,\n historySidebarOpen,\n setHistorySidebarOpen,\n undo,\n redo,\n editorRegistry,\n }}>\n {children}\n </DocumentContext.Provider>\n );\n};\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.js';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.js.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { createContext, useContext, useMemo, createElement } from 'react';\n\nconst LucideContext = createContext({});\nfunction LucideProvider({\n children,\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n className\n}) {\n const value = useMemo(\n () => ({\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n className\n }),\n [size, color, strokeWidth, absoluteStrokeWidth, className]\n );\n return createElement(LucideContext.Provider, { value }, children);\n}\nconst useLucideContext = () => useContext(LucideContext);\n\nexport { LucideProvider, useLucideContext };\n//# sourceMappingURL=context.js.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.js';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { useLucideContext } from './context.js';\n\nconst Icon = forwardRef(\n ({ color, size, strokeWidth, absoluteStrokeWidth, className = \"\", children, iconNode, ...rest }, ref) => {\n const {\n size: contextSize = 24,\n strokeWidth: contextStrokeWidth = 2,\n absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,\n color: contextColor = \"currentColor\",\n className: contextClass = \"\"\n } = useLucideContext() ?? {};\n const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;\n return createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size ?? contextSize ?? defaultAttributes.width,\n height: size ?? contextSize ?? defaultAttributes.height,\n stroke: color ?? contextColor,\n strokeWidth: calculatedStrokeWidth,\n className: mergeClasses(\"lucide\", contextClass, className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n );\n }\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { toKebabCase } from './shared/src/utils/toKebabCase.js';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8\", key: \"mg9rjx\" }\n ]\n];\nconst Bold = createLucideIcon(\"bold\", __iconNode);\n\nexport { __iconNode, Bold as default };\n//# sourceMappingURL=bold.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\", key: \"ezmyqa\" }\n ],\n [\n \"path\",\n {\n d: \"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\",\n key: \"e1hn23\"\n }\n ]\n];\nconst Braces = createLucideIcon(\"braces\", __iconNode);\n\nexport { __iconNode, Braces as default };\n//# sourceMappingURL=braces.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"15\", x2: \"15\", y1: \"12\", y2: \"18\", key: \"1p7wdc\" }],\n [\"line\", { x1: \"12\", x2: \"18\", y1: \"15\", y2: \"15\", key: \"1nscbv\" }],\n [\"rect\", { width: \"14\", height: \"14\", x: \"8\", y: \"8\", rx: \"2\", ry: \"2\", key: \"17jyea\" }],\n [\"path\", { d: \"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\", key: \"zix9uf\" }]\n];\nconst CopyPlus = createLucideIcon(\"copy-plus\", __iconNode);\n\nexport { __iconNode, CopyPlus as default };\n//# sourceMappingURL=copy-plus.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21\",\n key: \"g5wo59\"\n }\n ],\n [\"path\", { d: \"m5.082 11.09 8.828 8.828\", key: \"1wx5vj\" }]\n];\nconst Eraser = createLucideIcon(\"eraser\", __iconNode);\n\nexport { __iconNode, Eraser as default };\n//# sourceMappingURL=eraser.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"9\", y2: \"9\", key: \"4lhtct\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"15\", y2: \"15\", key: \"vyu0kd\" }],\n [\"line\", { x1: \"10\", x2: \"8\", y1: \"3\", y2: \"21\", key: \"1ggp8o\" }],\n [\"line\", { x1: \"16\", x2: \"14\", y1: \"3\", y2: \"21\", key: \"weycgp\" }]\n];\nconst Hash = createLucideIcon(\"hash\", __iconNode);\n\nexport { __iconNode, Hash as default };\n//# sourceMappingURL=hash.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"19\", x2: \"10\", y1: \"4\", y2: \"4\", key: \"15jd3p\" }],\n [\"line\", { x1: \"14\", x2: \"5\", y1: \"20\", y2: \"20\", key: \"bu0au3\" }],\n [\"line\", { x1: \"15\", x2: \"9\", y1: \"4\", y2: \"20\", key: \"uljnxc\" }]\n];\nconst Italic = createLucideIcon(\"italic\", __iconNode);\n\nexport { __iconNode, Italic as default };\n//# sourceMappingURL=italic.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H11\", key: \"us1j55\" }],\n [\"path\", { d: \"M21 12H11\", key: \"wd7e0v\" }],\n [\"path\", { d: \"M21 19H11\", key: \"saa85w\" }],\n [\"path\", { d: \"m7 8-4 4 4 4\", key: \"o5hrat\" }]\n];\nconst ListIndentDecrease = createLucideIcon(\"list-indent-decrease\", __iconNode);\n\nexport { __iconNode, ListIndentDecrease as default };\n//# sourceMappingURL=list-indent-decrease.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H11\", key: \"us1j55\" }],\n [\"path\", { d: \"M21 12H11\", key: \"wd7e0v\" }],\n [\"path\", { d: \"M21 19H11\", key: \"saa85w\" }],\n [\"path\", { d: \"m3 8 4 4-4 4\", key: \"1a3j6y\" }]\n];\nconst ListIndentIncrease = createLucideIcon(\"list-indent-increase\", __iconNode);\n\nexport { __iconNode, ListIndentIncrease as default };\n//# sourceMappingURL=list-indent-increase.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 5h10\", key: \"1cz7ny\" }],\n [\"path\", { d: \"M11 12h10\", key: \"1438ji\" }],\n [\"path\", { d: \"M11 19h10\", key: \"11t30w\" }],\n [\"path\", { d: \"M4 4h1v5\", key: \"10yrso\" }],\n [\"path\", { d: \"M4 9h2\", key: \"r1h2o0\" }],\n [\"path\", { d: \"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02\", key: \"xtkcd5\" }]\n];\nconst ListOrdered = createLucideIcon(\"list-ordered\", __iconNode);\n\nexport { __iconNode, ListOrdered as default };\n//# sourceMappingURL=list-ordered.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 5h.01\", key: \"18ugdj\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M3 19h.01\", key: \"noohij\" }],\n [\"path\", { d: \"M8 5h13\", key: \"1pao27\" }],\n [\"path\", { d: \"M8 12h13\", key: \"1za7za\" }],\n [\"path\", { d: \"M8 19h13\", key: \"m83p4d\" }]\n];\nconst List = createLucideIcon(\"list\", __iconNode);\n\nexport { __iconNode, List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n];\nconst PanelRight = createLucideIcon(\"panel-right\", __iconNode);\n\nexport { __iconNode, PanelRight as default };\n//# sourceMappingURL=panel-right.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m15 14 5-5-5-5\", key: \"12vg1m\" }],\n [\"path\", { d: \"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13\", key: \"6uklza\" }]\n];\nconst Redo2 = createLucideIcon(\"redo-2\", __iconNode);\n\nexport { __iconNode, Redo2 as default };\n//# sourceMappingURL=redo-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\", key: \"v9h5vc\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }],\n [\"path\", { d: \"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\", key: \"3uifl3\" }],\n [\"path\", { d: \"M8 16H3v5\", key: \"1cv678\" }]\n];\nconst RefreshCw = createLucideIcon(\"refresh-cw\", __iconNode);\n\nexport { __iconNode, RefreshCw as default };\n//# sourceMappingURL=refresh-cw.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m21 21-4.34-4.34\", key: \"14j7rj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }]\n];\nconst Search = createLucideIcon(\"search\", __iconNode);\n\nexport { __iconNode, Search as default };\n//# sourceMappingURL=search.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M16 4H9a3 3 0 0 0-2.83 4\", key: \"43sutm\" }],\n [\"path\", { d: \"M14 12a4 4 0 0 1 0 8H6\", key: \"nlfj13\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"12\", y2: \"12\", key: \"1e0a9i\" }]\n];\nconst Strikethrough = createLucideIcon(\"strikethrough\", __iconNode);\n\nexport { __iconNode, Strikethrough as default };\n//# sourceMappingURL=strikethrough.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H3\", key: \"1fi0y6\" }],\n [\"path\", { d: \"M17 12H7\", key: \"16if0g\" }],\n [\"path\", { d: \"M19 19H5\", key: \"vjpgq2\" }]\n];\nconst TextAlignCenter = createLucideIcon(\"text-align-center\", __iconNode);\n\nexport { __iconNode, TextAlignCenter as default };\n//# sourceMappingURL=text-align-center.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H3\", key: \"1fi0y6\" }],\n [\"path\", { d: \"M21 12H9\", key: \"dn1m92\" }],\n [\"path\", { d: \"M21 19H7\", key: \"4cu937\" }]\n];\nconst TextAlignEnd = createLucideIcon(\"text-align-end\", __iconNode);\n\nexport { __iconNode, TextAlignEnd as default };\n//# sourceMappingURL=text-align-end.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 5h18\", key: \"1u36vt\" }],\n [\"path\", { d: \"M3 12h18\", key: \"1i2n21\" }],\n [\"path\", { d: \"M3 19h18\", key: \"awlh7x\" }]\n];\nconst TextAlignJustify = createLucideIcon(\"text-align-justify\", __iconNode);\n\nexport { __iconNode, TextAlignJustify as default };\n//# sourceMappingURL=text-align-justify.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 5H3\", key: \"1fi0y6\" }],\n [\"path\", { d: \"M15 12H3\", key: \"6jk70r\" }],\n [\"path\", { d: \"M17 19H3\", key: \"z6ezky\" }]\n];\nconst TextAlignStart = createLucideIcon(\"text-align-start\", __iconNode);\n\nexport { __iconNode, TextAlignStart as default };\n//# sourceMappingURL=text-align-start.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M6 4v6a6 6 0 0 0 12 0V4\", key: \"9kb039\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"20\", y2: \"20\", key: \"nun2al\" }]\n];\nconst Underline = createLucideIcon(\"underline\", __iconNode);\n\nexport { __iconNode, Underline as default };\n//# sourceMappingURL=underline.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M9 14 4 9l5-5\", key: \"102s5s\" }],\n [\"path\", { d: \"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\", key: \"f3b9sd\" }]\n];\nconst Undo2 = createLucideIcon(\"undo-2\", __iconNode);\n\nexport { __iconNode, Undo2 as default };\n//# sourceMappingURL=undo-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n];\nconst X = createLucideIcon(\"x\", __iconNode);\n\nexport { __iconNode, X as default };\n//# sourceMappingURL=x.js.map\n","import type { Lex4Translations } from './types';\n\nexport const DEFAULT_TRANSLATIONS: Lex4Translations = {\n toolbar: {\n undo: 'Undo',\n redo: 'Redo',\n bold: 'Bold (Ctrl+B)',\n italic: 'Italic (Ctrl+I)',\n underline: 'Underline (Ctrl+U)',\n strikethrough: 'Strikethrough',\n alignLeft: 'Align Left',\n alignCenter: 'Align Center',\n alignRight: 'Align Right',\n justify: 'Justify',\n numberedList: 'Numbered List',\n bulletList: 'Bullet List',\n indent: 'Indent',\n outdent: 'Outdent',\n openHistory: 'Open History',\n closeHistory: 'Close History',\n },\n\n history: {\n title: 'History',\n subtitle: 'Word-style session history (last 100 actions)',\n empty: 'No history yet.',\n clearHistory: 'Clear History',\n actions: {\n enabledHeadersFooters: 'Enabled headers and footers',\n disabledHeadersFooters: 'Disabled headers and footers',\n copiedHeaderToAll: 'Copied header to all pages',\n copiedFooterToAll: 'Copied footer to all pages',\n clearedHeader: 'Cleared header',\n clearedFooter: 'Cleared footer',\n clearedAllHeaders: 'Cleared all headers',\n clearedAllFooters: 'Cleared all footers',\n pageCounterSet: 'Page counter set to {{value}}',\n boldApplied: 'Bold applied',\n italicApplied: 'Italic applied',\n underlineApplied: 'Underline applied',\n strikethroughApplied: 'Strikethrough applied',\n alignedLeft: 'Aligned left',\n alignedCenter: 'Aligned center',\n alignedRight: 'Aligned right',\n justifiedText: 'Justified text',\n insertedNumberedList: 'Inserted numbered list',\n insertedBulletList: 'Inserted bullet list',\n indentedContent: 'Indented content',\n outdentedContent: 'Outdented content',\n fontChanged: 'Font changed to {{value}}',\n fontSizeChanged: 'Font size changed to {{value}}pt',\n },\n },\n\n variables: {\n title: 'Variables',\n available: '{{count}} available',\n refreshVariables: 'Refresh variables',\n searchPlaceholder: 'Search variables...',\n noVariablesFound: 'No variables found',\n insertVariable: 'Insert variable {{key}}',\n openPanel: 'Open Variables',\n closePanel: 'Close Variables',\n },\n\n header: {\n placeholder: 'Header',\n },\n\n footer: {\n placeholder: 'Footer',\n },\n\n sidebar: {\n close: 'Close sidebar',\n },\n};\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type { Lex4Translations } from './types';\nimport { DEFAULT_TRANSLATIONS } from './defaults';\n\ntype DeepPartial<T> = {\n [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];\n};\n\nfunction deepMerge<T>(\n target: T,\n source: DeepPartial<T>,\n): T {\n if (typeof target !== 'object' || target === null) {\n return (source ?? target) as T;\n }\n const result = { ...target } as Record<string, unknown>;\n for (const key of Object.keys(source as Record<string, unknown>)) {\n const sourceVal = (source as Record<string, unknown>)[key];\n const targetVal = (target as Record<string, unknown>)[key];\n if (\n sourceVal !== undefined &&\n typeof sourceVal === 'object' &&\n sourceVal !== null &&\n !Array.isArray(sourceVal) &&\n typeof targetVal === 'object' &&\n targetVal !== null\n ) {\n result[key] = deepMerge(targetVal, sourceVal as DeepPartial<typeof targetVal>);\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal;\n }\n }\n return result as T;\n}\n\nconst TranslationsContext = createContext<Lex4Translations>(DEFAULT_TRANSLATIONS);\n\n/**\n * Returns the active translations. Use inside any editor component\n * to access localized strings.\n */\nexport function useTranslations(): Lex4Translations {\n return useContext(TranslationsContext);\n}\n\n/**\n * Interpolates `{{key}}` placeholders in a translation string.\n *\n * @example\n * interpolate('Font changed to {{value}}', { value: 'Inter' })\n * // => 'Font changed to Inter'\n */\nexport function interpolate(\n template: string,\n params: Record<string, string | number>,\n): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) =>\n String(params[key] ?? `{{${key}}}`),\n );\n}\n\ninterface TranslationsProviderProps {\n translations?: DeepPartial<Lex4Translations>;\n children: React.ReactNode;\n}\n\n/**\n * TranslationsProvider — merges consumer overrides with DEFAULT_TRANSLATIONS.\n */\nexport const TranslationsProvider: React.FC<TranslationsProviderProps> = ({\n translations,\n children,\n}) => {\n const merged = useMemo(\n () =>\n translations\n ? deepMerge(DEFAULT_TRANSLATIONS, translations)\n : DEFAULT_TRANSLATIONS,\n [translations],\n );\n\n return (\n <TranslationsContext.Provider value={merged}>\n {children}\n </TranslationsContext.Provider>\n );\n};\n","import React from 'react';\nimport { X } from 'lucide-react';\nimport { useTranslations } from '../i18n';\n\ninterface EditorSidebarProps {\n title: string;\n subtitle?: string;\n open: boolean;\n onClose?: () => void;\n headerActions?: React.ReactNode;\n testId?: string;\n children: React.ReactNode;\n}\n\nexport const EditorSidebar: React.FC<EditorSidebarProps> = ({\n title,\n subtitle,\n open,\n onClose,\n headerActions,\n testId = 'editor-sidebar',\n children,\n}) => {\n const t = useTranslations();\n\n if (!open) {\n return null;\n }\n\n return (\n <aside\n className=\"flex h-full w-[320px] shrink-0 flex-col border-l border-gray-200 bg-white\"\n data-testid={testId}\n >\n <div className=\"flex items-start justify-between border-b border-gray-200 px-3 py-2.5\">\n <div>\n <h2 className=\"text-xs font-semibold text-gray-900\">{title}</h2>\n {subtitle && (\n <p className=\"mt-0.5 text-xs text-gray-500\">{subtitle}</p>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n {headerActions}\n {onClose && (\n <button\n type=\"button\"\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-400\n transition-colors hover:bg-gray-100 hover:text-gray-600\"\n data-testid=\"close-editor-sidebar\"\n onClick={onClose}\n aria-label={t.sidebar.close}\n >\n <X size={14} />\n </button>\n )}\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {children}\n </div>\n </aside>\n );\n};\n","import React from 'react';\nimport { Trash2 } from 'lucide-react';\nimport { useDocument } from '../context/document-context';\nimport { EditorSidebar } from './EditorSidebar';\nimport { useTranslations } from '../i18n';\n\nfunction formatTimestamp(timestamp: string): string {\n const date = new Date(timestamp);\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nexport const HistorySidebar: React.FC = () => {\n const {\n clearHistory,\n historyEntries,\n historyCursor,\n historySidebarOpen,\n jumpToHistoryEntry,\n setHistorySidebarOpen,\n } = useDocument();\n const t = useTranslations();\n\n const visibleEntries = historyEntries.slice().reverse();\n\n const headerActions = (\n <button\n type=\"button\"\n title={t.history.clearHistory}\n aria-label={t.history.clearHistory}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => clearHistory('manual')}\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-400\n transition-colors hover:bg-gray-100 hover:text-gray-600\"\n data-testid=\"clear-history\"\n >\n <Trash2 size={13} />\n </button>\n );\n\n return (\n <EditorSidebar\n title={t.history.title}\n subtitle={t.history.subtitle}\n open={historySidebarOpen}\n onClose={() => setHistorySidebarOpen(false)}\n headerActions={headerActions}\n testId=\"history-sidebar\"\n >\n {visibleEntries.length === 0 ? (\n <div\n className=\"px-3 py-4 text-xs text-gray-500\"\n data-testid=\"history-empty\"\n >\n {t.history.empty}\n </div>\n ) : (\n <ol className=\"divide-y divide-gray-100\" data-testid=\"history-entry-list\">\n {visibleEntries.map((entry, reversedIndex) => {\n const actualIndex = historyEntries.length - reversedIndex - 1;\n const isCurrent = actualIndex === historyCursor - 1;\n\n return (\n <li key={entry.id}>\n <button\n type=\"button\"\n className={`w-full px-3 py-2 text-left transition-colors ${\n isCurrent ? 'bg-blue-50' : 'bg-white hover:bg-gray-50'\n }`}\n data-testid={`history-entry-${actualIndex}`}\n data-history-current={isCurrent ? 'true' : 'false'}\n onClick={() => jumpToHistoryEntry(actualIndex)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className={`text-xs ${isCurrent ? 'font-semibold text-blue-700' : 'text-gray-900'}`}>\n {entry.label}\n </div>\n <div className=\"mt-0.5 text-xs text-gray-400\">\n {entry.source}\n </div>\n </div>\n <div className=\"shrink-0 text-xs text-gray-400\">\n {formatTimestamp(entry.timestamp)}\n </div>\n </div>\n </button>\n </li>\n );\n })}\n </ol>\n )}\n </EditorSidebar>\n );\n};\n","import React from 'react';\n\ninterface HeaderFooterToggleProps {\n enabled: boolean;\n onToggle: (enabled: boolean) => void;\n}\n\nexport const HeaderFooterToggle: React.FC<HeaderFooterToggleProps> = ({\n enabled,\n onToggle,\n}) => {\n return (\n <label\n className=\"flex items-center gap-1.5 cursor-pointer select-none\"\n data-testid=\"header-footer-toggle\"\n >\n <span className=\"text-xs font-medium text-gray-600\">\n Headers & Footers\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={enabled}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onToggle(!enabled)}\n className={`\n relative inline-flex h-4 w-7 items-center rounded-full\n transition-colors duration-200\n ${enabled ? 'bg-blue-500' : 'bg-gray-300'}\n `}\n data-testid=\"header-footer-switch\"\n >\n <span\n className={`\n inline-block h-3 w-3 rounded-full bg-white shadow-sm\n transition-transform duration-200\n ${enabled ? 'translate-x-3.5' : 'translate-x-0.5'}\n `}\n />\n </button>\n </label>\n );\n};\n","import React from 'react';\nimport {\n Hash,\n CopyPlus,\n Eraser,\n Trash2,\n} from 'lucide-react';\nimport type { PageCounterMode } from '../types/document';\n\ninterface HeaderFooterActionsProps {\n activePageId: string | null;\n pageCounterMode: PageCounterMode;\n onPageCounterModeChange: (mode: PageCounterMode) => void;\n onCopyHeaderToAll: () => void;\n onCopyFooterToAll: () => void;\n onClearHeader: () => void;\n onClearFooter: () => void;\n onClearAllHeaders: () => void;\n onClearAllFooters: () => void;\n}\n\nexport const HeaderFooterActions: React.FC<HeaderFooterActionsProps> = ({\n activePageId,\n pageCounterMode,\n onPageCounterModeChange,\n onCopyHeaderToAll,\n onCopyFooterToAll,\n onClearHeader,\n onClearFooter,\n onClearAllHeaders,\n onClearAllFooters,\n}) => {\n const hasActivePage = activePageId !== null;\n const handlePageCounterModeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\n const nextMode = event.target.value;\n if (nextMode === 'none' || nextMode === 'header' || nextMode === 'footer' || nextMode === 'both') {\n onPageCounterModeChange(nextMode);\n }\n };\n\n return (\n <div\n className=\"flex flex-wrap items-center gap-2 text-xs\"\n data-testid=\"header-footer-actions\"\n >\n <label className=\"flex items-center gap-1 text-gray-500\" htmlFor=\"page-counter-mode\">\n <Hash size={13} className=\"text-gray-400\" />\n <select\n id=\"page-counter-mode\"\n className=\"h-6 rounded border border-gray-200 bg-white px-1.5 text-xs text-gray-600\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400\"\n data-testid=\"page-counter-mode\"\n value={pageCounterMode}\n onChange={handlePageCounterModeChange}\n >\n <option value=\"none\">None</option>\n <option value=\"header\">Header</option>\n <option value=\"footer\">Footer</option>\n <option value=\"both\">Both</option>\n </select>\n </label>\n\n <ActionDivider />\n\n <span className=\"text-gray-400 font-medium\">Header</span>\n <ActionIconButton\n title=\"Copy header to all pages\"\n icon={<CopyPlus size={13} />}\n onClick={onCopyHeaderToAll}\n disabled={!hasActivePage}\n testId=\"copy-header-all\"\n />\n <ActionIconButton\n title=\"Clear header on this page\"\n icon={<Eraser size={13} />}\n onClick={onClearHeader}\n disabled={!hasActivePage}\n testId=\"clear-header\"\n />\n <ActionIconButton\n title=\"Clear all headers\"\n icon={<Trash2 size={13} />}\n onClick={onClearAllHeaders}\n testId=\"clear-all-headers\"\n />\n\n <ActionDivider />\n\n <span className=\"text-gray-400 font-medium\">Footer</span>\n <ActionIconButton\n title=\"Copy footer to all pages\"\n icon={<CopyPlus size={13} />}\n onClick={onCopyFooterToAll}\n disabled={!hasActivePage}\n testId=\"copy-footer-all\"\n />\n <ActionIconButton\n title=\"Clear footer on this page\"\n icon={<Eraser size={13} />}\n onClick={onClearFooter}\n disabled={!hasActivePage}\n testId=\"clear-footer\"\n />\n <ActionIconButton\n title=\"Clear all footers\"\n icon={<Trash2 size={13} />}\n onClick={onClearAllFooters}\n testId=\"clear-all-footers\"\n />\n </div>\n );\n};\n\ninterface ActionIconButtonProps {\n title: string;\n icon: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n testId: string;\n}\n\nconst ActionIconButton: React.FC<ActionIconButtonProps> = ({ title, icon, onClick, disabled, testId }) => (\n <button\n type=\"button\"\n title={title}\n aria-label={title}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n disabled={disabled}\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-500 transition-colors\n hover:bg-gray-200/60 hover:text-gray-700\n disabled:cursor-not-allowed disabled:text-gray-300\"\n data-testid={testId}\n >\n {icon}\n </button>\n);\n\nconst ActionDivider: React.FC = () => (\n <div className=\"mx-0.5 h-4 w-px bg-gray-300/60\" />\n);\n","import type { EditorThemeClasses, Klass, LexicalNode } from 'lexical';\nimport type { Lex4Document } from '../types/document';\n\n/**\n * Context passed to extension handleMethods factories.\n * Provides read access to editor state so extensions can build\n * their imperative API methods.\n */\nexport interface ExtensionContext {\n getDocument: () => Lex4Document;\n getActiveEditor: () => import('lexical').LexicalEditor | null;\n getExtensionState: <T = unknown>(key: string) => T | undefined;\n setExtensionState: <T = unknown>(key: string, value: T) => void;\n}\n\n/**\n * Lex4Extension — Plugin-based extension contract.\n *\n * Extensions add capabilities to the editor without requiring\n * hard-wired imports. Each extension can contribute:\n * - Lexical nodes (custom block/inline node types)\n * - Body plugins (rendered inside every page's LexicalComposer)\n * - Toolbar items (rendered in the toolbar extension slot)\n * - Side panels (rendered to the right of the document area)\n * - Provider wrappers (React context providers wrapping the editor)\n * - Imperative handle methods (merged into the ref API)\n */\nexport interface Lex4Extension {\n /** Unique extension name used for identification. */\n name: string;\n\n /** Additional Lexical node classes to register in every editor instance. */\n nodes?: Klass<LexicalNode>[];\n\n /** Plugin components rendered inside each page body's LexicalComposer. */\n bodyPlugins?: React.ComponentType[];\n\n /** Components rendered in the toolbar's extension slot. */\n toolbarItems?: React.ComponentType[];\n\n /** Component rendered as a right side panel. */\n sidePanel?: React.ComponentType;\n\n /**\n * Provider component that wraps the editor tree.\n * Useful for injecting React contexts.\n */\n provider?: React.ComponentType<{ children: React.ReactNode }>;\n\n /**\n * Lexical editor theme overrides contributed by this extension.\n * Merged into the base theme.\n */\n themeOverrides?: Partial<EditorThemeClasses>;\n\n /**\n * Factory that returns imperative handle methods.\n * These are merged into the Lex4EditorHandle exposed via ref.\n */\n handleMethods?: (ctx: ExtensionContext) => Record<string, (...args: never[]) => unknown>;\n}\n\n/**\n * Resolved extension data after processing all extensions.\n * Used internally by the editor to wire everything together.\n */\nexport interface ResolvedExtensions {\n nodes: Klass<LexicalNode>[];\n bodyPlugins: React.ComponentType[];\n toolbarItems: React.ComponentType[];\n sidePanels: React.ComponentType[];\n providers: React.ComponentType<{ children: React.ReactNode }>[];\n themeOverrides: Partial<EditorThemeClasses>;\n handleFactories: Array<(ctx: ExtensionContext) => Record<string, (...args: never[]) => unknown>>;\n}\n\n/**\n * Processes an array of extensions into a single resolved structure.\n */\nexport function resolveExtensions(extensions: Lex4Extension[]): ResolvedExtensions {\n const resolved: ResolvedExtensions = {\n nodes: [],\n bodyPlugins: [],\n toolbarItems: [],\n sidePanels: [],\n providers: [],\n themeOverrides: {},\n handleFactories: [],\n };\n\n for (const ext of extensions) {\n if (ext.nodes) resolved.nodes.push(...ext.nodes);\n if (ext.bodyPlugins) resolved.bodyPlugins.push(...ext.bodyPlugins);\n if (ext.toolbarItems) resolved.toolbarItems.push(...ext.toolbarItems);\n if (ext.sidePanel) resolved.sidePanels.push(ext.sidePanel);\n if (ext.provider) resolved.providers.push(ext.provider);\n if (ext.themeOverrides) {\n resolved.themeOverrides = { ...resolved.themeOverrides, ...ext.themeOverrides };\n }\n if (ext.handleMethods) resolved.handleFactories.push(ext.handleMethods);\n }\n\n return resolved;\n}\n","import React, { createContext, useContext, useMemo, useRef } from 'react';\nimport type { ResolvedExtensions, ExtensionContext } from './types';\nimport { resolveExtensions } from './types';\nimport type { Lex4Extension } from './types';\n\nconst EMPTY_RESOLVED: ResolvedExtensions = {\n nodes: [],\n bodyPlugins: [],\n toolbarItems: [],\n sidePanels: [],\n providers: [],\n themeOverrides: {},\n handleFactories: [],\n};\n\nconst ExtensionResolvedContext = createContext<ResolvedExtensions>(EMPTY_RESOLVED);\n\n/**\n * Provides resolved extension data to all child components.\n * Extensions are resolved once from the extensions array.\n */\nexport const ExtensionProvider: React.FC<{\n extensions?: Lex4Extension[];\n children: React.ReactNode;\n}> = ({ extensions, children }) => {\n const resolved = useMemo(\n () => (extensions && extensions.length > 0 ? resolveExtensions(extensions) : EMPTY_RESOLVED),\n [extensions],\n );\n\n // Wrap children with extension providers (inside-out order)\n let wrapped = <>{children}</>;\n for (let i = resolved.providers.length - 1; i >= 0; i--) {\n const Provider = resolved.providers[i];\n wrapped = <Provider>{wrapped}</Provider>;\n }\n\n return (\n <ExtensionResolvedContext.Provider value={resolved}>\n {wrapped}\n </ExtensionResolvedContext.Provider>\n );\n};\n\n/**\n * Returns the resolved extension data.\n */\nexport function useExtensions(): ResolvedExtensions {\n return useContext(ExtensionResolvedContext);\n}\n\n// --- Extension state store ---\n\nconst ExtensionStateContext = createContext<React.MutableRefObject<Record<string, unknown>> | null>(null);\n\nexport const ExtensionStateProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const stateRef = useRef<Record<string, unknown>>({});\n return (\n <ExtensionStateContext.Provider value={stateRef}>\n {children}\n </ExtensionStateContext.Provider>\n );\n};\n\n/**\n * Hook to get/set extension shared state from any component within the editor tree.\n */\nexport function useExtensionState() {\n const stateRef = useContext(ExtensionStateContext);\n return {\n get: <T = unknown>(key: string): T | undefined => stateRef?.current[key] as T | undefined,\n set: <T = unknown>(key: string, value: T) => {\n if (stateRef) stateRef.current[key] = value;\n },\n };\n}\n\n/**\n * Builds an ExtensionContext for handle method factories.\n */\nexport function useExtensionContext(\n getDocument: ExtensionContext['getDocument'],\n getActiveEditor: ExtensionContext['getActiveEditor'],\n): ExtensionContext {\n const stateRef = useContext(ExtensionStateContext);\n\n return useMemo(() => ({\n getDocument,\n getActiveEditor,\n getExtensionState: <T = unknown>(key: string) => stateRef?.current[key] as T | undefined,\n setExtensionState: <T = unknown>(key: string, value: T) => {\n if (stateRef) stateRef.current[key] = value;\n },\n }), [getDocument, getActiveEditor, stateRef]);\n}\n","import React, { useCallback, useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n COMMAND_PRIORITY_LOW,\n SELECTION_CHANGE_COMMAND,\n type LexicalEditor,\n} from 'lexical';\n\nconst SUPPORTED_FONTS = [\n 'Inter',\n 'Times New Roman',\n 'Arial',\n 'Calibri',\n 'Georgia',\n 'Courier New',\n] as const;\n\nexport type FontFamily = (typeof SUPPORTED_FONTS)[number];\n\nexport { SUPPORTED_FONTS };\n\n/**\n * Applies a font family to the current text selection by setting\n * inline CSS style on each selected text node.\n */\nexport function applyFontFamily(editor: LexicalEditor, fontFamily: FontFamily): void {\n editor.update(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const nodes = selection.getNodes();\n for (const node of nodes) {\n if ($isTextNode(node)) {\n node.setStyle(`font-family: ${fontFamily}`);\n }\n }\n });\n}\n\ninterface FontPluginProps {\n onFontChange?: (font: string) => void;\n}\n\n/**\n * FontPlugin — tracks the current selection's font and exposes a callback\n * for the toolbar to display the active font.\n */\nexport const FontPlugin: React.FC<FontPluginProps> = ({ onFontChange }) => {\n const [editor] = useLexicalComposerContext();\n\n const reportFont = useCallback(() => {\n editor.getEditorState().read(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const node = selection.getNodes()[0];\n if ($isTextNode(node)) {\n const style = node.getStyle();\n const match = style.match(/font-family:\\s*([^;]+)/);\n onFontChange?.(match ? match[1].trim() : 'Arial');\n }\n });\n }, [editor, onFontChange]);\n\n useEffect(() => {\n return editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n reportFont();\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [editor, reportFont]);\n\n return null;\n};\n","import { useCallback, useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n COMMAND_PRIORITY_LOW,\n SELECTION_CHANGE_COMMAND,\n type LexicalEditor,\n} from 'lexical';\n\nexport const SUPPORTED_FONT_SIZES = [\n 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72,\n] as const;\n\nexport type FontSize = (typeof SUPPORTED_FONT_SIZES)[number];\n\nexport const DEFAULT_FONT_SIZE: FontSize = 12;\n\n/**\n * Applies a font size to the current text selection by merging\n * into the existing inline CSS style on each selected text node.\n */\nexport function applyFontSize(editor: LexicalEditor, size: FontSize): void {\n editor.update(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const nodes = selection.getNodes();\n for (const node of nodes) {\n if ($isTextNode(node)) {\n const existing = node.getStyle();\n const updated = mergeFontSize(existing, size);\n node.setStyle(updated);\n }\n }\n });\n}\n\nfunction mergeFontSize(existingStyle: string, size: FontSize): string {\n const stripped = existingStyle.replace(/font-size:\\s*[^;]+;?\\s*/g, '').trim();\n const sizeDecl = `font-size: ${size}pt`;\n return stripped ? `${stripped}; ${sizeDecl}` : sizeDecl;\n}\n\nfunction extractFontSize(style: string): number | null {\n const match = style.match(/font-size:\\s*(\\d+(?:\\.\\d+)?)\\s*pt/);\n return match ? parseFloat(match[1]) : null;\n}\n\ninterface FontSizePluginProps {\n onFontSizeChange?: (size: number) => void;\n}\n\n/**\n * FontSizePlugin — tracks the current selection's font size\n * and exposes a callback for the toolbar to display the active size.\n */\nexport const FontSizePlugin: React.FC<FontSizePluginProps> = ({ onFontSizeChange }) => {\n const [editor] = useLexicalComposerContext();\n\n const reportFontSize = useCallback(() => {\n editor.getEditorState().read(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const node = selection.getNodes()[0];\n if ($isTextNode(node)) {\n const style = node.getStyle();\n const size = extractFontSize(style);\n onFontSizeChange?.(size ?? DEFAULT_FONT_SIZE);\n }\n });\n }, [editor, onFontSizeChange]);\n\n useEffect(() => {\n return editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n reportFontSize();\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [editor, reportFontSize]);\n\n return null;\n};\n","import {\n FORMAT_TEXT_COMMAND,\n type LexicalEditor,\n type TextFormatType,\n} from 'lexical';\nimport { FORMAT_ELEMENT_COMMAND, type ElementFormatType } from 'lexical';\n\n/**\n * Dispatches a text formatting command to the given Lexical editor.\n */\nexport function toggleFormat(editor: LexicalEditor, format: TextFormatType): void {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);\n}\n\nexport function toggleBold(editor: LexicalEditor): void {\n toggleFormat(editor, 'bold');\n}\n\nexport function toggleItalic(editor: LexicalEditor): void {\n toggleFormat(editor, 'italic');\n}\n\nexport function toggleUnderline(editor: LexicalEditor): void {\n toggleFormat(editor, 'underline');\n}\n\nexport function toggleStrikethrough(editor: LexicalEditor): void {\n toggleFormat(editor, 'strikethrough');\n}\n\n/**\n * Dispatches an element alignment command.\n */\nexport function setAlignment(editor: LexicalEditor, alignment: ElementFormatType): void {\n editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, alignment);\n}\n","import {\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list';\nimport {\n INDENT_CONTENT_COMMAND,\n OUTDENT_CONTENT_COMMAND,\n type LexicalEditor,\n} from 'lexical';\n\nexport type ListType = 'number' | 'bullet';\n\n/**\n * Inserts a list of the given type into the editor.\n */\nexport function insertList(editor: LexicalEditor, type: ListType): void {\n if (type === 'number') {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n }\n}\n\n/**\n * Removes the current list formatting.\n */\nexport function removeList(editor: LexicalEditor): void {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n}\n\n/**\n * Indents the current selection.\n *\n * Paragraphs are rendered as first-line indents by the paragraph indent plugin,\n * while list items keep Lexical's native nesting behavior.\n */\nexport function indentContent(editor: LexicalEditor): void {\n editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined);\n}\n\n/**\n * Outdents the current selection.\n *\n * Paragraphs are rendered as first-line indents by the paragraph indent plugin,\n * while list items keep Lexical's native un-nesting behavior.\n */\nexport function outdentContent(editor: LexicalEditor): void {\n editor.dispatchCommand(OUTDENT_CONTENT_COMMAND, undefined);\n}\n","import React, { useCallback } from 'react';\nimport { $selectAll, type LexicalEditor } from 'lexical';\nimport {\n Undo2,\n Redo2,\n Bold,\n Italic,\n Underline,\n Strikethrough,\n AlignLeft,\n AlignCenter,\n AlignRight,\n AlignJustify,\n ListOrdered,\n List,\n IndentIncrease,\n IndentDecrease,\n PanelRight,\n} from 'lucide-react';\nimport { useDocument } from '../context/document-context';\nimport { HeaderFooterToggle } from './HeaderFooterToggle';\nimport { HeaderFooterActions } from './HeaderFooterActions';\nimport { useExtensions } from '../extensions/extension-context';\nimport { useTranslations, interpolate } from '../i18n';\nimport type { PageCounterMode } from '../types/document';\nimport { SUPPORTED_FONTS } from '../lexical/plugins/font-plugin';\nimport { applyFontFamily, type FontFamily } from '../lexical/plugins/font-plugin';\nimport { applyFontSize, SUPPORTED_FONT_SIZES, type FontSize } from '../lexical/plugins/font-size-plugin';\nimport { toggleBold, toggleItalic, toggleUnderline, toggleStrikethrough, setAlignment } from '../lexical/commands/format-commands';\nimport { insertList, indentContent, outdentContent } from '../lexical/commands/list-commands';\nimport { debug } from '../utils/debug';\n\nexport const Toolbar: React.FC = () => {\n const {\n document,\n dispatch,\n activePageId,\n activeEditor,\n canRedo,\n canUndo,\n editorRegistry,\n globalSelectionActive,\n historySidebarOpen,\n redo,\n runHistoryAction,\n setHistorySidebarOpen,\n undo,\n } = useDocument();\n const { toolbarItems } = useExtensions();\n const t = useTranslations();\n\n const withBodySelection = useCallback(\n (editor: LexicalEditor, action: (targetEditor: LexicalEditor) => void) => {\n editor.update(() => {\n $selectAll();\n });\n action(editor);\n },\n [],\n );\n\n const applyToBodyEditors = useCallback(\n (action: (targetEditor: LexicalEditor) => void) => {\n const targetEditors = globalSelectionActive\n ? editorRegistry.all()\n : activeEditor\n ? [activeEditor]\n : [];\n\n targetEditors.forEach(editor => {\n if (globalSelectionActive) {\n withBodySelection(editor, action);\n } else {\n action(editor);\n }\n });\n },\n [activeEditor, editorRegistry, globalSelectionActive, withBodySelection],\n );\n\n const runToolbarAction = useCallback(\n (label: string, callback: () => void) => {\n runHistoryAction(\n {\n label,\n source: 'toolbar',\n region: 'document',\n },\n callback,\n );\n },\n [runHistoryAction],\n );\n\n const handleToggle = (enabled: boolean) => {\n runToolbarAction(\n enabled ? t.history.actions.enabledHeadersFooters : t.history.actions.disabledHeadersFooters,\n () => {\n dispatch({ type: 'SET_HEADER_FOOTER_ENABLED', enabled });\n },\n );\n };\n\n const handleCopyHeaderToAll = () => {\n if (activePageId) {\n runToolbarAction(t.history.actions.copiedHeaderToAll, () => {\n dispatch({ type: 'COPY_HEADER_TO_ALL', sourcePageId: activePageId });\n });\n }\n };\n const handleCopyFooterToAll = () => {\n if (activePageId) {\n runToolbarAction(t.history.actions.copiedFooterToAll, () => {\n dispatch({ type: 'COPY_FOOTER_TO_ALL', sourcePageId: activePageId });\n });\n }\n };\n const handleClearHeader = () => {\n if (activePageId) {\n runToolbarAction(t.history.actions.clearedHeader, () => {\n dispatch({ type: 'CLEAR_HEADER', pageId: activePageId });\n });\n }\n };\n const handleClearFooter = () => {\n if (activePageId) {\n runToolbarAction(t.history.actions.clearedFooter, () => {\n dispatch({ type: 'CLEAR_FOOTER', pageId: activePageId });\n });\n }\n };\n const handleClearAllHeaders = () => runToolbarAction(t.history.actions.clearedAllHeaders, () => {\n dispatch({ type: 'CLEAR_ALL_HEADERS' });\n });\n const handleClearAllFooters = () => runToolbarAction(t.history.actions.clearedAllFooters, () => {\n dispatch({ type: 'CLEAR_ALL_FOOTERS' });\n });\n const handlePageCounterModeChange = useCallback((mode: PageCounterMode) => {\n runToolbarAction(interpolate(t.history.actions.pageCounterSet, { value: mode }), () => {\n dispatch({ type: 'SET_PAGE_COUNTER_MODE', mode });\n });\n }, [dispatch, runToolbarAction, t.history.actions.pageCounterSet]);\n\n const handleBold = useCallback(() => {\n debug('toolbar', `bold (globalSelection=${globalSelectionActive}, editors=${editorRegistry.all().length}, hasEditor=${!!activeEditor})`);\n runToolbarAction(t.history.actions.boldApplied, () => {\n applyToBodyEditors(toggleBold);\n });\n }, [activeEditor, applyToBodyEditors, editorRegistry, globalSelectionActive, runToolbarAction, t.history.actions.boldApplied]);\n\n const handleItalic = useCallback(() => {\n debug('toolbar', `italic (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);\n runToolbarAction(t.history.actions.italicApplied, () => {\n applyToBodyEditors(toggleItalic);\n });\n }, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction, t.history.actions.italicApplied]);\n\n const handleUnderline = useCallback(() => {\n debug('toolbar', `underline (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);\n runToolbarAction(t.history.actions.underlineApplied, () => {\n applyToBodyEditors(toggleUnderline);\n });\n }, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction, t.history.actions.underlineApplied]);\n\n const handleStrikethrough = useCallback(() => {\n debug('toolbar', `strikethrough (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);\n runToolbarAction(t.history.actions.strikethroughApplied, () => {\n applyToBodyEditors(toggleStrikethrough);\n });\n }, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction, t.history.actions.strikethroughApplied]);\n\n const handleAlignLeft = useCallback(() => {\n runToolbarAction(t.history.actions.alignedLeft, () => {\n applyToBodyEditors(editor => setAlignment(editor, 'left'));\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.alignedLeft]);\n\n const handleAlignCenter = useCallback(() => {\n runToolbarAction(t.history.actions.alignedCenter, () => {\n applyToBodyEditors(editor => setAlignment(editor, 'center'));\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.alignedCenter]);\n\n const handleAlignRight = useCallback(() => {\n runToolbarAction(t.history.actions.alignedRight, () => {\n applyToBodyEditors(editor => setAlignment(editor, 'right'));\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.alignedRight]);\n\n const handleAlignJustify = useCallback(() => {\n runToolbarAction(t.history.actions.justifiedText, () => {\n applyToBodyEditors(editor => setAlignment(editor, 'justify'));\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.justifiedText]);\n\n const handleListNumber = useCallback(() => {\n runToolbarAction(t.history.actions.insertedNumberedList, () => {\n applyToBodyEditors(editor => insertList(editor, 'number'));\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.insertedNumberedList]);\n\n const handleListBullet = useCallback(() => {\n runToolbarAction(t.history.actions.insertedBulletList, () => {\n applyToBodyEditors(editor => insertList(editor, 'bullet'));\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.insertedBulletList]);\n\n const handleIndent = useCallback(() => {\n runToolbarAction(t.history.actions.indentedContent, () => {\n applyToBodyEditors(indentContent);\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.indentedContent]);\n\n const handleOutdent = useCallback(() => {\n runToolbarAction(t.history.actions.outdentedContent, () => {\n applyToBodyEditors(outdentContent);\n });\n }, [applyToBodyEditors, runToolbarAction, t.history.actions.outdentedContent]);\n\n const handleFontChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n runToolbarAction(interpolate(t.history.actions.fontChanged, { value: e.target.value }), () => {\n applyToBodyEditors(editor => applyFontFamily(editor, e.target.value as FontFamily));\n });\n },\n [applyToBodyEditors, runToolbarAction, t.history.actions.fontChanged],\n );\n\n const handleFontSizeChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n const size = parseInt(e.target.value, 10) as FontSize;\n runToolbarAction(interpolate(t.history.actions.fontSizeChanged, { value: String(size) }), () => {\n applyToBodyEditors(editor => applyFontSize(editor, size));\n });\n },\n [applyToBodyEditors, runToolbarAction, t.history.actions.fontSizeChanged],\n );\n\n return (\n <div\n className=\"lex4-toolbar sticky top-0 z-10 bg-white border-b border-gray-200\"\n data-testid=\"toolbar\"\n >\n <div className=\"flex items-center gap-1 px-2 py-1.5\">\n <div className=\"flex items-center gap-0.5\" data-testid=\"history-controls\">\n <ToolbarIconButton\n title={t.toolbar.undo}\n testId=\"btn-undo\"\n disabled={!canUndo}\n onClick={undo}\n >\n <Undo2 size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton\n title={t.toolbar.redo}\n testId=\"btn-redo\"\n disabled={!canRedo}\n onClick={redo}\n >\n <Redo2 size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <select\n className=\"h-7 rounded border border-gray-200 bg-white px-2 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400\"\n data-testid=\"font-selector\"\n defaultValue=\"Inter\"\n onChange={handleFontChange}\n >\n {SUPPORTED_FONTS.map(font => (\n <option key={font} value={font} style={{ fontFamily: font }}>\n {font}\n </option>\n ))}\n </select>\n\n <select\n className=\"h-7 w-16 rounded border border-gray-200 bg-white px-1 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400\"\n data-testid=\"font-size-selector\"\n defaultValue=\"12\"\n onChange={handleFontSizeChange}\n >\n {SUPPORTED_FONT_SIZES.map(size => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n\n <Divider />\n\n <div className=\"flex items-center gap-0.5\" data-testid=\"format-group\">\n <ToolbarIconButton title={t.toolbar.bold} testId=\"btn-bold\" onClick={handleBold}>\n <Bold size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.italic} testId=\"btn-italic\" onClick={handleItalic}>\n <Italic size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.underline} testId=\"btn-underline\" onClick={handleUnderline}>\n <Underline size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.strikethrough} testId=\"btn-strike\" onClick={handleStrikethrough}>\n <Strikethrough size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <div className=\"flex items-center gap-0.5\" data-testid=\"align-group\">\n <ToolbarIconButton title={t.toolbar.alignLeft} testId=\"btn-align-left\" onClick={handleAlignLeft}>\n <AlignLeft size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.alignCenter} testId=\"btn-align-center\" onClick={handleAlignCenter}>\n <AlignCenter size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.alignRight} testId=\"btn-align-right\" onClick={handleAlignRight}>\n <AlignRight size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.justify} testId=\"btn-align-justify\" onClick={handleAlignJustify}>\n <AlignJustify size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <div className=\"flex items-center gap-0.5\" data-testid=\"list-group\">\n <ToolbarIconButton title={t.toolbar.numberedList} testId=\"btn-list-number\" onClick={handleListNumber}>\n <ListOrdered size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.bulletList} testId=\"btn-list-bullet\" onClick={handleListBullet}>\n <List size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.indent} testId=\"btn-indent\" onClick={handleIndent}>\n <IndentIncrease size={15} />\n </ToolbarIconButton>\n <ToolbarIconButton title={t.toolbar.outdent} testId=\"btn-outdent\" onClick={handleOutdent}>\n <IndentDecrease size={15} />\n </ToolbarIconButton>\n </div>\n\n <Divider />\n\n <HeaderFooterToggle\n enabled={document.headerFooterEnabled}\n onToggle={handleToggle}\n />\n\n {document.headerFooterEnabled && (\n <>\n <Divider />\n <HeaderFooterActions\n activePageId={activePageId}\n pageCounterMode={document.pageCounterMode}\n onPageCounterModeChange={handlePageCounterModeChange}\n onCopyHeaderToAll={handleCopyHeaderToAll}\n onCopyFooterToAll={handleCopyFooterToAll}\n onClearHeader={handleClearHeader}\n onClearFooter={handleClearFooter}\n onClearAllHeaders={handleClearAllHeaders}\n onClearAllFooters={handleClearAllFooters}\n />\n </>\n )}\n\n {toolbarItems.length > 0 && (\n <>\n <Divider />\n {toolbarItems.map((ToolbarItem, idx) => (\n <ToolbarItem key={idx} />\n ))}\n </>\n )}\n\n <div className=\"ml-auto flex items-center\">\n <ToolbarIconButton\n title={historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory}\n testId=\"toggle-history-sidebar\"\n active={historySidebarOpen}\n onClick={() => setHistorySidebarOpen(!historySidebarOpen)}\n >\n <PanelRight size={15} />\n </ToolbarIconButton>\n </div>\n </div>\n </div>\n );\n};\n\ninterface ToolbarIconButtonProps {\n title: string;\n testId: string;\n disabled?: boolean;\n active?: boolean;\n onClick?: () => void;\n children: React.ReactNode;\n}\n\nconst ToolbarIconButton: React.FC<ToolbarIconButtonProps> = ({\n title,\n testId,\n disabled = false,\n active = false,\n onClick,\n children,\n}) => (\n <button\n type=\"button\"\n title={title}\n aria-label={title}\n disabled={disabled}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n className={`\n flex h-7 w-7 items-center justify-center rounded transition-colors\n ${disabled\n ? 'cursor-not-allowed text-gray-300'\n : active\n ? 'bg-blue-50 text-blue-600'\n : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'}\n `}\n data-testid={testId}\n >\n {children}\n </button>\n);\n\nconst Divider: React.FC = () => (\n <div className=\"mx-0.5 h-5 w-px bg-gray-200\" />\n);","import {\n A4_HEIGHT_PX,\n PAGE_MARGIN_PX,\n} from './dimensions';\n\n/**\n * Computes the available body height for a page, accounting for\n * header/footer heights and page margins.\n */\nexport function computeBodyHeight(\n headerHeight: number,\n footerHeight: number,\n): number {\n const verticalMargins = PAGE_MARGIN_PX * 2;\n return A4_HEIGHT_PX - headerHeight - footerHeight - verticalMargins;\n}\n\n/**\n * Computes the content area height based on whether\n * headers/footers are enabled.\n */\nexport function computeContentAreaHeight(\n headerFooterEnabled: boolean,\n headerHeight: number,\n footerHeight: number,\n): number {\n if (!headerFooterEnabled) {\n return computeBodyHeight(0, 0);\n }\n return computeBodyHeight(headerHeight, footerHeight);\n}\n","import type { SerializedEditorState, SerializedLexicalNode } from 'lexical';\n\n/**\n * Utilities for splitting and merging Lexical editor states.\n *\n * A SerializedEditorState has shape:\n * { root: { children: [...], type: \"root\", ... } }\n *\n * Content flow between pages is achieved by manipulating\n * the root.children array — extracting, splitting, merging\n * top-level block nodes.\n */\n\n/** Extract all top-level nodes from a serialized editor state */\nexport function getTopLevelNodes(state: SerializedEditorState | null): SerializedLexicalNode[] {\n if (!state) return [];\n return (state.root as any).children ?? [];\n}\n\n/** Count top-level nodes in a serialized editor state */\nexport function countTopLevelNodes(state: SerializedEditorState | null): number {\n return getTopLevelNodes(state).length;\n}\n\n/**\n * Create a SerializedEditorState from a list of top-level nodes.\n * Uses a standard root wrapper.\n */\nexport function createEditorStateFromNodes(\n nodes: SerializedLexicalNode[],\n): SerializedEditorState {\n return {\n root: {\n children: nodes,\n direction: null,\n format: '',\n indent: 0,\n type: 'root',\n version: 1,\n },\n } as SerializedEditorState;\n}\n\n/**\n * Split a serialized editor state at a given node index.\n *\n * Returns [before, after] where:\n * - before contains nodes 0..splitIndex-1\n * - after contains nodes splitIndex..end\n */\nexport function splitEditorState(\n state: SerializedEditorState | null,\n splitIndex: number,\n): [SerializedEditorState | null, SerializedEditorState | null] {\n const nodes = getTopLevelNodes(state);\n\n if (splitIndex <= 0) {\n return [null, state];\n }\n if (splitIndex >= nodes.length) {\n return [state, null];\n }\n\n const before = nodes.slice(0, splitIndex);\n const after = nodes.slice(splitIndex);\n\n return [\n before.length > 0 ? createEditorStateFromNodes(before) : null,\n after.length > 0 ? createEditorStateFromNodes(after) : null,\n ];\n}\n\n/**\n * Merge two serialized editor states by concatenating their top-level nodes.\n * Returns a new state with all nodes from both states.\n */\nexport function mergeEditorStates(\n stateA: SerializedEditorState | null,\n stateB: SerializedEditorState | null,\n): SerializedEditorState | null {\n const nodesA = getTopLevelNodes(stateA);\n const nodesB = getTopLevelNodes(stateB);\n\n const all = [...nodesA, ...nodesB];\n if (all.length === 0) return null;\n\n return createEditorStateFromNodes(all);\n}\n\n/**\n * Append nodes to the end of a serialized editor state.\n */\nexport function appendNodes(\n state: SerializedEditorState | null,\n nodes: SerializedLexicalNode[],\n): SerializedEditorState {\n const existing = getTopLevelNodes(state);\n return createEditorStateFromNodes([...existing, ...nodes]);\n}\n\n/**\n * Remove the last N nodes from a serialized editor state.\n * Returns [trimmedState, removedNodes].\n */\nexport function removeLastNodes(\n state: SerializedEditorState | null,\n count: number,\n): [SerializedEditorState | null, SerializedLexicalNode[]] {\n const nodes = getTopLevelNodes(state);\n if (count >= nodes.length) {\n return [null, [...nodes]];\n }\n\n const kept = nodes.slice(0, nodes.length - count);\n const removed = nodes.slice(nodes.length - count);\n\n return [\n kept.length > 0 ? createEditorStateFromNodes(kept) : null,\n removed,\n ];\n}\n\n/**\n * Remove the first N nodes from a serialized editor state.\n * Returns [removedNodes, remainingState].\n */\nexport function removeFirstNodes(\n state: SerializedEditorState | null,\n count: number,\n): [SerializedLexicalNode[], SerializedEditorState | null] {\n const nodes = getTopLevelNodes(state);\n if (count >= nodes.length) {\n return [[...nodes], null];\n }\n\n const removed = nodes.slice(0, count);\n const remaining = nodes.slice(count);\n\n return [\n removed,\n remaining.length > 0 ? createEditorStateFromNodes(remaining) : null,\n ];\n}\n","import { useCallback, useRef } from 'react';\nimport type { SerializedEditorState } from 'lexical';\nimport type { DocumentAction } from '../context/document-context';\nimport { computeBodyHeight } from '../constants/page-layout';\nimport {\n getTopLevelNodes,\n splitEditorState,\n mergeEditorStates,\n createEditorStateFromNodes,\n} from '../utils/editor-state-utils';\nimport type { Lex4Document, PageState } from '../types/document';\nimport { createEmptyPage, createPageFromTemplate } from '../types/document';\n\n/**\n * usePagination — Orchestrates content flow between pages.\n *\n * When a page body overflows, this hook:\n * 1. Measures which nodes fit within the body height\n * 2. Splits the editor state at the overflow point\n * 3. Moves overflow content to the next page (creating it if needed)\n * 4. Cascades forward through all subsequent pages\n *\n * When a page body underflows (content deleted), it:\n * 1. Checks if the next page has content that fits\n * 2. Pulls content back from the next page\n * 3. Removes empty trailing pages\n */\nexport function usePagination(\n document: Lex4Document,\n dispatch: React.Dispatch<DocumentAction>,\n) {\n const reflowingRef = useRef(false);\n const pendingReflowRef = useRef(false);\n\n /**\n * Estimate how many top-level nodes fit within a given pixel height.\n *\n * Since we don't have DOM measurements at this point (the nodes may not\n * be rendered yet), we use a heuristic: assume each top-level paragraph\n * is approximately 24px (one line of text). This is imperfect but\n * provides a reasonable starting split point. The ResizeObserver in\n * PageBody will trigger another reflow if the estimate was wrong.\n */\n const estimateNodesFitting = useCallback(\n (\n state: SerializedEditorState | null,\n bodyHeight: number,\n ): number => {\n const nodes = getTopLevelNodes(state);\n if (nodes.length === 0) return 0;\n\n const estimatedLineHeight = 24;\n let usedHeight = 0;\n let fitCount = 0;\n\n for (const _node of nodes) {\n usedHeight += estimatedLineHeight;\n if (usedHeight > bodyHeight) break;\n fitCount++;\n }\n\n // At least one node must stay on the current page\n return Math.max(1, fitCount);\n },\n [],\n );\n\n /**\n * Handle overflow on a specific page.\n * Splits content and pushes overflow to the next page.\n */\n const handlePageOverflow = useCallback(\n (pageIndex: number) => {\n if (reflowingRef.current) {\n pendingReflowRef.current = true;\n return;\n }\n\n reflowingRef.current = true;\n\n try {\n const pages = document.pages;\n const page = pages[pageIndex];\n if (!page) return;\n\n const headerH = document.headerFooterEnabled ? page.headerHeight : 0;\n const footerH = document.headerFooterEnabled ? page.footerHeight : 0;\n const bodyHeight = computeBodyHeight(headerH, footerH);\n\n const nodes = getTopLevelNodes(page.bodyState);\n if (nodes.length <= 1) return; // Can't split a single node\n\n const fitCount = estimateNodesFitting(page.bodyState, bodyHeight);\n if (fitCount >= nodes.length) return; // Everything fits\n\n const [keepState, overflowState] = splitEditorState(page.bodyState, fitCount);\n\n if (!overflowState) return; // Nothing to overflow\n\n // Get or create the next page\n const nextPage = pages[pageIndex + 1];\n if (nextPage) {\n // Merge overflow into the beginning of the next page\n const mergedBody = mergeEditorStates(overflowState, nextPage.bodyState);\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: pages.map((p, i) => {\n if (i === pageIndex) return { ...p, bodyState: keepState };\n if (i === pageIndex + 1) return { ...p, bodyState: mergedBody };\n return p;\n }),\n },\n });\n } else {\n // Create a new page with overflow content\n const newPage: PageState = {\n ...createPageFromTemplate({\n headerState: document.defaultHeaderState,\n footerState: document.defaultFooterState,\n headerHeight: document.defaultHeaderHeight,\n footerHeight: document.defaultFooterHeight,\n }),\n bodyState: overflowState,\n };\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: [\n ...pages.map((p, i) =>\n i === pageIndex ? { ...p, bodyState: keepState } : p,\n ),\n newPage,\n ],\n },\n });\n }\n } finally {\n reflowingRef.current = false;\n\n if (pendingReflowRef.current) {\n pendingReflowRef.current = false;\n // Schedule another reflow on next tick\n setTimeout(() => handlePageOverflow(pageIndex), 0);\n }\n }\n },\n [document, dispatch, estimateNodesFitting],\n );\n\n /**\n * Handle underflow — try to pull content from the next page.\n */\n const handlePageUnderflow = useCallback(\n (pageIndex: number) => {\n if (reflowingRef.current) return;\n\n const pages = document.pages;\n const page = pages[pageIndex];\n const nextPage = pages[pageIndex + 1];\n\n if (!page || !nextPage) return;\n\n const nextNodes = getTopLevelNodes(nextPage.bodyState);\n if (nextNodes.length === 0) {\n // Next page is empty — remove it (unless it's the only page)\n if (pages.length > 1) {\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: pages.filter((_, i) => i !== pageIndex + 1),\n },\n });\n }\n return;\n }\n\n // Try to pull the first node from the next page\n const headerH = document.headerFooterEnabled ? page.headerHeight : 0;\n const footerH = document.headerFooterEnabled ? page.footerHeight : 0;\n const bodyHeight = computeBodyHeight(headerH, footerH);\n\n const currentNodes = getTopLevelNodes(page.bodyState);\n const estimatedCurrentHeight = currentNodes.length * 24;\n const remainingSpace = bodyHeight - estimatedCurrentHeight;\n\n if (remainingSpace > 24) {\n // Pull the first node from next page\n const [pulled, remaining] = [nextNodes.slice(0, 1), nextNodes.slice(1)];\n\n const updatedCurrent = mergeEditorStates(\n page.bodyState,\n createEditorStateFromNodes(pulled),\n );\n const updatedNext =\n remaining.length > 0 ? createEditorStateFromNodes(remaining) : null;\n\n const newPages = pages.map((p, i) => {\n if (i === pageIndex) return { ...p, bodyState: updatedCurrent };\n if (i === pageIndex + 1) return { ...p, bodyState: updatedNext };\n return p;\n });\n\n // Remove empty trailing pages\n while (newPages.length > 1) {\n const last = newPages[newPages.length - 1];\n if (getTopLevelNodes(last.bodyState).length === 0) {\n newPages.pop();\n } else {\n break;\n }\n }\n\n dispatch({\n type: 'SET_DOCUMENT',\n document: { ...document, pages: newPages },\n });\n }\n },\n [document, dispatch],\n );\n\n /**\n * Full document reflow — recalculate all pages from scratch.\n * Used after toggle changes or major content operations.\n */\n const reflowAll = useCallback(() => {\n if (reflowingRef.current) return;\n reflowingRef.current = true;\n\n try {\n const pages = document.pages;\n\n // Collect all body content across all pages\n const allNodes = pages.flatMap(p => getTopLevelNodes(p.bodyState));\n if (allNodes.length === 0) {\n // Ensure at least one page\n if (pages.length !== 1) {\n dispatch({\n type: 'SET_DOCUMENT',\n document: {\n ...document,\n pages: [pages[0] ?? createEmptyPage()],\n },\n });\n }\n return;\n }\n\n // Distribute nodes across pages\n const newPages: PageState[] = [];\n let remainingNodes = [...allNodes];\n let pageIdx = 0;\n\n while (remainingNodes.length > 0) {\n const existingPage = pages[pageIdx];\n const headerH = document.headerFooterEnabled\n ? (existingPage?.headerHeight ?? 0)\n : 0;\n const footerH = document.headerFooterEnabled\n ? (existingPage?.footerHeight ?? 0)\n : 0;\n const bodyHeight = computeBodyHeight(headerH, footerH);\n const estimatedLineHeight = 24;\n const maxNodes = Math.max(1, Math.floor(bodyHeight / estimatedLineHeight));\n\n const pageNodes = remainingNodes.slice(0, maxNodes);\n remainingNodes = remainingNodes.slice(maxNodes);\n\n const basePage = existingPage ?? createPageFromTemplate({\n headerState: document.defaultHeaderState,\n footerState: document.defaultFooterState,\n headerHeight: document.defaultHeaderHeight,\n footerHeight: document.defaultFooterHeight,\n });\n newPages.push({\n ...basePage,\n bodyState: createEditorStateFromNodes(pageNodes),\n });\n\n pageIdx++;\n }\n\n dispatch({\n type: 'SET_DOCUMENT',\n document: { ...document, pages: newPages },\n });\n } finally {\n reflowingRef.current = false;\n }\n }, [document, dispatch]);\n\n return {\n handlePageOverflow,\n handlePageUnderflow,\n reflowAll,\n };\n}\n","import type { EditorThemeClasses } from 'lexical';\n\n/**\n * Lexical theme configuration — maps Lexical CSS class names\n * to Tailwind-compatible class strings for consistent styling.\n */\nexport const lexicalTheme: EditorThemeClasses = {\n root: 'lex4-root outline-none',\n paragraph: 'lex4-paragraph mb-1',\n heading: {\n h1: 'text-3xl font-bold mb-2',\n h2: 'text-2xl font-bold mb-2',\n h3: 'text-xl font-semibold mb-1',\n h4: 'text-lg font-semibold mb-1',\n h5: 'text-base font-medium mb-1',\n },\n text: {\n bold: 'font-bold',\n italic: 'italic',\n underline: 'underline',\n strikethrough: 'line-through',\n underlineStrikethrough: 'underline line-through',\n },\n list: {\n nested: {\n listitem: 'list-none',\n },\n ol: 'list-decimal ml-6',\n ul: 'list-disc ml-6',\n listitem: 'lex4-listitem',\n listitemChecked: 'lex4-listitem-checked',\n listitemUnchecked: 'lex4-listitem-unchecked',\n },\n quote: 'border-l-4 border-gray-300 pl-4 italic text-gray-600',\n};\n","import type { InitialConfigType } from '@lexical/react/LexicalComposer';\nimport type { EditorThemeClasses, Klass, LexicalNode } from 'lexical';\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text';\nimport { ListNode, ListItemNode } from '@lexical/list';\n\nimport { lexicalTheme } from './theme';\n\nexport type EditorMode = 'body' | 'header' | 'footer';\n\nconst DEFAULT_NODES: Klass<LexicalNode>[] = [HeadingNode, QuoteNode, ListNode, ListItemNode];\n\n/**\n * Creates a Lexical editor configuration for the given mode.\n *\n * Each mode gets its own namespace to avoid conflicts when\n * multiple Lexical editors coexist on the same page.\n *\n * @param extraNodes - Additional node classes contributed by extensions\n * @param themeOverrides - Theme class overrides from extensions\n */\nexport function createEditorConfig(\n mode: EditorMode,\n pageId?: string,\n extraNodes: Klass<LexicalNode>[] = [],\n themeOverrides: Partial<EditorThemeClasses> = {},\n): InitialConfigType {\n const namespace = pageId ? `lex4-${mode}-${pageId}` : `lex4-${mode}`;\n\n return {\n namespace,\n theme: { ...lexicalTheme, ...themeOverrides },\n nodes: [...DEFAULT_NODES, ...extraNodes],\n onError: (error: Error) => {\n console.error(`[Lex4 ${mode} editor error]`, error);\n },\n };\n}\n","import React, { useCallback } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { COMMAND_PRIORITY_LOW, KEY_TAB_COMMAND } from 'lexical';\nimport { indentContent, outdentContent } from '../commands/list-commands';\n\n/**\n * TabIndentPlugin — handles Tab and Shift+Tab for indentation shortcuts.\n *\n * List items use Lexical's native nesting behavior. Regular paragraphs use the\n * editor's first-line indent behavior.\n */\nexport const TabIndentPlugin: React.FC = () => {\n const [editor] = useLexicalComposerContext();\n\n const handleTab = useCallback(\n (event: KeyboardEvent) => {\n event.preventDefault();\n if (event.shiftKey) {\n outdentContent(editor);\n } else {\n indentContent(editor);\n }\n return true;\n },\n [editor],\n );\n\n React.useEffect(() => {\n return editor.registerCommand(KEY_TAB_COMMAND, handleTab, COMMAND_PRIORITY_LOW);\n }, [editor, handleTab]);\n\n return null;\n};\n","import React, { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { $getRoot, $isElementNode, $isParagraphNode, type ElementNode } from 'lexical';\n\nconst FIRST_LINE_INDENT_PX = 40;\n\nfunction visitElements(node: ElementNode, callback: (element: ElementNode) => void): void {\n callback(node);\n\n for (const child of node.getChildren()) {\n if ($isElementNode(child)) {\n visitElements(child, callback);\n }\n }\n}\n\n/**\n * Applies first-line paragraph indentation in the DOM while leaving\n * Lexical's serialized paragraph indent levels intact.\n */\nexport const ParagraphIndentPlugin: React.FC = () => {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const syncParagraphIndents = () => editor.getEditorState().read(() => {\n visitElements($getRoot(), node => {\n if (!$isParagraphNode(node)) {\n return;\n }\n\n const element = editor.getElementByKey(node.getKey());\n if (!(element instanceof HTMLElement)) {\n return;\n }\n\n const indent = node.getIndent();\n element.style.paddingInlineStart = '0px';\n element.style.textIndent = indent > 0 ? `${indent * FIRST_LINE_INDENT_PX}px` : '';\n });\n });\n\n syncParagraphIndents();\n\n return editor.registerUpdateListener(() => {\n syncParagraphIndents();\n });\n }, [editor]);\n\n return null;\n};\n","import React from 'react';\n\n/**\n * PastePlugin — placeholder for paste normalization.\n *\n * Overflow detection after paste is handled by the OverflowPlugin\n * which monitors content size changes via ResizeObserver.\n */\nexport const PastePlugin: React.FC = () => {\n return null;\n};\n","import { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $createRangeSelectionFromDom,\n $getRoot,\n $setSelection,\n COMMAND_PRIORITY_LOW,\n FOCUS_COMMAND,\n} from 'lexical';\nimport type { LexicalEditor } from 'lexical';\nimport { useDocument } from '../../context/document-context';\nimport type { CaretPosition } from '../../types/history';\nimport { debug } from '../../utils/debug';\n\ninterface ActiveEditorPluginProps {\n pageId: string;\n region: CaretPosition['region'];\n onFocus?: (editor: LexicalEditor) => void;\n}\n\nfunction resolveTextOffset(root: HTMLElement, targetOffset: number): { node: Node; offset: number } {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n let remaining = targetOffset;\n let currentNode = walker.nextNode();\n let lastTextNode: Node | null = null;\n\n while (currentNode) {\n const textLength = currentNode.textContent?.length ?? 0;\n if (remaining <= textLength) {\n return { node: currentNode, offset: remaining };\n }\n\n remaining -= textLength;\n lastTextNode = currentNode;\n currentNode = walker.nextNode();\n }\n\n if (lastTextNode) {\n return {\n node: lastTextNode,\n offset: lastTextNode.textContent?.length ?? 0,\n };\n }\n\n return {\n node: root,\n offset: root.childNodes.length,\n };\n}\n\n/**\n * ActiveEditorPlugin — Registers the editor in the document context on focus.\n *\n * This enables the toolbar to dispatch commands (bold, italic, etc.)\n * to whichever editor the user is currently editing.\n */\nexport const ActiveEditorPlugin: React.FC<ActiveEditorPluginProps> = ({\n pageId,\n region,\n onFocus,\n}) => {\n const [editor] = useLexicalComposerContext();\n const {\n consumePendingCaretPosition,\n consumePendingFocusAtEnd,\n focusAtEndVersion,\n setActiveEditor,\n setActivePageId,\n } = useDocument();\n\n useEffect(() => {\n const caretPosition: CaretPosition = { pageId, region };\n const selectionToRestore = consumePendingCaretPosition(caretPosition);\n if (selectionToRestore === undefined) {\n return;\n }\n\n requestAnimationFrame(() => {\n setActivePageId(pageId);\n setActiveEditor(editor, caretPosition);\n editor.focus();\n if (!selectionToRestore) {\n return;\n }\n\n requestAnimationFrame(() => {\n const rootElement = editor.getRootElement();\n const domSelection = window.getSelection();\n if (!rootElement || !domSelection) {\n return;\n }\n\n const anchorPoint = resolveTextOffset(rootElement, selectionToRestore.anchorTextOffset);\n const focusPoint = resolveTextOffset(rootElement, selectionToRestore.focusTextOffset);\n const range = document.createRange();\n range.setStart(anchorPoint.node, anchorPoint.offset);\n range.setEnd(focusPoint.node, focusPoint.offset);\n\n domSelection.removeAllRanges();\n domSelection.addRange(range);\n\n editor.update(() => {\n const nextSelection = $createRangeSelectionFromDom(window.getSelection(), editor);\n if (nextSelection) {\n $setSelection(nextSelection);\n }\n });\n });\n });\n }, [consumePendingCaretPosition, editor, pageId, region, setActiveEditor, setActivePageId]);\n\n useEffect(() => {\n const caretPosition: CaretPosition = { pageId, region };\n if (!consumePendingFocusAtEnd(caretPosition)) {\n return;\n }\n\n requestAnimationFrame(() => {\n setActivePageId(pageId);\n setActiveEditor(editor, caretPosition);\n editor.focus(() => {\n editor.update(() => {\n $getRoot().selectEnd();\n });\n });\n });\n }, [\n consumePendingFocusAtEnd,\n editor,\n focusAtEndVersion,\n pageId,\n region,\n setActiveEditor,\n setActivePageId,\n ]);\n\n useEffect(() => {\n return editor.registerCommand(\n FOCUS_COMMAND,\n () => {\n debug('focus', `editor focused (ns=${editor.getKey()})`);\n setActivePageId(pageId);\n setActiveEditor(editor, { pageId, region });\n onFocus?.(editor);\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [editor, onFocus, pageId, region, setActiveEditor, setActivePageId]);\n\n return null;\n};\n","import { useEffect, useRef } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getRoot,\n $isElementNode,\n type LexicalNode,\n type SerializedEditorState,\n type SerializedLexicalNode,\n} from 'lexical';\nimport { debug, debugWarn } from '../../utils/debug';\n\n/**\n * Recursively serializes a Lexical node and all its children.\n * ElementNode.exportJSON() returns children: [] by default —\n * the recursive walk must be done manually.\n */\nfunction serializeNodeTree(node: LexicalNode): SerializedLexicalNode {\n const json = node.exportJSON();\n if ($isElementNode(node)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (json as any).children = node.getChildren().map(serializeNodeTree);\n }\n return json;\n}\n\ninterface OverflowPluginProps {\n /** Called with the serialized overflow content that must go to the next page */\n onOverflow: (\n overflowContent: SerializedEditorState,\n cause: 'paste' | 'content',\n ) => void;\n}\n\n/** Debounce delay for typing-triggered overflow checks (ms) */\nconst OVERFLOW_DEBOUNCE_MS = 300;\n\n/**\n * OverflowPlugin — Detects content overflow inside a Lexical editor\n * and automatically extracts overflow nodes.\n *\n * Uses registerRootListener to reliably get the root element (handles\n * the case where the root is not yet available on first render).\n *\n * Measures child element positions via getBoundingClientRect() relative\n * to the container, which works regardless of CSS overflow settings.\n *\n * Debounces overflow checks during normal typing (300ms) to avoid\n * extracting only the empty trailing paragraph. Paste and external\n * state changes (e.g. setEditorState) trigger immediate checks.\n */\nexport const OverflowPlugin: React.FC<OverflowPluginProps> = ({\n onOverflow,\n}) => {\n const [editor] = useLexicalComposerContext();\n const processingRef = useRef(false);\n const onOverflowRef = useRef(onOverflow);\n onOverflowRef.current = onOverflow;\n\n useEffect(() => {\n let observer: ResizeObserver | null = null;\n let unregisterUpdateListener: (() => void) | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const checkOverflow = (\n rootElement: HTMLElement,\n container: HTMLElement,\n cause: 'paste' | 'content',\n ) => {\n if (processingRef.current) return;\n\n const availableHeight = container.clientHeight;\n if (availableHeight <= 0) return;\n\n // Use scrollHeight for reliable overflow detection — unaffected by\n // scroll position (getBoundingClientRect is affected when the browser\n // scrolls overflow:hidden containers to follow the cursor after paste).\n const contentHeight = rootElement.scrollHeight;\n\n // No overflow if all content fits (+2px tolerance for sub-pixel rounding)\n if (contentHeight <= availableHeight + 2) return;\n\n const children = Array.from(rootElement.children) as HTMLElement[];\n if (children.length === 0) return;\n\n if (children.length <= 1) {\n debug('overflow', `single block overflows (content=${contentHeight}px > available=${availableHeight}px) — cannot split`);\n return;\n }\n\n processingRef.current = true;\n\n debug('overflow', `OVERFLOW detected: content=${contentHeight}px available=${availableHeight}px children=${children.length}`);\n\n // Find the first child whose bottom exceeds the available height.\n // Uses offsetTop (relative to offsetParent, unaffected by scroll)\n // instead of getBoundingClientRect (which shifts with scroll).\n let splitIndex = children.length;\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n const childBottom = child.offsetTop + child.offsetHeight;\n\n if (childBottom > availableHeight && i > 0) {\n splitIndex = i;\n debug('overflow', `split at index ${i} (childBottom=${childBottom}px > ${availableHeight}px)`);\n break;\n }\n }\n\n if (splitIndex >= children.length) {\n debugWarn('overflow', 'no valid split point found — all children fit individually');\n processingRef.current = false;\n return;\n }\n\n editor.update(\n () => {\n const root = $getRoot();\n const allChildren = root.getChildren();\n\n if (splitIndex >= allChildren.length) {\n debugWarn('overflow', `splitIndex=${splitIndex} >= Lexical children=${allChildren.length} — mismatch`);\n processingRef.current = false;\n return;\n }\n\n const overflowNodes: SerializedLexicalNode[] = [];\n const toRemove = allChildren.slice(splitIndex);\n\n for (const node of toRemove) {\n overflowNodes.push(serializeNodeTree(node));\n }\n\n for (const node of toRemove) {\n node.remove();\n }\n\n debug('overflow', `extracted ${overflowNodes.length} overflow nodes, kept ${splitIndex} nodes on current page`);\n\n const overflowState: SerializedEditorState = {\n root: {\n children: overflowNodes,\n direction: null,\n format: '',\n indent: 0,\n type: 'root',\n version: 1,\n },\n } as SerializedEditorState;\n\n setTimeout(() => {\n onOverflowRef.current(overflowState, cause);\n processingRef.current = false;\n }, 0);\n },\n { tag: 'overflow-split' },\n );\n };\n\n const setupObservers = (rootElement: HTMLElement) => {\n // Clean up any previous observers\n if (observer) observer.disconnect();\n if (unregisterUpdateListener) unregisterUpdateListener();\n if (debounceTimer) clearTimeout(debounceTimer);\n\n const container = rootElement.closest('.lex4-page-body') as HTMLElement | null;\n if (!container) {\n debugWarn('overflow', 'no .lex4-page-body container found');\n return;\n }\n\n debug('overflow', `observers attached (ns=${editor.getKey()})`);\n\n const immediateCheck = () => {\n requestAnimationFrame(() => checkOverflow(rootElement, container, 'content'));\n };\n\n const pasteCheck = () => {\n requestAnimationFrame(() => checkOverflow(rootElement, container, 'paste'));\n };\n\n const debouncedCheck = () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(immediateCheck, OVERFLOW_DEBOUNCE_MS);\n };\n\n // ResizeObserver fires on actual layout changes — debounce to\n // avoid constant checks during typing\n observer = new ResizeObserver(debouncedCheck);\n observer.observe(rootElement);\n observer.observe(container);\n\n unregisterUpdateListener = editor.registerUpdateListener(({ tags }) => {\n if (tags.has('overflow-split')) return;\n\n // Paste and external state changes trigger immediate overflow check.\n // Normal typing is debounced to avoid extracting only the cursor paragraph.\n if (tags.has('paste')) {\n debug('overflow', `paste check (tags=${Array.from(tags).join(',')})`);\n pasteCheck();\n } else if (tags.has('collaboration') || tags.has('historic')) {\n debug('overflow', `immediate check (tags=${Array.from(tags).join(',')})`);\n immediateCheck();\n } else {\n debouncedCheck();\n }\n });\n\n // Initial check after setup (immediate — handles mount with initial content)\n immediateCheck();\n };\n\n // registerRootListener fires immediately with current root (if any)\n // and again whenever the root element changes — handles the case\n // where getRootElement() returns null on first render\n const unregisterRootListener = editor.registerRootListener(\n (rootElement: HTMLElement | null) => {\n if (rootElement) {\n debug('overflow', `rootListener: root available (ns=${editor.getKey()})`);\n setupObservers(rootElement);\n } else {\n debug('overflow', `rootListener: root detached (ns=${editor.getKey()})`);\n if (observer) observer.disconnect();\n if (unregisterUpdateListener) unregisterUpdateListener();\n if (debounceTimer) clearTimeout(debounceTimer);\n observer = null;\n unregisterUpdateListener = null;\n debounceTimer = null;\n }\n },\n );\n\n return () => {\n unregisterRootListener();\n if (observer) observer.disconnect();\n if (unregisterUpdateListener) unregisterUpdateListener();\n if (debounceTimer) clearTimeout(debounceTimer);\n };\n }, [editor]);\n\n return null;\n};\n","import { useEffect, useMemo } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n COMMAND_PRIORITY_LOW,\n CONTROLLED_TEXT_INSERTION_COMMAND,\n FORMAT_ELEMENT_COMMAND,\n FORMAT_TEXT_COMMAND,\n KEY_BACKSPACE_COMMAND,\n KEY_DELETE_COMMAND,\n KEY_DOWN_COMMAND,\n KEY_ENTER_COMMAND,\n PASTE_COMMAND,\n} from 'lexical';\n\nimport { useDocument } from '../../context/document-context';\nimport type { HistoryActionDescriptor, HistoryRegion } from '../../types/history';\n\ninterface HistoryCapturePluginProps {\n pageId: string;\n region: Exclude<HistoryRegion, 'document'>;\n}\n\nfunction createPageLabel(region: HistoryCapturePluginProps['region'], pageNumber: number | null): string {\n if (region === 'body') {\n return pageNumber ? `Page ${pageNumber}` : 'Body';\n }\n\n const regionLabel = region.charAt(0).toUpperCase() + region.slice(1);\n return pageNumber ? `${regionLabel} Page ${pageNumber}` : regionLabel;\n}\n\nexport const HistoryCapturePlugin: React.FC<HistoryCapturePluginProps> = ({ pageId, region }) => {\n const [editor] = useLexicalComposerContext();\n const { document, queueHistoryAction } = useDocument();\n\n const context = useMemo(() => {\n const pageNumber = document.pages.findIndex(page => page.id === pageId);\n return {\n pageNumber: pageNumber >= 0 ? pageNumber + 1 : null,\n source: region,\n };\n }, [document.pages, pageId, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n CONTROLLED_TEXT_INSERTION_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Typed text'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event: KeyboardEvent) => {\n if (event.metaKey || event.ctrlKey || event.altKey) {\n return false;\n }\n\n if (event.key.length !== 1) {\n return false;\n }\n\n queueHistoryAction(buildDescriptor('Typed text'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n PASTE_COMMAND,\n (event: ClipboardEvent) => {\n const text = event.clipboardData?.getData('text/plain') ?? '';\n if (text.trim().length === 0) {\n return false;\n }\n queueHistoryAction(buildDescriptor('Pasted content'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_ENTER_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Inserted line break'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Deleted backward'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n KEY_DELETE_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Deleted forward'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n FORMAT_TEXT_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Formatted text'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n useEffect(() => {\n const buildDescriptor = (prefix: string): HistoryActionDescriptor => ({\n label: `${prefix} - ${createPageLabel(region, context.pageNumber)}`,\n source: context.source,\n pageId,\n region,\n });\n\n return editor.registerCommand(\n FORMAT_ELEMENT_COMMAND,\n () => {\n queueHistoryAction(buildDescriptor('Formatted paragraph'));\n return false;\n },\n COMMAND_PRIORITY_LOW,\n );\n }, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);\n\n return null;\n};\n","import { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n COMMAND_PRIORITY_HIGH,\n KEY_BACKSPACE_COMMAND,\n KEY_DELETE_COMMAND,\n KEY_DOWN_COMMAND,\n} from 'lexical';\n\ninterface PageBoundaryPluginProps {\n onBackspaceAtStart: () => void;\n onDeleteAtEnd: () => void;\n onMoveToPreviousPage: () => void;\n onMoveToNextPage: () => void;\n}\n\ninterface CollapsedTextPosition {\n textOffset: number;\n totalTextLength: number;\n}\n\nfunction getCollapsedTextPosition(rootElement: HTMLElement | null): CollapsedTextPosition | null {\n const domSelection = window.getSelection();\n if (!rootElement || !domSelection || domSelection.rangeCount === 0 || !domSelection.isCollapsed) {\n return null;\n }\n\n const range = domSelection.getRangeAt(0);\n if (!rootElement.contains(range.startContainer)) {\n return null;\n }\n\n const offsetRange = document.createRange();\n offsetRange.setStart(rootElement, 0);\n offsetRange.setEnd(range.startContainer, range.startOffset);\n\n const contentRange = document.createRange();\n contentRange.selectNodeContents(rootElement);\n\n return {\n textOffset: offsetRange.toString().length,\n totalTextLength: contentRange.toString().length,\n };\n}\n\nexport const PageBoundaryPlugin: React.FC<PageBoundaryPluginProps> = ({\n onBackspaceAtStart,\n onDeleteAtEnd,\n onMoveToPreviousPage,\n onMoveToNextPage,\n}) => {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n () => {\n const position = getCollapsedTextPosition(editor.getRootElement());\n if (!position || position.textOffset !== 0) {\n return false;\n }\n\n onBackspaceAtStart();\n return true;\n },\n COMMAND_PRIORITY_HIGH,\n ), [editor, onBackspaceAtStart]);\n\n useEffect(() => editor.registerCommand(\n KEY_DELETE_COMMAND,\n () => {\n const position = getCollapsedTextPosition(editor.getRootElement());\n if (!position || position.textOffset !== position.totalTextLength) {\n return false;\n }\n\n onDeleteAtEnd();\n return true;\n },\n COMMAND_PRIORITY_HIGH,\n ), [editor, onDeleteAtEnd]);\n\n useEffect(() => editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event: KeyboardEvent) => {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {\n return false;\n }\n\n const position = getCollapsedTextPosition(editor.getRootElement());\n if (!position) {\n return false;\n }\n\n if ((event.key === 'ArrowLeft' || event.key === 'ArrowUp') && position.textOffset === 0) {\n event.preventDefault();\n onMoveToPreviousPage();\n return true;\n }\n\n if (\n (event.key === 'ArrowRight' || event.key === 'ArrowDown')\n && position.textOffset === position.totalTextLength\n ) {\n event.preventDefault();\n onMoveToNextPage();\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH,\n ), [editor, onMoveToNextPage, onMoveToPreviousPage]);\n\n return null;\n};\n","import React, { useCallback, useEffect, useMemo } from 'react';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { ListPlugin } from '@lexical/react/LexicalListPlugin';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport type { EditorState, SerializedEditorState } from 'lexical';\n\nimport { createEditorConfig } from '../lexical/editor-setup';\nimport { TabIndentPlugin } from '../lexical/plugins/tab-indent-plugin';\nimport { ParagraphIndentPlugin } from '../lexical/plugins/paragraph-indent-plugin';\nimport { PastePlugin } from '../lexical/plugins/paste-plugin';\nimport { ActiveEditorPlugin } from '../lexical/plugins/active-editor-plugin';\nimport { OverflowPlugin } from '../lexical/plugins/overflow-plugin';\nimport { HistoryCapturePlugin } from '../lexical/plugins/history-capture-plugin';\nimport { PageBoundaryPlugin } from '../lexical/plugins/page-boundary-plugin';\nimport { useDocument } from '../context/document-context';\nimport { useExtensions } from '../extensions/extension-context';\nimport { debug, shortId } from '../utils/debug';\n\ninterface PageBodyProps {\n pageId: string;\n initialBodyState?: SerializedEditorState | null;\n onBodyChange?: (state: SerializedEditorState) => void;\n onOverflow?: (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => void;\n onFocus?: () => void;\n onBackspaceAtStart?: () => void;\n onDeleteAtEnd?: () => void;\n onMoveToPreviousPage?: () => void;\n onMoveToNextPage?: () => void;\n readOnly?: boolean;\n}\n\n/**\n * EditorRegistryPlugin — Registers the editor in the document-level\n * editor registry so other pages can directly push content into it.\n */\nconst EditorRegistryPlugin: React.FC<{ pageId: string }> = ({ pageId }) => {\n const [editor] = useLexicalComposerContext();\n const { editorRegistry } = useDocument();\n\n useEffect(() => {\n editorRegistry.register(pageId, editor);\n debug('registry', `registered editor for page ${shortId(pageId)}`);\n return () => {\n editorRegistry.unregister(pageId);\n debug('registry', `unregistered editor for page ${shortId(pageId)}`);\n };\n }, [editor, pageId, editorRegistry]);\n\n return null;\n};\n\n/**\n * PageBody — Lexical editor instance for one page's body content.\n *\n * Each page gets its own Lexical editor. The OverflowPlugin\n * handles splitting content when it exceeds the available height.\n *\n * Extension-contributed body plugins are rendered inside the LexicalComposer.\n */\nexport const PageBody: React.FC<PageBodyProps> = ({\n pageId,\n initialBodyState,\n onBodyChange,\n onOverflow,\n onFocus,\n onBackspaceAtStart,\n onDeleteAtEnd,\n onMoveToPreviousPage,\n onMoveToNextPage,\n readOnly = false,\n}) => {\n const { nodes, bodyPlugins, themeOverrides } = useExtensions();\n\n const config = useMemo(\n () => {\n const baseConfig = {\n ...createEditorConfig('body', pageId, nodes, themeOverrides),\n editable: !readOnly,\n };\n\n if (initialBodyState) {\n debug('page', `PageBody ${shortId(pageId)}: initializing with ${initialBodyState.root?.children?.length ?? 0} children`);\n return {\n ...baseConfig,\n editorState: JSON.stringify(initialBodyState),\n };\n }\n\n debug('page', `PageBody ${shortId(pageId)}: initializing empty`);\n return baseConfig;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally only use initialBodyState at mount time\n [pageId, readOnly, nodes, themeOverrides],\n );\n\n const handleChange = useCallback(\n (editorState: EditorState) => {\n const serialized = editorState.toJSON();\n onBodyChange?.(serialized);\n },\n [onBodyChange],\n );\n\n const handleOverflow = useCallback(\n (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => {\n debug('page', `PageBody ${shortId(pageId)}: overflow callback fired with ${overflowContent.root?.children?.length ?? 0} children`);\n onOverflow?.(overflowContent, cause);\n },\n [onOverflow, pageId],\n );\n\n return (\n <div\n className=\"lex4-page-body flex-1 min-h-0 relative\"\n style={{ overflow: 'hidden' }}\n data-testid={`page-body-${pageId}`}\n onFocus={onFocus}\n >\n <LexicalComposer initialConfig={config}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n className=\"outline-none h-full p-0\"\n style={{ overflow: 'visible' }}\n />\n }\n placeholder={\n <div className=\"absolute top-0 left-0 text-gray-400 pointer-events-none select-none\">\n Start typing...\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <ListPlugin />\n <ParagraphIndentPlugin />\n <TabIndentPlugin />\n <PastePlugin />\n <EditorRegistryPlugin pageId={pageId} />\n <ActiveEditorPlugin pageId={pageId} region=\"body\" />\n {!readOnly && <HistoryCapturePlugin pageId={pageId} region=\"body\" />}\n {!readOnly && onBackspaceAtStart && onDeleteAtEnd && onMoveToPreviousPage && onMoveToNextPage && (\n <PageBoundaryPlugin\n onBackspaceAtStart={onBackspaceAtStart}\n onDeleteAtEnd={onDeleteAtEnd}\n onMoveToPreviousPage={onMoveToPreviousPage}\n onMoveToNextPage={onMoveToNextPage}\n />\n )}\n <OverflowPlugin onOverflow={handleOverflow} />\n {bodyPlugins.map((Plugin, idx) => (\n <Plugin key={idx} />\n ))}\n <OnChangePlugin onChange={handleChange} ignoreSelectionChange />\n </LexicalComposer>\n </div>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { COMMAND_PRIORITY_CRITICAL, KEY_ENTER_COMMAND, PASTE_COMMAND } from 'lexical';\nimport { debug } from '../../utils/debug';\n\n/**\n * HeightLimitPlugin — Prevents editing that would push content beyond\n * a maximum height. Instead of clipping overflow, this plugin reverts\n * any change that makes the editor's scrollHeight exceed maxHeight.\n *\n * Works by:\n * 1. Blocking Enter key when already at max height\n * 2. Saving editor state before each update, reverting if scrollHeight exceeds limit\n * 3. Truncating paste content that would overflow\n */\nexport function HeightLimitPlugin({ maxHeight, channel }: { maxHeight: number; channel: 'header' | 'footer' }) {\n const [editor] = useLexicalComposerContext();\n const lastGoodStateRef = useRef<string | null>(null);\n const isRevertingRef = useRef(false);\n\n useEffect(() => {\n // Save initial state as \"last good\"\n lastGoodStateRef.current = JSON.stringify(editor.getEditorState().toJSON());\n\n // Intercept Enter key when at max height\n const removeEnterCommand = editor.registerCommand(\n KEY_ENTER_COMMAND,\n () => {\n const root = editor.getRootElement();\n if (root && root.scrollHeight >= maxHeight) {\n debug(channel, `blocked Enter — scrollHeight ${root.scrollHeight}px >= max ${maxHeight}px`);\n return true; // Prevent the Enter\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n\n // Intercept paste when at max height\n const removePasteCommand = editor.registerCommand(\n PASTE_COMMAND,\n () => {\n const root = editor.getRootElement();\n if (root && root.scrollHeight >= maxHeight) {\n debug(channel, `blocked paste — scrollHeight ${root.scrollHeight}px >= max ${maxHeight}px`);\n return true; // Prevent the paste\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n\n // After each update, check if content exceeds max height and revert if so\n const removeUpdateListener = editor.registerUpdateListener(({ editorState, prevEditorState }) => {\n if (isRevertingRef.current) return;\n\n const root = editor.getRootElement();\n if (!root) return;\n\n // Use requestAnimationFrame to read DOM after paint\n requestAnimationFrame(() => {\n if (root.scrollHeight > maxHeight) {\n debug(channel, `reverting — scrollHeight ${root.scrollHeight}px > max ${maxHeight}px`);\n const restoreState =\n JSON.stringify(prevEditorState.toJSON()) || lastGoodStateRef.current;\n if (!restoreState) {\n return;\n }\n isRevertingRef.current = true;\n\n editor.setEditorState(editor.parseEditorState(restoreState));\n\n isRevertingRef.current = false;\n } else {\n // Content fits — save as last good state\n lastGoodStateRef.current = JSON.stringify(editorState.toJSON());\n }\n });\n });\n\n return () => {\n removeEnterCommand();\n removePasteCommand();\n removeUpdateListener();\n };\n }, [editor, maxHeight, channel]);\n\n return null;\n}\n","import React, { useCallback, useMemo, useRef } from 'react';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport type { EditorState, SerializedEditorState } from 'lexical';\n\nimport { createEditorConfig } from '../lexical/editor-setup';\nimport { MAX_HEADER_HEIGHT_PX } from '../constants/dimensions';\nimport { ActiveEditorPlugin } from '../lexical/plugins/active-editor-plugin';\nimport { HeightLimitPlugin } from '../lexical/plugins/height-limit-plugin';\nimport { HistoryCapturePlugin } from '../lexical/plugins/history-capture-plugin';\nimport { useExtensions } from '../extensions/extension-context';\nimport { useTranslations } from '../i18n';\nimport { debug, shortId } from '../utils/debug';\n\ninterface PageHeaderProps {\n pageId: string;\n initialHeaderState?: SerializedEditorState | null;\n pageCounterLabel?: string;\n onHeaderChange?: (state: SerializedEditorState, height: number) => void;\n}\n\n/**\n * PageHeader — Mini Lexical editor for a page's header region.\n *\n * Constrained to MAX_HEADER_HEIGHT_PX. Uses overflow: clip to prevent\n * the browser from scrolling the container to follow the cursor.\n * Remounts via key={syncVersion} when content is copied/cleared externally.\n */\nexport const PageHeader: React.FC<PageHeaderProps> = ({\n pageId,\n initialHeaderState,\n pageCounterLabel,\n onHeaderChange,\n}) => {\n const hasPageCounter = !!pageCounterLabel;\n const { nodes, themeOverrides } = useExtensions();\n const t = useTranslations();\n const config = useMemo(\n () => {\n const baseConfig = createEditorConfig('header', pageId, nodes, themeOverrides);\n if (initialHeaderState) {\n return { ...baseConfig, editorState: JSON.stringify(initialHeaderState) };\n }\n return baseConfig;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- syncVersion forces remount via key, only used at init\n [pageId, nodes, themeOverrides],\n );\n\n const contentRef = useRef<HTMLDivElement>(null);\n\n const handleChange = useCallback(\n (editorState: EditorState) => {\n requestAnimationFrame(() => {\n const el = contentRef.current;\n if (el) {\n if (el.scrollHeight > MAX_HEADER_HEIGHT_PX) {\n debug(\n 'header',\n `page ${shortId(pageId)}: skipped external sync at ${el.scrollHeight}px > max ${MAX_HEADER_HEIGHT_PX}px`,\n );\n return;\n }\n const height = Math.min(el.scrollHeight, MAX_HEADER_HEIGHT_PX);\n debug('header', `page ${shortId(pageId)}: height=${height}px (scrollH=${el.scrollHeight})`);\n onHeaderChange?.(editorState.toJSON(), height);\n }\n });\n },\n [onHeaderChange, pageId],\n );\n\n return (\n <div\n className=\"lex4-page-header bg-blue-50/60 border-t-2 border-t-blue-200 border-b border-dashed border-blue-100 relative flex-shrink-0\"\n style={{ maxHeight: MAX_HEADER_HEIGHT_PX, overflow: 'clip' }}\n data-testid={`page-header-${pageId}`}\n >\n <LexicalComposer initialConfig={config}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n ref={contentRef}\n className={`outline-none p-2 text-sm text-gray-600 min-h-[24px] ${hasPageCounter ? 'pr-24' : ''}`}\n />\n }\n placeholder={\n <div className={`absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2 text-sm ${hasPageCounter ? 'pr-24' : ''}`}>\n {t.header.placeholder}\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <ActiveEditorPlugin pageId={pageId} region=\"header\" />\n <HistoryCapturePlugin pageId={pageId} region=\"header\" />\n <HeightLimitPlugin maxHeight={MAX_HEADER_HEIGHT_PX} channel=\"header\" />\n <OnChangePlugin onChange={handleChange} ignoreSelectionChange />\n </LexicalComposer>\n {pageCounterLabel && (\n <div\n className=\"pointer-events-none absolute right-2 top-2 select-none text-xs text-gray-500\"\n data-testid={`page-counter-header-${pageId}`}\n >\n {pageCounterLabel}\n </div>\n )}\n </div>\n );\n};\n","import React, { useCallback, useMemo, useRef } from 'react';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';\nimport type { EditorState, SerializedEditorState } from 'lexical';\n\nimport { createEditorConfig } from '../lexical/editor-setup';\nimport { MAX_FOOTER_HEIGHT_PX } from '../constants/dimensions';\nimport { ActiveEditorPlugin } from '../lexical/plugins/active-editor-plugin';\nimport { HeightLimitPlugin } from '../lexical/plugins/height-limit-plugin';\nimport { HistoryCapturePlugin } from '../lexical/plugins/history-capture-plugin';\nimport { useExtensions } from '../extensions/extension-context';\nimport { useTranslations } from '../i18n';\nimport { debug, shortId } from '../utils/debug';\n\ninterface PageFooterProps {\n pageId: string;\n initialFooterState?: SerializedEditorState | null;\n pageCounterLabel?: string;\n onFooterChange?: (state: SerializedEditorState, height: number) => void;\n}\n\n/**\n * PageFooter — Mini Lexical editor for a page's footer region.\n *\n * Constrained to MAX_FOOTER_HEIGHT_PX. Uses overflow: clip to prevent\n * the browser from scrolling the container to follow the cursor.\n * Remounts via key={syncVersion} when content is copied/cleared externally.\n */\nexport const PageFooter: React.FC<PageFooterProps> = ({\n pageId,\n initialFooterState,\n pageCounterLabel,\n onFooterChange,\n}) => {\n const hasPageCounter = !!pageCounterLabel;\n const { nodes, themeOverrides } = useExtensions();\n const t = useTranslations();\n const config = useMemo(\n () => {\n const baseConfig = createEditorConfig('footer', pageId, nodes, themeOverrides);\n if (initialFooterState) {\n return { ...baseConfig, editorState: JSON.stringify(initialFooterState) };\n }\n return baseConfig;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- syncVersion forces remount via key, only used at init\n [pageId, nodes, themeOverrides],\n );\n\n const contentRef = useRef<HTMLDivElement>(null);\n\n const handleChange = useCallback(\n (editorState: EditorState) => {\n requestAnimationFrame(() => {\n const el = contentRef.current;\n if (el) {\n if (el.scrollHeight > MAX_FOOTER_HEIGHT_PX) {\n debug(\n 'footer',\n `page ${shortId(pageId)}: skipped external sync at ${el.scrollHeight}px > max ${MAX_FOOTER_HEIGHT_PX}px`,\n );\n return;\n }\n const height = Math.min(el.scrollHeight, MAX_FOOTER_HEIGHT_PX);\n debug('footer', `page ${shortId(pageId)}: height=${height}px (scrollH=${el.scrollHeight})`);\n onFooterChange?.(editorState.toJSON(), height);\n }\n });\n },\n [onFooterChange, pageId],\n );\n\n return (\n <div\n className=\"lex4-page-footer bg-blue-50/60 border-b-2 border-b-blue-200 border-t border-dashed border-blue-100 relative flex-shrink-0\"\n style={{ maxHeight: MAX_FOOTER_HEIGHT_PX, overflow: 'clip' }}\n data-testid={`page-footer-${pageId}`}\n >\n <LexicalComposer initialConfig={config}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n ref={contentRef}\n className={`outline-none p-2 text-sm text-gray-600 min-h-[24px] ${hasPageCounter ? 'pr-24' : ''}`}\n />\n }\n placeholder={\n <div className={`absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2 text-sm ${hasPageCounter ? 'pr-24' : ''}`}>\n {t.footer.placeholder}\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <ActiveEditorPlugin pageId={pageId} region=\"footer\" />\n <HistoryCapturePlugin pageId={pageId} region=\"footer\" />\n <HeightLimitPlugin maxHeight={MAX_FOOTER_HEIGHT_PX} channel=\"footer\" />\n <OnChangePlugin onChange={handleChange} ignoreSelectionChange />\n </LexicalComposer>\n {pageCounterLabel && (\n <div\n className=\"pointer-events-none absolute right-2 top-2 select-none text-xs text-gray-500\"\n data-testid={`page-counter-footer-${pageId}`}\n >\n {pageCounterLabel}\n </div>\n )}\n </div>\n );\n};\n","import React, { useCallback } from 'react';\nimport { A4_WIDTH_PX, A4_HEIGHT_PX, PAGE_MARGIN_PX } from '../constants/dimensions';\nimport { useDocument } from '../context/document-context';\nimport { PageBody } from './PageBody';\nimport { PageHeader } from './PageHeader';\nimport { PageFooter } from './PageFooter';\nimport type { SerializedEditorState } from 'lexical';\n\ninterface PageViewProps {\n pageId: string;\n pageIndex: number;\n onOverflow?: (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => void;\n onBackspaceAtStart?: (pageIndex: number, pageId: string) => void;\n onDeleteAtEnd?: (pageIndex: number, pageId: string) => void;\n onMoveToPreviousPage?: (pageIndex: number) => void;\n onMoveToNextPage?: (pageIndex: number) => void;\n}\n\n/**\n * PageView — A single A4 page with header, body, and footer regions.\n *\n * Dimensions are always exactly A4 (794 × 1123 px).\n * Header and footer are only rendered when the global toggle is on.\n * Uses CSS flexbox: header/footer are flex-shrink-0, body is flex-1.\n */\nexport const PageView: React.FC<PageViewProps> = React.memo(({\n pageId,\n pageIndex,\n onOverflow,\n onBackspaceAtStart,\n onDeleteAtEnd,\n onMoveToPreviousPage,\n onMoveToNextPage,\n}) => {\n const { document, dispatch, setActivePageId } = useDocument();\n const page = document.pages.find(p => p.id === pageId);\n const showHeaderFooter = document.headerFooterEnabled;\n const pageCounterMode = document.pageCounterMode;\n const pageCounterLabel = `Page ${pageIndex + 1} of ${document.pages.length}`;\n\n if (!page) return null;\n\n const handleBodyChange = useCallback(\n (bodyState: SerializedEditorState) => {\n dispatch({ type: 'UPDATE_PAGE_BODY', pageId, bodyState });\n },\n [dispatch, pageId],\n );\n\n const handleHeaderChange = useCallback(\n (headerState: SerializedEditorState, height: number) => {\n dispatch({ type: 'UPDATE_PAGE_HEADER_CONTENT', pageId, headerState, height });\n },\n [dispatch, pageId],\n );\n\n const handleFooterChange = useCallback(\n (footerState: SerializedEditorState, height: number) => {\n dispatch({ type: 'UPDATE_PAGE_FOOTER_CONTENT', pageId, footerState, height });\n },\n [dispatch, pageId],\n );\n\n const handleFocus = useCallback(() => {\n setActivePageId(pageId);\n }, [setActivePageId, pageId]);\n\n const handleOverflow = useCallback(\n (overflowContent: SerializedEditorState, cause: 'paste' | 'content') => {\n onOverflow?.(overflowContent, cause);\n },\n [onOverflow],\n );\n\n return (\n <div\n className=\"lex4-page bg-white shadow-xl flex flex-col\"\n style={{\n width: A4_WIDTH_PX,\n height: A4_HEIGHT_PX,\n padding: PAGE_MARGIN_PX,\n }}\n data-testid={`page-${pageIndex}`}\n data-page-id={pageId}\n >\n {showHeaderFooter && (\n <PageHeader\n key={`header-${page.headerSyncVersion}`}\n pageId={pageId}\n initialHeaderState={page.headerState}\n pageCounterLabel={pageCounterMode === 'header' || pageCounterMode === 'both' ? pageCounterLabel : undefined}\n onHeaderChange={handleHeaderChange}\n />\n )}\n\n <PageBody\n key={`body-${page.bodySyncVersion}`}\n pageId={pageId}\n initialBodyState={page.bodyState}\n onBodyChange={handleBodyChange}\n onOverflow={handleOverflow}\n onFocus={handleFocus}\n onBackspaceAtStart={() => onBackspaceAtStart?.(pageIndex, pageId)}\n onDeleteAtEnd={() => onDeleteAtEnd?.(pageIndex, pageId)}\n onMoveToPreviousPage={() => onMoveToPreviousPage?.(pageIndex)}\n onMoveToNextPage={() => onMoveToNextPage?.(pageIndex)}\n />\n\n {showHeaderFooter && (\n <PageFooter\n key={`footer-${page.footerSyncVersion}`}\n pageId={pageId}\n initialFooterState={page.footerState}\n pageCounterLabel={pageCounterMode === 'footer' || pageCounterMode === 'both' ? pageCounterLabel : undefined}\n onFooterChange={handleFooterChange}\n />\n )}\n </div>\n );\n});\n\nPageView.displayName = 'PageView';\n","import React, { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { $getRoot } from 'lexical';\nimport type { SerializedEditorState, LexicalEditor } from 'lexical';\n\nimport { useDocument } from '../context/document-context';\nimport { computeBodyHeight } from '../constants/page-layout';\nimport { usePagination } from '../hooks/use-pagination';\nimport { PageView } from './PageView';\nimport { createPageFromTemplate } from '../types/document';\nimport { debug, shortId } from '../utils/debug';\n\n/**\n * DocumentView — Scrollable container rendering all pages vertically.\n *\n * Provides the page-layout visual with pages centered on a gray background\n * with gaps between pages. Handles overflow content from pages by\n * creating new pages or prepending to existing next pages.\n */\nexport const DocumentView: React.FC = () => {\n const {\n document,\n dispatch,\n editorRegistry,\n requestFocusAtEnd,\n runHistoryAction,\n setActiveEditor,\n setActivePageId,\n } = useDocument();\n const { handlePageUnderflow, reflowAll } = usePagination(document, dispatch);\n const previousBodyHeightsRef = useRef<number[] | null>(null);\n const pasteOverflowSequenceRef = useRef(false);\n const pasteOverflowReleaseTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const defaultPageTemplate = useMemo(\n () => ({\n headerState: document.defaultHeaderState,\n footerState: document.defaultFooterState,\n headerHeight: document.defaultHeaderHeight,\n footerHeight: document.defaultFooterHeight,\n }),\n [\n document.defaultFooterHeight,\n document.defaultFooterState,\n document.defaultHeaderHeight,\n document.defaultHeaderState,\n ],\n );\n\n const bodyHeights = useMemo(\n () => document.pages.map(page => computeBodyHeight(\n document.headerFooterEnabled ? page.headerHeight : 0,\n document.headerFooterEnabled ? page.footerHeight : 0,\n )),\n [document.headerFooterEnabled, document.pages],\n );\n\n useEffect(() => {\n const previousBodyHeights = previousBodyHeightsRef.current;\n previousBodyHeightsRef.current = bodyHeights;\n\n if (!previousBodyHeights) {\n return;\n }\n\n const bodySpaceExpanded = bodyHeights.some((height, index) => {\n const previousHeight = previousBodyHeights[index];\n return previousHeight !== undefined && height > previousHeight;\n });\n\n if (bodySpaceExpanded) {\n debug('page', 'body space expanded — running full reflow');\n reflowAll();\n }\n }, [bodyHeights, reflowAll]);\n\n useEffect(\n () => () => {\n if (pasteOverflowReleaseTimerRef.current) {\n clearTimeout(pasteOverflowReleaseTimerRef.current);\n }\n },\n [],\n );\n\n const focusBodyEditor = useCallback(\n (pageId: string, boundary: 'start' | 'end') => {\n let attempts = 0;\n\n const focusWhenReady = () => {\n const editor = editorRegistry.get(pageId);\n if (!editor) {\n if (attempts < 4) {\n attempts += 1;\n requestAnimationFrame(focusWhenReady);\n }\n return;\n }\n\n const caretPosition = { pageId, region: 'body' as const };\n setActivePageId(pageId);\n setActiveEditor(editor as LexicalEditor, caretPosition);\n editor.focus(() => {\n editor.update(() => {\n if (boundary === 'start') {\n $getRoot().selectStart();\n } else {\n $getRoot().selectEnd();\n }\n });\n });\n };\n\n requestAnimationFrame(focusWhenReady);\n },\n [editorRegistry, setActiveEditor, setActivePageId],\n );\n\n const handlePageOverflow = useCallback(\n (\n pageIndex: number,\n overflowContent: SerializedEditorState,\n cause: 'paste' | 'content',\n ) => {\n const nextPageIndex = pageIndex + 1;\n const overflowChildCount = overflowContent.root?.children?.length ?? 0;\n debug('page', `handlePageOverflow: pageIndex=${pageIndex} overflowChildren=${overflowChildCount} totalPages=${document.pages.length}`);\n\n if (cause === 'paste') {\n pasteOverflowSequenceRef.current = true;\n }\n\n if (pasteOverflowSequenceRef.current) {\n if (pasteOverflowReleaseTimerRef.current) {\n clearTimeout(pasteOverflowReleaseTimerRef.current);\n }\n pasteOverflowReleaseTimerRef.current = setTimeout(() => {\n pasteOverflowSequenceRef.current = false;\n pasteOverflowReleaseTimerRef.current = null;\n }, 800);\n }\n\n if (nextPageIndex < document.pages.length) {\n // Prepend overflow content to the next page's editor directly\n const nextPage = document.pages[nextPageIndex];\n const nextEditor = editorRegistry.get(nextPage.id);\n\n if (nextEditor) {\n const currentState = nextEditor.getEditorState().toJSON();\n const existingChildren = currentState.root?.children ?? [];\n const overflowChildren = overflowContent.root?.children ?? [];\n\n debug('page', `prepending ${overflowChildren.length} nodes to existing page ${shortId(nextPage.id)} (had ${existingChildren.length} children)`);\n\n const mergedState: SerializedEditorState = {\n root: {\n ...currentState.root,\n children: [...overflowChildren, ...existingChildren],\n },\n } as SerializedEditorState;\n\n const newEditorState = nextEditor.parseEditorState(JSON.stringify(mergedState));\n nextEditor.setEditorState(newEditorState);\n if (pasteOverflowSequenceRef.current) {\n requestFocusAtEnd({ pageId: nextPage.id, region: 'body' });\n }\n } else {\n debug('page', `editor not found in registry for page ${shortId(nextPage.id)} — falling back to ADD_PAGE`);\n const newPage = createPageFromTemplate(defaultPageTemplate);\n newPage.bodyState = overflowContent;\n runHistoryAction(\n {\n label: 'Overflow created new page',\n source: 'overflow',\n region: 'document',\n },\n () => {\n dispatch({ type: 'ADD_PAGE', afterIndex: pageIndex, page: newPage });\n },\n );\n if (pasteOverflowSequenceRef.current) {\n requestFocusAtEnd({ pageId: newPage.id, region: 'body' });\n }\n }\n } else {\n // Create a new page with the overflow content as initial state\n const newPage = createPageFromTemplate(defaultPageTemplate);\n newPage.bodyState = overflowContent;\n debug('page', `creating new page ${shortId(newPage.id)} with ${overflowChildCount} overflow children`);\n runHistoryAction(\n {\n label: 'Overflow created new page',\n source: 'overflow',\n region: 'document',\n },\n () => {\n dispatch({ type: 'ADD_PAGE', page: newPage });\n },\n );\n if (pasteOverflowSequenceRef.current) {\n requestFocusAtEnd({ pageId: newPage.id, region: 'body' });\n }\n }\n },\n [defaultPageTemplate, document.pages, dispatch, editorRegistry, requestFocusAtEnd, runHistoryAction],\n );\n\n const handleBackspaceAtPageStart = useCallback(\n (pageIndex: number, pageId: string) => {\n if (pageIndex <= 0) {\n return;\n }\n\n const previousPage = document.pages[pageIndex - 1];\n if (!previousPage) {\n return;\n }\n\n runHistoryAction(\n {\n label: `Deleted backward - Page ${pageIndex + 1}`,\n source: 'body',\n pageId,\n region: 'body',\n },\n () => {\n handlePageUnderflow(pageIndex - 1);\n },\n );\n\n focusBodyEditor(previousPage.id, 'end');\n },\n [document.pages, focusBodyEditor, handlePageUnderflow, runHistoryAction],\n );\n\n const handleDeleteAtPageEnd = useCallback(\n (pageIndex: number, pageId: string) => {\n const currentPage = document.pages[pageIndex];\n const nextPage = document.pages[pageIndex + 1];\n if (!currentPage || !nextPage) {\n return;\n }\n\n runHistoryAction(\n {\n label: `Deleted forward - Page ${pageIndex + 1}`,\n source: 'body',\n pageId,\n region: 'body',\n },\n () => {\n handlePageUnderflow(pageIndex);\n },\n );\n\n focusBodyEditor(currentPage.id, 'end');\n },\n [document.pages, focusBodyEditor, handlePageUnderflow, runHistoryAction],\n );\n\n const handleMoveToPreviousPage = useCallback(\n (pageIndex: number) => {\n if (pageIndex <= 0) {\n return;\n }\n\n const previousPage = document.pages[pageIndex - 1];\n if (!previousPage) {\n return;\n }\n\n focusBodyEditor(previousPage.id, 'end');\n },\n [document.pages, focusBodyEditor],\n );\n\n const handleMoveToNextPage = useCallback(\n (pageIndex: number) => {\n const nextPage = document.pages[pageIndex + 1];\n if (!nextPage) {\n return;\n }\n\n focusBodyEditor(nextPage.id, 'start');\n },\n [document.pages, focusBodyEditor],\n );\n\n return (\n <div\n className=\"lex4-document-view flex flex-col items-center gap-8 py-8 min-h-full\"\n data-testid=\"document-view\"\n tabIndex={-1}\n >\n {document.pages.map((page, index) => (\n <PageView\n key={page.id}\n pageId={page.id}\n pageIndex={index}\n onOverflow={(content, cause) => handlePageOverflow(index, content, cause)}\n onBackspaceAtStart={handleBackspaceAtPageStart}\n onDeleteAtEnd={handleDeleteAtPageEnd}\n onMoveToPreviousPage={handleMoveToPreviousPage}\n onMoveToNextPage={handleMoveToNextPage}\n />\n ))}\n </div>\n );\n};\n","import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react';\nimport type { Lex4EditorProps } from '../types/editor-props';\nimport type { Lex4EditorHandle } from '../types/editor-handle';\nimport { DocumentProvider } from '../context/document-provider';\nimport { useDocument } from '../context/document-context';\nimport { HistorySidebar } from './HistorySidebar';\nimport { Toolbar } from './Toolbar';\nimport { DocumentView } from './DocumentView';\nimport {\n ExtensionProvider,\n ExtensionStateProvider,\n useExtensions,\n useExtensionContext,\n} from '../extensions/extension-context';\nimport { TranslationsProvider } from '../i18n';\nimport '../styles.css';\n\nfunction selectEntireDocument(\n rootElement: HTMLDivElement | null,\n selectionBuffer: HTMLTextAreaElement | null,\n) {\n if (!rootElement || !selectionBuffer) {\n return;\n }\n\n const bodyRoots = Array.from(\n rootElement.querySelectorAll<HTMLElement>('[data-testid^=\"page-body-\"] [data-lexical-editor=\"true\"]'),\n );\n\n if (bodyRoots.length === 0) {\n return;\n }\n\n selectionBuffer.value = bodyRoots\n .map(bodyRoot => bodyRoot.innerText.trim())\n .filter(Boolean)\n .join('\\n');\n selectionBuffer.focus();\n selectionBuffer.select();\n}\n\nconst GLOBAL_SELECTION_BACKGROUND = 'rgb(191, 219, 254)';\nconst GLOBAL_SELECTION_FOREGROUND = 'rgb(30, 64, 175)';\n\nfunction isFormFieldTarget(target: EventTarget | null): boolean {\n const element = target as HTMLElement | null;\n const tagName = element?.tagName;\n return tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT';\n}\n\nconst EditorChrome: React.FC<{\n captureHistoryShortcutsOnWindow: boolean;\n className?: string;\n}> = ({\n captureHistoryShortcutsOnWindow,\n className,\n}) => {\n const {\n document,\n dispatch,\n globalSelectionActive,\n setGlobalSelectionActive,\n undo,\n redo,\n } = useDocument();\n const { sidePanels } = useExtensions();\n const rootRef = useRef<HTMLDivElement>(null);\n const selectionBufferRef = useRef<HTMLTextAreaElement>(null);\n\n const clearGlobalSelection = useCallback(() => {\n setGlobalSelectionActive(false);\n selectionBufferRef.current?.blur();\n }, [setGlobalSelectionActive]);\n\n const handleHistoryShortcut = useCallback((event: { key: string; metaKey: boolean; ctrlKey: boolean; shiftKey: boolean; preventDefault: () => void; stopPropagation?: () => void }) => {\n const key = event.key.toLowerCase();\n\n if (key === 'z') {\n event.preventDefault();\n event.stopPropagation?.();\n clearGlobalSelection();\n if (event.shiftKey) {\n redo();\n } else {\n undo();\n }\n return true;\n }\n\n if (key === 'y') {\n event.preventDefault();\n event.stopPropagation?.();\n clearGlobalSelection();\n redo();\n return true;\n }\n\n return false;\n }, [clearGlobalSelection, redo, undo]);\n\n const handleKeyDownCapture = useCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement | null;\n const isGlobalSelectionBufferTarget = target === selectionBufferRef.current;\n\n if (!isGlobalSelectionBufferTarget && isFormFieldTarget(target)) {\n return;\n }\n\n const key = event.key.toLowerCase();\n\n if (isGlobalSelectionBufferTarget && (key === 'backspace' || key === 'delete')) {\n event.preventDefault();\n event.stopPropagation();\n dispatch({ type: 'CLEAR_DOCUMENT_CONTENT' });\n clearGlobalSelection();\n return;\n }\n\n const hasModifier = event.metaKey || event.ctrlKey;\n if (!hasModifier) {\n return;\n }\n\n if (key === 'a') {\n event.preventDefault();\n event.stopPropagation();\n requestAnimationFrame(() => {\n const activeElement = window.document.activeElement;\n if (activeElement instanceof HTMLElement && activeElement.isContentEditable) {\n activeElement.blur();\n }\n selectEntireDocument(rootRef.current, selectionBufferRef.current);\n setGlobalSelectionActive(true);\n });\n return;\n }\n\n if (handleHistoryShortcut(event)) {\n return;\n }\n }, [\n dispatch,\n handleHistoryShortcut,\n setGlobalSelectionActive,\n ]);\n\n const handleMouseDownCapture = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n if (!globalSelectionActive) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n const clickedToolbar = target?.closest('[data-testid=\"toolbar\"]');\n\n if (event.target !== selectionBufferRef.current && !clickedToolbar) {\n clearGlobalSelection();\n }\n }, [clearGlobalSelection, globalSelectionActive]);\n\n useEffect(() => {\n const editableRoots =\n rootRef.current?.querySelectorAll<HTMLElement>(\n '[data-testid^=\"page-body-\"] [data-lexical-editor=\"true\"]',\n ) ?? [];\n\n editableRoots.forEach((editableRoot) => {\n editableRoot.style.backgroundColor = globalSelectionActive ? GLOBAL_SELECTION_BACKGROUND : '';\n editableRoot.style.color = globalSelectionActive ? GLOBAL_SELECTION_FOREGROUND : '';\n editableRoot.style.caretColor = globalSelectionActive ? 'transparent' : '';\n });\n }, [globalSelectionActive, document.pages.length]);\n\n useEffect(() => {\n if (!captureHistoryShortcutsOnWindow) {\n return;\n }\n\n const handleWindowKeyDown = (event: KeyboardEvent) => {\n const hasModifier = event.metaKey || event.ctrlKey;\n if (!hasModifier) {\n return;\n }\n\n handleHistoryShortcut(event);\n };\n\n window.addEventListener('keydown', handleWindowKeyDown, { capture: true });\n const handleWindowBeforeInput = (event: InputEvent) => {\n if (event.inputType === 'historyUndo') {\n event.preventDefault();\n clearGlobalSelection();\n undo();\n } else if (event.inputType === 'historyRedo') {\n event.preventDefault();\n clearGlobalSelection();\n redo();\n }\n };\n\n window.addEventListener('beforeinput', handleWindowBeforeInput, { capture: true });\n return () => {\n window.removeEventListener('keydown', handleWindowKeyDown, { capture: true });\n window.removeEventListener('beforeinput', handleWindowBeforeInput, { capture: true });\n };\n }, [captureHistoryShortcutsOnWindow, clearGlobalSelection, handleHistoryShortcut, redo, undo]);\n\n return (\n <div\n ref={rootRef}\n className={`lex4-editor flex flex-col h-full ${className ?? ''}`}\n data-testid=\"lex4-editor\"\n data-global-selection-active={globalSelectionActive ? 'true' : 'false'}\n onKeyDownCapture={handleKeyDownCapture}\n onMouseDownCapture={handleMouseDownCapture}\n >\n <textarea\n ref={selectionBufferRef}\n aria-hidden=\"true\"\n data-testid=\"global-selection-buffer\"\n readOnly\n tabIndex={-1}\n className=\"pointer-events-none fixed -left-[9999px] top-0 h-0 w-0 opacity-0\"\n />\n <Toolbar />\n <div className=\"flex min-h-0 flex-1 overflow-hidden bg-gray-700\">\n <div className=\"min-w-0 flex-1 overflow-auto\">\n <DocumentView />\n </div>\n {sidePanels.map((Panel, idx) => (\n <Panel key={idx} />\n ))}\n <HistorySidebar />\n </div>\n </div>\n );\n};\n\n/**\n * EditorWithHandle — Inner component that wires the imperative handle.\n * Has access to DocumentProvider and extension contexts.\n */\nconst EditorWithHandle = forwardRef<Lex4EditorHandle, {\n captureHistoryShortcutsOnWindow: boolean;\n className?: string;\n}>(({ captureHistoryShortcutsOnWindow, className }, ref) => {\n const { document: doc, activeEditor } = useDocument();\n const { handleFactories } = useExtensions();\n\n const getDocument = useCallback(() => doc, [doc]);\n const getActiveEditor = useCallback(() => activeEditor, [activeEditor]);\n const extensionCtx = useExtensionContext(getDocument, getActiveEditor);\n\n useImperativeHandle(ref, () => {\n const handle: Record<string, (...args: never[]) => unknown> = {};\n\n for (const factory of handleFactories) {\n const methods = factory(extensionCtx);\n Object.assign(handle, methods);\n }\n\n return handle as unknown as Lex4EditorHandle;\n }, [extensionCtx, handleFactories]);\n\n return (\n <EditorChrome\n captureHistoryShortcutsOnWindow={captureHistoryShortcutsOnWindow}\n className={className}\n />\n );\n});\n\nEditorWithHandle.displayName = 'EditorWithHandle';\n\n/**\n * Lex4Editor — The main public component.\n *\n * A paginated A4 document editor built on Meta Lexical.\n * Each page is a true discrete A4 page with its own Lexical editor instance.\n *\n * Uses an extension system for AST export, variables, and theming.\n * Pass extensions via the `extensions` prop:\n * @example\n * ```tsx\n * <Lex4Editor extensions={[defaultTheme(), astExtension(), variablesExtension(defs)]} />\n * ```\n */\nexport const Lex4Editor = forwardRef<Lex4EditorHandle, Lex4EditorProps>(({\n captureHistoryShortcutsOnWindow = true,\n initialDocument,\n onDocumentChange,\n extensions,\n translations,\n className,\n}, ref) => {\n return (\n <TranslationsProvider translations={translations}>\n <ExtensionStateProvider>\n <ExtensionProvider extensions={extensions}>\n <DocumentProvider\n initialDocument={initialDocument}\n onDocumentChange={onDocumentChange}\n >\n <EditorWithHandle\n ref={ref}\n captureHistoryShortcutsOnWindow={captureHistoryShortcutsOnWindow}\n className={className}\n />\n </DocumentProvider>\n </ExtensionProvider>\n </ExtensionStateProvider>\n </TranslationsProvider>\n );\n});\n\nLex4Editor.displayName = 'Lex4Editor';\n","import { useCallback, useRef, useEffect } from 'react';\n\n/**\n * useOverflowDetection — Debounced overflow detection for a page body.\n *\n * Watches a contentEditable element and fires `onOverflow` when the\n * content height exceeds the allowed body height. Uses a debounce\n * to avoid firing on every keystroke.\n */\nexport function useOverflowDetection(\n bodyHeight: number,\n onOverflow: (() => void) | undefined,\n debounceMs: number = 100,\n) {\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const observerRef = useRef<ResizeObserver | null>(null);\n\n const check = useCallback(\n (el: HTMLElement) => {\n if (!onOverflow) return;\n if (el.scrollHeight > bodyHeight + 2) {\n // +2 for sub-pixel rounding\n onOverflow();\n }\n },\n [bodyHeight, onOverflow],\n );\n\n const attachRef = useCallback(\n (el: HTMLElement | null) => {\n // Cleanup previous observer\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n\n if (!el || !onOverflow) return;\n\n observerRef.current = new ResizeObserver(() => {\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => check(el), debounceMs);\n });\n observerRef.current.observe(el);\n },\n [check, debounceMs, onOverflow],\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n if (observerRef.current) observerRef.current.disconnect();\n };\n }, []);\n\n return { attachRef };\n}\n","import { useCallback, useRef, useEffect } from 'react';\n\n/**\n * useHeaderFooter — Tracks header/footer height via ResizeObserver\n * and reports changes to the document context.\n *\n * Clamps the reported height to the maximum allowed.\n */\nexport function useHeaderFooter(\n maxHeight: number,\n onHeightChange: (height: number) => void,\n) {\n const observerRef = useRef<ResizeObserver | null>(null);\n const lastHeightRef = useRef<number>(0);\n\n const attachRef = useCallback(\n (el: HTMLElement | null) => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n\n if (!el) return;\n\n const measure = () => {\n const height = Math.min(el.scrollHeight, maxHeight);\n if (height !== lastHeightRef.current) {\n lastHeightRef.current = height;\n onHeightChange(height);\n }\n };\n\n observerRef.current = new ResizeObserver(measure);\n observerRef.current.observe(el);\n\n // Initial measurement\n measure();\n },\n [maxHeight, onHeightChange],\n );\n\n useEffect(() => {\n return () => {\n if (observerRef.current) observerRef.current.disconnect();\n };\n }, []);\n\n return { attachRef };\n}\n","/**\n * Document AST types — the backend integration contract.\n *\n * These types define the clean, Lexical-independent AST\n * that consumers receive when calling getDocumentAst().\n * Backend teams can use these types directly without any\n * knowledge of Lexical or React internals.\n *\n * @version 1.0.0\n */\n\nexport const AST_VERSION = '1.0.0' as const;\n\n// ---------------------------------------------------------------------------\n// Top-level document\n// ---------------------------------------------------------------------------\n\nexport interface DocumentAst {\n version: typeof AST_VERSION;\n page: PageFormatAst;\n headerFooter: HeaderFooterConfigAst;\n pages: PageAst[];\n metadata: DocumentMetadataAst;\n}\n\nexport interface PageFormatAst {\n format: 'A4';\n widthMm: number;\n heightMm: number;\n margins: MarginsAst;\n}\n\nexport interface MarginsAst {\n topMm: number;\n rightMm: number;\n bottomMm: number;\n leftMm: number;\n}\n\nexport interface HeaderFooterConfigAst {\n enabled: boolean;\n pageCounterMode: 'none' | 'header' | 'footer' | 'both';\n defaultHeader: ContentAst | null;\n defaultFooter: ContentAst | null;\n}\n\nexport interface DocumentMetadataAst {\n variables: Record<string, VariableDefinitionAst>;\n}\n\n// ---------------------------------------------------------------------------\n// Page\n// ---------------------------------------------------------------------------\n\nexport interface PageAst {\n pageIndex: number;\n body: BlockNodeAst[];\n header: ContentAst | null;\n footer: ContentAst | null;\n}\n\n// ---------------------------------------------------------------------------\n// Content container\n// ---------------------------------------------------------------------------\n\nexport interface ContentAst {\n blocks: BlockNodeAst[];\n}\n\n// ---------------------------------------------------------------------------\n// Block nodes\n// ---------------------------------------------------------------------------\n\nexport type BlockNodeAst =\n | ParagraphAst\n | HeadingAst\n | ListAst\n | BlockQuoteAst;\n\nexport type Alignment = 'left' | 'center' | 'right' | 'justify';\n\nexport interface ParagraphAst {\n type: 'paragraph';\n alignment?: Alignment;\n indent?: number;\n children: InlineNodeAst[];\n}\n\nexport interface HeadingAst {\n type: 'heading';\n level: 1 | 2 | 3 | 4 | 5;\n alignment?: Alignment;\n children: InlineNodeAst[];\n}\n\nexport interface ListAst {\n type: 'list';\n listType: 'ordered' | 'unordered';\n items: ListItemAst[];\n}\n\nexport interface ListItemAst {\n type: 'list-item';\n children: InlineNodeAst[];\n nestedList?: ListAst;\n}\n\nexport interface BlockQuoteAst {\n type: 'blockquote';\n children: InlineNodeAst[];\n}\n\n// ---------------------------------------------------------------------------\n// Inline nodes\n// ---------------------------------------------------------------------------\n\nexport type InlineNodeAst =\n | TextRunAst\n | VariableAst\n | LineBreakAst;\n\nexport interface TextMarks {\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n fontFamily?: string;\n fontSize?: number;\n}\n\nexport interface TextRunAst {\n type: 'text';\n text: string;\n marks?: TextMarks;\n}\n\nexport interface VariableAst {\n type: 'variable';\n key: string;\n marks?: TextMarks;\n}\n\nexport interface LineBreakAst {\n type: 'linebreak';\n}\n\n// ---------------------------------------------------------------------------\n// Variable definitions (shared with variables/types.ts)\n// ---------------------------------------------------------------------------\n\nexport interface VariableDefinitionAst {\n key: string;\n label: string;\n description?: string;\n valueType?: 'string' | 'number' | 'date' | 'boolean';\n group?: string;\n}\n\n// ---------------------------------------------------------------------------\n// REST payload\n// ---------------------------------------------------------------------------\n\nexport interface SaveDocumentRequest {\n document: DocumentAst;\n exportTarget?: 'pdf' | 'docx';\n documentId?: string;\n metadata?: Record<string, string>;\n}\n","/**\n * Inline mapper — Converts Lexical serialized inline nodes to AST inline nodes.\n *\n * Handles:\n * - TextNode → TextRunAst (decodes format bitmask + parses CSS style)\n * - VariableNode → VariableAst\n * - LineBreakNode → LineBreakAst\n */\n\nimport type { InlineNodeAst, TextMarks, TextRunAst, VariableAst, LineBreakAst } from './types';\nimport type { SerializedVariableNode } from '../variables/variable-node';\n\n// Lexical format bitmask constants\nconst IS_BOLD = 1;\nconst IS_ITALIC = 2;\nconst IS_STRIKETHROUGH = 4;\nconst IS_UNDERLINE = 8;\n\n/** Serialized Lexical text node shape (subset of fields we need). */\ninterface SerializedTextNode {\n type: 'text';\n text: string;\n format: number;\n style?: string;\n [key: string]: unknown;\n}\n\ninterface SerializedLineBreak {\n type: 'linebreak';\n [key: string]: unknown;\n}\n\ntype SerializedInlineNode = SerializedTextNode | SerializedVariableNode | SerializedLineBreak;\n\n/**\n * Decodes Lexical's format bitmask into named boolean marks.\n */\nexport function decodeFormatBitmask(format: number): Pick<TextMarks, 'bold' | 'italic' | 'underline' | 'strikethrough'> {\n const marks: Pick<TextMarks, 'bold' | 'italic' | 'underline' | 'strikethrough'> = {};\n if (format & IS_BOLD) marks.bold = true;\n if (format & IS_ITALIC) marks.italic = true;\n if (format & IS_UNDERLINE) marks.underline = true;\n if (format & IS_STRIKETHROUGH) marks.strikethrough = true;\n return marks;\n}\n\n/**\n * Extracts font-family from a CSS style string.\n */\nexport function extractFontFamily(style: string): string | undefined {\n const match = style.match(/font-family:\\s*([^;]+)/);\n return match ? match[1].trim().replace(/['\"]/g, '') : undefined;\n}\n\n/**\n * Extracts font-size (in pt) from a CSS style string.\n */\nexport function extractFontSizePt(style: string): number | undefined {\n const match = style.match(/font-size:\\s*(\\d+(?:\\.\\d+)?)\\s*pt/);\n return match ? parseFloat(match[1]) : undefined;\n}\n\n/**\n * Builds TextMarks from a Lexical format bitmask and style string.\n */\nexport function buildTextMarks(format: number, style?: string): TextMarks | undefined {\n const formatMarks = decodeFormatBitmask(format);\n const fontFamily = style ? extractFontFamily(style) : undefined;\n const fontSize = style ? extractFontSizePt(style) : undefined;\n\n const marks: TextMarks = {\n ...formatMarks,\n ...(fontFamily ? { fontFamily } : {}),\n ...(fontSize ? { fontSize } : {}),\n };\n\n return Object.keys(marks).length > 0 ? marks : undefined;\n}\n\n/**\n * Maps a single serialized Lexical inline node to an AST inline node.\n */\nexport function mapInlineNode(node: SerializedInlineNode): InlineNodeAst {\n switch (node.type) {\n case 'text':\n return mapTextNode(node as SerializedTextNode);\n case 'variable-node':\n return mapVariableNode(node as SerializedVariableNode);\n case 'linebreak':\n return mapLineBreak();\n default:\n // Fallback: treat unknown inline nodes as empty text\n return { type: 'text', text: '' };\n }\n}\n\nfunction mapTextNode(node: SerializedTextNode): TextRunAst {\n const marks = buildTextMarks(node.format, node.style);\n return {\n type: 'text',\n text: node.text,\n ...(marks ? { marks } : {}),\n };\n}\n\nfunction mapVariableNode(node: SerializedVariableNode): VariableAst {\n return {\n type: 'variable',\n key: node.variableKey,\n };\n}\n\nfunction mapLineBreak(): LineBreakAst {\n return { type: 'linebreak' };\n}\n\n/**\n * Maps an array of serialized Lexical inline nodes to AST inline nodes.\n */\nexport function mapInlineNodes(nodes: SerializedInlineNode[]): InlineNodeAst[] {\n return nodes.map(mapInlineNode);\n}\n","/**\n * Block mapper — Converts Lexical serialized block nodes to AST block nodes.\n *\n * Handles:\n * - ParagraphNode → ParagraphAst\n * - HeadingNode → HeadingAst\n * - ListNode → ListAst\n * - ListItemNode → ListItemAst (with nested list support)\n * - QuoteNode → BlockQuoteAst\n */\n\nimport type {\n BlockNodeAst,\n ParagraphAst,\n HeadingAst,\n ListAst,\n ListItemAst,\n BlockQuoteAst,\n Alignment,\n InlineNodeAst,\n} from './types';\nimport { mapInlineNodes } from './inline-mapper';\n\n// Lexical format bitmask for element alignment\nconst ALIGN_LEFT = 1;\nconst ALIGN_CENTER = 2;\nconst ALIGN_RIGHT = 3;\nconst ALIGN_JUSTIFY = 4;\n\n/** Generic serialized Lexical element node shape. */\ninterface SerializedElementNode {\n type: string;\n children?: SerializedElementNode[];\n format?: number | string;\n indent?: number;\n direction?: string;\n tag?: string;\n listType?: string;\n start?: number;\n value?: number;\n [key: string]: unknown;\n}\n\nfunction decodeAlignment(format: number | string | undefined): Alignment | undefined {\n if (typeof format === 'string') {\n if (['left', 'center', 'right', 'justify'].includes(format)) {\n return format as Alignment;\n }\n return undefined;\n }\n if (typeof format !== 'number' || format === 0) return undefined;\n switch (format) {\n case ALIGN_LEFT: return 'left';\n case ALIGN_CENTER: return 'center';\n case ALIGN_RIGHT: return 'right';\n case ALIGN_JUSTIFY: return 'justify';\n default: return undefined;\n }\n}\n\n/**\n * Maps a single serialized Lexical block node to an AST block node.\n */\nexport function mapBlockNode(node: SerializedElementNode): BlockNodeAst {\n switch (node.type) {\n case 'paragraph':\n return mapParagraph(node);\n case 'heading':\n return mapHeading(node);\n case 'list':\n return mapList(node);\n case 'quote':\n return mapBlockQuote(node);\n default:\n // Fallback: treat as paragraph with empty children\n return {\n type: 'paragraph',\n children: mapInlineChildren(node),\n };\n }\n}\n\nfunction mapParagraph(node: SerializedElementNode): ParagraphAst {\n const alignment = decodeAlignment(node.format);\n const indent = node.indent && node.indent > 0 ? node.indent : undefined;\n return {\n type: 'paragraph',\n ...(alignment ? { alignment } : {}),\n ...(indent ? { indent } : {}),\n children: mapInlineChildren(node),\n };\n}\n\nfunction mapHeading(node: SerializedElementNode): HeadingAst {\n const alignment = decodeAlignment(node.format);\n const tagMatch = node.tag?.match(/^h(\\d)$/);\n const level = tagMatch ? (parseInt(tagMatch[1], 10) as 1 | 2 | 3 | 4 | 5) : 1;\n return {\n type: 'heading',\n level,\n ...(alignment ? { alignment } : {}),\n children: mapInlineChildren(node),\n };\n}\n\nfunction mapList(node: SerializedElementNode): ListAst {\n const listType = node.listType === 'number' ? 'ordered' : 'unordered';\n const items = (node.children ?? [])\n .filter(c => c.type === 'listitem')\n .map(mapListItem);\n return {\n type: 'list',\n listType,\n items,\n };\n}\n\nfunction mapListItem(node: SerializedElementNode): ListItemAst {\n const inlineChildren: InlineNodeAst[] = [];\n let nestedList: ListAst | undefined;\n\n for (const child of node.children ?? []) {\n if (child.type === 'list') {\n nestedList = mapList(child);\n } else {\n // Inline children\n const mapped = mapInlineNodes([child as never]);\n inlineChildren.push(...mapped);\n }\n }\n\n return {\n type: 'list-item',\n children: inlineChildren,\n ...(nestedList ? { nestedList } : {}),\n };\n}\n\nfunction mapBlockQuote(node: SerializedElementNode): BlockQuoteAst {\n return {\n type: 'blockquote',\n children: mapInlineChildren(node),\n };\n}\n\n/** Extracts inline children from a block node. */\nfunction mapInlineChildren(node: SerializedElementNode): InlineNodeAst[] {\n if (!node.children || node.children.length === 0) return [];\n return mapInlineNodes(node.children as never[]);\n}\n\n/**\n * Maps an array of serialized Lexical block nodes to AST block nodes.\n */\nexport function mapBlockNodes(nodes: SerializedElementNode[]): BlockNodeAst[] {\n return nodes.map(mapBlockNode);\n}\n","/**\n * Content mapper — Converts a Lexical SerializedEditorState to AST content.\n *\n * This module bridges the gap between Lexical's serialized state\n * (which has a root → children hierarchy) and the flat BlockNodeAst[]\n * used in the AST contract.\n */\n\nimport type { SerializedEditorState } from 'lexical';\nimport type { BlockNodeAst, ContentAst } from './types';\nimport { mapBlockNodes } from './block-mapper';\n\n/**\n * Converts a Lexical SerializedEditorState into a ContentAst.\n *\n * Returns null if the state is null/undefined (e.g. disabled header).\n */\nexport function mapEditorStateToContent(\n state: SerializedEditorState | null | undefined,\n): ContentAst | null {\n if (!state || !state.root || !state.root.children) {\n return null;\n }\n\n const blocks = mapBlockNodes(state.root.children as never[]);\n return { blocks };\n}\n\n/**\n * Converts a Lexical SerializedEditorState to flat BlockNodeAst[].\n *\n * Used for body content where we need the array directly\n * rather than wrapped in a ContentAst.\n */\nexport function mapEditorStateToBlocks(\n state: SerializedEditorState | null | undefined,\n): BlockNodeAst[] {\n if (!state || !state.root || !state.root.children) {\n return [];\n }\n\n return mapBlockNodes(state.root.children as never[]);\n}\n","/**\n * Document serializer — Converts a Lex4Document to a DocumentAst.\n *\n * This is the top-level serialization pipeline that orchestrates\n * all sub-mappers (inline, block, content) to produce the final\n * AST contract object.\n */\n\nimport type {\n DocumentAst,\n PageAst,\n VariableDefinitionAst,\n DocumentMetadataAst,\n} from './types';\nimport { AST_VERSION } from './types';\nimport type { Lex4Document } from '../types/document';\nimport type { VariableDefinition } from '../variables/types';\nimport { mapEditorStateToBlocks, mapEditorStateToContent } from './content-mapper';\nimport { PAGE_MARGIN_PX, PX_PER_MM } from '../constants';\n\nconst MARGIN_MM = Math.round((PAGE_MARGIN_PX / PX_PER_MM) * 10) / 10;\n\n/**\n * Serializes a Lex4Document into a clean, backend-friendly DocumentAst.\n *\n * @param document - The current editor document state\n * @param variableDefinitions - Optional variable definitions for metadata\n */\nexport function serializeDocument(\n document: Lex4Document,\n variableDefinitions: VariableDefinition[] = [],\n): DocumentAst {\n const pages: PageAst[] = document.pages.map((page, index) =>\n serializePage(page, index),\n );\n\n const metadata = buildMetadata(variableDefinitions);\n\n return {\n version: AST_VERSION,\n page: {\n format: 'A4',\n widthMm: 210,\n heightMm: 297,\n margins: {\n topMm: MARGIN_MM,\n rightMm: MARGIN_MM,\n bottomMm: MARGIN_MM,\n leftMm: MARGIN_MM,\n },\n },\n headerFooter: {\n enabled: document.headerFooterEnabled,\n pageCounterMode: document.pageCounterMode,\n defaultHeader: document.pages.length > 0\n ? mapEditorStateToContent(document.pages[0].headerState)\n : null,\n defaultFooter: document.pages.length > 0\n ? mapEditorStateToContent(document.pages[0].footerState)\n : null,\n },\n pages,\n metadata,\n };\n}\n\nfunction serializePage(\n page: { bodyState: import('lexical').SerializedEditorState | null; headerState: import('lexical').SerializedEditorState | null; footerState: import('lexical').SerializedEditorState | null },\n pageIndex: number,\n): PageAst {\n return {\n pageIndex,\n body: mapEditorStateToBlocks(page.bodyState),\n header: mapEditorStateToContent(page.headerState),\n footer: mapEditorStateToContent(page.footerState),\n };\n}\n\nfunction buildMetadata(\n variableDefinitions: VariableDefinition[],\n): DocumentMetadataAst {\n const variables: Record<string, VariableDefinitionAst> = {};\n\n for (const def of variableDefinitions) {\n variables[def.key] = {\n key: def.key,\n label: def.label,\n ...(def.description ? { description: def.description } : {}),\n ...(def.valueType ? { valueType: def.valueType } : {}),\n ...(def.group ? { group: def.group } : {}),\n };\n }\n\n return { variables };\n}\n","/**\n * Payload builder — Wraps a DocumentAst into a REST-ready payload.\n *\n * This module provides a simple helper for consumers to construct\n * a request body suitable for sending to a backend document generation API.\n */\n\nimport type { DocumentAst, SaveDocumentRequest } from './types';\n\nexport interface PayloadOptions {\n /** Target export format */\n exportTarget?: 'pdf' | 'docx';\n /** External document identifier */\n documentId?: string;\n /** Additional metadata for the backend */\n metadata?: Record<string, string>;\n}\n\n/**\n * Builds a SaveDocumentRequest payload from a DocumentAst.\n */\nexport function buildSavePayload(\n ast: DocumentAst,\n options?: PayloadOptions,\n): SaveDocumentRequest {\n return {\n document: ast,\n ...(options?.exportTarget ? { exportTarget: options.exportTarget } : {}),\n ...(options?.documentId ? { documentId: options.documentId } : {}),\n ...(options?.metadata ? { metadata: options.metadata } : {}),\n };\n}\n\n/**\n * Serializes a DocumentAst to a JSON string.\n */\nexport function serializeDocumentJson(ast: DocumentAst): string {\n return JSON.stringify(ast, null, 2);\n}\n","import type { Lex4Extension, ExtensionContext } from './types';\nimport { serializeDocument } from '../ast/document-serializer';\nimport { buildSavePayload, serializeDocumentJson } from '../ast/payload-builder';\nimport type { VariableDefinition } from '../variables/types';\n\n/**\n * Creates an AST extension that adds document export capabilities.\n *\n * Handle methods provided:\n * - `getDocumentAst()` — returns the current document as a typed AST\n * - `getDocumentJson()` — returns the AST as a JSON string\n * - `buildSavePayload(options?)` — builds a REST payload wrapping the AST\n *\n * @example\n * ```tsx\n * <Lex4Editor extensions={[astExtension()]} />\n * ```\n */\nexport function astExtension(): Lex4Extension {\n return {\n name: 'ast',\n handleMethods: (ctx: ExtensionContext) => {\n const getDefinitions = (): VariableDefinition[] => {\n return ctx.getExtensionState<VariableDefinition[]>('variableDefinitions') ?? [];\n };\n\n return {\n getDocumentAst: () => {\n const doc = ctx.getDocument();\n return serializeDocument(doc, getDefinitions());\n },\n getDocumentJson: () => {\n const doc = ctx.getDocument();\n const ast = serializeDocument(doc, getDefinitions());\n return serializeDocumentJson(ast);\n },\n buildSavePayload: (options?: Parameters<typeof buildSavePayload>[1]) => {\n const doc = ctx.getDocument();\n const ast = serializeDocument(doc, getDefinitions());\n return buildSavePayload(ast, options);\n },\n };\n },\n };\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type DOMConversionMap,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from 'lexical';\n\nexport type SerializedVariableNode = Spread<\n { variableKey: string },\n SerializedLexicalNode\n>;\n\n/**\n * VariableNode — a custom Lexical DecoratorNode that represents\n * a document variable/placeholder (e.g. \"customer.name\").\n *\n * Variables are atomic, non-editable inline tokens that:\n * - Display as styled chips in the editor\n * - Serialize to a structured node in JSON (not plain text)\n * - Participate in copy/paste, undo/redo, and overflow\n * - Return {{key}} as text content for clipboard\n */\nexport class VariableNode extends DecoratorNode<JSX.Element> {\n __variableKey: string;\n\n static getType(): string {\n return 'variable-node';\n }\n\n static clone(node: VariableNode): VariableNode {\n return new VariableNode(node.__variableKey, node.__key);\n }\n\n constructor(variableKey: string, key?: NodeKey) {\n super(key);\n this.__variableKey = variableKey;\n }\n\n getVariableKey(): string {\n return this.__variableKey;\n }\n\n // -- Serialization --\n\n static importJSON(serializedNode: SerializedVariableNode): VariableNode {\n return $createVariableNode(serializedNode.variableKey);\n }\n\n exportJSON(): SerializedVariableNode {\n return {\n type: 'variable-node',\n version: 1,\n variableKey: this.__variableKey,\n };\n }\n\n // -- DOM --\n\n createDOM(): HTMLElement {\n const span = document.createElement('span');\n span.className = 'lex4-variable';\n span.setAttribute('data-variable-key', this.__variableKey);\n span.setAttribute('data-testid', `variable-${this.__variableKey}`);\n span.contentEditable = 'false';\n return span;\n }\n\n updateDOM(): false {\n return false;\n }\n\n exportDOM(): DOMExportOutput {\n const span = document.createElement('span');\n span.setAttribute('data-variable-key', this.__variableKey);\n span.textContent = `{{${this.__variableKey}}}`;\n return { element: span };\n }\n\n static importDOM(): DOMConversionMap | null {\n return null;\n }\n\n // -- Behavior --\n\n isInline(): boolean {\n return true;\n }\n\n isKeyboardSelectable(): boolean {\n return true;\n }\n\n getTextContent(): string {\n return `{{${this.__variableKey}}}`;\n }\n\n // -- Rendering --\n\n decorate(): JSX.Element {\n return (\n <span\n className=\"lex4-variable-chip inline-flex items-center rounded bg-white px-1.5 py-0.5\n text-xs font-medium text-blue-700 border border-blue-300 select-none\n cursor-default whitespace-nowrap mx-0.5\"\n data-testid={`variable-chip-${this.__variableKey}`}\n title={this.__variableKey}\n >\n {`{{${this.__variableKey}}}`}\n </span>\n );\n }\n}\n\nexport function $createVariableNode(variableKey: string): VariableNode {\n return $applyNodeReplacement(new VariableNode(variableKey));\n}\n\nexport function $isVariableNode(\n node: LexicalNode | null | undefined,\n): node is VariableNode {\n return node instanceof VariableNode;\n}\n","import {\n createCommand,\n type LexicalEditor,\n} from 'lexical';\n\n/**\n * Command to insert a variable node at the current selection.\n * Payload is the variable key string (e.g. \"customer.name\").\n */\nexport const INSERT_VARIABLE_COMMAND = createCommand<string>('INSERT_VARIABLE');\n\n/**\n * Inserts a variable node at the current cursor position.\n */\nexport function insertVariable(editor: LexicalEditor, variableKey: string): void {\n editor.dispatchCommand(INSERT_VARIABLE_COMMAND, variableKey);\n}\n","import { useEffect } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $getSelection,\n $isRangeSelection,\n $insertNodes,\n COMMAND_PRIORITY_EDITOR,\n} from 'lexical';\nimport { $createVariableNode } from './variable-node';\nimport { INSERT_VARIABLE_COMMAND } from './variable-commands';\n\n/**\n * VariablePlugin — registers the INSERT_VARIABLE_COMMAND handler.\n *\n * When the command fires, a VariableNode is created and inserted\n * at the current selection position.\n */\nexport const VariablePlugin: React.FC = () => {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n return editor.registerCommand(\n INSERT_VARIABLE_COMMAND,\n (variableKey: string) => {\n editor.update(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n const variableNode = $createVariableNode(variableKey);\n $insertNodes([variableNode]);\n });\n return true;\n },\n COMMAND_PRIORITY_EDITOR,\n );\n }, [editor]);\n\n return null;\n};\n","import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';\nimport type { VariableDefinition, VariableContextValue } from './types';\n\nconst EMPTY_CONTEXT: VariableContextValue = {\n definitions: [],\n refreshDefinitions: () => { /* no-op when variables extension not loaded */ },\n getDefinition: () => undefined,\n};\n\nconst VariableContext = createContext<VariableContextValue>(EMPTY_CONTEXT);\n\ninterface VariableProviderProps {\n initialDefinitions?: VariableDefinition[];\n children: React.ReactNode;\n}\n\n/**\n * VariableProvider — Manages the variable catalog.\n *\n * Host apps provide variable definitions via props.\n * The picker reads from this context. Definitions can be refreshed\n * at runtime without re-mounting the editor.\n */\nexport const VariableProvider: React.FC<VariableProviderProps> = ({\n initialDefinitions = [],\n children,\n}) => {\n const [definitions, setDefinitions] = useState<VariableDefinition[]>(initialDefinitions);\n\n const refresh = useCallback((newDefinitions: VariableDefinition[]) => {\n setDefinitions(newDefinitions);\n }, []);\n\n const getDefinition = useCallback(\n (key: string): VariableDefinition | undefined => {\n return definitions.find(d => d.key === key);\n },\n [definitions],\n );\n\n const value = useMemo<VariableContextValue>(\n () => ({ definitions, refreshDefinitions: refresh, getDefinition }),\n [definitions, refresh, getDefinition],\n );\n\n return (\n <VariableContext.Provider value={value}>\n {children}\n </VariableContext.Provider>\n );\n};\n\n/**\n * Hook to access the variable catalog from within the editor tree.\n * Returns empty defaults when called outside a VariableProvider.\n */\nexport function useVariables(): VariableContextValue {\n return useContext(VariableContext);\n}\n","import React, { useCallback, useMemo, useState, useRef, useEffect } from 'react';\nimport { useVariables } from '../variables/variable-context';\nimport type { VariableDefinition } from '../variables/types';\n\ninterface VariablePickerProps {\n onInsert: (variableKey: string) => void;\n disabled?: boolean;\n}\n\n/**\n * VariablePicker — Dropdown UI for browsing and inserting variables.\n *\n * Groups variables by their `group` field and allows filtering by name.\n * Clicking a variable calls `onInsert` with its key.\n */\nexport const VariablePicker: React.FC<VariablePickerProps> = ({ onInsert, disabled = false }) => {\n const { definitions } = useVariables();\n const [open, setOpen] = useState(false);\n const [filter, setFilter] = useState('');\n const containerRef = useRef<HTMLDivElement>(null);\n\n const filtered = useMemo(() => {\n if (!filter) return definitions;\n const lower = filter.toLowerCase();\n return definitions.filter(\n d =>\n d.key.toLowerCase().includes(lower) ||\n d.label.toLowerCase().includes(lower),\n );\n }, [definitions, filter]);\n\n const grouped = useMemo(() => {\n const groups: Record<string, VariableDefinition[]> = {};\n for (const def of filtered) {\n const g = def.group ?? 'Other';\n if (!groups[g]) groups[g] = [];\n groups[g].push(def);\n }\n return groups;\n }, [filtered]);\n\n const handleInsert = useCallback(\n (key: string) => {\n onInsert(key);\n setOpen(false);\n setFilter('');\n },\n [onInsert],\n );\n\n // Close on outside click\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setOpen(false);\n setFilter('');\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [open]);\n\n return (\n <div ref={containerRef} className=\"relative inline-block\">\n <button\n type=\"button\"\n className=\"h-7 rounded border border-gray-200 bg-white px-2 text-xs font-medium text-gray-700\n hover:bg-gray-50 focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400\n disabled:opacity-50 disabled:cursor-not-allowed\"\n data-testid=\"variable-picker-button\"\n disabled={disabled || definitions.length === 0}\n onClick={() => setOpen(!open)}\n title=\"Insert variable\"\n >\n {'{x}'}\n </button>\n\n {open && (\n <div\n className=\"absolute left-0 top-full z-50 mt-1 w-64 rounded-md border border-gray-200\n bg-white shadow-lg\"\n data-testid=\"variable-picker-dropdown\"\n >\n <div className=\"border-b border-gray-100 p-2\">\n <input\n type=\"text\"\n className=\"w-full rounded border border-gray-200 px-2 py-1 text-xs\n focus:border-blue-400 focus:outline-none\"\n placeholder=\"Search variables...\"\n data-testid=\"variable-picker-search\"\n value={filter}\n onChange={e => setFilter(e.target.value)}\n autoFocus\n />\n </div>\n\n <div className=\"max-h-48 overflow-y-auto p-1\">\n {Object.keys(grouped).length === 0 && (\n <div className=\"px-2 py-1 text-xs text-gray-400\">No variables found</div>\n )}\n {Object.entries(grouped).map(([group, defs]) => (\n <div key={group}>\n <div className=\"px-2 py-1 text-[10px] font-semibold uppercase text-gray-400\">\n {group}\n </div>\n {defs.map(def => (\n <button\n key={def.key}\n type=\"button\"\n className=\"flex w-full items-center gap-2 rounded px-2 py-1 text-left text-xs\n hover:bg-blue-50\"\n data-testid={`variable-option-${def.key}`}\n onClick={() => handleInsert(def.key)}\n >\n <span className=\"font-medium text-blue-700\">{`{{${def.key}}}`}</span>\n <span className=\"text-gray-500\">{def.label}</span>\n </button>\n ))}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n};\n","import React, { useCallback, useMemo, useState } from 'react';\nimport { Search, RefreshCw } from 'lucide-react';\nimport { EditorSidebar } from './EditorSidebar';\nimport { useVariables } from '../variables/variable-context';\nimport { useDocument } from '../context/document-context';\nimport { useTranslations, interpolate } from '../i18n';\nimport { INSERT_VARIABLE_COMMAND } from '../variables/variable-commands';\nimport type { VariableDefinition } from '../variables/types';\n\n/**\n * VariablePanel — Right sidebar for browsing and inserting variables.\n *\n * Features:\n * - Search/filter variables by name or key\n * - Grouped list with colored badges\n * - Click-to-insert into the active editor\n * - Refresh button for reloading definitions\n */\nexport const VariablePanel: React.FC<{\n open: boolean;\n onClose: () => void;\n}> = ({ open, onClose }) => {\n const { definitions } = useVariables();\n const { activeEditor, runHistoryAction } = useDocument();\n const t = useTranslations();\n const [filter, setFilter] = useState('');\n\n const filtered = useMemo(() => {\n if (!filter) return definitions;\n const lower = filter.toLowerCase();\n return definitions.filter(\n d => d.key.toLowerCase().includes(lower) || d.label.toLowerCase().includes(lower),\n );\n }, [definitions, filter]);\n\n const grouped = useMemo(() => {\n const groups: Record<string, VariableDefinition[]> = {};\n for (const def of filtered) {\n const g = def.group ?? 'Other';\n if (!groups[g]) groups[g] = [];\n groups[g].push(def);\n }\n return groups;\n }, [filtered]);\n\n const handleInsert = useCallback(\n (key: string) => {\n if (!activeEditor) return;\n runHistoryAction(\n { label: interpolate(t.variables.insertVariable, { key }), source: 'toolbar', region: 'document' },\n () => {\n activeEditor.dispatchCommand(INSERT_VARIABLE_COMMAND, key);\n },\n );\n },\n [activeEditor, runHistoryAction],\n );\n\n if (definitions.length === 0) return null;\n\n return (\n <EditorSidebar\n title={t.variables.title}\n subtitle={interpolate(t.variables.available, { count: String(definitions.length) })}\n open={open}\n onClose={onClose}\n testId=\"variable-panel\"\n headerActions={\n <button\n type=\"button\"\n className=\"flex h-6 w-6 items-center justify-center rounded text-gray-400\n transition-colors hover:bg-gray-100 hover:text-gray-600\"\n title={t.variables.refreshVariables}\n data-testid=\"btn-refresh-variables\"\n >\n <RefreshCw size={12} />\n </button>\n }\n >\n <div className=\"p-3\">\n <div className=\"relative\">\n <Search size={14} className=\"absolute left-2.5 top-1/2 -translate-y-1/2 text-gray-400\" />\n <input\n type=\"text\"\n className=\"w-full rounded-lg border border-gray-200 bg-gray-50 py-1.5 pl-8 pr-3 text-xs\n placeholder-gray-400 focus:border-blue-400 focus:bg-white focus:outline-none\n focus:ring-1 focus:ring-blue-400\"\n placeholder={t.variables.searchPlaceholder}\n data-testid=\"variable-panel-search\"\n value={filter}\n onChange={e => setFilter(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"px-3 pb-3\">\n {Object.keys(grouped).length === 0 && (\n <div className=\"py-4 text-center text-xs text-gray-400\">{t.variables.noVariablesFound}</div>\n )}\n {Object.entries(grouped).map(([group, defs]) => (\n <div key={group} className=\"mb-3\">\n <div className=\"flex flex-col gap-1\">\n {defs.map(def => (\n <button\n key={def.key}\n type=\"button\"\n className=\"flex items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-xs\n transition-colors hover:bg-blue-50 group\"\n data-testid={`variable-panel-${def.key}`}\n onClick={() => handleInsert(def.key)}\n disabled={!activeEditor}\n >\n <span\n className=\"inline-flex items-center rounded-full border border-blue-300 bg-white\n px-2 py-0.5 text-[11px] font-medium text-blue-700\n group-hover:border-blue-400 group-hover:bg-blue-50\"\n >\n {def.label}\n </span>\n <span className=\"text-[10px] font-semibold uppercase tracking-wider text-gray-400\">{group}</span>\n </button>\n ))}\n </div>\n </div>\n ))}\n </div>\n </EditorSidebar>\n );\n};\n","import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';\nimport { Braces } from 'lucide-react';\nimport type { Lex4Extension, ExtensionContext } from './types';\nimport type { VariableDefinition } from '../variables/types';\nimport { VariableNode } from '../variables/variable-node';\nimport { VariablePlugin } from '../variables/variable-plugin';\nimport { VariableProvider, useVariables } from '../variables/variable-context';\nimport { VariablePicker } from '../components/VariablePicker';\nimport { VariablePanel } from '../components/VariablePanel';\nimport { INSERT_VARIABLE_COMMAND } from '../variables/variable-commands';\nimport { useDocument } from '../context/document-context';\nimport { useExtensionState } from './extension-context';\nimport { useTranslations, interpolate } from '../i18n';\n\n// --- Variable panel open/close context ---\n\ninterface VariablePanelState {\n panelOpen: boolean;\n setPanelOpen: (open: boolean) => void;\n}\n\nconst VariablePanelContext = createContext<VariablePanelState>({\n panelOpen: false,\n setPanelOpen: () => {},\n});\n\nexport function useVariablePanelState(): VariablePanelState {\n return useContext(VariablePanelContext);\n}\n\nconst VariablePanelStateProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const [panelOpen, setPanelOpen] = useState(false);\n return (\n <VariablePanelContext.Provider value={{ panelOpen, setPanelOpen }}>\n {children}\n </VariablePanelContext.Provider>\n );\n};\n\n/**\n * Toolbar item contributed by the variables extension.\n * Wires the VariablePicker to the active editor and document context.\n */\nconst VariableToolbarItem: React.FC = () => {\n const { activeEditor, runHistoryAction } = useDocument();\n const t = useTranslations();\n\n const handleInsert = useCallback((variableKey: string) => {\n runHistoryAction(\n { label: interpolate(t.variables.insertVariable, { key: variableKey }), source: 'toolbar', region: 'document' },\n () => {\n if (activeEditor) {\n activeEditor.dispatchCommand(INSERT_VARIABLE_COMMAND, variableKey);\n }\n },\n );\n }, [activeEditor, runHistoryAction]);\n\n return (\n <VariablePicker\n onInsert={handleInsert}\n disabled={!activeEditor}\n />\n );\n};\n\n/**\n * Toolbar toggle button for the Variables side panel.\n */\nconst VariablePanelToggle: React.FC = () => {\n const { panelOpen, setPanelOpen } = useVariablePanelState();\n const t = useTranslations();\n\n return (\n <button\n type=\"button\"\n title={panelOpen ? t.variables.closePanel : t.variables.openPanel}\n aria-label={panelOpen ? t.variables.closePanel : t.variables.openPanel}\n onMouseDown={e => e.preventDefault()}\n onClick={() => setPanelOpen(!panelOpen)}\n className={`\n flex h-7 w-7 items-center justify-center rounded transition-colors\n ${panelOpen\n ? 'bg-blue-50 text-blue-600'\n : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'}\n `}\n data-testid=\"toggle-variable-panel\"\n >\n <Braces size={15} />\n </button>\n );\n};\n\n/**\n * Wrapped VariablePanel that reads open/close state from VariablePanelContext.\n */\nconst VariablePanelWithState: React.FC = () => {\n const { panelOpen, setPanelOpen } = useVariablePanelState();\n return <VariablePanel open={panelOpen} onClose={() => setPanelOpen(false)} />;\n};\n\n/**\n * Syncs the VariableProvider definitions into the extension state store\n * so astExtension can access them when building the AST.\n */\nconst VariableDefinitionsSync: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { definitions } = useVariables();\n const extState = useExtensionState();\n\n useEffect(() => {\n extState.set('variableDefinitions', definitions);\n }, [definitions, extState]);\n\n return <>{children}</>;\n};\n\n/**\n * Creates a variables extension that adds variable/placeholder support.\n *\n * Contributes:\n * - VariableNode (custom Lexical node)\n * - VariablePlugin (body plugin for insert command handling)\n * - VariableProvider (context provider for variable catalog)\n * - VariablePicker toolbar item + panel toggle button\n * - VariablePanel side panel with toggle state\n * - Handle methods: insertVariable, refreshVariables\n *\n * @param definitions Initial variable definitions to load\n *\n * @example\n * ```tsx\n * const defs = [\n * { key: 'customer.name', label: 'Customer', group: 'Customer', valueType: 'string' },\n * ];\n * <Lex4Editor extensions={[variablesExtension(defs)]} />\n * ```\n */\nexport function variablesExtension(definitions: VariableDefinition[] = []): Lex4Extension {\n const ProviderWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n return (\n <VariablePanelStateProvider>\n <VariableProvider initialDefinitions={definitions}>\n <VariableDefinitionsSync>\n {children}\n </VariableDefinitionsSync>\n </VariableProvider>\n </VariablePanelStateProvider>\n );\n };\n\n return {\n name: 'variables',\n nodes: [VariableNode],\n bodyPlugins: [VariablePlugin],\n toolbarItems: [VariableToolbarItem, VariablePanelToggle],\n sidePanel: VariablePanelWithState,\n provider: ProviderWrapper,\n handleMethods: (ctx: ExtensionContext) => ({\n insertVariable: (key: string) => {\n const editor = ctx.getActiveEditor();\n if (editor) {\n editor.dispatchCommand(INSERT_VARIABLE_COMMAND, key);\n }\n },\n refreshVariables: (newDefs: VariableDefinition[]) => {\n ctx.setExtensionState('variableDefinitions', newDefs);\n },\n }),\n };\n}\n"],"names":["document","__iconNode","jumpToHistoryEntry","AlignLeft","AlignCenter","AlignRight","AlignJustify","IndentIncrease","IndentDecrease"],"mappings":"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","x_google_ignoreList":[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38]}