@inkbrick/react 0.0.0-stage → 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/FormulaPalette-WFRPRHS5.js +320 -0
  2. package/dist/FormulaPalette-WFRPRHS5.js.map +1 -0
  3. package/dist/chunk-TPUX4C45.js +2309 -0
  4. package/dist/chunk-TPUX4C45.js.map +1 -0
  5. package/dist/index.d.ts +1431 -0
  6. package/dist/index.js +4880 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/mathCss-FLPE6QBM.js +361 -0
  9. package/dist/mathCss-FLPE6QBM.js.map +1 -0
  10. package/package.json +46 -3
  11. package/src/block-handle/BlockHandleController.ts +93 -0
  12. package/src/block-handle/BlockHandleHost.tsx +108 -0
  13. package/src/block-handle/DefaultBlockHandle.tsx +71 -0
  14. package/src/block-handle/DefaultBlockMenu.tsx +114 -0
  15. package/src/block-handle/DropIndicatorHost.tsx +58 -0
  16. package/src/block-handle/actions.tsx +146 -0
  17. package/src/block-handle/blockDrag.ts +215 -0
  18. package/src/block-handle/geometry.ts +64 -0
  19. package/src/block-handle/gripGesture.ts +108 -0
  20. package/src/block-handle/types.ts +65 -0
  21. package/src/block-handle/useBlockDrag.ts +21 -0
  22. package/src/block-handle/useBlockHandles.ts +125 -0
  23. package/src/blocks/BlockChildren.tsx +17 -0
  24. package/src/blocks/BlockProps.ts +5 -0
  25. package/src/blocks/CalloutBlock.tsx +61 -0
  26. package/src/blocks/CodeBlock.tsx +96 -0
  27. package/src/blocks/DividerBlock.tsx +15 -0
  28. package/src/blocks/Editable.tsx +84 -0
  29. package/src/blocks/FormulaBlock.tsx +173 -0
  30. package/src/blocks/HeadingBlock.tsx +22 -0
  31. package/src/blocks/ImageBlock.tsx +362 -0
  32. package/src/blocks/ListBlock.tsx +86 -0
  33. package/src/blocks/NoteBlock.tsx +10 -0
  34. package/src/blocks/PageBlock.tsx +10 -0
  35. package/src/blocks/ParagraphBlock.tsx +20 -0
  36. package/src/blocks/QuoteBlock.tsx +18 -0
  37. package/src/blocks/UnknownBlockView.tsx +27 -0
  38. package/src/blocks/defineBlock.ts +49 -0
  39. package/src/clipboard/html/blocks.ts +379 -0
  40. package/src/clipboard/html/inline.ts +92 -0
  41. package/src/clipboard/html/style.ts +92 -0
  42. package/src/clipboard/html/tags.ts +77 -0
  43. package/src/clipboard/htmlToFragment.ts +41 -0
  44. package/src/clipboard/useClipboard.ts +296 -0
  45. package/src/code/highlight.ts +56 -0
  46. package/src/code/languages.ts +236 -0
  47. package/src/code/scan/css.ts +164 -0
  48. package/src/code/scan/generic.ts +328 -0
  49. package/src/code/scan/html.ts +129 -0
  50. package/src/code/scan/markdown.ts +58 -0
  51. package/src/code/scan/shared.ts +81 -0
  52. package/src/code/scan/yaml.ts +34 -0
  53. package/src/code/types.ts +34 -0
  54. package/src/context/EditorContext.ts +9 -0
  55. package/src/context/EditorProvider.tsx +172 -0
  56. package/src/controllers/adapters.tsx +63 -0
  57. package/src/editing/BlockSelectionController.ts +27 -0
  58. package/src/editing/CaretController.ts +27 -0
  59. package/src/editing/EditorView.ts +108 -0
  60. package/src/editing/ViewportController.ts +63 -0
  61. package/src/editing/beforeInput.ts +276 -0
  62. package/src/editing/deleteAtBoundary.ts +16 -0
  63. package/src/editing/inputActions.ts +109 -0
  64. package/src/editing/renderCode.ts +69 -0
  65. package/src/editing/renderInline.ts +144 -0
  66. package/src/editing/selection.ts +262 -0
  67. package/src/editing/useEditorInput.ts +223 -0
  68. package/src/editing/useSelectionState.ts +46 -0
  69. package/src/formula/FormulaController.ts +51 -0
  70. package/src/formula/FormulaPalette.tsx +79 -0
  71. package/src/formula/FormulaPopover.tsx +181 -0
  72. package/src/formula/LazyFormulaPalette.tsx +42 -0
  73. package/src/formula/actions.ts +138 -0
  74. package/src/formula/snippet.ts +70 -0
  75. package/src/formula/symbols.ts +264 -0
  76. package/src/hooks/useBlock.ts +21 -0
  77. package/src/hooks/useBlockController.ts +30 -0
  78. package/src/hooks/useChildren.ts +16 -0
  79. package/src/hooks/useDocument.ts +16 -0
  80. package/src/hooks/useEditor.ts +13 -0
  81. package/src/hooks/useEditorView.ts +13 -0
  82. package/src/hooks/useHistory.ts +46 -0
  83. package/src/hooks/useReadOnly.ts +21 -0
  84. package/src/hooks/useT.ts +10 -0
  85. package/src/i18n/en.ts +182 -0
  86. package/src/i18n/ru.ts +174 -0
  87. package/src/i18n/translate.ts +77 -0
  88. package/src/icons/ICONS_LICENSE.md +50 -0
  89. package/src/icons/Icon.tsx +41 -0
  90. package/src/icons/lucide.ts +234 -0
  91. package/src/images/ImageError.ts +39 -0
  92. package/src/images/UploadTracker.ts +49 -0
  93. package/src/images/insertImages.ts +142 -0
  94. package/src/images/types.ts +22 -0
  95. package/src/images/upload.ts +62 -0
  96. package/src/index.ts +102 -0
  97. package/src/keymap/defaultKeymap.ts +189 -0
  98. package/src/keymap/keymap.ts +42 -0
  99. package/src/keymap/shortcut.ts +105 -0
  100. package/src/keymap/types.ts +40 -0
  101. package/src/math/FormulaView.tsx +62 -0
  102. package/src/math/mathCss.ts +4 -0
  103. package/src/math/renderer.ts +198 -0
  104. package/src/registry/defaultBlockComponents.ts +26 -0
  105. package/src/registry/resolveBlockComponent.ts +14 -0
  106. package/src/renderer/BlockRenderer.tsx +63 -0
  107. package/src/renderer/DocumentRenderer.tsx +33 -0
  108. package/src/renderer/DocumentView.tsx +94 -0
  109. package/src/renderer/virtual/VirtualChildList.tsx +355 -0
  110. package/src/renderer/virtual/estimate.ts +62 -0
  111. package/src/renderer/virtual/virtualRenderer.tsx +35 -0
  112. package/src/slash/DefaultSlashMenu.tsx +119 -0
  113. package/src/slash/SlashMenuController.ts +66 -0
  114. package/src/slash/SlashMenuHost.tsx +48 -0
  115. package/src/slash/applySlashItem.ts +57 -0
  116. package/src/slash/defaultSlashItems.tsx +186 -0
  117. package/src/slash/filter.ts +29 -0
  118. package/src/slash/items.ts +30 -0
  119. package/src/slash/syncSlashMenu.ts +67 -0
  120. package/src/slash/types.ts +21 -0
  121. package/src/toolbar/DefaultToolbar.tsx +281 -0
  122. package/src/toolbar/ToolbarController.ts +100 -0
  123. package/src/toolbar/ToolbarHost.tsx +81 -0
  124. package/src/toolbar/formatting.ts +75 -0
  125. package/src/toolbar/rich.ts +58 -0
  126. package/src/toolbar/syncToolbar.ts +39 -0
  127. package/src/toolbar/types.ts +21 -0
  128. package/src/ui/EditorUIContext.ts +26 -0
  129. package/src/ui/presentation.ts +24 -0
  130. package/src/ui/types.ts +70 -0
  131. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context/EditorContext.ts","../src/context/EditorProvider.tsx","../src/block-handle/BlockHandleController.ts","../src/images/UploadTracker.ts","../src/editing/BlockSelectionController.ts","../src/formula/FormulaController.ts","../src/editing/CaretController.ts","../src/slash/SlashMenuController.ts","../src/toolbar/ToolbarController.ts","../src/editing/ViewportController.ts","../src/editing/EditorView.ts","../src/keymap/shortcut.ts","../src/keymap/keymap.ts","../src/blocks/defineBlock.ts","../src/controllers/adapters.tsx","../src/ui/presentation.ts","../src/hooks/useEditor.ts","../src/hooks/useEditorView.ts","../src/hooks/useDocument.ts","../src/hooks/useBlock.ts","../src/hooks/useChildren.ts","../src/hooks/useHistory.ts","../src/hooks/useReadOnly.ts","../src/hooks/useBlockController.ts","../src/clipboard/htmlToFragment.ts","../src/clipboard/html/blocks.ts","../src/clipboard/html/inline.ts","../src/clipboard/html/style.ts","../src/clipboard/html/tags.ts","../src/images/upload.ts","../src/images/ImageError.ts","../src/images/types.ts","../src/blocks/BlockChildren.tsx","../src/renderer/DocumentRenderer.tsx","../src/renderer/BlockRenderer.tsx","../src/blocks/UnknownBlockView.tsx","../src/blocks/PageBlock.tsx","../src/blocks/NoteBlock.tsx","../src/blocks/ParagraphBlock.tsx","../src/blocks/Editable.tsx","../src/editing/renderCode.ts","../src/editing/renderInline.ts","../src/blocks/HeadingBlock.tsx","../src/blocks/ListBlock.tsx","../src/blocks/QuoteBlock.tsx","../src/blocks/CodeBlock.tsx","../src/blocks/DividerBlock.tsx","../src/blocks/CalloutBlock.tsx","../src/blocks/ImageBlock.tsx","../src/images/insertImages.ts","../src/blocks/FormulaBlock.tsx","../src/formula/LazyFormulaPalette.tsx","../src/math/FormulaView.tsx","../src/registry/defaultBlockComponents.ts","../src/registry/resolveBlockComponent.ts","../src/renderer/DocumentView.tsx","../src/block-handle/BlockHandleHost.tsx","../src/block-handle/actions.tsx","../src/slash/syncSlashMenu.ts","../src/block-handle/DefaultBlockHandle.tsx","../src/block-handle/DefaultBlockMenu.tsx","../src/block-handle/gripGesture.ts","../src/block-handle/useBlockDrag.ts","../src/block-handle/blockDrag.ts","../src/block-handle/geometry.ts","../src/block-handle/DropIndicatorHost.tsx","../src/clipboard/useClipboard.ts","../src/editing/inputActions.ts","../src/block-handle/useBlockHandles.ts","../src/editing/useEditorInput.ts","../src/editing/beforeInput.ts","../src/editing/useSelectionState.ts","../src/formula/FormulaPopover.tsx","../src/slash/SlashMenuHost.tsx","../src/slash/DefaultSlashMenu.tsx","../src/toolbar/ToolbarHost.tsx","../src/toolbar/DefaultToolbar.tsx","../src/renderer/virtual/estimate.ts","../src/renderer/virtual/VirtualChildList.tsx","../src/renderer/virtual/virtualRenderer.tsx"],"sourcesContent":["import { createContext } from 'react';\n\nimport type { Editor } from '@inkbrick/engine';\n\nimport type { EditorView } from '../editing/EditorView';\n\nexport const EditorContext = createContext<Editor | null>(null);\n\nexport const EditorViewContext = createContext<EditorView | null>(null);\n","import { useLayoutEffect, useMemo, type ReactNode } from 'react';\n\nimport type { Editor } from '@inkbrick/engine';\n\nimport { EditorView } from '../editing/EditorView';\nimport { highlightCode } from '../code/highlight';\nimport type { CodeHighlighter } from '../code/types';\nimport { createTranslator, resolveMessages } from '../i18n/translate';\nimport { temmlRenderer, type FormulaRenderer } from '../math/renderer';\nimport type { PartialMessages } from '../i18n/en';\nimport { resolveKeymap } from '../keymap/keymap';\nimport type { KeyBinding } from '../keymap/types';\nimport { resolveSlashItems } from '../slash/defaultSlashItems';\nimport type { ImageOptions } from '../images/types';\nimport type { SlashMenuItem } from '../slash/types';\nimport { EditorUIContext } from '../ui/EditorUIContext';\nimport type { EditorPresentation } from '../ui/presentation';\nimport type { BlockComponentRegistry, EditorSlots } from '../ui/types';\nimport { EditorContext, EditorViewContext } from './EditorContext';\nimport { blockComponentsOf, type ReactBlockDefinition } from '../blocks/defineBlock';\nimport { controllerKeymap, controllerSlashItems, mergeById } from '../controllers/adapters';\n\nexport interface EditorProviderProps {\n readonly editor: Editor;\n readonly children: ReactNode;\n /**\n * Визуальный слой одним объектом (дизайн-система): представления блоков, оболочка, slash-меню, подсветка кода\n * и формулы — см. `definePresentation`. Отдельные props ниже уточняют его. Держите объект стабильным.\n */\n readonly presentation?: EditorPresentation;\n /**\n * Пользовательские блоки из `defineBlock`: их компоненты добавляются к `components` (prop `components`\n * с тем же flavour важнее). Схемы и контроллеры этих блоков передайте и в `new Editor({ blocks })`:\n * пункты slash-меню, меню блока и клавиши берутся из контроллеров редактора. Держите массив стабильным.\n */\n readonly blocks?: readonly ReactBlockDefinition<any>[];\n /**\n * Свои React-представления блоков: `{ 'block:paragraph': MyParagraph }`.\n * Не указанные flavour используют стандартные компоненты Inkbrick.\n * Чтобы не перерисовывать документ без необходимости, держите объект стабильным\n * (вынесите из компонента или оберните в useMemo).\n */\n readonly components?: BlockComponentRegistry;\n readonly slots?: EditorSlots;\n /**\n * Пункты slash-меню. Дополняют стандартные (одинаковый `id` заменяет стандартный пункт);\n * `false` выключает меню. Держите массив стабильным (вынесите из компонента или useMemo).\n */\n readonly slashItems?: readonly SlashMenuItem[] | false;\n /**\n * Подсветка синтаксиса в блоках кода. По умолчанию — встроенный `highlightCode` (без зависимостей);\n * свой подсветчик (Shiki, Prism, highlight.js) — функция `(code, language) => токены`; `false` выключает подсветку.\n * Держите функцию стабильной: смена функции перерисовывает все блоки кода.\n */\n readonly highlighter?: CodeHighlighter | false;\n /**\n * Отрисовка формул (блоки и встроенные): по умолчанию Temml → MathML, подгружается при первой формуле.\n * Свой подсчётчик (KaTeX, MathJax) — функция `(latex, target, { display }) => void | Promise<void>`;\n * `false` — показывать только исходный код. Держите функцию стабильной: её смена перерисовывает все формулы.\n */\n readonly formulaRenderer?: FormulaRenderer | false;\n /**\n * Язык интерфейса: код подключённого словаря (`'en'`, `'ru'` или свой, см. `registerLocale` и `locales`).\n * `'pt-BR'` без своего словаря возьмёт `'pt'`; неизвестный код — английский. По умолчанию `'en'`.\n */\n readonly locale?: string;\n /**\n * Словари, подключаемые только к этому редактору: `{ de: { 'menu.delete': 'Löschen', … } }`.\n * Словарь может быть неполным — недостающее берётся из английского. Держите объект стабильным.\n */\n readonly locales?: Readonly<Record<string, PartialMessages>>;\n /** Точечные замены строк поверх выбранного языка: `{ 'menu.delete': 'Убрать' }`. Держите объект стабильным. */\n readonly messages?: PartialMessages;\n /**\n * Свои привязки клавиш. Привязка с `id` стандартной (`'undo'`, `'format.bold'`, `'indent'`, …) заменяет её,\n * новая проверяется раньше стандартных; `unbind('id')` отключает стандартную. Держите массив стабильным.\n */\n readonly keymap?: readonly KeyBinding[];\n /**\n * Режим только чтения: ввод, команды, undo, toolbar, ручки блоков и slash-меню отключены,\n * выделение и копирование работают. Применяется к редактору (`editor.setReadOnly`), поэтому\n * защищает документ и от вызовов из кода.\n */\n readonly readOnly?: boolean;\n /**\n * Изображения: `upload` — куда сохранять файлы (иначе картинки встраиваются в документ как data:-адреса\n * до `maxInlineBytes`), `acceptedTypes`, `onError`. Держите объект стабильным.\n */\n readonly images?: ImageOptions;\n}\n\nexport function EditorProvider({\n editor,\n children,\n presentation,\n blocks,\n components,\n slots,\n slashItems,\n keymap,\n highlighter,\n formulaRenderer,\n locale,\n locales,\n messages,\n readOnly,\n images,\n}: EditorProviderProps) {\n const view = useMemo(() => new EditorView(), [editor]);\n\n useLayoutEffect(() => {\n if (readOnly === undefined) return;\n\n const previous = editor.readOnly;\n\n editor.setReadOnly(readOnly);\n\n return () => editor.setReadOnly(previous);\n }, [editor, readOnly]);\n\n const t = useMemo(\n () => createTranslator(resolveMessages({ locale, locales, messages })),\n [locale, locales, messages],\n );\n\n const ui = useMemo(() => {\n const visual = presentation ?? {};\n const code = highlighter ?? visual.highlighter;\n const math = formulaRenderer ?? visual.formulaRenderer;\n const customSlash = slashItems ?? visual.slashItems;\n const customKeys = keymap ?? [];\n\n return {\n components: { ...blockComponentsOf(blocks), ...visual.components, ...components },\n slots: { ...visual.slots, ...slots },\n // Пункты контроллеров идут после стандартных; пункт приложения с тем же id важнее.\n slashItems:\n customSlash === false\n ? []\n : resolveSlashItems(mergeById(controllerSlashItems(editor), customSlash ?? []), t),\n highlighter: code === false ? null : (code ?? highlightCode),\n formulaRenderer: math === false ? null : (math ?? temmlRenderer),\n locale: locale ?? 'en',\n t,\n keymap: resolveKeymap(mergeById(controllerKeymap(editor), customKeys, 'preferred-first')),\n images: images ?? {},\n readOnly,\n };\n }, [\n editor,\n presentation,\n blocks,\n components,\n slots,\n slashItems,\n keymap,\n highlighter,\n formulaRenderer,\n locale,\n t,\n readOnly,\n images,\n ]);\n\n return (\n <EditorContext.Provider value={editor}>\n <EditorViewContext.Provider value={view}>\n <EditorUIContext.Provider value={ui}>{children}</EditorUIContext.Provider>\n </EditorViewContext.Provider>\n </EditorContext.Provider>\n );\n}\n","export type DropPosition = 'before' | 'after';\n\nexport interface BlockAnchor {\n readonly blockId: string;\n readonly x: number;\n readonly y: number;\n}\n\nexport interface DropIndicatorRect {\n readonly left: number;\n readonly top: number;\n readonly width: number;\n}\n\nexport interface DragState {\n readonly blockId: string;\n readonly targetId: string | null;\n readonly position: DropPosition | null;\n readonly indicator: DropIndicatorRect | null;\n}\n\nexport interface BlockHandleState {\n readonly hover: BlockAnchor | null;\n readonly menu: BlockAnchor | null;\n readonly drag: DragState | null;\n}\n\nconst IDLE: BlockHandleState = Object.freeze({ hover: null, menu: null, drag: null });\n\nconst sameAnchor = (a: BlockAnchor | null, b: BlockAnchor | null) =>\n a === b || (!!a && !!b && a.blockId === b.blockId && a.x === b.x && a.y === b.y);\n\nexport class BlockHandleController {\n private state: BlockHandleState = IDLE;\n\n private readonly listeners = new Set<() => void>();\n\n getState = (): BlockHandleState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n setHover(hover: BlockAnchor | null): void {\n if (!sameAnchor(this.state.hover, hover)) this.set({ ...this.state, hover });\n }\n\n openMenu(menu: BlockAnchor): void {\n this.set({ ...this.state, menu });\n }\n\n closeMenu(): void {\n if (this.state.menu) this.set({ ...this.state, menu: null });\n }\n\n startDrag(blockId: string): void {\n this.set({\n ...this.state,\n menu: null,\n drag: { blockId, targetId: null, position: null, indicator: null },\n });\n }\n\n updateDrag(patch: Partial<Omit<DragState, 'blockId'>>): void {\n const drag = this.state.drag;\n\n if (!drag) return;\n\n const next = { ...drag, ...patch };\n const same =\n next.targetId === drag.targetId &&\n next.position === drag.position &&\n next.indicator?.left === drag.indicator?.left &&\n next.indicator?.top === drag.indicator?.top &&\n next.indicator?.width === drag.indicator?.width;\n\n if (!same) this.set({ ...this.state, drag: next });\n }\n\n endDrag(): void {\n if (this.state.drag) this.set({ ...this.state, drag: null });\n }\n\n private set(state: BlockHandleState): void {\n this.state = state;\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","import type { ImageErrorInfo } from './ImageError';\n\n/**\n * Какие блоки-картинки сейчас загружаются и какие ошибки загрузки показать. Состояние живёт здесь, а не в\n * компоненте: пока файл обрабатывается, выбор файла заменяется индикатором и локальное состояние пропало бы.\n */\nexport class UploadTracker {\n private readonly active = new Set<string>();\n\n private readonly errors = new Map<string, ImageErrorInfo>();\n\n private readonly listeners = new Set<() => void>();\n\n has = (blockId: string): boolean => this.active.has(blockId);\n\n errorOf = (blockId: string): string | undefined => this.errors.get(blockId)?.message;\n\n errorDetailsOf = (blockId: string): ImageErrorInfo | undefined => this.errors.get(blockId);\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n start(blockId: string): void {\n this.errors.delete(blockId);\n this.active.add(blockId);\n this.notify();\n }\n\n finish(blockId: string, error?: string | ImageErrorInfo): void {\n const changed = this.active.delete(blockId);\n\n if (error) this.errors.set(blockId, typeof error === 'string' ? { message: error } : error);\n\n if (changed || error) this.notify();\n }\n\n clearError(blockId: string): void {\n if (this.errors.delete(blockId)) this.notify();\n }\n\n private notify(): void {\n for (const listener of [...this.listeners]) listener();\n }\n}\n","/**\n * Какие блоки сейчас затронуты непустым выделением. Подписка идёт на уровне отдельного блока:\n * при смене выделения перерисовываются только те блоки, у которых флаг `selected` изменился.\n */\nexport class BlockSelectionController {\n private selected: ReadonlySet<string> = new Set();\n\n private readonly listeners = new Set<() => void>();\n\n isSelected = (blockId: string): boolean => this.selected.has(blockId);\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n set(ids: readonly string[]): void {\n if (ids.length === this.selected.size && ids.every((id) => this.selected.has(id))) return;\n\n this.selected = new Set(ids);\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","export type FormulaEditorMode = 'insert' | 'edit';\n\nexport interface FormulaEditorState {\n readonly open: boolean;\n readonly mode: FormulaEditorMode;\n readonly blockId: string;\n readonly from: number;\n readonly to: number;\n readonly latex: string;\n readonly position: { readonly x: number; readonly y: number; readonly top: number };\n}\n\nconst CLOSED: FormulaEditorState = Object.freeze({\n open: false,\n mode: 'insert',\n blockId: '',\n from: 0,\n to: 0,\n latex: '',\n position: { x: 0, y: 0, top: 0 },\n});\n\nexport class FormulaController {\n private state: FormulaEditorState = CLOSED;\n\n private readonly listeners = new Set<() => void>();\n\n getState = (): FormulaEditorState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n open(state: Omit<FormulaEditorState, 'open'>): void {\n this.set({ ...state, open: true });\n }\n\n close(): void {\n if (this.state.open) this.set(CLOSED);\n }\n\n private set(state: FormulaEditorState): void {\n this.state = state;\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","/**\n * В каком блоке сейчас стоит каретка (выделение свёрнуто). Подписка идёт на уровне блока: при переносе каретки\n * перерисовываются только два блока — тот, который она покинула, и тот, куда попала.\n */\nexport class CaretController {\n private blockId: string | null = null;\n\n private readonly listeners = new Set<() => void>();\n\n has = (blockId: string): boolean => this.blockId === blockId;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n set(blockId: string | null): void {\n if (this.blockId === blockId) return;\n\n this.blockId = blockId;\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","export interface SlashMenuState {\n readonly open: boolean;\n readonly blockId: string | null;\n readonly slashOffset: number;\n readonly query: string;\n readonly activeIndex: number;\n readonly position: { readonly x: number; readonly y: number } | null;\n}\n\nconst CLOSED: SlashMenuState = Object.freeze({\n open: false,\n blockId: null,\n slashOffset: 0,\n query: '',\n activeIndex: 0,\n position: null,\n});\n\nexport class SlashMenuController {\n private state: SlashMenuState = CLOSED;\n\n private readonly listeners = new Set<() => void>();\n\n getState = (): SlashMenuState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n open(blockId: string, slashOffset: number): void {\n this.set({ ...CLOSED, open: true, blockId, slashOffset });\n }\n\n close(): void {\n if (this.state.open) this.set(CLOSED);\n }\n\n update(patch: Partial<Pick<SlashMenuState, 'query' | 'activeIndex' | 'position'>>): void {\n if (!this.state.open) return;\n\n const next = { ...this.state, ...patch };\n const same =\n next.query === this.state.query &&\n next.activeIndex === this.state.activeIndex &&\n next.position?.x === this.state.position?.x &&\n next.position?.y === this.state.position?.y;\n\n if (!same) this.set(next);\n }\n\n move(delta: number, count: number): void {\n if (!this.state.open || count === 0) return;\n\n this.update({ activeIndex: (this.state.activeIndex + delta + count) % count });\n }\n\n private set(state: SlashMenuState): void {\n this.state = state;\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","import type { RangeFormats } from '@inkbrick/engine';\n\nimport type { DocSelection } from '../editing/selection';\nimport type { ToolbarPanel } from './types';\n\nexport interface ToolbarState {\n readonly visible: boolean;\n readonly position: { readonly x: number; readonly y: number } | null;\n readonly formats: RangeFormats | null;\n readonly range: DocSelection | null;\n readonly linkOpen: boolean;\n readonly panel: ToolbarPanel | null;\n}\n\nconst HIDDEN: ToolbarState = Object.freeze({\n visible: false,\n position: null,\n formats: null,\n range: null,\n linkOpen: false,\n panel: null,\n});\n\nfunction sameFormats(a: RangeFormats | null, b: RangeFormats | null): boolean {\n return (\n a === b ||\n (!!a &&\n !!b &&\n a.bold === b.bold &&\n a.italic === b.italic &&\n a.underline === b.underline &&\n a.strike === b.strike &&\n a.code === b.code &&\n a.link === b.link &&\n a.color === b.color &&\n a.backgroundColor === b.backgroundColor &&\n a.align === b.align)\n );\n}\n\nexport class ToolbarController {\n private state: ToolbarState = HIDDEN;\n\n private readonly listeners = new Set<() => void>();\n\n getState = (): ToolbarState => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n show(range: DocSelection, formats: RangeFormats, position: { x: number; y: number }): void {\n const prev = this.state;\n const same =\n prev.visible &&\n sameFormats(prev.formats, formats) &&\n prev.position?.x === position.x &&\n prev.position?.y === position.y &&\n prev.range?.from.blockId === range.from.blockId &&\n prev.range?.from.offset === range.from.offset &&\n prev.range?.to.blockId === range.to.blockId &&\n prev.range?.to.offset === range.to.offset;\n\n if (!same) this.set({ ...prev, visible: true, position, formats, range });\n }\n\n hide(): void {\n if (this.state.visible) this.set(HIDDEN);\n }\n\n openLink(): void {\n if (this.state.visible && !this.state.linkOpen) {\n this.set({ ...this.state, linkOpen: true, panel: null });\n }\n }\n\n togglePanel(panel: ToolbarPanel): void {\n if (!this.state.visible || this.state.linkOpen) return;\n\n this.set({ ...this.state, panel: this.state.panel === panel ? null : panel });\n }\n\n closePanel(): void {\n if (this.state.panel) this.set({ ...this.state, panel: null });\n }\n\n closeLink(): void {\n if (this.state.linkOpen) this.set({ ...this.state, linkOpen: false });\n }\n\n private set(state: ToolbarState): void {\n this.state = state;\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","/**\n * Какие блоки обязаны оставаться в DOM при виртуальной отрисовке: края выделения (там стоит каретка или\n * начинается/кончается выделение) и блоки, которые редактор попросил показать (`reveal`), например перед\n * установкой каретки в блок за пределами окна. Обычный рендерер это состояние не читает.\n */\nexport class ViewportController {\n private edges: readonly string[] = [];\n\n private revealed: readonly string[] = [];\n\n private lists = 0;\n\n private version = 0;\n\n private readonly listeners = new Set<() => void>();\n\n getVersion = (): number => this.version;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getPinned(): readonly string[] {\n return this.revealed.length === 0 ? this.edges : [...this.edges, ...this.revealed];\n }\n\n get virtual(): boolean {\n return this.lists > 0;\n }\n\n attach(): () => void {\n this.lists += 1;\n\n return () => {\n this.lists -= 1;\n };\n }\n\n setEdges(ids: readonly string[]): void {\n if (ids.length === this.edges.length && ids.every((id, i) => this.edges[i] === id)) return;\n\n this.edges = ids;\n this.notify();\n }\n\n reveal(ids: readonly string[]): boolean {\n if (!this.virtual) return false;\n\n this.revealed = ids;\n this.notify();\n return true;\n }\n\n private notify(): void {\n this.version += 1;\n\n for (const listener of [...this.listeners]) listener();\n }\n}\n","import type { BlockId } from '@inkbrick/document';\n\nimport { BlockHandleController } from '../block-handle/BlockHandleController';\nimport { UploadTracker } from '../images/UploadTracker';\nimport { BlockSelectionController } from './BlockSelectionController';\nimport { FormulaController } from '../formula/FormulaController';\nimport { CaretController } from './CaretController';\nimport { SlashMenuController } from '../slash/SlashMenuController';\nimport { ToolbarController } from '../toolbar/ToolbarController';\nimport { ViewportController } from './ViewportController';\nimport { setDomSelection, type DocPoint } from './selection';\n\n/**\n * Связь модели с DOM: корневой редактируемый элемент и элементы текстовых блоков.\n * Нужна, чтобы после изменения модели вернуть курсор/выделение на место.\n */\nexport class EditorView {\n private readonly elements = new Map<BlockId, HTMLElement>();\n\n private root: HTMLElement | null = null;\n\n readonly slash = new SlashMenuController();\n\n readonly uploads = new UploadTracker();\n\n readonly selection = new BlockSelectionController();\n\n readonly caret = new CaretController();\n\n readonly blocks = new BlockHandleController();\n\n readonly formula = new FormulaController();\n\n readonly toolbar = new ToolbarController();\n\n readonly viewport = new ViewportController();\n\n pointerDown = false;\n\n private pending: { from: DocPoint; to: DocPoint } | null = null;\n\n setRoot(element: HTMLElement | null): () => void {\n this.root = element;\n\n return () => {\n if (this.root === element) this.root = null;\n };\n }\n\n getRoot(): HTMLElement | null {\n return this.root;\n }\n\n register(id: BlockId, element: HTMLElement): () => void {\n this.elements.set(id, element);\n\n const pending = this.pending;\n\n if (\n pending &&\n this.elements.has(pending.from.blockId) &&\n this.elements.has(pending.to.blockId)\n ) {\n // Регистрация идёт раньше, чем блок заполнит текст (тоже в layout-эффекте): ставим после фиксации.\n queueMicrotask(() => {\n if (this.pending === pending) this.placeSelection(pending.from, pending.to);\n });\n }\n\n return () => {\n // Не удаляем, если за это время зарегистрировали другой элемент для того же id.\n if (this.elements.get(id) === element) {\n this.elements.delete(id);\n }\n };\n }\n\n getElement(id: BlockId): HTMLElement | undefined {\n return this.elements.get(id);\n }\n\n placeCaret(id: BlockId, offset: number): void {\n this.placeSelection({ blockId: id, offset }, { blockId: id, offset });\n }\n\n placeSelection(from: DocPoint, to: DocPoint): void {\n const start = this.elements.get(from.blockId);\n const end = this.elements.get(to.blockId);\n\n if (!start || !end) {\n // Блок за пределами окна виртуального рендерера: просим отрисовать его и ставим выделение,\n // когда он зарегистрируется (прокрутка к нему — ниже, через scrollIntoView).\n this.pending = this.viewport.reveal([from.blockId, to.blockId]) ? { from, to } : null;\n return;\n }\n\n this.pending = null;\n\n // Фокус принадлежит корню: отдельные блоки не являются редактируемыми элементами.\n if (this.root && globalThis.document.activeElement !== this.root) {\n this.root.focus({ preventScroll: true });\n }\n\n setDomSelection(start, from.offset, end, to.offset);\n\n end.scrollIntoView?.({ block: 'nearest' });\n }\n}\n","interface Shortcut {\n mod: boolean;\n ctrl: boolean;\n meta: boolean;\n alt: boolean;\n shift: boolean;\n key: string;\n}\n\nconst MODIFIER = /^(mod|ctrl|control|meta|cmd|alt|option|shift)-/i;\n\nconst KEY_ALIASES: Record<string, string> = {\n esc: 'escape',\n space: ' ',\n up: 'arrowup',\n down: 'arrowdown',\n left: 'arrowleft',\n right: 'arrowright',\n del: 'delete',\n return: 'enter',\n};\n\nconst cache = new Map<string, Shortcut>();\n\n/**\n * Разбирает запись вида `Mod-Shift-z`, `Tab`, `Shift-ArrowDown`: модификаторы (`Mod`, `Ctrl`, `Meta`/`Cmd`,\n * `Alt`/`Option`, `Shift`) через дефис, затем клавиша (как `KeyboardEvent.key`, регистр не важен).\n */\nfunction parse(spec: string): Shortcut {\n const cached = cache.get(spec);\n\n if (cached) return cached;\n\n const shortcut: Shortcut = {\n mod: false,\n ctrl: false,\n meta: false,\n alt: false,\n shift: false,\n key: '',\n };\n let rest = spec.trim();\n\n for (let match = MODIFIER.exec(rest); match; match = MODIFIER.exec(rest)) {\n switch (match[1].toLowerCase()) {\n case 'mod':\n shortcut.mod = true;\n break;\n case 'ctrl':\n case 'control':\n shortcut.ctrl = true;\n break;\n case 'meta':\n case 'cmd':\n shortcut.meta = true;\n break;\n case 'alt':\n case 'option':\n shortcut.alt = true;\n break;\n default:\n shortcut.shift = true;\n }\n\n rest = rest.slice(match[0].length);\n }\n\n const key = rest.toLowerCase();\n\n if (key === '') throw new Error(`Invalid shortcut \"${spec}\": no key`);\n\n shortcut.key = KEY_ALIASES[key] ?? key;\n cache.set(spec, shortcut);\n\n return shortcut;\n}\n\nfunction matchesKey(event: KeyboardEvent, key: string): boolean {\n const pressed = event.key.toLowerCase();\n\n if (pressed === key) return true;\n\n // Ctrl+B на русской раскладке даёт key «и»: для латинских букв сверяем физическую клавишу.\n return (\n /^[a-z]$/.test(key) && !/^[a-z]$/.test(pressed) && event.code === `Key${key.toUpperCase()}`\n );\n}\n\n/**\n * Нажата ли ровно эта комбинация: Shift и Alt должны совпадать точно; Ctrl/Meta, если не упомянуты,\n * не должны быть нажаты (`Mod` принимает любую из двух).\n */\nexport function matchesShortcut(event: KeyboardEvent, spec: string): boolean {\n const shortcut = parse(spec);\n\n if (event.shiftKey !== shortcut.shift || event.altKey !== shortcut.alt) return false;\n\n if (shortcut.mod) {\n if (!(event.ctrlKey || event.metaKey)) return false;\n } else if (event.ctrlKey !== shortcut.ctrl || event.metaKey !== shortcut.meta) {\n return false;\n }\n\n return matchesKey(event, shortcut.key);\n}\n","import { defaultKeymap } from './defaultKeymap';\nimport { matchesShortcut } from './shortcut';\nimport type { KeyBinding, KeymapContext } from './types';\n\n/**\n * Собирает итоговый список привязок: свои привязки с `id` стандартной занимают её место, остальные идут\n * перед стандартными (проверяются первыми).\n */\nexport function resolveKeymap(custom: readonly KeyBinding[] = []): readonly KeyBinding[] {\n if (custom.length === 0) return defaultKeymap;\n\n const overrides = new Map(custom.map((binding) => [binding.id, binding]));\n const defaultIds = new Set(defaultKeymap.map((binding) => binding.id));\n\n return [\n ...custom.filter((binding) => !defaultIds.has(binding.id)),\n ...defaultKeymap.map((binding) => overrides.get(binding.id) ?? binding),\n ];\n}\n\nexport function unbind(id: string): KeyBinding {\n return { id, keys: [], run: () => false };\n}\n\nexport function handleKeyDown(bindings: readonly KeyBinding[], context: KeymapContext): boolean {\n const { event } = context;\n\n for (const binding of bindings) {\n const keys = typeof binding.keys === 'string' ? [binding.keys] : binding.keys;\n\n if (!keys.some((spec) => matchesShortcut(event, spec))) continue;\n if (binding.when && !binding.when(context)) continue;\n\n if (binding.run(context) === false) continue;\n\n event.preventDefault();\n\n return true;\n }\n\n return false;\n}\n","import type { ComponentType } from 'react';\n\nimport type { BlockProps as DocumentBlockProps } from '@inkbrick/document';\nimport type { BlockController, BlockDefinition, TypedBlock } from '@inkbrick/engine';\n\nimport type { BlockComponent, BlockComponentRegistry, BlockViewProps } from '../ui/types';\n\nexport type CustomBlockViewProps<TProps extends DocumentBlockProps = DocumentBlockProps> =\n BlockViewProps<TypedBlock<TProps> & { props: TProps }>;\n\n/**\n * Пользовательский блок целиком: схема документа, React-компонент и (необязательно) контроллер поведения.\n * Схема и контроллер нужны движку (`new Editor({ blocks: [...] })`), компонент — UI (`<EditorProvider blocks>`).\n */\nexport interface ReactBlockDefinition<\n TProps extends DocumentBlockProps = DocumentBlockProps,\n> extends BlockDefinition<TProps> {\n readonly component: ComponentType<CustomBlockViewProps<TProps>>;\n readonly controller?: BlockController<TProps>;\n}\n\n/**\n * Объявляет пользовательский блок одним объектом:\n *\n * ```ts\n * export const counterBlock = defineBlock<CounterProps>({ schema, component: CounterView, controller });\n * const editor = new Editor({ blocks: [counterBlock] });\n * <EditorProvider editor={editor} blocks={[counterBlock]}>…\n * ```\n *\n * Объект создавайте один раз (вне компонента).\n */\nexport function defineBlock<TProps extends DocumentBlockProps = DocumentBlockProps>(\n definition: ReactBlockDefinition<TProps>,\n): ReactBlockDefinition<TProps> {\n return definition;\n}\n\nexport function blockComponentsOf(\n blocks: readonly ReactBlockDefinition<any>[] | undefined,\n): BlockComponentRegistry {\n const registry: Record<string, BlockComponent> = {};\n\n for (const block of blocks ?? []) {\n registry[block.schema.flavour] = block.component as unknown as BlockComponent;\n }\n\n return registry;\n}\n","import type { ReactNode } from 'react';\n\nimport type { Editor } from '@inkbrick/engine';\n\nimport { Icon } from '../icons/Icon';\nimport { ICON_SHAPES, type IconName } from '../icons/lucide';\nimport type { KeyBinding, KeymapContext } from '../keymap/types';\nimport type { SlashMenuItem } from '../slash/types';\n\nexport function iconByName(name: string | undefined): ReactNode {\n return name && Object.hasOwn(ICON_SHAPES, name) ? <Icon name={name as IconName} /> : undefined;\n}\n\nexport function controllerSlashItems(editor: Editor): SlashMenuItem[] {\n return editor.controllers.entries().flatMap(([flavour, controller]) =>\n (controller.slashItems ?? []).map<SlashMenuItem>((item) => ({\n id: item.id,\n title: item.title,\n description: item.description,\n keywords: item.keywords,\n icon: iconByName(item.icon),\n flavour,\n props: item.props,\n })),\n );\n}\n\nfunction controlledBlockAt(context: KeymapContext, flavour: string) {\n const selection = context.selection();\n const block = selection && context.editor.store.getBlock(selection.from.blockId);\n\n return block?.flavour === flavour ? block : undefined;\n}\n\nexport function controllerKeymap(editor: Editor): KeyBinding[] {\n return editor.controllers.entries().flatMap(([flavour, controller]) =>\n (controller.keymap ?? []).map<KeyBinding>((binding) => ({\n id: binding.id,\n keys: binding.keys,\n when: (context) => controlledBlockAt(context, flavour) !== undefined,\n run: (context) => {\n const block = controlledBlockAt(context, flavour);\n\n return block ? binding.run(context.editor.controllers.contextOf(block)) : false;\n },\n })),\n );\n}\n\n/**\n * Объединяет пункты по id: пункт из `preferred` заменяет одноимённый из `base`.\n * Порядок: сначала `base`, затем `preferred` (или наоборот — `'preferred-first'`, для клавиш: проверяются раньше).\n */\nexport function mergeById<T extends { readonly id: string }>(\n base: readonly T[],\n preferred: readonly T[],\n order: 'base-first' | 'preferred-first' = 'base-first',\n): T[] {\n const ids = new Set(preferred.map((item) => item.id));\n const rest = base.filter((item) => !ids.has(item.id));\n\n return order === 'base-first' ? [...rest, ...preferred] : [...preferred, ...rest];\n}\n","import type { CodeHighlighter } from '../code/types';\nimport type { FormulaRenderer } from '../math/renderer';\nimport type { SlashMenuItem } from '../slash/types';\nimport type { BlockComponentRegistry, EditorSlots } from './types';\n\n/**\n * Визуальный слой редактора одним объектом: представления блоков, элементы оболочки (меню, toolbar, ручки),\n * пункты slash-меню, подсветка кода и отрисовка формул. Модель документа и команды от него не зависят, поэтому\n * дизайн-систему можно подключить к любому редактору: `<EditorProvider presentation={myDesignSystem}>`.\n *\n * Отдельные props провайдера (`components`, `slots`, …) уточняют presentation: `components` и `slots`\n * сливаются с ним (одинаковый ключ — из prop), остальное заменяется целиком.\n */\nexport interface EditorPresentation {\n readonly components?: BlockComponentRegistry;\n readonly slots?: EditorSlots;\n readonly slashItems?: readonly SlashMenuItem[] | false;\n readonly highlighter?: CodeHighlighter | false;\n readonly formulaRenderer?: FormulaRenderer | false;\n}\n\nexport function definePresentation<T extends EditorPresentation>(presentation: T): T {\n return presentation;\n}\n","import { useContext } from 'react';\n\nimport { EditorContext } from '../context/EditorContext';\n\nexport function useEditor() {\n const editor = useContext(EditorContext);\n\n if (!editor) {\n throw new Error('useEditor must be used inside <EditorProvider>');\n }\n\n return editor;\n}\n","import { useContext } from 'react';\n\nimport { EditorViewContext } from '../context/EditorContext';\n\nexport function useEditorView() {\n const view = useContext(EditorViewContext);\n\n if (!view) {\n throw new Error('useEditorView must be used inside <EditorProvider>');\n }\n\n return view;\n}\n","import { useSyncExternalStore } from 'react';\n\nimport { useEditor } from './useEditor';\n\nexport function useDocument() {\n const editor = useEditor();\n const { store } = editor;\n\n useSyncExternalStore(\n (listener) => store.subscribe(listener),\n () => store.getVersion(),\n () => store.getVersion(),\n );\n\n return editor.document;\n}\n","import { useCallback, useSyncExternalStore } from 'react';\n\nimport type { BlockId } from '@inkbrick/document';\n\nimport { useEditor } from './useEditor';\n\n/**\n * Подписывается на один блок. Блоки в документе иммутабельны (каждое изменение\n * создаёт новый объект), поэтому ссылка — корректный snapshot для React.\n */\nexport function useBlock(id: BlockId) {\n const { store } = useEditor();\n\n const subscribe = useCallback(\n (listener: () => void) => store.subscribeBlock(id, listener),\n [store, id],\n );\n const getSnapshot = useCallback(() => store.getBlock(id), [store, id]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import type { BlockId } from '@inkbrick/document';\n\nimport { useBlock } from './useBlock';\n\nconst NO_CHILDREN: readonly BlockId[] = [];\n\n/**\n * Идентификаторы дочерних блоков. Возвращает стабильную ссылку, пока children\n * не изменились (создавать новый массив в getSnapshot нельзя — это приводит\n * к бесконечному циклу рендера в useSyncExternalStore).\n */\nexport function useChildren(parentId: BlockId): readonly BlockId[] {\n const parent = useBlock(parentId);\n\n return parent?.children ?? NO_CHILDREN;\n}\n","import { useCallback, useSyncExternalStore } from 'react';\nimport { flushSync } from 'react-dom';\n\nimport type { HistoryResult } from '@inkbrick/engine';\n\nimport { useEditor } from './useEditor';\nimport { useEditorView } from './useEditorView';\n\nexport interface HistoryControls {\n readonly canUndo: boolean;\n readonly canRedo: boolean;\n undo(): boolean;\n redo(): boolean;\n}\n\nexport function useHistory(): HistoryControls {\n const editor = useEditor();\n const view = useEditorView();\n const { store } = editor;\n\n useSyncExternalStore(\n (listener) => store.subscribe(listener),\n () => store.getHistoryVersion(),\n () => store.getHistoryVersion(),\n );\n\n const apply = useCallback(\n (action: () => HistoryResult | undefined) => {\n let result: HistoryResult | undefined;\n\n flushSync(() => {\n result = action();\n });\n\n if (result?.caret) view.placeCaret(result.caret.blockId, result.caret.offset);\n\n return result !== undefined;\n },\n [view],\n );\n\n const undo = useCallback(() => apply(() => editor.undo()), [apply, editor]);\n const redo = useCallback(() => apply(() => editor.redo()), [apply, editor]);\n\n return { canUndo: editor.canUndo, canRedo: editor.canRedo, undo, redo };\n}\n","import { useSyncExternalStore } from 'react';\n\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { useEditor } from './useEditor';\n\nexport function useReadOnly(): boolean {\n const editor = useEditor();\n const { readOnly } = useEditorUI();\n\n const state = useSyncExternalStore(\n (listener) => editor.subscribeReadOnly(listener),\n () => editor.readOnly,\n () => editor.readOnly,\n );\n\n /*\n * Prop провайдера действует сразу (в том числе при серверном рендере, где эффекты не выполняются),\n * а движок синхронизируется эффектом.\n */\n return readOnly ?? state;\n}\n","import { useMemo } from 'react';\n\nimport type { BaseBlock, BlockProps } from '@inkbrick/document';\nimport type { BlockContext, BlockController } from '@inkbrick/engine';\n\nimport { useEditor } from './useEditor';\n\nexport interface BlockControllerHandle<\n TProps extends BlockProps = BlockProps,\n> extends BlockContext<TProps> {\n readonly controller: BlockController<TProps> | undefined;\n}\n\n/**\n * Контроллер блока для его React-компонента: `execute('counter.increment')` и `can(...)` уже знают `blockId`.\n * Команды уважают режим только чтения (возвращают undefined); для разметки используйте prop `readOnly`.\n */\nexport function useBlockController<TProps extends BlockProps = BlockProps>(\n block: BaseBlock,\n): BlockControllerHandle<TProps> {\n const editor = useEditor();\n\n return useMemo(() => {\n const context = editor.controllers.contextOf<TProps>(block);\n\n return Object.assign(Object.create(context) as BlockContext<TProps>, {\n controller: editor.controllers.get(block.flavour) as BlockController<TProps> | undefined,\n });\n }, [editor, block]);\n}\n","import { type Fragment, type FragmentBlock, sanitizeFragment } from '@inkbrick/engine';\nimport { collect } from './html/blocks';\n\n/**\n * HTML из буфера обмена → фрагмент Inkbrick.\n *\n * Разметка НИКОГДА не вставляется в DOM: HTML разбирается в изолированном документе (DOMParser: скрипты не\n * выполняются, картинки не загружаются), из него читается только структура и текст. Неизвестные теги\n * сводятся к тексту, ссылки проходят проверку, стили учитываются только для жирного/курсива/подчёркивания.\n * Понимает разметку Google Docs и Word (списки `mso-list`, обёртки `<b style=\"font-weight:normal\">`).\n */\n\nconst MAX_HTML = 2_000_000;\n\nexport function embeddedFragment(html: string): Fragment | null {\n if (!html.includes('data-inkbrick-fragment')) return null;\n\n const doc = new DOMParser().parseFromString(html.slice(0, MAX_HTML), 'text/html');\n const raw = doc.querySelector('[data-inkbrick-fragment]')?.getAttribute('data-inkbrick-fragment');\n\n if (!raw) return null;\n\n try {\n return sanitizeFragment(JSON.parse(decodeURIComponent(raw)));\n } catch {\n return null;\n }\n}\n\nexport function htmlToFragment(html: string): Fragment | null {\n if (!html || html.length > MAX_HTML) return null;\n\n const doc = new DOMParser().parseFromString(html, 'text/html');\n const blocks: FragmentBlock[] = [];\n\n collect(doc.body, {}, blocks, 0);\n\n const sanitized = sanitizeFragment({ blocks: blocks.map((b) => ({ ...b, complete: true })) });\n\n return sanitized;\n}\n","import { type InlineNode, isSafeImageUrl, normalizeInlineNodes } from '@inkbrick/document';\nimport type { FragmentBlock } from '@inkbrick/engine';\nimport { cleanInline, inlineOf } from './inline';\nimport { isHidden, styleOf } from './style';\nimport { BLOCK_TAGS, MAX_DEPTH, SKIP_TAGS, type Style, tagOf } from './tags';\n\ninterface Item {\n block: FragmentBlock;\n level: number;\n}\n\n/** Адрес картинки из вставленного HTML: только абсолютные http(s) и data:-адреса (относительные пути чужого сайта бессмысленны). */\nfunction pastedImageSrc(src: string | null): string | null {\n const value = (src ?? '').trim();\n\n return value !== '' && !value.startsWith('/') && isSafeImageUrl(value) ? value : null;\n}\n\nfunction imageBlock(img: Element, caption = ''): FragmentBlock | null {\n const src = pastedImageSrc(img.getAttribute('src'));\n\n if (!src) return null;\n\n return block('block:image', [], {\n src,\n alt: (img.getAttribute('alt') ?? '').slice(0, 1000),\n caption: caption.slice(0, 2000),\n });\n}\n\nconst block = (\n flavour: string,\n content: InlineNode[],\n props: Record<string, unknown> = {},\n): FragmentBlock => ({\n flavour,\n props,\n content,\n children: [],\n});\n\n/** Есть ли внутри блочный элемент. Обход в глубину с выходом на первом совпадении, без рекурсии. */\nfunction hasBlockDescendant(element: Element): boolean {\n const stack: Element[] = [];\n\n for (let child = element.lastElementChild; child; child = child.previousElementSibling)\n stack.push(child);\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n const tag = tagOf(current);\n\n if (BLOCK_TAGS.has(tag) && !SKIP_TAGS.has(tag)) return true;\n\n for (let child = current.lastElementChild; child; child = child.previousElementSibling)\n stack.push(child);\n }\n\n return false;\n}\n\nfunction wordListLevel(element: HTMLElement): number | null {\n const style = element.getAttribute('style') ?? '';\n const match = /mso-list:[^;]*level(\\d+)/i.exec(style);\n\n if (match) return Number(match[1]);\n\n return /^MsoListParagraph/i.test(element.className) ? 1 : null;\n}\n\nfunction wordListMarker(element: HTMLElement): string {\n for (const span of element.querySelectorAll('span')) {\n if (/mso-list:\\s*ignore/i.test(span.getAttribute('style') ?? '')) return span.textContent ?? '';\n }\n\n return '';\n}\n\nfunction listItems(\n list: HTMLElement,\n ordered: boolean,\n style: Style,\n depth: number,\n): FragmentBlock[] {\n const result: FragmentBlock[] = [];\n\n for (const child of Array.from(list.children) as HTMLElement[]) {\n if (SKIP_TAGS.has(tagOf(child)) || isHidden(child)) continue;\n\n // <ul><ul>…</ul></ul> (Google Docs): вложенный список без пункта-родителя — потомок предыдущего пункта.\n if (tagOf(child) === 'UL' || tagOf(child) === 'OL') {\n const nested = listItems(child, tagOf(child) === 'OL', style, depth + 1);\n const parent = result[result.length - 1];\n\n if (parent) parent.children.push(...nested);\n else result.push(...nested);\n continue;\n }\n\n if (tagOf(child) !== 'LI') continue;\n\n const content: InlineNode[] = [];\n const children: FragmentBlock[] = [];\n const itemStyle = styleOf(child, style);\n\n const checkbox = child.querySelector(\n ':scope > input[type=\"checkbox\"], :scope > p > input[type=\"checkbox\"]',\n ) as HTMLInputElement | null;\n const todo = !!checkbox || /task-list-item/.test(child.className);\n\n child.childNodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n\n if (tagOf(element) === 'UL' || tagOf(element) === 'OL') {\n children.push(...listItems(element, tagOf(element) === 'OL', itemStyle, depth + 1));\n return;\n }\n }\n\n inlineOf(node, itemStyle, content, depth + 1);\n });\n\n const props: Record<string, unknown> = { type: todo ? 'todo' : ordered ? 'ordered' : 'bullet' };\n\n if (todo) props.checked = !!checkbox?.checked || checkbox?.hasAttribute('checked') === true;\n\n const item = block('block:list', cleanInline(content), props);\n item.children = children;\n result.push(item);\n }\n\n return result;\n}\n\nfunction pushWordItem(\n out: FragmentBlock[],\n stack: Item[],\n item: FragmentBlock,\n level: number,\n): void {\n while (stack.length > 0 && stack[stack.length - 1].level >= level) stack.pop();\n\n const parent = stack[stack.length - 1];\n\n if (parent) parent.block.children.push(item);\n else out.push(item);\n\n stack.push({ block: item, level });\n}\n\nexport function collect(container: Node, style: Style, out: FragmentBlock[], depth: number): void {\n if (depth > MAX_DEPTH) return;\n\n let run: InlineNode[] = [];\n let wordStack: Item[] = [];\n\n const flush = () => {\n const content = cleanInline(run);\n\n if (content.length > 0) out.push(block('block:paragraph', content));\n\n run = [];\n };\n\n const endWordList = () => {\n wordStack = [];\n };\n\n container.childNodes.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n inlineOf(node, style, run, depth + 1);\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n\n const element = node as HTMLElement;\n\n if (SKIP_TAGS.has(tagOf(element)) || isHidden(element)) return;\n\n const tag = tagOf(element);\n const next = styleOf(element, style);\n\n const level = tag === 'P' ? wordListLevel(element) : null;\n\n if (level !== null) {\n flush();\n\n const marker = wordListMarker(element).trim();\n const content: InlineNode[] = [];\n\n element.childNodes.forEach((child) => inlineOf(child, next, content, depth + 1));\n\n pushWordItem(\n out,\n wordStack,\n block('block:list', cleanInline(content), {\n type: /^(\\d+|[a-z]|[ivxlc]+)[.)]/i.test(marker) ? 'ordered' : 'bullet',\n }),\n level,\n );\n return;\n }\n\n endWordList();\n\n if (/^H[1-6]$/.test(tag)) {\n flush();\n\n const content: InlineNode[] = [];\n element.childNodes.forEach((child) => inlineOf(child, next, content, depth + 1));\n\n const cleaned = cleanInline(content);\n\n if (cleaned.length > 0) out.push(block('block:heading', cleaned, { level: Number(tag[1]) }));\n return;\n }\n\n if (tag === 'IMG') {\n flush();\n\n const image = imageBlock(element);\n\n if (image) out.push(image);\n return;\n }\n\n switch (tag) {\n case 'FIGURE': {\n const img = element.querySelector('img');\n\n if (img) {\n flush();\n\n const caption = (element.querySelector('figcaption')?.textContent ?? '')\n .replace(/\\s+/g, ' ')\n .trim();\n const image = imageBlock(img, caption);\n\n if (image) out.push(image);\n return;\n }\n break;\n }\n\n case 'ASIDE': {\n const tone = element.getAttribute('data-callout');\n\n if (tone !== null) {\n flush();\n\n const content: InlineNode[] = [];\n element.childNodes.forEach((child) => inlineOf(child, next, content, depth + 1));\n const cleaned = cleanInline(content);\n\n if (cleaned.length > 0) {\n out.push(\n block(\n 'block:callout',\n cleaned,\n /^(info|warning|success|danger)$/.test(tone) ? { tone } : {},\n ),\n );\n }\n return;\n }\n break;\n }\n\n case 'UL':\n case 'OL':\n flush();\n out.push(...listItems(element, tag === 'OL', next, depth + 1));\n return;\n\n case 'LI':\n flush();\n out.push(\n ...listItems(element.parentElement ?? element, false, next, depth + 1).slice(0, 1),\n );\n return;\n\n case 'PRE': {\n flush();\n\n const code = element.querySelector('code');\n const language =\n /language-([\\w+#-]+)/.exec(code?.className ?? element.className)?.[1] ??\n element.getAttribute('data-language') ??\n 'plain';\n const text = (element.textContent ?? '').replace(/\\n$/, '');\n\n out.push(block('block:code', text ? [{ insert: text }] : [], { language }));\n return;\n }\n\n case 'HR':\n flush();\n out.push(block('block:divider', []));\n return;\n\n case 'BLOCKQUOTE': {\n flush();\n\n if (hasBlockDescendant(element)) {\n const inner: FragmentBlock[] = [];\n collect(element, next, inner, depth + 1);\n\n out.push(\n ...inner.map((b) =>\n b.flavour === 'block:paragraph' ? { ...b, flavour: 'block:quote' } : b,\n ),\n );\n } else {\n const content: InlineNode[] = [];\n element.childNodes.forEach((child) => inlineOf(child, next, content, depth + 1));\n const cleaned = cleanInline(content);\n\n if (cleaned.length > 0) out.push(block('block:quote', cleaned));\n }\n return;\n }\n\n case 'TABLE': {\n flush();\n\n // Таблиц в Inkbrick нет: каждая строка — абзац, ячейки через табуляцию.\n element.querySelectorAll('tr').forEach((row) => {\n const cells: InlineNode[] = [];\n\n row.querySelectorAll(':scope > td, :scope > th').forEach((cell, index) => {\n const content: InlineNode[] = [];\n\n if (index > 0) cells.push({ insert: '\\t' });\n cell.childNodes.forEach((child) => inlineOf(child, next, content, depth + 1));\n cells.push(...cleanInline(content));\n });\n\n const cleaned = normalizeInlineNodes(cells);\n\n if (cleaned.length > 0) out.push(block('block:paragraph', cleaned));\n });\n return;\n }\n }\n\n /*\n * Любой контейнер с блочными потомками (в том числе обёртка Google Docs `<b style=\"font-weight:normal\">`)\n * разбираем по блокам, сохраняя унаследованный стиль.\n */\n if (hasBlockDescendant(element)) {\n flush();\n collect(element, next, out, depth + 1);\n return;\n }\n\n if (BLOCK_TAGS.has(tag)) {\n flush();\n\n const content: InlineNode[] = [];\n element.childNodes.forEach((child) => inlineOf(child, next, content, depth + 1));\n const cleaned = cleanInline(content);\n\n if (cleaned.length > 0) out.push(block('block:paragraph', cleaned));\n\n element.querySelectorAll('img').forEach((img) => {\n const image = imageBlock(img);\n\n if (image) out.push(image);\n });\n return;\n }\n\n inlineOf(element, style, run, depth + 1);\n });\n\n flush();\n}\n","import { type InlineNode, normalizeInlineNodes } from '@inkbrick/document';\nimport { attributesOf, isHidden, styleOf } from './style';\nimport { BLOCK_TAGS, MAX_DEPTH, SKIP_TAGS, type Style, tagOf } from './tags';\n\n/** Приводит к виду, который показал бы браузер: сворачивает пробелы между узлами, обрезает края. */\nexport function cleanInline(nodes: InlineNode[], preserve = false): InlineNode[] {\n if (preserve) return normalizeInlineNodes(nodes.filter((n) => n.insert.length > 0));\n\n const cleaned: InlineNode[] = [];\n let previousSpace = true; // пробелы в начале блока отбрасываем\n\n for (const node of nodes) {\n let text = '';\n\n for (const ch of node.insert.replace(/\\u00a0/g, ' ')) {\n if (ch === '\\n') {\n text = text.replace(/ $/, '') + ch;\n previousSpace = true;\n } else if (/\\s/.test(ch)) {\n if (!previousSpace) text += ' ';\n previousSpace = true;\n } else {\n text += ch;\n previousSpace = false;\n }\n }\n\n if (text)\n cleaned.push({ insert: text, ...(node.attributes ? { attributes: node.attributes } : {}) });\n }\n\n while (cleaned.length > 0) {\n const last = cleaned[cleaned.length - 1];\n const trimmed = last.insert.replace(/[ \\n]+$/, '');\n\n if (trimmed === '') cleaned.pop();\n else {\n last.insert = trimmed;\n break;\n }\n }\n\n while (cleaned.length > 0 && /^\\n+/.test(cleaned[0].insert)) {\n cleaned[0].insert = cleaned[0].insert.replace(/^\\n+/, '');\n if (cleaned[0].insert === '') cleaned.shift();\n }\n\n return normalizeInlineNodes(cleaned);\n}\n\nexport function inlineOf(\n node: Node,\n style: Style,\n out: InlineNode[],\n depth: number,\n preserve = false,\n): void {\n if (depth > MAX_DEPTH) return;\n\n if (node.nodeType === Node.TEXT_NODE) {\n const raw = node.textContent ?? '';\n const text = preserve ? raw : raw.replace(/[\\t\\n\\r\\f ]+/g, ' ');\n const attributes = attributesOf(style);\n\n if (text) out.push({ insert: text, ...(attributes ? { attributes } : {}) });\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n\n const element = node as HTMLElement;\n\n if (SKIP_TAGS.has(tagOf(element)) || isHidden(element)) return;\n\n // Номера/маркеры Word (`mso-list:Ignore`) — не текст.\n if (/mso-list:\\s*ignore/i.test(element.getAttribute('style') ?? '')) return;\n\n if (tagOf(element) === 'BR') {\n out.push({ insert: '\\n' });\n return;\n }\n\n const next = styleOf(element, style);\n const isBlock = BLOCK_TAGS.has(tagOf(element));\n\n // Блочный элемент внутри inline-контекста (абзацы внутри пункта списка) отделяется переводом строки.\n if (isBlock && out.length > 0) out.push({ insert: '\\n' });\n\n element.childNodes.forEach((child) => inlineOf(child, next, out, depth + 1, preserve));\n\n if (isBlock) out.push({ insert: '\\n' });\n}\n","import { type TextAttributes, isSafeUrl, normalizeLinkUrl } from '@inkbrick/document';\nimport { type Style, tagOf } from './tags';\n\nexport function weight(value: string): boolean | undefined {\n const v = value.trim().toLowerCase();\n\n if (v === '') return undefined;\n if (v === 'bold' || v === 'bolder') return true;\n if (v === 'normal' || v === 'lighter') return false;\n\n const n = Number(v);\n\n return Number.isNaN(n) ? undefined : n >= 600;\n}\n\nexport function styleOf(element: HTMLElement, base: Style): Style {\n const style: Style = { ...base };\n\n switch (tagOf(element)) {\n case 'B':\n case 'STRONG':\n style.bold = true;\n break;\n case 'I':\n case 'EM':\n case 'CITE':\n case 'DFN':\n style.italic = true;\n break;\n case 'U':\n case 'INS':\n style.underline = true;\n break;\n case 'S':\n case 'DEL':\n case 'STRIKE':\n style.strike = true;\n break;\n case 'CODE':\n case 'KBD':\n case 'SAMP':\n case 'TT':\n style.code = true;\n break;\n case 'A': {\n const href = element.getAttribute('href');\n const link = href ? normalizeLinkUrl(href) : null;\n\n if (link) style.link = link;\n break;\n }\n }\n\n // Встроенные стили (Google Docs / Word передают форматирование ими) переопределяют теги.\n const css = element.style;\n\n if (css) {\n const bold = weight(css.fontWeight ?? '');\n if (bold !== undefined) style.bold = bold;\n\n const italic = (css.fontStyle ?? '').toLowerCase();\n if (italic === 'italic' || italic === 'oblique') style.italic = true;\n else if (italic === 'normal') style.italic = false;\n\n const decoration = `${css.textDecorationLine ?? ''} ${css.textDecoration ?? ''}`.toLowerCase();\n if (decoration.includes('underline')) style.underline = true;\n if (decoration.includes('line-through')) style.strike = true;\n }\n\n return style;\n}\n\nexport function attributesOf(style: Style): TextAttributes | undefined {\n const attributes: TextAttributes = {};\n\n if (style.bold) attributes.bold = true;\n if (style.italic) attributes.italic = true;\n if (style.underline) attributes.underline = true;\n if (style.strike) attributes.strike = true;\n if (style.code) attributes.code = true;\n if (style.link && isSafeUrl(style.link)) attributes.link = style.link;\n\n return Object.keys(attributes).length > 0 ? attributes : undefined;\n}\n\nexport function isHidden(element: HTMLElement): boolean {\n return (\n element.hasAttribute('hidden') ||\n element.style?.display === 'none' ||\n element.style?.visibility === 'hidden'\n );\n}\n","export const MAX_DEPTH = 60;\n\nexport const SKIP_TAGS = new Set([\n 'MATH',\n 'SCRIPT',\n 'STYLE',\n 'HEAD',\n 'TEMPLATE',\n 'NOSCRIPT',\n 'IFRAME',\n 'OBJECT',\n 'EMBED',\n 'SVG',\n 'CANVAS',\n 'IMG',\n 'VIDEO',\n 'AUDIO',\n 'TITLE',\n 'META',\n 'LINK',\n 'INPUT',\n 'BUTTON',\n 'SELECT',\n 'TEXTAREA',\n 'FORM',\n]);\n\nexport const BLOCK_TAGS = new Set([\n 'P',\n 'DIV',\n 'H1',\n 'H2',\n 'H3',\n 'H4',\n 'H5',\n 'H6',\n 'UL',\n 'OL',\n 'LI',\n 'BLOCKQUOTE',\n 'PRE',\n 'HR',\n 'TABLE',\n 'TR',\n 'SECTION',\n 'ARTICLE',\n 'HEADER',\n 'FOOTER',\n 'MAIN',\n 'ASIDE',\n 'NAV',\n 'FIGURE',\n 'FIGCAPTION',\n 'DL',\n 'DT',\n 'DD',\n 'ADDRESS',\n 'FIELDSET',\n 'BODY',\n 'HTML',\n 'TBODY',\n 'THEAD',\n 'TFOOT',\n 'CAPTION',\n]);\n\n/** Имя тега в верхнем регистре: у SVG/MathML элементов tagName строчный. */\nexport const tagOf = (element: Element): string => element.localName.toUpperCase();\n\nexport interface Style {\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n code?: boolean;\n link?: string;\n}\n","import { isSafeImageUrl } from '@inkbrick/document';\n\nimport { ImageError } from './ImageError';\nimport { DEFAULT_IMAGE_TYPES, DEFAULT_MAX_INLINE_BYTES, type ImageOptions } from './types';\n\nexport function isAcceptedImage(file: { type: string }, options: ImageOptions): boolean {\n return (options.acceptedTypes ?? DEFAULT_IMAGE_TYPES).includes(file.type.toLowerCase());\n}\n\nfunction readAsDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => resolve(String(reader.result));\n reader.onerror = () => reject(new ImageError('read', 'Could not read the file'));\n reader.readAsDataURL(file);\n });\n}\n\nexport async function uploadImage(file: File, options: ImageOptions): Promise<string> {\n if (!isAcceptedImage(file, options)) {\n const type = file.type || 'unknown';\n\n throw new ImageError('type', `Unsupported image type \"${type}\"`, { type });\n }\n\n let url: string;\n\n if (options.upload) {\n url = await options.upload(file);\n } else {\n const limit = options.maxInlineBytes ?? DEFAULT_MAX_INLINE_BYTES;\n\n if (file.size > limit) {\n const size = Math.round(limit / 1024);\n\n throw new ImageError(\n 'size',\n `The image is larger than ${size} KB. Provide \"images.upload\" to store larger images.`,\n { size },\n );\n }\n\n url = await readAsDataUrl(file);\n }\n\n if (!isSafeImageUrl(url))\n throw new ImageError('uploadAddress', 'The upload returned an unsupported image address');\n\n return url;\n}\n\nexport function normalizeImageUrl(input: string): string | null {\n const value = input.trim();\n\n if (value === '') return null;\n\n const candidate =\n /^[a-z][a-z0-9+.-]*:/i.test(value) || value.startsWith('/') ? value : `https://${value}`;\n\n return isSafeImageUrl(candidate) ? candidate : null;\n}\n","import type { MessageKey } from '../i18n/en';\nimport type { MessageParams, TFunction } from '../i18n/translate';\n\nexport type ImageErrorCode = 'type' | 'size' | 'uploadAddress' | 'read';\n\n/**\n * Ошибка добавления картинки. `message` — английский текст для разработчика (попадает в `onError` и консоль);\n * в интерфейсе ошибка показывается переведённой по `code`.\n */\nexport class ImageError extends Error {\n constructor(\n readonly code: ImageErrorCode,\n message: string,\n readonly params?: MessageParams,\n ) {\n super(message);\n this.name = 'ImageError';\n }\n}\n\nexport interface ImageErrorInfo {\n readonly message: string;\n readonly code?: ImageErrorCode;\n readonly params?: MessageParams;\n}\n\nexport function toImageErrorInfo(error: unknown): ImageErrorInfo {\n if (error instanceof ImageError) {\n return { message: error.message, code: error.code, params: error.params };\n }\n\n return { message: error instanceof Error ? error.message : '' };\n}\n\nexport function formatImageError(info: ImageErrorInfo, t: TFunction): string {\n if (info.code) return t(`image.error.${info.code}` as MessageKey, info.params);\n\n return info.message || t('image.error.generic');\n}\n","export const DEFAULT_IMAGE_TYPES = [\n 'image/png',\n 'image/jpeg',\n 'image/gif',\n 'image/webp',\n 'image/avif',\n] as const;\n\nexport const DEFAULT_MAX_INLINE_BYTES = 1_500_000;\n\nexport interface ImageOptions {\n /**\n * Загружает файл и возвращает адрес картинки (http(s) или относительный). Без него картинки\n * встраиваются в документ как data:-адреса (до `maxInlineBytes`).\n */\n readonly upload?: (file: File) => Promise<string>;\n /** Предел размера для встраивания data:-картинки, байт (по умолчанию 1,5 МБ). */\n readonly maxInlineBytes?: number;\n /** Допустимые MIME-типы (по умолчанию PNG, JPEG, GIF, WebP, AVIF). SVG не поддерживается. */\n readonly acceptedTypes?: readonly string[];\n readonly onError?: (error: unknown, file: File) => void;\n}\n","import { useContext } from 'react';\n\nimport { DocumentRendererContext } from '../renderer/DocumentRenderer';\nimport { useChildren } from '../hooks/useChildren';\n\nimport type { BlockId } from '@inkbrick/document';\n\n/**\n * Выводит дочерние блоки `id` — для пользовательских компонентов-контейнеров. Как именно (все сразу или только\n * видимые), решает рендерер документа (`<DocumentView renderer>`).\n */\nexport function BlockChildren({ id }: { readonly id: BlockId }) {\n const children = useChildren(id);\n const { ChildList } = useContext(DocumentRendererContext);\n\n return <ChildList parentId={id} ids={children} />;\n}\n","import { createContext, type ComponentType } from 'react';\n\nimport type { BlockId } from '@inkbrick/document';\n\nimport { BlockRenderer } from './BlockRenderer';\n\nexport interface ChildListProps {\n readonly parentId: BlockId;\n readonly ids: readonly BlockId[];\n}\n\n/**\n * Способ отрисовки документа: как выводить детей каждого контейнера (страницы, заметки, вложенного списка).\n * Модель и команды от него не зависят. Встроенные варианты — `fullRenderer` (всё дерево, по умолчанию)\n * и `virtualRenderer()` (только блоки около видимой области).\n */\nexport interface DocumentRenderer {\n readonly ChildList: ComponentType<ChildListProps>;\n}\n\nfunction FullChildList({ ids }: ChildListProps) {\n return (\n <>\n {ids.map((id) => (\n <BlockRenderer key={id} id={id} />\n ))}\n </>\n );\n}\n\nexport const fullRenderer: DocumentRenderer = { ChildList: FullChildList };\n\nexport const DocumentRendererContext = createContext<DocumentRenderer>(fullRenderer);\n","import { memo, useSyncExternalStore } from 'react';\n\nimport type { BlockId } from '@inkbrick/document';\n\nimport { BlockChildren } from '../blocks/BlockChildren';\nimport { UnknownBlockView } from '../blocks/UnknownBlockView';\nimport { useBlock } from '../hooks/useBlock';\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { resolveBlockComponent } from '../registry/resolveBlockComponent';\nimport { useEditorUI } from '../ui/EditorUIContext';\n\nexport interface BlockRendererProps {\n readonly id: BlockId;\n}\n\nconst warned = new Set<string>();\n\nexport const BlockRenderer = memo(function BlockRenderer({ id }: BlockRendererProps) {\n const editor = useEditor();\n const view = useEditorView();\n const readOnly = useReadOnly();\n const { components, slots } = useEditorUI();\n const selected = useSyncExternalStore(\n view.selection.subscribe,\n () => view.selection.isSelected(id),\n () => false,\n );\n const block = useBlock(id);\n\n if (!block) {\n return null;\n }\n\n const Component = resolveBlockComponent(block.flavour, components);\n\n if (Component) {\n return (\n <Component\n block={block}\n editor={editor}\n selected={selected}\n readOnly={readOnly}\n controller={editor.controllers.get(block.flavour)}\n />\n );\n }\n\n // Неизвестный тип блока не должен ронять редактор и не должен подменяться другим типом.\n if (!warned.has(block.flavour)) {\n warned.add(block.flavour);\n console.warn(`[@inkbrick/react] No component registered for block \"${block.flavour}\"`);\n }\n\n const Fallback = slots.UnknownBlock ?? UnknownBlockView;\n\n return (\n <Fallback block={block} editor={editor} selected={selected} readOnly={readOnly}>\n <BlockChildren id={block.id} />\n </Fallback>\n );\n});\n","import { useT } from '../hooks/useT';\nimport type { UnknownBlockViewProps } from '../ui/types';\n\n/**\n * Стандартная заглушка для блока с незарегистрированным flavour.\n * Не редактируется; данные блока остаются в документе нетронутыми.\n */\nexport function UnknownBlockView({ block, children }: UnknownBlockViewProps) {\n const t = useT();\n\n return (\n <div\n className=\"block block-unknown\"\n data-inkbrick-block=\"unknown\"\n role=\"note\"\n contentEditable={false}\n data-block-id={block.id}\n data-unknown-flavour={block.flavour}\n >\n <div className=\"block-unknown__message\" data-inkbrick-part=\"message\">\n {t('block.unknown.title')} <code>{block.flavour}</code>. {t('block.unknown.hint')}{' '}\n <code>components</code>.\n </div>\n {children}\n </div>\n );\n}\n","import { BlockChildren } from './BlockChildren';\nimport type { BlockProps } from './BlockProps';\n\nexport function PageBlock({ block }: BlockProps) {\n return (\n <div className=\"page\" data-inkbrick-block=\"page\" data-block-id={block.id}>\n <BlockChildren id={block.id} />\n </div>\n );\n}\n","import { BlockChildren } from './BlockChildren';\nimport type { BlockProps } from './BlockProps';\n\nexport function NoteBlock({ block }: BlockProps) {\n return (\n <section className=\"page-content\" data-inkbrick-block=\"note\" data-block-id={block.id}>\n <BlockChildren id={block.id} />\n </section>\n );\n}\n","import { getBlockAlign } from '@inkbrick/document';\n\nimport { Editable } from './Editable';\nimport type { BlockProps } from './BlockProps';\n\nexport function ParagraphBlock({ block, selected }: BlockProps) {\n const align = getBlockAlign(block) ?? 'left';\n\n return (\n <div\n className=\"block block-paragraph\"\n data-inkbrick-block=\"paragraph\"\n data-block-id={block.id}\n data-selected={selected || undefined}\n data-align={align}\n >\n <Editable block={block} />\n </div>\n );\n}\n","import { useLayoutEffect, useRef, useSyncExternalStore } from 'react';\n\nimport type { BaseBlock } from '@inkbrick/document';\n\nimport { renderCode } from '../editing/renderCode';\nimport { renderInline } from '../editing/renderInline';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { useT } from '../hooks/useT';\nimport { useEditorUI } from '../ui/EditorUIContext';\n\nexport interface EditableProps {\n readonly block: BaseBlock;\n /**\n * Собственная подсказка пустого блока (показывается всегда, пока блок пуст). Не нужна: по умолчанию редактор\n * сам показывает одну общую подсказку («Нажмите / …») в пустом блоке, где стоит каретка.\n */\n readonly placeholder?: string;\n}\n\n/**\n * Текст блока. Сам по себе не является contenteditable: редактируемым элементом\n * служит корень `<DocumentView>`, благодаря чему выделение может охватывать несколько блоков.\n * Содержимое рисуется из `block.content`, а ввод обрабатывается корнем через движок.\n *\n * Атрибуты для стилизации: `data-empty`, `data-focused` (каретка в этом блоке), `data-hint` (текст общей\n * подсказки; есть только там, где работает slash-меню), `data-placeholder` (своя подсказка, если задана).\n */\nexport function Editable({ block, placeholder }: EditableProps) {\n const ref = useRef<HTMLDivElement>(null);\n const view = useEditorView();\n const t = useT();\n const readOnly = useReadOnly();\n const { slashItems, highlighter, formulaRenderer } = useEditorUI();\n const focused = useSyncExternalStore(\n view.caret.subscribe,\n () => view.caret.has(block.id),\n () => false,\n );\n\n useLayoutEffect(() => view.register(block.id, ref.current!), [view, block.id]);\n\n const isCode = block.flavour === 'block:code';\n const language = typeof block.props.language === 'string' ? block.props.language : 'plain';\n\n useLayoutEffect(() => {\n const plain = block.content.every((node) => !node.attributes);\n\n // Код — простой текст: подсветка только оборачивает его в <span data-inkbrick-token>, не меняя символов.\n if (isCode && highlighter && plain) {\n const text = block.content.map((node) => node.insert).join('');\n let tokens: ReturnType<typeof highlighter> = [];\n\n try {\n tokens = highlighter(text, language);\n } catch (error) {\n // Ошибка подсветчика (в том числе чужого) не должна ронять редактор: показываем текст без подсветки.\n console.error('[@inkbrick/react] The code highlighter failed:', error);\n }\n\n renderCode(ref.current!, text, tokens);\n } else {\n renderInline(ref.current!, block.content, { formulaRenderer });\n }\n }, [block.content, isCode, language, highlighter, formulaRenderer]);\n\n const isEmpty = block.content.every((node) => node.insert.length === 0);\n\n // Подсказка про «/» уместна там, где меню открывается: не в режиме чтения, не в коде и если меню не отключено.\n const hinted = !readOnly && slashItems.length > 0 && block.flavour !== 'block:code';\n\n return (\n <div\n ref={ref}\n className=\"editable\"\n data-inkbrick-part=\"content\"\n data-id={block.id}\n data-empty={isEmpty}\n data-focused={focused || undefined}\n data-hint={hinted ? t('editor.hint') : undefined}\n data-placeholder={placeholder}\n />\n );\n}\n","import type { HighlightToken } from '../code/types';\n\nconst TOKEN_TYPE = /^[a-z][a-z0-9-]{0,31}$/;\n\n/**\n * Приводит токены подсветчика к безопасному виду: границы внутри текста, без пересечений и пустых токенов,\n * тип — короткое имя из строчных букв, цифр и дефисов (он попадает в атрибут разметки). Порядок не важен.\n */\nexport function normalizeTokens(\n tokens: readonly HighlightToken[],\n length: number,\n): HighlightToken[] {\n const valid = tokens\n .filter(\n (token) =>\n Number.isInteger(token.from) &&\n Number.isInteger(token.to) &&\n token.from >= 0 &&\n token.to <= length &&\n token.from < token.to &&\n TOKEN_TYPE.test(token.type),\n )\n .sort((a, b) => a.from - b.from || b.to - a.to);\n\n const result: HighlightToken[] = [];\n let end = 0;\n\n for (const token of valid) {\n if (token.from >= end) {\n result.push(token);\n end = token.to;\n }\n }\n\n return result;\n}\n\n/**\n * Рисует текст блока кода с подсветкой: токены становятся `<span data-inkbrick-token=\"тип\">`, остальное — текстовые узлы.\n * Текст в DOM всегда равен тексту модели (подсветка только оборачивает его), поэтому смещения курсора и выделения\n * считаются как обычно. Как и в `renderInline`, пустой блок и завершающий перевод строки получают `<br>`.\n */\nexport function renderCode(\n root: HTMLElement,\n text: string,\n tokens: readonly HighlightToken[],\n): void {\n const doc = globalThis.document;\n const fragment = doc.createDocumentFragment();\n let position = 0;\n\n for (const token of normalizeTokens(tokens, text.length)) {\n if (token.from > position)\n fragment.appendChild(doc.createTextNode(text.slice(position, token.from)));\n\n const span = doc.createElement('span');\n\n span.setAttribute('data-inkbrick-token', token.type);\n span.textContent = text.slice(token.from, token.to);\n fragment.appendChild(span);\n position = token.to;\n }\n\n if (position < text.length) fragment.appendChild(doc.createTextNode(text.slice(position)));\n\n if (text === '' || text.endsWith('\\n')) fragment.appendChild(doc.createElement('br'));\n\n root.replaceChildren(fragment);\n}\n","import {\n FORMULA_CHAR,\n isColorName,\n isSafeUrl,\n safeCssColor,\n type InlineNode,\n type TextAttributes,\n} from '@inkbrick/document';\n\nimport { ensureMathStyles, mountFormula, type FormulaRenderer } from '../math/renderer';\n\nexport interface RenderInlineOptions {\n readonly formulaRenderer?: FormulaRenderer | null;\n}\n\nfunction wrap(node: Node, tag: keyof HTMLElementTagNameMap): HTMLElement {\n const element = globalThis.document.createElement(tag);\n element.appendChild(node);\n return element;\n}\n\n/**\n * Встроенная формула — нередактируемый «объект» из одного символа. Сама формула рисуется в теневом корне: так её\n * внутренний текст (MathML) не попадает в `Range.toString()` и `textContent`, и смещения курсора остаются равными\n * смещениям модели (объект занимает ровно один символ — `FORMULA_CHAR` в обычном DOM).\n */\nfunction renderFormulaAtom(latex: string, options: RenderInlineOptions): HTMLElement {\n const doc = globalThis.document;\n const host = doc.createElement('span');\n\n host.setAttribute('data-inkbrick-formula', '');\n host.setAttribute('data-inkbrick-part', 'formula-inline');\n host.setAttribute('data-latex', latex);\n host.setAttribute('contenteditable', 'false');\n host.textContent = FORMULA_CHAR;\n\n const view = doc.createElement('span');\n\n view.setAttribute('part', 'math');\n\n try {\n const shadow = host.attachShadow({ mode: 'open' });\n\n ensureMathStyles(shadow);\n shadow.appendChild(view);\n } catch {\n // Теневой DOM недоступен: исходный код показывает CSS (`[data-state='fallback']::after`), смещения не меняются.\n host.setAttribute('data-state', 'fallback');\n\n return host;\n }\n\n mountFormula(view, latex, {\n display: false,\n renderer: options.formulaRenderer ?? null,\n onSettled: (state) => host.setAttribute('data-state', state),\n });\n host.setAttribute('data-state', view.getAttribute('data-state') ?? 'loading');\n\n return host;\n}\n\nfunction renderNode(\n insert: string,\n attributes: TextAttributes | undefined,\n options: RenderInlineOptions,\n): Node {\n let node: Node;\n\n if (typeof attributes?.formula === 'string') {\n const fragment = globalThis.document.createDocumentFragment();\n\n for (let i = 0; i < insert.length; i++)\n fragment.appendChild(renderFormulaAtom(attributes.formula, options));\n\n node = fragment;\n } else {\n node = globalThis.document.createTextNode(insert);\n }\n\n if (!attributes) return node;\n\n if (attributes.code) node = wrap(node, 'code');\n if (attributes.bold) node = wrap(node, 'strong');\n if (attributes.italic) node = wrap(node, 'em');\n if (attributes.underline) node = wrap(node, 'u');\n if (attributes.strike) node = wrap(node, 's');\n\n if (typeof attributes.link === 'string' && isSafeUrl(attributes.link)) {\n const anchor = wrap(node, 'a') as HTMLAnchorElement;\n anchor.href = attributes.link.trim();\n anchor.rel = 'noopener noreferrer';\n anchor.target = '_blank';\n node = anchor;\n }\n\n const color = attributes.color;\n const background = attributes.backgroundColor;\n const safeColor = isColorName(color) ? null : safeCssColor(color);\n const safeBackground = isColorName(background) ? null : safeCssColor(background);\n\n if (isColorName(color) || isColorName(background) || safeColor || safeBackground) {\n const span = wrap(node, 'span');\n\n if (isColorName(color)) span.setAttribute('data-inkbrick-color', color);\n else if (safeColor) span.style.color = safeColor;\n\n if (isColorName(background)) span.setAttribute('data-inkbrick-bg', background);\n else if (safeBackground) span.style.backgroundColor = safeBackground;\n\n node = span;\n }\n\n return node;\n}\n\n/**\n * Перерисовывает содержимое блока из модели. Содержимое contenteditable\n * намеренно рисуется императивно, а не через React: браузер может менять DOM\n * (например, при IME-вводе), и React не должен с этим конфликтовать.\n */\nexport function renderInline(\n root: HTMLElement,\n nodes: readonly InlineNode[],\n options: RenderInlineOptions = {},\n): void {\n const fragment = globalThis.document.createDocumentFragment();\n\n for (const { insert, attributes } of nodes) {\n if (insert.length > 0) fragment.appendChild(renderNode(insert, attributes, options));\n }\n\n /*\n * <br> нужен в двух случаях: пустой блок (иначе в нём нельзя поставить курсор)\n * и завершающий перевод строки в white-space: pre-wrap (виден только с <br> после него).\n * На смещения текста <br> не влияет: Range.toString() его игнорирует.\n */\n const text = nodes.map((node) => node.insert).join('');\n if (text === '' || text.endsWith('\\n')) {\n fragment.appendChild(globalThis.document.createElement('br'));\n }\n\n root.replaceChildren(fragment);\n}\n","import { getBlockAlign } from '@inkbrick/document';\n\nimport { Editable } from './Editable';\nimport type { BlockProps } from './BlockProps';\n\nexport function HeadingBlock({ block, selected }: BlockProps) {\n const level = typeof block.props.level === 'number' ? block.props.level : 1;\n const align = getBlockAlign(block) ?? 'left';\n\n return (\n <div\n className={`block block-heading level-${level}`}\n data-inkbrick-block=\"heading\"\n data-level={level}\n data-block-id={block.id}\n data-selected={selected || undefined}\n data-align={align}\n >\n <Editable block={block} />\n </div>\n );\n}\n","import { getBlockAlign } from '@inkbrick/document';\n\nimport { BlockChildren } from './BlockChildren';\nimport { useBlock } from '../hooks/useBlock';\nimport { useChildren } from '../hooks/useChildren';\nimport { useEditor } from '../hooks/useEditor';\nimport { useT } from '../hooks/useT';\nimport { Editable } from './Editable';\nimport type { BlockProps } from './BlockProps';\n\nfunction useOrderedNumber(block: BlockProps['block']): number {\n const { store } = useEditor();\n const parent = useBlock(block.parentId ?? '');\n\n if (!parent) return 1;\n\n let number = 1;\n\n for (let i = parent.children.indexOf(block.id) - 1; i >= 0; i--) {\n const sibling = store.getBlock(parent.children[i]);\n\n if (sibling?.flavour !== 'block:list' || sibling.props.type !== 'ordered') break;\n\n number++;\n }\n\n return number;\n}\n\nexport function ListBlock({ block, selected, readOnly }: BlockProps) {\n const editor = useEditor();\n const t = useT();\n const children = useChildren(block.id);\n const orderedNumber = useOrderedNumber(block);\n\n const type = typeof block.props.type === 'string' ? block.props.type : 'bullet';\n\n return (\n <div\n className=\"block-list-item\"\n data-inkbrick-block=\"list\"\n data-align={getBlockAlign(block) ?? 'left'}\n data-block-id={block.id}\n data-list-type={type}\n data-checked={type === 'todo' ? block.props.checked === true : undefined}\n data-selected={selected || undefined}\n >\n <div className=\"block block-list\" data-inkbrick-part=\"row\" data-list-type={type}>\n {type === 'todo' ? (\n <input\n className=\"list-marker list-checkbox\"\n data-inkbrick-part=\"checkbox\"\n type=\"checkbox\"\n aria-label={t('block.list.done')}\n contentEditable={false}\n disabled={readOnly}\n checked={block.props.checked === true}\n onChange={(event) =>\n editor.dispatch({\n type: 'setBlockProps',\n payload: { blockId: block.id, props: { checked: event.target.checked } },\n })\n }\n />\n ) : (\n <span\n className=\"list-marker\"\n data-inkbrick-part=\"marker\"\n contentEditable={false}\n aria-hidden=\"true\"\n >\n {type === 'ordered' ? `${orderedNumber}.` : '•'}\n </span>\n )}\n\n <Editable block={block} />\n </div>\n\n {children.length > 0 && (\n <div className=\"block-nested-children\" data-inkbrick-part=\"children\">\n <BlockChildren id={block.id} />\n </div>\n )}\n </div>\n );\n}\n","import { getBlockAlign } from '@inkbrick/document';\n\nimport { Editable } from './Editable';\nimport type { BlockProps } from './BlockProps';\n\nexport function QuoteBlock({ block, selected }: BlockProps) {\n return (\n <blockquote\n className=\"block block-quote\"\n data-inkbrick-block=\"quote\"\n data-align={getBlockAlign(block) ?? 'left'}\n data-block-id={block.id}\n data-selected={selected || undefined}\n >\n <Editable block={block} />\n </blockquote>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { useT } from '../hooks/useT';\nimport { Icon } from '../icons/Icon';\nimport { Editable } from './Editable';\nimport type { BlockViewProps } from '../ui/types';\n\n/**\n * Языки в выпадающем списке. Редактор хранит только `language`; подсветку делает `highlighter` провайдера\n * (по умолчанию встроенный — он знает эти языки и их псевдонимы).\n */\nexport const CODE_LANGUAGES = [\n 'plain',\n 'typescript',\n 'javascript',\n 'json',\n 'html',\n 'css',\n 'python',\n 'bash',\n 'sql',\n 'go',\n 'rust',\n 'java',\n 'c',\n 'cpp',\n 'markdown',\n 'yaml',\n] as const;\n\nexport function CodeBlock({ block, editor, selected, readOnly }: BlockViewProps) {\n const t = useT();\n const language = typeof block.props.language === 'string' ? block.props.language : 'plain';\n const languages = CODE_LANGUAGES.includes(language as (typeof CODE_LANGUAGES)[number])\n ? CODE_LANGUAGES\n : [...CODE_LANGUAGES, language];\n\n const [copied, setCopied] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n const copy = () => {\n const text = block.content.map((node) => node.insert).join('');\n\n void navigator.clipboard?.writeText(text).then(() => {\n setCopied(true);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), 1500);\n });\n };\n\n return (\n <div\n className=\"block block-code\"\n data-inkbrick-block=\"code\"\n data-block-id={block.id}\n data-language={language}\n data-selected={selected || undefined}\n >\n <div className=\"code-toolbar\" data-inkbrick-part=\"toolbar\" contentEditable={false}>\n <select\n className=\"code-language\"\n data-inkbrick-part=\"language\"\n aria-label={t('block.code.language')}\n disabled={readOnly}\n value={language}\n onChange={(event) =>\n editor.dispatch({\n type: 'setBlockProps',\n payload: { blockId: block.id, props: { language: event.target.value } },\n })\n }\n >\n {languages.map((name) => (\n <option key={name} value={name}>\n {name}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n className=\"code-copy\"\n data-inkbrick-part=\"copy\"\n data-state={copied ? 'copied' : undefined}\n aria-label={copied ? t('block.code.copied') : t('block.code.copy')}\n title={copied ? t('block.code.copied') : t('block.code.copy')}\n onClick={copy}\n >\n <Icon name={copied ? 'check' : 'copy'} />\n </button>\n </div>\n <Editable block={block} />\n </div>\n );\n}\n","import type { BlockProps } from './BlockProps';\n\nexport function DividerBlock({ block, selected }: BlockProps) {\n return (\n <div\n className=\"block block-divider\"\n data-inkbrick-block=\"divider\"\n data-block-id={block.id}\n data-selected={selected || undefined}\n contentEditable={false}\n >\n <hr data-inkbrick-part=\"rule\" />\n </div>\n );\n}\n","import { CALLOUT_TONES, getBlockAlign } from '@inkbrick/document';\n\nimport { useT } from '../hooks/useT';\nimport { Icon, type IconName } from '../icons/Icon';\n\nimport { Editable } from './Editable';\nimport type { BlockViewProps } from '../ui/types';\n\nconst ICONS: Record<(typeof CALLOUT_TONES)[number], IconName> = {\n info: 'info',\n warning: 'warning',\n success: 'success',\n danger: 'danger',\n};\n\ntype Tone = (typeof CALLOUT_TONES)[number];\n\nconst isTone = (value: unknown): value is Tone => CALLOUT_TONES.includes(value as Tone);\n\nexport function CalloutBlock({ block, editor, selected, readOnly }: BlockViewProps) {\n const t = useT();\n const tone: Tone = isTone(block.props.tone) ? block.props.tone : 'info';\n const icon =\n typeof block.props.icon === 'string' && block.props.icon !== '' ? (\n block.props.icon\n ) : (\n <Icon name={ICONS[tone]} />\n );\n\n const nextTone = CALLOUT_TONES[(CALLOUT_TONES.indexOf(tone) + 1) % CALLOUT_TONES.length];\n\n return (\n <div\n className=\"block block-callout\"\n data-inkbrick-block=\"callout\"\n data-align={getBlockAlign(block) ?? 'left'}\n data-tone={tone}\n data-block-id={block.id}\n data-selected={selected || undefined}\n >\n <button\n type=\"button\"\n className=\"callout-icon\"\n data-inkbrick-part=\"icon\"\n contentEditable={false}\n disabled={readOnly}\n aria-label={t('block.callout.label', { tone: t(`block.callout.tone.${tone}`) })}\n title={t('block.callout.change')}\n onClick={() =>\n editor.dispatch({\n type: 'setBlockProps',\n payload: { blockId: block.id, props: { tone: nextTone } },\n })\n }\n >\n {icon}\n </button>\n <Editable block={block} />\n </div>\n );\n}\n","import { useEffect, useRef, useState, useSyncExternalStore } from 'react';\n\nimport { isSafeImageUrl } from '@inkbrick/document';\nimport type { Editor } from '@inkbrick/engine';\n\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useT } from '../hooks/useT';\nimport type { MessageKey } from '../i18n/en';\nimport { Icon, type IconName } from '../icons/Icon';\nimport { formatImageError } from '../images/ImageError';\nimport { fillImageBlock } from '../images/insertImages';\nimport { normalizeImageUrl } from '../images/upload';\nimport { DEFAULT_IMAGE_TYPES } from '../images/types';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport type { BlockViewProps } from '../ui/types';\n\nconst WIDTHS = [25, 50, 75, 100];\nconst ALIGNS: ReadonlyArray<{ value: string; label: MessageKey; icon: IconName }> = [\n { value: 'left', label: 'image.align.left', icon: 'align-left' },\n { value: 'center', label: 'image.align.center', icon: 'align-center' },\n { value: 'right', label: 'image.align.right', icon: 'align-right' },\n];\n\nconst setProps = (editor: Editor, blockId: string, props: Record<string, unknown>) =>\n editor.dispatch({ type: 'setBlockProps', payload: { blockId, props: props as never } });\n\n/** Поле, которое сохраняется по Enter/потере фокуса, а не на каждую букву (одна запись в истории). */\nfunction CommitInput({\n value,\n label,\n placeholder,\n className,\n part,\n onCommit,\n}: {\n value: string;\n label: string;\n placeholder: string;\n className: string;\n part: string;\n onCommit: (value: string) => void;\n}) {\n const [draft, setDraft] = useState(value);\n // Последнее сохранённое/известное значение: Enter сохраняет и тут же снимает фокус, а blur не должен сохранить второй раз.\n const saved = useRef(value);\n const cancelled = useRef(false);\n\n useEffect(() => {\n saved.current = value;\n setDraft(value);\n }, [value]);\n\n const commit = () => {\n if (cancelled.current) {\n cancelled.current = false;\n return;\n }\n\n if (draft !== saved.current) {\n saved.current = draft;\n onCommit(draft);\n }\n };\n\n return (\n <input\n className={className}\n data-inkbrick-part={part}\n type=\"text\"\n aria-label={label}\n placeholder={placeholder}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n commit();\n (event.target as HTMLInputElement).blur();\n } else if (event.key === 'Escape') {\n cancelled.current = true;\n setDraft(saved.current);\n (event.target as HTMLInputElement).blur();\n }\n }}\n />\n );\n}\n\nfunction ImagePicker({ blockId, editor }: { blockId: string; editor: Editor }) {\n const view = useEditorView();\n const t = useT();\n const { images } = useEditorUI();\n const [url, setUrl] = useState('');\n const [linkError, setLinkError] = useState<MessageKey | null>(null);\n const uploadError = useSyncExternalStore(\n view.uploads.subscribe,\n () => view.uploads.errorDetailsOf(blockId),\n () => undefined,\n );\n const error = linkError ? t(linkError) : uploadError ? formatImageError(uploadError, t) : null;\n const file = useRef<HTMLInputElement>(null);\n\n const embed = () => {\n const normalized = normalizeImageUrl(url);\n\n if (!normalized) {\n setLinkError('image.error.invalidLink');\n return;\n }\n\n if (\n editor.dispatch({\n type: 'setBlockProps',\n payload: { blockId, props: { src: normalized } },\n }) === undefined\n ) {\n setLinkError('image.error.unsupportedAddress');\n }\n };\n\n const upload = async (selected: File | undefined) => {\n if (!selected) return;\n\n setLinkError(null);\n await fillImageBlock(editor, view, images, blockId, selected);\n };\n\n return (\n <div className=\"image-picker\" data-inkbrick-part=\"picker\" data-testid=\"image-picker\">\n <div className=\"image-picker__row\" data-inkbrick-part=\"picker-row\">\n <input\n className=\"image-picker__input\"\n data-inkbrick-part=\"picker-input\"\n type=\"text\"\n aria-label={t('image.url.label')}\n aria-invalid={linkError !== null}\n placeholder={t('image.url.placeholder')}\n value={url}\n onChange={(event) => {\n setUrl(event.target.value);\n setLinkError(null);\n view.uploads.clearError(blockId);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n embed();\n }\n }}\n />\n <button\n type=\"button\"\n className=\"image-picker__button\"\n data-inkbrick-part=\"picker-button\"\n onClick={embed}\n >\n {t('image.embed')}\n </button>\n <button\n type=\"button\"\n className=\"image-picker__button\"\n onClick={() => file.current?.click()}\n >\n {t('image.upload')}\n </button>\n <input\n ref={file}\n type=\"file\"\n hidden\n data-testid=\"image-file\"\n accept={(images.acceptedTypes ?? DEFAULT_IMAGE_TYPES).join(',')}\n onChange={(event) => {\n void upload(event.target.files?.[0]);\n event.target.value = '';\n }}\n />\n </div>\n {error && (\n <div className=\"image-picker__error\" data-inkbrick-part=\"picker-error\" role=\"alert\">\n {error}\n </div>\n )}\n </div>\n );\n}\n\nexport function ImageBlock({ block, editor, selected, readOnly }: BlockViewProps) {\n const view = useEditorView();\n const t = useT();\n const uploading = useSyncExternalStore(\n view.uploads.subscribe,\n () => view.uploads.has(block.id),\n () => false,\n );\n\n const { src, alt, caption } = block.props as { src?: string; alt?: string; caption?: string };\n const width = typeof block.props.width === 'number' ? block.props.width : 100;\n const align = typeof block.props.align === 'string' ? block.props.align : 'center';\n const address = typeof src === 'string' ? src : '';\n\n const [failed, setFailed] = useState(false);\n\n useEffect(() => setFailed(false), [address]);\n\n let content;\n\n if (uploading) {\n content = (\n <div className=\"image-status\" data-inkbrick-part=\"status\" data-state=\"loading\" role=\"status\">\n {t('image.status.uploading')}\n </div>\n );\n } else if (address === '') {\n content = readOnly ? (\n <div className=\"image-status\" data-inkbrick-part=\"status\" data-state=\"empty\">\n {t('image.status.none')}\n </div>\n ) : (\n <ImagePicker blockId={block.id} editor={editor} />\n );\n } else if (!isSafeImageUrl(address)) {\n content = (\n <div\n className=\"image-status image-status--error\"\n data-inkbrick-part=\"status\"\n data-state=\"error\"\n >\n {t('image.status.unsupported')}\n </div>\n );\n } else if (failed) {\n content = (\n <div\n className=\"image-status image-status--error\"\n data-inkbrick-part=\"status\"\n data-state=\"error\"\n role=\"alert\"\n >\n {t('image.status.failed')}\n {!readOnly && (\n <button\n type=\"button\"\n className=\"image-picker__button\"\n data-inkbrick-part=\"picker-button\"\n onClick={() => setProps(editor, block.id, { src: '' })}\n >\n {t('image.status.retry')}\n </button>\n )}\n </div>\n );\n } else {\n content = (\n <figure\n className=\"image-figure\"\n data-inkbrick-part=\"figure\"\n data-align={align}\n style={{ width: `${width}%` }}\n >\n <img\n src={address}\n alt={alt ?? ''}\n loading=\"lazy\"\n decoding=\"async\"\n draggable={false}\n data-inkbrick-part=\"image\"\n referrerPolicy=\"no-referrer\"\n onError={() => setFailed(true)}\n />\n\n {!readOnly && (\n <div\n className=\"image-tools\"\n data-inkbrick-part=\"tools\"\n role=\"toolbar\"\n aria-label={t('image.options')}\n >\n {ALIGNS.map(({ value, label, icon }) => (\n <button\n key={value}\n type=\"button\"\n className=\"image-tools__button\"\n data-inkbrick-part=\"tool\"\n data-pressed={align === value || undefined}\n aria-label={t(label)}\n aria-pressed={align === value}\n title={t(label)}\n onClick={() => setProps(editor, block.id, { align: value })}\n >\n <Icon name={icon} />\n </button>\n ))}\n <select\n className=\"image-tools__select\"\n data-inkbrick-part=\"width\"\n aria-label={t('image.width')}\n value={WIDTHS.includes(width) ? width : ''}\n onChange={(event) =>\n setProps(editor, block.id, { width: Number(event.target.value) })\n }\n >\n {!WIDTHS.includes(width) && <option value=\"\">{width}%</option>}\n {WIDTHS.map((w) => (\n <option key={w} value={w}>\n {w}%\n </option>\n ))}\n </select>\n <CommitInput\n className=\"image-tools__alt\"\n part=\"alt\"\n label={t('image.alt')}\n placeholder={t('image.alt')}\n value={alt ?? ''}\n onCommit={(value) => setProps(editor, block.id, { alt: value })}\n />\n <button\n type=\"button\"\n className=\"image-tools__button\"\n data-inkbrick-part=\"tool\"\n aria-label={t('image.replace')}\n title={t('image.replace')}\n onClick={() => setProps(editor, block.id, { src: '' })}\n >\n <Icon name=\"replace\" />\n </button>\n </div>\n )}\n\n {readOnly ? (\n caption ? (\n <figcaption className=\"image-caption\" data-inkbrick-part=\"caption\">\n {caption}\n </figcaption>\n ) : null\n ) : (\n <CommitInput\n className=\"image-caption image-caption--input\"\n part=\"caption\"\n label={t('image.caption.label')}\n placeholder={t('image.caption.placeholder')}\n value={caption ?? ''}\n onCommit={(value) => setProps(editor, block.id, { caption: value })}\n />\n )}\n </figure>\n );\n }\n\n return (\n <div\n className=\"block block-image\"\n data-inkbrick-block=\"image\"\n data-block-id={block.id}\n data-selected={selected || undefined}\n contentEditable={false}\n >\n {content}\n </div>\n );\n}\n","import { flushSync } from 'react-dom';\n\nimport { createId } from '@inkbrick/document';\nimport type { CaretResult, Editor } from '@inkbrick/engine';\n\nimport type { EditorView } from '../editing/EditorView';\nimport { toImageErrorInfo } from './ImageError';\nimport type { ImageOptions } from './types';\nimport { isAcceptedImage, uploadImage } from './upload';\n\nexport function topLevelBlockId(editor: Editor, blockId: string): string {\n let current = editor.store.getBlock(blockId);\n\n while (current?.parentId) {\n const parent = editor.store.getBlock(current.parentId);\n\n if (!parent || parent.flavour === 'block:note' || !parent.parentId) break;\n\n current = parent;\n }\n\n return current?.id ?? blockId;\n}\n\nconst altFromName = (file: File) => file.name.replace(/\\.[^.]+$/, '').slice(0, 200);\n\nfunction report(options: ImageOptions, error: unknown, file: File): void {\n if (options.onError) options.onError(error, file);\n else console.error('[@inkbrick/react] Could not add the image:', error);\n}\n\nexport async function fillImageBlock(\n editor: Editor,\n view: EditorView,\n options: ImageOptions,\n blockId: string,\n file: File,\n mergeKey?: string,\n): Promise<boolean> {\n view.uploads.start(blockId);\n\n try {\n const src = await uploadImage(file, options);\n\n flushSync(() => {\n editor.dispatch({\n type: 'setBlockProps',\n payload: { blockId, props: { src, alt: altFromName(file) }, mergeKey },\n });\n });\n\n view.uploads.finish(blockId);\n\n return true;\n } catch (error) {\n view.uploads.finish(blockId, toImageErrorInfo(error));\n report(options, error, file);\n return false;\n }\n}\n\n/**\n * Вставляет картинки из файлов (вставка, перетаскивание) после блока `afterId`. Блок появляется сразу\n * (с индикатором загрузки); если загрузка не удалась, пустой блок убирается. Пустой параграф заменяется картинкой.\n * Возвращает false, если среди файлов нет подходящих изображений.\n */\nexport function insertImageFiles(\n editor: Editor,\n view: EditorView,\n options: ImageOptions,\n files: readonly File[],\n afterId: string,\n): boolean {\n const images = files.filter((file) => isAcceptedImage(file, options));\n\n if (images.length === 0 || editor.readOnly) return false;\n\n let anchor = topLevelBlockId(editor, afterId);\n let caret: CaretResult | undefined;\n\n const mergeKey = `images:${createId()}`;\n const created: Array<{ id: string; file: File }> = [];\n\n flushSync(() => {\n editor.batch(\n () => {\n for (const file of images) {\n const target = editor.store.getBlock(anchor);\n const alt = altFromName(file);\n\n // Пустой параграф заменяется картинкой (и под ней появляется параграф для продолжения).\n const emptyParagraph =\n target?.flavour === 'block:paragraph' &&\n target.content.length === 0 &&\n target.children.length === 0;\n\n if (emptyParagraph) {\n caret = editor.dispatch({\n type: 'convertBlock',\n payload: { blockId: anchor, flavour: 'block:image', props: { alt } },\n }) as CaretResult | undefined;\n created.push({ id: anchor, file });\n } else {\n const inserted = editor.dispatch({\n type: 'insertBlock',\n payload: { flavour: 'block:image', afterId: anchor, props: { alt } },\n }) as CaretResult | undefined;\n\n if (!inserted) continue;\n\n created.push({ id: inserted.blockId, file });\n anchor = inserted.blockId;\n\n if (!editor.document.getNextSibling(anchor)) {\n caret = editor.dispatch({\n type: 'insertBlock',\n payload: { flavour: 'block:paragraph', afterId: anchor },\n }) as CaretResult | undefined;\n } else {\n caret = { blockId: editor.document.getNextSibling(anchor)!.id, offset: 0 };\n }\n }\n }\n },\n { mergeKey },\n );\n });\n\n if (caret) view.placeCaret(caret.blockId, caret.offset);\n\n for (const { id, file } of created) {\n void fillImageBlock(editor, view, options, id, file, mergeKey).then((ok) => {\n if (!ok && (editor.store.getBlock(id)?.props.src ?? '') === '') {\n flushSync(() => {\n editor.execute('delete-block', { id });\n });\n }\n });\n }\n\n return true;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { MAX_FORMULA_LENGTH } from '@inkbrick/document';\n\nimport { useT } from '../hooks/useT';\nimport { LazyFormulaPalette } from '../formula/LazyFormulaPalette';\nimport { useSnippetInsert } from '../formula/snippet';\nimport { FormulaView } from '../math/FormulaView';\nimport type { BlockViewProps } from '../ui/types';\n\n/**\n * Формула отдельной строкой. Блок без редактируемого текста («остров»): код LaTeX хранится в `props.latex`,\n * а правится в собственном поле. Клик по формуле открывает поле; `Ctrl/Cmd+Enter` или потеря фокуса применяют код,\n * `Esc` отменяет. Пустой блок сразу открывается для ввода.\n */\nexport function FormulaBlock({ block, editor, selected, readOnly }: BlockViewProps) {\n const t = useT();\n const latex = typeof block.props.latex === 'string' ? block.props.latex : '';\n const [editing, setEditing] = useState(latex === '' && !readOnly);\n const [draft, setDraft] = useState(latex);\n const [error, setError] = useState<string | null>(null);\n const field = useRef<HTMLTextAreaElement>(null);\n const container = useRef<HTMLDivElement>(null);\n const insertSnippet = useSnippetInsert(field, draft, setDraft);\n // Escape отменяет ввод, а blur после него не должен сохранить набранное.\n const cancelled = useRef(false);\n const born = useRef(Date.now());\n\n useEffect(() => {\n if (!editing) setDraft(latex);\n }, [latex, editing]);\n\n useEffect(() => {\n if (!editing) return;\n\n // После Esc поле удаляется, а blur при удалении шлёт не каждый браузер (Firefox — нет): флаг сбрасываем здесь.\n cancelled.current = false;\n // Окно «фокус отняли программно» отсчитывается от установки фокуса, а не от отрисовки: на медленной машине\n // отрисовка нового блока сама может занять больше этого окна.\n born.current = Date.now();\n field.current?.focus();\n\n // Сразу после создания блока редактор переносит курсор в следующий блок и забирает фокус: возвращаем его в поле.\n const timer = setTimeout(() => {\n if (Date.now() - born.current < 300) field.current?.focus();\n }, 0);\n\n return () => clearTimeout(timer);\n }, [editing]);\n\n useEffect(() => {\n if (readOnly) setEditing(false);\n }, [readOnly]);\n\n const settle = useCallback((state: 'ready' | 'error', message?: string) => {\n setError(state === 'error' ? (message ?? '') : null);\n }, []);\n\n const commit = () => {\n if (cancelled.current) {\n cancelled.current = false;\n return;\n }\n\n // Блок только что создан и пуст: фокус отняли программно (курсор перенесён дальше) — поле остаётся открытым.\n if (latex === '' && draft === '' && Date.now() - born.current < 300) {\n setTimeout(() => field.current?.focus(), 0);\n return;\n }\n\n if (draft !== latex) {\n editor.dispatch({\n type: 'setBlockProps',\n payload: { blockId: block.id, props: { latex: draft } },\n });\n }\n\n setEditing(false);\n };\n\n const cancel = () => {\n cancelled.current = true;\n setDraft(latex);\n setEditing(false);\n };\n\n return (\n <div\n className=\"block block-formula\"\n data-inkbrick-block=\"formula\"\n data-block-id={block.id}\n data-selected={selected || undefined}\n contentEditable={false}\n >\n {editing ? (\n <div\n ref={container}\n className=\"formula-editor\"\n data-inkbrick-part=\"formula-editor\"\n // Поле закрывается, когда фокус ушёл из редактора целиком; переход на кнопки палитры его не закрывает.\n onBlur={(event) => {\n if (\n event.relatedTarget instanceof Node &&\n container.current?.contains(event.relatedTarget)\n )\n return;\n\n commit();\n }}\n >\n <textarea\n ref={field}\n className=\"formula-source\"\n data-inkbrick-part=\"formula-source\"\n aria-label={t('formula.source')}\n aria-invalid={error !== null || undefined}\n placeholder={t('formula.placeholder')}\n spellCheck={false}\n rows={Math.min(8, Math.max(2, draft.split('\\n').length))}\n maxLength={MAX_FORMULA_LENGTH}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n cancel();\n (event.target as HTMLTextAreaElement).blur();\n } else if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {\n event.preventDefault();\n (event.target as HTMLTextAreaElement).blur();\n }\n }}\n />\n <div className=\"formula-preview\" data-inkbrick-part=\"formula-preview\">\n <FormulaView latex={draft} display showError onSettled={settle} />\n </div>\n <LazyFormulaPalette onInsert={insertSnippet} />\n <div className=\"formula-hint\" data-inkbrick-part=\"formula-hint\">\n {t('formula.hint')}\n </div>\n </div>\n ) : latex === '' ? (\n <button\n type=\"button\"\n className=\"formula-empty\"\n data-inkbrick-part=\"formula-empty\"\n disabled={readOnly}\n onClick={() => setEditing(true)}\n >\n {t('formula.empty')}\n </button>\n ) : (\n <div\n className=\"formula-display\"\n data-inkbrick-part=\"formula-display\"\n role={readOnly ? undefined : 'button'}\n tabIndex={readOnly ? undefined : 0}\n aria-label={readOnly ? undefined : t('formula.edit')}\n title={readOnly ? undefined : t('formula.edit')}\n onClick={() => !readOnly && setEditing(true)}\n onKeyDown={(event) => {\n if (!readOnly && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n setEditing(true);\n }\n }}\n >\n <FormulaView latex={latex} display showError />\n </div>\n )}\n </div>\n );\n}\n","import { useEffect, useState, type ComponentType } from 'react';\n\nimport type { FormulaPaletteProps } from './FormulaPalette';\n\ntype Palette = ComponentType<FormulaPaletteProps>;\n\nlet loaded: Palette | undefined;\nlet loading: Promise<Palette> | undefined;\n\n/**\n * Загружает палитру заранее. Палитра (около 300 символов и шаблонов) не нужна для первой отрисовки, но должна\n * быть готова к первому редактору формулы: иначе Tab из поля кода, нажатый до её появления, уводит фокус из редактора.\n */\nexport function preloadFormulaPalette(): Promise<Palette> {\n return (loading ??= import('./FormulaPalette').then(\n (module) => (loaded = module.FormulaPalette),\n ));\n}\n\n/**\n * Палитра, загружаемая по требованию. Без React.lazy: Suspense придерживает показ загруженного содержимого\n * (~300 мс), а палитра должна появиться сразу, как только модуль готов.\n */\nexport function LazyFormulaPalette(props: FormulaPaletteProps) {\n const [Palette, setPalette] = useState<Palette | undefined>(() => loaded);\n\n useEffect(() => {\n if (Palette) return;\n\n let active = true;\n\n void preloadFormulaPalette().then((component) => {\n if (active) setPalette(() => component);\n });\n\n return () => {\n active = false;\n };\n }, [Palette]);\n\n return Palette ? <Palette {...props} /> : null;\n}\n","import { useEffect, useRef, useState, type ElementType } from 'react';\n\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { ensureMathStyles, mountFormula } from './renderer';\n\nexport interface FormulaViewProps {\n readonly latex: string;\n readonly display?: boolean;\n readonly showError?: boolean;\n readonly onSettled?: (state: 'ready' | 'error', message?: string) => void;\n}\n\n/**\n * Формула, нарисованная выбранным в `EditorProvider` подсчётчиком (по умолчанию Temml → MathML). Пока считается и при\n * ошибке виден исходный код. Атрибуты: `data-inkbrick-part=\"formula-render\"`, `data-state=\"empty|source|loading|ready|error\"`.\n */\nexport function FormulaView({\n latex,\n display = false,\n showError = false,\n onSettled,\n}: FormulaViewProps) {\n const { formulaRenderer } = useEditorUI();\n const ref = useRef<HTMLElement | null>(null);\n const [error, setError] = useState<string | null>(null);\n const Tag: ElementType = display ? 'div' : 'span';\n\n useEffect(() => {\n const target = ref.current;\n\n if (!target) return;\n\n ensureMathStyles(globalThis.document);\n setError(null);\n\n return mountFormula(target, latex, {\n display,\n renderer: formulaRenderer,\n onSettled: (state, message) => {\n setError(state === 'error' ? (message ?? '') : null);\n onSettled?.(state, message);\n },\n });\n }, [latex, display, formulaRenderer, onSettled]);\n\n return (\n <>\n <Tag\n ref={(node: HTMLElement | null) => {\n ref.current = node;\n }}\n data-inkbrick-part=\"formula-render\"\n data-display={display || undefined}\n />\n {showError && error !== null && (\n <span data-inkbrick-part=\"formula-error\" role=\"alert\">\n {error}\n </span>\n )}\n </>\n );\n}\n","import type { BlockComponentRegistry } from '../ui/types';\nimport { PageBlock } from '../blocks/PageBlock';\nimport { NoteBlock } from '../blocks/NoteBlock';\nimport { ParagraphBlock } from '../blocks/ParagraphBlock';\nimport { HeadingBlock } from '../blocks/HeadingBlock';\nimport { ListBlock } from '../blocks/ListBlock';\nimport { QuoteBlock } from '../blocks/QuoteBlock';\nimport { CodeBlock } from '../blocks/CodeBlock';\nimport { DividerBlock } from '../blocks/DividerBlock';\nimport { CalloutBlock } from '../blocks/CalloutBlock';\nimport { ImageBlock } from '../blocks/ImageBlock';\nimport { FormulaBlock } from '../blocks/FormulaBlock';\n\nexport const defaultBlockComponents: BlockComponentRegistry = Object.freeze({\n 'block:page': PageBlock,\n 'block:note': NoteBlock,\n 'block:paragraph': ParagraphBlock,\n 'block:heading': HeadingBlock,\n 'block:list': ListBlock,\n 'block:quote': QuoteBlock,\n 'block:code': CodeBlock,\n 'block:divider': DividerBlock,\n 'block:callout': CalloutBlock,\n 'block:image': ImageBlock,\n 'block:formula': FormulaBlock,\n});\n","import type { BlockComponent, BlockComponentRegistry } from '../ui/types';\nimport { defaultBlockComponents } from './defaultBlockComponents';\n\nfunction lookup(registry: BlockComponentRegistry, flavour: string): BlockComponent | undefined {\n // hasOwn: ключи вроде \"constructor\" или \"__proto__\" не должны находить прототипные свойства.\n return Object.hasOwn(registry, flavour) ? registry[flavour] : undefined;\n}\n\nexport function resolveBlockComponent(\n flavour: string,\n custom: BlockComponentRegistry,\n): BlockComponent | undefined {\n return lookup(custom, flavour) ?? lookup(defaultBlockComponents, flavour);\n}\n","import { useEffect, useLayoutEffect, useRef } from 'react';\n\nimport { BlockHandleHost } from '../block-handle/BlockHandleHost';\nimport { DropIndicatorHost } from '../block-handle/DropIndicatorHost';\nimport { useClipboard } from '../clipboard/useClipboard';\nimport { useBlockHandles } from '../block-handle/useBlockHandles';\nimport { useEditorInput } from '../editing/useEditorInput';\nimport { useSelectionState } from '../editing/useSelectionState';\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { useT } from '../hooks/useT';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { FormulaPopover } from '../formula/FormulaPopover';\nimport { preloadFormulaPalette } from '../formula/LazyFormulaPalette';\nimport { SlashMenuHost } from '../slash/SlashMenuHost';\nimport { ToolbarHost } from '../toolbar/ToolbarHost';\nimport { BlockRenderer } from './BlockRenderer';\nimport { DocumentRendererContext, fullRenderer, type DocumentRenderer } from './DocumentRenderer';\nimport { defaultVirtualRenderer } from './virtual/virtualRenderer';\n\nexport interface DocumentViewProps {\n readonly label?: string;\n /**\n * Как рисовать блоки: `'full'` (по умолчанию) — всё дерево; `'virtual'` или `virtualRenderer({...})` — только\n * блоки около видимой области (для документов на тысячи блоков); либо свой `DocumentRenderer`.\n */\n readonly renderer?: 'full' | 'virtual' | DocumentRenderer;\n}\n\nfunction resolveRenderer(renderer: DocumentViewProps['renderer']): DocumentRenderer {\n if (renderer === 'virtual') return defaultVirtualRenderer;\n if (!renderer || renderer === 'full') return fullRenderer;\n return renderer;\n}\n\n/**\n * Единственный редактируемый элемент документа. Все блоки лежат внутри него, поэтому\n * выделение работает через границы блоков; ввод перехватывается и превращается в команды движка.\n */\nexport function DocumentView({ label, renderer }: DocumentViewProps = {}) {\n const editor = useEditor();\n const view = useEditorView();\n const ref = useRef<HTMLDivElement>(null);\n\n const { slots } = useEditorUI();\n\n const readOnly = useReadOnly();\n const t = useT();\n\n useEditorInput(ref, !readOnly);\n useSelectionState(ref);\n useClipboard(ref, readOnly);\n useBlockHandles(ref, slots.BlockHandle !== null && !readOnly);\n\n useLayoutEffect(() => view.setRoot(ref.current), [view]);\n\n /*\n * Палитру формул (отдельный чанк ~5 КБ) начинаем грузить сразу после первой отрисовки: она не задерживает\n * открытие документа, но готова к первому редактору формулы (Tab из поля кода ведёт в палитру).\n */\n useEffect(() => {\n if (!readOnly) void preloadFormulaPalette();\n }, [readOnly]);\n\n return (\n <>\n <div\n ref={ref}\n className=\"inkbrick-editor\"\n data-inkbrick-root=\"\"\n contentEditable={!readOnly}\n suppressContentEditableWarning\n spellCheck={false}\n role=\"textbox\"\n aria-multiline=\"true\"\n aria-label={label ?? t('editor.label')}\n // Документ только для чтения должен получать фокус: так работают Ctrl+A и Ctrl+C с клавиатуры.\n tabIndex={readOnly ? 0 : undefined}\n aria-readonly={readOnly || undefined}\n data-readonly={readOnly || undefined}\n >\n <DocumentRendererContext.Provider value={resolveRenderer(renderer)}>\n <BlockRenderer id={editor.document.rootId} />\n </DocumentRendererContext.Provider>\n </div>\n <SlashMenuHost />\n <ToolbarHost />\n <FormulaPopover />\n <BlockHandleHost />\n <DropIndicatorHost />\n </>\n );\n}\n","import { useEffect, useRef, useSyncExternalStore } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { addBlockBelow, buildBlockActions } from './actions';\nimport { DefaultBlockHandle } from './DefaultBlockHandle';\nimport { DefaultBlockMenu } from './DefaultBlockMenu';\nimport { startGripGesture } from './gripGesture';\nimport type { GripProps } from './types';\nimport { useBlockDrag } from './useBlockDrag';\n\nconst GRIP_STYLE = Object.freeze({ touchAction: 'none' as const });\n\n/**\n * Ручка блока и меню действий. `slots.BlockHandle = null` отключает их вместе со встроенным перетаскиванием;\n * линию вставки рисует DropIndicatorHost, поэтому свой DnD через `useBlockDrag` работает и без ручек.\n */\nexport function BlockHandleHost() {\n const editor = useEditor();\n const view = useEditorView();\n const drag = useBlockDrag();\n const { slots, slashItems, t } = useEditorUI();\n const readOnly = useReadOnly();\n const state = useSyncExternalStore(\n view.blocks.subscribe,\n view.blocks.getState,\n view.blocks.getState,\n );\n const cleanup = useRef<(() => void) | null>(null);\n\n // Не оставляем слушателей, если компонент исчез посреди перетаскивания.\n useEffect(() => () => cleanup.current?.(), []);\n\n if (slots.BlockHandle === null || readOnly || typeof document === 'undefined') return null;\n\n const { hover, menu } = state;\n const dragging = state.drag;\n\n const openMenuFor = (blockId: string) => {\n const anchor = view.blocks.getState().hover ?? hover;\n\n if (anchor) view.blocks.openMenu({ blockId, x: anchor.x, y: anchor.y + 30 });\n };\n\n const gripPropsFor = (blockId: string): GripProps => ({\n onPointerDown: (event) => {\n if (event.button !== 0) return;\n\n event.preventDefault();\n cleanup.current?.();\n\n const anchor = hover;\n const cancel = startGripGesture(drag, blockId, event.nativeEvent, {\n onTap: () => {\n cleanup.current = null;\n if (anchor) view.blocks.openMenu({ blockId, x: anchor.x, y: anchor.y + 30 });\n },\n });\n\n cleanup.current = cancel;\n },\n onContextMenu: (event) => event.preventDefault(),\n style: GRIP_STYLE,\n 'data-inkbrick-grip': '',\n });\n\n const Handle = slots.BlockHandle ?? DefaultBlockHandle;\n const Menu = slots.BlockMenu ?? DefaultBlockMenu;\n const activeId = dragging?.blockId ?? hover?.blockId;\n\n const menuBlock = menu ? editor.store.getBlock(menu.blockId) : undefined;\n const menuContent =\n menu && menuBlock ? buildBlockActions(editor, view, menu.blockId, slashItems, t) : null;\n\n return createPortal(\n <>\n {hover && activeId && (\n <Handle\n blockId={activeId}\n position={{ x: hover.x, y: hover.y }}\n canAdd={editor.can('insertBlock', { flavour: 'block:paragraph', afterId: activeId })}\n dragging={!!dragging}\n menuOpen={!!menu}\n onAdd={() => addBlockBelow(editor, view, activeId, slashItems)}\n onOpenMenu={() => openMenuFor(activeId)}\n gripProps={gripPropsFor(activeId)}\n />\n )}\n\n {menu && menuBlock && menuContent && (\n <Menu\n block={menuBlock}\n position={{ x: menu.x, y: menu.y }}\n actions={menuContent.actions}\n turnInto={menuContent.turnInto}\n onClose={() => {\n view.blocks.closeMenu();\n view.getRoot()?.focus({ preventScroll: true });\n }}\n />\n )}\n </>,\n document.body,\n );\n}\n","import { flushSync } from 'react-dom';\n\nimport type { CaretResult, Editor } from '@inkbrick/engine';\n\nimport type { EditorView } from '../editing/EditorView';\nimport type { TFunction } from '../i18n/translate';\nimport { Icon } from '../icons/Icon';\nimport { availableSlashItems } from '../slash/items';\nimport type { SlashMenuItem } from '../slash/types';\nimport { syncSlashMenu } from '../slash/syncSlashMenu';\nimport { iconByName } from '../controllers/adapters';\nimport type { BlockMenuAction } from './types';\n\nconst isCaret = (value: unknown): value is CaretResult =>\n typeof value === 'object' && value !== null && 'blockId' in value && 'offset' in value;\n\nexport function performBlockAction(view: EditorView, action: () => unknown): void {\n let result: unknown;\n\n flushSync(() => {\n result = action();\n });\n\n view.blocks.closeMenu();\n\n if (isCaret(result) && view.getElement(result.blockId)) {\n view.placeCaret(result.blockId, result.offset);\n } else {\n view.getRoot()?.focus({ preventScroll: true });\n }\n}\n\nexport function buildBlockActions(\n editor: Editor,\n view: EditorView,\n blockId: string,\n slashItems: readonly SlashMenuItem[],\n t: TFunction,\n): { actions: BlockMenuAction[]; turnInto: BlockMenuAction[] } {\n const previous = editor.document.getPreviousSibling(blockId);\n const next = editor.document.getNextSibling(blockId);\n const perform = (fn: () => unknown) => () => performBlockAction(view, fn);\n\n const moveUp = previous && { blockId, targetId: previous.id, position: 'before' as const };\n const moveDown = next && { blockId, targetId: next.id, position: 'after' as const };\n\n const block = editor.store.getBlock(blockId);\n const controller = block && editor.controllers.get(block.flavour);\n const own = (controller?.menuItems ?? []).map<BlockMenuAction>((item) => {\n const context = editor.controllers.contextOf(block!);\n\n return {\n id: item.id,\n title: item.title,\n icon: iconByName(item.icon),\n danger: item.danger,\n disabled: item.isDisabled ? item.isDisabled(context) : context.readOnly,\n run: perform(() => item.run(context)),\n };\n });\n\n const actions: BlockMenuAction[] = [\n ...own,\n {\n id: 'duplicate',\n title: t('menu.duplicate'),\n icon: <Icon name=\"copy\" />,\n disabled: !editor.can('duplicateBlock', { blockId }),\n run: perform(() => editor.dispatch({ type: 'duplicateBlock', payload: { blockId } })),\n },\n {\n id: 'move-up',\n title: t('menu.moveUp'),\n icon: <Icon name=\"arrow-up\" />,\n disabled: !moveUp || !editor.can('moveBlock', moveUp),\n run: perform(() => moveUp && editor.dispatch({ type: 'moveBlock', payload: moveUp })),\n },\n {\n id: 'move-down',\n title: t('menu.moveDown'),\n icon: <Icon name=\"arrow-down\" />,\n disabled: !moveDown || !editor.can('moveBlock', moveDown),\n run: perform(() => moveDown && editor.dispatch({ type: 'moveBlock', payload: moveDown })),\n },\n {\n id: 'delete',\n title: t('menu.delete'),\n icon: <Icon name=\"trash\" />,\n danger: true,\n run: perform(() => editor.execute('delete-block', { id: blockId })),\n },\n ];\n\n const turnInto = availableSlashItems(editor, slashItems, blockId)\n .filter((item) =>\n editor.can('convertBlock', { blockId, flavour: item.flavour, props: item.props }),\n )\n .map<BlockMenuAction>((item) => ({\n id: item.id,\n title: item.title,\n icon: item.icon,\n run: perform(() =>\n editor.dispatch({\n type: 'convertBlock',\n payload: { blockId, flavour: item.flavour, props: item.props as never },\n }),\n ),\n }));\n\n return { actions, turnInto };\n}\n\nexport function addBlockBelow(\n editor: Editor,\n view: EditorView,\n blockId: string,\n slashItems: readonly SlashMenuItem[],\n): void {\n const block = editor.store.getBlock(blockId);\n const parent = block?.parentId ? editor.store.getBlock(block.parentId) : undefined;\n\n if (!block || !parent) return;\n\n // Рядом с вложенным блоком вставляем блок того же типа: параграф «провалился» бы внутрь списка.\n const nested = parent.flavour !== 'block:note';\n const payload = {\n flavour: nested ? block.flavour : 'block:paragraph',\n afterId: blockId,\n props: nested ? (block.props as never) : undefined,\n content: [{ insert: '/' }],\n };\n\n let caret: CaretResult | undefined;\n\n flushSync(() => {\n caret = editor.dispatch({ type: 'insertBlock', payload }) as CaretResult | undefined;\n });\n\n view.blocks.setHover(null);\n\n if (!caret) return;\n\n view.placeCaret(caret.blockId, 1);\n view.slash.open(caret.blockId, 0);\n syncSlashMenu(editor, view, slashItems);\n}\n","import type { Editor } from '@inkbrick/engine';\n\nimport type { EditorView } from '../editing/EditorView';\nimport { readDocSelection } from '../editing/selection';\nimport { visibleSlashItems } from './items';\nimport type { SlashMenuItem } from './types';\n\nfunction caretPosition(view: EditorView, blockId: string): { x: number; y: number } | null {\n const selection = globalThis.getSelection();\n const range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;\n const rect = range?.getClientRects()[0];\n\n if (rect && (rect.width > 0 || rect.height > 0)) return { x: rect.left, y: rect.bottom };\n\n const element = view.getElement(blockId);\n\n if (!element) return null;\n\n const box = element.getBoundingClientRect();\n\n return { x: box.left, y: box.bottom };\n}\n\n/**\n * Сверяет меню с текущим состоянием документа и выделением: обновляет запрос и позицию\n * или закрывает меню, если каретка ушла от «/» или «/» удалён.\n */\nexport function syncSlashMenu(\n editor: Editor,\n view: EditorView,\n items: readonly SlashMenuItem[],\n): void {\n const state = view.slash.getState();\n\n if (!state.open || !state.blockId) return;\n\n const root = view.getRoot();\n const selection = root ? readDocSelection(root) : null;\n const block = editor.store.getBlock(state.blockId);\n const text = block ? editor.engine.inline.toPlainText(block.content) : '';\n\n if (\n !selection ||\n !selection.collapsed ||\n selection.from.blockId !== state.blockId ||\n selection.from.offset <= state.slashOffset ||\n text[state.slashOffset] !== '/'\n ) {\n view.slash.close();\n return;\n }\n\n const query = text.slice(state.slashOffset + 1, selection.from.offset);\n const visible = visibleSlashItems(editor, items, state.blockId, query);\n\n if (visible.length === 0 && /\\s$/.test(query)) {\n view.slash.close();\n return;\n }\n\n view.slash.update({\n query,\n activeIndex:\n query !== state.query ? 0 : Math.min(state.activeIndex, Math.max(visible.length - 1, 0)),\n position: caretPosition(view, state.blockId),\n });\n}\n","import { useT } from '../hooks/useT';\nimport { Icon } from '../icons/Icon';\nimport type { BlockHandleProps } from './types';\n\nconst HANDLE_WIDTH = 52;\n\nexport function DefaultBlockHandle({\n blockId,\n position,\n canAdd,\n dragging,\n menuOpen,\n onAdd,\n onOpenMenu,\n gripProps,\n}: BlockHandleProps) {\n const t = useT();\n const left = position.x - HANDLE_WIDTH;\n\n return (\n <div\n className=\"inkbrick-block-handle\"\n data-inkbrick-ui=\"block-handle\"\n data-testid=\"block-handle\"\n data-block={blockId}\n data-inkbrick-block-ui\n // Слева от текста нет места (узкий экран): ручка ложится поверх текста отдельной плашкой.\n data-compact={left < 2 || undefined}\n style={{\n left: Math.max(2, left),\n top: position.y,\n pointerEvents: dragging ? 'none' : undefined,\n }}\n // Не уводим фокус и выделение из редактора.\n onMouseDown={(event) => event.preventDefault()}\n >\n <button\n type=\"button\"\n className=\"inkbrick-block-handle__button\"\n data-inkbrick-part=\"button\"\n aria-label={t('handle.add')}\n title={t('handle.add')}\n data-action=\"add\"\n disabled={!canAdd}\n onClick={onAdd}\n >\n <Icon name=\"plus\" />\n </button>\n <button\n type=\"button\"\n className=\"inkbrick-block-handle__button inkbrick-block-handle__grip\"\n data-inkbrick-part=\"grip\"\n data-active={menuOpen || undefined}\n aria-label={t('handle.grip')}\n title={t('handle.grip')}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n data-action=\"grip\"\n {...gripProps}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onOpenMenu();\n }\n }}\n >\n <Icon name=\"grip\" />\n </button>\n </div>\n );\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport { useT } from '../hooks/useT';\nimport type { BlockMenuAction, BlockMenuProps } from './types';\n\nexport function DefaultBlockMenu({ position, actions, turnInto, onClose }: BlockMenuProps) {\n const t = useT();\n const ref = useRef<HTMLDivElement>(null);\n const [flip, setFlip] = useState(false);\n\n const entries: BlockMenuAction[] = [...actions, ...turnInto].filter((entry) => !entry.disabled);\n\n useEffect(() => {\n ref.current\n ?.querySelector<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])')\n ?.focus();\n }, []);\n\n useLayoutEffect(() => {\n const menu = ref.current;\n\n if (menu)\n setFlip(\n position.y + menu.offsetHeight > window.innerHeight && position.y - menu.offsetHeight > 0,\n );\n }, [position.y]);\n\n const move = (delta: number) => {\n const items = [\n ...(ref.current?.querySelectorAll<HTMLElement>(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])',\n ) ?? []),\n ];\n const index = items.indexOf(document.activeElement as HTMLElement);\n\n items[(index + delta + items.length) % items.length]?.focus();\n };\n\n const renderItem = (action: BlockMenuAction) => (\n <div\n key={action.id}\n role=\"menuitem\"\n tabIndex={action.disabled ? -1 : 0}\n aria-disabled={action.disabled || undefined}\n data-action={action.id}\n data-inkbrick-part=\"item\"\n data-disabled={action.disabled || undefined}\n data-danger={action.danger || undefined}\n className={`inkbrick-block-menu__item${action.danger ? ' inkbrick-block-menu__item--danger' : ''}`}\n onClick={() => !action.disabled && action.run()}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n if (!action.disabled) action.run();\n }\n }}\n >\n {action.icon !== undefined && (\n <span className=\"inkbrick-block-menu__icon\" data-inkbrick-part=\"icon\">\n {action.icon}\n </span>\n )}\n {action.title}\n </div>\n );\n\n return (\n <div\n ref={ref}\n className=\"inkbrick-block-menu\"\n data-inkbrick-ui=\"block-menu\"\n role=\"menu\"\n aria-label={t('menu.label')}\n data-testid=\"block-menu\"\n data-inkbrick-block-ui\n style={{\n left: Math.max(\n 8,\n Math.min(position.x, window.innerWidth - (ref.current?.offsetWidth ?? 232) - 8),\n ),\n top: flip ? Math.max(8, position.y - (ref.current?.offsetHeight ?? 0) - 32) : position.y,\n }}\n onKeyDown={(event) => {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n move(1);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n move(-1);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n onClose();\n }\n }}\n >\n {actions.map(renderItem)}\n\n {turnInto.length > 0 && (\n <>\n <div className=\"inkbrick-block-menu__label\" data-inkbrick-part=\"label\" role=\"separator\">\n {t('menu.turnInto')}\n </div>\n {turnInto.map(renderItem)}\n </>\n )}\n\n {entries.length === 0 && (\n <div className=\"inkbrick-block-menu__label\" data-inkbrick-part=\"label\">\n {t('menu.empty')}\n </div>\n )}\n </div>\n );\n}\n","import type { BlockDragApi } from './blockDrag';\n\n/** Сколько пикселей мышью нужно протянуть, чтобы клик стал переносом. */\nexport const DRAG_THRESHOLD = 5;\n/** Сколько держать палец на хваталке, чтобы начать перенос. */\nexport const LONG_PRESS_MS = 350;\n/** Дрожание пальца, которое ещё не считается движением до начала переноса. */\nexport const TOUCH_SLOP = 10;\n\nexport interface GripGestureOptions {\n readonly onTap: () => void;\n}\n\n/**\n * Встроенный жест хваталки поверх публичного API переноса.\n * Мышь: протягивание дальше порога — перенос, иначе клик. Палец и перо: долгое нажатие — перенос,\n * короткое касание — клик, сдвиг до долгого нажатия отменяет жест. Возвращает функцию отмены.\n */\nexport function startGripGesture(\n drag: BlockDragApi,\n blockId: string,\n event: PointerEvent,\n { onTap }: GripGestureOptions,\n): () => void {\n const touch = event.pointerType === 'touch' || event.pointerType === 'pen';\n const pointerId = event.pointerId;\n const startX = event.clientX;\n const startY = event.clientY;\n let dragging = false;\n let aborted = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const begin = () => {\n if (dragging || aborted) return;\n\n dragging = true;\n drag.start(blockId);\n\n if (touch) navigator.vibrate?.(10);\n };\n\n const finish = () => {\n clearTimeout(timer);\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerup', onUp);\n document.removeEventListener('pointercancel', onCancel);\n document.removeEventListener('keydown', onKey);\n };\n\n const onMove = (move: PointerEvent) => {\n if (move.pointerId !== pointerId) return;\n\n const distance = Math.hypot(move.clientX - startX, move.clientY - startY);\n\n if (!dragging) {\n if (touch) {\n if (distance > TOUCH_SLOP) {\n aborted = true;\n finish();\n }\n\n return;\n }\n\n if (distance > DRAG_THRESHOLD) begin();\n }\n\n if (dragging) {\n move.preventDefault();\n drag.update(move.clientX, move.clientY);\n }\n };\n\n const onUp = (up: PointerEvent) => {\n if (up.pointerId !== pointerId) return;\n\n finish();\n\n if (dragging) drag.drop();\n else if (!aborted) onTap();\n };\n\n const onCancel = (cancel: PointerEvent) => {\n if (cancel.pointerId !== pointerId) return;\n\n abort();\n };\n\n const onKey = (key: KeyboardEvent) => {\n if (key.key === 'Escape') abort();\n };\n\n const abort = () => {\n aborted = true;\n finish();\n\n if (dragging) drag.cancel();\n };\n\n if (touch) timer = setTimeout(begin, LONG_PRESS_MS);\n\n document.addEventListener('pointermove', onMove, { passive: false });\n document.addEventListener('pointerup', onUp);\n document.addEventListener('pointercancel', onCancel);\n document.addEventListener('keydown', onKey);\n\n return abort;\n}\n","import { useSyncExternalStore } from 'react';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport type { DragState } from './BlockHandleController';\nimport { getBlockDrag, type BlockDragApi } from './blockDrag';\n\n/**\n * API перетаскивания блоков текущего редактора: на нём строится своя система DnD\n * (dnd-kit, pragmatic-drag-and-drop и т. п.). Объект стабилен между рендерами.\n * Работает внутри `<EditorProvider>`, в том числе в компоненте `slots.BlockHandle`.\n */\nexport function useBlockDrag(): BlockDragApi {\n return getBlockDrag(useEditor(), useEditorView());\n}\n\nexport function useBlockDragState(): DragState | null {\n const drag = useBlockDrag();\n\n return useSyncExternalStore(drag.subscribe, drag.getState, drag.getState);\n}\n","import { flushSync } from 'react-dom';\n\nimport type { Editor } from '@inkbrick/engine';\n\nimport type { EditorView } from '../editing/EditorView';\nimport type { DragState, DropIndicatorRect, DropPosition } from './BlockHandleController';\nimport { blockAtPoint, blockElement, probePoint, rowRect } from './geometry';\n\nexport interface BlockDropTarget {\n readonly targetId: string;\n readonly position: DropPosition;\n readonly indicator: DropIndicatorRect;\n}\n\nexport interface BlockRects {\n /** Строка самого блока (его текст), без вложенных блоков. */\n readonly row: DOMRect;\n /** Весь блок вместе с вложенными блоками. */\n readonly box: DOMRect;\n}\n\n/**\n * Всё, что нужно своей системе перетаскивания блоков (dnd-kit, pragmatic-drag-and-drop, своя на pointer events):\n * геометрия, проверка цели, линия вставки и сам перенос. Встроенное перетаскивание построено на этом же API.\n *\n * Обычный порядок: `start(blockId)` → на каждое движение `update(x, y)` → `drop()` или `cancel()`.\n */\nexport interface BlockDragApi {\n /** Блок с ручкой под точкой окна; точку в полосе слева от текста прижимает к тексту. */\n blockAtPoint(x: number, y: number): string | null;\n blockRects(blockId: string): BlockRects | null;\n /** Можно ли перенести блок `blockId` перед/после `targetId` (схема, вложенность, глубина). */\n canMove(blockId: string, targetId: string, position: DropPosition): boolean;\n /** Допустимое место вставки под точкой окна для блока `blockId`; верхняя половина строки — «перед». */\n dropTargetAt(blockId: string, x: number, y: number): BlockDropTarget | null;\n\n start(blockId: string): void;\n /** Задаёт текущее место вставки (или убирает его) и рисует линию. Цель, которую движок не примет, отбрасывается. */\n setTarget(target: BlockDropTarget | null): void;\n /** Удобная связка `dropTargetAt` + `setTarget` с автопрокруткой у края окна. Возвращает найденную цель. */\n update(x: number, y: number): BlockDropTarget | null;\n /** Завершает перенос: применяет его к текущей цели одним шагом undo. `true`, если блок перенесён. */\n drop(): boolean;\n cancel(): void;\n\n /** Переносит блок сразу, без жеста (например, из своего DnD без линии вставки). Один шаг undo. */\n move(blockId: string, targetId: string, position: DropPosition): boolean;\n autoScroll(clientY: number): void;\n\n getState(): DragState | null;\n subscribe(listener: () => void): () => void;\n}\n\nconst EDGE = 56;\n\nconst cache = new WeakMap<EditorView, BlockDragApi>();\n\nexport function getBlockDrag(editor: Editor, view: EditorView): BlockDragApi {\n let api = cache.get(view);\n\n if (!api) {\n api = createBlockDrag(editor, view);\n cache.set(view, api);\n }\n\n return api;\n}\n\nfunction createBlockDrag(editor: Editor, view: EditorView): BlockDragApi {\n const controller = view.blocks;\n\n const markBody = (on: boolean) => {\n if (typeof document === 'undefined') return;\n\n document.body.classList.toggle('inkbrick-dragging', on);\n\n if (on) document.body.setAttribute('data-inkbrick-dragging', '');\n else document.body.removeAttribute('data-inkbrick-dragging');\n };\n\n const canMove = (blockId: string, targetId: string, position: DropPosition) =>\n blockId !== targetId && editor.can('moveBlock', { blockId, targetId, position });\n\n const blockRects = (blockId: string): BlockRects | null => {\n const wrapper = blockElement(view, blockId);\n const row = rowRect(view, blockId);\n\n return wrapper && row ? { row, box: wrapper.getBoundingClientRect() } : null;\n };\n\n const api: BlockDragApi = {\n blockAtPoint(x, y) {\n const probe = probePoint(view, x, y);\n\n return probe ? blockAtPoint(editor, view, probe.x, probe.y) : null;\n },\n\n blockRects,\n canMove,\n\n dropTargetAt(blockId, x, y) {\n const targetId = api.blockAtPoint(x, y);\n const rects = targetId ? blockRects(targetId) : null;\n\n if (!targetId || !rects) return null;\n\n const { row, box } = rects;\n const position: DropPosition = y < row.top + row.height / 2 ? 'before' : 'after';\n\n if (!canMove(blockId, targetId, position)) return null;\n\n return {\n targetId,\n position,\n // «После» — после всего поддерева цели (вместе с вложенными блоками).\n indicator: {\n left: box.left,\n width: box.width,\n top: position === 'before' ? row.top - 1 : box.bottom + 1,\n },\n };\n },\n\n start(blockId) {\n controller.startDrag(blockId);\n markBody(true);\n },\n\n setTarget(target) {\n const drag = controller.getState().drag;\n\n if (!drag) return;\n\n if (!target || !canMove(drag.blockId, target.targetId, target.position)) {\n controller.updateDrag({ targetId: null, position: null, indicator: null });\n return;\n }\n\n controller.updateDrag({\n targetId: target.targetId,\n position: target.position,\n indicator: target.indicator,\n });\n },\n\n update(x, y) {\n const drag = controller.getState().drag;\n\n if (!drag) return null;\n\n api.autoScroll(y);\n\n const target = api.dropTargetAt(drag.blockId, x, y);\n\n api.setTarget(target);\n\n return target;\n },\n\n drop() {\n const drag = controller.getState().drag;\n\n controller.endDrag();\n markBody(false);\n\n if (!drag?.targetId || !drag.position) return false;\n\n return api.move(drag.blockId, drag.targetId, drag.position);\n },\n\n cancel() {\n controller.endDrag();\n markBody(false);\n },\n\n move(blockId, targetId, position) {\n if (!canMove(blockId, targetId, position)) return false;\n\n const payload = { blockId, targetId, position };\n\n // Синхронно обновляем DOM: сразу после переноса можно мерить блоки на новых местах.\n flushSync(() => {\n editor.dispatch({ type: 'moveBlock', payload });\n });\n\n controller.setHover(null);\n\n return true;\n },\n\n autoScroll(clientY) {\n if (typeof window === 'undefined') return;\n\n if (clientY < EDGE) window.scrollBy(0, -14);\n else if (clientY > window.innerHeight - EDGE) window.scrollBy(0, 14);\n },\n\n getState: () => controller.getState().drag,\n\n subscribe: (listener) => {\n let last = controller.getState().drag;\n\n return controller.subscribe(() => {\n const next = controller.getState().drag;\n\n if (next !== last) {\n last = next;\n listener();\n }\n });\n },\n };\n\n return api;\n}\n","import type { Editor } from '@inkbrick/engine';\n\nimport type { EditorView } from '../editing/EditorView';\n\n/** Ширина полосы слева от текста, в которой ручка остаётся видимой. */\nexport const GUTTER = 72;\n\nexport function hasHandle(editor: Editor, blockId: string): boolean {\n const block = editor.store.getBlock(blockId);\n const parent = block?.parentId ? editor.store.getBlock(block.parentId) : undefined;\n\n return !!parent?.parentId;\n}\n\nexport function blockElement(view: EditorView, blockId: string): HTMLElement | null {\n return (\n view.getRoot()?.querySelector<HTMLElement>(`[data-block-id=\"${CSS.escape(blockId)}\"]`) ?? null\n );\n}\n\nexport function blockAtPoint(\n editor: Editor,\n view: EditorView,\n x: number,\n y: number,\n): string | null {\n const root = view.getRoot();\n const hit = root ? document.elementFromPoint(x, y) : null;\n\n if (!root || !hit || !root.contains(hit)) return null;\n\n let node: Element | null = hit.closest('[data-block-id]');\n\n while (node && root.contains(node)) {\n const id = node.getAttribute('data-block-id')!;\n\n if (hasHandle(editor, id)) return id;\n\n node = node.parentElement?.closest('[data-block-id]') ?? null;\n }\n\n return null;\n}\n\n/** Точка в колонке редактора: прижимает x к тексту, чтобы блок находился и при наведении в полосу слева. */\nexport function probePoint(\n view: EditorView,\n x: number,\n y: number,\n): { x: number; y: number } | null {\n const root = view.getRoot();\n\n if (!root) return null;\n\n const rect = root.getBoundingClientRect();\n\n if (x < rect.left - GUTTER || x > rect.right || y < rect.top || y > rect.bottom) return null;\n\n return { x: Math.min(Math.max(x, rect.left + 12), rect.right - 12), y };\n}\n\nexport function rowRect(view: EditorView, blockId: string): DOMRect | null {\n return (view.getElement(blockId) ?? blockElement(view, blockId))?.getBoundingClientRect() ?? null;\n}\n","import { useEffect } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { blockElement } from './geometry';\nimport type { DropIndicatorProps } from './types';\nimport { useBlockDragState } from './useBlockDrag';\n\nexport function DefaultDropIndicator({ indicator, position }: DropIndicatorProps) {\n return (\n <div\n className=\"inkbrick-drop-indicator\"\n data-inkbrick-ui=\"drop-indicator\"\n data-testid=\"drop-indicator\"\n data-position={position}\n style={{ left: indicator.left, top: indicator.top, width: indicator.width }}\n />\n );\n}\n\n/**\n * Линия вставки и затемнение переносимого блока. Рисуется по состоянию API переноса,\n * поэтому работает и со встроенным перетаскиванием, и со своим (`useBlockDrag`), даже без ручек.\n */\nexport function DropIndicatorHost() {\n const view = useEditorView();\n const { slots } = useEditorUI();\n const readOnly = useReadOnly();\n const drag = useBlockDragState();\n const draggedId = drag?.blockId;\n\n useEffect(() => {\n if (!draggedId) return;\n\n const element = blockElement(view, draggedId);\n\n element?.setAttribute('data-inkbrick-dragging', 'true');\n\n return () => element?.removeAttribute('data-inkbrick-dragging');\n }, [draggedId, view]);\n\n if (readOnly || slots.DropIndicator === null || typeof document === 'undefined') return null;\n if (!drag?.indicator || !drag.targetId || !drag.position) return null;\n\n const Indicator = slots.DropIndicator ?? DefaultDropIndicator;\n\n return createPortal(\n <Indicator\n blockId={drag.blockId}\n targetId={drag.targetId}\n position={drag.position}\n indicator={drag.indicator}\n />,\n document.body,\n );\n}\n","import { useEffect, type RefObject } from 'react';\n\nimport { normalizeLinkUrl } from '@inkbrick/document';\nimport {\n FRAGMENT_MIME,\n fragmentToHtml,\n fragmentToPlainText,\n sanitizeFragment,\n type CaretResult,\n type Fragment,\n} from '@inkbrick/engine';\n\nimport { blockAtPoint, probePoint } from '../block-handle/geometry';\nimport { createInputActions } from '../editing/inputActions';\nimport { readDocSelection, type DocSelection } from '../editing/selection';\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { insertImageFiles } from '../images/insertImages';\nimport { isAcceptedImage } from '../images/upload';\nimport { setLinkInSelection } from '../toolbar/formatting';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { embeddedFragment, htmlToFragment } from './htmlToFragment';\n\nconst URL_ONLY = /^(https?:\\/\\/|mailto:)\\S+$/i;\n\n/**\n * Текстовое поле внутри пользовательского компонента (подпись картинки, свои input) работает с буфером как обычно.\n * Смотрим на сфокусированный элемент: у события copy цель может быть кнопкой, внутри которой начинается\n * выделение (значок callout, панель картинки), и это не повод отказываться от копирования блоков.\n */\nfunction isForeignControl(_target: EventTarget | null): boolean {\n const active = document.activeElement;\n\n return (\n active instanceof Element &&\n active.closest('input, textarea, select, [data-inkbrick-ignore-input]') !== null\n );\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return null;\n }\n}\n\n/**\n * Копирование, вырезание и вставка.\n *\n * Копирование кладёт в буфер три формата: простой текст, семантический HTML (для Word, Docs, почты) и точный\n * фрагмент Inkbrick (типы, props, вложенность — для вставки в другой Inkbrick). Вставка выбирает лучший из доступных:\n * точный фрагмент → HTML → простой текст. `Ctrl/Cmd+Shift+V` вставляет только текст. Всё, что пришло из\n * буфера, считается недоверенным и проверяется. Копирование работает и в режиме только чтения.\n */\nexport function useClipboard(ref: RefObject<HTMLElement | null>, readOnly: boolean) {\n const editor = useEditor();\n const view = useEditorView();\n const { images, slashItems } = useEditorUI();\n\n useEffect(() => {\n const root = ref.current;\n\n if (!root) return;\n\n let plainNext = false;\n let plainTimer: ReturnType<typeof setTimeout> | undefined;\n\n const { exec, run, deleteSelection, insertAt } = createInputActions(\n editor,\n view,\n root,\n slashItems,\n );\n\n const writeSelection = (event: ClipboardEvent, cut: boolean) => {\n if (isForeignControl(event.target)) return;\n\n const selection = readDocSelection(root);\n\n if (!selection || selection.collapsed || !event.clipboardData) return;\n\n const fragment = editor.copyFragment(selection.from, selection.to);\n\n if (fragment.blocks.length === 0) return;\n\n const json = JSON.stringify(fragment);\n\n event.clipboardData.setData('text/plain', fragmentToPlainText(fragment));\n event.clipboardData.setData('text/html', fragmentToHtml(fragment, encodeURIComponent(json)));\n event.clipboardData.setData(FRAGMENT_MIME, json);\n event.preventDefault();\n\n if (cut && !readOnly) run(() => editor.batch(() => deleteSelection(selection)));\n };\n\n const pastePlain = (text: string, selection: DocSelection) => {\n const trimmed = text.trim();\n\n // Адрес поверх выделенного текста делает его ссылкой (как в Slack/Notion), а не заменяет.\n if (\n !selection.collapsed &&\n selection.from.blockId === selection.to.blockId &&\n URL_ONLY.test(trimmed) &&\n normalizeLinkUrl(trimmed) &&\n editor.store.getBlock(selection.from.blockId)?.flavour !== 'block:code' &&\n setLinkInSelection(editor, view, selection, trimmed)\n ) {\n return;\n }\n\n const lines = text.replace(/\\r\\n?/g, '\\n').split('\\n');\n\n run(() =>\n editor.batch(() => {\n let caret: CaretResult | undefined = selection.collapsed\n ? { blockId: selection.from.blockId, offset: selection.from.offset }\n : deleteSelection(selection);\n\n if (!caret) return undefined;\n\n /*\n * Где Enter вставляет перевод строки (код), текст вставляется целиком: деление по строкам вывело бы\n * из блока на первой же пустой строке.\n */\n const flavour = editor.store.getBlock(caret.blockId)?.flavour ?? '';\n\n if (editor.schema.getBlockSchema(flavour)?.enter?.mode === 'newline') {\n return insertAt(caret.blockId, caret.offset, lines.join('\\n'));\n }\n\n caret = insertAt(caret.blockId, caret.offset, lines[0]);\n\n for (const line of lines.slice(1)) {\n if (!caret) return undefined;\n\n const next: CaretResult | undefined = exec<CaretResult>({\n type: 'splitBlock',\n payload: { blockId: caret.blockId, offset: caret.offset },\n });\n\n if (!next) return caret;\n\n caret = insertAt(next.blockId, next.offset, line);\n }\n\n return caret;\n }),\n );\n };\n\n const pasteFragment = (fragment: Fragment, selection: DocSelection): boolean => {\n // Проверяем заранее: иначе после удаления выделения вставка могла бы отказать.\n if (!editor.can('pasteFragment', { at: selection.from, fragment })) return false;\n\n run(() =>\n editor.batch(() => {\n const caret: CaretResult | undefined = selection.collapsed\n ? { blockId: selection.from.blockId, offset: selection.from.offset }\n : deleteSelection(selection);\n\n return caret\n ? exec<CaretResult>({ type: 'pasteFragment', payload: { at: caret, fragment } })\n : undefined;\n }),\n );\n\n return true;\n };\n\n const onPaste = (event: ClipboardEvent) => {\n if (isForeignControl(event.target)) return;\n\n event.preventDefault();\n\n const data = event.clipboardData;\n const selection = readDocSelection(root);\n\n if (readOnly || !data || !selection) return;\n\n const text = data.getData('text/plain');\n\n /*\n * Картинка в буфере (снимок экрана, «копировать изображение»): загружаем файл. Если рядом есть текст — это\n * обычная вставка (например, из таблицы), и файлы игнорируются.\n */\n const files = [...data.files].filter((file) => isAcceptedImage(file, images));\n\n if (files.length > 0 && text.trim() === '') {\n plainNext = false;\n\n insertImageFiles(editor, view, images, files, selection.to.blockId);\n return;\n }\n\n const plainOnly = plainNext;\n\n plainNext = false;\n\n const inCode = editor.store.getBlock(selection.from.blockId)?.flavour === 'block:code';\n\n if (!plainOnly && !inCode) {\n const json = data.getData(FRAGMENT_MIME);\n const html = data.getData('text/html');\n\n const fragment =\n (json ? sanitizeFragment(parseJson(json)) : null) ??\n (html ? (embeddedFragment(html) ?? htmlToFragment(html)) : null);\n\n if (fragment && pasteFragment(fragment, selection)) return;\n }\n\n if (text) pastePlain(text, selection);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n // В режиме чтения Backspace на документе ничего не делает (в WebKit он иначе уходит назад по истории).\n if (readOnly && event.key === 'Backspace' && !isForeignControl(event.target)) {\n event.preventDefault();\n return;\n }\n\n if (\n readOnly &&\n (event.ctrlKey || event.metaKey) &&\n !event.shiftKey &&\n event.key.toLowerCase() === 'a'\n ) {\n const selection = globalThis.getSelection();\n\n event.preventDefault();\n selection?.removeAllRanges();\n\n const range = document.createRange();\n range.selectNodeContents(root);\n selection?.addRange(range);\n return;\n }\n\n if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key.toLowerCase() === 'v') {\n plainNext = true;\n clearTimeout(plainTimer);\n plainTimer = setTimeout(() => {\n plainNext = false;\n }, 1000);\n }\n };\n\n // Перетаскивание картинок из файлового менеджера. Без обработки браузер открыл бы файл вместо редактора.\n const hasFiles = (event: DragEvent) =>\n !!event.dataTransfer && [...event.dataTransfer.types].includes('Files');\n\n const onDragOver = (event: DragEvent) => {\n if (hasFiles(event)) event.preventDefault();\n };\n\n const onDrop = (event: DragEvent) => {\n if (!hasFiles(event)) return;\n\n event.preventDefault();\n\n const files = [...(event.dataTransfer?.files ?? [])].filter((file) =>\n isAcceptedImage(file, images),\n );\n\n if (readOnly || files.length === 0) return;\n\n const probe = probePoint(view, event.clientX, event.clientY);\n const target =\n (probe ? blockAtPoint(editor, view, probe.x, probe.y) : null) ??\n readDocSelection(root)?.to.blockId;\n\n if (target) insertImageFiles(editor, view, images, files, target);\n };\n\n const onCopy = (event: ClipboardEvent) => writeSelection(event, false);\n const onCut = (event: ClipboardEvent) => writeSelection(event, true);\n\n root.addEventListener('copy', onCopy);\n root.addEventListener('cut', onCut);\n root.addEventListener('paste', onPaste);\n root.addEventListener('keydown', onKeyDown);\n root.addEventListener('dragover', onDragOver);\n root.addEventListener('drop', onDrop);\n\n return () => {\n clearTimeout(plainTimer);\n root.removeEventListener('copy', onCopy);\n root.removeEventListener('cut', onCut);\n root.removeEventListener('paste', onPaste);\n root.removeEventListener('keydown', onKeyDown);\n root.removeEventListener('dragover', onDragOver);\n root.removeEventListener('drop', onDrop);\n };\n }, [editor, view, ref, readOnly, images, slashItems]);\n}\n","import { flushSync } from 'react-dom';\n\nimport type { CaretResult, Editor, EditorIntent } from '@inkbrick/engine';\n\nimport { syncSlashMenu } from '../slash/syncSlashMenu';\nimport type { SlashMenuItem } from '../slash/types';\nimport { toggleFormatInSelection } from '../toolbar/formatting';\nimport type { EditorView } from './EditorView';\nimport { readDocSelection, type DocSelection } from './selection';\n\nexport interface InputActions {\n exec<T>(intent: EditorIntent): T | undefined;\n run(action: () => CaretResult | undefined): void;\n syncSlash(): void;\n blockText(blockId: string): string;\n deleteSelection(selection: DocSelection): CaretResult | undefined;\n insertAt(blockId: string, offset: number, text: string): CaretResult | undefined;\n replaceSelection(selection: DocSelection, text: string): CaretResult | undefined;\n toggleFormat(format: string): void;\n undo(): void;\n redo(): void;\n}\n\nexport function createInputActions(\n editor: Editor,\n view: EditorView,\n root: HTMLElement,\n slashItems: readonly SlashMenuItem[],\n): InputActions {\n const exec = <T>(intent: EditorIntent) => editor.dispatch(intent) as T | undefined;\n\n const run = (action: () => CaretResult | undefined) => {\n let caret: CaretResult | undefined;\n\n flushSync(() => {\n caret = action();\n });\n\n if (caret) view.placeCaret(caret.blockId, caret.offset);\n\n syncSlash();\n };\n\n const syncSlash = () => syncSlashMenu(editor, view, slashItems);\n\n const blockText = (blockId: string) => {\n const block = editor.store.getBlock(blockId);\n return block ? editor.engine.inline.toPlainText(block.content) : '';\n };\n\n const isSingleBlock = (selection: DocSelection) =>\n selection.from.blockId === selection.to.blockId;\n\n const deleteSelection = (selection: DocSelection) =>\n isSingleBlock(selection)\n ? exec<CaretResult>({\n type: 'deleteText',\n payload: {\n blockId: selection.from.blockId,\n from: selection.from.offset,\n to: selection.to.offset,\n },\n })\n : exec<CaretResult>({\n type: 'deleteRange',\n payload: { from: selection.from, to: selection.to },\n });\n\n const insertAt = (blockId: string, offset: number, text: string) =>\n exec<CaretResult>({\n type: 'replaceText',\n payload: { blockId, from: offset, to: offset, text },\n });\n\n const replaceSelection = (selection: DocSelection, text: string) => {\n // Обычный ввод идёт без batch: иначе набор подряд не сливается в один шаг undo.\n if (selection.collapsed) {\n return insertAt(selection.from.blockId, selection.from.offset, text);\n }\n\n return editor.batch(() => {\n const caret = deleteSelection(selection);\n\n return caret ? insertAt(caret.blockId, caret.offset, text) : undefined;\n });\n };\n\n const toggleFormat = (format: string) => {\n const selection = readDocSelection(root);\n\n if (selection) toggleFormatInSelection(editor, view, selection, format);\n };\n\n const undo = () => run(() => editor.undo()?.caret);\n const redo = () => run(() => editor.redo()?.caret);\n\n return {\n exec,\n run,\n syncSlash,\n blockText,\n deleteSelection,\n insertAt,\n replaceSelection,\n toggleFormat,\n undo,\n redo,\n };\n}\n","import { useEffect, type RefObject } from 'react';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { blockAtPoint, blockElement, hasHandle, probePoint, rowRect } from './geometry';\n\n/**\n * Следит за указателем: показывает ручку у блока под курсором (в том числе в полосе слева от текста),\n * на сенсорном экране — у блока, которого коснулись; закрывает меню по клику снаружи/Esc/прокрутке\n * и скрывает ручку при наборе текста. Перетаскивание запускается из ручки (см. BlockHandleHost).\n */\nexport function useBlockHandles(ref: RefObject<HTMLElement | null>, enabled: boolean) {\n const editor = useEditor();\n const view = useEditorView();\n\n useEffect(() => {\n const root = ref.current;\n\n if (!root || !enabled) return;\n\n const showAt = (event: PointerEvent) => {\n const probe = probePoint(view, event.clientX, event.clientY);\n\n if (!probe) {\n view.blocks.setHover(null);\n return;\n }\n\n const blockId = blockAtPoint(editor, view, probe.x, probe.y);\n\n if (!blockId) return;\n\n const wrapper = blockElement(view, blockId);\n const row = rowRect(view, blockId);\n\n if (wrapper && row) {\n view.blocks.setHover({\n blockId,\n x: Math.round(wrapper.getBoundingClientRect().left),\n y: Math.round(row.top),\n });\n }\n };\n\n const onUiTarget = (event: Event) =>\n event.target instanceof Element && !!event.target.closest('[data-inkbrick-block-ui]');\n\n const onMove = (event: PointerEvent) => {\n const { menu, drag } = view.blocks.getState();\n\n // Палец «наводится» только касанием (см. onPointerUp); движение пальца — это прокрутка.\n if (event.pointerType === 'touch') return;\n\n if (drag || menu || view.pointerDown) return;\n\n if (onUiTarget(event)) return;\n\n showAt(event);\n };\n\n const onPointerUp = (event: PointerEvent) => {\n if (event.pointerType === 'mouse' || onUiTarget(event)) return;\n\n const { menu, drag } = view.blocks.getState();\n\n if (!drag && !menu) showAt(event);\n };\n\n const onPointerDown = (event: PointerEvent) => {\n if (onUiTarget(event)) return;\n\n view.blocks.closeMenu();\n };\n\n const hide = (event: Event) => {\n // Прокрутка самого меню (оно может не помещаться в окно) не должна его закрывать.\n if (onUiTarget(event)) return;\n // Автопрокрутка при переносе: элемент-хваталка (в том числе у стороннего DnD) должен остаться.\n if (view.blocks.getState().drag) return;\n\n view.blocks.setHover(null);\n view.blocks.closeMenu();\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') view.blocks.closeMenu();\n\n if (view.blocks.getState().hover && !event.metaKey && !event.ctrlKey)\n view.blocks.setHover(null);\n };\n\n const onLeave = (event: PointerEvent) => {\n // Палец «уходит» со страницы после каждого касания — ручка должна остаться.\n if (event.pointerType === 'touch') return;\n if (!event.relatedTarget) view.blocks.setHover(null);\n };\n\n // Блок исчез из документа (удалён, undo) — ручка и меню не должны остаться висеть.\n const unsubscribe = editor.store.subscribe(() => {\n const { hover, menu } = view.blocks.getState();\n\n if (hover && !hasHandle(editor, hover.blockId)) view.blocks.setHover(null);\n if (menu && !hasHandle(editor, menu.blockId)) view.blocks.closeMenu();\n });\n\n document.addEventListener('pointermove', onMove);\n document.addEventListener('pointerdown', onPointerDown);\n document.addEventListener('pointerup', onPointerUp);\n document.addEventListener('pointerout', onLeave);\n document.addEventListener('keydown', onKeyDown);\n window.addEventListener('scroll', hide, true);\n\n return () => {\n unsubscribe();\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerdown', onPointerDown);\n document.removeEventListener('pointerup', onPointerUp);\n document.removeEventListener('pointerout', onLeave);\n document.removeEventListener('keydown', onKeyDown);\n window.removeEventListener('scroll', hide, true);\n view.blocks.setHover(null);\n view.blocks.closeMenu();\n };\n }, [editor, view, ref, enabled]);\n}\n","import { useEffect, type RefObject } from 'react';\n\nimport type { CaretResult } from '@inkbrick/engine';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { syncToolbar } from '../toolbar/syncToolbar';\nimport { openFormulaAt } from '../formula/actions';\nimport { handleKeyDown } from '../keymap/keymap';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { applyBeforeInput } from './beforeInput';\nimport { createInputActions } from './inputActions';\nimport { readDocSelection } from './selection';\n\nconst NAVIGATION_KEYS = new Set([\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n]);\n\nfunction diffText(before: string, after: string) {\n let start = 0;\n while (start < before.length && start < after.length && before[start] === after[start]) start++;\n\n let endBefore = before.length;\n let endAfter = after.length;\n while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {\n endBefore--;\n endAfter--;\n }\n\n return { from: start, to: endBefore, text: after.slice(start, endAfter) };\n}\n\n/** События из полей ввода и кнопок внутри пользовательских компонентов редактор не перехватывает. */\nfunction isForeignControl(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target.closest('input, textarea, select, button, [data-inkbrick-ignore-input]') !== null\n );\n}\n\n/**\n * Подключает ввод к корню документа. Все изменения текста перехватываются на beforeinput,\n * превращаются в intent'ы движка, а выделение возвращается после перерисовки.\n * Выделение может охватывать несколько блоков.\n */\nexport function useEditorInput(ref: RefObject<HTMLElement | null>, enabled = true) {\n const editor = useEditor();\n const view = useEditorView();\n const { slashItems, keymap } = useEditorUI();\n\n useEffect(() => {\n const root = ref.current;\n\n if (!root || !enabled) return;\n\n let composing = false;\n\n const actions = createInputActions(editor, view, root, slashItems);\n const { exec, run, syncSlash, blockText, replaceSelection, toggleFormat, undo, redo } = actions;\n\n const onBeforeInput = (event: InputEvent) => {\n if (isForeignControl(event.target)) return;\n\n // Во время IME-композиции браузер сам меняет DOM; модель синхронизируется на compositionend.\n if (composing || event.isComposing) return;\n\n event.preventDefault();\n\n applyBeforeInput(event, root, editor, view, slashItems, actions);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (isForeignControl(event.target)) return;\n\n const handled = handleKeyDown(keymap, {\n editor,\n view,\n root,\n event,\n slashItems,\n selection: () => readDocSelection(root),\n exec,\n run,\n replaceSelection,\n undo,\n redo,\n toggleFormat,\n });\n\n // Перемещение курсора — граница шага undo: следующий набор текста начнёт новый шаг.\n if (!handled && NAVIGATION_KEYS.has(event.key)) editor.sealHistory();\n };\n\n /** Блок, в котором стоит каретка. Цель событий композиции — корень (contenteditable), а не блок. */\n const editableAtCaret = () => {\n const node = document.getSelection()?.anchorNode ?? null;\n const element = node instanceof Element ? node : node?.parentElement;\n const editable = element?.closest<HTMLElement>('.editable[data-id]');\n\n return editable && root.contains(editable) ? editable : null;\n };\n\n // Блок, где началась композиция: к её концу каретка у некоторых клавиатур уже может быть в другом месте.\n let compositionBlock: HTMLElement | null = null;\n\n const onCompositionStart = () => {\n composing = true;\n compositionBlock = editableAtCaret();\n // Набираемое слово ещё не в модели, и блок считается пустым: атрибут прячет подсказку поверх текста.\n compositionBlock?.setAttribute('data-composing', '');\n };\n\n /*\n * Клавиатуры телефонов набирают почти всё композицией: слово живёт только в DOM до compositionend,\n * поэтому здесь его нужно обязательно перенести в модель — иначе следующая перерисовка его сотрёт.\n */\n const onCompositionEnd = () => {\n composing = false;\n\n const started = compositionBlock?.isConnected ? compositionBlock : null;\n const element = started ?? editableAtCaret();\n const blockId = element?.dataset.id;\n\n compositionBlock?.removeAttribute('data-composing');\n compositionBlock = null;\n\n if (!element || !blockId) return;\n\n const { from, to, text } = diffText(blockText(blockId), element.textContent ?? '');\n\n if (from === to && text === '') return;\n\n run(() => exec<CaretResult>({ type: 'replaceText', payload: { blockId, from, to, text } }));\n };\n\n const prevent = (event: Event) => event.preventDefault();\n const sealHistory = () => editor.sealHistory();\n const closeSlash = () => view.slash.close();\n const onPointerDown = () => {\n view.pointerDown = true;\n view.toolbar.closeLink();\n view.toolbar.hide();\n };\n const onPointerUp = () => {\n if (!view.pointerDown) return;\n\n view.pointerDown = false;\n // Выделение окончательно установится после mouseup.\n setTimeout(() => syncToolbar(editor, view), 0);\n };\n const onClick = (event: MouseEvent) => {\n const formula =\n event.target instanceof Element ? event.target.closest('[data-inkbrick-formula]') : null;\n\n if (formula && root.contains(formula)) {\n event.preventDefault();\n openFormulaAt(view, formula);\n return;\n }\n\n if (!(event.ctrlKey || event.metaKey) || !(event.target instanceof Element)) return;\n\n const anchor = event.target.closest<HTMLAnchorElement>('a[href]');\n\n if (anchor && root.contains(anchor)) {\n event.preventDefault();\n window.open(anchor.href, '_blank', 'noopener,noreferrer');\n }\n };\n const onSelectionChange = () => {\n if (view.slash.getState().open) syncSlash();\n syncToolbar(editor, view);\n };\n const syncIfOpen = () => {\n if (view.slash.getState().open) syncSlash();\n if (view.toolbar.getState().visible) syncToolbar(editor, view);\n };\n\n root.addEventListener('beforeinput', onBeforeInput);\n root.addEventListener('keydown', onKeyDown);\n root.addEventListener('compositionstart', onCompositionStart);\n root.addEventListener('compositionend', onCompositionEnd);\n root.addEventListener('drop', prevent);\n root.addEventListener('pointerdown', sealHistory);\n root.addEventListener('focusout', sealHistory);\n root.addEventListener('pointerdown', closeSlash);\n root.addEventListener('focusout', closeSlash);\n root.addEventListener('pointerdown', onPointerDown);\n root.addEventListener('click', onClick);\n document.addEventListener('pointerup', onPointerUp);\n document.addEventListener('pointercancel', onPointerUp);\n document.addEventListener('selectionchange', onSelectionChange);\n window.addEventListener('scroll', syncIfOpen, true);\n\n return () => {\n root.removeEventListener('beforeinput', onBeforeInput);\n root.removeEventListener('keydown', onKeyDown);\n root.removeEventListener('compositionstart', onCompositionStart);\n root.removeEventListener('compositionend', onCompositionEnd);\n root.removeEventListener('drop', prevent);\n root.removeEventListener('pointerdown', sealHistory);\n root.removeEventListener('focusout', sealHistory);\n root.removeEventListener('pointerdown', closeSlash);\n root.removeEventListener('focusout', closeSlash);\n root.removeEventListener('pointerdown', onPointerDown);\n root.removeEventListener('click', onClick);\n document.removeEventListener('pointerup', onPointerUp);\n document.removeEventListener('pointercancel', onPointerUp);\n document.removeEventListener('selectionchange', onSelectionChange);\n window.removeEventListener('scroll', syncIfOpen, true);\n compositionBlock?.removeAttribute('data-composing');\n view.slash.close();\n view.toolbar.hide();\n };\n }, [editor, view, ref, slashItems, keymap, enabled]);\n}\n","import type { CaretResult, Editor } from '@inkbrick/engine';\n\nimport { availableSlashItems } from '../slash/items';\nimport type { SlashMenuItem } from '../slash/types';\nimport { matchInlineFormula } from '../formula/actions';\nimport { deleteForwardAtEnd } from './deleteAtBoundary';\nimport type { EditorView } from './EditorView';\nimport type { InputActions } from './inputActions';\nimport { readDocSelection } from './selection';\n\nconst FORMAT_BY_INPUT_TYPE: Record<string, string> = {\n formatBold: 'bold',\n formatItalic: 'italic',\n formatUnderline: 'underline',\n formatStrikeThrough: 'strike',\n};\n\nfunction matchShortcut(prefix: string) {\n if (/^#{1,6}$/.test(prefix)) {\n return { flavour: 'block:heading', props: { level: prefix.length } };\n }\n if (prefix === '>') return { flavour: 'block:quote', props: {} };\n if (prefix === '```') return { flavour: 'block:code', props: {} };\n if (prefix === '---') return { flavour: 'block:divider', props: {} };\n if (prefix === '$$') return { flavour: 'block:formula', props: {} };\n if (/^[-*+]$/.test(prefix)) return { flavour: 'block:list', props: { type: 'bullet' } };\n if (/^\\d+\\.$/.test(prefix)) return { flavour: 'block:list', props: { type: 'ordered' } };\n if (prefix === '[]') return { flavour: 'block:list', props: { type: 'todo', checked: false } };\n return null;\n}\n\n/**\n * Превращает `beforeinput` в команды движка: ввод, Enter, удаление (символ, слово, строка), история и формат из\n * системного меню, Markdown-шорткаты, `$формула$` и открытие slash-меню. Событие уже отменено вызывающим кодом.\n */\nexport function applyBeforeInput(\n event: InputEvent,\n root: HTMLElement,\n editor: Editor,\n view: EditorView,\n slashItems: readonly SlashMenuItem[],\n actions: InputActions,\n): void {\n const {\n exec,\n run,\n syncSlash,\n blockText,\n deleteSelection,\n replaceSelection,\n toggleFormat,\n undo,\n redo,\n } = actions;\n const selection = readDocSelection(root);\n\n if (!selection) return;\n\n const { from, collapsed } = selection;\n const type = event.inputType;\n const block = editor.store.getBlock(from.blockId);\n const text = blockText(from.blockId);\n\n switch (type) {\n case 'insertText':\n case 'insertReplacementText': {\n const data = event.data ?? event.dataTransfer?.getData('text/plain') ?? '';\n\n if (!data) return;\n\n if (data === '$' && collapsed && block && block.flavour !== 'block:code') {\n const formula = matchInlineFormula(text.slice(0, from.offset));\n\n if (\n formula &&\n editor.can('insertFormula', {\n blockId: from.blockId,\n from: formula.from,\n to: from.offset,\n latex: formula.latex,\n })\n ) {\n run(() =>\n exec<CaretResult>({\n type: 'insertFormula',\n payload: {\n blockId: from.blockId,\n from: formula.from,\n to: from.offset,\n latex: formula.latex,\n },\n }),\n );\n return;\n }\n }\n\n if (data === ' ' && collapsed && block?.flavour === 'block:paragraph') {\n const shortcut = matchShortcut(text.slice(0, from.offset));\n\n if (shortcut) {\n run(() =>\n editor.batch(() => {\n exec({\n type: 'deleteText',\n payload: { blockId: from.blockId, from: 0, to: from.offset },\n });\n\n return exec<CaretResult>({\n type: 'convertBlock',\n payload: { blockId: from.blockId, ...shortcut, offset: 0 },\n });\n }),\n );\n return;\n }\n }\n\n const opensSlash =\n data === '/' &&\n collapsed &&\n !!block &&\n block.flavour !== 'block:code' &&\n editor.schema.getBlockSchema(block.flavour)?.inline !== false &&\n (from.offset === 0 || /\\s/.test(text[from.offset - 1])) &&\n availableSlashItems(editor, slashItems, from.blockId).length > 0;\n\n run(() => replaceSelection(selection, data));\n\n if (opensSlash) {\n view.slash.open(from.blockId, from.offset);\n syncSlash();\n }\n\n return;\n }\n\n case 'insertParagraph':\n run(() =>\n editor.batch(() => {\n const caret = collapsed\n ? { blockId: from.blockId, offset: from.offset }\n : deleteSelection(selection);\n\n return caret\n ? exec<CaretResult>({\n type: 'splitBlock',\n payload: { blockId: caret.blockId, offset: caret.offset },\n })\n : undefined;\n }),\n );\n return;\n\n case 'insertLineBreak':\n run(() => replaceSelection(selection, '\\n'));\n return;\n\n case 'deleteContentBackward':\n run(() =>\n collapsed\n ? exec<CaretResult>({\n type: 'deleteBackward',\n payload: { blockId: from.blockId, offset: from.offset },\n })\n : deleteSelection(selection),\n );\n return;\n\n case 'deleteContentForward':\n run(() => {\n if (!collapsed) return deleteSelection(selection);\n\n if (from.offset < text.length) {\n return exec<CaretResult>({\n type: 'deleteText',\n payload: { blockId: from.blockId, from: from.offset, to: from.offset + 1 },\n });\n }\n\n return deleteForwardAtEnd(editor, from.blockId);\n });\n return;\n\n case 'deleteWordBackward':\n run(() => {\n if (!collapsed) return deleteSelection(selection);\n\n // Как в браузерах и Word: слово вместе с пробелами после него (пробел перед словом остаётся).\n const start = text.slice(0, from.offset).replace(/(\\S+\\s*|\\s+)$/, '').length;\n\n return start < from.offset\n ? exec<CaretResult>({\n type: 'deleteText',\n payload: { blockId: from.blockId, from: start, to: from.offset },\n })\n : exec<CaretResult>({\n type: 'deleteBackward',\n payload: { blockId: from.blockId, offset: from.offset },\n });\n });\n return;\n\n case 'deleteWordForward':\n run(() => {\n if (!collapsed) return deleteSelection(selection);\n\n const rest = text.slice(from.offset);\n const length = rest.length - rest.replace(/^(\\s*[^\\s]+|\\s+)/, '').length;\n\n return length > 0\n ? exec<CaretResult>({\n type: 'deleteText',\n payload: { blockId: from.blockId, from: from.offset, to: from.offset + length },\n })\n : undefined;\n });\n return;\n\n case 'deleteSoftLineBackward':\n case 'deleteHardLineBackward':\n run(() => {\n if (!collapsed) return deleteSelection(selection);\n\n return from.offset > 0\n ? exec<CaretResult>({\n type: 'deleteText',\n payload: { blockId: from.blockId, from: 0, to: from.offset },\n })\n : undefined;\n });\n return;\n\n case 'deleteSoftLineForward':\n case 'deleteHardLineForward':\n run(() => {\n if (!collapsed) return deleteSelection(selection);\n\n return from.offset < text.length\n ? exec<CaretResult>({\n type: 'deleteText',\n payload: { blockId: from.blockId, from: from.offset, to: text.length },\n })\n : undefined;\n });\n return;\n\n case 'deleteByCut':\n case 'deleteByDrag':\n case 'deleteContent':\n if (!collapsed) run(() => deleteSelection(selection));\n return;\n\n case 'historyUndo':\n undo();\n return;\n\n case 'historyRedo':\n redo();\n return;\n\n case 'formatBold':\n case 'formatItalic':\n case 'formatUnderline':\n case 'formatStrikeThrough':\n toggleFormat(FORMAT_BY_INPUT_TYPE[type]);\n return;\n\n default:\n /*\n * insertFromPaste обрабатывается в useClipboard; drop и всё неизвестное блокируем,\n * чтобы DOM не разошёлся с моделью.\n */\n return;\n }\n}\n","import { useEffect, type RefObject } from 'react';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { readDocSelection } from './selection';\n\nexport function useSelectionState(ref: RefObject<HTMLElement | null>) {\n const editor = useEditor();\n const view = useEditorView();\n\n useEffect(() => {\n const root = ref.current;\n\n if (!root) return;\n\n const update = () => {\n const selection = readDocSelection(root);\n\n view.selection.set(\n selection && !selection.collapsed ? editor.blocksBetween(selection.from, selection.to) : [],\n );\n const caret = selection?.collapsed ? selection.from.blockId : null;\n\n view.caret.set(caret);\n editor.controllers.setFocusedBlock(caret);\n view.viewport.setEdges(\n !selection\n ? []\n : selection.collapsed\n ? [selection.from.blockId]\n : [selection.from.blockId, selection.to.blockId],\n );\n };\n\n document.addEventListener('selectionchange', update);\n update();\n\n return () => {\n document.removeEventListener('selectionchange', update);\n view.selection.set([]);\n view.caret.set(null);\n view.viewport.setEdges([]);\n editor.controllers.setFocusedBlock(null);\n };\n }, [editor, view, ref]);\n}\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { MAX_FORMULA_LENGTH } from '@inkbrick/document';\n\nimport type { EditorView } from '../editing/EditorView';\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { useT } from '../hooks/useT';\nimport { Icon } from '../icons/Icon';\nimport { FormulaView } from '../math/FormulaView';\nimport { applyInlineFormula } from './actions';\nimport { LazyFormulaPalette } from './LazyFormulaPalette';\nimport { useSnippetInsert } from './snippet';\nimport type { FormulaEditorState } from './FormulaController';\n\nconst WIDTH = 340;\n\nfunction close(view: EditorView, state: FormulaEditorState) {\n view.formula.close();\n view.placeSelection(\n { blockId: state.blockId, offset: state.mode === 'edit' ? state.to : state.from },\n { blockId: state.blockId, offset: state.to },\n );\n}\n\nfunction Body({ state }: { state: FormulaEditorState }) {\n const editor = useEditor();\n const view = useEditorView();\n const t = useT();\n const [draft, setDraft] = useState(state.latex);\n const [error, setError] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const field = useRef<HTMLTextAreaElement>(null);\n const [top, setTop] = useState<number | null>(null);\n const insertSnippet = useSnippetInsert(field, draft, setDraft);\n\n const settle = useCallback((result: 'ready' | 'error') => setError(result === 'error'), []);\n const width = Math.min(WIDTH, window.innerWidth - 16);\n\n useEffect(() => {\n field.current?.focus();\n field.current?.select();\n }, []);\n\n useLayoutEffect(() => {\n const height = ref.current?.offsetHeight ?? 0;\n const below = state.position.y + 8;\n\n setTop(\n below + height > window.innerHeight && state.position.top - height - 8 > 0\n ? state.position.top - height - 8\n : below,\n );\n }, [state.position.y, state.position.top, draft]);\n\n useEffect(() => {\n const onPointerDown = (event: PointerEvent) => {\n if (event.target instanceof Node && ref.current?.contains(event.target)) return;\n\n close(view, state);\n };\n\n document.addEventListener('pointerdown', onPointerDown, true);\n\n return () => document.removeEventListener('pointerdown', onPointerDown, true);\n }, [view, state]);\n\n const apply = () => {\n if (applyInlineFormula(editor, view, state, draft)) view.formula.close();\n };\n\n const remove = () => {\n if (applyInlineFormula(editor, view, state, '')) view.formula.close();\n };\n\n return (\n <div\n ref={ref}\n className=\"formula-popover\"\n data-inkbrick-ui=\"formula-popover\"\n data-testid=\"formula-popover\"\n role=\"dialog\"\n aria-label={t('formula.inline.title')}\n style={{\n left: Math.max(8, Math.min(state.position.x - width / 2, window.innerWidth - width - 8)),\n top: top ?? state.position.y + 8,\n width,\n }}\n onMouseDown={(event) => {\n if (!(event.target instanceof HTMLTextAreaElement)) event.preventDefault();\n }}\n >\n <textarea\n ref={field}\n className=\"formula-popover__source\"\n data-inkbrick-part=\"formula-source\"\n aria-label={t('formula.source')}\n aria-invalid={error || undefined}\n placeholder={t('formula.placeholder')}\n spellCheck={false}\n rows={2}\n maxLength={MAX_FORMULA_LENGTH}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n close(view, state);\n } else if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n apply();\n }\n }}\n />\n <div className=\"formula-popover__preview\" data-inkbrick-part=\"formula-preview\">\n <FormulaView latex={draft} showError onSettled={settle} />\n </div>\n <LazyFormulaPalette onInsert={insertSnippet} />\n <div className=\"formula-popover__actions\" data-inkbrick-part=\"formula-actions\">\n {state.mode === 'edit' && (\n <button\n type=\"button\"\n data-inkbrick-part=\"button\"\n data-danger=\"\"\n data-action=\"remove\"\n aria-label={t('formula.remove')}\n title={t('formula.remove')}\n onClick={remove}\n >\n <Icon name=\"trash\" />\n </button>\n )}\n <span className=\"formula-popover__spacer\" />\n <button\n type=\"button\"\n data-inkbrick-part=\"button\"\n data-action=\"cancel\"\n onClick={() => close(view, state)}\n >\n {t('formula.cancel')}\n </button>\n <button\n type=\"button\"\n data-inkbrick-part=\"button\"\n data-primary=\"\"\n data-action=\"apply\"\n disabled={state.mode === 'insert' && draft.trim() === ''}\n onClick={apply}\n >\n {t('formula.apply')}\n </button>\n </div>\n </div>\n );\n}\n\nexport function FormulaPopover() {\n const view = useEditorView();\n const readOnly = useReadOnly();\n const state = useSyncExternalStore(\n view.formula.subscribe,\n view.formula.getState,\n view.formula.getState,\n );\n\n if (!state.open || readOnly || typeof document === 'undefined') return null;\n\n return createPortal(\n <Body key={`${state.mode}:${state.blockId}:${state.from}:${state.to}`} state={state} />,\n document.body,\n );\n}\n","import { createPortal } from 'react-dom';\nimport { useSyncExternalStore } from 'react';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { applySlashItem } from './applySlashItem';\nimport { DefaultSlashMenu } from './DefaultSlashMenu';\nimport { visibleSlashItems } from './items';\n\nexport function SlashMenuHost() {\n const editor = useEditor();\n const view = useEditorView();\n const { slots, slashItems } = useEditorUI();\n const readOnly = useReadOnly();\n const state = useSyncExternalStore(\n view.slash.subscribe,\n view.slash.getState,\n view.slash.getState,\n );\n\n if (\n readOnly ||\n !state.open ||\n !state.blockId ||\n !state.position ||\n typeof document === 'undefined'\n ) {\n return null;\n }\n\n const items = visibleSlashItems(editor, slashItems, state.blockId, state.query);\n const Menu = slots.SlashMenu ?? DefaultSlashMenu;\n\n return createPortal(\n <Menu\n items={items}\n query={state.query}\n activeIndex={Math.min(state.activeIndex, Math.max(items.length - 1, 0))}\n position={state.position}\n onSelect={(item) => applySlashItem(editor, view, item)}\n onHover={(index) => view.slash.update({ activeIndex: index })}\n onClose={() => view.slash.close()}\n />,\n document.body,\n );\n}\n","import { useId, useLayoutEffect, useRef, useState } from 'react';\n\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useT } from '../hooks/useT';\nimport type { SlashMenuProps } from './types';\n\nconst ESTIMATED_LINE = 28;\n\nexport function DefaultSlashMenu({\n items,\n activeIndex,\n position,\n onSelect,\n onHover,\n}: SlashMenuProps) {\n const t = useT();\n const view = useEditorView();\n const ref = useRef<HTMLDivElement>(null);\n const [flip, setFlip] = useState(false);\n const menuId = useId();\n const optionId = (index: number) => `${menuId}-option-${index}`;\n\n useLayoutEffect(() => {\n const menu = ref.current;\n\n if (!menu) return;\n\n setFlip(\n position.y + menu.offsetHeight > window.innerHeight &&\n position.y - menu.offsetHeight - ESTIMATED_LINE > 0,\n );\n }, [position.x, position.y, items.length]);\n\n useLayoutEffect(() => {\n ref.current?.querySelector('[aria-selected=\"true\"]')?.scrollIntoView?.({ block: 'nearest' });\n }, [activeIndex, items]);\n\n /*\n * Фокус остаётся в тексте документа, а меню управляется с клавиатуры редактором (паттерн combobox ARIA):\n * корень документа ссылается на меню и на выбранный пункт — так экранный чтец озвучивает выбор.\n */\n useLayoutEffect(() => {\n const root = view.getRoot();\n\n if (!root) return;\n\n root.setAttribute('aria-controls', menuId);\n\n if (items.length > 0) root.setAttribute('aria-activedescendant', optionId(activeIndex));\n else root.removeAttribute('aria-activedescendant');\n\n return () => {\n root.removeAttribute('aria-controls');\n root.removeAttribute('aria-activedescendant');\n };\n }, [view, menuId, activeIndex, items.length]);\n\n return (\n <div\n ref={ref}\n id={menuId}\n className=\"inkbrick-slash-menu\"\n data-inkbrick-ui=\"slash-menu\"\n /*\n * Прокручиваемая область должна быть доступна с клавиатуры. До меню фокус Tab-ом не доходит: в открытом\n * меню Tab выбирает пункт (его перехватывает редактор), а клик по меню не уводит фокус из текста.\n */\n tabIndex={0}\n role=\"listbox\"\n aria-label={t('slash.label')}\n data-testid=\"slash-menu\"\n style={{\n left: Math.max(\n 8,\n Math.min(position.x, window.innerWidth - (ref.current?.offsetWidth ?? 320) - 8),\n ),\n top: flip ? position.y - (ref.current?.offsetHeight ?? 0) - ESTIMATED_LINE : position.y + 4,\n }}\n onMouseDown={(event) => event.preventDefault()}\n >\n {items.length === 0 && (\n <div className=\"inkbrick-slash-menu__description\" data-inkbrick-part=\"empty\">\n {t('slash.empty')}\n </div>\n )}\n\n {items.map((item, index) => (\n <div\n key={item.id}\n id={optionId(index)}\n role=\"option\"\n aria-selected={index === activeIndex}\n data-slash-item={item.id}\n data-inkbrick-part=\"item\"\n data-active={index === activeIndex || undefined}\n className={`inkbrick-slash-menu__item${index === activeIndex ? ' inkbrick-slash-menu__item--selected' : ''}`}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(item)}\n >\n {item.icon !== undefined && (\n <span className=\"inkbrick-slash-menu__icon\" data-inkbrick-part=\"icon\">\n {item.icon}\n </span>\n )}\n <div className=\"inkbrick-slash-menu__body\" data-inkbrick-part=\"body\">\n <div className=\"inkbrick-slash-menu__header\" data-inkbrick-part=\"title\">\n {item.title}\n </div>\n {item.description && (\n <div className=\"inkbrick-slash-menu__description\" data-inkbrick-part=\"description\">\n {item.description}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import { createPortal } from 'react-dom';\nimport { useSyncExternalStore } from 'react';\n\nimport { useEditor } from '../hooks/useEditor';\nimport { useEditorView } from '../hooks/useEditorView';\nimport { useReadOnly } from '../hooks/useReadOnly';\nimport { openInlineFormula } from '../formula/actions';\nimport { useEditorUI } from '../ui/EditorUIContext';\nimport { DefaultToolbar } from './DefaultToolbar';\nimport { setLinkInSelection, toggleFormatInSelection } from './formatting';\nimport { setAlignInSelection, setColorInSelection } from './rich';\nimport { syncToolbar } from './syncToolbar';\n\nexport function ToolbarHost() {\n const editor = useEditor();\n const view = useEditorView();\n const { slots } = useEditorUI();\n const readOnly = useReadOnly();\n const state = useSyncExternalStore(\n view.toolbar.subscribe,\n view.toolbar.getState,\n view.toolbar.getState,\n );\n\n if (slots.Toolbar === null || readOnly) return null;\n\n if (\n !state.visible ||\n !state.position ||\n !state.formats ||\n !state.range ||\n typeof document === 'undefined'\n ) {\n return null;\n }\n\n const Toolbar = slots.Toolbar ?? DefaultToolbar;\n const range = state.range;\n\n return createPortal(\n <Toolbar\n formats={state.formats}\n position={state.position}\n linkOpen={state.linkOpen}\n panel={state.panel}\n onToggle={(format) => {\n toggleFormatInSelection(editor, view, range, format);\n syncToolbar(editor, view);\n }}\n onOpenLink={() => view.toolbar.openLink()}\n onApplyLink={(url) => {\n if (!setLinkInSelection(editor, view, range, url)) return false;\n\n view.toolbar.closeLink();\n syncToolbar(editor, view);\n\n return true;\n }}\n onTogglePanel={(panel) => view.toolbar.togglePanel(panel)}\n onApplyColor={(kind, value) => {\n setColorInSelection(editor, view, range, kind, value);\n view.toolbar.closePanel();\n syncToolbar(editor, view);\n }}\n onAlign={(align) => {\n setAlignInSelection(editor, view, range, align);\n syncToolbar(editor, view);\n }}\n onInsertFormula={() => {\n view.placeSelection(range.from, range.to);\n openInlineFormula(editor, view);\n }}\n onCancelLink={() => {\n view.toolbar.closeLink();\n view.placeSelection(range.from, range.to);\n syncToolbar(editor, view);\n }}\n />,\n document.body,\n );\n}\n","import { useEffect, useLayoutEffect, useRef, useState, type FormEvent } from 'react';\n\nimport { ALIGNMENTS, COLOR_NAMES, isColorName, type Alignment } from '@inkbrick/document';\n\nimport { useT } from '../hooks/useT';\nimport { Icon, type IconName } from '../icons/Icon';\nimport type { InlineFormat, ToolbarPanel, ToolbarProps } from './types';\n\nconst BUTTONS: readonly { format: InlineFormat; icon: IconName }[] = [\n { format: 'bold', icon: 'bold' },\n { format: 'italic', icon: 'italic' },\n { format: 'underline', icon: 'underline' },\n { format: 'strike', icon: 'strike' },\n { format: 'code', icon: 'code' },\n];\n\nconst ALIGN_ICONS: Record<Alignment, IconName> = {\n left: 'align-left',\n center: 'align-center',\n right: 'align-right',\n justify: 'align-justify',\n};\n\nconst PANELS: readonly { panel: ToolbarPanel; icon: IconName }[] = [\n { panel: 'color', icon: 'baseline' },\n { panel: 'highlight', icon: 'highlighter' },\n];\n\nexport function DefaultToolbar({\n formats,\n position,\n linkOpen,\n panel,\n onToggle,\n onOpenLink,\n onApplyLink,\n onCancelLink,\n onTogglePanel,\n onApplyColor,\n onAlign,\n onInsertFormula,\n}: ToolbarProps) {\n const t = useT();\n const input = useRef<HTMLInputElement>(null);\n const ref = useRef<HTMLDivElement>(null);\n const [value, setValue] = useState('');\n const [invalid, setInvalid] = useState(false);\n const [below, setBelow] = useState(false);\n const [width, setWidth] = useState(0);\n\n useEffect(() => {\n if (!linkOpen) return;\n\n setValue(formats.link ?? '');\n setInvalid(false);\n input.current?.focus();\n input.current?.select();\n }, [linkOpen]);\n\n /*\n * У верхнего края окна показываем под выделением. На сенсорных экранах — всегда под ним: сверху системное\n * меню выделения («Копировать», «Вставить») закрыло бы toolbar.\n */\n useLayoutEffect(() => {\n const coarse = window.matchMedia?.('(pointer: coarse)').matches ?? false;\n\n setBelow(coarse || position.y - (ref.current?.offsetHeight ?? 40) - 12 < 0);\n setWidth(ref.current?.offsetWidth ?? 0);\n }, [position.x, position.y, linkOpen, panel]);\n\n const left = Math.max(8, Math.min(position.x - width / 2, window.innerWidth - width - 8));\n\n const submit = (event: FormEvent) => {\n event.preventDefault();\n\n if (!onApplyLink(value)) setInvalid(true);\n };\n\n const colorKind = panel === 'highlight' ? 'backgroundColor' : 'color';\n const currentColor = panel === 'highlight' ? formats.backgroundColor : formats.color;\n\n return (\n <div\n ref={ref}\n className=\"inkbrick-toolbar\"\n role=\"toolbar\"\n aria-label={t('toolbar.label')}\n data-inkbrick-ui=\"toolbar\"\n data-placement={below ? 'below' : 'above'}\n data-testid=\"toolbar\"\n style={{\n left,\n top: position.y,\n transform: below ? 'translateY(28px)' : 'translateY(calc(-100% - 8px))',\n }}\n onMouseDown={(event) => {\n if (event.target !== input.current) event.preventDefault();\n }}\n >\n {linkOpen ? (\n <form className=\"inkbrick-toolbar__link\" data-inkbrick-part=\"link-form\" onSubmit={submit}>\n <input\n ref={input}\n data-inkbrick-part=\"input\"\n data-invalid={invalid || undefined}\n type=\"text\"\n aria-label={t('toolbar.link.url')}\n aria-invalid={invalid}\n placeholder={t('toolbar.link.placeholder')}\n value={value}\n onChange={(event) => {\n setValue(event.target.value);\n setInvalid(false);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n onCancelLink();\n }\n }}\n />\n <button\n type=\"submit\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n aria-label={t('toolbar.link.apply')}\n title={t('toolbar.link.apply')}\n >\n <Icon name=\"check\" />\n </button>\n {formats.link && (\n <button\n type=\"button\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n aria-label={t('toolbar.link.remove')}\n title={t('toolbar.link.remove')}\n onClick={() => onApplyLink(null)}\n >\n <Icon name=\"unlink\" />\n </button>\n )}\n </form>\n ) : (\n <>\n {BUTTONS.map(({ format, icon }) => (\n <button\n key={format}\n type=\"button\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n data-format={format}\n data-pressed={formats[format] || undefined}\n aria-label={t(`toolbar.${format}.label`)}\n aria-pressed={formats[format]}\n title={t(`toolbar.${format}.title`)}\n onClick={() => onToggle(format)}\n >\n <Icon name={icon} />\n </button>\n ))}\n <span\n className=\"inkbrick-toolbar__separator\"\n data-inkbrick-part=\"separator\"\n role=\"separator\"\n />\n <button\n type=\"button\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n data-format=\"link\"\n data-pressed={formats.link !== undefined || undefined}\n aria-label={t('toolbar.link.label')}\n aria-pressed={formats.link !== undefined}\n title={t('toolbar.link.title')}\n onClick={onOpenLink}\n >\n <Icon name=\"link\" />\n </button>\n <button\n type=\"button\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n data-format=\"formula\"\n aria-label={t('toolbar.formula.label')}\n title={t('toolbar.formula.title')}\n onClick={onInsertFormula}\n >\n <Icon name=\"sigma\" />\n </button>\n <span\n className=\"inkbrick-toolbar__separator\"\n data-inkbrick-part=\"separator\"\n role=\"separator\"\n />\n {PANELS.map(({ panel: name, icon }) => {\n const current = name === 'color' ? formats.color : formats.backgroundColor;\n\n return (\n <button\n key={name}\n type=\"button\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n data-format={name}\n data-pressed={panel === name || undefined}\n data-current-color={isColorName(current) ? current : undefined}\n aria-label={t(`toolbar.${name}.label`)}\n aria-haspopup=\"true\"\n aria-expanded={panel === name}\n title={t(`toolbar.${name}.title`)}\n onClick={() => onTogglePanel(name)}\n >\n <Icon name={icon} />\n <span className=\"inkbrick-toolbar__indicator\" data-inkbrick-part=\"indicator\" />\n </button>\n );\n })}\n <span\n className=\"inkbrick-toolbar__separator\"\n data-inkbrick-part=\"separator\"\n role=\"separator\"\n />\n {ALIGNMENTS.map((align) => (\n <button\n key={align}\n type=\"button\"\n className=\"inkbrick-toolbar__button\"\n data-inkbrick-part=\"button\"\n data-format={`align-${align}`}\n data-pressed={formats.align === align || undefined}\n aria-label={t(`toolbar.align.${align}.label`)}\n aria-pressed={formats.align === align}\n title={t(`toolbar.align.${align}.title`)}\n onClick={() => onAlign(align)}\n >\n <Icon name={ALIGN_ICONS[align]} />\n </button>\n ))}\n {panel && (\n <div\n className=\"inkbrick-toolbar__panel\"\n data-inkbrick-part=\"panel\"\n data-kind={panel}\n role=\"group\"\n aria-label={t(`toolbar.${panel}.label`)}\n >\n <button\n type=\"button\"\n data-inkbrick-part=\"swatch\"\n data-color=\"\"\n data-pressed={currentColor === undefined || undefined}\n aria-label={t(\n panel === 'color' ? 'toolbar.color.default' : 'toolbar.highlight.none',\n )}\n title={t(panel === 'color' ? 'toolbar.color.default' : 'toolbar.highlight.none')}\n onClick={() => onApplyColor(colorKind, null)}\n >\n <Icon name=\"x\" />\n </button>\n {COLOR_NAMES.map((name) => (\n <button\n key={name}\n type=\"button\"\n data-inkbrick-part=\"swatch\"\n data-color={name}\n data-pressed={currentColor === name || undefined}\n aria-label={t(`color.${name}`)}\n title={t(`color.${name}`)}\n onClick={() => onApplyColor(colorKind, name)}\n >\n {panel === 'color' ? 'A' : null}\n </button>\n ))}\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n","import type { BaseBlock, BlockId } from '@inkbrick/document';\n\nexport type BlockHeightEstimate = (block: BaseBlock) => number;\n\nconst CHARS_PER_LINE = 80;\n\nfunction textLength(block: BaseBlock): number {\n let length = 0;\n\n for (const node of block.content) length += node.insert.length;\n return length;\n}\n\n/**\n * Оценка по умолчанию под стандартные стили: строки текста × высота строки + отступы блока.\n * Ошибка оценки сказывается только на длине полосы прокрутки: отрисованный блок измеряется точно.\n */\nexport const estimateBlockHeight: BlockHeightEstimate = (block) => {\n const lines = Math.max(1, Math.ceil(textLength(block) / CHARS_PER_LINE));\n\n switch (block.flavour) {\n case 'block:heading':\n return 20 + 34 * lines;\n case 'block:code': {\n let breaks = 0;\n\n for (const node of block.content)\n for (const char of node.insert) if (char === '\\n') breaks += 1;\n\n return 40 + 21 * (breaks + 1);\n }\n case 'block:image':\n return 260;\n case 'block:divider':\n return 25;\n case 'block:formula':\n return 64;\n case 'block:callout':\n return 24 + 26 * lines;\n default:\n return 8 + 26 * lines;\n }\n};\n\nexport function estimateSubtree(\n getBlock: (id: BlockId) => BaseBlock | undefined,\n id: BlockId,\n estimate: BlockHeightEstimate,\n): number {\n let total = 0;\n const queue: BlockId[] = [id];\n\n for (let i = 0; i < queue.length; i++) {\n const block = getBlock(queue[i]);\n\n if (!block) continue;\n total += estimate(block);\n for (const child of block.children) queue.push(child);\n }\n\n return total;\n}\n","import {\n useEffect,\n useLayoutEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\n\nimport type { BlockId } from '@inkbrick/document';\nimport type { Editor } from '@inkbrick/engine';\n\nimport { useEditor } from '../../hooks/useEditor';\nimport { useEditorView } from '../../hooks/useEditorView';\nimport { BlockRenderer } from '../BlockRenderer';\nimport type { ChildListProps } from '../DocumentRenderer';\nimport { estimateSubtree, type BlockHeightEstimate } from './estimate';\n\nexport interface ResolvedVirtualOptions {\n readonly threshold: number;\n readonly overscan: number;\n readonly maxRendered: number;\n readonly estimateHeight: BlockHeightEstimate;\n}\n\ninterface Range {\n readonly top: number;\n readonly bottom: number;\n}\n\nconst SPACER = 'data-inkbrick-spacer';\n\nfunction upperBound(offsets: Float64Array, value: number): number {\n let lo = 0;\n let hi = offsets.length;\n\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n\n if (offsets[mid] <= value) lo = mid + 1;\n else hi = mid;\n }\n\n return lo;\n}\n\nfunction scrollParents(element: HTMLElement): HTMLElement[] {\n const result: HTMLElement[] = [];\n\n for (\n let node = element.parentElement;\n node && node !== document.body && node !== document.documentElement;\n node = node.parentElement\n ) {\n if (/(auto|scroll|hidden|clip)/.test(getComputedStyle(node).overflowY)) result.push(node);\n }\n\n return result;\n}\n\nfunction visibleRange(marker: HTMLElement, parents: readonly HTMLElement[]): Range {\n let top = 0;\n let bottom = window.innerHeight;\n\n for (const parent of parents) {\n const rect = parent.getBoundingClientRect();\n\n top = Math.max(top, rect.top);\n bottom = Math.min(bottom, rect.bottom);\n }\n\n const origin = marker.getBoundingClientRect().top;\n\n return { top: top - origin, bottom: Math.max(top, bottom) - origin };\n}\n\nfunction indexOfItem(\n editor: Editor,\n parentId: BlockId,\n ids: readonly BlockId[],\n id: BlockId,\n): number {\n let block = editor.store.getBlock(id);\n\n while (block && block.parentId !== parentId) {\n block = block.parentId ? editor.store.getBlock(block.parentId) : undefined;\n }\n\n return block ? ids.indexOf(block.id) : -1;\n}\n\nfunction Spacer({ height }: { readonly height: number }) {\n return (\n <div\n className=\"inkbrick-spacer\"\n data-inkbrick-spacer=\"\"\n aria-hidden=\"true\"\n contentEditable={false}\n style={{ height }}\n />\n );\n}\n\n/**\n * Дети контейнера с окном отрисовки: в DOM — блоки около видимой области, первый и последний блок (для Ctrl+A),\n * края выделения, перетаскиваемый блок и запрошенные редактором (`view.viewport`); остальные заменены\n * распорками. Высота отрисованного блока измеряется (вместе с отступом до следующего), неотрисованного — оценивается.\n * Короткие списки (меньше `threshold`) рисуются целиком теми же элементами, поэтому переход порога ничего не\n * пересоздаёт.\n */\nexport function VirtualChildList({\n parentId,\n ids,\n options,\n}: ChildListProps & { readonly options: ResolvedVirtualOptions }) {\n const editor = useEditor();\n const view = useEditorView();\n const windowed = ids.length >= options.threshold;\n const marker = useRef<HTMLDivElement>(null);\n const parents = useRef<HTMLElement[]>([]);\n // Измеренные высоты блоков и оценки неотрисованных (оценка не обновляется, пока блок не отрисуют и не измерят).\n const [heights] = useState(() => new Map<BlockId, number>());\n const [estimates] = useState(() => new Map<BlockId, number>());\n const [measured, remeasure] = useReducer((n: number) => n + 1, 0);\n const [range, setRange] = useState<Range>(() => ({\n top: 0,\n bottom: typeof window === 'undefined' ? 1000 : window.innerHeight,\n }));\n\n const pins = useSyncExternalStore(\n view.viewport.subscribe,\n view.viewport.getVersion,\n view.viewport.getVersion,\n );\n const dragId = useSyncExternalStore(\n view.blocks.subscribe,\n () => view.blocks.getState().drag?.blockId ?? null,\n () => null,\n );\n const dropId = useSyncExternalStore(\n view.blocks.subscribe,\n () => view.blocks.getState().drag?.targetId ?? null,\n () => null,\n );\n\n useEffect(() => (windowed ? view.viewport.attach() : undefined), [view, windowed]);\n\n const offsets = useMemo(() => {\n if (!windowed) return null;\n\n const result = new Float64Array(ids.length + 1);\n const getBlock = (id: BlockId) => editor.store.getBlock(id);\n\n for (let i = 0; i < ids.length; i++) {\n const id = ids[i];\n let height = heights.get(id) ?? estimates.get(id);\n\n if (height === undefined) {\n height = estimateSubtree(getBlock, id, options.estimateHeight);\n estimates.set(id, height);\n }\n\n result[i + 1] = result[i] + height;\n }\n\n return result;\n // measured — версия изменяемой карты heights\n }, [ids, windowed, measured, heights, estimates, editor, options.estimateHeight]);\n\n const rendered = useMemo(() => {\n if (!offsets) return null;\n\n const last = ids.length - 1;\n const from = Math.max(0, upperBound(offsets, range.top - options.overscan) - 1);\n const to = Math.min(\n last,\n upperBound(offsets, range.bottom + options.overscan) - 1,\n from + options.maxRendered - 1,\n );\n const pinned = new Set<number>([0, last]);\n\n for (const id of [...view.viewport.getPinned(), dragId, dropId]) {\n if (id) pinned.add(indexOfItem(editor, parentId, ids, id));\n }\n\n pinned.delete(-1);\n\n const result: number[] = [];\n\n for (const i of [...pinned].sort((a, b) => a - b)) if (i < from) result.push(i);\n for (let i = from; i <= to; i++) result.push(i);\n for (const i of [...pinned].sort((a, b) => a - b)) if (i > to) result.push(i);\n\n return result;\n // pins — версия view.viewport: getPinned() меняется вместе с ней\n }, [offsets, ids, range, options, view, editor, parentId, dragId, dropId, pins]);\n\n const observer = useRef<ResizeObserver | null>(null);\n const observed = useRef(new Map<Element, number>());\n\n useLayoutEffect(() => {\n if (!windowed || !rendered || !marker.current) return;\n\n const seen = new Set<Element>();\n const expected = new Set(rendered.map((i) => ids[i]));\n let changed = false;\n let previous: { id: BlockId; top: number; height: number } | null = null;\n let remaining = rendered.length;\n\n const settle = (height: number) => {\n if (!previous) return;\n // Элемент без раскладки (скрыт, jsdom) не измеряем: остаётся оценка.\n if (height > 0 && Math.abs((heights.get(previous.id) ?? -1) - height) > 0.5) {\n heights.set(previous.id, height);\n changed = true;\n }\n previous = null;\n };\n\n for (\n let element = marker.current.nextElementSibling;\n element && remaining > 0;\n element = element.nextElementSibling\n ) {\n const rect = element.getBoundingClientRect();\n\n if (previous) settle(rect.top - previous.top);\n if (element.hasAttribute(SPACER)) continue;\n\n remaining -= 1;\n\n const id = element.getAttribute('data-block-id');\n\n if (id && expected.has(id)) {\n previous = { id, top: rect.top, height: rect.height };\n seen.add(element);\n }\n }\n\n if (previous) settle((previous as { height: number }).height);\n\n if (typeof ResizeObserver !== 'undefined') {\n const sizes = observed.current;\n\n observer.current ??= new ResizeObserver((entries) => {\n let resized = false;\n\n for (const entry of entries) {\n const size = entry.contentRect.height;\n const known = sizes.get(entry.target);\n\n // Первое уведомление приходит сразу после observe — это не изменение.\n if (known !== undefined && Math.abs(known - size) > 0.5) resized = true;\n sizes.set(entry.target, size);\n }\n\n if (resized) remeasure();\n });\n\n for (const element of [...sizes.keys()]) {\n if (!seen.has(element)) {\n observer.current.unobserve(element);\n sizes.delete(element);\n }\n }\n\n for (const element of seen) {\n if (!sizes.has(element)) observer.current.observe(element);\n }\n }\n\n const next = visibleRange(marker.current, parents.current);\n const step = options.overscan / 4;\n\n setRange((current) =>\n Math.abs(current.top - next.top) < step && Math.abs(current.bottom - next.bottom) < step\n ? current\n : next,\n );\n\n if (changed) remeasure();\n });\n\n useEffect(() => () => observer.current?.disconnect(), []);\n\n useEffect(() => {\n if (!windowed || !marker.current) return;\n\n parents.current = scrollParents(marker.current);\n\n let frame = 0;\n const step = options.overscan / 4;\n\n const onScroll = () => {\n if (frame) return;\n\n frame = requestAnimationFrame(() => {\n frame = 0;\n if (!marker.current) return;\n\n const next = visibleRange(marker.current, parents.current);\n\n setRange((current) =>\n Math.abs(current.top - next.top) < step && Math.abs(current.bottom - next.bottom) < step\n ? current\n : next,\n );\n });\n };\n\n window.addEventListener('scroll', onScroll, { capture: true, passive: true });\n window.addEventListener('resize', onScroll);\n\n return () => {\n cancelAnimationFrame(frame);\n window.removeEventListener('scroll', onScroll, { capture: true });\n window.removeEventListener('resize', onScroll);\n };\n }, [windowed, options.overscan]);\n\n if (!rendered || !offsets) {\n return (\n <>\n {null}\n {ids.map((id) => (\n <BlockRenderer key={id} id={id} />\n ))}\n </>\n );\n }\n\n const items: ReactNode[] = [];\n let next = 0;\n\n for (const i of rendered) {\n if (i > next) items.push(<Spacer key={`gap:${next}`} height={offsets[i] - offsets[next]} />);\n items.push(<BlockRenderer key={ids[i]} id={ids[i]} />);\n next = i + 1;\n }\n\n return (\n <>\n <div\n ref={marker}\n className=\"inkbrick-spacer\"\n data-inkbrick-spacer=\"start\"\n aria-hidden=\"true\"\n contentEditable={false}\n />\n {items}\n </>\n );\n}\n","import type { ChildListProps, DocumentRenderer } from '../DocumentRenderer';\nimport { estimateBlockHeight, type BlockHeightEstimate } from './estimate';\nimport { VirtualChildList, type ResolvedVirtualOptions } from './VirtualChildList';\n\nexport interface VirtualRendererOptions {\n /** Контейнер с меньшим числом детей рисуется целиком. По умолчанию 100. */\n readonly threshold?: number;\n /** Запас над и под видимой областью, в котором блоки уже отрисованы, px. По умолчанию 1200. */\n readonly overscan?: number;\n /** Не больше стольких блоков подряд в окне (защита от нулевых высот). По умолчанию 400. */\n readonly maxRendered?: number;\n readonly estimateHeight?: BlockHeightEstimate;\n}\n\n/**\n * Виртуальный рендерер: в DOM только блоки около видимой области, остальные заменены распорками известной\n * (измеренной) или оценённой высоты. Подключение: `<DocumentView renderer={virtualRenderer()} />` (или\n * `renderer=\"virtual\"` с настройками по умолчанию). Создавайте рендерер один раз, вне компонента.\n */\nexport function virtualRenderer(options: VirtualRendererOptions = {}): DocumentRenderer {\n const resolved: ResolvedVirtualOptions = {\n threshold: Math.max(1, options.threshold ?? 100),\n overscan: Math.max(0, options.overscan ?? 1200),\n maxRendered: Math.max(1, options.maxRendered ?? 400),\n estimateHeight: options.estimateHeight ?? estimateBlockHeight,\n };\n\n function VirtualChildren(props: ChildListProps) {\n return <VirtualChildList {...props} options={resolved} />;\n }\n\n return { ChildList: VirtualChildren };\n}\n\nexport const defaultVirtualRenderer = virtualRenderer();\n"],"mappings":"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","names":["CLOSED","block","block","jsx","useContext","useContext","useSyncExternalStore","useSyncExternalStore","useCallback","useSyncExternalStore","useSyncExternalStore","useCallback","useSyncExternalStore","useSyncExternalStore","useMemo","block","useMemo","normalizeInlineNodes","normalizeInlineNodes","isSafeImageUrl","isSafeImageUrl","useContext","createContext","useSyncExternalStore","jsx","block","jsx","block","jsx","block","useLayoutEffect","useSyncExternalStore","isSafeUrl","isSafeUrl","jsx","block","useSyncExternalStore","useLayoutEffect","jsx","block","getBlockAlign","jsx","block","getBlockAlign","getBlockAlign","jsx","jsxs","block","getBlockAlign","getBlockAlign","jsx","block","getBlockAlign","useRef","jsx","jsxs","block","useRef","jsx","block","getBlockAlign","jsx","jsxs","block","getBlockAlign","useEffect","useRef","useState","useSyncExternalStore","isSafeImageUrl","flushSync","flushSync","jsx","jsxs","useState","useRef","useEffect","useSyncExternalStore","block","isSafeImageUrl","useCallback","useEffect","useRef","useState","useEffect","useState","jsx","useEffect","useRef","useState","jsx","jsxs","useRef","useState","useEffect","jsx","jsxs","block","useState","useRef","useEffect","useCallback","jsx","BlockRenderer","useSyncExternalStore","block","Fragment","jsx","createContext","jsx","useContext","useEffect","useLayoutEffect","useRef","useEffect","useRef","useSyncExternalStore","flushSync","block","jsx","flushSync","block","jsx","jsxs","useEffect","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useRef","useState","useEffect","useLayoutEffect","useSyncExternalStore","flushSync","block","cache","flushSync","useSyncExternalStore","Fragment","jsx","jsxs","useSyncExternalStore","useRef","useEffect","useEffect","createPortal","jsx","useEffect","createPortal","useEffect","normalizeLinkUrl","sanitizeFragment","flushSync","flushSync","block","useEffect","normalizeLinkUrl","sanitizeFragment","useEffect","useEffect","useEffect","block","isForeignControl","useEffect","useEffect","useEffect","useCallback","useEffect","useLayoutEffect","useRef","useState","useSyncExternalStore","createPortal","MAX_FORMULA_LENGTH","jsx","jsxs","useState","useRef","useCallback","useEffect","useLayoutEffect","MAX_FORMULA_LENGTH","useSyncExternalStore","createPortal","createPortal","useSyncExternalStore","useLayoutEffect","useRef","useState","jsx","jsxs","useRef","useState","useLayoutEffect","jsx","useSyncExternalStore","createPortal","createPortal","useSyncExternalStore","useEffect","useLayoutEffect","useRef","useState","isColorName","Fragment","jsx","jsxs","useRef","useState","useEffect","useLayoutEffect","isColorName","jsx","useSyncExternalStore","createPortal","block","useEffect","useLayoutEffect","useMemo","useRef","useState","useSyncExternalStore","Fragment","jsx","jsxs","block","useRef","useState","useSyncExternalStore","useEffect","useMemo","useLayoutEffect","next","jsx","Fragment","jsx","jsxs","useRef","useLayoutEffect","useEffect"]}