@matops/editor 0.1.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.
- package/README.md +277 -0
- package/dist/index.d.ts +1140 -0
- package/dist/index.esm.js +9067 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +9067 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +4710 -0
- package/package.json +99 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../shared/editor/core/context/EditorProvider.tsx","../shared/editor/core/types.ts","../shared/editor/core/registry/featureRegistry.ts","../shared/editor/extensions/features/historyFeature.ts","../shared/editor/extensions/features/placeholderFeature.ts","../shared/editor/extensions/features/characterCountFeature.ts","../shared/editor/extensions/plugins/searchPlugin.ts","../shared/editor/extensions/features/findReplaceFeature.ts","../shared/editor/extensions/plugins/pageHeaderGuardPlugin.ts","../shared/editor/extensions/features/coverImageFeature.ts","../shared/editor/extensions/features/pageHeaderFeature.ts","../shared/editor/extensions/plugins/attachmentsGuardPlugin.ts","../shared/editor/extensions/features/attachmentsFeature.ts","../shared/editor/extensions/features/mediaFeature.ts","../shared/editor/extensions/features/tablesFeature.ts","../shared/editor/extensions/features/collaborationFeature.ts","../shared/editor/extensions/formatting/formattingFeature.ts","../shared/editor/extensions/formatting/codeFeature.ts","../shared/editor/extensions/formatting/taskListFeature.ts","../shared/editor/extensions/nodes/documentNode.ts","../shared/editor/utils/constants/index.ts","../shared/editor/core/registry/editorConfigBuilder.ts","../shared/editor/utils/helpers/docHelpers.ts","../shared/editor/utils/hooks/useEditorInstance.ts","../shared/editor/utils/hooks/useEditorKeyboard.ts","../shared/editor/utils/hooks/useShortcutsModal.ts","../shared/editor/utils/hooks/useImageUpload.ts","../shared/editor/core/context/editorHooks.ts","../shared/editor/ui/commands/commandRegistry.ts","../shared/editor/ui/icons/index.tsx","../shared/editor/utils/helpers/cn.ts","../shared/editor/ui/toolbar/TableTriggerButton.tsx","../shared/editor/utils/hooks/useDropdown.ts","../shared/editor/ui/toolbar/EditorToolbar.tsx","../shared/editor/ui/primitives/CharacterCountBar.tsx","../shared/editor/ui/primitives/ModalPrimitives.tsx","../shared/editor/ui/modals/KeyboardShortcutsModal.tsx","../shared/editor/ui/modals/FindReplacePanel.tsx","../shared/editor/viewer/viewerExtensions.ts","../shared/editor/utils/markdown/index.ts","../shared/editor/utils/helpers/cropHelpers.ts","../shared/editor/ui/primitives/TitleSeparator.tsx","../shared/editor/ui/primitives/fileUtils.tsx","../shared/editor/ui/node-views/AttachmentsSectionView.tsx","../shared/editor/extensions/nodes/attachmentsNode.ts","../shared/editor/ui/modals/ExportPanel.tsx","../shared/editor/viewer/ViewerStatBar.tsx","../shared/editor/viewer/MatopsViewer.tsx","../shared/editor/ui/modals/CropModal.tsx","../shared/editor/ui/panels/CoverImagePanel.tsx","../shared/editor/ui/panels/TitlePanel.tsx","../shared/editor/ui/panels/SeparatorIconPanel.tsx","../shared/editor/ui/panels/AttachmentsPanel.tsx","../shared/editor/ui/menus/FormattingBubbleMenu.tsx","../shared/editor/ui/menus/BlockFloatingMenu.tsx","../shared/editor/ui/menus/SlashMenu.tsx","../shared/editor/ui/primitives/MenuButton.tsx","../shared/editor/ui/menus/TableContextMenu.tsx","../shared/editor/utils/helpers/tableHelpers.ts","../shared/editor/ui/menus/TableHandles.tsx","../shared/editor/ui/menus/TableExtendButtons.tsx","../shared/editor/ui/menus/LinkPopover.tsx","../shared/editor/ui/menus/ImageBubbleMenu.tsx","../shared/editor/core/components/EditorMenus.tsx","../shared/editor/core/components/EditorComposer.tsx","../shared/editor/core/components/MatopsEditor.tsx","../shared/editor/ui/node-views/CoverImageView.tsx","../shared/editor/extensions/nodes/coverImageNode.ts","../shared/editor/ui/node-views/TitleView.tsx","../shared/editor/extensions/nodes/titleNode.ts","../shared/editor/ui/node-views/SeparatorIconView.tsx","../shared/editor/extensions/nodes/separatorIconNode.ts"],"sourcesContent":["import {\n createContext,\n useContext,\n useMemo,\n type ReactNode,\n} from \"react\";\nimport {\n type EditorContextValue,\n type MatopsEditorFeature,\n type MatopsEditorTheme,\n} from \"@matops/editor/core/types\";\nimport type { Editor } from \"@tiptap/core\";\n\n// ─────────────────────────────────────────────\n// Context\n// ─────────────────────────────────────────────\n\nconst EditorContext = createContext<EditorContextValue | null>(null);\nEditorContext.displayName = \"MatopsEditorContext\";\n\n// ─────────────────────────────────────────────\n// Provider Props\n// ─────────────────────────────────────────────\n\ninterface EditorProviderProps {\n children: ReactNode;\n editor: Editor | null;\n features: MatopsEditorFeature[];\n theme: MatopsEditorTheme;\n editable: boolean;\n onFileUploaded?: (file: File) => Promise<string>;\n separatorIcon?: ReactNode;\n}\n\n// ─────────────────────────────────────────────\n// Provider\n// ─────────────────────────────────────────────\n\nexport function EditorProvider({\n children,\n editor,\n features,\n theme,\n editable,\n onFileUploaded,\n separatorIcon,\n}: EditorProviderProps) {\n /**\n * Convert features array → Set for O(1) lookups\n */\n const featureSet = useMemo(() => new Set(features), [features]);\n\n /**\n * Stable context value\n */\n const value = useMemo<EditorContextValue>(\n () => ({\n editor,\n features,\n featureSet,\n theme,\n editable,\n onFileUploaded,\n separatorIcon,\n }),\n [editor, featureSet, theme, editable, onFileUploaded, separatorIcon],\n );\n\n return (\n <EditorContext.Provider value={value}>{children}</EditorContext.Provider>\n );\n}\n\n// ─────────────────────────────────────────────\n// Context Accessor\n// ─────────────────────────────────────────────\n\n/**\n * Returns the raw EditorContext value.\n * Use the focused hooks in editorHooks.ts for most cases — this is\n * only needed when accessing onFileUploaded or separatorIcon directly.\n */\nexport function useEditorContext(): EditorContextValue {\n const ctx = useContext(EditorContext);\n\n if (!ctx) {\n throw new Error(\n \"[MatopsEditor] useEditorContext must be used inside <EditorProvider>.\",\n );\n }\n\n return ctx;\n}\n","import type { Editor, JSONContent, Extensions } from \"@tiptap/core\";\nimport type { Doc } from \"yjs\";\nimport type { ReactNode } from \"react\";\n\n/* ────────────────────────────────────────────\n Features\n──────────────────────────────────────────── */\n\nexport const EditorFeatures = {\n formatting: \"formatting\",\n code: \"code\",\n media: \"media\",\n tables: \"tables\",\n taskList: \"task-list\",\n layout: \"layout\",\n collaboration: \"collaboration\",\n history: \"history\",\n slashCommand: \"slash-command\",\n placeholder: \"placeholder\",\n characterCount: \"character-count\",\n findReplace: \"find-replace\",\n coverImage: \"cover-image\",\n pageHeader: \"page-header\",\n attachments: \"attachments\",\n} as const;\n\nexport type MatopsEditorFeature =\n (typeof EditorFeatures)[keyof typeof EditorFeatures];\n\n/* ────────────────────────────────────────────\n Theme\n──────────────────────────────────────────── */\n\nexport const EditorThemes = {\n light: \"light\",\n dark: \"dark\",\n} as const;\n\nexport type MatopsEditorTheme =\n (typeof EditorThemes)[keyof typeof EditorThemes];\n\n/* ────────────────────────────────────────────\n Layout\n──────────────────────────────────────────── */\n\nexport const ContentWidths = {\n full: \"full\",\n normal: \"normal\",\n compact: \"compact\",\n} as const;\n\nexport type MatopsContentWidth =\n (typeof ContentWidths)[keyof typeof ContentWidths];\n\nexport interface DocLayout {\n contentWidth?: MatopsContentWidth;\n}\n\n/* ────────────────────────────────────────────\n Doc Attributes\n──────────────────────────────────────────── */\n\nexport interface CoverImageDocAttr {\n src: string | null;\n alt: string;\n objectPosition: string;\n cropX: number;\n cropY: number;\n cropWidth: number;\n cropHeight: number;\n}\n\nexport interface TitleDocAttr {\n text: string;\n placeholder: string;\n}\n\nexport interface SeparatorIconDocAttr {\n src: string | null;\n alt: string;\n cropX: number;\n cropY: number;\n cropWidth: number;\n cropHeight: number;\n}\n\nexport interface AttachmentsDocAttr {\n items: string;\n}\n\nexport interface DocAttrs {\n contentWidth?: MatopsContentWidth;\n coverImage?: CoverImageDocAttr | null;\n title?: TitleDocAttr | null;\n separatorIcon?: SeparatorIconDocAttr | null;\n attachments?: AttachmentsDocAttr | null;\n}\n\n/* ────────────────────────────────────────────\n Crop\n──────────────────────────────────────────── */\n\nexport interface CropRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/* ────────────────────────────────────────────\n Node Attrs\n──────────────────────────────────────────── */\n\nexport interface CoverImageAttrs {\n src: string | null;\n alt: string;\n objectPosition: string;\n cropX: number;\n cropY: number;\n cropWidth: number;\n cropHeight: number;\n}\n\nexport interface TitleAttrs {\n placeholder: string;\n}\n\nexport interface SeparatorIconAttrs {\n src: string | null;\n alt: string;\n cropX: number;\n cropY: number;\n cropWidth: number;\n cropHeight: number;\n}\n\n/* ────────────────────────────────────────────\n Attachments\n──────────────────────────────────────────── */\n\nexport interface AttachmentItem {\n id: string;\n name: string;\n size: number;\n mimeType: string;\n url: string;\n}\n\nexport interface AttachmentsAttrs {\n items: string;\n}\n\n/* ────────────────────────────────────────────\n Collaboration\n──────────────────────────────────────────── */\n\nexport interface CollaborationUser {\n name: string;\n color: string;\n avatar?: string;\n}\n\nexport interface CollaborationProvider {\n document: Doc;\n user?: CollaborationUser;\n}\n\n/* ────────────────────────────────────────────\n Editor Props\n──────────────────────────────────────────── */\n\nexport interface EditorProps {\n features?: MatopsEditorFeature[];\n\n initialContent?: JSONContent;\n\n theme?: MatopsEditorTheme;\n\n editable?: boolean;\n\n placeholder?: string;\n\n collaborationProvider?: CollaborationProvider;\n\n className?: string;\n\n onChange?: (json: JSONContent) => void;\n\n onContentChange?: (html: string, json: JSONContent) => void;\n\n onPublish?: (content: JSONContent) => void;\n\n onFileUploaded?: (file: File) => Promise<string>;\n\n onEditorReady?: (editor: Editor) => void;\n\n separatorIcon?: ReactNode;\n}\n\n/* ────────────────────────────────────────────\n Viewer Props\n──────────────────────────────────────────── */\n\nexport interface EditorViewerProps {\n content: JSONContent;\n\n theme?: MatopsEditorTheme;\n\n className?: string;\n\n features?: MatopsEditorFeature[];\n\n separatorIcon?: ReactNode;\n\n showStats?: boolean;\n}\n\n/* ────────────────────────────────────────────\n Feature Registry\n──────────────────────────────────────────── */\n\nexport interface FeatureDefinition {\n name: MatopsEditorFeature;\n extensions: Extensions;\n dependencies?: MatopsEditorFeature[];\n enabled?: (activeFeatures: MatopsEditorFeature[]) => boolean;\n}\n\n/* ────────────────────────────────────────────\n Internal Config\n──────────────────────────────────────────── */\n\nexport interface ResolvedEditorConfig {\n resolvedFeatures: MatopsEditorFeature[];\n extensions: Extensions;\n}\n\n/* ────────────────────────────────────────────\n React Context\n──────────────────────────────────────────── */\n\nexport interface EditorContextValue {\n editor: Editor | null;\n features: MatopsEditorFeature[];\n featureSet: Set<MatopsEditorFeature>;\n theme: MatopsEditorTheme;\n editable: boolean;\n onFileUploaded?: (file: File) => Promise<string>;\n separatorIcon?: ReactNode;\n}\n","import type { Extensions } from \"@tiptap/core\";\nimport type {\n MatopsEditorFeature,\n FeatureDefinition,\n ResolvedEditorConfig,\n} from \"@matops/editor/core/types\";\n\n// ─────────────────────────────────────────────\n// Feature Registry\n// ─────────────────────────────────────────────\n\nclass FeatureRegistry {\n private readonly registry = new Map<MatopsEditorFeature, FeatureDefinition>();\n\n // ──────────────────────────────────────────\n // Public API\n // ──────────────────────────────────────────\n\n register(definition: FeatureDefinition): void {\n if (this.registry.has(definition.name)) {\n console.warn(\n `[FeatureRegistry] Feature \"${definition.name}\" is already registered. Overwriting.`,\n );\n }\n\n this.registry.set(definition.name, definition);\n }\n\n resolve(requestedFeatures: MatopsEditorFeature[]): ResolvedEditorConfig {\n const resolved = this.resolveDependencies(requestedFeatures);\n const activeFeatures = this.filterEnabled(resolved);\n const extensions = this.collectExtensions(activeFeatures);\n\n return {\n resolvedFeatures: activeFeatures,\n extensions,\n };\n }\n\n has(name: MatopsEditorFeature): boolean {\n return this.registry.has(name);\n }\n\n get(name: MatopsEditorFeature): FeatureDefinition | undefined {\n return this.registry.get(name);\n }\n\n list(): MatopsEditorFeature[] {\n return [...this.registry.keys()];\n }\n\n get size(): number {\n return this.registry.size;\n }\n\n unregister(name: MatopsEditorFeature): void {\n this.registry.delete(name);\n }\n\n clear(): void {\n this.registry.clear();\n }\n\n // ──────────────────────────────────────────\n // Private Helpers\n // ──────────────────────────────────────────\n\n private resolveDependencies(\n features: MatopsEditorFeature[],\n ): MatopsEditorFeature[] {\n const result: MatopsEditorFeature[] = [];\n const visited = new Set<MatopsEditorFeature>();\n\n const visit = (feature: MatopsEditorFeature) => {\n if (visited.has(feature)) return;\n\n const definition = this.registry.get(feature);\n\n if (!definition) {\n console.warn(\n `[FeatureRegistry] Feature \"${feature}\" is not registered. Skipping.`,\n );\n return;\n }\n\n visited.add(feature);\n\n const deps = definition.dependencies;\n if (deps?.length) {\n for (const dep of deps) {\n visit(dep);\n }\n }\n\n result.push(feature);\n };\n\n for (const feature of features) {\n visit(feature);\n }\n\n return result;\n }\n\n private filterEnabled(\n features: MatopsEditorFeature[],\n ): MatopsEditorFeature[] {\n const result: MatopsEditorFeature[] = [];\n\n for (const feature of features) {\n const definition = this.registry.get(feature);\n\n if (!definition) continue;\n\n if (definition.enabled?.(features) ?? true) {\n result.push(feature);\n }\n }\n\n return result;\n }\n\n private collectExtensions(features: MatopsEditorFeature[]): Extensions {\n const extensions: Extensions = [];\n\n for (const feature of features) {\n const def = this.registry.get(feature);\n if (def?.extensions?.length) {\n extensions.push(...def.extensions);\n }\n }\n\n return extensions;\n }\n}\n\n// ─────────────────────────────────────────────\n// Singleton Export\n// ─────────────────────────────────────────────\n\nexport const featureRegistry = new FeatureRegistry();\n\nexport function registerFeature(definition: FeatureDefinition): void {\n featureRegistry.register(definition);\n}\n","/**\n * @feature history\n *\n * v3 NOTE: History extension is now called UndoRedo and lives in\n * the consolidated @tiptap/extensions package.\n *\n * The feature name stays \"history\" for public API backward compat.\n *\n * Disabled when \"collaboration\" is active — Yjs provides its own CRDT undo.\n */\nimport { UndoRedo } from \"@tiptap/extensions\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\nimport { EditorFeatures } from \"@matops/editor/core/types\";\n\nregisterFeature({\n name: \"history\",\n extensions: [UndoRedo],\n dependencies: [],\n enabled: (activeFeatures) =>\n !activeFeatures.includes(EditorFeatures.collaboration),\n});\n","/**\n * @feature placeholder\n *\n * Registers \"placeholder\" as a known feature name so the registry and\n * dependency system recognise it. The actual Placeholder extension instance\n * is NOT created here because it needs the runtime `placeholder` string from\n * the consuming app's prop — a value that doesn't exist at module-load time.\n *\n * The extension is instantiated in editorConfigBuilder.ts exactly like\n * CollaborationExtension, where runtime values are available.\n *\n * This is the same pattern used by the \"collaboration\" feature.\n */\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"placeholder\",\n extensions: [], // Instantiated at runtime by editorConfigBuilder.ts\n dependencies: [],\n});\n","/**\n * @feature character-count\n *\n * v3 NOTE: CharacterCount is now from the consolidated @tiptap/extensions package.\n */\nimport { CharacterCount } from \"@tiptap/extensions\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"character-count\",\n extensions: [\n CharacterCount.configure({ limit: null }),\n ],\n dependencies: [],\n});\n","/**\n * Search Plugin\n *\n * A ProseMirror Plugin + Tiptap Extension that powers find-and-replace.\n * Uses DecorationSet to highlight matches in real-time without modifying\n * the document. Separated from the UI panel (FindReplacePanel) so the\n * extension layer never imports from the UI layer.\n */\nimport { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport type { Node as PmNode } from \"@tiptap/pm/model\";\n\n// ─────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────\n\nexport interface SearchMatch {\n from: number;\n to: number;\n}\n\ninterface SearchPluginState {\n query: string;\n caseSensitive: boolean;\n decorations: DecorationSet;\n results: SearchMatch[];\n currentIndex: number;\n}\n\n// ─────────────────────────────────────────────\n// Plugin Key (exported so UI can dispatch meta)\n// ─────────────────────────────────────────────\n\nexport const searchPluginKey = new PluginKey<SearchPluginState>(\"matopsSearch\");\n\n// ─────────────────────────────────────────────\n// Core search logic\n// ─────────────────────────────────────────────\n\nfunction findMatches(doc: PmNode, query: string, caseSensitive: boolean): SearchMatch[] {\n if (!query) return [];\n\n const results: SearchMatch[] = [];\n const needle = caseSensitive ? query : query.toLowerCase();\n\n doc.descendants((node, pos) => {\n if (!node.isText || !node.text) return;\n const haystack = caseSensitive ? node.text : node.text.toLowerCase();\n let idx = haystack.indexOf(needle);\n while (idx !== -1) {\n results.push({ from: pos + idx, to: pos + idx + query.length });\n idx = haystack.indexOf(needle, idx + 1);\n }\n });\n\n return results;\n}\n\nfunction buildDecorationSet(\n doc: PmNode,\n results: SearchMatch[],\n currentIndex: number\n): DecorationSet {\n if (!results.length) return DecorationSet.empty;\n\n return DecorationSet.create(\n doc,\n results.map((r, i) =>\n Decoration.inline(r.from, r.to, {\n class: i === currentIndex\n ? \"mat-search-highlight mat-search-current\"\n : \"mat-search-highlight\",\n })\n )\n );\n}\n\n// ─────────────────────────────────────────────\n// Tiptap Extension\n// ─────────────────────────────────────────────\n\nexport const SearchExtension = Extension.create({\n name: \"matopsSearch\",\n\n addProseMirrorPlugins() {\n return [\n new Plugin<SearchPluginState>({\n key: searchPluginKey,\n\n state: {\n init: () => ({\n query: \"\",\n caseSensitive: false,\n decorations: DecorationSet.empty,\n results: [],\n currentIndex: 0,\n }),\n\n apply(tr, prev) {\n const meta = tr.getMeta(searchPluginKey) as Partial<SearchPluginState> | undefined;\n\n // State update dispatched from UI\n if (meta !== undefined) {\n const next: SearchPluginState = { ...prev, ...meta };\n const results = findMatches(tr.doc, next.query, next.caseSensitive);\n const currentIndex = Math.min(next.currentIndex, Math.max(0, results.length - 1));\n return {\n ...next,\n results,\n currentIndex,\n decorations: buildDecorationSet(tr.doc, results, currentIndex),\n };\n }\n\n // Document changed — re-run search with same params\n if (tr.docChanged && prev.query) {\n const results = findMatches(tr.doc, prev.query, prev.caseSensitive);\n const currentIndex = Math.min(prev.currentIndex, Math.max(0, results.length - 1));\n return {\n ...prev,\n results,\n currentIndex,\n decorations: buildDecorationSet(tr.doc, results, currentIndex),\n };\n }\n\n return prev;\n },\n },\n\n props: {\n decorations(state) {\n return searchPluginKey.getState(state)?.decorations;\n },\n },\n }),\n ];\n },\n});\n","/**\n * @feature find-replace\n *\n * Registers the ProseMirror search decoration plugin.\n * The UI lives in ui/modals/FindReplacePanel.tsx — no circular dependency.\n */\nimport { SearchExtension } from \"@matops/editor/extensions/plugins/searchPlugin\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"find-replace\",\n extensions: [SearchExtension],\n dependencies: [],\n});\n","/**\n * pageHeaderGuardPlugin — formerly guarded cover-image, title, and separator-icon\n * content nodes from deletion/displacement.\n *\n * ## Structural nodes removed from content[]\n *\n * As of the 3-panel architecture, cover-image, title, and separator-icon are\n * no longer ProseMirror content nodes. They live in `doc.attrs` and are rendered\n * as pure React panels (CoverImagePanel, TitlePanel, SeparatorIconPanel) above\n * <EditorContent>. There are no structural nodes left to protect.\n *\n * These extensions are kept as empty stubs so the feature registry remains\n * consistent — removing them would require updating all import sites.\n */\n\nimport { Extension } from \"@tiptap/core\";\n\n/**\n * CoverImageGuard — stub extension for the `\"cover-image\"` feature.\n * Previously guarded the cover-image content node; now a no-op since\n * cover-image data lives in doc.attrs.\n */\nexport const CoverImageGuard = Extension.create({\n name: \"coverImageGuard\",\n});\n\n/**\n * PageHeaderGuard — stub extension for the `\"page-header\"` feature.\n * Previously guarded title + separator-icon content nodes; now a no-op since\n * those sections live in doc.attrs and are rendered as React panels.\n */\nexport const PageHeaderGuard = Extension.create({\n name: \"pageHeaderGuard\",\n});\n\n","/**\n * @feature cover-image\n *\n * Controls the cover/banner image at the top of the document.\n * This is fully independent from the \"page-header\" (title) feature —\n * you can have a cover without a title, or a title without a cover.\n *\n * Enabling this feature:\n * - Adds CoverImageGuard → prevents deletion of the cover-image node\n * and blocks cursor / content from landing inside the cover zone.\n * - Activates edit controls inside CoverImageView (Change, Crop, Remove,\n * drag-drop, and the \"Add cover image\" empty-state button).\n *\n * Disabling this feature:\n * - The cover-image node renders as a static <img> (or nothing if src is null).\n * - No upload/edit controls are shown.\n * - Guard plugin is absent — the node can be deleted.\n *\n * NOTE: CoverImageNode is always in BASE_EXTENSIONS to prevent schema crashes\n * when a saved document containing a cover-image node is loaded while this\n * feature is disabled.\n */\n\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\nimport { CoverImageGuard } from \"@matops/editor/extensions/plugins/pageHeaderGuardPlugin\";\n\nregisterFeature({\n name: \"cover-image\",\n extensions: [CoverImageGuard],\n dependencies: [],\n});\n","/**\n * @feature page-header\n *\n * Controls the title + separator-icon area of the document.\n *\n * Enabling this feature:\n * - Adds PageHeaderGuard → prevents deletion of title / separator-icon nodes\n * and blocks cursor / content from landing inside the title zone.\n * - Activates edit controls inside TitleView and SeparatorIconView.\n *\n * Disabling this feature:\n * - title and separator-icon nodes render as static read-only content.\n * - No upload/edit controls are shown on the separator icon.\n * - Guard plugin is absent — nodes can be deleted.\n *\n * NOTE: The node types themselves (TitleNode, SeparatorIconNode) are always in\n * BASE_EXTENSIONS to prevent \"Unknown node type\" crashes when a document that\n * includes these nodes is loaded while the feature is disabled.\n *\n * @see \"cover-image\" feature — independently controls the cover/banner image.\n */\n\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\nimport { PageHeaderGuard } from \"@matops/editor/extensions/plugins/pageHeaderGuardPlugin\";\n\nregisterFeature({\n name: \"page-header\",\n extensions: [PageHeaderGuard],\n dependencies: [],\n});\n","/**\n * attachmentsGuardPlugin — formerly guarded the `attachments` content node.\n *\n * ## Attachments removed from content[]\n *\n * As of the 3-panel architecture, the attachments section is stored in\n * `doc.attrs.attachments` and rendered as a pure React panel (AttachmentsPanel)\n * below <EditorContent>. There is no `attachments` content node left to guard.\n *\n * This extension is kept as an empty stub so the feature registry remains\n * consistent — removing it would require updating all import sites.\n */\n\nimport { Extension } from \"@tiptap/core\";\n\n/**\n * AttachmentsGuard — stub extension for the `\"attachments\"` feature.\n * Previously guarded the attachments content node; now a no-op since\n * attachments data lives in doc.attrs and is rendered as a React panel.\n */\nexport const AttachmentsGuard = Extension.create({\n name: \"attachmentsGuard\",\n});\n\n","/**\n * @feature attachments\n *\n * Controls the attachments section behaviour: cursor/insertion guards and\n * the file upload UI in AttachmentsSectionView.\n *\n * NOTE: The node TYPE itself (AttachmentsNode) is always registered in\n * BASE_EXTENSIONS (editorConfigBuilder.ts) regardless of whether this feature\n * is active. This prevents \"Unknown node type: attachments\" crashes when a\n * document containing an attachments node is loaded while the feature is\n * temporarily disabled.\n *\n * Enabling this feature:\n * - Adds AttachmentsGuard → prevents cursor from landing after the\n * attachments node and blocks content insertion after it.\n * - Activates the \"Add attachment\" button and file removal controls in\n * AttachmentsSectionView (hidden when feature is off).\n *\n * Disabling this feature:\n * - The attachments node in the document renders as a static read-only\n * file list (download links, no add/remove controls).\n * - Guard plugin is absent — cursor can navigate past the node.\n */\n\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\nimport { AttachmentsGuard } from \"@matops/editor/extensions/plugins/attachmentsGuardPlugin\";\n\nregisterFeature({\n name: \"attachments\",\n extensions: [AttachmentsGuard],\n dependencies: [],\n});\n","/**\n * @feature media\n *\n * Provides image embedding support.\n * The editor does NOT upload files — it calls `onFileUploaded` from EditorProps\n * and receives a URL back. The URL is then embedded as an image node.\n *\n * Future additions to this feature:\n * - Video embeds\n * - File attachments\n * - Image resizing (via custom NodeView)\n */\n\nimport Image from \"@tiptap/extension-image\";\nimport Link from \"@tiptap/extension-link\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"media\",\n extensions: [\n Image.configure({\n inline: false,\n allowBase64: false, // Prefer URL-based images via onFileUploaded\n HTMLAttributes: {\n class: \"matops-editor__image\",\n loading: \"lazy\",\n },\n }),\n Link.configure({\n openOnClick: false, // Let the app decide how to handle link clicks\n autolink: true,\n linkOnPaste: true,\n HTMLAttributes: {\n rel: \"noopener noreferrer\",\n target: \"_blank\",\n class: \"matops-editor__link\",\n },\n }),\n ],\n dependencies: [],\n});\n","/**\n * @feature tables\n *\n * Provides rich table support built on top of @tiptap/extension-table's\n * TableKit bundle (Table + TableRow + TableHeader + TableCell).\n *\n * ── What this feature provides ────────────────────────────────────────\n *\n * Extensions (Tiptap)\n * • Table — the table node with column-resize handles\n * • TableRow — <tr> node\n * • TableHeader — <th> node with default header styling\n * • TableCell — <td> node\n *\n * UI (activated automatically when this feature is resolved)\n * • Toolbar button — \"Insert Table\" icon in the toolbar block strip\n * • Slash command — /table inserts a default-sized table\n * • TableContextMenu — BubbleMenu that appears inside a table with\n * Row / Column / Cell / Table action sections\n *\n * Keyboard shortcuts (built into Tiptap table extensions)\n * • Tab — move to next cell (creates new row at end)\n * • Shift+Tab — move to previous cell\n *\n * ── Enabled vs disabled ───────────────────────────────────────────────\n *\n * Enabled → TableKit is loaded. All of the above are active. The toolbar\n * table button and /table slash command both insert a table with\n * TABLE_DEFAULTS rows, cols, and withHeaderRow settings.\n *\n * Disabled → No table schema. Existing table nodes in a document will not\n * parse correctly and content may be lost. If you need read-only\n * table rendering without the editing UI, keep this feature on\n * and set `editable={false}` on the editor instead.\n *\n * ── Custom configuration ──────────────────────────────────────────────\n *\n * Call configureTablesFeature(options) BEFORE featureBootstrap runs to\n * override the defaults. Typically done in your app entry point:\n *\n * import { configureTablesFeature } from \"@matops/editor/extensions/features/tablesFeature\";\n *\n * configureTablesFeature({\n * resizable: true,\n * cellMinWidth: 80,\n * defaultRows: 4,\n * defaultCols: 4,\n * withHeaderRow: true,\n * });\n *\n * featureBootstrap.ts still re-imports this file — the registration is\n * idempotent (it warns and overwrites on duplicate) so calling\n * configureTablesFeature() first is safe and the correct approach.\n *\n * ── Dependencies ─────────────────────────────────────────────────────\n * Requires \"formatting\" because TableCell content is paragraph-based and\n * needs the paragraph + text extensions already registered.\n */\n\nimport { TableKit } from \"@tiptap/extension-table\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\n// ─────────────────────────────────────────────\n// Public Configuration Interface\n// ─────────────────────────────────────────────\n\n/**\n * Options for the \"tables\" feature.\n *\n * All fields are optional — unset fields fall back to TABLE_DEFAULTS.\n */\nexport interface TableFeatureOptions {\n /**\n * Allow column widths to be dragged to resize.\n * @default true\n */\n resizable?: boolean;\n\n /**\n * Minimum width in pixels for every table cell.\n * Prevents columns from collapsing to zero when resizing.\n * @default 100\n */\n cellMinWidth?: number;\n\n /**\n * Whether the last column can be resized.\n * Set false when the table fills the full content width and the last\n * column should stretch to absorb any remaining space.\n * @default true\n */\n lastColumnResizable?: boolean;\n\n /**\n * Number of rows inserted when a new table is created via the toolbar\n * button or the /table slash command.\n * @default 3\n */\n defaultRows?: number;\n\n /**\n * Number of columns inserted when a new table is created.\n * @default 3\n */\n defaultCols?: number;\n\n /**\n * Whether newly inserted tables include a styled header row.\n * @default true\n */\n withHeaderRow?: boolean;\n}\n\n// ─────────────────────────────────────────────\n// Resolved Defaults (mutable — written by configureTablesFeature)\n// ─────────────────────────────────────────────\n\n/**\n * Live defaults consumed by the table insert command in commandRegistry.ts\n * and by the toolbar / slash-menu integrations.\n *\n * Do NOT mutate this object directly — use configureTablesFeature() instead\n * so that the feature registration is re-run with the updated options.\n */\nexport const TABLE_DEFAULTS: Required<TableFeatureOptions> = {\n resizable: true,\n cellMinWidth: 100,\n lastColumnResizable: true,\n defaultRows: 3,\n defaultCols: 3,\n withHeaderRow: true,\n};\n\n// ─────────────────────────────────────────────\n// Feature Registration\n// ─────────────────────────────────────────────\n\n/**\n * Registers (or re-registers) the \"tables\" feature with the given options.\n *\n * Calling this function multiple times is intentional when you need custom\n * configuration — the registry warns on overwrite, which is expected.\n *\n * @param options - Partial options to override TABLE_DEFAULTS.\n */\nexport function configureTablesFeature(options: TableFeatureOptions = {}): void {\n // Merge options into the live defaults object so commandRegistry picks\n // them up without an explicit import cycle.\n Object.assign(TABLE_DEFAULTS, options);\n\n registerFeature({\n name: \"tables\",\n\n extensions: [\n TableKit.configure({\n // Table node — column resizing and cell minimum width\n table: {\n resizable: TABLE_DEFAULTS.resizable,\n lastColumnResizable: TABLE_DEFAULTS.lastColumnResizable,\n cellMinWidth: TABLE_DEFAULTS.cellMinWidth,\n // Allow table node selection (e.g. Ctrl+A inside a table)\n // so the table can be selected and deleted as a unit.\n allowTableNodeSelection: true,\n },\n // TableRow, TableHeader, and TableCell use their built-in defaults.\n // Override here if you need custom HTML attributes or parse rules:\n // tableRow: { HTMLAttributes: { class: \"...\" } },\n // tableHeader: { HTMLAttributes: { class: \"...\" } },\n // tableCell: { HTMLAttributes: { class: \"...\" } },\n }),\n ],\n\n // Paragraph and Text nodes (provided by \"formatting\") must be present\n // so table cells can hold block content.\n dependencies: [\"formatting\"],\n });\n}\n\n// ─────────────────────────────────────────────\n// Default Registration\n// Called on import by featureBootstrap.ts.\n// Call configureTablesFeature(options) BEFORE this file is imported to\n// override the defaults before the initial registration runs.\n// ─────────────────────────────────────────────\n\nconfigureTablesFeature();\n","/**\n * @feature collaboration\n *\n * Registers \"collaboration\" as a known feature.\n *\n * NOTE: The actual CollaborationExtension and CollaborationCaret are NOT\n * registered here because they require a runtime `provider` value that\n * doesn't exist at module-load time. They are injected by\n * `editorConfigBuilder.ts` when a `collaborationProvider` prop is supplied.\n *\n * Registering this feature still serves two purposes:\n * 1. It satisfies dependency checks from other features\n * 2. It suppresses the \"history\" feature via its `enabled` predicate\n * (Yjs provides its own CRDT-based undo stack)\n */\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"collaboration\",\n extensions: [], // Built at runtime by editorConfigBuilder\n dependencies: [],\n});\n","/**\n * @feature formatting\n *\n * v3: Lists are now bundled via ListKit from @tiptap/extension-list\n * Text styles consolidated via TextStyleKit from @tiptap/extension-text-style\n */\nimport Bold from \"@tiptap/extension-bold\";\nimport Italic from \"@tiptap/extension-italic\";\nimport Underline from \"@tiptap/extension-underline\";\nimport Strike from \"@tiptap/extension-strike\";\nimport Heading from \"@tiptap/extension-heading\";\nimport Blockquote from \"@tiptap/extension-blockquote\";\nimport { ListKit } from \"@tiptap/extension-list\";\nimport TextAlign from \"@tiptap/extension-text-align\";\nimport { TextStyleKit } from \"@tiptap/extension-text-style\";\nimport Highlight from \"@tiptap/extension-highlight\";\nimport HorizontalRule from \"@tiptap/extension-horizontal-rule\";\nimport HardBreak from \"@tiptap/extension-hard-break\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"formatting\",\n extensions: [\n Bold,\n Italic,\n Underline,\n Strike,\n Heading.configure({ levels: [1, 2, 3] }),\n Blockquote,\n // ListKit bundles: BulletList, OrderedList, ListItem, ListKeymap\n ListKit,\n // TextStyleKit bundles: TextStyle, Color, FontFamily, FontSize, BackgroundColor, LineHeight\n TextStyleKit,\n Highlight.configure({ multicolor: true }),\n TextAlign.configure({ types: [\"heading\", \"paragraph\"] }),\n HorizontalRule,\n HardBreak,\n ],\n dependencies: [],\n});\n","/**\n * @feature code\n *\n * Provides inline code and fenced code blocks with syntax highlighting.\n * Uses lowlight (highlight.js) for language detection and highlighting.\n */\n\nimport Code from \"@tiptap/extension-code\";\nimport CodeBlockLowlight from \"@tiptap/extension-code-block-lowlight\";\nimport { common, createLowlight } from \"lowlight\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\n// Initialize lowlight with common languages\n// For tree-shaking, import only the languages you need in production\nconst lowlight = createLowlight(common);\n\nregisterFeature({\n name: \"code\",\n extensions: [\n Code,\n CodeBlockLowlight.configure({\n lowlight,\n // Default language shown in the language picker\n defaultLanguage: \"plaintext\",\n }),\n ],\n dependencies: [\"formatting\"],\n});\n","/**\n * @feature task-list\n *\n * v3: TaskList and TaskItem are named exports from @tiptap/extension-list\n */\nimport { TaskList, TaskItem } from \"@tiptap/extension-list\";\nimport { registerFeature } from \"@matops/editor/core/registry/featureRegistry\";\n\nregisterFeature({\n name: \"task-list\",\n extensions: [\n TaskList,\n TaskItem.configure({ nested: true }),\n ],\n dependencies: [\"formatting\"],\n});\n","/**\n * MatopsDocument — Tiptap Document extension with all doc-level metadata attrs.\n *\n * Replaces the vanilla `@tiptap/extension-document` in BASE_EXTENSIONS.\n *\n * ## Why doc attrs?\n *\n * Document \"chrome\" (cover image, title, separator icon, attachments) was\n * previously stored as structural content nodes inside `content[]`. Keeping\n * them as root-node **attrs** is architecturally cleaner:\n *\n * - `content[]` contains only editable body nodes — no special handling or\n * guard plugins are needed to protect structural slots.\n * - All metadata is accessible in O(1) via `editor.state.doc.attrs.<key>` —\n * no walking the node tree.\n * - A single `tr.setDocAttribute(key, value)` mutates any metadata field —\n * uniform, undo-friendly, and safe from accidental ProseMirror transformations.\n * - The JSON shape is self-describing: every key at `doc.attrs` is metadata;\n * every node in `doc.content` is body content.\n *\n * ## New JSON shape\n *\n * ```json\n * {\n * \"type\": \"doc\",\n * \"attrs\": {\n * \"contentWidth\": \"full\",\n * \"coverImage\": { \"src\": \"https://…\", \"alt\": \"…\", … },\n * \"title\": { \"text\": \"Getting Started\", \"placeholder\": \"Untitled\" },\n * \"separatorIcon\": { \"src\": null, … },\n * \"attachments\": { \"items\": \"[]\" }\n * },\n * \"content\": [ /* body only *\\/ ]\n * }\n * ```\n *\n * ## Commands\n *\n * | Command | Mutates |\n * |-------------------------|----------------------|\n * | `setContentWidth` | `contentWidth` |\n * | `setCoverImageAttr` | `coverImage` |\n * | `setTitleAttr` | `title` |\n * | `setSeparatorIconAttr` | `separatorIcon` |\n * | `setAttachmentsAttr` | `attachments` |\n *\n * All commands use `tr.setDocAttribute` — the only correct ProseMirror API for\n * mutating root doc attrs. `setNodeMarkup(0, …)` targets the first *child* node,\n * not the document itself, and must never be used here.\n */\n\nimport Document from \"@tiptap/extension-document\";\nimport type {\n MatopsContentWidth,\n CoverImageDocAttr,\n TitleDocAttr,\n SeparatorIconDocAttr,\n AttachmentsDocAttr,\n AttachmentItem,\n} from \"@matops/editor/core/types\";\nexport const DEFAULT_CONTENT_WIDTH: MatopsContentWidth = \"normal\";\n\n/** Augment Tiptap's Commands interface so TypeScript knows about all doc-attr setters. */\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n matopsDocument: {\n /**\n * Update the document-level `contentWidth` layout attribute.\n *\n * @example\n * editor.commands.setContentWidth(\"compact\")\n */\n setContentWidth: (width: MatopsContentWidth) => ReturnType;\n\n /**\n * Set or clear the cover-image doc attr.\n *\n * Pass a partial `CoverImageDocAttr` to merge into the existing value,\n * or `null` to remove the cover image (keeps the attr key with null value\n * so the feature knows the slot exists).\n *\n * @example\n * editor.commands.setCoverImageAttr({ src: \"https://cdn.example.com/banner.jpg\" })\n * editor.commands.setCoverImageAttr(null) // clear image\n */\n setCoverImageAttr: (\n value: Partial<CoverImageDocAttr> | null,\n ) => ReturnType;\n\n /**\n * Update the title text and/or placeholder stored in the doc attr.\n *\n * @example\n * editor.commands.setTitleAttr({ text: \"My Document\" })\n * editor.commands.setTitleAttr({ text: \"Draft\", placeholder: \"Untitled\" })\n */\n setTitleAttr: (value: Partial<TitleDocAttr> | null) => ReturnType;\n\n /**\n * Set or clear the separator-icon doc attr.\n *\n * @example\n * editor.commands.setSeparatorIconAttr({ src: \"https://cdn.example.com/logo.png\" })\n * editor.commands.setSeparatorIconAttr(null) // revert to default icon\n */\n setSeparatorIconAttr: (\n value: Partial<SeparatorIconDocAttr> | null,\n ) => ReturnType;\n\n /**\n * Replace the attachments list stored in the doc attr.\n *\n * @example\n * editor.commands.setAttachmentsAttr([\n * { id: \"a1\", name: \"brief.pdf\", size: 51200, mimeType: \"application/pdf\", url: \"https://…\" }\n * ])\n */\n setAttachmentsAttr: (items: AttachmentItem[]) => ReturnType;\n };\n }\n}\n\nexport const MatopsDocument = Document.extend({\n addAttributes() {\n return {\n // ── Layout ────────────────────────────────────────────────────────\n contentWidth: {\n default: DEFAULT_CONTENT_WIDTH satisfies MatopsContentWidth,\n parseHTML: (el) =>\n (el.getAttribute(\n \"data-content-width\",\n ) as MatopsContentWidth | null) ?? DEFAULT_CONTENT_WIDTH,\n renderHTML: (attrs) => ({\n \"data-content-width\": attrs.contentWidth ?? DEFAULT_CONTENT_WIDTH,\n }),\n },\n\n // ── Cover image ───────────────────────────────────────────────────\n /**\n * Stores all cover-image fields as a JSON object in `doc.attrs.coverImage`.\n * `null` = feature is enabled but no image has been uploaded yet.\n * absent = feature is disabled.\n */\n coverImage: {\n default: null as CoverImageDocAttr | null,\n parseHTML: (el) => {\n const raw = el.getAttribute(\"data-cover-image\");\n if (!raw) return null;\n try {\n return JSON.parse(raw) as CoverImageDocAttr;\n } catch {\n return null;\n }\n },\n renderHTML: (attrs) =>\n attrs.coverImage\n ? { \"data-cover-image\": JSON.stringify(attrs.coverImage) }\n : {},\n },\n\n // ── Title ─────────────────────────────────────────────────────────\n /**\n * Stores title text + placeholder as a JSON object in `doc.attrs.title`.\n * NOTE: the HTML attribute is named `data-title-config` to avoid clashing\n * with the standard `title` attribute.\n * `null` = feature is enabled but no text entered yet.\n * absent = feature is disabled.\n */\n title: {\n default: null as TitleDocAttr | null,\n parseHTML: (el) => {\n const raw = el.getAttribute(\"data-title-config\");\n if (!raw) return null;\n try {\n return JSON.parse(raw) as TitleDocAttr;\n } catch {\n return null;\n }\n },\n renderHTML: (attrs) =>\n attrs.title\n ? { \"data-title-config\": JSON.stringify(attrs.title) }\n : {},\n },\n\n // ── Separator icon ────────────────────────────────────────────────\n /**\n * Stores separator-icon fields as a JSON object in `doc.attrs.separatorIcon`.\n * `null` = feature is enabled, uses prop/default icon.\n * absent = feature is disabled.\n */\n separatorIcon: {\n default: null as SeparatorIconDocAttr | null,\n parseHTML: (el) => {\n const raw = el.getAttribute(\"data-separator-icon\");\n if (!raw) return null;\n try {\n return JSON.parse(raw) as SeparatorIconDocAttr;\n } catch {\n return null;\n }\n },\n renderHTML: (attrs) =>\n attrs.separatorIcon\n ? { \"data-separator-icon\": JSON.stringify(attrs.separatorIcon) }\n : {},\n },\n\n // ── Attachments ───────────────────────────────────────────────────\n /**\n * Stores the `AttachmentItem[]` as a JSON-encoded string inside an object\n * in `doc.attrs.attachments`.\n * `null` = feature is enabled but no files attached.\n * absent = feature is disabled.\n */\n attachments: {\n default: null as AttachmentsDocAttr | null,\n parseHTML: (el) => {\n const raw = el.getAttribute(\"data-attachments\");\n if (!raw) return null;\n try {\n return JSON.parse(raw) as AttachmentsDocAttr;\n } catch {\n return null;\n }\n },\n renderHTML: (attrs) =>\n attrs.attachments\n ? { \"data-attachments\": JSON.stringify(attrs.attachments) }\n : {},\n },\n };\n },\n\n addCommands() {\n return {\n // ── contentWidth ─────────────────────────────────────────────────\n /**\n * Dispatch a `DocAttrStep` via `tr.setDocAttribute` to update the\n * `contentWidth` attr on the root doc node.\n *\n * `tr.setDocAttribute` is the only correct ProseMirror API for mutating\n * root doc attrs — `setNodeMarkup(0, ...)` targets the first *child* node.\n */\n setContentWidth:\n (width: MatopsContentWidth) =>\n ({ tr, dispatch }) => {\n if (dispatch) dispatch(tr.setDocAttribute(\"contentWidth\", width));\n return true;\n },\n\n // ── coverImage ───────────────────────────────────────────────────\n setCoverImageAttr:\n (value: Partial<CoverImageDocAttr> | null) =>\n ({ tr, dispatch, editor }) => {\n if (dispatch) {\n if (value === null) {\n dispatch(tr.setDocAttribute(\"coverImage\", null));\n } else {\n const current = (editor.state.doc.attrs\n ?.coverImage as CoverImageDocAttr | null) ?? {\n src: null,\n alt: \"Cover image\",\n objectPosition: \"center 40%\",\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n };\n dispatch(\n tr.setDocAttribute(\"coverImage\", { ...current, ...value }),\n );\n }\n }\n return true;\n },\n\n // ── title ────────────────────────────────────────────────────────\n setTitleAttr:\n (value: Partial<TitleDocAttr> | null) =>\n ({ tr, dispatch, editor }) => {\n if (dispatch) {\n if (value === null) {\n dispatch(tr.setDocAttribute(\"title\", null));\n } else {\n const current = (editor.state.doc.attrs\n ?.title as TitleDocAttr | null) ?? {\n text: \"\",\n placeholder: \"Untitled\",\n };\n dispatch(tr.setDocAttribute(\"title\", { ...current, ...value }));\n }\n }\n return true;\n },\n\n // ── separatorIcon ────────────────────────────────────────────────\n setSeparatorIconAttr:\n (value: Partial<SeparatorIconDocAttr> | null) =>\n ({ tr, dispatch, editor }) => {\n if (dispatch) {\n if (value === null) {\n dispatch(tr.setDocAttribute(\"separatorIcon\", null));\n } else {\n const current = (editor.state.doc.attrs\n ?.separatorIcon as SeparatorIconDocAttr | null) ?? {\n src: null,\n alt: \"Section separator\",\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n };\n dispatch(\n tr.setDocAttribute(\"separatorIcon\", { ...current, ...value }),\n );\n }\n }\n return true;\n },\n\n // ── attachments ──────────────────────────────────────────────────\n setAttachmentsAttr:\n (items: AttachmentItem[]) =>\n ({ tr, dispatch }) => {\n if (dispatch) {\n dispatch(\n tr.setDocAttribute(\"attachments\", {\n items: JSON.stringify(items),\n } satisfies AttachmentsDocAttr),\n );\n }\n return true;\n },\n };\n },\n});\n\n// ─────────────────────────────────────────────\n// Read helpers\n// ─────────────────────────────────────────────\n\n/**\n * Returns the `contentWidth` stored in a live Tiptap editor's document,\n * falling back to `DEFAULT_CONTENT_WIDTH` if the attr is missing or invalid.\n *\n * @example\n * const width = getContentWidth(editor);\n * // → \"normal\" | \"compact\" | \"full\"\n */\nexport function getContentWidth(\n editor: import(\"@tiptap/core\").Editor | null,\n): MatopsContentWidth {\n const val = editor?.state?.doc?.attrs?.contentWidth as\n | MatopsContentWidth\n | undefined;\n return val ?? DEFAULT_CONTENT_WIDTH;\n}\n\n/**\n * Returns the `coverImage` attr from a live editor's document.\n * Returns `null` if the attr is absent or null.\n */\nexport function getCoverImageAttr(\n editor: import(\"@tiptap/core\").Editor | null,\n): CoverImageDocAttr | null {\n return (\n (editor?.state?.doc?.attrs?.coverImage as\n | CoverImageDocAttr\n | null\n | undefined) ?? null\n );\n}\n\n/**\n * Returns the `title` attr from a live editor's document.\n * Returns `null` if the attr is absent or null.\n */\nexport function getTitleAttr(\n editor: import(\"@tiptap/core\").Editor | null,\n): TitleDocAttr | null {\n return (\n (editor?.state?.doc?.attrs?.title as TitleDocAttr | null | undefined) ??\n null\n );\n}\n\n/**\n * Returns the `separatorIcon` attr from a live editor's document.\n * Returns `null` if the attr is absent or null.\n */\nexport function getSeparatorIconAttr(\n editor: import(\"@tiptap/core\").Editor | null,\n): SeparatorIconDocAttr | null {\n return (\n (editor?.state?.doc?.attrs?.separatorIcon as\n | SeparatorIconDocAttr\n | null\n | undefined) ?? null\n );\n}\n\n/**\n * Returns the `attachments` attr from a live editor's document.\n * Returns `null` if the attr is absent or null.\n */\nexport function getAttachmentsAttr(\n editor: import(\"@tiptap/core\").Editor | null,\n): AttachmentsDocAttr | null {\n return (\n (editor?.state?.doc?.attrs?.attachments as\n | AttachmentsDocAttr\n | null\n | undefined) ?? null\n );\n}\n","import type { MatopsEditorFeature } from \"@matops/editor/core/types\";\n\n// ─────────────────────────────────────────────\n// Default Values\n// ─────────────────────────────────────────────\n\n/**\n * Default feature set when no `features` prop is provided.\n * Covers the most common editing needs out of the box.\n */\nexport const DEFAULT_FEATURES: MatopsEditorFeature[] = [\n \"history\",\n \"formatting\",\n \"placeholder\",\n];\n\n/**\n * Default placeholder text shown in empty editors.\n */\nexport const DEFAULT_PLACEHOLDER = \"Start writing…\";\n\n// ─────────────────────────────────────────────\n// CSS Classes / Tokens\n// ─────────────────────────────────────────────\n\n/** CSS class applied to the outer editor wrapper in light theme */\nexport const THEME_LIGHT_CLASS = \"matops-editor--light\";\n\n/** CSS class applied to the outer editor wrapper in dark theme */\nexport const THEME_DARK_CLASS = \"matops-editor--dark\";\n\n/** Data attribute used to scope ProseMirror CSS */\nexport const EDITOR_DATA_ATTR = \"data-matops-editor\";\n\n// ─────────────────────────────────────────────\n// Keyboard Shortcuts\n// ─────────────────────────────────────────────\n\nexport const SHORTCUTS = {\n PUBLISH: \"Mod-Shift-P\",\n TOGGLE_TOOLBAR: \"Mod-Shift-T\",\n SLASH_COMMAND: \"/\",\n} as const;\n\n// ─────────────────────────────────────────────\n// Feature Dependencies Map\n// INFORMATIONAL ONLY — for documentation / tooling purposes.\n// The actual runtime dependency resolution happens inside featureRegistry.ts.\n// If you add a new dependency, update BOTH this map AND the feature's\n// `dependencies` array in its registration file so they stay in sync.\n// ─────────────────────────────────────────────\n\n/** @deprecated Use featureRegistry.resolve() for authoritative dependency resolution. */\n\nexport const FEATURE_DEPENDENCY_MAP: Partial<\n Record<MatopsEditorFeature, MatopsEditorFeature[]>\n> = {\n collaboration: [\"history\"],\n tables: [\"formatting\"],\n \"slash-command\": [],\n code: [\"formatting\"],\n layout: [\"formatting\"],\n media: [],\n};\n","import type { Extensions } from \"@tiptap/core\";\nimport Paragraph from \"@tiptap/extension-paragraph\";\nimport Text from \"@tiptap/extension-text\";\nimport { Placeholder } from \"@tiptap/extensions\";\nimport CollaborationExtension from \"@tiptap/extension-collaboration\";\nimport CollaborationCaret from \"@tiptap/extension-collaboration-caret\";\n\nimport { MatopsDocument } from \"@matops/editor/extensions/nodes/documentNode\";\n\nimport type {\n CollaborationProvider,\n MatopsEditorFeature,\n ResolvedEditorConfig,\n} from \"@matops/editor/core/types\";\n\nimport { featureRegistry } from \"./featureRegistry\";\nimport { DEFAULT_PLACEHOLDER } from \"@matops/editor/utils/constants\";\n\n// ─────────────────────────────────────────────\n// Base Extensions (always present)\n// ─────────────────────────────────────────────\n\nconst BASE_EXTENSIONS: Extensions = [MatopsDocument, Paragraph, Text];\n\n// ─────────────────────────────────────────────\n// Config Builder\n// ─────────────────────────────────────────────\n\nexport interface BuildEditorConfigOptions {\n features: MatopsEditorFeature[];\n\n placeholder?: string;\n\n collaborationProvider?: CollaborationProvider;\n}\n\nexport function buildEditorConfig({\n features,\n placeholder,\n collaborationProvider,\n}: BuildEditorConfigOptions): ResolvedEditorConfig {\n const { resolvedFeatures, extensions: featureExtensions } =\n featureRegistry.resolve(features);\n\n // Fast feature lookup\n const featureSet = new Set(resolvedFeatures);\n\n const runtimeExtensions: Extensions = [];\n\n buildPlaceholderExtension(runtimeExtensions, featureSet, placeholder);\n buildCollaborationExtensions(\n runtimeExtensions,\n featureSet,\n collaborationProvider,\n );\n\n return {\n resolvedFeatures,\n extensions: [\n ...BASE_EXTENSIONS,\n ...featureExtensions,\n ...runtimeExtensions,\n ],\n };\n}\n\n// ─────────────────────────────────────────────\n// Runtime Extension Builders\n// ─────────────────────────────────────────────\n\nfunction buildPlaceholderExtension(\n extensions: Extensions,\n featureSet: Set<MatopsEditorFeature>,\n placeholder: string | undefined,\n) {\n if (!featureSet.has(\"placeholder\")) return;\n\n extensions.push(\n Placeholder.configure({\n placeholder: placeholder ?? DEFAULT_PLACEHOLDER,\n showOnlyWhenEditable: true,\n }),\n );\n}\n\nfunction buildCollaborationExtensions(\n extensions: Extensions,\n featureSet: Set<MatopsEditorFeature>,\n provider: CollaborationProvider | undefined,\n) {\n if (!featureSet.has(\"collaboration\") || !provider) return;\n\n extensions.push(\n CollaborationExtension.configure({\n document: provider.document,\n }),\n );\n\n extensions.push(\n CollaborationCaret.configure({\n provider,\n user: provider.user ?? {\n name: \"Anonymous\",\n color: \"#6366f1\",\n },\n }),\n );\n}\n","/**\n * docHelpers — Pure utilities for building Tiptap document JSON.\n *\n * ## Internal vs External document format\n *\n * This package uses TWO representations of a document:\n *\n * ### External format (consumer-facing)\n * Structural metadata (cover image, title, separator icon, attachments) is\n * stored in root `doc.attrs`. Only editable body content lives in `content[]`.\n *\n * ```json\n * {\n * \"type\": \"doc\",\n * \"attrs\": {\n * \"contentWidth\": \"full\",\n * \"coverImage\": { \"src\": \"https://cdn.example.com/banner.jpg\", … },\n * \"title\": { \"text\": \"Getting Started\", \"placeholder\": \"Untitled\" },\n * \"separatorIcon\": { \"src\": null, … },\n * \"attachments\": { \"items\": \"[]\" }\n * },\n * \"content\": [ /* body paragraphs, headings, tables … *\\/ ]\n * }\n * ```\n *\n * This is what `onChange` delivers and what `createDocContent()` produces.\n * It is also what `<EditorViewer>` accepts.\n *\n * ### Internal format (Tiptap state)\n * Structural sections exist as typed content nodes inside `content[]` so\n * their React NodeViews render correctly in ProseMirror.\n *\n * ```json\n * {\n * \"type\": \"doc\",\n * \"attrs\": { \"contentWidth\": \"full\" },\n * \"content\": [\n * { \"type\": \"cover-image\", \"attrs\": { … } },\n * { \"type\": \"title\", \"attrs\": { … }, \"content\": [ … ] },\n * { \"type\": \"separator-icon\", \"attrs\": { … } },\n * { … body … },\n * { \"type\": \"attachments\", \"attrs\": { … } }\n * ]\n * }\n * ```\n *\n * ### Conversion utilities\n * - `toExternalFormat(doc)` — internal → external (used inside `onChange`)\n * - `rebuildContent(…)` — external/legacy/internal → internal (used by `Editor.tsx`)\n *\n * All `extract*()` helpers transparently support BOTH formats.\n */\n\nimport type { JSONContent } from \"@tiptap/core\";\nimport {\n type CoverImageAttrs,\n type TitleAttrs,\n type SeparatorIconAttrs,\n type AttachmentItem,\n type DocLayout,\n type MatopsContentWidth,\n type CoverImageDocAttr,\n type TitleDocAttr,\n type SeparatorIconDocAttr,\n type AttachmentsDocAttr,\n type DocAttrs,\n ContentWidths,\n} from \"@matops/editor/core/types\";\nimport { DEFAULT_CONTENT_WIDTH } from \"@matops/editor/extensions/nodes/documentNode\";\n\n// ─────────────────────────────────────────────\n// Internal helpers\n// ─────────────────────────────────────────────\n\nconst ALL_STRUCTURAL_TYPES = new Set([\n \"cover-image\",\n \"title\",\n \"separator-icon\",\n \"attachments\",\n]);\n\nfunction defaultCoverImageAttr(\n src: string | null,\n options: Partial<Omit<CoverImageDocAttr, \"src\">> = {},\n): CoverImageDocAttr {\n return {\n src,\n alt: options.alt ?? \"Cover image\",\n objectPosition: options.objectPosition ?? \"center 40%\",\n cropX: options.cropX ?? 0,\n cropY: options.cropY ?? 0,\n cropWidth: options.cropWidth ?? 100,\n cropHeight: options.cropHeight ?? 100,\n };\n}\n\nfunction defaultSeparatorIconAttr(\n src: string | null,\n options: Partial<Omit<SeparatorIconDocAttr, \"src\">> = {},\n): SeparatorIconDocAttr {\n return {\n src,\n alt: options.alt ?? \"Section separator\",\n cropX: options.cropX ?? 0,\n cropY: options.cropY ?? 0,\n cropWidth: options.cropWidth ?? 100,\n cropHeight: options.cropHeight ?? 100,\n };\n}\n\n// ─────────────────────────────────────────────\n// Structural data pickers\n// Read from: new doc.attrs → legacy content[] → defaults\n// ─────────────────────────────────────────────\n\nfunction pickCoverImageData(\n currNodes: JSONContent[],\n fallNodes: JSONContent[],\n mergedAttrs: DocAttrs,\n): CoverImageDocAttr {\n // New external format: doc.attrs.coverImage\n if (\"coverImage\" in mergedAttrs && mergedAttrs.coverImage !== undefined) {\n return mergedAttrs.coverImage ?? defaultCoverImageAttr(null);\n }\n // Legacy / internal format: cover-image content node\n const node =\n currNodes.find((n) => n.type === \"cover-image\") ??\n fallNodes.find((n) => n.type === \"cover-image\");\n if (node) {\n return {\n src: (node.attrs?.src as string | null) ?? null,\n alt: (node.attrs?.alt as string) ?? \"Cover image\",\n objectPosition: (node.attrs?.objectPosition as string) ?? \"center 40%\",\n cropX: (node.attrs?.cropX as number) ?? 0,\n cropY: (node.attrs?.cropY as number) ?? 0,\n cropWidth: (node.attrs?.cropWidth as number) ?? 100,\n cropHeight: (node.attrs?.cropHeight as number) ?? 100,\n };\n }\n return defaultCoverImageAttr(null);\n}\n\nfunction pickTitleData(\n currNodes: JSONContent[],\n fallNodes: JSONContent[],\n mergedAttrs: DocAttrs,\n): TitleDocAttr {\n if (\"title\" in mergedAttrs && mergedAttrs.title !== undefined) {\n return mergedAttrs.title ?? { text: \"\", placeholder: \"Untitled\" };\n }\n const node =\n currNodes.find((n) => n.type === \"title\") ??\n fallNodes.find((n) => n.type === \"title\");\n if (node) {\n return {\n text: (node.content ?? []).map((n: JSONContent) => n.text ?? \"\").join(\"\"),\n placeholder: (node.attrs?.placeholder as string) ?? \"Untitled\",\n };\n }\n return { text: \"\", placeholder: \"Untitled\" };\n}\n\nfunction pickSeparatorIconData(\n currNodes: JSONContent[],\n fallNodes: JSONContent[],\n mergedAttrs: DocAttrs,\n): SeparatorIconDocAttr {\n if (\n \"separatorIcon\" in mergedAttrs &&\n mergedAttrs.separatorIcon !== undefined\n ) {\n return mergedAttrs.separatorIcon ?? defaultSeparatorIconAttr(null);\n }\n const node =\n currNodes.find((n) => n.type === \"separator-icon\") ??\n fallNodes.find((n) => n.type === \"separator-icon\");\n if (node) {\n return {\n src: (node.attrs?.src as string | null) ?? null,\n alt: (node.attrs?.alt as string) ?? \"Section separator\",\n cropX: (node.attrs?.cropX as number) ?? 0,\n cropY: (node.attrs?.cropY as number) ?? 0,\n cropWidth: (node.attrs?.cropWidth as number) ?? 100,\n cropHeight: (node.attrs?.cropHeight as number) ?? 100,\n };\n }\n return defaultSeparatorIconAttr(null);\n}\n\nfunction pickAttachmentsData(\n currNodes: JSONContent[],\n fallNodes: JSONContent[],\n mergedAttrs: DocAttrs,\n): AttachmentsDocAttr {\n if (\"attachments\" in mergedAttrs && mergedAttrs.attachments !== undefined) {\n return mergedAttrs.attachments ?? { items: \"[]\" };\n }\n const node =\n currNodes.find((n) => n.type === \"attachments\") ??\n fallNodes.find((n) => n.type === \"attachments\");\n if (node) {\n return { items: (node.attrs?.items as string) ?? \"[]\" };\n }\n return { items: \"[]\" };\n}\n\n// ─────────────────────────────────────────────\n// Legacy content-node builders\n// (kept for backward compatibility and for rebuildContent internals)\n// ─────────────────────────────────────────────\n\n/**\n * @deprecated Use `createDocContent()` instead.\n * Returns a `cover-image` content node for internal Tiptap use.\n */\nexport function createCoverImageNode(\n src: string,\n options: Partial<Omit<CoverImageAttrs, \"src\">> = {},\n): JSONContent {\n return {\n type: \"cover-image\",\n attrs: {\n src,\n alt: options.alt ?? \"Cover image\",\n objectPosition: options.objectPosition ?? \"center 40%\",\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n },\n };\n}\n\n/** @deprecated Use `createDocContent()` instead. */\nexport function createEmptyCoverImageNode(): JSONContent {\n return {\n type: \"cover-image\",\n attrs: {\n src: null,\n alt: \"Cover image\",\n objectPosition: \"center 40%\",\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n },\n };\n}\n\n/** @deprecated Use `createDocContent()` instead. */\nexport function createTitleNode(\n text?: string,\n options: Partial<TitleAttrs> = {},\n): JSONContent {\n return {\n type: \"title\",\n attrs: { placeholder: options.placeholder ?? \"Untitled\" },\n content: text ? [{ type: \"text\", text }] : [],\n };\n}\n\n/** @deprecated Use `createDocContent()` instead. */\nexport function createSeparatorIconNode(\n src: string,\n options: Partial<Omit<SeparatorIconAttrs, \"src\">> = {},\n): JSONContent {\n return {\n type: \"separator-icon\",\n attrs: {\n src,\n alt: options.alt ?? \"Section separator\",\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n },\n };\n}\n\n/** @deprecated Use `createDocContent()` instead. */\nexport function createEmptySeparatorIconNode(): JSONContent {\n return {\n type: \"separator-icon\",\n attrs: {\n src: null,\n alt: \"Section separator\",\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n },\n };\n}\n\n/** @deprecated Use `createDocContent()` instead. */\nexport function createAttachmentsNode(\n items: AttachmentItem[] = [],\n): JSONContent {\n return {\n type: \"attachments\",\n attrs: { items: serializeAttachments(items) },\n };\n}\n\n// ─────────────────────────────────────────────\n// Attachment helpers\n// ─────────────────────────────────────────────\n\nexport function parseAttachments(\n raw: string | null | undefined,\n): AttachmentItem[] {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as AttachmentItem[]) : [];\n } catch {\n return [];\n }\n}\n\nexport function serializeAttachments(items: AttachmentItem[]): string {\n return JSON.stringify(items);\n}\n\n// ─────────────────────────────────────────────\n// Document Builder\n// ─────────────────────────────────────────────\n\nexport interface DocContentOptions {\n /** Cover image URL. Omit to skip the `coverImage` attr entirely. */\n coverSrc?: string;\n coverOptions?: Partial<Omit<CoverImageDocAttr, \"src\">>;\n /**\n * Document title text. Pass `\"\"` to include the title with no text\n * (shows placeholder in the editor). Omit to skip entirely.\n */\n title?: string;\n titleOptions?: Partial<TitleDocAttr>;\n /**\n * Separator icon URL. Only applied when `title` is also present.\n */\n separatorIconSrc?: string;\n /** Body content nodes. Defaults to a single empty paragraph. */\n body?: JSONContent[];\n /**\n * Attachments section.\n * - `true` → empty section\n * - `AttachmentItem[]` → pre-populated\n * - omit / `false` → disabled\n */\n attachments?: boolean | AttachmentItem[];\n layout?: DocLayout;\n}\n\n/**\n * Build a complete Tiptap document JSONContent in **external format**.\n *\n * Structural metadata (cover image, title, separator icon, attachments) is\n * stored in `doc.attrs`. Only body content goes in `content[]`.\n *\n * Pass the result as `initialContent` to `<Editor>` — it reads doc.attrs and\n * injects the appropriate content nodes internally.\n *\n * @example\n * createDocContent({\n * coverSrc: \"https://cdn.example.com/cover.jpg\",\n * title: \"Getting Started\",\n * body: [{ type: \"paragraph\", content: [{ type: \"text\", text: \"Hello!\" }] }],\n * })\n */\nexport function createDocContent(options: DocContentOptions = {}): JSONContent {\n const {\n coverSrc,\n coverOptions,\n title,\n titleOptions,\n separatorIconSrc,\n body,\n attachments,\n layout,\n } = options;\n\n const attrs: DocAttrs = {};\n\n if (layout?.contentWidth && layout.contentWidth !== DEFAULT_CONTENT_WIDTH) {\n attrs.contentWidth = layout.contentWidth;\n }\n\n if (coverSrc !== undefined) {\n attrs.coverImage = defaultCoverImageAttr(coverSrc, coverOptions);\n }\n\n if (title !== undefined) {\n attrs.title = {\n text: title,\n placeholder: titleOptions?.placeholder ?? \"Untitled\",\n };\n attrs.separatorIcon = defaultSeparatorIconAttr(separatorIconSrc ?? null);\n }\n\n if (attachments === true) {\n attrs.attachments = { items: serializeAttachments([]) };\n } else if (Array.isArray(attachments)) {\n attrs.attachments = { items: serializeAttachments(attachments) };\n }\n\n const bodyNodes = body?.length ? body : [{ type: \"paragraph\" }];\n\n return {\n type: \"doc\",\n ...(Object.keys(attrs).length ? { attrs } : {}),\n content: bodyNodes,\n };\n}\n\n// ─────────────────────────────────────────────\n// Format conversion\n// ─────────────────────────────────────────────\n\n/**\n * Convert a Tiptap **internal** document (structural nodes in `content[]`) to\n * **external** format (structural metadata in `doc.attrs`, body-only `content[]`).\n *\n * This is called inside `useEditorInstance` before firing `onChange` so that\n * consumers always receive the canonical external format regardless of how\n * Tiptap stores the document internally.\n *\n * Safe to call on documents already in external format — returns them unchanged.\n */\nexport function toExternalFormat(doc: JSONContent): JSONContent {\n const nodes = doc.content ?? [];\n const hasStructuralNodes = nodes.some((n) =>\n ALL_STRUCTURAL_TYPES.has(n.type ?? \"\"),\n );\n if (!hasStructuralNodes) return doc; // already external or has no structural sections\n\n const coverNode = nodes.find((n) => n.type === \"cover-image\");\n const titleNode = nodes.find((n) => n.type === \"title\");\n const sepNode = nodes.find((n) => n.type === \"separator-icon\");\n const attachNode = nodes.find((n) => n.type === \"attachments\");\n const bodyNodes = nodes.filter(\n (n) => !ALL_STRUCTURAL_TYPES.has(n.type ?? \"\"),\n );\n\n const newAttrs: DocAttrs = { ...(doc.attrs ?? {}) };\n\n if (coverNode) {\n newAttrs.coverImage = {\n src: (coverNode.attrs?.src as string | null) ?? null,\n alt: (coverNode.attrs?.alt as string) ?? \"Cover image\",\n objectPosition:\n (coverNode.attrs?.objectPosition as string) ?? \"center 40%\",\n cropX: (coverNode.attrs?.cropX as number) ?? 0,\n cropY: (coverNode.attrs?.cropY as number) ?? 0,\n cropWidth: (coverNode.attrs?.cropWidth as number) ?? 100,\n cropHeight: (coverNode.attrs?.cropHeight as number) ?? 100,\n };\n }\n\n if (titleNode) {\n newAttrs.title = {\n text: (titleNode.content ?? [])\n .map((n: JSONContent) => n.text ?? \"\")\n .join(\"\"),\n placeholder: (titleNode.attrs?.placeholder as string) ?? \"Untitled\",\n };\n }\n\n if (sepNode) {\n newAttrs.separatorIcon = {\n src: (sepNode.attrs?.src as string | null) ?? null,\n alt: (sepNode.attrs?.alt as string) ?? \"Section separator\",\n cropX: (sepNode.attrs?.cropX as number) ?? 0,\n cropY: (sepNode.attrs?.cropY as number) ?? 0,\n cropWidth: (sepNode.attrs?.cropWidth as number) ?? 100,\n cropHeight: (sepNode.attrs?.cropHeight as number) ?? 100,\n };\n }\n\n if (attachNode) {\n newAttrs.attachments = {\n items: (attachNode.attrs?.items as string) ?? \"[]\",\n };\n }\n\n return {\n type: \"doc\",\n attrs: newAttrs,\n content: bodyNodes.length ? bodyNodes : [{ type: \"paragraph\" }],\n };\n}\n\n// ─────────────────────────────────────────────\n// rebuildContent — external/legacy/internal → internal\n// ─────────────────────────────────────────────\n\n/**\n * Rebuild a Tiptap document in **internal format** (structural nodes in `content[]`)\n * from any input format: external (doc.attrs), legacy (structural content nodes),\n * or internal (already has content nodes).\n *\n * Called by `Editor.tsx` when features change so that Tiptap always receives a\n * document whose `content[]` contains the correct set of structural nodes for the\n * active feature set.\n *\n * @param current - Latest live document JSON (any format).\n * @param hasCoverImage - Whether `\"cover-image\"` feature is active.\n * @param hasPageHeader - Whether `\"page-header\"` feature is active.\n * @param hasAttachments - Whether `\"attachments\"` feature is active.\n * @param fallbackContent - Used as a secondary source when structural data is\n * absent from `current`. Defaults to `current`.\n */\nexport function rebuildContent(\n current: JSONContent,\n hasCoverImage: boolean,\n hasPageHeader: boolean,\n hasAttachments: boolean,\n fallbackContent: JSONContent = current,\n): JSONContent {\n const currNodes = current.content ?? [];\n const fallNodes = fallbackContent.content ?? [];\n\n // ── Body: everything that is not a structural node ─────────────────────\n const body = currNodes.filter((n) => !ALL_STRUCTURAL_TYPES.has(n.type ?? \"\"));\n const safeBody = body.length ? body : [{ type: \"paragraph\" }];\n\n // ── Merge doc attrs (fallback → current wins) ──────────────────────────\n const mergedAttrs: DocAttrs = {\n ...(fallbackContent.attrs ?? {}),\n ...(current.attrs ?? {}),\n };\n\n // ── Build content[] with structural nodes first ────────────────────────\n const content: JSONContent[] = [];\n\n if (hasCoverImage) {\n const d = pickCoverImageData(currNodes, fallNodes, mergedAttrs);\n content.push({\n type: \"cover-image\",\n attrs: {\n src: d.src,\n alt: d.alt,\n objectPosition: d.objectPosition,\n cropX: d.cropX,\n cropY: d.cropY,\n cropWidth: d.cropWidth,\n cropHeight: d.cropHeight,\n },\n });\n }\n\n if (hasPageHeader) {\n const t = pickTitleData(currNodes, fallNodes, mergedAttrs);\n const s = pickSeparatorIconData(currNodes, fallNodes, mergedAttrs);\n\n content.push({\n type: \"title\",\n attrs: { placeholder: t.placeholder },\n content: t.text ? [{ type: \"text\", text: t.text }] : [],\n });\n content.push({\n type: \"separator-icon\",\n attrs: {\n src: s.src,\n alt: s.alt,\n cropX: s.cropX,\n cropY: s.cropY,\n cropWidth: s.cropWidth,\n cropHeight: s.cropHeight,\n },\n });\n }\n\n content.push(...safeBody);\n\n if (hasAttachments) {\n const a = pickAttachmentsData(currNodes, fallNodes, mergedAttrs);\n content.push({\n type: \"attachments\",\n attrs: { items: a.items },\n });\n }\n\n // ── Preserve only contentWidth in doc.attrs (not structural data) ──────\n const nextAttrs: Record<string, unknown> = {};\n if (mergedAttrs.contentWidth)\n nextAttrs.contentWidth = mergedAttrs.contentWidth;\n\n return {\n type: \"doc\",\n ...(Object.keys(nextAttrs).length ? { attrs: nextAttrs } : {}),\n content,\n };\n}\n\n// ─────────────────────────────────────────────\n// Read helpers (external format first, then legacy content[])\n// ─────────────────────────────────────────────\n\n/**\n * Extract the cover image src. Reads `doc.attrs.coverImage.src` first,\n * then falls back to the legacy `cover-image` content node.\n */\nexport function extractCoverSrc(doc: JSONContent): string | null {\n if (doc.attrs && \"coverImage\" in doc.attrs) {\n return (doc.attrs.coverImage as CoverImageDocAttr | null)?.src ?? null;\n }\n const node = doc.content?.find((n) => n.type === \"cover-image\");\n return (node?.attrs?.src as string | null | undefined) ?? null;\n}\n\n/**\n * Extract the full cover-image attr object.\n * Returns `null` if no cover image attr is present.\n */\nexport function extractCoverImageAttr(\n doc: JSONContent,\n): CoverImageDocAttr | null {\n if (doc.attrs && \"coverImage\" in doc.attrs) {\n return (doc.attrs.coverImage as CoverImageDocAttr | null) ?? null;\n }\n const node = doc.content?.find((n) => n.type === \"cover-image\");\n if (!node) return null;\n return {\n src: (node.attrs?.src as string | null) ?? null,\n alt: (node.attrs?.alt as string) ?? \"Cover image\",\n objectPosition: (node.attrs?.objectPosition as string) ?? \"center 40%\",\n cropX: (node.attrs?.cropX as number) ?? 0,\n cropY: (node.attrs?.cropY as number) ?? 0,\n cropWidth: (node.attrs?.cropWidth as number) ?? 100,\n cropHeight: (node.attrs?.cropHeight as number) ?? 100,\n };\n}\n\n/**\n * Extract the title text. Reads `doc.attrs.title.text` first,\n * then falls back to the legacy `title` content node.\n */\nexport function extractTitle(doc: JSONContent): string {\n if (doc.attrs && \"title\" in doc.attrs) {\n return (doc.attrs.title as TitleDocAttr | null)?.text ?? \"\";\n }\n const node = doc.content?.find((n) => n.type === \"title\");\n if (!node?.content) return \"\";\n return node.content.map((n: JSONContent) => n.text ?? \"\").join(\"\");\n}\n\n/**\n * Extract the full title attr object.\n * Returns `null` if no title attr is present.\n */\nexport function extractTitleAttr(doc: JSONContent): TitleDocAttr | null {\n if (doc.attrs && \"title\" in doc.attrs) {\n return (doc.attrs.title as TitleDocAttr | null) ?? null;\n }\n const node = doc.content?.find((n) => n.type === \"title\");\n if (!node) return null;\n return {\n text: (node.content ?? []).map((n: JSONContent) => n.text ?? \"\").join(\"\"),\n placeholder: (node.attrs?.placeholder as string) ?? \"Untitled\",\n };\n}\n\n/**\n * Extract the separator icon src. Reads `doc.attrs.separatorIcon.src` first,\n * then falls back to the legacy `separator-icon` content node.\n */\nexport function extractSeparatorIconSrc(doc: JSONContent): string | null {\n if (doc.attrs && \"separatorIcon\" in doc.attrs) {\n return (\n (doc.attrs.separatorIcon as SeparatorIconDocAttr | null)?.src ?? null\n );\n }\n const node = doc.content?.find((n) => n.type === \"separator-icon\");\n return (node?.attrs?.src as string | null | undefined) ?? null;\n}\n\n/**\n * Extract the attachment list. Reads `doc.attrs.attachments.items` first,\n * then falls back to the legacy `attachments` content node.\n */\nexport function extractAttachments(doc: JSONContent): AttachmentItem[] {\n if (doc.attrs && \"attachments\" in doc.attrs) {\n const raw = (doc.attrs.attachments as AttachmentsDocAttr | null)?.items;\n return parseAttachments(raw);\n }\n const node = doc.content?.find((n) => n.type === \"attachments\");\n if (!node) return [];\n return parseAttachments(node.attrs?.items as string | undefined);\n}\n\n/**\n * Extract `contentWidth`. Returns `DEFAULT_CONTENT_WIDTH` if absent or invalid.\n */\nexport function extractContentWidth(doc: JSONContent): MatopsContentWidth {\n const val = doc.attrs?.contentWidth as MatopsContentWidth;\n const valid: MatopsContentWidth[] = [\n ContentWidths.full,\n ContentWidths.normal,\n ContentWidths.compact,\n ];\n return valid.includes(val as MatopsContentWidth)\n ? (val as MatopsContentWidth)\n : DEFAULT_CONTENT_WIDTH;\n}\n\n// ─────────────────────────────────────────────\n// Migration helper (legacy content[] → external doc.attrs format)\n// ─────────────────────────────────────────────\n\n/**\n * Migrate a **legacy** document (structural nodes in `content[]`) to the\n * **external** format (structural metadata in `doc.attrs`).\n *\n * Safe to call on already-migrated documents — returns them unchanged.\n * Alias of `toExternalFormat`.\n */\nexport const migrateToDocAttrs = toExternalFormat;\n","import { useEffect, useRef } from \"react\";\nimport { useEditor as useTiptapEditor } from \"@tiptap/react\";\nimport type { Editor, JSONContent } from \"@tiptap/core\";\nimport type {\n MatopsEditorFeature,\n EditorProps,\n} from \"@matops/editor/core/types\";\nimport { buildEditorConfig } from \"@matops/editor/core/registry/editorConfigBuilder\";\nimport { toExternalFormat } from \"@matops/editor/utils/helpers/docHelpers\";\n\n// ─────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────\n\n/**\n * Subset of EditorProps consumed by this hook.\n * Uses Pick so adding a prop to EditorProps automatically makes it available here.\n *\n * NOTE: \"placeholder\" is intentionally included even though the Placeholder\n * extension is configured at build time (not Tiptap's internal placeholder).\n * It must flow through here → buildEditorConfig → Placeholder.configure().\n */\ntype UseEditorInstanceOptions = Pick<\n EditorProps,\n | \"features\"\n | \"initialContent\"\n | \"editable\"\n | \"placeholder\"\n | \"collaborationProvider\"\n | \"onChange\"\n | \"onContentChange\"\n | \"onEditorReady\"\n>;\n\ninterface UseEditorInstanceResult {\n editor: Editor | null;\n resolvedFeatures: MatopsEditorFeature[];\n}\n\n// ─────────────────────────────────────────────\n// Hook\n// ─────────────────────────────────────────────\n\n/**\n * useEditorInstance\n *\n * Manages the full Tiptap editor lifecycle for the <Editor> component.\n *\n * Design decisions:\n * - `buildEditorConfig` is called once on mount and stored in a ref. The\n * feature list and placeholder are intentionally not reactive — changing\n * them after mount would require destroying and recreating the entire editor.\n * - Callback props (onChange, onContentChange, onEditorReady) are stored in\n * refs so they can be updated without recreating the editor instance.\n * - `editable` is the only prop synced reactively via editor.setEditable().\n */\nexport function useEditorInstance({\n features = [],\n initialContent,\n editable = true,\n placeholder,\n collaborationProvider,\n onChange,\n onContentChange,\n onEditorReady,\n}: UseEditorInstanceOptions): UseEditorInstanceResult {\n // Config is built once on mount. Feature list + placeholder are stable.\n const configRef = useRef(\n buildEditorConfig({ features, placeholder, collaborationProvider }),\n );\n const { resolvedFeatures, extensions } = configRef.current;\n\n // Callback refs — lets consumers update handlers without recreating the editor\n const onChangeRef = useRef(onChange);\n const onContentChangeRef = useRef(onContentChange);\n const onEditorReadyRef = useRef(onEditorReady);\n\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n useEffect(() => {\n onContentChangeRef.current = onContentChange;\n }, [onContentChange]);\n useEffect(() => {\n onEditorReadyRef.current = onEditorReady;\n }, [onEditorReady]);\n\n const editor = useTiptapEditor({\n extensions,\n content: initialContent,\n editable,\n onUpdate({ editor: e }) {\n // In the new architecture, structural data (cover, title, separator,\n // attachments) lives in doc.attrs via MatopsDocument commands.\n // The body content[] contains only real body nodes.\n // toExternalFormat is called for backward-compat with legacy docs that\n // may still have structural nodes in content[], but for new docs it is\n // effectively a no-op on the structural migration path — it just\n // returns the doc as-is since content[] has no structural nodes.\n const internalJson = e.getJSON() as JSONContent;\n const json = toExternalFormat(internalJson);\n onChangeRef.current?.(json);\n onContentChangeRef.current?.(e.getHTML(), json);\n },\n onCreate({ editor: e }) {\n onEditorReadyRef.current?.(e as Editor);\n },\n });\n\n // Sync editable reactively without recreating the editor\n useEffect(() => {\n if (!editor) return;\n editor.setEditable(editable);\n }, [editor, editable]);\n\n return { editor: editor as Editor | null, resolvedFeatures };\n}\n","import { useEffect } from \"react\";\nimport type { Editor, JSONContent } from \"@tiptap/core\";\nimport type { MatopsEditorFeature } from \"@matops/editor/core/types\";\n\ninterface UseEditorKeyboardOptions {\n editor: Editor | null;\n editable: boolean;\n resolvedFeatures: MatopsEditorFeature[];\n onPublish?: (content: JSONContent) => void;\n onOpenFind?: () => void;\n}\n\n/**\n * useEditorKeyboard\n *\n * Central hub for all global keyboard shortcuts that live outside the\n * Tiptap extension system. Tiptap handles its own shortcuts (bold, italic, etc.)\n * internally — this hook only manages shortcuts that need React state or that\n * trigger UI panels/modals.\n *\n * Shortcuts managed here:\n * - Ctrl/Cmd + Shift + P → onPublish (save/publish document)\n * - Ctrl/Cmd + F → open Find & Replace panel\n *\n * To add a new shortcut:\n * 1. Add its handler inside the `handler` function below\n * 2. Add it to KeyboardShortcutsModal.tsx SHORTCUTS data array\n *\n * Shortcuts NOT managed here:\n * - `?` → KeyboardShortcutsModal (managed by useShortcutsModal)\n * - Formatting shortcuts (Bold, Italic…) → handled by Tiptap extensions\n * - Table navigation (Tab) → handled by Tiptap table extension\n * - Slash command (/) → handled by SlashMenu\n * - Escape → handled locally in each panel/modal component\n */\nexport function useEditorKeyboard({\n editor,\n editable,\n resolvedFeatures,\n onPublish,\n onOpenFind,\n}: UseEditorKeyboardOptions): void {\n useEffect(() => {\n // Nothing to bind\n if (!editor || !editable) return;\n\n const handler = (e: KeyboardEvent) => {\n const mod = e.ctrlKey || e.metaKey;\n\n // Ctrl/Cmd + Shift + P → Publish\n if (mod && e.shiftKey && e.key === \"P\" && onPublish) {\n e.preventDefault();\n onPublish(editor.getJSON());\n return;\n }\n\n // Ctrl/Cmd + F → Find & Replace\n if (\n mod &&\n e.key === \"f\" &&\n resolvedFeatures.includes(\"find-replace\") &&\n onOpenFind\n ) {\n e.preventDefault();\n onOpenFind();\n return;\n }\n };\n\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [editor, editable, resolvedFeatures, onPublish, onOpenFind]);\n}\n","import { useState, useEffect } from \"react\";\n\n/**\n * useShortcutsModal\n *\n * Manages open/close state for the KeyboardShortcutsModal.\n * Binds the `?` key globally to toggle the modal, but only when\n * the active element is not a text input or textarea (to avoid\n * interfering with typing \"?\" in form fields or in the editor itself).\n *\n * Usage in parent:\n * ```ts\n * const { open, onClose, setOpen } = useShortcutsModal();\n * <KeyboardShortcutsModal open={open} onClose={onClose} />\n * ```\n */\nexport function useShortcutsModal() {\n const [open, setOpen] = useState(false);\n\n useEffect(() => {\n const handleKey = (e: KeyboardEvent) => {\n const tag = (e.target as HTMLElement)?.tagName;\n const isTyping = tag === \"INPUT\" || tag === \"TEXTAREA\" || (e.target as HTMLElement)?.isContentEditable;\n if (e.key === \"?\" && !isTyping) {\n e.preventDefault();\n setOpen((prev) => !prev);\n }\n };\n\n window.addEventListener(\"keydown\", handleKey);\n return () => window.removeEventListener(\"keydown\", handleKey);\n }, []);\n\n return {\n open,\n setOpen,\n onClose: () => setOpen(false),\n };\n}\n","import { useEffect, useCallback, useRef } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\n\ninterface UseImageUploadOptions {\n editor: Editor | null;\n editable: boolean;\n onFileUploaded?: (file: File) => Promise<string>;\n containerRef?: React.RefObject<HTMLElement>;\n}\n\n/**\n * Resolve a safe insertion position from drop coordinates.\n *\n * NOTE: In the 3-panel architecture, content[] contains ONLY body nodes.\n * No zone-clamping needed — every pos is a valid body insertion point.\n */\nfunction resolveDropPos(editor: Editor, clientX: number, clientY: number): number | null {\n const coords = editor.view.posAtCoords({ left: clientX, top: clientY });\n if (!coords) return null;\n return Math.max(0, Math.min(coords.pos, editor.state.doc.content.size));\n}\n\nexport function useImageUpload({\n editor,\n editable,\n onFileUploaded,\n containerRef,\n}: UseImageUploadOptions): void {\n const uploadRef = useRef(onFileUploaded);\n useEffect(() => { uploadRef.current = onFileUploaded; }, [onFileUploaded]);\n\n const uploadAndInsert = useCallback(\n async (file: File, insertPos?: number) => {\n if (!editor || !uploadRef.current) return;\n if (!file.type.startsWith(\"image/\")) return;\n try {\n const localUrl = URL.createObjectURL(file);\n if (insertPos !== undefined) {\n const imageType = editor.schema.nodes.image;\n if (!imageType) return;\n const node = imageType.create({ src: localUrl, alt: file.name });\n editor.view.dispatch(editor.state.tr.insert(insertPos, node));\n } else {\n editor.chain().focus().setImage({ src: localUrl, alt: file.name }).run();\n }\n const remoteUrl = await uploadRef.current(file);\n URL.revokeObjectURL(localUrl);\n const { tr } = editor.state;\n let replaced = false;\n editor.state.doc.descendants((node, pos) => {\n if (node.type.name === \"image\" && node.attrs.src === localUrl) {\n tr.setNodeMarkup(pos, undefined, { ...node.attrs, src: remoteUrl });\n replaced = true;\n }\n });\n if (replaced) editor.view.dispatch(tr);\n } catch (err) {\n console.error(\"[useImageUpload] Upload failed:\", err);\n }\n },\n [editor]\n );\n\n // Paste handler\n useEffect(() => {\n if (!editor || !editable || !onFileUploaded) return;\n const dom = editor.view.dom as HTMLElement;\n const handlePaste = (e: ClipboardEvent) => {\n const items = Array.from(e.clipboardData?.items ?? []).filter(i => i.type.startsWith(\"image/\"));\n if (!items.length) return;\n e.preventDefault();\n items.forEach(item => { const f = item.getAsFile(); if (f) uploadAndInsert(f); });\n };\n dom.addEventListener(\"paste\", handlePaste);\n return () => dom.removeEventListener(\"paste\", handlePaste);\n }, [editor, editable, onFileUploaded, uploadAndInsert]);\n\n // Drag & drop handler\n useEffect(() => {\n if (!editor || !editable || !onFileUploaded) return;\n const target = containerRef?.current ?? (editor.view.dom as HTMLElement);\n\n const handleDragOver = (e: DragEvent) => {\n const hasImg = Array.from(e.dataTransfer?.items ?? []).some(i => i.kind === \"file\" && i.type.startsWith(\"image/\"));\n if (hasImg) { e.preventDefault(); e.dataTransfer!.dropEffect = \"copy\"; target.classList.add(\"mat-drag-over\"); }\n };\n const handleDragLeave = () => target.classList.remove(\"mat-drag-over\");\n const handleDrop = (e: DragEvent) => {\n target.classList.remove(\"mat-drag-over\");\n const files = Array.from(e.dataTransfer?.files ?? []).filter(f => f.type.startsWith(\"image/\"));\n if (!files.length) return;\n e.preventDefault();\n const basePos = resolveDropPos(editor, e.clientX, e.clientY);\n if (basePos === null) return;\n files.forEach((file, i) => uploadAndInsert(file, basePos + i * 2));\n };\n\n target.addEventListener(\"dragover\", handleDragOver);\n target.addEventListener(\"dragleave\", handleDragLeave);\n target.addEventListener(\"drop\", handleDrop);\n return () => {\n target.removeEventListener(\"dragover\", handleDragOver);\n target.removeEventListener(\"dragleave\", handleDragLeave);\n target.removeEventListener(\"drop\", handleDrop);\n };\n }, [editor, editable, onFileUploaded, containerRef, uploadAndInsert]);\n}\n","/**\n * editorHooks.ts\n *\n * All React hooks that consume the EditorContext.\n * These are the primary interface for any component that needs to\n * read editor state, subscribe to updates, or check feature flags.\n */\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport { EditorFeatures, type MatopsEditorFeature, type MatopsEditorTheme } from \"@matops/editor/core/types\";\nimport { useEditorContext } from \"./EditorProvider\";\n\n// ─────────────────────────────────────────────\n// Instance & State\n// ─────────────────────────────────────────────\n\n/**\n * Returns the live Tiptap editor instance, or null while initializing.\n */\nexport const useEditor = () => useEditorContext().editor;\n\n/**\n * Returns the current editor theme.\n */\nexport function useEditorTheme(): MatopsEditorTheme {\n return useEditorContext().theme;\n}\n\n/**\n * Forces a re-render on every editor transaction.\n * Use when you need UI to stay in sync with every state change.\n */\nexport function useEditorUpdate() {\n const { editor } = useEditorContext();\n const [, setTick] = useState(0);\n\n useEffect(() => {\n if (!editor) return;\n const handler = () => setTick((t) => t + 1);\n editor.on(\"transaction\", handler);\n return () => { editor.off(\"transaction\", handler); };\n }, [editor]);\n}\n\n/**\n * Subscribes to a derived slice of editor state.\n * Re-renders only when the selected value changes (by reference equality).\n *\n * @example\n * const isBold = useEditorState(ed => ed?.isActive(\"bold\") ?? false);\n */\nexport function useEditorState<T>(selector: (editor: Editor | null) => T): T {\n const { editor } = useEditorContext();\n const [value, setValue] = useState<T>(() => selector(editor));\n\n useEffect(() => {\n if (!editor) return;\n\n const update = () => {\n const next = selector(editor);\n setValue((prev) => (Object.is(prev, next) ? prev : next));\n };\n\n update();\n editor.on(\"transaction\", update);\n return () => { editor.off(\"transaction\", update); };\n }, [editor, selector]);\n\n return value;\n}\n\n// ─────────────────────────────────────────────\n// Feature Flags\n// ─────────────────────────────────────────────\n\n/**\n * Returns true if a single feature is active in the current editor instance.\n */\nexport function useFeature(feature: MatopsEditorFeature): boolean {\n return useEditorContext().featureSet.has(feature);\n}\n\n/**\n * Returns a map of all feature flags as named booleans.\n * Prefer this over multiple `useFeature` calls in the same component.\n */\nexport function useFeatures() {\n const { featureSet } = useEditorContext();\n\n return useMemo(() => {\n const has = (name: MatopsEditorFeature) => featureSet.has(name);\n return {\n hasFormatting: has(EditorFeatures.formatting),\n hasCode: has(EditorFeatures.code),\n hasMedia: has(EditorFeatures.media),\n hasTables: has(EditorFeatures.tables),\n hasTaskList: has(EditorFeatures.taskList),\n hasCollaboration:has(EditorFeatures.collaboration),\n hasHistory: has(EditorFeatures.history),\n hasPlaceholder: has(EditorFeatures.placeholder),\n hasCharCount: has(EditorFeatures.characterCount),\n hasFindReplace: has(EditorFeatures.findReplace),\n hasCoverImage: has(EditorFeatures.coverImage),\n hasPageHeader: has(EditorFeatures.pageHeader),\n hasAttachments: has(EditorFeatures.attachments),\n };\n }, [featureSet]);\n}\n","import type { Editor } from \"@tiptap/core\";\nimport type { MatopsEditorFeature } from \"@matops/editor/core/types\";\nimport { TABLE_DEFAULTS } from \"@matops/editor/extensions/features/tablesFeature\";\n\n// ─────────────────────────────────────────────\n// Command Definition\n// ─────────────────────────────────────────────\n\nexport interface EditorCommand {\n id: string;\n title: string;\n description: string;\n /** Short text glyph — shown in slash menu icons and floating strip */\n icon: string;\n keywords: string[];\n /** Feature gate. null = always available */\n feature: MatopsEditorFeature | null;\n /**\n * Which logical group this command belongs to.\n * Controls how each surface organises its UI.\n *\n * text-style — paragraph + headings (toolbar dropdown, bubble picker)\n * list — bullet / ordered / task\n * block — blockquote, divider\n * code — code block\n * media — table (and future image insert)\n */\n group: \"text-style\" | \"list\" | \"block\" | \"code\" | \"media\";\n action: (editor: Editor) => void;\n isActive?: (editor: Editor) => boolean;\n}\n\n// ─────────────────────────────────────────────\n// Master Command List\n// ALL menus derive from here — edit once, applies everywhere.\n// Order within each group is the canonical display order.\n// ─────────────────────────────────────────────\n\nexport const EDITOR_COMMANDS: EditorCommand[] = [\n // ── Text style (Paragraph → H1 → … → H6) ────\n {\n id: \"paragraph\",\n group: \"text-style\",\n title: \"Paragraph\",\n description: \"Plain body text\",\n icon: \"¶\",\n keywords: [\"paragraph\", \"text\", \"body\", \"normal\", \"p\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().setParagraph().run(),\n isActive: (e) => e.isActive(\"paragraph\"),\n },\n {\n id: \"h1\",\n group: \"text-style\",\n title: \"Heading 1\",\n description: \"Largest section heading\",\n icon: \"H1\",\n keywords: [\"heading\", \"h1\", \"title\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleHeading({ level: 1 }).run(),\n isActive: (e) => e.isActive(\"heading\", { level: 1 }),\n },\n {\n id: \"h2\",\n group: \"text-style\",\n title: \"Heading 2\",\n description: \"Large section heading\",\n icon: \"H2\",\n keywords: [\"heading\", \"h2\", \"subtitle\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleHeading({ level: 2 }).run(),\n isActive: (e) => e.isActive(\"heading\", { level: 2 }),\n },\n {\n id: \"h3\",\n group: \"text-style\",\n title: \"Heading 3\",\n description: \"Medium section heading\",\n icon: \"H3\",\n keywords: [\"heading\", \"h3\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleHeading({ level: 3 }).run(),\n isActive: (e) => e.isActive(\"heading\", { level: 3 }),\n },\n {\n id: \"h4\",\n group: \"text-style\",\n title: \"Heading 4\",\n description: \"Small section heading\",\n icon: \"H4\",\n keywords: [\"heading\", \"h4\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleHeading({ level: 4 }).run(),\n isActive: (e) => e.isActive(\"heading\", { level: 4 }),\n },\n {\n id: \"h5\",\n group: \"text-style\",\n title: \"Heading 5\",\n description: \"Minor heading\",\n icon: \"H5\",\n keywords: [\"heading\", \"h5\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleHeading({ level: 5 }).run(),\n isActive: (e) => e.isActive(\"heading\", { level: 5 }),\n },\n {\n id: \"h6\",\n group: \"text-style\",\n title: \"Heading 6\",\n description: \"Smallest heading\",\n icon: \"H6\",\n keywords: [\"heading\", \"h6\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleHeading({ level: 6 }).run(),\n isActive: (e) => e.isActive(\"heading\", { level: 6 }),\n },\n\n // ── Lists ────────────────────────────────────\n {\n id: \"bullet\",\n group: \"list\",\n title: \"Bullet List\",\n description: \"Unordered list of items\",\n icon: \"•—\",\n keywords: [\"bullet\", \"list\", \"unordered\", \"ul\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleBulletList().run(),\n isActive: (e) => e.isActive(\"bulletList\"),\n },\n {\n id: \"ordered\",\n group: \"list\",\n title: \"Numbered List\",\n description: \"Ordered list of items\",\n icon: \"1.\",\n keywords: [\"ordered\", \"numbered\", \"list\", \"ol\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleOrderedList().run(),\n isActive: (e) => e.isActive(\"orderedList\"),\n },\n {\n id: \"task\",\n group: \"list\",\n title: \"Task List\",\n description: \"Checkbox to-do items\",\n icon: \"☑\",\n keywords: [\"task\", \"todo\", \"checklist\", \"checkbox\"],\n feature: \"task-list\",\n action: (e) => e.chain().focus().toggleTaskList().run(),\n isActive: (e) => e.isActive(\"taskList\"),\n },\n\n // ── Blocks ───────────────────────────────────\n {\n id: \"blockquote\",\n group: \"block\",\n title: \"Blockquote\",\n description: \"Highlighted quote block\",\n icon: \"❝\",\n keywords: [\"quote\", \"blockquote\", \"callout\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().toggleBlockquote().run(),\n isActive: (e) => e.isActive(\"blockquote\"),\n },\n {\n id: \"divider\",\n group: \"block\",\n title: \"Divider\",\n description: \"Horizontal separator line\",\n icon: \"—\",\n keywords: [\"divider\", \"hr\", \"separator\", \"line\", \"rule\"],\n feature: \"formatting\",\n action: (e) => e.chain().focus().setHorizontalRule().run(),\n },\n\n // ── Code ─────────────────────────────────────\n {\n id: \"code-block\",\n group: \"code\",\n title: \"Code Block\",\n description: \"Syntax-highlighted code\",\n icon: \"</>\",\n keywords: [\"code\", \"codeblock\", \"snippet\", \"pre\"],\n feature: \"code\",\n action: (e) => e.chain().focus().toggleCodeBlock().run(),\n isActive: (e) => e.isActive(\"codeBlock\"),\n },\n\n // ── Media ─────────────────────────────────────\n {\n id: \"table\",\n group: \"media\",\n title: \"Table\",\n description: \"Insert a table\",\n icon: \"⊞\",\n keywords: [\"table\", \"grid\", \"spreadsheet\"],\n feature: \"tables\",\n action: (e) =>\n e\n .chain()\n .focus()\n .insertTable({\n rows: TABLE_DEFAULTS.defaultRows,\n cols: TABLE_DEFAULTS.defaultCols,\n withHeaderRow: TABLE_DEFAULTS.withHeaderRow,\n })\n .run(),\n },\n];\n\n// ─────────────────────────────────────────────\n// Canonical group order (used by slash menu for section headers)\n// ─────────────────────────────────────────────\n\nexport const GROUP_ORDER: EditorCommand[\"group\"][] = [\n \"text-style\",\n \"list\",\n \"block\",\n \"code\",\n \"media\",\n];\n\nexport const GROUP_LABELS: Record<EditorCommand[\"group\"], string> = {\n \"text-style\": \"Text Style\",\n list: \"Lists\",\n block: \"Blocks\",\n code: \"Code\",\n media: \"Media\",\n};\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\n/**\n * Returns all commands available for the given feature set,\n * optionally narrowed by a search query.\n */\nexport function filterCommands(\n features: MatopsEditorFeature[],\n query?: string,\n): EditorCommand[] {\n const base = EDITOR_COMMANDS.filter(\n (c) => c.feature === null || features.includes(c.feature),\n );\n if (!query) return base;\n const q = query.toLowerCase();\n return base.filter(\n (c) =>\n c.title.toLowerCase().includes(q) ||\n c.keywords.some((k) => k.includes(q)),\n );\n}\n\n/**\n * Returns commands split into canonical groups (preserving GROUP_ORDER).\n * Empty groups are omitted.\n */\nexport function groupedCommands(\n features: MatopsEditorFeature[],\n query?: string,\n): Array<{\n group: EditorCommand[\"group\"];\n label: string;\n commands: EditorCommand[];\n}> {\n const filtered = filterCommands(features, query);\n return GROUP_ORDER.map((group) => ({\n group,\n label: GROUP_LABELS[group],\n commands: filtered.filter((c) => c.group === group),\n })).filter((g) => g.commands.length > 0);\n}\n\n/**\n * Returns only commands belonging to the \"text-style\" group.\n * Used by toolbar dropdown and bubble menu style picker.\n */\nexport function textStyleCommands(\n features: MatopsEditorFeature[],\n): EditorCommand[] {\n return filterCommands(features).filter((c) => c.group === \"text-style\");\n}\n\n/**\n * Returns only block-insert commands (list + block + code + media).\n * Used by toolbar icon strip and floating menu strip.\n */\nexport function blockCommands(\n features: MatopsEditorFeature[],\n): EditorCommand[] {\n return filterCommands(features).filter((c) => c.group !== \"text-style\");\n}\n","/**\n * @matops/editor — Icon Library\n *\n * Single source of truth for all inline SVG icons used across the editor UI.\n * No external icon library dependency — keeps bundle lean and icons consistent.\n *\n * Naming convention: <PurposeName>Icon\n * All icons default to 14×14 unless a specific size is needed by their context.\n */\n\n// ─────────────────────────────────────────────\n// Shared prop type\n// ─────────────────────────────────────────────\n\ninterface IconProps {\n size?: number;\n}\n\n// ─────────────────────────────────────────────\n// Text Formatting\n// ─────────────────────────────────────────────\n\nexport const BoldIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n <path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n </svg>\n);\n\nexport const ItalicIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\" />\n <line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\" />\n <line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\" />\n </svg>\n);\n\nexport const UnderlineIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\" />\n <line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\" />\n </svg>\n);\n\nexport const StrikeIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M16 4H9a3 3 0 0 0-2.83 4\" />\n <path d=\"M14 12a4 4 0 0 1 0 8H6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n </svg>\n);\n\nexport const HighlightIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 11-6 6v3h9l3-3\" />\n <path d=\"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Headings\n// ─────────────────────────────────────────────\n\nexport const H1Icon = ({ size = 16 }: IconProps) => (\n <svg\n width={size}\n height={14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 12h8M4 6v12M12 6v12M17 12l3-2v8\" />\n </svg>\n);\n\nexport const H2Icon = ({ size = 16 }: IconProps) => (\n <svg\n width={size}\n height={14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 12h8M4 6v12M12 6v12M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1\" />\n </svg>\n);\n\nexport const H3Icon = ({ size = 16 }: IconProps) => (\n <svg\n width={size}\n height={14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 12h8M4 6v12M12 6v12M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2 2 2 0 0 1 2 2c0 1.5-1.83 2.5-3.5 1.5\" />\n </svg>\n);\n\nexport const H4Icon = ({ size = 16 }: IconProps) => (\n <svg\n width={size}\n height={14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 12h8M4 6v12M12 6v12M17 10v4h4M21 10v8\" />\n </svg>\n);\n\nexport const H5Icon = ({ size = 16 }: IconProps) => (\n <svg\n width={size}\n height={14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 12h8M4 6v12M12 6v12M21 10h-4l-1 4c1.5-1 4 0 4 2.5S18.5 19 17 18\" />\n </svg>\n);\n\nexport const H6Icon = ({ size = 16 }: IconProps) => (\n <svg\n width={size}\n height={14}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 12h8M4 6v12M12 6v12M19 10c-2 0-4 2-4 4s1.5 4 3.5 4 3.5-2 3.5-4\" />\n </svg>\n);\n\nexport const ParagraphIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M13 4v16M17 4H9.5a4.5 4.5 0 0 0 0 9H13\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Lists & Blocks\n// ─────────────────────────────────────────────\n\nexport const BulletListIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"9\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"9\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"9\" y1=\"18\" x2=\"20\" y2=\"18\" />\n <circle cx=\"4\" cy=\"6\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"4\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"4\" cy=\"18\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n);\n\nexport const OrderedListIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\" />\n <path\n d=\"M4 6h1v4M4 10h2M6 18H4c0-1 2-2 2-3s-1-1.5-2-1\"\n stroke=\"currentColor\"\n />\n </svg>\n);\n\nexport const BlockquoteIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\" />\n <path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\" />\n </svg>\n);\n\nexport const DividerIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Code\n// ─────────────────────────────────────────────\n\nexport const CodeIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </svg>\n);\n\nexport const CodeBlockIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"18\" rx=\"3\" />\n <path d=\"M8 9l-4 3 4 3M16 9l4 3-4 3M12 6l-2 12\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// History\n// ─────────────────────────────────────────────\n\nexport const UndoIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 7v6h6\" />\n <path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\" />\n </svg>\n);\n\nexport const RedoIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 7v6h-6\" />\n <path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Links & Media\n// ─────────────────────────────────────────────\n\nexport const LinkIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n);\n\nexport const UnlinkIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n <line x1=\"2\" y1=\"2\" x2=\"22\" y2=\"22\" />\n </svg>\n);\n\nexport const ExternalLinkIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n);\n\nexport const EditIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n);\n\nexport const EyeIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n);\n\nexport const EyeOffIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\" />\n <path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\" />\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Alignment\n// ─────────────────────────────────────────────\n\nexport const AlignLeftIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\" />\n <line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\" />\n <line x1=\"11\" y1=\"18\" x2=\"3\" y2=\"18\" />\n </svg>\n);\n\nexport const AlignCenterIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"17\" y1=\"10\" x2=\"7\" y2=\"10\" />\n <line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\" />\n <line x1=\"17\" y1=\"18\" x2=\"7\" y2=\"18\" />\n </svg>\n);\n\nexport const AlignRightIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\" />\n <line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\" />\n <line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\" />\n <line x1=\"21\" y1=\"18\" x2=\"11\" y2=\"18\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Tables\n// ─────────────────────────────────────────────\n\nexport const TableIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <path d=\"M3 9h18M3 15h18M9 3v18M15 3v18\" />\n </svg>\n);\n\nexport const AddRowAboveIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"10\" rx=\"1\" />\n <path d=\"M12 5v6M9 8l3-3 3 3\" />\n </svg>\n);\n\nexport const AddRowBelowIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"10\" rx=\"1\" />\n <path d=\"M12 19v-6M9 16l3 3 3-3\" />\n </svg>\n);\n\nexport const AddColLeftIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"13\" y=\"3\" width=\"8\" height=\"18\" rx=\"1\" />\n <path d=\"M9 12H3M6 9l-3 3 3 3\" />\n </svg>\n);\n\nexport const AddColRightIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"3\" width=\"8\" height=\"18\" rx=\"1\" />\n <path d=\"M15 12h6M18 9l3 3-3 3\" />\n </svg>\n);\n\nexport const DeleteRowIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"8\" width=\"18\" height=\"8\" rx=\"1\" />\n <path d=\"M9 12h6\" />\n </svg>\n);\n\nexport const DeleteColIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"8\" y=\"3\" width=\"8\" height=\"18\" rx=\"1\" />\n <path d=\"M12 9v6\" />\n </svg>\n);\n\nexport const MergeCellsIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\" />\n <path d=\"M3 9h18M3 15h18M9 3v18\" />\n <path d=\"M15 9l2 3-2 3\" />\n </svg>\n);\n\nexport const SplitCellIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\" />\n <path d=\"M12 3v18M3 9h9M3 15h9\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Actions\n// ─────────────────────────────────────────────\n\nexport const DeleteIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n <line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\" />\n <line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\" />\n </svg>\n);\n\nexport const CheckIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n);\n\nexport const SearchIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n);\n\nexport const DownloadIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"7 10 12 15 17 10\" />\n <line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" />\n </svg>\n);\n\nexport const HelpIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n);\n\nexport const AltTextIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n);\n\nexport const DeleteTableIcon = ({ size = 14 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n >\n <path d=\"M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n <line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\" />\n <line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Table Handles & Controls\n// ─────────────────────────────────────────────\n\n/** 6-dot vertical grip — row handle trigger */\nexport const GripVerticalIcon = ({ size = 12 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 10 16\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <circle cx=\"3\" cy=\"2.5\" r=\"1.3\" />\n <circle cx=\"7\" cy=\"2.5\" r=\"1.3\" />\n <circle cx=\"3\" cy=\"8\" r=\"1.3\" />\n <circle cx=\"7\" cy=\"8\" r=\"1.3\" />\n <circle cx=\"3\" cy=\"13.5\" r=\"1.3\" />\n <circle cx=\"7\" cy=\"13.5\" r=\"1.3\" />\n </svg>\n);\n\n/** 6-dot horizontal grip — column handle trigger */\nexport const GripHorizontalIcon = ({ size = 12 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 10\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <circle cx=\"2.5\" cy=\"3\" r=\"1.3\" />\n <circle cx=\"8\" cy=\"3\" r=\"1.3\" />\n <circle cx=\"13.5\" cy=\"3\" r=\"1.3\" />\n <circle cx=\"2.5\" cy=\"7\" r=\"1.3\" />\n <circle cx=\"8\" cy=\"7\" r=\"1.3\" />\n <circle cx=\"13.5\" cy=\"7\" r=\"1.3\" />\n </svg>\n);\n\nexport const ArrowUpIcon = ({ size = 13 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\" />\n <polyline points=\"5 12 12 5 19 12\" />\n </svg>\n);\n\nexport const ArrowDownIcon = ({ size = 13 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <polyline points=\"19 12 12 19 5 12\" />\n </svg>\n);\n\nexport const ArrowLeftIcon = ({ size = 13 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"19\" y1=\"12\" x2=\"5\" y2=\"12\" />\n <polyline points=\"12 19 5 12 12 5\" />\n </svg>\n);\n\nexport const ArrowRightIcon = ({ size = 13 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n <polyline points=\"12 5 19 12 12 19\" />\n </svg>\n);\n\nexport const DuplicateIcon = ({ size = 13 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n);\n\nexport const PlusIcon = ({ size = 13 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\n// ─────────────────────────────────────────────\n// Page Header\n// ─────────────────────────────────────────────\n\n/**\n * DefaultSeparatorIcon — the quill SVG used as the fallback badge icon\n * in TitleSeparator, SeparatorIconView, and EditorViewer.\n * Single source of truth — no more duplication across three files.\n */\nexport const DefaultSeparatorIcon = ({ size = 10 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M20 2L2 22\" />\n <path d=\"M2 2c0 0 10 0 18 8\" />\n </svg>\n);\n\nexport const UploadIcon = ({ size = 10 }: IconProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n);\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge Tailwind CSS classes safely.\n * Combines clsx (conditional classes) with tailwind-merge (deduplication).\n *\n * @example\n * cn(\"p-4\", isActive && \"bg-blue-500\", \"p-2\")\n * // → \"bg-blue-500 p-2\" (p-4 deduplicated by tailwind-merge)\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * TableTriggerButton\n *\n * A toolbar button that opens an interactive 8 × 8 grid picker when clicked.\n * Hovering over a cell highlights the selection and shows \"N × M\" in the label.\n * Clicking inserts a table with those dimensions.\n *\n * Rendered inline (not a portal) because the toolbar already sits above the\n * editor content in the stacking context — the dropdown just needs to float\n * below the button, which `position: absolute` handles fine here.\n */\n\nimport { useState, useRef, useEffect, useCallback } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport { TableIcon } from \"@matops/editor/ui/icons/index\";\nimport { TABLE_DEFAULTS } from \"@matops/editor/extensions/features/tablesFeature\";\n\nconst MAX_ROWS = 8;\nconst MAX_COLS = 8;\n\nexport function TableTriggerButton() {\n const { editor, editable } = useEditorContext();\n const [open, setOpen] = useState(false);\n const [hovered, setHovered] = useState<{ rows: number; cols: number } | null>(\n null,\n );\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Close on outside click\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(e.target as Node)\n ) {\n setOpen(false);\n setHovered(null);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n const insert = useCallback(\n (rows: number, cols: number) => {\n if (!editor) return;\n editor\n .chain()\n .focus()\n .insertTable({\n rows,\n cols,\n withHeaderRow: TABLE_DEFAULTS.withHeaderRow,\n })\n .run();\n setOpen(false);\n setHovered(null);\n },\n [editor],\n );\n\n if (!editable) return null;\n\n const label = hovered ? `${hovered.rows} × ${hovered.cols}` : \"Table\";\n\n return (\n <div\n ref={containerRef}\n className=\"mat-table-trigger-wrap\"\n style={{ position: \"relative\", display: \"inline-flex\" }}\n >\n {/* ── Toolbar button ── */}\n <button\n type=\"button\"\n className={cn(\"mat-toolbar-btn\", open && \"is-active\")}\n title=\"Insert table\"\n aria-label=\"Insert table\"\n aria-haspopup=\"true\"\n aria-expanded={open}\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen((p) => !p);\n if (open) setHovered(null);\n }}\n >\n <TableIcon />\n </button>\n\n {/* ── Grid picker dropdown ── */}\n {open && (\n <div\n className=\"mat-table-picker\"\n role=\"dialog\"\n aria-label=\"Choose table dimensions\"\n >\n {/* Dimension label */}\n <div className=\"mat-table-picker__label\">{label}</div>\n\n {/* 8×8 grid */}\n <div\n className=\"mat-table-picker__grid\"\n onMouseLeave={() => setHovered(null)}\n >\n {Array.from({ length: MAX_ROWS }, (_, r) =>\n Array.from({ length: MAX_COLS }, (_, c) => {\n const row = r + 1;\n const col = c + 1;\n const isHighlighted =\n hovered !== null &&\n row <= hovered.rows &&\n col <= hovered.cols;\n return (\n <div\n key={`${r}-${c}`}\n className={cn(\n \"mat-table-picker__cell\",\n isHighlighted && \"is-highlighted\",\n )}\n onMouseEnter={() => setHovered({ rows: row, cols: col })}\n onMouseDown={(e) => {\n e.preventDefault();\n insert(row, col);\n }}\n aria-label={`${row} rows, ${col} columns`}\n />\n );\n }),\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","import {\n useState,\n useRef,\n useEffect,\n useLayoutEffect,\n useCallback,\n type RefObject,\n} from \"react\";\n\nexport interface DropdownPosition {\n top: number;\n left: number;\n}\n\ninterface UseDropdownOptions {\n /** Extra vertical gap between trigger and menu (px). Default 4. */\n offset?: number;\n}\n\ninterface UseDropdownResult {\n open: boolean;\n visible: boolean;\n dropPos: DropdownPosition;\n triggerRef: RefObject<HTMLButtonElement>;\n menuRef: RefObject<HTMLDivElement>;\n toggle: () => void;\n close: () => void;\n}\n\n/**\n * useDropdown\n *\n * Shared hook for portal-based dropdown menus used in EditorToolbar and\n * FormattingBubbleMenu. Handles:\n * - Open / close state\n * - Post-render position measurement (via useLayoutEffect)\n * - Viewport clamping so the menu never overflows the screen\n * - Close on outside click and scroll\n *\n * The menu is initially rendered off-screen (left: -9999) and becomes\n * visible only after its real dimensions are measured.\n *\n * @example\n * const { open, visible, dropPos, triggerRef, menuRef, toggle, close } =\n * useDropdown({ offset: 6 });\n */\nexport function useDropdown({ offset = 4 }: UseDropdownOptions = {}): UseDropdownResult {\n const [open, setOpen] = useState(false);\n const [visible, setVisible] = useState(false);\n const [dropPos, setDropPos] = useState<DropdownPosition>({ top: 0, left: -9999 });\n\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // ── Measure and clamp position after portal renders ──────────────────────\n useLayoutEffect(() => {\n if (!open || !triggerRef.current || !menuRef.current) return;\n\n const tr = triggerRef.current.getBoundingClientRect();\n const mw = menuRef.current.offsetWidth;\n const mh = menuRef.current.offsetHeight;\n\n let top = tr.bottom + offset;\n let left = tr.left;\n\n // Flip above trigger if menu would overflow viewport bottom\n if (top + mh > window.innerHeight - 8) top = tr.top - mh - offset;\n // Clamp horizontal edges\n if (left + mw > window.innerWidth - 8) left = Math.max(8, window.innerWidth - mw - 8);\n if (left < 8) left = 8;\n\n setDropPos({ top, left });\n setVisible(true);\n }, [open, offset]);\n\n // ── Close on outside click or scroll ─────────────────────────────────────\n useEffect(() => {\n if (!open) return;\n\n const handleMouseDown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n menuRef.current && !menuRef.current.contains(target) &&\n triggerRef.current && !triggerRef.current.contains(target)\n ) {\n setOpen(false);\n setVisible(false);\n }\n };\n\n const handleScroll = () => {\n setOpen(false);\n setVisible(false);\n };\n\n document.addEventListener(\"mousedown\", handleMouseDown);\n window.addEventListener(\"scroll\", handleScroll, { capture: true, passive: true });\n\n return () => {\n document.removeEventListener(\"mousedown\", handleMouseDown);\n window.removeEventListener(\"scroll\", handleScroll, true);\n };\n }, [open]);\n\n const toggle = useCallback(() => {\n if (open) {\n setOpen(false);\n setVisible(false);\n } else {\n setVisible(false);\n setDropPos({ top: 0, left: -9999 }); // off-screen until measured\n setOpen(true);\n }\n }, [open]);\n\n const close = useCallback(() => {\n setOpen(false);\n setVisible(false);\n }, []);\n\n return { open, visible, dropPos, triggerRef, menuRef, toggle, close };\n}\n","import React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useEditorUpdate } from \"@matops/editor/core/context/editorHooks\";\nimport {\n textStyleCommands,\n blockCommands,\n} from \"@matops/editor/ui/commands/commandRegistry\";\nimport {\n BulletListIcon,\n OrderedListIcon,\n BlockquoteIcon,\n DividerIcon,\n CodeIcon,\n CodeBlockIcon,\n UndoIcon,\n RedoIcon,\n SearchIcon,\n DownloadIcon,\n HelpIcon,\n BoldIcon,\n ItalicIcon,\n UnderlineIcon,\n StrikeIcon,\n HighlightIcon,\n EyeIcon,\n EyeOffIcon,\n} from \"@matops/editor/ui/icons/index\";\nimport { TableTriggerButton } from \"@matops/editor/ui/toolbar/TableTriggerButton\";\nimport type { EditorCommand } from \"@matops/editor/ui/commands/commandRegistry\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport { useDropdown } from \"@matops/editor/utils/hooks/useDropdown\";\nimport { getContentWidth } from \"@matops/editor/extensions/nodes/documentNode\";\nimport type { MatopsContentWidth } from \"@matops/editor/core/types\";\n\nconst BLOCK_ICONS: Record<string, React.ReactNode> = {\n bullet: <BulletListIcon />,\n ordered: <OrderedListIcon />,\n task: <span style={{ fontSize: 11, fontWeight: 700 }}>☑</span>,\n blockquote: <BlockquoteIcon />,\n divider: <DividerIcon />,\n \"code-block\": <CodeBlockIcon />,\n};\n\n// ─────────────────────────────────────────────\n// Content Width Picker\n// ─────────────────────────────────────────────\n\nconst WIDTH_OPTIONS: {\n value: MatopsContentWidth;\n label: string;\n title: string;\n}[] = [\n { value: \"full\", label: \"⟷\", title: \"Full width\" },\n { value: \"normal\", label: \"▭\", title: \"Normal width (default)\" },\n { value: \"compact\", label: \"▯\", title: \"Compact width\" },\n];\n\n/**\n * ContentWidthPicker — inline toolbar segment that calls `setContentWidth`\n * to update the `contentWidth` doc-level attribute via a `DocAttrStep`.\n *\n * The setting is stored in the JSON doc — not in React state — so it persists\n * across saves, remounts, and viewer renders automatically.\n */\nfunction ContentWidthPicker() {\n const { editor, editable } = useEditorContext();\n useEditorUpdate();\n\n if (!editor || !editable) return null;\n\n const current = getContentWidth(editor);\n\n const setWidth = (width: MatopsContentWidth) => {\n // editor.commands.setContentWidth is defined on MatopsDocument and dispatches\n // a DocAttrStep via tr.setDocAttribute — the only correct way to update\n // the root doc node's attrs (setNodeMarkup(0) targets the first child, not the doc).\n editor.commands.setContentWidth(width);\n editor.commands.focus();\n };\n\n return (\n <div className=\"mat-width-picker\" role=\"group\" aria-label=\"Content width\">\n {WIDTH_OPTIONS.map(({ value, label, title }) => (\n <button\n key={value}\n type=\"button\"\n className={cn(\n \"mat-width-picker__btn\",\n current === value && \"is-active\",\n )}\n onClick={() => setWidth(value)}\n title={title}\n aria-label={title}\n aria-pressed={current === value}\n >\n {label}\n </button>\n ))}\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// ─────────────────────────────────────────────\n\nfunction TextStyleDropdown({ commands }: { commands: EditorCommand[] }) {\n const { editor, theme } = useEditorContext();\n useEditorUpdate();\n\n const { open, visible, dropPos, triggerRef, menuRef, toggle, close } =\n useDropdown();\n\n const active = commands.find((cmd) => cmd.isActive?.(editor!)) ?? commands[0];\n\n if (!editor) return null;\n\n const dropdown = open\n ? createPortal(\n <div\n ref={menuRef}\n className={`mat-style-picker__menu matops-editor--${theme ?? \"light\"}`}\n role=\"listbox\"\n aria-label=\"Text style\"\n style={{\n position: \"fixed\",\n top: dropPos.top,\n left: dropPos.left,\n zIndex: 99999,\n visibility: visible ? \"visible\" : \"hidden\",\n }}\n >\n {commands.map((cmd) => (\n <button\n key={cmd.id}\n type=\"button\"\n role=\"option\"\n aria-selected={cmd.isActive?.(editor)}\n className={cn(\n \"mat-style-picker__item\",\n cmd.isActive?.(editor) && \"is-active\",\n )}\n data-style={cmd.id}\n onMouseDown={(e) => {\n e.preventDefault();\n cmd.action(editor);\n close();\n }}\n >\n {cmd.title}\n </button>\n ))}\n </div>,\n document.body,\n )\n : null;\n\n return (\n <>\n <div className=\"mat-style-picker\">\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"mat-style-picker__trigger\"\n onClick={toggle}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n title=\"Text style\"\n >\n <span className=\"mat-style-picker__label\">\n {active?.title ?? \"Paragraph\"}\n </span>\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n style={{ flexShrink: 0, opacity: 0.6 }}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n </div>\n {dropdown}\n </>\n );\n}\n\n// ─────────────────────────────────────────────\n// Toolbar Button\n// ─────────────────────────────────────────────\n\ninterface ToolbarButtonProps {\n onClick: () => void;\n isActive?: boolean;\n isDisabled?: boolean;\n title: string;\n children: React.ReactNode;\n}\n\nfunction ToolbarButton({\n onClick,\n isActive,\n isDisabled,\n title,\n children,\n}: ToolbarButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={isDisabled}\n title={title}\n aria-label={title}\n aria-pressed={isActive}\n className={cn(\n \"matops-editor__toolbar-btn\",\n isActive && \"is-active\",\n isDisabled && \"is-disabled\",\n )}\n >\n {children}\n </button>\n );\n}\n\nfunction ToolbarDivider() {\n return <div className=\"matops-editor__toolbar-divider\" aria-hidden=\"true\" />;\n}\n\n// ─────────────────────────────────────────────\n// Core Toolbar\n// ─────────────────────────────────────────────\n\nexport function EditorToolbar() {\n const { editor, features, editable } = useEditorContext();\n useEditorUpdate();\n\n if (!editor || !editable) return null;\n\n const hasHistory =\n features.includes(\"history\") || features.includes(\"collaboration\");\n const hasFormatting = features.includes(\"formatting\");\n const hasCode = features.includes(\"code\");\n\n const styleCmds = textStyleCommands(features);\n const blockCmds = blockCommands(features);\n\n return (\n <div\n className=\"matops-editor__toolbar\"\n role=\"toolbar\"\n aria-label=\"Text formatting\"\n >\n {hasHistory && (\n <>\n <ToolbarButton\n onClick={() => editor.chain().focus().undo().run()}\n isDisabled={!editor.can().undo()}\n title=\"Undo (Ctrl+Z)\"\n >\n <UndoIcon />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().redo().run()}\n isDisabled={!editor.can().redo()}\n title=\"Redo (Ctrl+Shift+Z)\"\n >\n <RedoIcon />\n </ToolbarButton>\n </>\n )}\n\n {hasFormatting && styleCmds.length > 0 && (\n <>\n <ToolbarDivider />\n <TextStyleDropdown commands={styleCmds} />\n </>\n )}\n\n {hasFormatting && (\n <>\n <ToolbarDivider />\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleBold().run()}\n isActive={editor.isActive(\"bold\")}\n title=\"Bold (Ctrl+B)\"\n >\n <BoldIcon />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleItalic().run()}\n isActive={editor.isActive(\"italic\")}\n title=\"Italic (Ctrl+I)\"\n >\n <ItalicIcon />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleUnderline().run()}\n isActive={editor.isActive(\"underline\")}\n title=\"Underline\"\n >\n <UnderlineIcon />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleStrike().run()}\n isActive={editor.isActive(\"strike\")}\n title=\"Strikethrough\"\n >\n <StrikeIcon />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleHighlight().run()}\n isActive={editor.isActive(\"highlight\")}\n title=\"Highlight\"\n >\n <HighlightIcon />\n </ToolbarButton>\n </>\n )}\n\n {hasCode && (\n <>\n <ToolbarDivider />\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleCode().run()}\n isActive={editor.isActive(\"code\")}\n title=\"Inline code (Ctrl+E)\"\n >\n <CodeIcon />\n </ToolbarButton>\n </>\n )}\n\n {blockCmds.length > 0 && (\n <>\n <ToolbarDivider />\n {blockCmds.map((cmd: EditorCommand) => {\n // Table gets its own visual grid-picker button\n if (cmd.id === \"table\") {\n return <TableTriggerButton key=\"table\" />;\n }\n return (\n <ToolbarButton\n key={cmd.id}\n onClick={() => cmd.action(editor)}\n isActive={cmd.isActive?.(editor)}\n title={cmd.title}\n >\n {BLOCK_ICONS[cmd.id] ?? (\n <span style={{ fontSize: 10, fontWeight: 700 }}>\n {cmd.icon}\n </span>\n )}\n </ToolbarButton>\n );\n })}\n </>\n )}\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// Toolbar with Action Buttons\n// ─────────────────────────────────────────────\n\ninterface EditorToolbarWithActionsProps {\n onOpenFind?: () => void;\n onOpenExport?: () => void;\n onOpenShortcuts?: () => void;\n /** Whether preview (read-only viewer) mode is currently active */\n previewMode?: boolean;\n /** Called when the user clicks the preview toggle pill */\n onTogglePreview?: () => void;\n}\n\nexport function EditorToolbarWithActions({\n onOpenFind,\n onOpenExport,\n onOpenShortcuts,\n previewMode = false,\n onTogglePreview,\n}: EditorToolbarWithActionsProps = {}) {\n const { editable } = useEditorContext();\n if (!editable) return null;\n\n const hasActions =\n onOpenFind || onOpenExport || onOpenShortcuts || onTogglePreview;\n\n return (\n <div className=\"matops-editor__toolbar-wrapper\">\n <EditorToolbar />\n {hasActions && (\n <div\n className=\"mat-toolbar-right\"\n role=\"toolbar\"\n aria-label=\"Editor actions\"\n >\n <ContentWidthPicker />\n\n {/* ── Preview toggle pill ─── */}\n {onTogglePreview && (\n <button\n type=\"button\"\n className={`mat-preview-toggle${previewMode ? \" mat-preview-toggle--active\" : \"\"}`}\n onClick={onTogglePreview}\n title={previewMode ? \"Back to editing\" : \"Preview document\"}\n aria-label={previewMode ? \"Back to editing\" : \"Preview document\"}\n aria-pressed={previewMode}\n >\n {previewMode ? <EyeOffIcon size={12} /> : <EyeIcon size={12} />}\n {previewMode ? \"Editing\" : \"Preview\"}\n </button>\n )}\n\n {/* ── Separator before icon buttons ─── */}\n {onTogglePreview &&\n (onOpenFind || onOpenExport || onOpenShortcuts) && (\n <span className=\"mat-toolbar-sep\" aria-hidden=\"true\" />\n )}\n\n {onOpenFind && (\n <button\n type=\"button\"\n className=\"mat-toolbar-action\"\n onClick={onOpenFind}\n title=\"Find & Replace (Ctrl+F)\"\n aria-label=\"Find and replace\"\n >\n <SearchIcon />\n </button>\n )}\n {onOpenExport && (\n <button\n type=\"button\"\n className=\"mat-toolbar-action\"\n onClick={onOpenExport}\n title=\"Export document\"\n aria-label=\"Export\"\n >\n <DownloadIcon />\n </button>\n )}\n {onOpenShortcuts && (\n <button\n type=\"button\"\n className=\"mat-toolbar-action\"\n onClick={onOpenShortcuts}\n title=\"Keyboard shortcuts (?)\"\n aria-label=\"Keyboard shortcuts\"\n >\n <HelpIcon />\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useMemo } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useEditorUpdate } from \"@matops/editor/core/context/editorHooks\";\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\nfunction estimateReadingTime(wordCount: number): string {\n // Average reading speed: ~200 wpm\n const minutes = wordCount / 200;\n if (minutes < 1) return \"< 1 min read\";\n return `${Math.ceil(minutes)} min read`;\n}\n\nfunction fallbackWordCount(text: string): number {\n return text.trim() === \"\" ? 0 : text.trim().split(/\\s+/).length;\n}\n\nfunction StatPill({ label, value }: { label: string; value: string | number }) {\n return (\n <div className=\"mat-count-stat\">\n <span className=\"mat-count-value\">{value}</span>\n {label && <span className=\"mat-count-label\">{label}</span>}\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// Character Count Bar\n// ─────────────────────────────────────────────\n\ninterface CharacterCountBarProps {\n /** Optional word limit — shows a progress indicator when set */\n wordLimit?: number;\n /** Optional character limit */\n charLimit?: number;\n}\n\n/**\n * CharacterCountBar\n *\n * A slim footer bar rendered below the editor content area.\n * Shows: words, characters, paragraphs, and estimated reading time.\n *\n * IMPORTANT: useEditorUpdate() is called so this component re-renders on\n * every editor transaction — without it, stats would only refresh on\n * React prop changes (i.e. never, since the editor ref is stable).\n */\nexport function CharacterCountBar({\n wordLimit,\n charLimit,\n}: CharacterCountBarProps) {\n const { editor } = useEditorContext();\n\n // Re-render on every transaction so stats stay live\n useEditorUpdate();\n\n const stats = useMemo(() => {\n if (!editor) return null;\n\n // Try @tiptap/extension-character-count storage first (accurate)\n const storage = editor.storage?.characterCount;\n const words: number =\n storage?.words?.() ?? fallbackWordCount(editor.getText());\n const chars: number = storage?.characters?.() ?? editor.getText().length;\n\n // Paragraph count from document structure\n let paragraphs = 0;\n editor.state.doc.descendants((node) => {\n if (\n node.type.name === \"paragraph\" &&\n node.textContent.trim().length > 0\n ) {\n paragraphs++;\n }\n });\n\n return { words, chars, paragraphs };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editor, editor?.state]); // editor.state changes on every transaction → triggers memo\n\n if (!editor || !stats) return null;\n\n const { words, chars, paragraphs } = stats;\n\n const wordProgress = wordLimit\n ? Math.min((words / wordLimit) * 100, 100)\n : null;\n const charProgress = charLimit\n ? Math.min((chars / charLimit) * 100, 100)\n : null;\n const isOverWordLimit = wordLimit ? words > wordLimit : false;\n const isOverCharLimit = charLimit ? chars > charLimit : false;\n const isOverAnyLimit = isOverWordLimit || isOverCharLimit;\n\n return (\n <div className=\"mat-count-bar\" aria-label=\"Document statistics\">\n <div className=\"mat-count-stats\">\n <StatPill label=\"words\" value={words.toLocaleString()} />\n <div className=\"mat-count-sep\" />\n <StatPill label=\"chars\" value={chars.toLocaleString()} />\n <div className=\"mat-count-sep\" />\n <StatPill label=\"paragraphs\" value={paragraphs} />\n <div className=\"mat-count-sep\" />\n <StatPill label=\"\" value={estimateReadingTime(words)} />\n\n {wordLimit && (\n <>\n <div className=\"mat-count-sep\" />\n <span\n className={`mat-count-limit ${isOverWordLimit ? \"over\" : \"\"}`}\n title={`Word limit: ${wordLimit}`}\n >\n {words} / {wordLimit.toLocaleString()} words\n </span>\n </>\n )}\n {charLimit && (\n <>\n <div className=\"mat-count-sep\" />\n <span\n className={`mat-count-limit ${isOverCharLimit ? \"over\" : \"\"}`}\n title={`Character limit: ${charLimit}`}\n >\n {chars} / {charLimit.toLocaleString()} chars\n </span>\n </>\n )}\n </div>\n\n {(wordProgress !== null || charProgress !== null) && (\n <div className=\"mat-count-progress-track\">\n <div\n className={`mat-count-progress-fill ${isOverAnyLimit ? \"over\" : \"\"}`}\n style={{ width: `${wordProgress ?? charProgress ?? 0}%` }}\n />\n </div>\n )}\n </div>\n );\n}\n","/**\n * ModalPrimitives.tsx\n *\n * Shared modal building blocks used by ExportPanel, KeyboardShortcutsModal,\n * and any future overlay. Extracted from MenuButton.tsx where they didn't belong.\n *\n * WHY PORTAL for ModalOverlay:\n * The editor container can create CSS stacking contexts via `transform`,\n * `will-change`, `filter`, or `z-index`. A `position: fixed` element inside\n * such a container is clipped to it rather than the viewport.\n * `createPortal(…, document.body)` bypasses all stacking contexts, guaranteeing\n * the overlay always covers the full viewport.\n *\n * WHY THEME CLASS on ModalOverlay:\n * Portaling to `document.body` breaks CSS variable inheritance from the editor\n * container (`.matops-editor--dark`). Stamping the theme class directly here\n * gives all `.mat-modal` descendants their own variable scope.\n */\nimport React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\n\n// ── ModalOverlay ──────────────────────────────────────────────────────────────\n\nexport function ModalOverlay({\n onClose,\n children,\n}: {\n onClose: () => void;\n children: React.ReactNode;\n}) {\n const { theme } = useEditorContext();\n\n return createPortal(\n <div\n className={cn(\n \"mat-modal-overlay\",\n theme === \"dark\" ? \"matops-editor--dark\" : \"matops-editor--light\",\n )}\n onMouseDown={onClose}\n role=\"presentation\"\n >\n {children}\n </div>,\n document.body,\n );\n}\n\n// ── ModalDialog ───────────────────────────────────────────────────────────────\n\nexport function ModalDialog({\n children,\n className,\n label,\n}: {\n children: React.ReactNode;\n className?: string;\n label?: string;\n}) {\n return (\n <div\n className={cn(\"mat-modal\", className)}\n role=\"dialog\"\n aria-label={label}\n onMouseDown={(e) => e.stopPropagation()}\n >\n {children}\n </div>\n );\n}\n\n// ── ModalHeader ───────────────────────────────────────────────────────────────\n\nexport function ModalHeader({\n title,\n onClose,\n}: {\n title: string;\n onClose: () => void;\n}) {\n return (\n <div className=\"mat-modal-header\">\n <span className=\"mat-modal-title\">{title}</span>\n <button\n type=\"button\"\n className=\"mat-modal-close\"\n onClick={onClose}\n aria-label=\"Close\"\n >\n ✕\n </button>\n </div>\n );\n}\n","import React, { useEffect } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport {\n ModalOverlay,\n ModalDialog,\n ModalHeader,\n} from \"@matops/editor/ui/primitives/ModalPrimitives\";\nimport type { MatopsEditorFeature } from \"@matops/editor/core/types\";\n\n// Re-export hook from its proper home (utils/hooks)\nexport { useShortcutsModal } from \"@matops/editor/utils/hooks/useShortcutsModal\";\n\n// ─────────────────────────────────────────────\n// Shortcut Data\n// ─────────────────────────────────────────────\n\ninterface ShortcutEntry {\n keys: string[];\n description: string;\n /** null = always show regardless of active features */\n feature: MatopsEditorFeature | null;\n}\n\nconst isMac =\n typeof navigator !== \"undefined\" && /Mac/.test(navigator.platform);\nconst Mod = isMac ? \"⌘\" : \"Ctrl\";\nconst Alt = isMac ? \"⌥\" : \"Alt\";\n\n/**\n * All keyboard shortcuts shown in the reference modal.\n *\n * To add a new shortcut:\n * 1. Add it here with the correct `feature` guard\n * 2. Implement the handler (in Tiptap extension or useEditorKeyboard)\n */\nconst SHORTCUTS: { group: string; items: ShortcutEntry[] }[] = [\n {\n group: \"Document\",\n items: [\n {\n keys: [Mod, \"Shift\", \"P\"],\n description: \"Publish / Save\",\n feature: null,\n },\n { keys: [Mod, \"Z\"], description: \"Undo\", feature: \"history\" },\n { keys: [Mod, \"Shift\", \"Z\"], description: \"Redo\", feature: \"history\" },\n {\n keys: [Mod, \"F\"],\n description: \"Find & Replace\",\n feature: \"find-replace\",\n },\n ],\n },\n {\n group: \"Formatting\",\n items: [\n { keys: [Mod, \"B\"], description: \"Bold\", feature: \"formatting\" },\n { keys: [Mod, \"I\"], description: \"Italic\", feature: \"formatting\" },\n { keys: [Mod, \"U\"], description: \"Underline\", feature: \"formatting\" },\n {\n keys: [Mod, \"Shift\", \"S\"],\n description: \"Strikethrough\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, \"Shift\", \"H\"],\n description: \"Highlight\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, Alt, \"1\"],\n description: \"Heading 1\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, Alt, \"2\"],\n description: \"Heading 2\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, Alt, \"3\"],\n description: \"Heading 3\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, \"Shift\", \"7\"],\n description: \"Ordered list\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, \"Shift\", \"8\"],\n description: \"Bullet list\",\n feature: \"formatting\",\n },\n {\n keys: [Mod, \"Shift\", \"B\"],\n description: \"Blockquote\",\n feature: \"formatting\",\n },\n ],\n },\n {\n group: \"Code\",\n items: [\n { keys: [Mod, \"E\"], description: \"Inline code\", feature: \"code\" },\n { keys: [Mod, Alt, \"C\"], description: \"Code block\", feature: \"code\" },\n ],\n },\n {\n group: \"Tables\",\n items: [\n { keys: [\"Tab\"], description: \"Next cell\", feature: \"tables\" },\n {\n keys: [\"Shift\", \"Tab\"],\n description: \"Previous cell\",\n feature: \"tables\",\n },\n ],\n },\n {\n group: \"Commands\",\n items: [\n { keys: [\"/\"], description: \"Slash commands\", feature: null },\n { keys: [\"?\"], description: \"This modal\", feature: null },\n ],\n },\n];\n\n// ─────────────────────────────────────────────\n// Kbd\n// ─────────────────────────────────────────────\n\nfunction Kbd({ children }: { children: React.ReactNode }) {\n return <kbd className=\"mat-kbd\">{children}</kbd>;\n}\n\n// ─────────────────────────────────────────────\n// Modal\n// ─────────────────────────────────────────────\n\ninterface KeyboardShortcutsModalProps {\n open: boolean;\n onClose: () => void;\n}\n\n/**\n * KeyboardShortcutsModal\n *\n * Feature-aware keyboard shortcut reference.\n * Only shows shortcuts whose `feature` is currently active.\n * Closes on Escape or overlay click.\n *\n * Triggered by: `?` key (via useShortcutsModal) or toolbar Help button.\n */\nexport function KeyboardShortcutsModal({\n open,\n onClose,\n}: KeyboardShortcutsModalProps) {\n const { features } = useEditorContext();\n\n // Escape to close\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [open, onClose]);\n\n if (!open) return null;\n\n const visibleGroups = SHORTCUTS.map((group) => ({\n ...group,\n items: group.items.filter(\n (item) => item.feature === null || features.includes(item.feature),\n ),\n })).filter((group) => group.items.length > 0);\n\n return (\n <ModalOverlay onClose={onClose}>\n <ModalDialog label=\"Keyboard shortcuts\">\n <ModalHeader title=\"Keyboard Shortcuts\" onClose={onClose} />\n <div className=\"mat-modal-body\">\n {visibleGroups.map((group) => (\n <div key={group.group} className=\"mat-shortcut-group\">\n <div className=\"mat-shortcut-group__label\">{group.group}</div>\n {group.items.map((item) => (\n <div key={item.description} className=\"mat-shortcut-row\">\n <span className=\"mat-shortcut-desc\">{item.description}</span>\n <span className=\"mat-shortcut-keys\">\n {item.keys.map((key, i) => (\n <React.Fragment key={i}>\n {i > 0 && <span className=\"mat-shortcut-plus\">+</span>}\n <Kbd>{key}</Kbd>\n </React.Fragment>\n ))}\n </span>\n </div>\n ))}\n </div>\n ))}\n </div>\n </ModalDialog>\n </ModalOverlay>\n );\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport {\n searchPluginKey,\n type SearchMatch,\n} from \"@matops/editor/extensions/plugins/searchPlugin\";\n\ninterface FindReplacePanelProps {\n open: boolean;\n onClose: () => void;\n}\n\n/**\n * FindReplacePanel\n *\n * UI for the find-and-replace feature. Works with SearchExtension\n * (extensions/plugins/searchPlugin.ts) which manages all ProseMirror\n * decoration state.\n *\n * Optimisation notes vs original:\n * - Search (query + caseSensitive) and navigation (currentIndex) are\n * dispatched separately so changing the active match doesn't re-run the\n * full text search.\n * - Plugin state is read immediately after each dispatch (synchronous in\n * ProseMirror) so results are always consistent.\n */\nexport function FindReplacePanel({ open, onClose }: FindReplacePanelProps) {\n const { editor } = useEditorContext();\n\n const [query, setQuery] = useState(\"\");\n const [replacement, setReplacement] = useState(\"\");\n const [caseSensitive, setCaseSensitive] = useState(false);\n const [currentIndex, setCurrentIndex] = useState(0);\n const [results, setResults] = useState<SearchMatch[]>([]);\n const [showReplace, setShowReplace] = useState(false);\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n // ── Dispatch helpers ──────────────────────────────────────────────────────\n\n /** Run a new search and update the results list. */\n const dispatchNewSearch = useCallback(\n (q: string, idx: number, cs: boolean) => {\n if (!editor) return;\n editor.view.dispatch(\n editor.state.tr.setMeta(searchPluginKey, {\n query: q,\n currentIndex: idx,\n caseSensitive: cs,\n }),\n );\n const pluginState = searchPluginKey.getState(editor.view.state);\n setResults(pluginState?.results ?? []);\n },\n [editor],\n );\n\n /** Only update the highlighted match index — no text re-scan needed. */\n const dispatchIndexOnly = useCallback(\n (idx: number) => {\n if (!editor) return;\n editor.view.dispatch(\n editor.state.tr.setMeta(searchPluginKey, { currentIndex: idx }),\n );\n },\n [editor],\n );\n\n // Re-run search when query or case sensitivity changes\n useEffect(() => {\n dispatchNewSearch(query, 0, caseSensitive);\n setCurrentIndex(0);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [query, caseSensitive]);\n\n // Update highlighted match decoration without re-scanning\n useEffect(() => {\n dispatchIndexOnly(currentIndex);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentIndex]);\n\n // ── Open / close lifecycle ─────────────────────────────────────────────────\n useEffect(() => {\n if (!open) {\n dispatchNewSearch(\"\", 0, false);\n setQuery(\"\");\n setReplacement(\"\");\n setCurrentIndex(0);\n setResults([]);\n } else {\n setTimeout(() => inputRef.current?.focus(), 50);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n // ── Navigation ─────────────────────────────────────────────────────────────\n const navigate = useCallback(\n (direction: \"next\" | \"prev\") => {\n if (!results.length || !editor) return;\n const next =\n direction === \"next\"\n ? (currentIndex + 1) % results.length\n : (currentIndex - 1 + results.length) % results.length;\n setCurrentIndex(next);\n editor.chain().focus().setTextSelection(results[next].from).run();\n },\n [results, currentIndex, editor],\n );\n\n // ── Replace ────────────────────────────────────────────────────────────────\n const replaceCurrent = useCallback(() => {\n if (!editor || !results.length) return;\n const { from, to } = results[currentIndex];\n editor\n .chain()\n .focus()\n .deleteRange({ from, to })\n .insertContentAt(from, replacement)\n .run();\n // Re-run search after the doc changed (plugin auto-re-scans on docChanged\n // but we need to sync the local results array too)\n dispatchNewSearch(\n query,\n Math.min(currentIndex, results.length - 2),\n caseSensitive,\n );\n }, [\n editor,\n results,\n currentIndex,\n replacement,\n query,\n caseSensitive,\n dispatchNewSearch,\n ]);\n\n const replaceAll = useCallback(() => {\n if (!editor || !results.length) return;\n // Process in reverse order so earlier positions stay valid\n const reversed = [...results].reverse();\n let tr = editor.state.tr;\n reversed.forEach(({ from, to }) => {\n tr = tr.replaceWith(from, to, editor.schema.text(replacement));\n });\n editor.view.dispatch(tr);\n setQuery(\"\");\n }, [editor, results, replacement]);\n\n // ── Escape to close ────────────────────────────────────────────────────────\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [open, onClose]);\n\n if (!open) return null;\n\n const hasResults = results.length > 0;\n const countLabel = !query\n ? \"\"\n : hasResults\n ? `${currentIndex + 1} / ${results.length}`\n : \"No results\";\n\n return (\n <div className=\"mat-find-panel\" role=\"search\" aria-label=\"Find and replace\">\n {/* Header */}\n <div className=\"mat-find-header\">\n <span className=\"mat-find-title\">\n {showReplace ? \"Find & Replace\" : \"Find\"}\n </span>\n <div className=\"mat-find-header-actions\">\n <button\n type=\"button\"\n className=\"mat-find-toggle\"\n onClick={() => setShowReplace((v) => !v)}\n title={showReplace ? \"Hide replace\" : \"Show replace\"}\n >\n {showReplace ? \"↑ Hide\" : \"↓ Replace\"}\n </button>\n <button\n type=\"button\"\n className=\"mat-find-close\"\n onClick={onClose}\n aria-label=\"Close find panel\"\n >\n ✕\n </button>\n </div>\n </div>\n\n {/* Find row */}\n <div className=\"mat-find-row\">\n <div className=\"mat-find-input-wrap\">\n <input\n ref={inputRef}\n className=\"mat-find-input\"\n placeholder=\"Find…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") navigate(e.shiftKey ? \"prev\" : \"next\");\n }}\n spellCheck={false}\n aria-label=\"Search query\"\n />\n {query && (\n <span className=\"mat-find-count\" aria-live=\"polite\">\n {countLabel}\n </span>\n )}\n </div>\n <button\n type=\"button\"\n className={`mat-find-btn-icon ${caseSensitive ? \"active\" : \"\"}`}\n onClick={() => setCaseSensitive((v) => !v)}\n title=\"Case sensitive\"\n aria-pressed={caseSensitive}\n >\n Aa\n </button>\n <button\n type=\"button\"\n className=\"mat-find-btn-icon\"\n onClick={() => navigate(\"prev\")}\n title=\"Previous match (Shift+Enter)\"\n disabled={!hasResults}\n aria-label=\"Previous match\"\n >\n ↑\n </button>\n <button\n type=\"button\"\n className=\"mat-find-btn-icon\"\n onClick={() => navigate(\"next\")}\n title=\"Next match (Enter)\"\n disabled={!hasResults}\n aria-label=\"Next match\"\n >\n ↓\n </button>\n </div>\n\n {/* Replace row */}\n {showReplace && (\n <div className=\"mat-find-row\">\n <input\n className=\"mat-find-input\"\n placeholder=\"Replace with…\"\n value={replacement}\n onChange={(e) => setReplacement(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") replaceCurrent();\n }}\n spellCheck={false}\n aria-label=\"Replacement text\"\n />\n <button\n type=\"button\"\n className=\"mat-find-btn\"\n onClick={replaceCurrent}\n disabled={!hasResults}\n title=\"Replace this occurrence\"\n >\n Replace\n </button>\n <button\n type=\"button\"\n className=\"mat-find-btn\"\n onClick={replaceAll}\n disabled={!hasResults}\n title=\"Replace all occurrences\"\n >\n All\n </button>\n </div>\n )}\n </div>\n );\n}\n","/**\n * viewerExtensions.ts\n *\n * Tiptap extensions used by MatopsViewer to generate static HTML from\n * JSONContent via generateHTML(). This is intentionally separate from the\n * editor's live extension set — the viewer is read-only and does not need\n * ProseMirror plugins, commands, or collaborative features.\n */\nimport Document from \"@tiptap/extension-document\";\nimport Paragraph from \"@tiptap/extension-paragraph\";\nimport Text from \"@tiptap/extension-text\";\nimport Bold from \"@tiptap/extension-bold\";\nimport Italic from \"@tiptap/extension-italic\";\nimport Underline from \"@tiptap/extension-underline\";\nimport Strike from \"@tiptap/extension-strike\";\nimport Heading from \"@tiptap/extension-heading\";\nimport Blockquote from \"@tiptap/extension-blockquote\";\nimport Code from \"@tiptap/extension-code\";\nimport CodeBlockLowlight from \"@tiptap/extension-code-block-lowlight\";\nimport Image from \"@tiptap/extension-image\";\nimport Link from \"@tiptap/extension-link\";\nimport Highlight from \"@tiptap/extension-highlight\";\nimport HorizontalRule from \"@tiptap/extension-horizontal-rule\";\nimport HardBreak from \"@tiptap/extension-hard-break\";\nimport TextAlign from \"@tiptap/extension-text-align\";\nimport { ListKit } from \"@tiptap/extension-list\";\nimport { TableKit } from \"@tiptap/extension-table\";\nimport { TextStyleKit } from \"@tiptap/extension-text-style\";\nimport { common, createLowlight } from \"lowlight\";\n\nconst lowlight = createLowlight(common);\n\nexport const VIEWER_EXTENSIONS = [\n Document,\n Paragraph,\n Text,\n Bold,\n Italic,\n Underline,\n Strike,\n Heading.configure({ levels: [1, 2, 3, 4, 5, 6] }),\n Blockquote,\n ListKit,\n Code,\n CodeBlockLowlight.configure({ lowlight }),\n Image.configure({\n HTMLAttributes: {\n class: \"matops-editor__image\",\n loading: \"lazy\",\n },\n }),\n Link.configure({\n HTMLAttributes: {\n rel: \"noopener noreferrer\",\n target: \"_blank\",\n class: \"matops-editor__link\",\n },\n }),\n TableKit,\n TextStyleKit,\n TextAlign.configure({ types: [\"heading\", \"paragraph\"] }),\n Highlight.configure({ multicolor: true }),\n HorizontalRule,\n HardBreak,\n];\n\n/** Node types that belong to document structure, not body content. */\nexport const STRUCTURAL_NODE_TYPES = new Set([\n \"cover-image\",\n \"title\",\n \"separator-icon\",\n \"attachments\",\n]);\n","import type { JSONContent } from \"@tiptap/core\";\n\n// ─────────────────────────────────────────────\n// Inline serializer (marks)\n// ─────────────────────────────────────────────\n\nfunction inlineToMarkdown(node: JSONContent): string {\n if (!node) return \"\";\n\n let text = node.text ?? (node.content ?? []).map(inlineToMarkdown).join(\"\");\n if (!node.marks?.length) return text;\n\n for (const mark of node.marks) {\n switch (mark.type) {\n case \"bold\": text = `**${text}**`; break;\n case \"italic\": text = `_${text}_`; break;\n case \"code\": text = `\\`${text}\\``; break;\n case \"strike\": text = `~~${text}~~`; break;\n case \"underline\": text = `<u>${text}</u>`; break;\n case \"link\": {\n const href = (mark.attrs?.href as string) ?? \"\";\n text = `[${text}](${href})`;\n break;\n }\n }\n }\n return text;\n}\n\n// ─────────────────────────────────────────────\n// Block serializer (nodes)\n// ─────────────────────────────────────────────\n\n/**\n * Convert a Tiptap JSONContent node tree to Markdown.\n *\n * Supports all standard nodes plus the page-header nodes:\n * - `cover-image` → HTML img tag (no native Markdown equivalent)\n * - `title` → # heading (H1)\n *\n * @param node - The JSONContent node to serialize\n * @param depth - Indentation depth for nested lists (internal)\n */\nexport function toMarkdown(node: JSONContent, depth = 0): string {\n if (!node) return \"\";\n\n switch (node.type) {\n case \"doc\": {\n // New external format: structural sections live in doc.attrs.\n // Serialize them before the body content[].\n const parts: string[] = [];\n\n // Cover image from doc.attrs.coverImage\n const coverAttr = node.attrs?.coverImage as { src?: string | null; alt?: string } | null | undefined;\n if (coverAttr?.src) {\n const alt = coverAttr.alt || \"Cover image\";\n parts.push(``);\n }\n\n // Title from doc.attrs.title\n const titleAttr = node.attrs?.title as { text?: string } | null | undefined;\n if (titleAttr?.text) {\n parts.push(`# ${titleAttr.text}`);\n parts.push(\"---\"); // separator\n }\n\n // Body content[]\n const bodyParts = (node.content ?? [])\n .map((n) => toMarkdown(n))\n .filter(Boolean);\n parts.push(...bodyParts);\n\n // Attachments from doc.attrs.attachments\n const attachAttr = node.attrs?.attachments as { items?: string } | null | undefined;\n if (attachAttr?.items) {\n let items: Array<{ name: string; size: number; url: string }> = [];\n try { items = JSON.parse(attachAttr.items); } catch { items = []; }\n if (items.length > 0) {\n const formatSize = (bytes: number): string => {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const v = bytes / Math.pow(1024, i);\n return `${v % 1 === 0 ? v : v.toFixed(1)} ${units[i]}`;\n };\n parts.push(`## Attachments\\n\\n${items.map(item => `- [${item.name}](${item.url}) *(${formatSize(item.size)})*`).join(\"\\n\")}`);\n }\n }\n\n return parts.filter(Boolean).join(\"\\n\\n\").trim();\n }\n\n // ── Page-header nodes ──────────────────────────────────────────\n\n case \"cover-image\": {\n const src = node.attrs?.src as string | null;\n if (!src) return \"\";\n const alt = (node.attrs?.alt as string) || \"Cover image\";\n return ``;\n }\n\n case \"title\": {\n const text = (node.content ?? []).map(inlineToMarkdown).join(\"\");\n if (!text) return \"\";\n return `# ${text}`;\n }\n\n case \"separator-icon\":\n // Render as a thematic break — no Markdown equivalent for icon badges\n return \"---\";\n\n case \"attachments\": {\n const raw = node.attrs?.items as string | undefined;\n let items: Array<{ name: string; size: number; url: string }> = [];\n try { items = JSON.parse(raw ?? \"[]\"); } catch { items = []; }\n if (items.length === 0) return \"\";\n const formatSize = (bytes: number): string => {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const v = bytes / Math.pow(1024, i);\n return `${v % 1 === 0 ? v : v.toFixed(1)} ${units[i]}`;\n };\n const header = \"## Attachments\";\n const list = items.map((item) => `- [${item.name}](${item.url}) *(${formatSize(item.size)})*`).join(\"\\n\");\n return `${header}\\n\\n${list}`;\n }\n\n // ── Standard nodes ──────────────────────────────────────────────\n\n case \"paragraph\":\n if (!node.content?.length) return \"\";\n return (node.content ?? []).map(inlineToMarkdown).join(\"\");\n\n case \"heading\": {\n const level = (node.attrs?.level as number) ?? 1;\n const text = (node.content ?? []).map(inlineToMarkdown).join(\"\");\n return `${\"#\".repeat(level)} ${text}`;\n }\n\n case \"blockquote\":\n return (node.content ?? [])\n .map((n) => toMarkdown(n))\n .join(\"\\n\")\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n case \"bulletList\":\n return (node.content ?? [])\n .map((item) => {\n const text = (item.content ?? [])\n .map((n) => toMarkdown(n, depth + 1))\n .join(\"\\n\");\n return `${\" \".repeat(depth)}- ${text}`;\n })\n .join(\"\\n\");\n\n case \"orderedList\":\n return (node.content ?? [])\n .map((item, i) => {\n const text = (item.content ?? [])\n .map((n) => toMarkdown(n, depth + 1))\n .join(\"\\n\");\n return `${\" \".repeat(depth)}${i + 1}. ${text}`;\n })\n .join(\"\\n\");\n\n case \"taskList\":\n return (node.content ?? [])\n .map((item) => {\n const checked = item.attrs?.checked ? \"[x]\" : \"[ ]\";\n const text = (item.content ?? []).map((n) => toMarkdown(n)).join(\" \");\n return `- ${checked} ${text}`;\n })\n .join(\"\\n\");\n\n case \"codeBlock\": {\n const lang = (node.attrs?.language as string) ?? \"\";\n const code = (node.content ?? []).map((n) => n.text ?? \"\").join(\"\");\n return `\\`\\`\\`${lang}\\n${code}\\n\\`\\`\\``;\n }\n\n case \"horizontalRule\":\n return \"---\";\n\n case \"hardBreak\":\n return \" \\n\";\n\n default:\n return (node.content ?? []).map((n) => toMarkdown(n)).join(\"\");\n }\n}\n","/**\n * cropHelpers — Shared utilities for rendering image crops.\n */\n\nimport type { CropRect } from \"@matops/editor/core/types\";\n\nexport const DEFAULT_CROP: CropRect = { x: 0, y: 0, width: 100, height: 100 };\n\n// ───────────────────────────────────────────────────────────\n// Utilities\n// ───────────────────────────────────────────────────────────\n\nexport function isDefaultCrop(crop: CropRect): boolean {\n return (\n crop.x === DEFAULT_CROP.x &&\n crop.y === DEFAULT_CROP.y &&\n crop.width === DEFAULT_CROP.width &&\n crop.height === DEFAULT_CROP.height\n );\n}\n\nfunction computeValues(crop: CropRect) {\n const scaleX = 100 / crop.width;\n const scaleY = 100 / crop.height;\n\n return {\n width: scaleX * 100,\n height: scaleY * 100,\n left: -(crop.x / crop.width) * 100,\n top: -(crop.y / crop.height) * 100,\n };\n}\n\n// ───────────────────────────────────────────────────────────\n// React style\n// ───────────────────────────────────────────────────────────\n\nexport function computeCropStyle(\n crop: CropRect,\n objectPosition = \"center 40%\",\n): React.CSSProperties {\n if (isDefaultCrop(crop)) {\n return {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n objectPosition,\n display: \"block\",\n };\n }\n\n const v = computeValues(crop);\n\n return {\n position: \"absolute\",\n width: `${v.width}%`,\n height: `${v.height}%`,\n left: `${v.left}%`,\n top: `${v.top}%`,\n maxWidth: \"none\",\n objectFit: \"unset\",\n display: \"block\",\n };\n}\n\n// ───────────────────────────────────────────────────────────\n// String style (for renderHTML)\n// ───────────────────────────────────────────────────────────\n\nexport function computeCropStyleStr(\n crop: CropRect,\n objectPosition = \"center 40%\",\n): string {\n if (isDefaultCrop(crop)) {\n return `width:100%;height:100%;object-fit:cover;object-position:${objectPosition};display:block`;\n }\n\n const v = computeValues(crop);\n\n return [\n \"position:absolute\",\n `width:${v.width}%`,\n `height:${v.height}%`,\n `left:${v.left}%`,\n `top:${v.top}%`,\n \"max-width:none\",\n \"display:block\",\n ].join(\";\");\n}\n\n// ───────────────────────────────────────────────────────────\n// Attr helpers\n// ───────────────────────────────────────────────────────────\n\nexport function readCropFromAttrs(attrs: unknown): CropRect {\n const a = attrs as Record<string, unknown> | null;\n\n return {\n x: typeof a?.cropX === \"number\" ? a.cropX : DEFAULT_CROP.x,\n y: typeof a?.cropY === \"number\" ? a.cropY : DEFAULT_CROP.y,\n width: typeof a?.cropWidth === \"number\" ? a.cropWidth : DEFAULT_CROP.width,\n height:\n typeof a?.cropHeight === \"number\" ? a.cropHeight : DEFAULT_CROP.height,\n };\n}\n\nexport function cropToAttrs(crop: CropRect) {\n return {\n cropX: crop.x,\n cropY: crop.y,\n cropWidth: crop.width,\n cropHeight: crop.height,\n };\n}\n","/**\n * TitleSeparator — decorative divider between the page title and body content.\n *\n * Renders: ────── ❋ ──────\n *\n * The centre badge shows either:\n * - A custom `icon` ReactNode passed by the consumer (via `separatorIcon` prop\n * on <Editor> or <EditorViewer>), OR\n * - The default quill-stroke SVG when no icon is provided.\n *\n * Used in two contexts:\n * - TitleView.tsx (edit mode — ReactNodeView component)\n * - EditorViewer.tsx (read mode — rendered directly alongside generateHTML output)\n */\n\nimport { type ReactNode } from \"react\";\nimport { DefaultSeparatorIcon } from \"@matops/editor/ui/icons/index\";\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\ninterface TitleSeparatorProps {\n /** Custom icon to render in the centre badge. Defaults to the quill SVG. */\n icon?: ReactNode;\n /**\n * Set to true when the icon is an uploaded image that may use position:absolute\n * crop styles. Adds `overflow:hidden` + `position:relative` to the badge span\n * so the cropped image is clipped correctly.\n */\n hasImageIcon?: boolean;\n}\n\nexport function TitleSeparator({ icon, hasImageIcon }: TitleSeparatorProps) {\n return (\n <div className=\"mat-title-separator\" aria-hidden=\"true\">\n <span className=\"mat-title-separator__line\" />\n <span\n className={[\n \"mat-title-separator__icon\",\n hasImageIcon ? \"mat-title-separator__icon--img\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {icon ?? <DefaultSeparatorIcon />}\n </span>\n <span className=\"mat-title-separator__line\" />\n </div>\n );\n}\n","/**\n * fileUtils.tsx\n *\n * Shared file-handling utilities used by both AttachmentsSectionView (node-view)\n * and AttachmentsPanel (panel-based approach).\n *\n * Extracted to eliminate ~150 lines of verbatim duplication across those two files.\n */\n// ── Id generator ──────────────────────────────────────────────────────────────\n\nexport function genId(): string {\n return Math.random().toString(36).slice(2, 10);\n}\n\n// ── MIME-type → display category ──────────────────────────────────────────────\n\nexport function getMimeCategory(mimeType: string): string {\n if (mimeType.startsWith(\"image/\")) return \"image\";\n if (mimeType.startsWith(\"video/\")) return \"video\";\n if (mimeType.startsWith(\"audio/\")) return \"audio\";\n if (mimeType === \"application/pdf\") return \"pdf\";\n if (\n mimeType.includes(\"spreadsheet\") ||\n mimeType.includes(\"excel\") ||\n mimeType === \"text/csv\"\n )\n return \"spreadsheet\";\n if (\n mimeType.includes(\"word\") ||\n mimeType.includes(\"document\") ||\n mimeType === \"text/plain\"\n )\n return \"document\";\n if (\n mimeType.includes(\"zip\") ||\n mimeType.includes(\"archive\") ||\n mimeType.includes(\"compressed\")\n )\n return \"archive\";\n if (\n mimeType.includes(\"javascript\") ||\n mimeType.includes(\"json\") ||\n mimeType.includes(\"html\") ||\n mimeType.includes(\"css\") ||\n mimeType === \"text/x-python\" ||\n mimeType === \"text/x-java\" ||\n mimeType.startsWith(\"text/\")\n )\n return \"code\";\n return \"generic\";\n}\n\n// ── File type icon ────────────────────────────────────────────────────────────\n\nconst SVG_PROPS = {\n width: 16,\n height: 16,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n};\n\nexport function FileIcon({ category }: { category: string }) {\n switch (category) {\n case \"image\":\n return (\n <svg {...SVG_PROPS}>\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n );\n case \"video\":\n return (\n <svg {...SVG_PROPS}>\n <polygon points=\"23 7 16 12 23 17 23 7\" />\n <rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\" />\n </svg>\n );\n case \"audio\":\n return (\n <svg {...SVG_PROPS}>\n <path d=\"M9 18V5l12-2v13\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\n </svg>\n );\n case \"pdf\":\n return (\n <svg {...SVG_PROPS}>\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"9\" y1=\"13\" x2=\"15\" y2=\"13\" />\n <line x1=\"9\" y1=\"17\" x2=\"15\" y2=\"17\" />\n </svg>\n );\n case \"spreadsheet\":\n return (\n <svg {...SVG_PROPS}>\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" />\n <line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" />\n <line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" />\n <line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n );\n case \"document\":\n return (\n <svg {...SVG_PROPS}>\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"9\" y1=\"13\" x2=\"15\" y2=\"13\" />\n <line x1=\"9\" y1=\"17\" x2=\"12\" y2=\"17\" />\n </svg>\n );\n case \"archive\":\n return (\n <svg {...SVG_PROPS}>\n <polyline points=\"21 8 21 21 3 21 3 8\" />\n <rect x=\"1\" y=\"3\" width=\"22\" height=\"5\" />\n <line x1=\"10\" y1=\"12\" x2=\"14\" y2=\"12\" />\n </svg>\n );\n case \"code\":\n return (\n <svg {...SVG_PROPS}>\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </svg>\n );\n default:\n return (\n <svg {...SVG_PROPS}>\n <path d=\"M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z\" />\n <polyline points=\"13 2 13 9 20 9\" />\n </svg>\n );\n }\n}\n","/**\n * AttachmentsSectionView — React NodeView for the `attachments` Tiptap node.\n *\n * Structure:\n * ────── [separator-icon mirror] ────── ← static, mirrors page-header separator\n * 📎 Attachments [+ Add attachment]\n * [ file list ]\n *\n * Key design decisions:\n * - The separator at the top is a READ-ONLY mirror of the page-header\n * `separator-icon` node. It reads the same src/crop/alt attrs reactively\n * via `useLiveSeparatorAttrs()` but exposes ZERO edit controls.\n * - All drag events call e.stopPropagation() so files dropped here don't\n * also get picked up by the editor's useImageUpload handler.\n * - All upload logic delegates to onFileUploaded; no backend code here.\n */\n\nimport React, { useRef, useState, useCallback, useEffect } from \"react\";\nimport { NodeViewWrapper } from \"@tiptap/react\";\nimport type { NodeViewProps } from \"@tiptap/react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures } from \"@matops/editor/core/context/editorHooks\";\nimport type { AttachmentItem, CropRect } from \"@matops/editor/core/types\";\nimport {\n parseAttachments,\n serializeAttachments,\n} from \"@matops/editor/utils/helpers/docHelpers\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n DEFAULT_CROP,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\nimport { TitleSeparator } from \"@matops/editor/ui/primitives/TitleSeparator\";\nimport { formatFileSize } from \"@matops/editor/extensions/nodes/attachmentsNode\";\nimport { genId, getMimeCategory, FileIcon } from \"@matops/editor/ui/primitives/fileUtils\";\n\n// ── Hook: live separator-icon attrs ──────────────────────────────────────────\n// Reactively reads `separator-icon` node attrs from the editor doc on every\n// update. The bottom separator mirrors the page-header separator-icon exactly\n// — same src, same crop — but with zero edit controls.\ninterface SepAttrs {\n src: string | null;\n crop: CropRect;\n alt: string;\n}\n\nconst EMPTY_SEP: SepAttrs = {\n src: null,\n crop: DEFAULT_CROP,\n alt: \"Section separator\",\n};\n\nfunction useLiveSeparatorAttrs(\n editor: import(\"@tiptap/core\").Editor | null,\n): SepAttrs {\n const read = useCallback((): SepAttrs => {\n if (!editor) return EMPTY_SEP;\n let found: SepAttrs = EMPTY_SEP;\n editor.state.doc.forEach((node) => {\n if (node.type.name === \"separator-icon\") {\n found = {\n src: (node.attrs.src as string | null) ?? null,\n crop: readCropFromAttrs(node.attrs),\n alt: (node.attrs.alt as string) || \"Section separator\",\n };\n }\n });\n return found;\n }, [editor]);\n\n const [attrs, setAttrs] = useState<SepAttrs>(read);\n\n useEffect(() => {\n if (!editor) return;\n const update = () => setAttrs(read());\n editor.on(\"transaction\", update);\n return () => {\n editor.off(\"transaction\", update);\n };\n }, [editor, read]);\n\n return attrs;\n}\n\n// ── Static bottom separator ───────────────────────────────────────────────────\n// Renders the same ────[icon]──── as the page-header separator-icon,\n// but purely for display. No upload / crop / change / remove controls.\nfunction BottomSeparator({\n editor,\n}: {\n editor: import(\"@tiptap/core\").Editor | null;\n}) {\n const { separatorIcon } = useEditorContext();\n const sepAttrs = useLiveSeparatorAttrs(editor);\n\n // Build badge content — same priority chain as SeparatorIconView, no editing\n const badge = sepAttrs.src ? (\n <span\n style={{\n position: \"absolute\",\n inset: 0,\n overflow: \"hidden\",\n borderRadius: \"50%\",\n }}\n >\n <img\n src={sepAttrs.src}\n alt={sepAttrs.alt}\n style={computeCropStyle(sepAttrs.crop)}\n />\n </span>\n ) : (\n (separatorIcon ?? undefined)\n ); // undefined → TitleSeparator uses its default quill icon\n\n return <TitleSeparator icon={badge} hasImageIcon={!!sepAttrs.src} />;\n}\n\n// ── Main component ────────────────────────────────────────────────────────────\nexport function AttachmentsSectionView({\n node,\n updateAttributes,\n}: NodeViewProps) {\n const { editable, onFileUploaded, editor } = useEditorContext();\n const { hasAttachments } = useFeatures();\n\n // Upload / remove controls only when both editable AND attachments feature is on.\n const canEdit = editable && hasAttachments;\n const items = parseAttachments(node.attrs.items as string);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [uploading, setUploading] = useState<string[]>([]);\n\n // ── Upload ────────────────────────────────────────────────────────────────\n const uploadFiles = useCallback(\n async (files: FileList | File[]) => {\n const fileArr = Array.from(files);\n if (!fileArr.length) return;\n\n setUploading((p) => [...p, ...fileArr.map((f) => f.name)]);\n\n const newItems: AttachmentItem[] = [];\n for (const file of fileArr) {\n try {\n const url = onFileUploaded\n ? await onFileUploaded(file)\n : URL.createObjectURL(file);\n newItems.push({\n id: genId(),\n name: file.name,\n size: file.size,\n mimeType: file.type || \"application/octet-stream\",\n url,\n });\n } catch (err) {\n console.error(\n \"[AttachmentsSectionView] Upload failed:\",\n file.name,\n err,\n );\n }\n }\n\n setUploading((p) => p.filter((n) => !fileArr.some((f) => f.name === n)));\n if (newItems.length)\n updateAttributes({\n items: serializeAttachments([...items, ...newItems]),\n });\n },\n [items, onFileUploaded, updateAttributes],\n );\n\n const handleFileInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (e.target.files) uploadFiles(e.target.files);\n e.target.value = \"\";\n },\n [uploadFiles],\n );\n\n // stopPropagation on ALL drag events so they never bubble up to the editor's\n // useImageUpload handler — without this, dropped files get inserted into\n // the editor content AND added to the attachment list simultaneously.\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.stopPropagation();\n setIsDragging(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n if (e.dataTransfer.files) uploadFiles(e.dataTransfer.files);\n },\n [uploadFiles],\n );\n\n const handleRemove = useCallback(\n (id: string) => {\n updateAttributes({\n items: serializeAttachments(items.filter((i) => i.id !== id)),\n });\n },\n [items, updateAttributes],\n );\n\n // ── File list shared between read and edit ────────────────────────────────\n const fileList = (\n <ul className=\"mat-attachments__list\">\n {uploading.map((name) => (\n <li\n key={`uploading-${name}`}\n className=\"mat-attachment-item mat-attachment-item--uploading\"\n >\n <span className=\"mat-attachment-item__icon\" aria-hidden=\"true\">\n <span className=\"mat-attachments__spinner mat-attachments__spinner--sm\" />\n </span>\n <span className=\"mat-attachment-item__name\">{name}</span>\n <span className=\"mat-attachment-item__meta\">Uploading…</span>\n </li>\n ))}\n {items.map((item) => (\n <li key={item.id} className=\"mat-attachment-item\">\n <span className=\"mat-attachment-item__icon\" aria-hidden=\"true\">\n <FileIcon category={getMimeCategory(item.mimeType)} />\n </span>\n <a\n href={item.url}\n className=\"mat-attachment-item__name mat-attachment-item__name--link\"\n download={item.name}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title={`Download ${item.name}`}\n >\n {item.name}\n </a>\n <span className=\"mat-attachment-item__meta\">\n {formatFileSize(item.size)}\n </span>\n {editable && (\n <button\n type=\"button\"\n className=\"mat-attachment-item__remove\"\n onClick={() => handleRemove(item.id)}\n title={`Remove ${item.name}`}\n aria-label={`Remove ${item.name}`}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )}\n </li>\n ))}\n </ul>\n );\n\n // ── Read-only view ────────────────────────────────────────────────────────\n if (!canEdit) {\n if (items.length === 0) return null;\n return (\n <NodeViewWrapper\n as=\"section\"\n className=\"mat-attachments\"\n contentEditable={false}\n aria-label=\"Attachments\"\n >\n <BottomSeparator editor={editor} />\n <div className=\"mat-attachments__header\">\n <div className=\"mat-attachments__heading-row\">\n <svg\n className=\"mat-attachments__heading-icon\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n <h3 className=\"mat-attachments__heading\">Attachments</h3>\n </div>\n </div>\n {fileList}\n </NodeViewWrapper>\n );\n }\n\n // ── Edit view ─────────────────────────────────────────────────────────────\n return (\n <NodeViewWrapper\n as=\"section\"\n className={`mat-attachments mat-attachments--editable${isDragging ? \" mat-attachments--dragging\" : \"\"}`}\n contentEditable={false}\n aria-label=\"Attachments\"\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {/* Static separator — mirrors page-header separator-icon, no edit controls */}\n <BottomSeparator editor={editor} />\n\n {/* Header */}\n <div className=\"mat-attachments__header\">\n <div className=\"mat-attachments__heading-row\">\n <svg\n className=\"mat-attachments__heading-icon\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n <h3 className=\"mat-attachments__heading\">Attachments</h3>\n {items.length > 0 && (\n <span className=\"mat-attachments__count\">{items.length}</span>\n )}\n </div>\n <button\n type=\"button\"\n className=\"mat-attachments__add-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading.length > 0}\n >\n {uploading.length > 0 ? (\n <span className=\"mat-attachments__spinner\" aria-hidden=\"true\" />\n ) : (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n )}\n Add attachment\n </button>\n </div>\n\n {/* File list or empty state */}\n {items.length === 0 && uploading.length === 0 ? (\n <div className=\"mat-attachments__empty\">\n <svg\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"mat-attachments__empty-icon\"\n aria-hidden=\"true\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n <p className=\"mat-attachments__empty-text\">\n {isDragging\n ? \"Drop files to attach\"\n : 'No attachments yet — drag & drop or click \"Add attachment\"'}\n </p>\n </div>\n ) : (\n fileList\n )}\n\n {/* Drop overlay */}\n {isDragging && (\n <div className=\"mat-attachments__drop-overlay\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n Drop files to attach\n </div>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </NodeViewWrapper>\n );\n}\n","/**\n * AttachmentsNode — first-class Tiptap block node for document attachments.\n *\n * Always the LAST node in the document.\n * The AttachmentsGuard plugin (attachmentsGuardPlugin.ts) enforces this\n * structurally via filterTransaction + appendTransaction.\n *\n * These keyboard shortcuts are a secondary ergonomic layer:\n * - Enter at the last body paragraph → swallowed (prevents creating para after)\n * - Delete at end of last body paragraph → swallowed (prevents forward-delete into node)\n * - Backspace at start of first body paragraph → already guarded by separatorIconNode\n */\n\nimport { Node, mergeAttributes } from \"@tiptap/core\";\nimport { ReactNodeViewRenderer } from \"@tiptap/react\";\nimport { AttachmentsSectionView } from \"@matops/editor/ui/node-views/AttachmentsSectionView\";\n\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const val = bytes / Math.pow(1024, i);\n return `${val % 1 === 0 ? val : val.toFixed(1)} ${units[i]}`;\n}\n\nexport const AttachmentsNode = Node.create({\n name: \"attachments\",\n group: \"block\",\n atom: true,\n selectable: false,\n draggable: false,\n isolating: true,\n\n addAttributes() {\n return {\n items: {\n default: \"[]\",\n parseHTML: (el) => el.getAttribute(\"data-items\") ?? \"[]\",\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'section[data-type=\"attachments\"]' }];\n },\n\n renderHTML({ node }) {\n const rawItems = (node.attrs.items as string) ?? \"[]\";\n let items: Array<{ id: string; name: string; size: number; mimeType: string; url: string }> = [];\n try { items = JSON.parse(rawItems); } catch { items = []; }\n\n if (items.length === 0) {\n return [\"section\", mergeAttributes({ \"data-type\": \"attachments\", \"data-items\": \"[]\", class: \"mat-attachments mat-attachments--empty\", \"aria-label\": \"Attachments\" })];\n }\n\n const listChildren = items.map((item) => {\n const sizeStr = formatFileSize(item.size);\n return [\"li\", { class: \"mat-attachment-item\", \"data-id\": item.id },\n [\"a\", { href: item.url, class: \"mat-attachment-item__link\", download: item.name, target: \"_blank\", rel: \"noopener noreferrer\" },\n [\"span\", { class: \"mat-attachment-item__icon\", \"aria-hidden\": \"true\" }],\n [\"span\", { class: \"mat-attachment-item__name\" }, item.name],\n [\"span\", { class: \"mat-attachment-item__meta\" }, sizeStr],\n ],\n ];\n });\n\n return [\"section\", mergeAttributes({ \"data-type\": \"attachments\", \"data-items\": rawItems, class: \"mat-attachments\", \"aria-label\": \"Attachments\" }),\n [\"h3\", { class: \"mat-attachments__heading\" }, \"Attachments\"],\n [\"ul\", { class: \"mat-attachments__list\" }, ...listChildren],\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(AttachmentsSectionView);\n },\n\n // ── Keyboard guards ──────────────────────────────────────────────────────\n // Ergonomic secondary layer — the plugin handles structural enforcement.\n addKeyboardShortcuts() {\n return {\n // When the cursor is at the end of the last body paragraph and the next\n // sibling is `attachments`, insert a new paragraph BEFORE the attachments\n // node rather than blocking Enter entirely. This keeps the writing area\n // navigable regardless of how many body paragraphs exist.\n //\n // The attachments guard plugin allows this because attachments remains\n // the last child after the insertion — its positional invariant is met.\n Enter: ({ editor }) => {\n const { $from } = editor.state.selection;\n // Only intercept when cursor is at the very end of its block\n if ($from.parentOffset !== $from.parent.content.size) return false;\n // Determine what comes immediately after this block at the top level\n const afterPos = $from.after($from.depth);\n const afterNode = editor.state.doc.resolve(afterPos).nodeAfter;\n if (afterNode?.type.name !== \"attachments\") return false;\n\n // Insert an empty paragraph right before the attachments node, then\n // place the cursor inside it so the user can continue typing.\n return editor\n .chain()\n .insertContentAt(afterPos, { type: \"paragraph\" })\n .setTextSelection(afterPos + 1)\n .run();\n },\n\n // Block Delete when it would merge forward into the attachments node\n Delete: ({ editor }) => {\n const { $from, empty } = editor.state.selection;\n if (!empty || $from.parentOffset !== $from.parent.content.size) return false;\n const afterPos = $from.after($from.depth);\n const resolved = editor.state.doc.resolve(afterPos);\n if (resolved.nodeAfter?.type.name === \"attachments\") return true;\n return false;\n },\n };\n },\n});\n","import { useState, useCallback } from \"react\";\nimport { generateHTML } from \"@tiptap/core\";\nimport type { JSONContent } from \"@tiptap/core\";\n\nimport { VIEWER_EXTENSIONS } from \"@matops/editor/viewer/viewerExtensions\";\n\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport {\n ModalOverlay,\n ModalDialog,\n ModalHeader,\n} from \"@matops/editor/ui/primitives/ModalPrimitives\";\nimport { toMarkdown } from \"@matops/editor/utils/markdown\";\nimport {\n parseAttachments,\n toExternalFormat,\n} from \"@matops/editor/utils/helpers/docHelpers\";\nimport { formatFileSize } from \"@matops/editor/extensions/nodes/attachmentsNode\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype ExportFormat = \"json\" | \"html\" | \"markdown\" | \"text\";\n\nconst FORMATS: { id: ExportFormat; label: string; desc: string }[] = [\n { id: \"json\", label: \"JSON\", desc: \"Tiptap JSONContent\" },\n { id: \"html\", label: \"HTML\", desc: \"Rendered HTML markup\" },\n { id: \"markdown\", label: \"Markdown\", desc: \"Standard .md format\" },\n { id: \"text\", label: \"Plain\", desc: \"Stripped plain text\" },\n];\n\nconst FILE_EXTENSION: Record<ExportFormat, string> = {\n json: \"json\",\n html: \"html\",\n markdown: \"md\",\n text: \"txt\",\n};\n\nconst MIME_TYPE: Record<ExportFormat, string> = {\n json: \"application/json\",\n html: \"text/html\",\n markdown: \"text/markdown\",\n text: \"text/plain\",\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Extract plain text from the full document JSON.\n *\n * editor.getText() only extracts text from text nodes — it skips attachment\n * filenames since those are stored in attrs, not text content. This helper\n * walks the JSON manually to include attachment file info at the end.\n */\nfunction toPlainText(json: JSONContent): string {\n const lines: string[] = [];\n\n // Handle doc.attrs structural sections (new external format)\n const titleAttr = json.attrs?.title as { text?: string } | null | undefined;\n if (titleAttr?.text) lines.push(titleAttr.text);\n\n // function walk(node: JSONContent) {\n // switch (node.type) {\n // // Legacy structural node cases (kept for backward compat with old docs)\n // case \"cover-image\":\n // case \"separator-icon\":\n // break;\n\n // case \"attachments\": {\n // const items = parseAttachments(node.attrs?.items as string | undefined);\n // if (items.length > 0) {\n // lines.push(\"--- Attachments ---\");\n // items.forEach((item) => {\n // lines.push(`• ${item.name} (${formatFileSize(item.size)})`);\n // });\n // }\n // break;\n // }\n\n // case \"hardBreak\":\n // lines.push(\"\");\n // break;\n\n // case \"horizontalRule\":\n // lines.push(\"---\");\n // break;\n\n // default:\n // // For nodes with text content (title, paragraph, heading, etc.)\n // if (node.text) {\n // // Inline text node — accumulated by parent\n // return;\n // }\n // if (node.content?.length) {\n // // Collect inline text from this block\n // const blockText = node.content\n // .map((n) => extractInlineText(n))\n // .join(\"\");\n // if (blockText.trim()) lines.push(blockText);\n // return;\n // }\n // }\n // }\n\n function extractInlineText(node: JSONContent): string {\n if (node.text) return node.text;\n return (node.content ?? []).map(extractInlineText).join(\"\");\n }\n\n // Walk top-level nodes, recurse into containers (blockquote, lists, etc.)\n function walkDeep(node: JSONContent) {\n if (!node) return;\n\n switch (node.type) {\n case \"doc\":\n // Walk only body content[] (structural sections handled via doc.attrs above)\n (node.content ?? []).forEach(walkDeep);\n // Attachments from doc.attrs (new format)\n {\n const attachAttr = node.attrs?.attachments as\n | { items?: string }\n | null\n | undefined;\n if (attachAttr?.items) {\n const items = parseAttachments(attachAttr.items);\n if (items.length > 0) {\n lines.push(\"\");\n lines.push(\"--- Attachments ---\");\n items.forEach((item) => {\n lines.push(`• ${item.name} (${formatFileSize(item.size)})`);\n });\n }\n }\n }\n break;\n\n // Legacy structural node cases (kept for backward compat)\n case \"cover-image\":\n case \"separator-icon\":\n break; // skip\n\n case \"attachments\": {\n const items = parseAttachments(node.attrs?.items as string | undefined);\n if (items.length > 0) {\n lines.push(\"\");\n lines.push(\"--- Attachments ---\");\n items.forEach((item) => {\n lines.push(`• ${item.name} (${formatFileSize(item.size)})`);\n });\n }\n break;\n }\n\n case \"horizontalRule\":\n lines.push(\"---\");\n break;\n\n case \"hardBreak\":\n break;\n\n case \"blockquote\":\n case \"bulletList\":\n case \"orderedList\":\n case \"taskList\":\n case \"listItem\":\n case \"taskItem\":\n (node.content ?? []).forEach(walkDeep);\n break;\n\n default: {\n const text = extractInlineText(node);\n if (text.trim()) lines.push(text);\n break;\n }\n }\n }\n\n walkDeep(json);\n return lines.join(\"\\n\").trim();\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface ExportPanelProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ExportPanel({ open, onClose }: ExportPanelProps) {\n const { editor } = useEditorContext();\n const [format, setFormat] = useState<ExportFormat>(\"json\");\n const [copied, setCopied] = useState(false);\n\n const getContent = useCallback((): string => {\n if (!editor) return \"\";\n // getJSON() returns the body-only internal doc.\n // toExternalFormat ensures doc.attrs are correctly emitted in external format.\n const internalJson = editor.getJSON() as JSONContent;\n const json = toExternalFormat(internalJson);\n\n switch (format) {\n case \"json\":\n return JSON.stringify(json, null, 2);\n\n case \"html\": {\n // For HTML export, generate body HTML from the body-only content[].\n // The structural sections (cover, title, separator, attachments) are\n // read from doc.attrs and rendered as HTML strings below.\n const bodyDoc: JSONContent = {\n type: \"doc\",\n content: json.content?.length\n ? json.content\n : [{ type: \"paragraph\" }],\n };\n const bodyHtml = generateHTML(bodyDoc, VIEWER_EXTENSIONS);\n\n // Build structural HTML from doc.attrs\n const coverAttr = json.attrs?.coverImage as\n | import(\"../../core/types\").CoverImageDocAttr\n | null\n | undefined;\n const titleAttr = json.attrs?.title as\n | import(\"../../core/types\").TitleDocAttr\n | null\n | undefined;\n const attachAttr = json.attrs?.attachments as\n | import(\"../../core/types\").AttachmentsDocAttr\n | null\n | undefined;\n\n let html = \"\";\n if (coverAttr?.src) {\n html += `<div class=\"mat-cover mat-cover--has-image\"><img src=\"${coverAttr.src}\" alt=\"${coverAttr.alt || \"Cover image\"}\" class=\"mat-cover__img\" /></div>\\n`;\n }\n if (titleAttr?.text) {\n html += `<div class=\"mat-page-title-wrap\"><h1 class=\"mat-page-title\">${titleAttr.text}</h1></div>\\n`;\n html += `<div class=\"mat-title-separator\" aria-hidden=\"true\"><span class=\"mat-title-separator__line\"></span><span class=\"mat-title-separator__icon\"></span><span class=\"mat-title-separator__line\"></span></div>\\n`;\n }\n html += bodyHtml;\n if (attachAttr) {\n const items = parseAttachments(attachAttr.items);\n if (items.length > 0) {\n const listItems = items\n .map(\n (item) =>\n `<li class=\"mat-attachment-item\"><a href=\"${item.url}\" download=\"${item.name}\" target=\"_blank\" rel=\"noopener noreferrer\">${item.name}</a> <span class=\"mat-attachment-item__meta\">${formatFileSize(item.size)}</span></li>`,\n )\n .join(\"\\n\");\n html += `\\n<section class=\"mat-attachments\" aria-label=\"Attachments\"><h3 class=\"mat-attachments__heading\">Attachments</h3><ul class=\"mat-attachments__list\">\\n${listItems}\\n</ul></section>`;\n }\n }\n return html;\n }\n\n case \"markdown\":\n return toMarkdown(json);\n\n case \"text\":\n return toPlainText(json);\n }\n }, [editor, format]);\n\n const handleCopy = useCallback(async () => {\n await navigator.clipboard.writeText(getContent());\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [getContent]);\n\n const handleDownload = useCallback(() => {\n const content = getContent();\n const blob = new Blob([content], { type: MIME_TYPE[format] });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `document.${FILE_EXTENSION[format]}`;\n a.click();\n URL.revokeObjectURL(url);\n }, [getContent, format]);\n\n if (!open) return null;\n\n return (\n <ModalOverlay onClose={onClose}>\n <ModalDialog className=\"mat-export-modal\" label=\"Export document\">\n <ModalHeader title=\"Export Document\" onClose={onClose} />\n\n {/* Format tabs */}\n <div className=\"mat-export-tabs\" role=\"tablist\">\n {FORMATS.map((f) => (\n <button\n key={f.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={format === f.id}\n className={`mat-export-tab ${format === f.id ? \"active\" : \"\"}`}\n onClick={() => setFormat(f.id)}\n >\n <span className=\"mat-export-tab__label\">{f.label}</span>\n <span className=\"mat-export-tab__desc\">{f.desc}</span>\n </button>\n ))}\n </div>\n\n {/* Preview */}\n <div className=\"mat-export-preview\">\n <pre className=\"mat-export-code\">{getContent()}</pre>\n </div>\n\n {/* Actions */}\n <div className=\"mat-export-actions\">\n <button\n type=\"button\"\n className=\"mat-export-btn primary\"\n onClick={handleCopy}\n >\n {copied ? \"✓ Copied!\" : \"Copy to clipboard\"}\n </button>\n <button\n type=\"button\"\n className=\"mat-export-btn\"\n onClick={handleDownload}\n >\n Download file\n </button>\n </div>\n </ModalDialog>\n </ModalOverlay>\n );\n}\n","/**\n * ViewerStatBar.tsx\n *\n * Read-only document statistics bar rendered below MatopsViewer when\n * `showStats={true}`. Computes word count, character count, paragraph\n * count, and estimated reading time from the raw JSONContent tree.\n */\nimport { useMemo } from \"react\";\nimport type { JSONContent } from \"@tiptap/core\";\nimport { STRUCTURAL_NODE_TYPES } from \"./viewerExtensions\";\n\ninterface ViewerStatBarProps {\n content: JSONContent;\n}\n\nexport function ViewerStatBar({ content }: ViewerStatBarProps) {\n const stats = useMemo(() => {\n let text = \"\";\n let paragraphs = 0;\n\n function walk(node: JSONContent) {\n if (STRUCTURAL_NODE_TYPES.has(node.type ?? \"\")) return;\n if (node.text) text += node.text;\n if (node.type === \"paragraph\" && (node.content?.length ?? 0) > 0) {\n paragraphs++;\n }\n node.content?.forEach(walk);\n }\n\n content.content?.forEach(walk);\n\n const words = text.trim() ? text.trim().split(/\\s+/).length : 0;\n const chars = text.length;\n const minutes = words / 200;\n const readingTime =\n minutes < 1 ? \"< 1 min read\" : `${Math.ceil(minutes)} min read`;\n\n return { words, chars, paragraphs, readingTime };\n }, [content]);\n\n return (\n <div className=\"mat-count-bar\" aria-label=\"Document statistics\">\n <div className=\"mat-count-stats\">\n <div className=\"mat-count-stat\">\n <span className=\"mat-count-value\">{stats.words.toLocaleString()}</span>\n <span className=\"mat-count-label\">words</span>\n </div>\n\n <div className=\"mat-count-sep\" />\n\n <div className=\"mat-count-stat\">\n <span className=\"mat-count-value\">{stats.chars.toLocaleString()}</span>\n <span className=\"mat-count-label\">chars</span>\n </div>\n\n <div className=\"mat-count-sep\" />\n\n <div className=\"mat-count-stat\">\n <span className=\"mat-count-value\">{stats.paragraphs}</span>\n <span className=\"mat-count-label\">paragraphs</span>\n </div>\n\n <div className=\"mat-count-sep\" />\n\n <div className=\"mat-count-stat\">\n <span className=\"mat-count-value\">{stats.readingTime}</span>\n </div>\n </div>\n </div>\n );\n}\n","import { useMemo, type ReactNode } from \"react\";\nimport { generateHTML } from \"@tiptap/core\";\nimport type { JSONContent } from \"@tiptap/core\";\n\nimport { DefaultSeparatorIcon } from \"@matops/editor/ui/icons\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\nimport {\n extractCoverImageAttr,\n extractTitleAttr,\n extractSeparatorIconSrc,\n extractAttachments,\n extractContentWidth,\n} from \"@matops/editor/utils/helpers/docHelpers\";\nimport type { EditorViewerProps } from \"@matops/editor/core/types\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport {\n EDITOR_DATA_ATTR,\n THEME_DARK_CLASS,\n THEME_LIGHT_CLASS,\n} from \"@matops/editor/utils/constants\";\n\nimport { VIEWER_EXTENSIONS, STRUCTURAL_NODE_TYPES } from \"./viewerExtensions\";\nimport { ViewerStatBar } from \"./ViewerStatBar\";\n\nimport \"@matops/editor/ui/styles/editor.css\";\n\n/* -------------------------------------------------------------------------- */\n/* MatopsViewer */\n/* -------------------------------------------------------------------------- */\n\nexport function MatopsViewer({\n content,\n theme = \"light\",\n className,\n separatorIcon,\n showStats = false,\n}: EditorViewerProps) {\n /* ── Structural data ─────────────────────────────────────────────── */\n\n const {\n coverAttr,\n titleAttr,\n sepIconSrc,\n attachItems,\n contentWidth,\n sepIconCrop,\n sepIconAlt,\n } = useMemo(() => {\n const nodes = content.content ?? [];\n\n const coverAttr = extractCoverImageAttr(content);\n const titleAttr = extractTitleAttr(content);\n const sepIconSrc = extractSeparatorIconSrc(content);\n const attachItems = extractAttachments(content);\n const contentWidth = extractContentWidth(content);\n\n const sepIconNode = nodes.find((n) => n.type === \"separator-icon\");\n\n let sepIconCrop = { x: 0, y: 0, width: 100, height: 100 };\n let sepIconAlt = \"Section separator\";\n\n if (content.attrs?.separatorIcon) {\n const attr = content.attrs.separatorIcon;\n sepIconCrop = readCropFromAttrs(attr);\n sepIconAlt = attr.alt ?? sepIconAlt;\n } else if (sepIconNode?.attrs) {\n sepIconCrop = readCropFromAttrs(sepIconNode.attrs);\n sepIconAlt = sepIconNode.attrs.alt ?? sepIconAlt;\n }\n\n return {\n coverAttr,\n titleAttr,\n sepIconSrc,\n attachItems,\n contentWidth,\n sepIconCrop,\n sepIconAlt,\n };\n }, [content]);\n\n /* ── Body HTML ───────────────────────────────────────────────────── */\n\n const bodyHtml = useMemo(() => {\n const bodyNodes = (content.content ?? []).filter(\n (node) => !STRUCTURAL_NODE_TYPES.has(node.type ?? \"\"),\n );\n const bodyDoc: JSONContent = {\n type: \"doc\",\n content: bodyNodes.length ? bodyNodes : [{ type: \"paragraph\" }],\n };\n return generateHTML(bodyDoc, VIEWER_EXTENSIONS);\n }, [content]);\n\n /* ── Separator badge ─────────────────────────────────────────────── */\n\n const sepBadge = useMemo<ReactNode>(() => {\n if (sepIconSrc) {\n return (\n <span style={{ overflow: \"hidden\", borderRadius: \"50%\" }}>\n <img\n src={sepIconSrc}\n alt={sepIconAlt}\n style={computeCropStyle(sepIconCrop)}\n />\n </span>\n );\n }\n return separatorIcon ?? <DefaultSeparatorIcon />;\n }, [sepIconSrc, sepIconAlt, sepIconCrop, separatorIcon]);\n\n /* ── Render ──────────────────────────────────────────────────────── */\n\n const hasCover = !!coverAttr?.src;\n const hasTitle = !!titleAttr;\n const hasAttachments = attachItems.length > 0;\n const themeClass = theme === \"dark\" ? THEME_DARK_CLASS : THEME_LIGHT_CLASS;\n\n return (\n <div\n className=\"matops-editor__viewer-wrap\"\n data-content-width={contentWidth}\n >\n <div\n {...{ [EDITOR_DATA_ATTR]: true }}\n className={cn(themeClass, \"matops-editor__viewer\", className)}\n data-theme={theme}\n data-readonly=\"true\"\n >\n <div className=\"matops-editor__scroll-inner\">\n {/* Page Header */}\n <div className=\"matops-editor__page-header\">\n {hasCover && coverAttr && (\n <div className=\"mat-cover mat-cover--has-image\">\n <img\n src={coverAttr.src!}\n alt={coverAttr.alt || \"Cover image\"}\n className=\"mat-cover__img\"\n style={computeCropStyle(\n readCropFromAttrs(coverAttr),\n coverAttr.objectPosition || \"center 40%\",\n )}\n loading=\"lazy\"\n />\n </div>\n )}\n\n {hasTitle && titleAttr && (\n <div className=\"mat-page-title-wrap\">\n <h1 className=\"mat-page-title mat-page-title--readonly\">\n {titleAttr.text}\n </h1>\n </div>\n )}\n\n {hasTitle && (\n <div className=\"mat-title-separator\" aria-hidden=\"true\">\n <span className=\"mat-title-separator__line\" />\n <span className=\"mat-title-separator__icon\">{sepBadge}</span>\n <span className=\"mat-title-separator__line\" />\n </div>\n )}\n </div>\n\n {/* Body */}\n <div className=\"matops-editor__body-panel\">\n <div className=\"matops-editor__content\">\n <div\n {...{ [EDITOR_DATA_ATTR]: true }}\n className={cn(themeClass, \"ProseMirror\")}\n data-theme={theme}\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n </div>\n </div>\n\n {/* Attachments */}\n {hasAttachments && (\n <div className=\"matops-editor__attachments-panel\">\n <div className=\"mat-title-separator\" aria-hidden=\"true\">\n <span className=\"mat-title-separator__line\" />\n <span className=\"mat-title-separator__icon\">{sepBadge}</span>\n <span className=\"mat-title-separator__line\" />\n </div>\n </div>\n )}\n </div>\n </div>\n\n {showStats && (\n <div\n className={cn(themeClass, \"matops-editor__viewer-footer\")}\n data-theme={theme}\n >\n <ViewerStatBar content={content} />\n </div>\n )}\n </div>\n );\n}\n\nexport default MatopsViewer;\n","/**\n * CropModal — responsive image cropping overlay.\n *\n * Canvas dimensions are computed dynamically from the viewport so the modal\n * works on every screen size (desktop, tablet, mobile).\n *\n * Touch events are fully supported so mobile users can drag handles and\n * reposition the crop rect with a finger.\n */\n\nimport React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n type MouseEvent as RMouseEvent,\n type TouchEvent as RTouchEvent,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { CropRect } from \"@matops/editor/core/types\";\nimport { DEFAULT_CROP } from \"@matops/editor/utils/helpers/cropHelpers\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\ntype Handle = \"nw\" | \"n\" | \"ne\" | \"w\" | \"e\" | \"sw\" | \"s\" | \"se\" | \"body\";\n\ninterface DragState {\n handle: Handle;\n startMouseX: number;\n startMouseY: number;\n startPx: Px;\n}\n\ninterface Px {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface CropModalProps {\n src: string;\n initialCrop?: CropRect;\n aspectRatio?: number;\n onConfirm: (crop: CropRect) => void;\n onCancel: () => void;\n}\n\n// ── Constants ─────────────────────────────────────────────────────────────────\n\nconst MAX_CANVAS_W = 620;\nconst MAX_CANVAS_H = 420;\nconst CANVAS_RATIO = MAX_CANVAS_H / MAX_CANVAS_W;\nconst MIN_PX = 20;\nconst H_SIZE = 10;\n\n// ── Dynamic canvas size ───────────────────────────────────────────────────────\n\nfunction computeCanvasSize(): { cw: number; ch: number } {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const maxW = Math.min(\n MAX_CANVAS_W,\n Math.max(260, Math.floor(vw * 0.95 - 40)),\n );\n const fromW = Math.round(maxW * CANVAS_RATIO);\n const maxH = Math.min(MAX_CANVAS_H, Math.max(180, Math.floor(vh - 180)));\n const ch = Math.min(fromW, maxH);\n const cw = ch < fromW ? Math.round(ch / CANVAS_RATIO) : maxW;\n return { cw, ch };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction clamp(v: number, lo: number, hi: number) {\n return Math.max(lo, Math.min(hi, v));\n}\n\nfunction fitImage(natW: number, natH: number, cw: number, ch: number) {\n const scale = Math.min(cw / natW, ch / natH);\n const imgW = Math.round(natW * scale);\n const imgH = Math.round(natH * scale);\n const imgOX = Math.round((cw - imgW) / 2);\n const imgOY = Math.round((ch - imgH) / 2);\n return { imgW, imgH, imgOX, imgOY };\n}\n\nfunction pctToImgPx(pct: CropRect, imgW: number, imgH: number): Px {\n return {\n x: (pct.x / 100) * imgW,\n y: (pct.y / 100) * imgH,\n w: (pct.width / 100) * imgW,\n h: (pct.height / 100) * imgH,\n };\n}\n\nfunction imgPxToPct(px: Px, imgW: number, imgH: number): CropRect {\n return {\n x: clamp((px.x / imgW) * 100, 0, 100),\n y: clamp((px.y / imgH) * 100, 0, 100),\n width: clamp((px.w / imgW) * 100, 0, 100),\n height: clamp((px.h / imgH) * 100, 0, 100),\n };\n}\n\nfunction initialCropForRatio(\n aspectRatio: number,\n imgW: number,\n imgH: number,\n): CropRect {\n const R = aspectRatio;\n const CAP = 0.65;\n let w = imgW * CAP;\n let h = w / R;\n if (h > imgH * CAP) {\n h = imgH * CAP;\n w = h * R;\n }\n w = clamp(w, MIN_PX, imgW);\n h = clamp(h, MIN_PX, imgH);\n return imgPxToPct({ x: (imgW - w) / 2, y: (imgH - h) / 2, w, h }, imgW, imgH);\n}\n\nfunction applyDelta(\n handle: Handle,\n start: Px,\n dx: number,\n dy: number,\n imgW: number,\n imgH: number,\n R: number | undefined,\n): Px {\n if (handle === \"body\") {\n return {\n x: clamp(start.x + dx, 0, imgW - start.w),\n y: clamp(start.y + dy, 0, imgH - start.h),\n w: start.w,\n h: start.h,\n };\n }\n\n const right = start.x + start.w;\n const bottom = start.y + start.h;\n const cx0 = start.x + start.w / 2;\n const cy0 = start.y + start.h / 2;\n\n if (!R) {\n let { x, y, w, h } = start;\n switch (handle) {\n case \"nw\": {\n const nx = clamp(x + dx, 0, right - MIN_PX),\n ny = clamp(y + dy, 0, bottom - MIN_PX);\n w = right - nx;\n h = bottom - ny;\n x = nx;\n y = ny;\n break;\n }\n case \"n\": {\n const ny = clamp(y + dy, 0, bottom - MIN_PX);\n h = bottom - ny;\n y = ny;\n break;\n }\n case \"ne\": {\n w = clamp(w + dx, MIN_PX, imgW - x);\n const ny = clamp(y + dy, 0, bottom - MIN_PX);\n h = bottom - ny;\n y = ny;\n break;\n }\n case \"e\": {\n w = clamp(w + dx, MIN_PX, imgW - x);\n break;\n }\n case \"se\": {\n w = clamp(w + dx, MIN_PX, imgW - x);\n h = clamp(h + dy, MIN_PX, imgH - y);\n break;\n }\n case \"s\": {\n h = clamp(h + dy, MIN_PX, imgH - y);\n break;\n }\n case \"sw\": {\n const nx = clamp(x + dx, 0, right - MIN_PX);\n w = right - nx;\n x = nx;\n h = clamp(h + dy, MIN_PX, imgH - y);\n break;\n }\n case \"w\": {\n const nx = clamp(x + dx, 0, right - MIN_PX);\n w = right - nx;\n x = nx;\n break;\n }\n }\n return { x, y, w, h };\n }\n\n const solveWH = (\n desiredW: number,\n maxH: number,\n ): { w: number; h: number } => {\n let w = clamp(desiredW, MIN_PX, imgW);\n let h = w / R;\n if (h > maxH) {\n h = maxH;\n w = h * R;\n }\n if (h < MIN_PX) {\n h = MIN_PX;\n w = h * R;\n }\n w = clamp(w, MIN_PX, imgW);\n return { w, h };\n };\n\n const solveHW = (\n desiredH: number,\n maxW: number,\n ): { w: number; h: number } => {\n let h = clamp(desiredH, MIN_PX, imgH);\n let w = h * R;\n if (w > maxW) {\n w = maxW;\n h = w / R;\n }\n if (w < MIN_PX) {\n w = MIN_PX;\n h = w / R;\n }\n h = clamp(h, MIN_PX, imgH);\n return { w, h };\n };\n\n switch (handle) {\n case \"nw\": {\n const desiredW = clamp(right - (start.x + dx), MIN_PX, right);\n const { w, h } = solveWH(desiredW, bottom);\n return { x: right - w, y: bottom - h, w, h };\n }\n case \"ne\": {\n const desiredW = clamp(start.w + dx, MIN_PX, imgW - start.x);\n const { w, h } = solveWH(desiredW, bottom);\n return { x: start.x, y: bottom - h, w, h };\n }\n case \"sw\": {\n const desiredW = clamp(right - (start.x + dx), MIN_PX, right);\n const { w, h } = solveWH(desiredW, imgH - start.y);\n return { x: right - w, y: start.y, w, h };\n }\n case \"se\": {\n const desiredW = clamp(start.w + dx, MIN_PX, imgW - start.x);\n const { w, h } = solveWH(desiredW, imgH - start.y);\n return { x: start.x, y: start.y, w, h };\n }\n case \"n\": {\n const desiredH = clamp(bottom - (start.y + dy), MIN_PX, bottom);\n const { w, h } = solveHW(desiredH, imgW);\n const x = clamp(cx0 - w / 2, 0, imgW - w);\n return { x, y: bottom - h, w, h };\n }\n case \"s\": {\n const desiredH = clamp(start.h + dy, MIN_PX, imgH - start.y);\n const { w, h } = solveHW(desiredH, imgW);\n const x = clamp(cx0 - w / 2, 0, imgW - w);\n return { x, y: start.y, w, h };\n }\n case \"w\": {\n const desiredW = clamp(right - (start.x + dx), MIN_PX, right);\n const { w, h } = solveWH(desiredW, imgH);\n const y = clamp(cy0 - h / 2, 0, imgH - h);\n return { x: right - w, y, w, h };\n }\n case \"e\": {\n const desiredW = clamp(start.w + dx, MIN_PX, imgW - start.x);\n const { w, h } = solveWH(desiredW, imgH);\n const y = clamp(cy0 - h / 2, 0, imgH - h);\n return { x: start.x, y, w, h };\n }\n }\n return start;\n}\n\nconst CURSORS: Record<Handle, string> = {\n nw: \"nwse-resize\",\n n: \"ns-resize\",\n ne: \"nesw-resize\",\n w: \"ew-resize\",\n e: \"ew-resize\",\n sw: \"nesw-resize\",\n s: \"ns-resize\",\n se: \"nwse-resize\",\n body: \"move\",\n};\n\n// ── HandleDot ─────────────────────────────────────────────────────────────────\n\nfunction HandleDot({\n handle,\n style,\n onMouseDown,\n onTouchStart,\n}: {\n handle: Handle;\n style: React.CSSProperties;\n onMouseDown: (e: RMouseEvent, h: Handle) => void;\n onTouchStart: (e: RTouchEvent, h: Handle) => void;\n}) {\n return (\n <div\n className=\"mat-crop__handle\"\n style={{ cursor: CURSORS[handle], ...style }}\n onMouseDown={(e) => {\n e.stopPropagation();\n onMouseDown(e, handle);\n }}\n onTouchStart={(e) => {\n e.stopPropagation();\n onTouchStart(e, handle);\n }}\n />\n );\n}\n\n// ── CropModal ─────────────────────────────────────────────────────────────────\n\nexport function CropModal({\n src,\n initialCrop,\n aspectRatio,\n onConfirm,\n onCancel,\n}: CropModalProps) {\n // ── Responsive canvas size ────────────────────────────────────────────────\n const [{ cw, ch }, setCanvasSize] = useState(() => computeCanvasSize());\n\n useEffect(() => {\n const onResize = () => setCanvasSize(computeCanvasSize());\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n // Fitted image geometry\n const [img, setImg] = useState({ imgW: 0, imgH: 0, imgOX: 0, imgOY: 0 });\n const [cropPct, setCropPct] = useState<CropRect>(initialCrop ?? DEFAULT_CROP);\n\n const dragRef = useRef<DragState | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const { imgW, imgH, imgOX, imgOY } = img;\n const R = aspectRatio && imgW > 0 ? aspectRatio : undefined;\n const px =\n imgW > 0 ? pctToImgPx(cropPct, imgW, imgH) : { x: 0, y: 0, w: 0, h: 0 };\n const cx = imgOX + px.x;\n const cy = imgOY + px.y;\n\n // ── Image load ───────────────────────────────────────────────────────────\n const handleImageLoad = useCallback(\n (e: React.SyntheticEvent<HTMLImageElement>) => {\n const el = e.currentTarget;\n const natW = el.naturalWidth || 1;\n const natH = el.naturalHeight || 1;\n const fitted = fitImage(natW, natH, cw, ch);\n setImg(fitted);\n if (aspectRatio) {\n setCropPct(initialCropForRatio(aspectRatio, fitted.imgW, fitted.imgH));\n } else {\n setCropPct(initialCrop ?? DEFAULT_CROP);\n }\n },\n [initialCrop, aspectRatio, cw, ch],\n );\n\n // Re-fit when canvas size changes (viewport resize)\n useEffect(() => {\n if (!imgW) return;\n const imgEl = containerRef.current?.querySelector(\"img\");\n if (!imgEl) return;\n const natW = imgEl.naturalWidth || 1;\n const natH = imgEl.naturalHeight || 1;\n const fitted = fitImage(natW, natH, cw, ch);\n setImg(fitted);\n if (aspectRatio) {\n setCropPct(initialCropForRatio(aspectRatio, fitted.imgW, fitted.imgH));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [cw, ch]);\n\n // ── Mouse drag ───────────────────────────────────────────────────────────\n const startDrag = useCallback(\n (e: RMouseEvent, handle: Handle) => {\n e.preventDefault();\n dragRef.current = {\n handle,\n startMouseX: e.clientX,\n startMouseY: e.clientY,\n startPx: px,\n };\n },\n [px],\n );\n\n // ── Touch drag ───────────────────────────────────────────────────────────\n const startTouchDrag = useCallback(\n (e: RTouchEvent, handle: Handle) => {\n e.preventDefault();\n const t = e.touches[0];\n dragRef.current = {\n handle,\n startMouseX: t.clientX,\n startMouseY: t.clientY,\n startPx: px,\n };\n },\n [px],\n );\n\n // Canvas click — snap crop centre\n const handleCanvasClick = useCallback(\n (e: RMouseEvent<HTMLDivElement>) => {\n if (!imgW) return;\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const mx = e.clientX - rect.left - imgOX;\n const my = e.clientY - rect.top - imgOY;\n if (mx < 0 || mx > imgW || my < 0 || my > imgH) return;\n if (mx >= px.x && mx <= px.x + px.w && my >= px.y && my <= px.y + px.h)\n return;\n const nx = clamp(mx - px.w / 2, 0, imgW - px.w);\n const ny = clamp(my - px.h / 2, 0, imgH - px.h);\n setCropPct(imgPxToPct({ ...px, x: nx, y: ny }, imgW, imgH));\n },\n [px, imgW, imgH, imgOX, imgOY],\n );\n\n // Canvas tap — snap crop centre on touch devices\n const handleCanvasTouchEnd = useCallback(\n (e: RTouchEvent<HTMLDivElement>) => {\n if (!imgW || dragRef.current) return;\n const t = e.changedTouches[0];\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const mx = t.clientX - rect.left - imgOX;\n const my = t.clientY - rect.top - imgOY;\n if (mx < 0 || mx > imgW || my < 0 || my > imgH) return;\n if (mx >= px.x && mx <= px.x + px.w && my >= px.y && my <= px.y + px.h)\n return;\n const nx = clamp(mx - px.w / 2, 0, imgW - px.w);\n const ny = clamp(my - px.h / 2, 0, imgH - px.h);\n setCropPct(imgPxToPct({ ...px, x: nx, y: ny }, imgW, imgH));\n },\n [px, imgW, imgH, imgOX, imgOY],\n );\n\n useEffect(() => {\n const onMove = (e: MouseEvent) => {\n const d = dragRef.current;\n if (!d || !imgW) return;\n const newPx = applyDelta(\n d.handle,\n d.startPx,\n e.clientX - d.startMouseX,\n e.clientY - d.startMouseY,\n imgW,\n imgH,\n R,\n );\n setCropPct(imgPxToPct(newPx, imgW, imgH));\n };\n const onUp = () => {\n dragRef.current = null;\n };\n\n const onTouchMove = (e: TouchEvent) => {\n const d = dragRef.current;\n if (!d || !imgW) return;\n e.preventDefault();\n const t = e.touches[0];\n const newPx = applyDelta(\n d.handle,\n d.startPx,\n t.clientX - d.startMouseX,\n t.clientY - d.startMouseY,\n imgW,\n imgH,\n R,\n );\n setCropPct(imgPxToPct(newPx, imgW, imgH));\n };\n const onTouchEnd = () => {\n dragRef.current = null;\n };\n\n window.addEventListener(\"mousemove\", onMove);\n window.addEventListener(\"mouseup\", onUp);\n window.addEventListener(\"touchmove\", onTouchMove, { passive: false });\n window.addEventListener(\"touchend\", onTouchEnd);\n return () => {\n window.removeEventListener(\"mousemove\", onMove);\n window.removeEventListener(\"mouseup\", onUp);\n window.removeEventListener(\"touchmove\", onTouchMove);\n window.removeEventListener(\"touchend\", onTouchEnd);\n };\n }, [imgW, imgH, R]);\n\n // ── Keyboard ─────────────────────────────────────────────────────────────\n const handleConfirm = useCallback(() => {\n if (imgW) onConfirm(cropPct);\n }, [imgW, cropPct, onConfirm]);\n\n // Keep latest handlers in a ref so the keydown listener is never stale\n const keyHandlersRef = useRef({ handleConfirm, onCancel });\n useEffect(() => {\n keyHandlersRef.current = { handleConfirm, onCancel };\n }, [handleConfirm, onCancel]);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") keyHandlersRef.current.onCancel();\n if (e.key === \"Enter\") keyHandlersRef.current.handleConfirm();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, []); // stable — always reads from keyHandlersRef\n\n // ── Ratio badge ───────────────────────────────────────────────────────────\n const ratioLabel =\n aspectRatio === undefined\n ? null\n : aspectRatio === 1\n ? \"1 : 1\"\n : aspectRatio >= 1\n ? `${aspectRatio.toFixed(1)} : 1`\n : `1 : ${(1 / aspectRatio).toFixed(1)}`;\n\n // ── Handle positions (canvas-space) ──────────────────────────────────────\n const ho = -(H_SIZE / 2);\n const handles: Array<{ handle: Handle; style: React.CSSProperties }> = [\n { handle: \"nw\", style: { top: cy + ho, left: cx + ho } },\n { handle: \"n\", style: { top: cy + ho, left: cx + px.w / 2 + ho } },\n { handle: \"ne\", style: { top: cy + ho, left: cx + px.w + ho } },\n { handle: \"w\", style: { top: cy + px.h / 2 + ho, left: cx + ho } },\n { handle: \"e\", style: { top: cy + px.h / 2 + ho, left: cx + px.w + ho } },\n { handle: \"sw\", style: { top: cy + px.h + ho, left: cx + ho } },\n { handle: \"s\", style: { top: cy + px.h + ho, left: cx + px.w / 2 + ho } },\n { handle: \"se\", style: { top: cy + px.h + ho, left: cx + px.w + ho } },\n ];\n\n // ── Render ────────────────────────────────────────────────────────────────\n return createPortal(\n <div\n className=\"mat-crop-backdrop\"\n onClick={(e) => {\n if (e.target === e.currentTarget) onCancel();\n }}\n >\n <div\n className=\"mat-crop-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Crop image\"\n >\n {/* Header */}\n <div className=\"mat-crop-modal__header\">\n <span className=\"mat-crop-modal__title\">\n Crop image\n {ratioLabel && (\n <span className=\"mat-crop-modal__aspect-badge\">{ratioLabel}</span>\n )}\n </span>\n <button\n className=\"mat-crop-modal__close\"\n onClick={onCancel}\n type=\"button\"\n aria-label=\"Cancel\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n {/* Responsive canvas — dimensions driven by JS state, not CSS px */}\n <div className=\"mat-crop-modal__body\">\n <div\n ref={containerRef}\n className=\"mat-crop-canvas\"\n style={{ width: cw, height: ch }}\n onMouseDown={handleCanvasClick}\n onTouchEnd={handleCanvasTouchEnd}\n >\n <img\n src={src}\n alt=\"Crop preview\"\n className=\"mat-crop-canvas__img\"\n style={\n imgW > 0\n ? {\n position: \"absolute\",\n left: imgOX,\n top: imgOY,\n width: imgW,\n height: imgH,\n }\n : { visibility: \"hidden\" }\n }\n onLoad={handleImageLoad}\n draggable={false}\n />\n\n {imgW > 0 && (\n <>\n <svg\n className=\"mat-crop-scrim\"\n width={cw}\n height={ch}\n viewBox={`0 0 ${cw} ${ch}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <mask id=\"mat-crop-mask\">\n <rect width={cw} height={ch} fill=\"white\" />\n <rect\n x={cx}\n y={cy}\n width={px.w}\n height={px.h}\n fill=\"black\"\n />\n </mask>\n </defs>\n <rect\n width={cw}\n height={ch}\n fill=\"rgba(0,0,0,0.6)\"\n mask=\"url(#mat-crop-mask)\"\n />\n </svg>\n\n <div\n className=\"mat-crop-rect\"\n style={{ left: cx, top: cy, width: px.w, height: px.h }}\n onMouseDown={(e) => {\n e.stopPropagation();\n startDrag(e, \"body\");\n }}\n onTouchStart={(e) => {\n e.stopPropagation();\n startTouchDrag(e, \"body\");\n }}\n >\n <div className=\"mat-crop-rect__grid\">\n <div\n className=\"mat-crop-rect__grid-v\"\n style={{ left: \"33.33%\" }}\n />\n <div\n className=\"mat-crop-rect__grid-v\"\n style={{ left: \"66.66%\" }}\n />\n <div\n className=\"mat-crop-rect__grid-h\"\n style={{ top: \"33.33%\" }}\n />\n <div\n className=\"mat-crop-rect__grid-h\"\n style={{ top: \"66.66%\" }}\n />\n </div>\n </div>\n\n {handles.map(({ handle, style }) => (\n <HandleDot\n key={handle}\n handle={handle}\n style={{ width: H_SIZE, height: H_SIZE, ...style }}\n onMouseDown={startDrag}\n onTouchStart={startTouchDrag}\n />\n ))}\n\n {/* Dims tooltip — clamped so it never escapes the canvas */}\n <div\n className=\"mat-crop-dims\"\n style={{ left: Math.min(cx + px.w + 6, cw - 56), top: cy }}\n >\n {Math.round(cropPct.width)} × {Math.round(cropPct.height)}%\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"mat-crop-modal__footer\">\n <button\n className=\"mat-crop-modal__btn mat-crop-modal__btn--ghost\"\n onClick={onCancel}\n type=\"button\"\n >\n Cancel\n </button>\n <button\n className=\"mat-crop-modal__btn mat-crop-modal__btn--primary\"\n onClick={handleConfirm}\n type=\"button\"\n disabled={!imgW}\n >\n <svg\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n Apply crop\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n","/**\n * CoverImagePanel — React panel (Panel 1) for the cover/banner image.\n *\n * Reads from `editor.state.doc.attrs.coverImage` (a CoverImageDocAttr or null).\n * Writes via `editor.commands.setCoverImageAttr(...)`.\n *\n * No ProseMirror NodeView — this is pure React rendered above <EditorContent>.\n *\n * Crop coordinates are percentages (0–100) stored in doc.attrs.coverImage.\n */\n\nimport React, { useRef, useState, useCallback } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures, useEditorState } from \"@matops/editor/core/context/editorHooks\";\nimport { CropModal } from \"@matops/editor/ui/modals/CropModal\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n cropToAttrs,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\nimport type { CropRect } from \"@matops/editor/core/types\";\nimport { getCoverImageAttr } from \"@matops/editor/extensions/nodes/documentNode\";\n\nexport function CoverImagePanel() {\n const { editable, onFileUploaded, editor } = useEditorContext();\n const { hasCoverImage } = useFeatures();\n\n // Read coverImage attr reactively from doc.attrs\n const coverAttr = useEditorState((ed) => getCoverImageAttr(ed));\n\n const canEdit = editable && hasCoverImage;\n const src = coverAttr?.src ?? null;\n const alt = coverAttr?.alt ?? \"Cover image\";\n const objectPosition = coverAttr?.objectPosition ?? \"center 40%\";\n const crop: CropRect = coverAttr\n ? readCropFromAttrs(coverAttr)\n : { x: 0, y: 0, width: 100, height: 100 };\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const coverWrapRef = useRef<HTMLDivElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [isUploading, setIsUploading] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [showCrop, setShowCrop] = useState(false);\n const [coverRatio, setCoverRatio] = useState<number | undefined>(undefined);\n\n // ── File handling ──────────────────────────────────────────────────────────\n const handleFile = useCallback(\n async (file: File) => {\n if (!file.type.startsWith(\"image/\") || !editor) return;\n setIsUploading(true);\n try {\n const url = onFileUploaded\n ? await onFileUploaded(file)\n : URL.createObjectURL(file);\n editor.commands.setCoverImageAttr({\n src: url,\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n });\n } catch (err) {\n console.error(\"[CoverImagePanel] Upload failed:\", err);\n } finally {\n setIsUploading(false);\n }\n },\n [onFileUploaded, editor],\n );\n\n const handleFileInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) handleFile(file);\n e.target.value = \"\";\n },\n [handleFile],\n );\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n const file = e.dataTransfer.files?.[0];\n if (file) handleFile(file);\n },\n [handleFile],\n );\n\n const handleRemove = useCallback(() => {\n editor?.commands.setCoverImageAttr(null);\n }, [editor]);\n\n const openCropModal = useCallback(() => {\n const el = coverWrapRef.current;\n if (el) {\n const { width, height } = el.getBoundingClientRect();\n setCoverRatio(height > 0 ? width / height : undefined);\n }\n setShowCrop(true);\n }, []);\n\n const handleCropConfirm = useCallback(\n (newCrop: CropRect) => {\n editor?.commands.setCoverImageAttr(cropToAttrs(newCrop));\n setShowCrop(false);\n },\n [editor],\n );\n\n const imgStyle = computeCropStyle(crop, objectPosition);\n\n // ── No-op when cover-image feature is off ─────────────────────────────────\n if (!hasCoverImage) return null;\n\n // ── Read mode — static image (or nothing) ─────────────────────────────────\n if (!canEdit) {\n if (!src) return null;\n return (\n <div className=\"mat-cover mat-cover--has-image\">\n <img src={src} alt={alt} className=\"mat-cover__img\" style={imgStyle} />\n </div>\n );\n }\n\n // ── Edit mode — with cover ─────────────────────────────────────────────────\n if (src) {\n return (\n <>\n <div\n ref={coverWrapRef}\n className={`mat-cover mat-cover--has-image${isHovered ? \" mat-cover--hovered\" : \"\"}`}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onDragOver={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }}\n onDragLeave={(e) => {\n e.stopPropagation();\n setIsDragging(false);\n }}\n onDrop={handleDrop}\n >\n <img\n src={src}\n alt={alt}\n className=\"mat-cover__img\"\n style={imgStyle}\n />\n\n <div\n className={`mat-cover__actions${isHovered ? \" mat-cover__actions--visible\" : \"\"}`}\n >\n <button\n type=\"button\"\n className=\"mat-cover__btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n >\n {isUploading ? (\n <span className=\"mat-cover__spinner\" />\n ) : (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n )}\n Change\n </button>\n\n <button\n type=\"button\"\n className=\"mat-cover__btn\"\n onClick={openCropModal}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n >\n <path d=\"M6 2v14a2 2 0 0 0 2 2h14\" />\n <path d=\"M18 22V8a2 2 0 0 0-2-2H2\" />\n </svg>\n Crop\n </button>\n\n <button\n type=\"button\"\n className=\"mat-cover__btn mat-cover__btn--danger\"\n onClick={handleRemove}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\" />\n </svg>\n Remove\n </button>\n </div>\n\n {isDragging && (\n <div className=\"mat-cover__drop-overlay\">Drop to replace cover</div>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </div>\n\n {showCrop && (\n <CropModal\n src={src}\n initialCrop={crop}\n aspectRatio={coverRatio}\n onConfirm={handleCropConfirm}\n onCancel={() => setShowCrop(false)}\n />\n )}\n </>\n );\n }\n\n // ── Edit mode — empty ──────────────────────────────────────────────────────\n return (\n <div\n className={`mat-cover mat-cover--empty${isDragging ? \" mat-cover--dragging\" : \"\"}`}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onDragOver={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }}\n onDragLeave={(e) => {\n e.stopPropagation();\n setIsDragging(false);\n }}\n onDrop={handleDrop}\n >\n <div\n className={`mat-cover__empty-inner${isHovered || isDragging ? \" mat-cover__empty-inner--visible\" : \"\"}`}\n >\n {isDragging ? (\n <div className=\"mat-cover__drop-hint\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n Drop image to set cover\n </div>\n ) : (\n <button\n type=\"button\"\n className=\"mat-cover__add-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n >\n {isUploading ? (\n <span className=\"mat-cover__spinner mat-cover__spinner--muted\" />\n ) : (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n )}\n Add cover image\n </button>\n )}\n </div>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </div>\n );\n}\n","/**\n * TitlePanel — React panel (Panel 1) for the document title.\n *\n * Reads from `editor.state.doc.attrs.title` (a TitleDocAttr or null).\n * Writes via `editor.commands.setTitleAttr({ text })`.\n *\n * Uses a contentEditable div so the user gets native text-editing behaviour\n * (cursor, selection, copy/paste). The doc.attrs.title.text is the source of\n * truth; the div is kept in sync via a ref and only triggers a command when\n * the user actually changes the text (avoids re-render loops).\n *\n * No ProseMirror NodeView — this is pure React rendered above <EditorContent>.\n */\n\nimport React, { useRef, useEffect, useCallback, useLayoutEffect } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures, useEditorState } from \"@matops/editor/core/context/editorHooks\";\nimport { getTitleAttr } from \"@matops/editor/extensions/nodes/documentNode\";\n\nexport function TitlePanel() {\n const { editable, editor } = useEditorContext();\n const { hasPageHeader } = useFeatures();\n\n // Read title attr reactively\n const titleAttr = useEditorState((ed) => getTitleAttr(ed));\n\n const canEdit = editable && hasPageHeader;\n const text = titleAttr?.text ?? \"\";\n const placeholder = titleAttr?.placeholder ?? \"Untitled\";\n\n // ── ContentEditable ref ────────────────────────────────────────────────────\n const divRef = useRef<HTMLDivElement>(null);\n // Track last text we set so we don't re-set when the update came from us\n const lastSentText = useRef(text);\n\n // Sync external text → DOM (only when it differs from what we last sent)\n useLayoutEffect(() => {\n const el = divRef.current;\n if (!el) return;\n // Only update DOM if external value changed due to something other than\n // our own input (e.g. undo, collaboration, feature toggle)\n if (el.textContent !== text && text !== lastSentText.current) {\n el.textContent = text;\n lastSentText.current = text;\n }\n }, [text]);\n\n // Initial population\n useEffect(() => {\n if (divRef.current && divRef.current.textContent !== text) {\n divRef.current.textContent = text;\n lastSentText.current = text;\n }\n // Only on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleInput = useCallback(() => {\n if (!editor) return;\n const newText = divRef.current?.textContent ?? \"\";\n lastSentText.current = newText;\n editor.commands.setTitleAttr({ text: newText });\n }, [editor]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n // Move focus into the ProseMirror body\n editor?.commands.focus(\"start\");\n }\n },\n [editor],\n );\n\n // Block drag events — title accepts text only, not images\n const blockDrag = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n if (!hasPageHeader) return null;\n\n // ── Read-only ──────────────────────────────────────────────────────────────\n if (!canEdit) {\n if (!text) return null;\n return (\n <div className=\"mat-page-title-wrap\">\n <h1 className=\"mat-page-title mat-page-title--readonly\">{text}</h1>\n </div>\n );\n }\n\n // ── Edit mode ──────────────────────────────────────────────────────────────\n return (\n <div\n className=\"mat-page-title-wrap\"\n onDragOver={blockDrag}\n onDragEnter={blockDrag}\n onDragLeave={blockDrag}\n onDrop={blockDrag}\n >\n <div className=\"mat-page-title-editable-wrap\">\n {!text && (\n <div className=\"mat-page-title__placeholder\" aria-hidden=\"true\">\n {placeholder}\n </div>\n )}\n <div\n ref={divRef}\n contentEditable\n suppressContentEditableWarning\n className=\"mat-page-title mat-page-title--editable\"\n onInput={handleInput}\n onKeyDown={handleKeyDown}\n aria-label=\"Document title\"\n aria-placeholder={placeholder}\n spellCheck\n />\n </div>\n </div>\n );\n}\n","/**\n * SeparatorIconPanel — React panel (Panel 1) for the title/body separator.\n *\n * Reads from `editor.state.doc.attrs.separatorIcon` (a SeparatorIconDocAttr or null).\n * Writes via `editor.commands.setSeparatorIconAttr(...)`.\n *\n * Renders: ────── [badge] ──────\n *\n * Icon resolution priority:\n * 1. doc.attrs.separatorIcon.src + crop → uploaded image, cropped\n * 2. separatorIcon prop (ReactNode from EditorProvider)\n * 3. Default quill SVG\n *\n * No ProseMirror NodeView — this is pure React rendered above <EditorContent>.\n */\n\nimport React, { useRef, useState, useCallback } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures, useEditorState } from \"@matops/editor/core/context/editorHooks\";\nimport { CropModal } from \"@matops/editor/ui/modals/CropModal\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n cropToAttrs,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\nimport type { CropRect } from \"@matops/editor/core/types\";\nimport { DefaultSeparatorIcon, UploadIcon } from \"@matops/editor/ui/icons/index\";\nimport { getSeparatorIconAttr } from \"@matops/editor/extensions/nodes/documentNode\";\n\nfunction Spinner() {\n return <span className=\"mat-cover__spinner mat-cover__spinner--muted\" />;\n}\n\nexport function SeparatorIconPanel() {\n const { editable, onFileUploaded, separatorIcon, editor } =\n useEditorContext();\n const { hasPageHeader } = useFeatures();\n\n // Read separatorIcon attr reactively\n const sepAttr = useEditorState((ed) => getSeparatorIconAttr(ed));\n\n const canEdit = editable && hasPageHeader;\n const src = sepAttr?.src ?? null;\n const alt = sepAttr?.alt ?? \"Section separator\";\n const crop: CropRect = sepAttr\n ? readCropFromAttrs(sepAttr)\n : { x: 0, y: 0, width: 100, height: 100 };\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [isUploading, setIsUploading] = useState(false);\n const [showCrop, setShowCrop] = useState(false);\n\n // ── File handling ──────────────────────────────────────────────────────────\n const handleFile = useCallback(\n async (file: File) => {\n if (!file.type.startsWith(\"image/\") || !editor) return;\n setIsUploading(true);\n try {\n const url = onFileUploaded\n ? await onFileUploaded(file)\n : URL.createObjectURL(file);\n editor.commands.setSeparatorIconAttr({\n src: url,\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n });\n } catch (err) {\n console.error(\"[SeparatorIconPanel] Upload failed:\", err);\n } finally {\n setIsUploading(false);\n }\n },\n [onFileUploaded, editor],\n );\n\n const handleFileInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) handleFile(file);\n e.target.value = \"\";\n },\n [handleFile],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.stopPropagation();\n if (!e.currentTarget.contains(e.relatedTarget as Node))\n setIsDragging(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n const file = e.dataTransfer.files?.[0];\n if (file) handleFile(file);\n },\n [handleFile],\n );\n\n const openFilePicker = useCallback(() => fileInputRef.current?.click(), []);\n\n const removeSrc = useCallback(() => {\n editor?.commands.setSeparatorIconAttr(null);\n }, [editor]);\n\n const handleCropConfirm = useCallback(\n (newCrop: CropRect) => {\n editor?.commands.setSeparatorIconAttr(cropToAttrs(newCrop));\n setShowCrop(false);\n },\n [editor],\n );\n\n if (!hasPageHeader) return null;\n\n // ── Badge content ──────────────────────────────────────────────────────────\n const badgeContent = isUploading ? (\n <Spinner />\n ) : src ? (\n <span\n style={{\n position: \"absolute\",\n inset: 0,\n overflow: \"hidden\",\n borderRadius: \"50%\",\n }}\n >\n <img src={src} alt={alt} style={computeCropStyle(crop)} />\n </span>\n ) : (\n (separatorIcon ?? <DefaultSeparatorIcon />)\n );\n\n // ── Read mode ──────────────────────────────────────────────────────────────\n if (!canEdit) {\n return (\n <div className=\"mat-title-separator\" aria-hidden=\"true\">\n <span className=\"mat-title-separator__line\" />\n <span\n className={`mat-title-separator__icon${src ? \" mat-title-separator__icon--img\" : \"\"}`}\n >\n {badgeContent}\n </span>\n <span className=\"mat-title-separator__line\" />\n </div>\n );\n }\n\n // ── Edit mode ──────────────────────────────────────────────────────────────\n return (\n <>\n <div\n className={[\n \"mat-title-separator\",\n \"mat-title-separator--editable\",\n isDragging ? \"mat-title-separator--dragging\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n aria-hidden=\"true\"\n >\n {/* Separator row */}\n <span className=\"mat-title-separator__line\" />\n <span\n className={`mat-title-separator__icon mat-title-separator__icon--editable${src ? \" mat-title-separator__icon--img\" : \"\"}`}\n >\n {badgeContent}\n </span>\n <span className=\"mat-title-separator__line\" />\n\n {/* Always-visible action bar */}\n <span className=\"mat-sep-action-bar\">\n {src ? (\n <>\n <span className=\"mat-sep-action-bar__label mat-sep-action-bar__label--set\">\n <img\n src={src}\n alt=\"\"\n className=\"mat-sep-action-bar__thumb\"\n aria-hidden=\"true\"\n />\n Custom icon\n </span>\n <button\n className=\"mat-sep-action-bar__btn\"\n onClick={() => setShowCrop(true)}\n type=\"button\"\n title=\"Crop icon image\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 2v14a2 2 0 0 0 2 2h14\" />\n <path d=\"M18 22V8a2 2 0 0 0-2-2H2\" />\n </svg>\n Crop\n </button>\n <button\n className=\"mat-sep-action-bar__btn\"\n onClick={openFilePicker}\n type=\"button\"\n title=\"Change icon image\"\n >\n Change\n </button>\n <button\n className=\"mat-sep-action-bar__btn mat-sep-action-bar__btn--danger\"\n onClick={removeSrc}\n type=\"button\"\n title=\"Remove icon image\"\n >\n Remove\n </button>\n </>\n ) : (\n <button\n className=\"mat-sep-action-bar__upload-pill\"\n onClick={openFilePicker}\n type=\"button\"\n title=\"Upload a custom icon for the separator\"\n >\n <UploadIcon />\n Upload icon\n </button>\n )}\n </span>\n\n {isDragging && (\n <span className=\"mat-sep-drop-overlay\">Drop image here</span>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </div>\n\n {showCrop && src && (\n <CropModal\n src={src}\n initialCrop={crop}\n aspectRatio={1} // always 1:1 for the circular badge\n onConfirm={handleCropConfirm}\n onCancel={() => setShowCrop(false)}\n />\n )}\n </>\n );\n}\n","/**\n * AttachmentsPanel — React panel (Panel 3) for document attachments.\n *\n * Reads from `editor.state.doc.attrs.attachments` (an AttachmentsDocAttr or null).\n * Writes via `editor.commands.setAttachmentsAttr(items)`.\n *\n * Structure (mirrors the old AttachmentsSectionView layout exactly):\n * ────── [separator-icon mirror] ────── ← static, reads from doc.attrs.separatorIcon\n * 📎 Attachments [+ Add attachment]\n * [ file list ]\n *\n * No ProseMirror NodeView — this is pure React rendered below <EditorContent>.\n *\n * All drag events call e.stopPropagation() so files dropped here don't also\n * get picked up by the editor's useImageUpload handler.\n */\n\nimport React, { useRef, useState, useCallback } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures, useEditorState } from \"@matops/editor/core/context/editorHooks\";\nimport type { AttachmentItem, CropRect } from \"@matops/editor/core/types\";\nimport { parseAttachments } from \"@matops/editor/utils/helpers/docHelpers\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\nimport { TitleSeparator } from \"@matops/editor/ui/primitives/TitleSeparator\";\nimport { formatFileSize } from \"@matops/editor/extensions/nodes/attachmentsNode\";\nimport { genId, getMimeCategory, FileIcon } from \"@matops/editor/ui/primitives/fileUtils\";\nimport {\n getAttachmentsAttr,\n getSeparatorIconAttr,\n} from \"@matops/editor/extensions/nodes/documentNode\";\n\n// ── Static bottom separator — mirrors page-header separator-icon ──────────────\nfunction BottomSeparator() {\n const { separatorIcon } = useEditorContext();\n const { hasPageHeader } = useFeatures();\n // Read separator-icon attrs reactively so it mirrors any changes\n const sepAttr = useEditorState((ed) => getSeparatorIconAttr(ed));\n\n const src = sepAttr?.src ?? null;\n const alt = sepAttr?.alt ?? \"Section separator\";\n const crop: CropRect = sepAttr\n ? readCropFromAttrs(sepAttr)\n : { x: 0, y: 0, width: 100, height: 100 };\n\n const badge = src ? (\n <span\n style={{\n position: \"absolute\",\n inset: 0,\n overflow: \"hidden\",\n borderRadius: \"50%\",\n }}\n >\n <img src={src} alt={alt} style={computeCropStyle(crop)} />\n </span>\n ) : (\n (separatorIcon ?? undefined)\n );\n\n // Only render when the page-header (title + separator) is active.\n // Without a matching top separator, a bottom separator would be orphaned.\n if (!hasPageHeader) return null;\n\n return <TitleSeparator icon={badge} hasImageIcon={!!src} />;\n}\n\n// ── Main component ────────────────────────────────────────────────────────────\nexport function AttachmentsPanel() {\n const { editable, onFileUploaded, editor } = useEditorContext();\n const { hasAttachments } = useFeatures();\n\n // Read attachments attr reactively from doc.attrs\n const attachAttr = useEditorState((ed) => getAttachmentsAttr(ed));\n const items = parseAttachments(attachAttr?.items ?? null);\n\n const canEdit = editable && hasAttachments;\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [uploading, setUploading] = useState<string[]>([]);\n\n // ── Upload ────────────────────────────────────────────────────────────────\n const uploadFiles = useCallback(\n async (files: FileList | File[]) => {\n if (!editor) return;\n const fileArr = Array.from(files);\n if (!fileArr.length) return;\n\n setUploading((p) => [...p, ...fileArr.map((f) => f.name)]);\n\n const newItems: AttachmentItem[] = [];\n for (const file of fileArr) {\n try {\n const url = onFileUploaded\n ? await onFileUploaded(file)\n : URL.createObjectURL(file);\n newItems.push({\n id: genId(),\n name: file.name,\n size: file.size,\n mimeType: file.type || \"application/octet-stream\",\n url,\n });\n } catch (err) {\n console.error(\"[AttachmentsPanel] Upload failed:\", file.name, err);\n }\n }\n\n setUploading((p) => p.filter((n) => !fileArr.some((f) => f.name === n)));\n if (newItems.length) {\n editor.commands.setAttachmentsAttr([...items, ...newItems]);\n }\n },\n [items, onFileUploaded, editor],\n );\n\n const handleFileInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (e.target.files) uploadFiles(e.target.files);\n e.target.value = \"\";\n },\n [uploadFiles],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.stopPropagation();\n setIsDragging(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n if (e.dataTransfer.files) uploadFiles(e.dataTransfer.files);\n },\n [uploadFiles],\n );\n\n const handleRemove = useCallback(\n (id: string) => {\n editor?.commands.setAttachmentsAttr(items.filter((i) => i.id !== id));\n },\n [items, editor],\n );\n\n // Feature off — render nothing\n if (!hasAttachments) return null;\n\n // ── File list shared between read and edit ────────────────────────────────\n const fileList = (\n <ul className=\"mat-attachments__list\">\n {uploading.map((name) => (\n <li\n key={`uploading-${name}`}\n className=\"mat-attachment-item mat-attachment-item--uploading\"\n >\n <span className=\"mat-attachment-item__icon\" aria-hidden=\"true\">\n <span className=\"mat-attachments__spinner mat-attachments__spinner--sm\" />\n </span>\n <span className=\"mat-attachment-item__name\">{name}</span>\n <span className=\"mat-attachment-item__meta\">Uploading…</span>\n </li>\n ))}\n {items.map((item) => (\n <li key={item.id} className=\"mat-attachment-item\">\n <span className=\"mat-attachment-item__icon\" aria-hidden=\"true\">\n <FileIcon category={getMimeCategory(item.mimeType)} />\n </span>\n <a\n href={item.url}\n className=\"mat-attachment-item__name mat-attachment-item__name--link\"\n download={item.name}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title={`Download ${item.name}`}\n >\n {item.name}\n </a>\n <span className=\"mat-attachment-item__meta\">\n {formatFileSize(item.size)}\n </span>\n {editable && (\n <button\n type=\"button\"\n className=\"mat-attachment-item__remove\"\n onClick={() => handleRemove(item.id)}\n title={`Remove ${item.name}`}\n aria-label={`Remove ${item.name}`}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )}\n </li>\n ))}\n </ul>\n );\n\n // ── Read-only view ────────────────────────────────────────────────────────\n if (!canEdit) {\n if (items.length === 0) return null;\n return (\n <section className=\"mat-attachments\" aria-label=\"Attachments\">\n <BottomSeparator />\n <div className=\"mat-attachments__header\">\n <div className=\"mat-attachments__heading-row\">\n <svg\n className=\"mat-attachments__heading-icon\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n <h3 className=\"mat-attachments__heading\">Attachments</h3>\n </div>\n </div>\n {fileList}\n </section>\n );\n }\n\n // ── Edit view ─────────────────────────────────────────────────────────────\n return (\n <section\n className={`mat-attachments mat-attachments--editable${isDragging ? \" mat-attachments--dragging\" : \"\"}`}\n aria-label=\"Attachments\"\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {/* Static separator — mirrors page-header separator-icon, no edit controls */}\n <BottomSeparator />\n\n {/* Header */}\n <div className=\"mat-attachments__header\">\n <div className=\"mat-attachments__heading-row\">\n <svg\n className=\"mat-attachments__heading-icon\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n <h3 className=\"mat-attachments__heading\">Attachments</h3>\n {items.length > 0 && (\n <span className=\"mat-attachments__count\">{items.length}</span>\n )}\n </div>\n <button\n type=\"button\"\n className=\"mat-attachments__add-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading.length > 0}\n >\n {uploading.length > 0 ? (\n <span className=\"mat-attachments__spinner\" aria-hidden=\"true\" />\n ) : (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n )}\n Add attachment\n </button>\n </div>\n\n {/* File list or empty state */}\n {items.length === 0 && uploading.length === 0 ? (\n <div className=\"mat-attachments__empty\">\n <svg\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"mat-attachments__empty-icon\"\n aria-hidden=\"true\"\n >\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n <p className=\"mat-attachments__empty-text\">\n {isDragging\n ? \"Drop files to attach\"\n : 'No attachments yet — drag & drop or click \"Add attachment\"'}\n </p>\n </div>\n ) : (\n fileList\n )}\n\n {/* Drop overlay */}\n {isDragging && (\n <div className=\"mat-attachments__drop-overlay\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n Drop files to attach\n </div>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </section>\n );\n}\n","import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { BubbleMenu } from \"@tiptap/react/menus\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useEditorUpdate } from \"@matops/editor/core/context/editorHooks\";\nimport { textStyleCommands } from \"@matops/editor/ui/commands/commandRegistry\";\nimport {\n BoldIcon, ItalicIcon, UnderlineIcon, StrikeIcon, HighlightIcon,\n CodeIcon, LinkIcon, UnlinkIcon,\n} from \"@matops/editor/ui/icons/index\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport { useDropdown } from \"@matops/editor/utils/hooks/useDropdown\";\n\n// ─────────────────────────────────────────────\n// Text Style Mini-Picker (inside bubble menu)\n// ─────────────────────────────────────────────\n\nfunction BubbleTextStyle() {\n const { editor, features, theme } = useEditorContext();\n useEditorUpdate();\n\n // Offset 6px for bubble menu (slightly more than toolbar's 4px)\n const { open, visible, dropPos, triggerRef, menuRef, toggle, close } = useDropdown({ offset: 6 });\n\n const cmds = textStyleCommands(features);\n const active = cmds.find(c => c.isActive?.(editor!)) ?? cmds[0];\n\n if (!editor || cmds.length === 0) return null;\n\n const dropdown = open\n ? createPortal(\n <div\n ref={menuRef}\n className={`mat-bubble-style-menu matops-editor--${theme ?? \"light\"}`}\n role=\"listbox\"\n style={{\n position: \"fixed\",\n top: dropPos.top,\n left: dropPos.left,\n zIndex: 99999,\n visibility: visible ? \"visible\" : \"hidden\",\n }}\n >\n {cmds.map(cmd => (\n <button\n key={cmd.id}\n type=\"button\"\n role=\"option\"\n aria-selected={!!cmd.isActive?.(editor)}\n className={cn(\"mat-bubble-style-item\", cmd.isActive?.(editor) && \"is-active\")}\n data-style={cmd.id}\n onMouseDown={e => {\n e.preventDefault();\n cmd.action(editor);\n close();\n }}\n >\n {cmd.title}\n </button>\n ))}\n </div>,\n document.body\n )\n : null;\n\n return (\n <>\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"mat-bubble-style-trigger\"\n onMouseDown={e => { e.preventDefault(); toggle(); }}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n title=\"Text style\"\n >\n <span>{active?.title ?? \"Text\"}</span>\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" style={{ opacity: 0.5 }}>\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {dropdown}\n </>\n );\n}\n\n// ─────────────────────────────────────────────\n// Inline Link Editor\n// ─────────────────────────────────────────────\n\nfunction LinkEditor({ onClose }: { onClose: () => void }) {\n const { editor } = useEditorContext();\n const [url, setUrl] = useState(() => editor?.getAttributes(\"link\").href ?? \"\");\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => { inputRef.current?.focus(); inputRef.current?.select(); }, []);\n\n const apply = useCallback(() => {\n if (!editor) return;\n const trimmed = url.trim();\n if (trimmed) {\n editor.chain().focus().setLink({\n href: trimmed.startsWith(\"http\") ? trimmed : `https://${trimmed}`,\n }).run();\n } else {\n editor.chain().focus().unsetLink().run();\n }\n onClose();\n }, [editor, url, onClose]);\n\n const handleKey = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") { e.preventDefault(); apply(); }\n if (e.key === \"Escape\") { e.preventDefault(); onClose(); }\n };\n\n return (\n <div className=\"mat-bubble-link-editor\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\" style={{ flexShrink: 0, opacity: 0.5 }}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/>\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>\n </svg>\n <input\n ref={inputRef}\n className=\"mat-bubble-link-input\"\n placeholder=\"Paste or type URL…\"\n value={url}\n onChange={e => setUrl(e.target.value)}\n onKeyDown={handleKey}\n />\n <button type=\"button\" className=\"mat-bubble-link-apply\" onMouseDown={e => { e.preventDefault(); apply(); }} title=\"Apply\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n </button>\n {editor?.isActive(\"link\") && (\n <button\n type=\"button\"\n className=\"mat-bubble-link-remove\"\n onMouseDown={e => { e.preventDefault(); editor?.chain().focus().unsetLink().run(); onClose(); }}\n title=\"Remove link\"\n >\n <UnlinkIcon size={12} />\n </button>\n )}\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// Bubble Menu Button\n// ─────────────────────────────────────────────\n\ninterface BubbleBtnProps {\n isActive?: boolean;\n title: string;\n ariaLabel: string;\n onMouseDown: (e: React.MouseEvent) => void;\n children: React.ReactNode;\n}\n\nfunction BubbleBtn({ isActive, title, ariaLabel, onMouseDown, children }: BubbleBtnProps) {\n return (\n <button\n type=\"button\"\n className={cn(\"mat-bubble-btn\", isActive && \"is-active\")}\n onMouseDown={onMouseDown}\n title={title}\n aria-label={ariaLabel}\n aria-pressed={isActive}\n >\n {children}\n </button>\n );\n}\n\n// ─────────────────────────────────────────────\n// Bubble Menu\n// ─────────────────────────────────────────────\n\nexport function FormattingBubbleMenu() {\n const { editor, features, editable } = useEditorContext();\n useEditorUpdate();\n\n const [showLinkEditor, setShowLinkEditor] = useState(false);\n\n if (!editor || !editable) return null;\n\n const hasFormatting = features.includes(\"formatting\");\n const hasCode = features.includes(\"code\");\n const hasMedia = features.includes(\"media\");\n\n if (!hasFormatting && !hasCode && !hasMedia) return null;\n\n const prevent = (e: React.MouseEvent) => e.preventDefault();\n\n return (\n <BubbleMenu\n editor={editor}\n options={{ placement: \"top\", offset: 10 }}\n shouldShow={({ editor: e, from, to }) =>\n // Never show alongside the TableContextMenu — that menu owns the\n // bubble position when the cursor is anywhere inside a table.\n // Text formatting inside cells is handled by TableContextMenu's\n // own Format section (visible when text is selected).\n from !== to &&\n !e.isActive(\"table\") &&\n !e.isActive(\"image\") &&\n !e.isActive(\"codeBlock\")\n }\n >\n <div className=\"mat-bubble-menu\" role=\"toolbar\" aria-label=\"Text formatting\">\n\n {showLinkEditor ? (\n <LinkEditor onClose={() => setShowLinkEditor(false)} />\n ) : (\n <>\n {hasFormatting && (\n <>\n <BubbleTextStyle />\n <div className=\"mat-bubble-divider\" />\n </>\n )}\n\n {hasFormatting && (\n <>\n <BubbleBtn isActive={editor.isActive(\"bold\")} title=\"Bold (Ctrl+B)\" ariaLabel=\"Bold\" onMouseDown={e => { prevent(e); editor.chain().focus().toggleBold().run(); }}><BoldIcon /></BubbleBtn>\n <BubbleBtn isActive={editor.isActive(\"italic\")} title=\"Italic (Ctrl+I)\" ariaLabel=\"Italic\" onMouseDown={e => { prevent(e); editor.chain().focus().toggleItalic().run(); }}><ItalicIcon /></BubbleBtn>\n <BubbleBtn isActive={editor.isActive(\"underline\")} title=\"Underline\" ariaLabel=\"Underline\" onMouseDown={e => { prevent(e); editor.chain().focus().toggleUnderline().run(); }}><UnderlineIcon /></BubbleBtn>\n <BubbleBtn isActive={editor.isActive(\"strike\")} title=\"Strikethrough\" ariaLabel=\"Strikethrough\" onMouseDown={e => { prevent(e); editor.chain().focus().toggleStrike().run(); }}><StrikeIcon /></BubbleBtn>\n <BubbleBtn isActive={editor.isActive(\"highlight\")} title=\"Highlight\" ariaLabel=\"Highlight\" onMouseDown={e => { prevent(e); editor.chain().focus().toggleHighlight().run(); }}><HighlightIcon /></BubbleBtn>\n </>\n )}\n\n {hasCode && (\n <>\n {hasFormatting && <div className=\"mat-bubble-divider\" />}\n <BubbleBtn isActive={editor.isActive(\"code\")} title=\"Inline code (Ctrl+E)\" ariaLabel=\"Inline code\" onMouseDown={e => { prevent(e); editor.chain().focus().toggleCode().run(); }}><CodeIcon /></BubbleBtn>\n </>\n )}\n\n {hasMedia && (\n <>\n {(hasFormatting || hasCode) && <div className=\"mat-bubble-divider\" />}\n <BubbleBtn isActive={editor.isActive(\"link\")} title=\"Link\" ariaLabel=\"Link\" onMouseDown={e => { prevent(e); setShowLinkEditor(true); }}><LinkIcon /></BubbleBtn>\n </>\n )}\n </>\n )}\n </div>\n </BubbleMenu>\n );\n}\n","import { useState, useRef, useEffect } from \"react\";\nimport { FloatingMenu } from \"@tiptap/react/menus\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { blockCommands } from \"@matops/editor/ui/commands/commandRegistry\";\n\n/**\n * BlockFloatingMenu\n *\n * A compact \"+\" trigger button on empty lines.\n * Click to expand into an icon-only pill of available commands.\n * Hover each icon to see the label as a tooltip.\n */\nexport function BlockFloatingMenu() {\n const { editor, features, editable } = useEditorContext();\n const [expanded, setExpanded] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const commands = blockCommands(features);\n\n // Close on outside click\n useEffect(() => {\n if (!expanded) return;\n const handle = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setExpanded(false);\n }\n };\n document.addEventListener(\"mousedown\", handle);\n return () => document.removeEventListener(\"mousedown\", handle);\n }, [expanded]);\n\n // Close when cursor moves away from the empty line\n useEffect(() => {\n if (!editor) return;\n\n const handle = () => setExpanded(false);\n editor.on(\"selectionUpdate\", handle);\n\n return () => {\n editor.off(\"selectionUpdate\", handle);\n };\n }, [editor]);\n\n if (!editor || !editable || commands.length === 0) return null;\n\n return (\n <FloatingMenu\n editor={editor}\n options={{ placement: \"left\", offset: 8 }}\n shouldShow={({ state }) => {\n const { $from } = state.selection;\n return (\n $from.parent.type.name === \"paragraph\" &&\n $from.parent.content.size === 0\n );\n }}\n >\n <div\n ref={menuRef}\n className={`mat-float-wrap${expanded ? \" mat-float-wrap--open\" : \"\"}`}\n >\n {/* The \"+\" trigger */}\n <button\n type=\"button\"\n className=\"mat-float-trigger\"\n aria-label=\"Insert block\"\n title=\"Insert block\"\n onClick={() => setExpanded((o) => !o)}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n style={{\n transition: \"transform 0.18s ease\",\n transform: expanded ? \"rotate(45deg)\" : \"rotate(0deg)\",\n }}\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n\n {/* Expanded icon strip */}\n {expanded && (\n <div\n className=\"mat-float-strip\"\n role=\"toolbar\"\n aria-label=\"Insert block\"\n >\n {commands.map((cmd) => (\n <button\n key={cmd.id}\n type=\"button\"\n className=\"mat-float-icon-btn\"\n title={cmd.title}\n aria-label={cmd.title}\n onClick={() => {\n cmd.action(editor);\n setExpanded(false);\n }}\n >\n <span className=\"mat-float-icon-btn__glyph\">{cmd.icon}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n </FloatingMenu>\n );\n}\n","import { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport {\n filterCommands,\n groupedCommands,\n} from \"@matops/editor/ui/commands/commandRegistry\";\nimport type { EditorCommand } from \"@matops/editor/ui/commands/commandRegistry\";\n\nconst VISIBLE_LIMIT = 5;\n\n// ─────────────────────────────────────────────\n// Full command grid popup (Confluence-style)\n// ─────────────────────────────────────────────\n\nfunction CommandGrid({\n features,\n onSelect,\n onClose,\n}: {\n features: import(\"../../core/types\").MatopsEditorFeature[];\n onSelect: (cmd: EditorCommand) => void;\n onClose: () => void;\n}) {\n const [search, setSearch] = useState(\"\");\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n useEffect(() => {\n const handle = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", handle);\n return () => window.removeEventListener(\"keydown\", handle);\n }, [onClose]);\n\n const groups = useMemo(\n () => groupedCommands(features, search || undefined),\n [features, search],\n );\n\n const totalCount = groups.reduce((n, g) => n + g.commands.length, 0);\n\n return (\n <div\n className=\"mat-cmd-overlay\"\n onMouseDown={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div className=\"mat-cmd-popup\">\n <div className=\"mat-cmd-popup__header\">\n <input\n ref={inputRef}\n className=\"mat-cmd-popup__search\"\n placeholder=\"Search commands…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n <button\n type=\"button\"\n className=\"mat-cmd-popup__close\"\n onClick={onClose}\n aria-label=\"Close\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n {totalCount === 0 ? (\n <div className=\"mat-cmd-popup__empty\">\n No commands match \"{search}\"\n </div>\n ) : (\n <div className=\"mat-cmd-popup__body\">\n {groups.map(({ group, label, commands }) => (\n <div key={group} className=\"mat-cmd-popup__section\">\n <div className=\"mat-cmd-popup__section-label\">{label}</div>\n <div className=\"mat-cmd-popup__grid\">\n {commands.map((cmd) => (\n <button\n key={cmd.id}\n type=\"button\"\n className=\"mat-cmd-popup__item\"\n onMouseDown={(e) => {\n e.preventDefault();\n onSelect(cmd);\n }}\n >\n <span className=\"mat-cmd-popup__icon\">{cmd.icon}</span>\n <span className=\"mat-cmd-popup__title\">{cmd.title}</span>\n <span className=\"mat-cmd-popup__desc\">\n {cmd.description}\n </span>\n </button>\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// Slash Command Menu\n// ─────────────────────────────────────────────\n\nexport function SlashMenu() {\n const { editor, features, editable } = useEditorContext();\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [menuPos, setMenuPos] = useState<{ top: number; left: number } | null>(\n null,\n );\n const [showGrid, setShowGrid] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const allCommands = useMemo(() => filterCommands(features), [features]);\n\n // When typing a query, filter all commands. When idle, show first VISIBLE_LIMIT.\n const visibleCommands = useMemo(\n () =>\n query\n ? filterCommands(features, query)\n : allCommands.slice(0, VISIBLE_LIMIT),\n [features, allCommands, query],\n );\n\n const showMoreButton = !query && allCommands.length > VISIBLE_LIMIT;\n\n useEffect(() => {\n setSelectedIndex(0);\n }, [visibleCommands.length]);\n\n // ── Detect \"/\" typed in empty paragraph ─────\n useEffect(() => {\n if (!editor || !editable) return;\n\n const handleUpdate = () => {\n const { $from } = editor.state.selection;\n\n if ($from.parent.type.name !== \"paragraph\") {\n setOpen(false);\n return;\n }\n\n const text = $from.parent.textContent;\n\n if (text.startsWith(\"/\")) {\n setQuery(text.slice(1));\n\n const domPos = editor.view.domAtPos($from.pos);\n const node = domPos.node as HTMLElement;\n\n if (node?.getBoundingClientRect) {\n const rect = node.getBoundingClientRect();\n setMenuPos({ top: rect.bottom + 4, left: rect.left });\n }\n\n setOpen(true);\n } else {\n setOpen(false);\n }\n };\n\n editor.on(\"update\", handleUpdate);\n\n return () => {\n editor.off(\"update\", handleUpdate);\n };\n }, [editor, editable]);\n\n // ── Clamp menu inside viewport after it renders ──────────────────\n useEffect(() => {\n if (!open || !menuPos || !menuRef.current) return;\n const menu = menuRef.current;\n const { offsetWidth: w, offsetHeight: h } = menu;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n let { top, left } = menuPos;\n\n // Flip above cursor if overflows bottom (cursor line ≈ top - 28px)\n if (top + h > vh - 8) {\n const above = top - 28 - h - 4;\n top = above > 8 ? above : Math.max(8, vh - h - 8);\n }\n\n // Clamp horizontally\n if (left + w > vw - 8) left = Math.max(8, vw - w - 8);\n if (left < 8) left = 8;\n\n if (top !== menuPos.top || left !== menuPos.left) {\n setMenuPos({ top, left });\n }\n }, [open, menuPos]);\n\n // ── Execute a command ─────────────────────────\n const executeCommand = useCallback(\n (cmd: EditorCommand) => {\n if (!editor) return;\n const { $from } = editor.state.selection;\n editor\n .chain()\n .focus()\n .deleteRange({ from: $from.start(), to: $from.end() })\n .run();\n cmd.action(editor);\n setOpen(false);\n setShowGrid(false);\n setQuery(\"\");\n },\n [editor],\n );\n\n // ── Keyboard navigation ─────────────────────\n useEffect(() => {\n if (!open || showGrid) return;\n const total = visibleCommands.length + (showMoreButton ? 1 : 0);\n const handle = (e: KeyboardEvent) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setSelectedIndex((i) => (i + 1) % total);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setSelectedIndex((i) => (i - 1 + total) % total);\n } else if (e.key === \"Enter\" || e.key === \"Tab\") {\n e.preventDefault();\n if (selectedIndex === visibleCommands.length && showMoreButton) {\n setShowGrid(true);\n } else {\n const cmd = visibleCommands[selectedIndex];\n if (cmd) executeCommand(cmd);\n }\n } else if (e.key === \"Escape\") {\n setOpen(false);\n }\n };\n window.addEventListener(\"keydown\", handle, true);\n return () => window.removeEventListener(\"keydown\", handle, true);\n }, [\n open,\n showGrid,\n visibleCommands,\n selectedIndex,\n showMoreButton,\n executeCommand,\n ]);\n\n // ── Scroll selected into view ─────────────────\n useEffect(() => {\n menuRef.current\n ?.querySelector(\".mat-slash-item.is-selected\")\n ?.scrollIntoView({ block: \"nearest\" });\n }, [selectedIndex]);\n\n if (!open || !menuPos) return null;\n\n return (\n <>\n {/* Inline dropdown */}\n <div\n ref={menuRef}\n className=\"mat-slash-menu\"\n style={{ top: menuPos.top, left: menuPos.left }}\n role=\"listbox\"\n aria-label=\"Insert command\"\n >\n {!query && <div className=\"mat-slash-header\">Commands</div>}\n\n {visibleCommands.map((cmd, i) => (\n <button\n key={cmd.id}\n type=\"button\"\n role=\"option\"\n aria-selected={i === selectedIndex}\n className={`mat-slash-item${i === selectedIndex ? \" is-selected\" : \"\"}`}\n onMouseDown={(e) => {\n e.preventDefault();\n executeCommand(cmd);\n }}\n onMouseEnter={() => setSelectedIndex(i)}\n >\n <span className=\"mat-slash-icon\">{cmd.icon}</span>\n <span className=\"mat-slash-text\">\n <span className=\"mat-slash-title\">{cmd.title}</span>\n <span className=\"mat-slash-desc\">{cmd.description}</span>\n </span>\n </button>\n ))}\n\n {visibleCommands.length === 0 && query && (\n <div className=\"mat-slash-empty\">No results for \"{query}\"</div>\n )}\n\n {showMoreButton && (\n <button\n type=\"button\"\n className={`mat-slash-more${selectedIndex === visibleCommands.length ? \" is-selected\" : \"\"}`}\n onMouseDown={(e) => {\n e.preventDefault();\n setShowGrid(true);\n }}\n onMouseEnter={() => setSelectedIndex(visibleCommands.length)}\n >\n <svg\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n >\n <circle\n cx=\"5\"\n cy=\"12\"\n r=\"1.5\"\n fill=\"currentColor\"\n stroke=\"none\"\n />\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"1.5\"\n fill=\"currentColor\"\n stroke=\"none\"\n />\n <circle\n cx=\"19\"\n cy=\"12\"\n r=\"1.5\"\n fill=\"currentColor\"\n stroke=\"none\"\n />\n </svg>\n More options\n <span className=\"mat-slash-more__count\">\n {allCommands.length - VISIBLE_LIMIT} more\n </span>\n </button>\n )}\n </div>\n\n {/* Full grid popup */}\n {showGrid && (\n <CommandGrid\n features={features}\n onSelect={executeCommand}\n onClose={() => setShowGrid(false)}\n />\n )}\n </>\n );\n}\n","import React from \"react\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\n\n// ─────────────────────────────────────────────\n// MenuButton\n// ─────────────────────────────────────────────\n\n/**\n * MenuButton — shared button primitive for all floating menus.\n *\n * Uses `onMouseDown` + `e.preventDefault()` to prevent the editor from\n * losing focus when a menu button is pressed.\n */\nexport interface MenuButtonProps {\n onClick: () => void;\n isActive?: boolean;\n isDisabled?: boolean;\n isDanger?: boolean;\n title: string;\n className?: string;\n children: React.ReactNode;\n}\n\nexport function MenuButton({\n onClick,\n isActive,\n isDisabled,\n isDanger,\n title,\n className,\n children,\n}: MenuButtonProps) {\n return (\n <button\n type=\"button\"\n onMouseDown={(e) => {\n e.preventDefault();\n if (!isDisabled) onClick();\n }}\n title={title}\n aria-label={title}\n aria-pressed={isActive}\n disabled={isDisabled}\n className={cn(\n \"mat-menu-btn\",\n isActive && \"is-active\",\n isDisabled && \"is-disabled\",\n isDanger && \"is-danger\",\n className,\n )}\n >\n {children}\n </button>\n );\n}\n\n// ─────────────────────────────────────────────\n// MenuDivider\n// ─────────────────────────────────────────────\n\nexport function MenuDivider() {\n return <div className=\"mat-menu-divider\" aria-hidden=\"true\" />;\n}\n\n// ── Backward-compatible re-exports ───────────────────────────────────────────\n// ModalOverlay, ModalDialog, ModalHeader have been extracted to ModalPrimitives.tsx.\n// These re-exports keep existing consumers working without changes.\nexport { ModalOverlay, ModalDialog, ModalHeader } from \"./ModalPrimitives\";\n","import React from \"react\";\nimport { BubbleMenu } from \"@tiptap/react/menus\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useEditorUpdate } from \"@matops/editor/core/context/editorHooks\";\nimport {\n MenuButton,\n MenuDivider,\n} from \"@matops/editor/ui/primitives/MenuButton\";\nimport {\n AddRowAboveIcon,\n AddRowBelowIcon,\n DeleteRowIcon,\n AddColLeftIcon,\n AddColRightIcon,\n DeleteColIcon,\n MergeCellsIcon,\n SplitCellIcon,\n DeleteTableIcon,\n BoldIcon,\n ItalicIcon,\n UnderlineIcon,\n StrikeIcon,\n HighlightIcon,\n CodeIcon,\n LinkIcon,\n} from \"@matops/editor/ui/icons/index\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\n\n// ─────────────────────────────────────────────\n// TableMenuSection — labelled group of actions\n// ─────────────────────────────────────────────\n\nfunction TableMenuSection({\n label,\n children,\n}: {\n label: string;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"mat-table-section\">\n <div className=\"mat-table-section__label\">{label}</div>\n <div className=\"mat-table-section__actions\">{children}</div>\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// TableMenuButton — labelled structural action\n// ─────────────────────────────────────────────\n\nfunction TableMenuButton({\n onClick,\n title,\n label,\n isDanger,\n isDisabled,\n icon,\n}: {\n onClick: () => void;\n title: string;\n label: string;\n isDanger?: boolean;\n isDisabled?: boolean;\n icon: React.ReactNode;\n}) {\n return (\n <MenuButton\n onClick={onClick}\n title={title}\n isDanger={isDanger}\n isDisabled={isDisabled}\n className=\"mat-table-btn\"\n >\n <span className=\"mat-table-btn__icon\">{icon}</span>\n <span className=\"mat-table-btn__label\">{label}</span>\n </MenuButton>\n );\n}\n\n// ─────────────────────────────────────────────\n// FormatSection — inline text formatting shown\n// only when text is selected inside a cell\n// ─────────────────────────────────────────────\n\nfunction FormatSection() {\n const { editor, features } = useEditorContext();\n useEditorUpdate();\n\n if (!editor) return null;\n\n const hasFormatting = features.includes(\"formatting\");\n const hasCode = features.includes(\"code\");\n const hasMedia = features.includes(\"media\");\n\n if (!hasFormatting && !hasCode && !hasMedia) return null;\n\n const prevent = (e: React.MouseEvent) => e.preventDefault();\n\n return (\n <>\n <MenuDivider />\n <TableMenuSection label=\"Format\">\n {hasFormatting && (\n <>\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"bold\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().toggleBold().run();\n }}\n title=\"Bold (Ctrl+B)\"\n aria-label=\"Bold\"\n aria-pressed={editor.isActive(\"bold\")}\n >\n <BoldIcon />\n </button>\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"italic\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().toggleItalic().run();\n }}\n title=\"Italic (Ctrl+I)\"\n aria-label=\"Italic\"\n aria-pressed={editor.isActive(\"italic\")}\n >\n <ItalicIcon />\n </button>\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"underline\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().toggleUnderline().run();\n }}\n title=\"Underline\"\n aria-label=\"Underline\"\n aria-pressed={editor.isActive(\"underline\")}\n >\n <UnderlineIcon />\n </button>\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"strike\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().toggleStrike().run();\n }}\n title=\"Strikethrough\"\n aria-label=\"Strikethrough\"\n aria-pressed={editor.isActive(\"strike\")}\n >\n <StrikeIcon />\n </button>\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"highlight\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().toggleHighlight().run();\n }}\n title=\"Highlight\"\n aria-label=\"Highlight\"\n aria-pressed={editor.isActive(\"highlight\")}\n >\n <HighlightIcon />\n </button>\n </>\n )}\n {hasCode && (\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"code\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().toggleCode().run();\n }}\n title=\"Inline code (Ctrl+E)\"\n aria-label=\"Inline code\"\n aria-pressed={editor.isActive(\"code\")}\n >\n <CodeIcon />\n </button>\n )}\n {hasMedia && (\n <button\n type=\"button\"\n className={cn(\n \"mat-table-btn\",\n editor.isActive(\"link\") && \"is-active\",\n )}\n onMouseDown={(e) => {\n prevent(e);\n editor.chain().focus().setLink({ href: \"\" }).run();\n }}\n title=\"Link\"\n aria-label=\"Link\"\n aria-pressed={editor.isActive(\"link\")}\n >\n <LinkIcon />\n </button>\n )}\n </TableMenuSection>\n </>\n );\n}\n\n// ─────────────────────────────────────────────\n// Component\n// ─────────────────────────────────────────────\n\n/**\n * TableContextMenu\n *\n * A BubbleMenu that appears whenever the cursor is inside a table.\n * Uses `pluginKey=\"tableMenu\"` to coexist with other BubbleMenus —\n * FormattingBubbleMenu suppresses itself when `e.isActive(\"table\")` so\n * these two menus never overlap.\n *\n * Sections (always): Row | Column | Cell | Table\n * Section (conditional): Format — shown only when text is selected inside\n * a cell (from !== to), giving users bold/italic/etc. without needing to\n * dismiss the table menu first.\n *\n * v3: imports from @tiptap/react/menus, uses `options` (not `tippyOptions`).\n */\nexport function TableContextMenu() {\n const { editor, features, editable } = useEditorContext();\n\n if (!editor || !editable || !features.includes(\"tables\")) return null;\n\n const { from, to } = editor.state.selection;\n const hasSelection = from !== to;\n\n return (\n <BubbleMenu\n editor={editor}\n pluginKey=\"tableMenu\"\n options={{ placement: \"top\", offset: 10 }}\n shouldShow={({ editor: e }) => e.isActive(\"table\")}\n >\n <div\n className=\"mat-table-menu\"\n role=\"toolbar\"\n aria-label=\"Table options\"\n onMouseDown={(ev) => ev.preventDefault()}\n >\n <TableMenuSection label=\"Row\">\n <TableMenuButton\n onClick={() => editor.chain().focus().addRowBefore().run()}\n title=\"Add row above\"\n label=\"Above\"\n icon={<AddRowAboveIcon />}\n />\n <TableMenuButton\n onClick={() => editor.chain().focus().addRowAfter().run()}\n title=\"Add row below\"\n label=\"Below\"\n icon={<AddRowBelowIcon />}\n />\n <TableMenuButton\n onClick={() => editor.chain().focus().deleteRow().run()}\n title=\"Delete row\"\n label=\"Delete\"\n isDanger\n icon={<DeleteRowIcon />}\n />\n </TableMenuSection>\n\n <MenuDivider />\n\n <TableMenuSection label=\"Column\">\n <TableMenuButton\n onClick={() => editor.chain().focus().addColumnBefore().run()}\n title=\"Add column left\"\n label=\"Left\"\n icon={<AddColLeftIcon />}\n />\n <TableMenuButton\n onClick={() => editor.chain().focus().addColumnAfter().run()}\n title=\"Add column right\"\n label=\"Right\"\n icon={<AddColRightIcon />}\n />\n <TableMenuButton\n onClick={() => editor.chain().focus().deleteColumn().run()}\n title=\"Delete column\"\n label=\"Delete\"\n isDanger\n icon={<DeleteColIcon />}\n />\n </TableMenuSection>\n\n <MenuDivider />\n\n <TableMenuSection label=\"Cell\">\n <TableMenuButton\n onClick={() => editor.chain().focus().mergeCells().run()}\n title=\"Merge selected cells\"\n label=\"Merge\"\n isDisabled={!editor.can().mergeCells()}\n icon={<MergeCellsIcon />}\n />\n <TableMenuButton\n onClick={() => editor.chain().focus().splitCell().run()}\n title=\"Split cell\"\n label=\"Split\"\n isDisabled={!editor.can().splitCell()}\n icon={<SplitCellIcon />}\n />\n </TableMenuSection>\n\n <MenuDivider />\n\n <TableMenuSection label=\"Table\">\n <TableMenuButton\n onClick={() => editor.chain().focus().deleteTable().run()}\n title=\"Delete entire table\"\n label=\"Delete\"\n isDanger\n icon={<DeleteTableIcon />}\n />\n </TableMenuSection>\n\n {hasSelection && <FormatSection />}\n </div>\n </BubbleMenu>\n );\n}\n","/**\n * tableHelpers.ts\n *\n * ProseMirror-level table utilities used by TableHandles, TableExtendButtons,\n * and any other surface that needs to operate on specific rows/columns by index\n * rather than by cursor position.\n *\n * All operations:\n * 1. Derive the PM table node from the DOM element (avoids coupling to cursor pos)\n * 2. Build a new table node with the desired content\n * 3. Dispatch a single `replaceWith` transaction\n *\n * The cursor is repositioned to the first cell of the operated row/column so\n * the user has clear visual feedback of where the change occurred.\n */\n\nimport { TextSelection } from \"@tiptap/pm/state\";\nimport type { Node as PmNode } from \"@tiptap/pm/model\";\nimport type { Editor } from \"@tiptap/core\";\n\n// ─────────────────────────────────────────────\n// Internal — resolve PM table node from DOM\n// ─────────────────────────────────────────────\n\ninterface TableContext {\n node: PmNode;\n pos: number; // position BEFORE the table node in the PM document\n}\n\n/**\n * Resolve the ProseMirror table node and its document position from an\n * HTMLTableElement that lives inside the editor view DOM.\n *\n * Strategy: convert the position of the first cell to a PM position,\n * then walk up the resolved position tree to find the `table` node.\n */\nfunction getTableCtx(editor: Editor, tableEl: HTMLTableElement): TableContext | null {\n const firstCell = tableEl.rows[0]?.cells[0];\n if (!firstCell) return null;\n\n let innerPos: number;\n try {\n innerPos = editor.view.posAtDOM(firstCell, 0);\n } catch {\n return null;\n }\n if (innerPos < 0) return null;\n\n const $pos = editor.state.doc.resolve(innerPos);\n for (let d = $pos.depth; d >= 0; d--) {\n if ($pos.node(d).type.name === \"table\") {\n return { node: $pos.node(d), pos: $pos.before(d) };\n }\n }\n return null;\n}\n\n// ─────────────────────────────────────────────\n// Internal — dispatch a new table node\n// ─────────────────────────────────────────────\n\nfunction dispatchTable(editor: Editor, ctx: TableContext, newRows: PmNode[]): void {\n const newTable = ctx.node.type.create(ctx.node.attrs, newRows);\n editor.view.dispatch(\n editor.state.tr.replaceWith(ctx.pos, ctx.pos + ctx.node.nodeSize, newTable),\n );\n}\n\n// ─────────────────────────────────────────────\n// Public — cursor positioning helper\n// ─────────────────────────────────────────────\n\n/**\n * Move the editor cursor to the cell at (rowIndex, colIndex) of `tableEl`,\n * then immediately invoke `callback`.\n *\n * This is the key building-block for row/column commands (addRowBefore,\n * deleteColumn, etc.) which always operate relative to the cursor cell.\n * By placing the cursor first we can target any row/column regardless of\n * where the user last clicked.\n */\nexport function runAtCell(\n editor: Editor,\n tableEl: HTMLTableElement,\n rowIndex: number,\n colIndex: number,\n callback: () => void,\n): void {\n const row = tableEl.rows[rowIndex];\n if (!row) return;\n\n const cell = row.cells[Math.min(colIndex, row.cells.length - 1)];\n if (!cell) return;\n\n let pos: number;\n try {\n pos = editor.view.posAtDOM(cell, 0);\n } catch {\n return;\n }\n if (pos < 0) return;\n\n const $pos = editor.state.doc.resolve(pos);\n const sel = TextSelection.near($pos);\n editor.view.dispatch(editor.state.tr.setSelection(sel));\n\n callback();\n}\n\n// ─────────────────────────────────────────────\n// Public — Row operations\n// ─────────────────────────────────────────────\n\n/** Swap row at `fromIdx` with the row at `toIdx`. */\nexport function moveTableRow(\n editor: Editor,\n tableEl: HTMLTableElement,\n fromIdx: number,\n toIdx: number,\n): void {\n const ctx = getTableCtx(editor, tableEl);\n if (!ctx) return;\n\n const rows: PmNode[] = [];\n ctx.node.forEach((r) => rows.push(r));\n\n if (\n fromIdx === toIdx ||\n fromIdx < 0 || toIdx < 0 ||\n fromIdx >= rows.length || toIdx >= rows.length\n ) return;\n\n const next = [...rows];\n const [moved] = next.splice(fromIdx, 1);\n next.splice(toIdx, 0, moved);\n\n dispatchTable(editor, ctx, next);\n}\n\n/** Insert a copy of row `rowIdx` immediately below it. */\nexport function duplicateTableRow(\n editor: Editor,\n tableEl: HTMLTableElement,\n rowIdx: number,\n): void {\n const ctx = getTableCtx(editor, tableEl);\n if (!ctx) return;\n\n const rows: PmNode[] = [];\n ctx.node.forEach((r) => rows.push(r));\n\n if (rowIdx < 0 || rowIdx >= rows.length) return;\n\n const src = rows[rowIdx];\n // Retype every cell as tableCell (not tableHeader) so the duplicate is\n // a data row even when duplicating the header row.\n const cellType =\n ctx.node.type.schema.nodes.tableCell ?? ctx.node.type.schema.nodes.table_cell;\n\n const dupCells: PmNode[] = [];\n src.forEach((cell) => {\n const type = cellType ?? cell.type;\n dupCells.push(type.create(\n { ...cell.attrs, colspan: cell.attrs.colspan, rowspan: cell.attrs.rowspan },\n cell.content,\n cell.marks,\n ));\n });\n\n const rowType = src.type.schema.nodes.tableRow ?? src.type.schema.nodes.table_row ?? src.type;\n const dup = rowType.create(src.attrs, dupCells, src.marks);\n\n const next = [...rows];\n next.splice(rowIdx + 1, 0, dup);\n\n dispatchTable(editor, ctx, next);\n}\n\n// ─────────────────────────────────────────────\n// Public — Column operations\n// ─────────────────────────────────────────────\n\n/** Swap column at `fromIdx` with the column at `toIdx` across all rows. */\nexport function moveTableColumn(\n editor: Editor,\n tableEl: HTMLTableElement,\n fromIdx: number,\n toIdx: number,\n): void {\n const ctx = getTableCtx(editor, tableEl);\n if (!ctx) return;\n\n const newRows: PmNode[] = [];\n ctx.node.forEach((rowNode) => {\n const cells: PmNode[] = [];\n rowNode.forEach((c) => cells.push(c));\n\n if (\n fromIdx === toIdx ||\n fromIdx >= cells.length || toIdx >= cells.length\n ) {\n newRows.push(rowNode);\n return;\n }\n\n const next = [...cells];\n const [moved] = next.splice(fromIdx, 1);\n next.splice(toIdx, 0, moved);\n\n newRows.push(rowNode.type.create(rowNode.attrs, next, rowNode.marks));\n });\n\n dispatchTable(editor, ctx, newRows);\n}\n\n/** Insert a copy of column `colIdx` immediately to its right across all rows. */\nexport function duplicateTableColumn(\n editor: Editor,\n tableEl: HTMLTableElement,\n colIdx: number,\n): void {\n const ctx = getTableCtx(editor, tableEl);\n if (!ctx) return;\n\n const newRows: PmNode[] = [];\n ctx.node.forEach((rowNode) => {\n const cells: PmNode[] = [];\n rowNode.forEach((c) => cells.push(c));\n\n if (colIdx >= cells.length) {\n newRows.push(rowNode);\n return;\n }\n\n const src = cells[colIdx];\n const dup = src.type.create(src.attrs, src.content, src.marks);\n\n const next = [...cells];\n next.splice(colIdx + 1, 0, dup);\n\n newRows.push(rowNode.type.create(rowNode.attrs, next, rowNode.marks));\n });\n\n dispatchTable(editor, ctx, newRows);\n}\n\n// ─────────────────────────────────────────────\n// Public — Active table DOM lookup\n// ─────────────────────────────────────────────\n\n/**\n * Return the HTMLTableElement that contains the current editor selection,\n * or null if the cursor is not inside a table.\n */\nexport function getActiveTableEl(editor: Editor): HTMLTableElement | null {\n if (!editor.isActive(\"table\")) return null;\n\n const { $from } = editor.state.selection;\n for (let d = $from.depth; d >= 0; d--) {\n if ($from.node(d).type.name === \"table\") {\n const el = editor.view.nodeDOM($from.before(d));\n if (el instanceof HTMLTableElement) return el;\n if (el instanceof Element) {\n const t = el.querySelector(\"table\");\n if (t) return t as HTMLTableElement;\n }\n return null;\n }\n }\n return null;\n}\n","/**\n * TableHandles\n *\n * Two floating grip handles that appear when the mouse hovers inside a table:\n *\n * • Row handle — left of the hovered row. Opens a dropdown menu:\n * Add row above / below, Move up / down, Duplicate, Delete.\n *\n * • Column handle — above the hovered column (anchored to the first row so\n * it stays still as the mouse moves between rows).\n * Opens: Add column left / right, Move left / right, Duplicate, Delete.\n *\n * Architecture:\n * - `mousemove` listener on `editor.view.dom` tracks the hovered <td>/<th>.\n * - A 250 ms hide timer lets the mouse travel to the handle without it disappearing.\n * The timer is cancelled on `mouseenter` of either handle.\n * - While a dropdown is open the hide timer is suppressed entirely.\n * - Both handles are rendered via `createPortal` to `document.body` using\n * `position: fixed` and viewport coordinates — no Floating UI needed.\n * - All row/column mutations go through `tableHelpers.ts` so this file is pure UI.\n */\n\nimport React, { useState, useEffect, useRef, useCallback } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport {\n runAtCell,\n moveTableRow,\n duplicateTableRow,\n moveTableColumn,\n duplicateTableColumn,\n} from \"@matops/editor/utils/helpers/tableHelpers\";\nimport {\n GripVerticalIcon,\n GripHorizontalIcon,\n AddRowAboveIcon,\n AddRowBelowIcon,\n DeleteRowIcon,\n AddColLeftIcon,\n AddColRightIcon,\n DeleteColIcon,\n ArrowUpIcon,\n ArrowDownIcon,\n ArrowLeftIcon,\n ArrowRightIcon,\n DuplicateIcon,\n} from \"@matops/editor/ui/icons/index\";\nimport { createPortal } from \"react-dom\";\n\n// ─────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────\n\ninterface HoverState {\n rowIndex: number;\n colIndex: number;\n rowRect: DOMRect;\n /** First-row cell in the hovered column — keeps the col handle stable */\n colCellRect: DOMRect;\n tableRect: DOMRect;\n tableEl: HTMLTableElement;\n totalRows: number;\n totalCols: number;\n}\n\n// ─────────────────────────────────────────────\n// Shared menu primitives\n// ─────────────────────────────────────────────\n\ninterface MenuItemProps {\n icon: React.ReactNode;\n label: string;\n isDanger?: boolean;\n isDisabled?: boolean;\n onClick: () => void;\n}\n\nfunction HandleMenuItem({\n icon,\n label,\n isDanger,\n isDisabled,\n onClick,\n}: MenuItemProps) {\n return (\n <button\n type=\"button\"\n className={cn(\n \"mat-th-item\",\n isDanger && \"is-danger\",\n isDisabled && \"is-disabled\",\n )}\n disabled={isDisabled}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n if (!isDisabled) onClick();\n }}\n >\n <span className=\"mat-th-item__icon\">{icon}</span>\n <span className=\"mat-th-item__label\">{label}</span>\n </button>\n );\n}\n\nfunction HandleMenuDivider() {\n return <div className=\"mat-th-divider\" />;\n}\n\n// ─────────────────────────────────────────────\n// Row handle dropdown\n// ─────────────────────────────────────────────\n\nfunction RowMenu({\n hover,\n editor,\n onClose,\n}: {\n hover: HoverState;\n editor: ReturnType<typeof useEditorContext>[\"editor\"];\n onClose: () => void;\n}) {\n if (!editor) return null;\n const { rowIndex, tableEl, totalRows } = hover;\n const run = (fn: () => void) => {\n fn();\n onClose();\n };\n\n return (\n <div className=\"mat-th-menu\">\n <HandleMenuItem\n icon={<AddRowAboveIcon size={13} />}\n label=\"Add row above\"\n onClick={() =>\n run(() =>\n runAtCell(editor, tableEl, rowIndex, 0, () =>\n editor.chain().focus().addRowBefore().run(),\n ),\n )\n }\n />\n <HandleMenuItem\n icon={<AddRowBelowIcon size={13} />}\n label=\"Add row below\"\n onClick={() =>\n run(() =>\n runAtCell(editor, tableEl, rowIndex, 0, () =>\n editor.chain().focus().addRowAfter().run(),\n ),\n )\n }\n />\n <HandleMenuDivider />\n <HandleMenuItem\n icon={<ArrowUpIcon />}\n label=\"Move up\"\n isDisabled={rowIndex === 0}\n onClick={() =>\n run(() => moveTableRow(editor, tableEl, rowIndex, rowIndex - 1))\n }\n />\n <HandleMenuItem\n icon={<ArrowDownIcon />}\n label=\"Move down\"\n isDisabled={rowIndex >= totalRows - 1}\n onClick={() =>\n run(() => moveTableRow(editor, tableEl, rowIndex, rowIndex + 1))\n }\n />\n <HandleMenuDivider />\n <HandleMenuItem\n icon={<DuplicateIcon />}\n label=\"Duplicate row\"\n onClick={() => run(() => duplicateTableRow(editor, tableEl, rowIndex))}\n />\n <HandleMenuDivider />\n <HandleMenuItem\n icon={<DeleteRowIcon size={13} />}\n label=\"Delete row\"\n isDanger\n onClick={() =>\n run(() =>\n runAtCell(editor, tableEl, rowIndex, 0, () =>\n editor.chain().focus().deleteRow().run(),\n ),\n )\n }\n />\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// Column handle dropdown\n// ─────────────────────────────────────────────\n\nfunction ColMenu({\n hover,\n editor,\n onClose,\n}: {\n hover: HoverState;\n editor: ReturnType<typeof useEditorContext>[\"editor\"];\n onClose: () => void;\n}) {\n if (!editor) return null;\n const { colIndex, tableEl, totalCols } = hover;\n const run = (fn: () => void) => {\n fn();\n onClose();\n };\n\n return (\n <div className=\"mat-th-menu\">\n <HandleMenuItem\n icon={<AddColLeftIcon size={13} />}\n label=\"Add column left\"\n onClick={() =>\n run(() =>\n runAtCell(editor, tableEl, 0, colIndex, () =>\n editor.chain().focus().addColumnBefore().run(),\n ),\n )\n }\n />\n <HandleMenuItem\n icon={<AddColRightIcon size={13} />}\n label=\"Add column right\"\n onClick={() =>\n run(() =>\n runAtCell(editor, tableEl, 0, colIndex, () =>\n editor.chain().focus().addColumnAfter().run(),\n ),\n )\n }\n />\n <HandleMenuDivider />\n <HandleMenuItem\n icon={<ArrowLeftIcon />}\n label=\"Move left\"\n isDisabled={colIndex === 0}\n onClick={() =>\n run(() => moveTableColumn(editor, tableEl, colIndex, colIndex - 1))\n }\n />\n <HandleMenuItem\n icon={<ArrowRightIcon />}\n label=\"Move right\"\n isDisabled={colIndex >= totalCols - 1}\n onClick={() =>\n run(() => moveTableColumn(editor, tableEl, colIndex, colIndex + 1))\n }\n />\n <HandleMenuDivider />\n <HandleMenuItem\n icon={<DuplicateIcon />}\n label=\"Duplicate column\"\n onClick={() =>\n run(() => duplicateTableColumn(editor, tableEl, colIndex))\n }\n />\n <HandleMenuDivider />\n <HandleMenuItem\n icon={<DeleteColIcon size={13} />}\n label=\"Delete column\"\n isDanger\n onClick={() =>\n run(() =>\n runAtCell(editor, tableEl, 0, colIndex, () =>\n editor.chain().focus().deleteColumn().run(),\n ),\n )\n }\n />\n </div>\n );\n}\n\n// ─────────────────────────────────────────────\n// Main export\n// ─────────────────────────────────────────────\n\nexport function TableHandles() {\n const { editor, editable, featureSet, theme } = useEditorContext();\n const [hover, setHover] = useState<HoverState | null>(null);\n const [openMenu, setOpenMenu] = useState<\"row\" | \"col\" | null>(null);\n\n const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Stable ref so callbacks can read the latest openMenu without going stale\n const openMenuRef = useRef<\"row\" | \"col\" | null>(null);\n openMenuRef.current = openMenu;\n\n const themeClass = `matops-editor--${theme}`;\n\n // ── Hide timer helpers ──────────────────────────────────────────────────\n\n const cancelHide = useCallback(() => {\n if (hideTimer.current) {\n clearTimeout(hideTimer.current);\n hideTimer.current = null;\n }\n }, []);\n\n const scheduleHide = useCallback(() => {\n // Never hide while a dropdown is open\n if (openMenuRef.current !== null) return;\n cancelHide();\n hideTimer.current = setTimeout(() => {\n setHover(null);\n setOpenMenu(null);\n }, 240);\n }, [cancelHide]);\n\n // ── Track hovered table cell ────────────────────────────────────────────\n\n useEffect(() => {\n if (!editor || !editable) return;\n const dom = editor.view.dom as HTMLElement;\n\n const onMove = (e: MouseEvent) => {\n // Don't update position while a menu is open\n if (openMenuRef.current !== null) return;\n\n const cell = (e.target as Element).closest?.(\n \"td, th\",\n ) as HTMLTableCellElement | null;\n if (!cell || !dom.contains(cell)) {\n scheduleHide();\n return;\n }\n\n const tableEl = cell.closest(\"table\") as HTMLTableElement | null;\n if (!tableEl || !dom.contains(tableEl)) {\n scheduleHide();\n return;\n }\n\n cancelHide();\n\n const rowEl = cell.closest(\"tr\") as HTMLTableRowElement;\n const rowIndex = rowEl.rowIndex;\n const colIndex = cell.cellIndex;\n const anchorCell = tableEl.rows[0]?.cells[colIndex] ?? cell;\n\n setHover({\n rowIndex,\n colIndex,\n rowRect: rowEl.getBoundingClientRect(),\n colCellRect: anchorCell.getBoundingClientRect(),\n tableRect: tableEl.getBoundingClientRect(),\n tableEl,\n totalRows: tableEl.rows.length,\n totalCols: tableEl.rows[0]?.cells.length ?? 1,\n });\n };\n\n const onLeave = () => scheduleHide();\n\n dom.addEventListener(\"mousemove\", onMove);\n dom.addEventListener(\"mouseleave\", onLeave);\n return () => {\n dom.removeEventListener(\"mousemove\", onMove);\n dom.removeEventListener(\"mouseleave\", onLeave);\n };\n }, [editor, editable, cancelHide, scheduleHide]);\n\n // ── Close dropdown on outside click ────────────────────────────────────\n\n useEffect(() => {\n if (!openMenu) return;\n const handler = (e: MouseEvent) => {\n if (!(e.target as Element).closest(\".mat-table-handle\")) {\n setOpenMenu(null);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [openMenu]);\n\n // ── Bail out ────────────────────────────────────────────────────────────\n\n if (!featureSet.has(\"tables\") || !editor || !editable || !hover) return null;\n if (typeof document === \"undefined\") return null;\n\n const { rowRect, colCellRect, tableRect } = hover;\n\n // Row handle: centred vertically on the row, just outside the left edge\n const rowLeft = tableRect.left - 26;\n const rowTop = rowRect.top + rowRect.height / 2 - 11;\n\n // Col handle: centred horizontally on the column's first-row cell, above the table\n const colLeft = colCellRect.left + colCellRect.width / 2 - 11;\n const colTop = tableRect.top - 26;\n\n return createPortal(\n <>\n {/* ── Row handle ── */}\n <div\n className={cn(\"mat-table-handle\", themeClass)}\n style={{ position: \"fixed\", left: rowLeft, top: rowTop, zIndex: 9999 }}\n onMouseEnter={cancelHide}\n onMouseLeave={scheduleHide}\n >\n <button\n type=\"button\"\n className={cn(\"mat-th-btn\", openMenu === \"row\" && \"is-open\")}\n title=\"Row options\"\n aria-label=\"Row options\"\n aria-haspopup=\"true\"\n aria-expanded={openMenu === \"row\"}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setOpenMenu((p) => (p === \"row\" ? null : \"row\"));\n }}\n >\n <GripVerticalIcon />\n </button>\n {openMenu === \"row\" && (\n <RowMenu\n hover={hover}\n editor={editor}\n onClose={() => setOpenMenu(null)}\n />\n )}\n </div>\n\n {/* ── Column handle ── */}\n <div\n className={cn(\"mat-table-handle\", themeClass)}\n style={{ position: \"fixed\", left: colLeft, top: colTop, zIndex: 9999 }}\n onMouseEnter={cancelHide}\n onMouseLeave={scheduleHide}\n >\n <button\n type=\"button\"\n className={cn(\"mat-th-btn\", openMenu === \"col\" && \"is-open\")}\n title=\"Column options\"\n aria-label=\"Column options\"\n aria-haspopup=\"true\"\n aria-expanded={openMenu === \"col\"}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setOpenMenu((p) => (p === \"col\" ? null : \"col\"));\n }}\n >\n <GripHorizontalIcon />\n </button>\n {openMenu === \"col\" && (\n <ColMenu\n hover={hover}\n editor={editor}\n onClose={() => setOpenMenu(null)}\n />\n )}\n </div>\n </>,\n document.body,\n );\n}\n","/**\n * TableExtendButtons\n *\n * Two `+` buttons that float outside the active table whenever the cursor\n * is inside one:\n *\n * • Bottom button — centred below the table → addRowAfter() at the last row\n * • Right button — centred to the right of the table → addColumnAfter() at the last column\n *\n * Both are rendered via `createPortal` to `document.body` using `position: fixed`.\n * Position is recalculated on every editor transaction so the buttons follow the\n * table as content above it changes.\n *\n * The buttons are hidden while the TableHandles dropdown is open (no explicit\n * coordination needed — they simply re-check the table DOM position each frame).\n */\n\nimport React, { useState, useEffect, useCallback } from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport {\n getActiveTableEl,\n runAtCell,\n} from \"@matops/editor/utils/helpers/tableHelpers\";\nimport { PlusIcon } from \"@matops/editor/ui/icons/index\";\nimport { createPortal } from \"react-dom\";\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\ninterface TableRect {\n top: number;\n left: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n}\n\nfunction getTableRect(tableEl: HTMLTableElement): TableRect {\n const r = tableEl.getBoundingClientRect();\n return {\n top: r.top,\n left: r.left,\n right: r.right,\n bottom: r.bottom,\n width: r.width,\n height: r.height,\n };\n}\n\n// ─────────────────────────────────────────────\n// Component\n// ─────────────────────────────────────────────\n\nexport function TableExtendButtons() {\n const { editor, editable, featureSet, theme } = useEditorContext();\n const [rect, setRect] = useState<TableRect | null>(null);\n const themeClass = `matops-editor--${theme}`;\n\n // Recalculate bounding rect on every transaction\n const measure = useCallback(() => {\n if (!editor || !editor.isActive(\"table\")) {\n setRect(null);\n return;\n }\n const tableEl = getActiveTableEl(editor);\n if (!tableEl) {\n setRect(null);\n return;\n }\n setRect(getTableRect(tableEl));\n }, [editor]);\n\n useEffect(() => {\n if (!editor) return;\n editor.on(\"transaction\", measure);\n editor.on(\"selectionUpdate\", measure);\n // Also measure on scroll/resize so buttons track table position\n const onScroll = () => measure();\n window.addEventListener(\"scroll\", onScroll, {\n capture: true,\n passive: true,\n });\n window.addEventListener(\"resize\", onScroll, { passive: true });\n return () => {\n editor.off(\"transaction\", measure);\n editor.off(\"selectionUpdate\", measure);\n window.removeEventListener(\"scroll\", onScroll, true);\n window.removeEventListener(\"resize\", onScroll);\n };\n }, [editor, measure]);\n\n if (!featureSet.has(\"tables\") || !editor || !editable || !rect) return null;\n if (typeof document === \"undefined\") return null;\n\n const BUTTON_SIZE = 20;\n const GAP = 6;\n\n // Bottom button: horizontally centred, just below the table\n const bottomLeft = rect.left + rect.width / 2 - BUTTON_SIZE / 2;\n const bottomTop = rect.bottom + GAP;\n\n // Right button: vertically centred, just right of the table\n const rightLeft = rect.right + GAP;\n const rightTop = rect.top + rect.height / 2 - BUTTON_SIZE / 2;\n\n const addRow = (e: React.MouseEvent) => {\n e.preventDefault();\n const tableEl = getActiveTableEl(editor);\n if (!tableEl) return;\n const lastRow = tableEl.rows.length - 1;\n const lastCol = 0;\n runAtCell(editor, tableEl, lastRow, lastCol, () =>\n editor.chain().focus().addRowAfter().run(),\n );\n };\n\n const addCol = (e: React.MouseEvent) => {\n e.preventDefault();\n const tableEl = getActiveTableEl(editor);\n if (!tableEl) return;\n const lastCol = (tableEl.rows[0]?.cells.length ?? 1) - 1;\n runAtCell(editor, tableEl, 0, lastCol, () =>\n editor.chain().focus().addColumnAfter().run(),\n );\n };\n\n return createPortal(\n <>\n {/* ── Add row button (bottom) ── */}\n <button\n type=\"button\"\n className={cn(\"mat-table-extend-btn\", themeClass)}\n style={{\n position: \"fixed\",\n left: bottomLeft,\n top: bottomTop,\n width: BUTTON_SIZE,\n height: BUTTON_SIZE,\n zIndex: 9998,\n }}\n title=\"Add row\"\n aria-label=\"Add row\"\n onMouseDown={addRow}\n >\n <PlusIcon size={10} />\n </button>\n\n {/* ── Add column button (right) ── */}\n <button\n type=\"button\"\n className={cn(\"mat-table-extend-btn\", themeClass)}\n style={{\n position: \"fixed\",\n left: rightLeft,\n top: rightTop,\n width: BUTTON_SIZE,\n height: BUTTON_SIZE,\n zIndex: 9998,\n }}\n title=\"Add column\"\n aria-label=\"Add column\"\n onMouseDown={addCol}\n >\n <PlusIcon size={10} />\n </button>\n </>,\n document.body,\n );\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\";\nimport { BubbleMenu } from \"@tiptap/react/menus\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport {\n MenuButton,\n MenuDivider,\n} from \"@matops/editor/ui/primitives/MenuButton\";\nimport {\n EditIcon,\n ExternalLinkIcon,\n UnlinkIcon,\n CheckIcon,\n} from \"@matops/editor/ui/icons/index\";\n\n/**\n * LinkPopover\n *\n * Appears when the cursor is inside a link node.\n * Two modes:\n * - Preview: shows URL with edit / open / unlink buttons\n * - Edit: inline input field to change the URL\n *\n * Uses `pluginKey=\"linkMenu\"` to coexist with the text formatting BubbleMenu.\n */\nexport function LinkPopover() {\n const { editor, features, editable } = useEditorContext();\n const [editing, setEditing] = useState(false);\n const [urlValue, setUrlValue] = useState(\"\");\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Sync local URL state when the active link changes\n useEffect(() => {\n if (!editor) return;\n const href = (editor.getAttributes(\"link\").href as string) ?? \"\";\n setUrlValue(href);\n setEditing(false);\n }, [editor?.state]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const startEdit = useCallback(() => {\n setEditing(true);\n setTimeout(() => inputRef.current?.focus(), 50);\n }, []);\n\n const saveEdit = useCallback(() => {\n if (!editor || !urlValue.trim()) return;\n editor.chain().focus().setLink({ href: urlValue.trim() }).run();\n setEditing(false);\n }, [editor, urlValue]);\n\n const openLink = useCallback(() => {\n const href = editor?.getAttributes(\"link\").href as string;\n if (href) window.open(href, \"_blank\", \"noopener,noreferrer\");\n }, [editor]);\n\n const removeLink = useCallback(() => {\n editor?.chain().focus().unsetLink().run();\n setEditing(false);\n }, [editor]);\n\n if (!editor || !features.includes(\"media\")) return null;\n\n const currentHref = (editor.getAttributes(\"link\").href as string) ?? \"\";\n const displayUrl =\n currentHref.length > 40 ? `${currentHref.slice(0, 40)}…` : currentHref;\n\n return (\n <BubbleMenu\n editor={editor}\n pluginKey=\"linkMenu\"\n options={{ placement: \"bottom\", offset: 8 }}\n shouldShow={({ editor: e }) => e.isActive(\"link\") && editable}\n >\n <div className=\"mat-link-popover\" onMouseDown={(e) => e.preventDefault()}>\n {editing ? (\n /* ── Edit mode ── */\n <div className=\"mat-link-edit-row\">\n <input\n ref={inputRef}\n className=\"mat-link-input\"\n value={urlValue}\n onChange={(e) => setUrlValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") saveEdit();\n if (e.key === \"Escape\") setEditing(false);\n }}\n placeholder=\"https://…\"\n spellCheck={false}\n aria-label=\"Link URL\"\n />\n <MenuButton\n onClick={saveEdit}\n title=\"Save link\"\n className=\"mat-link-btn primary\"\n >\n <CheckIcon />\n </MenuButton>\n </div>\n ) : (\n /* ── Preview mode ── */\n <div className=\"mat-link-preview-row\">\n <span className=\"mat-link-url\" title={currentHref}>\n {displayUrl || \"No URL\"}\n </span>\n <div className=\"mat-link-actions\">\n <MenuButton\n onClick={startEdit}\n title=\"Edit link\"\n className=\"mat-link-btn\"\n >\n <EditIcon />\n </MenuButton>\n <MenuButton\n onClick={openLink}\n title=\"Open in new tab\"\n className=\"mat-link-btn\"\n >\n <ExternalLinkIcon />\n </MenuButton>\n <MenuDivider />\n <MenuButton\n onClick={removeLink}\n isDanger\n title=\"Remove link\"\n className=\"mat-link-btn\"\n >\n <UnlinkIcon />\n </MenuButton>\n </div>\n </div>\n )}\n </div>\n </BubbleMenu>\n );\n}\n","import { BubbleMenu } from \"@tiptap/react/menus\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { MenuButton, MenuDivider } from \"@matops/editor/ui/primitives/MenuButton\";\nimport {\n AlignLeftIcon,\n AlignCenterIcon,\n AlignRightIcon,\n AltTextIcon,\n DeleteIcon,\n} from \"@matops/editor/ui/icons/index\";\n\n/**\n * ImageBubbleMenu\n *\n * Appears when an image is selected. Provides:\n * - Text alignment (left / center / right)\n * - Alt text editing via prompt\n * - Delete image\n *\n * Uses `pluginKey=\"imageMenu\"` to coexist with text + link bubble menus.\n */\nexport function ImageBubbleMenu() {\n const { editor, features, editable } = useEditorContext();\n\n if (!editor || !editable || !features.includes(\"media\")) return null;\n\n const handleSetAlt = () => {\n const current = (editor.getAttributes(\"image\").alt as string) ?? \"\";\n const alt = window.prompt(\"Alt text for this image:\", current);\n if (alt !== null) {\n editor.chain().focus().updateAttributes(\"image\", { alt }).run();\n }\n };\n\n return (\n <BubbleMenu\n editor={editor}\n pluginKey=\"imageMenu\"\n options={{ placement: \"top\", offset: 8 }}\n shouldShow={({ editor: e }) => e.isActive(\"image\") && editable}\n >\n <div\n className=\"mat-bubble-menu\"\n role=\"toolbar\"\n aria-label=\"Image options\"\n onMouseDown={(e) => e.preventDefault()}\n >\n {/* Alignment — only if formatting feature is active */}\n {features.includes(\"formatting\") && (\n <>\n <MenuButton\n onClick={() => editor.chain().focus().setTextAlign(\"left\").run()}\n isActive={editor.isActive({ textAlign: \"left\" })}\n title=\"Align left\"\n >\n <AlignLeftIcon />\n </MenuButton>\n <MenuButton\n onClick={() =>\n editor.chain().focus().setTextAlign(\"center\").run()\n }\n isActive={editor.isActive({ textAlign: \"center\" })}\n title=\"Align center\"\n >\n <AlignCenterIcon />\n </MenuButton>\n <MenuButton\n onClick={() => editor.chain().focus().setTextAlign(\"right\").run()}\n isActive={editor.isActive({ textAlign: \"right\" })}\n title=\"Align right\"\n >\n <AlignRightIcon />\n </MenuButton>\n <MenuDivider />\n </>\n )}\n\n <MenuButton onClick={handleSetAlt} title=\"Edit alt text\">\n <AltTextIcon />\n </MenuButton>\n\n <MenuDivider />\n\n <MenuButton\n onClick={() => editor.chain().focus().deleteSelection().run()}\n isDanger\n title=\"Delete image\"\n >\n <DeleteIcon />\n </MenuButton>\n </div>\n </BubbleMenu>\n );\n}\n","import React from \"react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { FormattingBubbleMenu } from \"@matops/editor/ui/menus/FormattingBubbleMenu\";\nimport { BlockFloatingMenu } from \"@matops/editor/ui/menus/BlockFloatingMenu\";\nimport { SlashMenu } from \"@matops/editor/ui/menus/SlashMenu\";\nimport { TableContextMenu } from \"@matops/editor/ui/menus/TableContextMenu\";\nimport { TableHandles } from \"@matops/editor/ui/menus/TableHandles\";\nimport { TableExtendButtons } from \"@matops/editor/ui/menus/TableExtendButtons\";\nimport { LinkPopover } from \"@matops/editor/ui/menus/LinkPopover\";\nimport { ImageBubbleMenu } from \"@matops/editor/ui/menus/ImageBubbleMenu\";\n\nexport const EditorMenus = React.memo(function EditorMenus() {\n const { featureSet } = useEditorContext();\n\n return (\n <>\n <FormattingBubbleMenu />\n <BlockFloatingMenu />\n <SlashMenu />\n {/* All three table UI components are only mounted when tables feature is active */}\n {featureSet.has(\"tables\") && <TableContextMenu />}\n {featureSet.has(\"tables\") && <TableHandles />}\n {featureSet.has(\"tables\") && <TableExtendButtons />}\n <LinkPopover />\n <ImageBubbleMenu />\n </>\n );\n});\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { JSONContent } from \"@tiptap/core\";\nimport { EditorContent } from \"@tiptap/react\";\n\n// Core\nimport { EditorProvider } from \"@matops/editor/core/context/EditorProvider\";\nimport { EditorThemes, type EditorProps } from \"@matops/editor/core/types\";\n\n// Feature registrations\nimport \"@matops/editor/core/registry/featureBootstrap\";\n\n// Hooks\nimport { useEditorInstance } from \"@matops/editor/utils/hooks/useEditorInstance\";\nimport { useEditorKeyboard } from \"@matops/editor/utils/hooks/useEditorKeyboard\";\nimport { useShortcutsModal } from \"@matops/editor/utils/hooks/useShortcutsModal\";\nimport { useImageUpload } from \"@matops/editor/utils/hooks/useImageUpload\";\n\n// UI\nimport { EditorToolbarWithActions } from \"@matops/editor/ui/toolbar/EditorToolbar\";\nimport { CharacterCountBar } from \"@matops/editor/ui/primitives/CharacterCountBar\";\nimport { KeyboardShortcutsModal } from \"@matops/editor/ui/modals/KeyboardShortcutsModal\";\nimport { FindReplacePanel } from \"@matops/editor/ui/modals/FindReplacePanel\";\nimport { ExportPanel } from \"@matops/editor/ui/modals/ExportPanel\";\nimport { MatopsViewer } from \"@matops/editor/viewer/MatopsViewer\";\n\n// Panels\nimport { CoverImagePanel } from \"@matops/editor/ui/panels/CoverImagePanel\";\nimport { TitlePanel } from \"@matops/editor/ui/panels/TitlePanel\";\nimport { SeparatorIconPanel } from \"@matops/editor/ui/panels/SeparatorIconPanel\";\nimport { AttachmentsPanel } from \"@matops/editor/ui/panels/AttachmentsPanel\";\nimport { toExternalFormat } from \"@matops/editor/utils/helpers/docHelpers\";\nimport {\n DEFAULT_FEATURES,\n DEFAULT_PLACEHOLDER,\n EDITOR_DATA_ATTR,\n THEME_DARK_CLASS,\n THEME_LIGHT_CLASS,\n} from \"@matops/editor/utils/constants\";\nimport { getContentWidth } from \"@matops/editor/extensions/nodes/documentNode\";\nimport { cn } from \"@matops/editor/utils/helpers/cn\";\nimport { EditorMenus } from \"./EditorMenus\";\n\nfunction EditorCore({\n features = DEFAULT_FEATURES,\n initialContent,\n theme = EditorThemes.light,\n editable = true,\n placeholder = DEFAULT_PLACEHOLDER,\n collaborationProvider,\n className,\n onChange,\n onContentChange,\n onPublish,\n onFileUploaded,\n onEditorReady,\n separatorIcon,\n}: EditorProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n const [findOpen, setFindOpen] = useState(false);\n const [exportOpen, setExportOpen] = useState(false);\n\n const {\n open: shortcutsOpen,\n onClose: closeShortcuts,\n setOpen: setShortcutsOpen,\n } = useShortcutsModal();\n\n const [previewMode, setPreviewMode] = useState(false);\n const [previewContent, setPreviewContent] = useState<JSONContent | null>(\n null,\n );\n\n const { editor, resolvedFeatures } = useEditorInstance({\n features,\n initialContent,\n editable,\n placeholder,\n collaborationProvider,\n onChange,\n onContentChange,\n onEditorReady,\n });\n\n useImageUpload({\n editor,\n editable,\n onFileUploaded,\n containerRef: containerRef as React.RefObject<HTMLElement>,\n });\n\n useEditorKeyboard({\n editor,\n editable,\n resolvedFeatures,\n onPublish,\n onOpenFind: () => setFindOpen(true),\n });\n\n const [contentWidth, setContentWidth] = useState(() =>\n getContentWidth(editor),\n );\n\n useEffect(() => {\n if (!editor) return;\n\n const update = () => setContentWidth(getContentWidth(editor));\n\n editor.on(\"update\", update);\n\n return () => {\n editor.off(\"update\", update);\n };\n }, [editor]);\n\n const handleTogglePreview = useCallback(() => {\n if (!editor) return;\n\n setPreviewMode((prev) => {\n const next = !prev;\n\n if (next) {\n setPreviewContent(toExternalFormat(editor.getJSON() as JSONContent));\n }\n\n return next;\n });\n }, [editor]);\n\n const themeClass = theme === \"dark\" ? THEME_DARK_CLASS : THEME_LIGHT_CLASS;\n\n return (\n <EditorProvider\n editor={editor}\n features={resolvedFeatures}\n theme={theme}\n editable={editable}\n onFileUploaded={onFileUploaded}\n separatorIcon={separatorIcon}\n >\n <header\n className={cn(themeClass, \"matops-editor__header\")}\n data-theme={theme}\n >\n <EditorToolbarWithActions\n onOpenFind={\n resolvedFeatures.includes(\"find-replace\")\n ? () => setFindOpen(true)\n : undefined\n }\n onOpenExport={() => setExportOpen(true)}\n onOpenShortcuts={() => setShortcutsOpen((v: boolean) => !v)}\n previewMode={previewMode}\n onTogglePreview={handleTogglePreview}\n />\n\n {resolvedFeatures.includes(\"find-replace\") && (\n <FindReplacePanel\n open={findOpen}\n onClose={() => setFindOpen(false)}\n />\n )}\n </header>\n\n <main\n {...{ [EDITOR_DATA_ATTR]: true }}\n data-content-width={contentWidth}\n className={cn(themeClass, \"matops-editor__body\", className)}\n data-theme={theme}\n >\n {previewMode && previewContent ? (\n <div className=\"matops-editor__preview-panel\">\n <MatopsViewer\n content={previewContent}\n theme={theme}\n separatorIcon={separatorIcon}\n showStats={false}\n />\n </div>\n ) : (\n <div className=\"matops-editor__scroll-inner\">\n <div className=\"matops-editor__page-header\">\n <CoverImagePanel />\n <TitlePanel />\n <SeparatorIconPanel />\n </div>\n\n <div ref={containerRef} className=\"matops-editor__body-panel\">\n <EditorMenus />\n\n <EditorContent\n editor={editor}\n className=\"matops-editor__content\"\n />\n </div>\n\n <div className=\"matops-editor__attachments-panel\">\n <AttachmentsPanel />\n </div>\n </div>\n )}\n\n <KeyboardShortcutsModal open={shortcutsOpen} onClose={closeShortcuts} />\n\n <ExportPanel open={exportOpen} onClose={() => setExportOpen(false)} />\n </main>\n\n {resolvedFeatures.includes(\"character-count\") && (\n <footer\n className={cn(themeClass, \"matops-editor__footer\")}\n data-theme={theme}\n >\n <CharacterCountBar />\n </footer>\n )}\n </EditorProvider>\n );\n}\n\nexport default EditorCore;\n","import { useCallback } from \"react\";\nimport type { JSONContent } from \"@tiptap/core\";\n\n// Core\nimport type { EditorProps } from \"@matops/editor/core/types\";\nimport EditorComposer from \"./EditorComposer\";\n\n\n// Panels\nimport { toExternalFormat } from \"@matops/editor/utils/helpers/docHelpers\";\nimport { DEFAULT_FEATURES } from \"@matops/editor/utils/constants\";\n\nconst EMPTY_DOC: JSONContent = {\n type: \"doc\",\n content: [{ type: \"paragraph\" }],\n};\n\nexport function MatopsEditor(props: EditorProps) {\n const {\n features = DEFAULT_FEATURES,\n initialContent,\n onChange,\n ...rest\n } = props;\n\n const normalizedContent = toExternalFormat(initialContent ?? EMPTY_DOC);\n\n const handleChange = useCallback(\n (json: JSONContent) => {\n onChange?.(json);\n },\n [onChange],\n );\n\n return (\n <EditorComposer\n {...rest}\n features={features}\n initialContent={normalizedContent}\n onChange={handleChange}\n />\n );\n}\n\nexport default MatopsEditor;\n","/**\n * CoverImageView — React NodeView for the `cover-image` Tiptap node.\n *\n * Responsibilities:\n * - Render the cover image with the stored crop applied\n * - Action buttons: Change cover, Crop, Remove\n * - Opens CropModal for interactive crop editing\n * - Empty state: dot-grid placeholder with \"Add cover image\" / drag-drop\n *\n * Design principles:\n * - Zero upload logic: delegates to onFileUploaded, stores URL in node attrs\n * - All persistent data (src, crop) lives in node.attrs — no local state\n * - Crop = percentages stored as cropX/cropY/cropWidth/cropHeight attrs\n */\n\nimport React, { useRef, useState, useCallback } from \"react\";\nimport { NodeViewWrapper } from \"@tiptap/react\";\nimport type { NodeViewProps } from \"@tiptap/react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures } from \"@matops/editor/core/context/editorHooks\";\nimport { CropModal } from \"@matops/editor/ui/modals/CropModal\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n cropToAttrs,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\n\nexport function CoverImageView({ node, updateAttributes }: NodeViewProps) {\n const { editable, onFileUploaded } = useEditorContext();\n const { hasCoverImage } = useFeatures();\n\n // Edit controls are only active when both editable AND cover-image feature is on.\n // When cover-image is disabled the node renders as a static image even in edit mode.\n const canEdit = editable && hasCoverImage;\n\n const src = (node.attrs.src as string | null) ?? null;\n const alt = (node.attrs.alt as string) || \"Cover image\";\n const objectPosition = (node.attrs.objectPosition as string) || \"center 40%\";\n const crop = readCropFromAttrs(node.attrs);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const coverWrapRef = useRef<HTMLDivElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [isUploading, setIsUploading] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [showCrop, setShowCrop] = useState(false);\n const [coverRatio, setCoverRatio] = useState<number | undefined>(undefined);\n\n // ── File handling ──────────────────────────────────────────────────────────\n const handleFile = useCallback(\n async (file: File) => {\n if (!file.type.startsWith(\"image/\")) return;\n setIsUploading(true);\n try {\n if (onFileUploaded) {\n const url = await onFileUploaded(file);\n // Reset crop when a new image is uploaded\n updateAttributes({\n src: url,\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n });\n } else {\n updateAttributes({\n src: URL.createObjectURL(file),\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n });\n }\n } catch (err) {\n console.error(\"[CoverImageView] Upload failed:\", err);\n } finally {\n setIsUploading(false);\n }\n },\n [onFileUploaded, updateAttributes],\n );\n\n const handleFileInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) handleFile(file);\n e.target.value = \"\";\n },\n [handleFile],\n );\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation(); // prevent useImageUpload from also inserting into content\n setIsDragging(false);\n const file = e.dataTransfer.files?.[0];\n if (file) handleFile(file);\n },\n [handleFile],\n );\n\n const handleRemove = useCallback(() => {\n updateAttributes({\n src: null,\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n });\n }, [updateAttributes]);\n\n // ── Open crop — measure the cover display ratio for the aspect lock ──────────\n const openCropModal = useCallback(() => {\n const el = coverWrapRef.current;\n if (el) {\n const { width, height } = el.getBoundingClientRect();\n setCoverRatio(height > 0 ? width / height : undefined);\n }\n setShowCrop(true);\n }, []);\n\n // ── Crop confirm ───────────────────────────────────────────────────────────\n const handleCropConfirm = useCallback(\n (newCrop: import(\"../../core/types\").CropRect) => {\n updateAttributes(cropToAttrs(newCrop));\n setShowCrop(false);\n },\n [updateAttributes],\n );\n\n // ── Image style (applies crop) ─────────────────────────────────────────────\n const imgStyle = computeCropStyle(crop, objectPosition);\n\n // ── Read mode ──────────────────────────────────────────────────────────────\n if (!canEdit) {\n if (!src) return null;\n return (\n <NodeViewWrapper\n as=\"div\"\n className=\"mat-cover mat-cover--has-image\"\n contentEditable={false}\n >\n <img src={src} alt={alt} className=\"mat-cover__img\" style={imgStyle} />\n </NodeViewWrapper>\n );\n }\n\n // ── Edit mode — with cover ─────────────────────────────────────────────────\n if (src) {\n return (\n <>\n <NodeViewWrapper\n as=\"div\"\n ref={coverWrapRef}\n className={`mat-cover mat-cover--has-image${isHovered ? \" mat-cover--hovered\" : \"\"}`}\n contentEditable={false}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onDragOver={(e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }}\n onDragLeave={(e: React.DragEvent) => {\n e.stopPropagation();\n setIsDragging(false);\n }}\n onDrop={handleDrop}\n >\n <img\n src={src}\n alt={alt}\n className=\"mat-cover__img\"\n style={imgStyle}\n />\n\n <div\n className={`mat-cover__actions${isHovered ? \" mat-cover__actions--visible\" : \"\"}`}\n >\n <button\n type=\"button\"\n className=\"mat-cover__btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n >\n {isUploading ? (\n <span className=\"mat-cover__spinner\" />\n ) : (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n )}\n Change\n </button>\n\n <button\n type=\"button\"\n className=\"mat-cover__btn\"\n onClick={openCropModal}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n >\n <path d=\"M6 2v14a2 2 0 0 0 2 2h14\" />\n <path d=\"M18 22V8a2 2 0 0 0-2-2H2\" />\n </svg>\n Crop\n </button>\n\n <button\n type=\"button\"\n className=\"mat-cover__btn mat-cover__btn--danger\"\n onClick={handleRemove}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\" />\n </svg>\n Remove\n </button>\n </div>\n\n {isDragging && (\n <div className=\"mat-cover__drop-overlay\">Drop to replace cover</div>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </NodeViewWrapper>\n\n {showCrop && (\n <CropModal\n src={src}\n initialCrop={crop}\n aspectRatio={coverRatio}\n onConfirm={handleCropConfirm}\n onCancel={() => setShowCrop(false)}\n />\n )}\n </>\n );\n }\n\n // ── Edit mode — empty ──────────────────────────────────────────────────────\n return (\n <NodeViewWrapper\n as=\"div\"\n className={`mat-cover mat-cover--empty${isDragging ? \" mat-cover--dragging\" : \"\"}`}\n contentEditable={false}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onDragOver={(e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }}\n onDragLeave={(e: React.DragEvent) => {\n e.stopPropagation();\n setIsDragging(false);\n }}\n onDrop={handleDrop}\n >\n <div\n className={`mat-cover__empty-inner${isHovered || isDragging ? \" mat-cover__empty-inner--visible\" : \"\"}`}\n >\n {isDragging ? (\n <div className=\"mat-cover__drop-hint\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n Drop image to set cover\n </div>\n ) : (\n <button\n type=\"button\"\n className=\"mat-cover__add-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n >\n {isUploading ? (\n <span className=\"mat-cover__spinner mat-cover__spinner--muted\" />\n ) : (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"17 8 12 3 7 8\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" />\n </svg>\n )}\n Add cover image\n </button>\n )}\n </div>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </NodeViewWrapper>\n );\n}\n","/**\n * CoverImageNode — first-class Tiptap block node for document cover images.\n *\n * Stored in the document JSON as:\n * {\n * type: \"cover-image\",\n * attrs: {\n * src: \"https://...\",\n * alt: \"...\",\n * objectPosition: \"center 40%\",\n * cropX: 0, cropY: 0, cropWidth: 100, cropHeight: 100\n * }\n * }\n *\n * Crop coords are percentages (0–100) of the image size. Default (0,0,100,100)\n * = no crop — falls back to object-fit:cover + objectPosition.\n *\n * In edit mode: CoverImageView (React NodeView) — full interactive UI.\n * In read mode: renderHTML with inline crop styles for generateHTML/EditorViewer.\n *\n * Enabled by: the \"page-header\" feature.\n */\n\nimport { Node, mergeAttributes } from \"@tiptap/core\";\nimport { ReactNodeViewRenderer } from \"@tiptap/react\";\nimport { CoverImageView } from \"@matops/editor/ui/node-views/CoverImageView\";\nimport { computeCropStyleStr, readCropFromAttrs } from \"@matops/editor/utils/helpers/cropHelpers\";\n\nexport const CoverImageNode = Node.create({\n name: \"cover-image\",\n group: \"block\",\n\n atom: true,\n selectable: false,\n draggable: false,\n\n addAttributes() {\n return {\n src: {\n default: null,\n parseHTML: (el) => el.querySelector(\"img\")?.getAttribute(\"src\") ?? null,\n },\n alt: {\n default: \"Cover image\",\n parseHTML: (el) => el.querySelector(\"img\")?.getAttribute(\"alt\") ?? \"Cover image\",\n },\n objectPosition: {\n default: \"center 40%\",\n parseHTML: (el) =>\n (el.querySelector(\"img\") as HTMLImageElement | null)\n ?.style.objectPosition ?? \"center 40%\",\n },\n // Crop attrs — stored as individual numbers so JSON serialisation is clean\n cropX: { default: 0, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-x\") ?? \"0\") },\n cropY: { default: 0, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-y\") ?? \"0\") },\n cropWidth: { default: 100, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-w\") ?? \"100\") },\n cropHeight: { default: 100, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-h\") ?? \"100\") },\n };\n },\n\n parseHTML() {\n return [{ tag: 'div[data-type=\"cover-image\"]' }];\n },\n\n renderHTML({ node }) {\n const { src, alt, objectPosition } = node.attrs as {\n src: string | null;\n alt: string;\n objectPosition: string;\n };\n\n if (!src) {\n return [\n \"div\",\n mergeAttributes({\n \"data-type\": \"cover-image\",\n \"data-empty\": \"true\",\n style: \"display:none;height:0;overflow:hidden\",\n }),\n ];\n }\n\n const crop = readCropFromAttrs(node.attrs);\n const imgStyle = computeCropStyleStr(crop, objectPosition);\n\n return [\n \"div\",\n mergeAttributes({\n \"data-type\": \"cover-image\",\n \"data-crop-x\": String(crop.x),\n \"data-crop-y\": String(crop.y),\n \"data-crop-w\": String(crop.width),\n \"data-crop-h\": String(crop.height),\n class: \"mat-cover mat-cover--has-image\",\n style: \"position:relative;overflow:hidden;\",\n }),\n [\n \"img\",\n {\n src,\n alt,\n class: \"mat-cover__img\",\n style: imgStyle,\n loading: \"lazy\",\n },\n ],\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(CoverImageView);\n },\n});\n","/**\n * TitleView — React NodeView for the `title` Tiptap node.\n *\n * Renders only the document title. The separator between the title and body\n * is handled by the `separator-icon` node (SeparatorIconView), which sits\n * immediately after the title in the document content array.\n *\n * Design principles:\n * - Tiptap owns the text via NodeViewContent — no controlled inputs needed.\n * - Placeholder is an absolutely-positioned overlay shown when title is empty.\n * - Read mode: renders as a semantic <h1>.\n */\n\nimport React, { useCallback } from \"react\";\nimport { NodeViewWrapper, NodeViewContent } from \"@tiptap/react\";\nimport type { NodeViewProps } from \"@tiptap/react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures } from \"@matops/editor/core/context/editorHooks\";\n\nexport function TitleView({ node }: NodeViewProps) {\n const { editable } = useEditorContext();\n const { hasPageHeader } = useFeatures();\n\n const canEdit = editable && hasPageHeader;\n\n const placeholder = (node.attrs.placeholder as string) || \"Untitled\";\n const isEmpty = node.textContent.length === 0;\n\n // Block all drag events — the title accepts text only. Without this, an image\n // dragged over the title bubbles up to useImageUpload and gets inserted into\n // the document body. stopPropagation + preventDefault kills both behaviours.\n const blockDrag = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n if (!canEdit) {\n return (\n <NodeViewWrapper as=\"div\" className=\"mat-page-title-wrap\">\n <h1 className=\"mat-page-title mat-page-title--readonly\">\n <NodeViewContent as=\"div\" />\n </h1>\n </NodeViewWrapper>\n );\n }\n\n return (\n <NodeViewWrapper\n as=\"div\"\n className=\"mat-page-title-wrap\"\n onDragOver={blockDrag}\n onDragEnter={blockDrag}\n onDragLeave={blockDrag}\n onDrop={blockDrag}\n >\n <div className=\"mat-page-title-editable-wrap\">\n {isEmpty && (\n <div className=\"mat-page-title__placeholder\" aria-hidden=\"true\">\n {placeholder}\n </div>\n )}\n <NodeViewContent\n as=\"div\"\n className=\"mat-page-title mat-page-title--editable\"\n />\n </div>\n </NodeViewWrapper>\n );\n}\n","/**\n * TitleNode — first-class Tiptap block node for document titles.\n *\n * Stored in the document JSON as:\n * { type: \"title\", content: [{ type: \"text\", text: \"My Document\" }] }\n *\n * In edit mode: renders a large auto-resizing title input via TitleView (React\n * NodeView). Pressing Enter moves focus to the next block.\n *\n * In read mode: renders as a semantic <h1> for clean HTML output.\n *\n * Enabled by: the \"page-header\" feature.\n */\n\nimport { Node, mergeAttributes } from \"@tiptap/core\";\nimport { ReactNodeViewRenderer } from \"@tiptap/react\";\nimport { TitleView } from \"@matops/editor/ui/node-views/TitleView\";\n\nexport const TitleNode = Node.create({\n name: \"title\",\n group: \"block\",\n\n // Title contains inline text (same as paragraph)\n content: \"inline*\",\n\n // isolating: true prevents the cursor from \"escaping\" the title node\n // upward into (and merging with) the cover-image node via Backspace.\n isolating: true,\n\n addAttributes() {\n return {\n placeholder: {\n default: \"Untitled\",\n parseHTML: (el) => el.getAttribute(\"data-placeholder\") ?? \"Untitled\",\n renderHTML: (attrs) => ({\n \"data-placeholder\": attrs.placeholder as string,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n { tag: 'h1[data-type=\"title\"]' },\n { tag: 'div[data-type=\"title\"]' },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n // Render as an h1 for semantic HTML (viewer / generateHTML / export)\n return [\n \"h1\",\n mergeAttributes(\n {\n \"data-type\": \"title\",\n class: \"mat-page-title mat-page-title--readonly\",\n },\n HTMLAttributes,\n ),\n // 0 = content hole (renders child text nodes)\n 0,\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(TitleView);\n },\n\n // ── Keyboard behaviour ──────────────────────────────────────────\n addKeyboardShortcuts() {\n return {\n // Move focus to next block on Enter (don't split the title node)\n Enter: ({ editor }) => {\n const { $from } = editor.state.selection;\n if ($from.parent.type.name !== \"title\") return false;\n\n return editor.commands.command(({ tr, state, dispatch }) => {\n const titleEnd = $from.end($from.depth);\n const afterTitle = titleEnd + 1;\n\n if (afterTitle <= state.doc.content.size) {\n if (dispatch) {\n tr.setSelection(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (state.selection.constructor as any).near(\n state.doc.resolve(afterTitle),\n ),\n );\n dispatch(tr);\n }\n editor.view.focus();\n return true;\n }\n return false;\n });\n },\n\n // Backspace at the very start of the title — do nothing (isolating\n // already prevents merging upward; this is an extra safety net).\n Backspace: ({ editor }) => {\n const { $from, empty } = editor.state.selection;\n if ($from.parent.type.name !== \"title\") return false;\n // Only intercept when cursor is at position 0 inside the title\n if (empty && $from.parentOffset === 0) return true; // swallow\n return false;\n },\n\n // Delete at the very end of the title — prevent jumping into / deleting\n // the separator-icon node that follows.\n Delete: ({ editor }) => {\n const { $from, empty } = editor.state.selection;\n if ($from.parent.type.name !== \"title\") return false;\n if (empty && $from.parentOffset === $from.parent.content.size)\n return true; // swallow\n return false;\n },\n };\n },\n});\n","/**\n * SeparatorIconView — React NodeView for the `separator-icon` Tiptap node.\n *\n * Renders: ────── [badge] ──────\n *\n * Icon resolution priority:\n * 1. node.attrs.src + crop → uploaded image, cropped\n * 2. separatorIcon prop (ReactNode)\n * 3. Default quill SVG\n *\n * Edit mode: always-visible action bar below the separator.\n * • No image: \"⊕ Upload icon\" pill\n * • Image set: thumbnail label + \"Crop\" + \"Change\" + \"Remove\" buttons\n *\n * Crop is always 1:1 (square) enforced by CropModal aspectRatio={1}.\n */\n\nimport React, { useRef, useState, useCallback } from \"react\";\nimport { NodeViewWrapper } from \"@tiptap/react\";\nimport type { NodeViewProps } from \"@tiptap/react\";\nimport { useEditorContext } from \"@matops/editor/core/context/EditorProvider\";\nimport { useFeatures } from \"@matops/editor/core/context/editorHooks\";\nimport { CropModal } from \"@matops/editor/ui/modals/CropModal\";\nimport {\n computeCropStyle,\n readCropFromAttrs,\n cropToAttrs,\n} from \"@matops/editor/utils/helpers/cropHelpers\";\n\nimport { DefaultSeparatorIcon, UploadIcon } from \"@matops/editor/ui/icons/index\";\n\nfunction Spinner() {\n return <span className=\"mat-cover__spinner mat-cover__spinner--muted\" />;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\nexport function SeparatorIconView({ node, updateAttributes }: NodeViewProps) {\n const { editable, onFileUploaded, separatorIcon } = useEditorContext();\n const { hasPageHeader } = useFeatures();\n\n // Edit controls only when both editable AND page-header feature is active.\n const canEdit = editable && hasPageHeader;\n\n const src = (node.attrs.src as string | null) ?? null;\n const alt = (node.attrs.alt as string) || \"Section separator\";\n const crop = readCropFromAttrs(node.attrs);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [isUploading, setIsUploading] = useState(false);\n const [showCrop, setShowCrop] = useState(false);\n\n // ── File handling ──────────────────────────────────────────────────────────\n const handleFile = useCallback(\n async (file: File) => {\n if (!file.type.startsWith(\"image/\")) return;\n setIsUploading(true);\n try {\n const url = onFileUploaded\n ? await onFileUploaded(file)\n : URL.createObjectURL(file);\n // Reset crop when new image is uploaded\n updateAttributes({\n src: url,\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n });\n } catch (err) {\n console.error(\"[SeparatorIconView] Upload failed:\", err);\n } finally {\n setIsUploading(false);\n }\n },\n [onFileUploaded, updateAttributes],\n );\n\n const handleFileInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) handleFile(file);\n e.target.value = \"\";\n },\n [handleFile],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(true);\n }, []);\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.stopPropagation();\n if (!e.currentTarget.contains(e.relatedTarget as Node))\n setIsDragging(false);\n }, []);\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n const file = e.dataTransfer.files?.[0];\n if (file) handleFile(file);\n },\n [handleFile],\n );\n\n const openFilePicker = useCallback(() => fileInputRef.current?.click(), []);\n const removeSrc = useCallback(\n () =>\n updateAttributes({\n src: null,\n cropX: 0,\n cropY: 0,\n cropWidth: 100,\n cropHeight: 100,\n }),\n [updateAttributes],\n );\n\n const handleCropConfirm = useCallback(\n (newCrop: import(\"../../core/types\").CropRect) => {\n updateAttributes(cropToAttrs(newCrop));\n setShowCrop(false);\n },\n [updateAttributes],\n );\n\n // ── Resolve badge content ──────────────────────────────────────────────────\n // The image is wrapped in an explicit crop-viewport span that owns\n // position:relative + overflow:hidden + border-radius:50% as inline styles.\n //\n // The outer badge span is display:flex. In some rendering contexts (notably\n // inside Tiptap NodeViews), overflow:hidden on a flex container does not\n // reliably clip position:absolute children. An inner block-level containing\n // block makes the crop self-contained regardless of the outer flex context.\n // The inner span uses position:absolute + inset:0 so it always fills exactly\n // the 22×22 badge regardless of whether the parent is flex (NodeView) or not.\n // width/height \"100%\" fails in flex NodeViews; inset:0 always resolves correctly.\n const badgeContent = isUploading ? (\n <Spinner />\n ) : src ? (\n <span\n style={{\n position: \"absolute\",\n inset: 0,\n overflow: \"hidden\",\n borderRadius: \"50%\",\n }}\n >\n <img src={src} alt={alt} style={computeCropStyle(crop)} />\n </span>\n ) : (\n (separatorIcon ?? <DefaultSeparatorIcon />)\n );\n\n // ── Read mode ──────────────────────────────────────────────────────────────\n if (!canEdit) {\n return (\n <NodeViewWrapper\n as=\"div\"\n className=\"mat-title-separator\"\n aria-hidden=\"true\"\n >\n <span className=\"mat-title-separator__line\" />\n <span\n className={`mat-title-separator__icon${src ? \" mat-title-separator__icon--img\" : \"\"}`}\n >\n {badgeContent}\n </span>\n <span className=\"mat-title-separator__line\" />\n </NodeViewWrapper>\n );\n }\n\n // ── Edit mode ──────────────────────────────────────────────────────────────\n return (\n <>\n <NodeViewWrapper\n as=\"div\"\n className={[\n \"mat-title-separator\",\n \"mat-title-separator--editable\",\n isDragging ? \"mat-title-separator--dragging\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n aria-hidden=\"true\"\n >\n {/* Separator row */}\n <span className=\"mat-title-separator__line\" />\n <span\n className={`mat-title-separator__icon mat-title-separator__icon--editable${src ? \" mat-title-separator__icon--img\" : \"\"}`}\n >\n {badgeContent}\n </span>\n <span className=\"mat-title-separator__line\" />\n\n {/* Always-visible action bar */}\n <span className=\"mat-sep-action-bar\">\n {src ? (\n <>\n <span className=\"mat-sep-action-bar__label mat-sep-action-bar__label--set\">\n <img\n src={src}\n alt=\"\"\n className=\"mat-sep-action-bar__thumb\"\n aria-hidden=\"true\"\n />\n Custom icon\n </span>\n <button\n className=\"mat-sep-action-bar__btn\"\n onClick={() => setShowCrop(true)}\n type=\"button\"\n title=\"Crop icon image\"\n >\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 2v14a2 2 0 0 0 2 2h14\" />\n <path d=\"M18 22V8a2 2 0 0 0-2-2H2\" />\n </svg>\n Crop\n </button>\n <button\n className=\"mat-sep-action-bar__btn\"\n onClick={openFilePicker}\n type=\"button\"\n title=\"Change icon image\"\n >\n Change\n </button>\n <button\n className=\"mat-sep-action-bar__btn mat-sep-action-bar__btn--danger\"\n onClick={removeSrc}\n type=\"button\"\n title=\"Remove icon image\"\n >\n Remove\n </button>\n </>\n ) : (\n <button\n className=\"mat-sep-action-bar__upload-pill\"\n onClick={openFilePicker}\n type=\"button\"\n title=\"Upload a custom icon for the separator\"\n >\n <UploadIcon />\n Upload icon\n </button>\n )}\n </span>\n\n {isDragging && (\n <span className=\"mat-sep-drop-overlay\">Drop image here</span>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={handleFileInput}\n />\n </NodeViewWrapper>\n\n {showCrop && src && (\n <CropModal\n src={src}\n initialCrop={crop}\n aspectRatio={1} // always 1:1 for the circular badge\n onConfirm={handleCropConfirm}\n onCancel={() => setShowCrop(false)}\n />\n )}\n </>\n );\n}\n","/**\n * SeparatorIconNode — first-class Tiptap block node for the title/body separator.\n *\n * Stored in the document JSON as:\n * { type: \"separator-icon\", attrs: { src: \"https://...\" | null, alt: \"...\" } }\n *\n * This node IS the separator — it renders the full:\n * ────── [icon badge] ──────\n * structure between the title and body content.\n *\n * Icon resolution priority (highest → lowest):\n * 1. src attr (user uploaded an image into the badge)\n * 2. separatorIcon prop on <Editor> / <EditorViewer> (ReactNode)\n * 3. Default quill SVG icon\n *\n * In edit mode → SeparatorIconView (interactive upload / remove)\n * In view mode → EditorViewer renders it as React for full icon support;\n * renderHTML is a structural fallback for raw generateHTML usage.\n *\n * Enabled by: the \"page-header\" feature.\n */\n\nimport { Node, mergeAttributes } from \"@tiptap/core\";\nimport { ReactNodeViewRenderer } from \"@tiptap/react\";\nimport { SeparatorIconView } from \"@matops/editor/ui/node-views/SeparatorIconView\";\nimport { computeCropStyleStr, readCropFromAttrs } from \"@matops/editor/utils/helpers/cropHelpers\";\n\nexport const SeparatorIconNode = Node.create({\n name: \"separator-icon\",\n group: \"block\",\n\n atom: true,\n selectable: false, // Cannot enter NodeSelection → cannot be deleted as a unit\n draggable: false,\n isolating: true, // Cursor cannot escape into this node from adjacent nodes\n\n addAttributes() {\n return {\n src: {\n default: null,\n parseHTML: (el) =>\n el.querySelector(\"img.mat-separator-icon__img\")?.getAttribute(\"src\") ?? null,\n },\n alt: {\n default: \"Section separator\",\n parseHTML: (el) =>\n el.querySelector(\"img.mat-separator-icon__img\")?.getAttribute(\"alt\") ??\n \"Section separator\",\n },\n // Crop attrs (1:1 square enforced by CropModal aspectRatio=1)\n cropX: { default: 0, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-x\") ?? \"0\") },\n cropY: { default: 0, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-y\") ?? \"0\") },\n cropWidth: { default: 100, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-w\") ?? \"100\") },\n cropHeight: { default: 100, parseHTML: (el) => parseFloat(el.getAttribute(\"data-crop-h\") ?? \"100\") },\n };\n },\n\n parseHTML() {\n return [{ tag: 'div[data-type=\"separator-icon\"]' }];\n },\n\n renderHTML({ node }) {\n const { src, alt } = node.attrs as { src: string | null; alt: string };\n\n const crop = readCropFromAttrs(node.attrs);\n const imgStyle = computeCropStyleStr(crop);\n\n // Badge inner: <img> with crop styles if src, otherwise default quill SVG\n const badgeInner = src\n ? [\n \"img\",\n {\n src,\n alt,\n class: \"mat-separator-icon__img\",\n loading: \"lazy\",\n style: imgStyle,\n },\n ]\n : [\n \"svg\",\n {\n width: \"10\", height: \"10\", viewBox: \"0 0 24 24\",\n fill: \"none\", stroke: \"currentColor\",\n \"stroke-width\": \"2.2\", \"stroke-linecap\": \"round\", \"stroke-linejoin\": \"round\",\n \"aria-hidden\": \"true\",\n },\n [\"path\", { d: \"M20 2L2 22\" }],\n [\"path\", { d: \"M2 2c0 0 10 0 18 8\" }],\n ];\n\n return [\n \"div\",\n mergeAttributes({\n \"data-type\": \"separator-icon\",\n ...(src ? {\n \"data-src\": src,\n \"data-crop-x\": String(crop.x),\n \"data-crop-y\": String(crop.y),\n \"data-crop-w\": String(crop.width),\n \"data-crop-h\": String(crop.height),\n } : {}),\n \"aria-hidden\": \"true\",\n class: \"mat-title-separator\",\n }),\n [\"span\", { class: \"mat-title-separator__line\" }],\n [\n \"span\",\n {\n class: \"mat-title-separator__icon\",\n // Badge needs overflow:hidden + relative for crop to work\n ...(src ? { style: \"position:relative;overflow:hidden;\" } : {}),\n },\n badgeInner,\n ],\n [\"span\", { class: \"mat-title-separator__line\" }],\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(SeparatorIconView);\n },\n\n // ── Keyboard guards ──────────────────────────────────────────────────────\n // The filterTransaction plugin is the primary defence. These handlers are a\n // second layer that prevent the cursor from ever sitting at a position where\n // a single Delete/Backspace keystroke would target the separator-icon node.\n addKeyboardShortcuts() {\n return {\n // Backspace when cursor is at the very start of a block that immediately\n // follows the separator-icon — block the join-backward attempt.\n Backspace: ({ editor }) => {\n const { $from, empty } = editor.state.selection;\n if (!empty || $from.parentOffset !== 0) return false;\n\n // Check if the node immediately before the current block is separator-icon\n const nodeBefore = $from.node($from.depth - 1)\n ? editor.state.doc.resolve(\n Math.max(0, $from.before($from.depth) - 1)\n ).nodeBefore\n : null;\n\n if (nodeBefore?.type.name === \"separator-icon\") return true; // swallow\n return false;\n },\n\n // Delete when cursor is at the very end of the title block (which sits\n // directly before the separator-icon) — block the forward-delete.\n Delete: ({ editor }) => {\n const { $from, empty } = editor.state.selection;\n if (!empty) return false;\n if ($from.parent.type.name !== \"title\") return false;\n if ($from.parentOffset === $from.parent.content.size) return true; // swallow\n return false;\n },\n };\n },\n});\n"],"names":["createContext","useMemo","jsx","useContext","extensions","UndoRedo","CharacterCount","PluginKey","DecorationSet","Decoration","Extension","Plugin","state","TableKit","ListKit","TextStyleKit","lowlight","createLowlight","common","TaskList","TaskItem","Placeholder","useRef","useEffect","useTiptapEditor","useState","useCallback","jsxs","twMerge","clsx","_","useLayoutEffect","createPortal","Fragment","words","chars","paragraphs","_a","BottomSeparator","NodeViewWrapper","Node","mergeAttributes","ReactNodeViewRenderer","generateHTML","coverAttr","titleAttr","sepIconSrc","attachItems","contentWidth","sepIconCrop","sepIconAlt","Spinner","BubbleMenu","FloatingMenu","TextSelection","EditorMenus","EditorContent","EditorComposer","NodeViewContent"],"mappings":"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"}
|