@olddevs/ui 4.5.0 → 4.6.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 (213) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/editor/RichTextEditor.d.ts +2 -2
  3. package/dist/editor/RichTextEditor.d.ts.map +1 -1
  4. package/dist/editor/RichTextEditor.js +3 -0
  5. package/dist/editor/RichTextEditor.js.map +1 -1
  6. package/dist/editor/core/blockTypes.d.ts +2 -8
  7. package/dist/editor/core/blockTypes.d.ts.map +1 -1
  8. package/dist/editor/core/blockTypes.js +11 -54
  9. package/dist/editor/core/blockTypes.js.map +1 -1
  10. package/dist/editor/core/containers.d.ts.map +1 -1
  11. package/dist/editor/core/containers.js +1 -0
  12. package/dist/editor/core/containers.js.map +1 -1
  13. package/dist/editor/core/customMarkdown.js +1 -1
  14. package/dist/editor/core/customMarkdown.js.map +1 -1
  15. package/dist/editor/core/customTool.d.ts +6 -6
  16. package/dist/editor/core/customTool.d.ts.map +1 -1
  17. package/dist/editor/core/customToolEngine.d.ts +2 -2
  18. package/dist/editor/core/extensions.d.ts +7 -2
  19. package/dist/editor/core/extensions.d.ts.map +1 -1
  20. package/dist/editor/core/extensions.js +96 -64
  21. package/dist/editor/core/extensions.js.map +1 -1
  22. package/dist/editor/core/fieldNotice.d.ts +1 -1
  23. package/dist/editor/core/insertItems.d.ts +5 -28
  24. package/dist/editor/core/insertItems.d.ts.map +1 -1
  25. package/dist/editor/core/insertItems.js +3 -94
  26. package/dist/editor/core/insertItems.js.map +1 -1
  27. package/dist/editor/core/insertMenuTool.d.ts +13 -0
  28. package/dist/editor/core/insertMenuTool.d.ts.map +1 -0
  29. package/dist/editor/core/insertMenuTool.js +20 -0
  30. package/dist/editor/core/insertMenuTool.js.map +1 -0
  31. package/dist/editor/core/schema.d.ts +20 -5
  32. package/dist/editor/core/schema.d.ts.map +1 -1
  33. package/dist/editor/core/schema.js +18 -3
  34. package/dist/editor/core/schema.js.map +1 -1
  35. package/dist/editor/core/shortcuts.d.ts +56 -5
  36. package/dist/editor/core/shortcuts.d.ts.map +1 -1
  37. package/dist/editor/core/shortcuts.js +91 -156
  38. package/dist/editor/core/shortcuts.js.map +1 -1
  39. package/dist/editor/core/skeleton.d.ts +1 -1
  40. package/dist/editor/core/skeleton.d.ts.map +1 -1
  41. package/dist/editor/core/skeleton.js +1 -0
  42. package/dist/editor/core/skeleton.js.map +1 -1
  43. package/dist/editor/core/toolButtons.d.ts +3 -3
  44. package/dist/editor/core/toolDefinition.d.ts +3 -3
  45. package/dist/editor/core/toolDescriptor.d.ts +49 -30
  46. package/dist/editor/core/toolDescriptor.d.ts.map +1 -1
  47. package/dist/editor/core/toolDescriptor.js +2 -5
  48. package/dist/editor/core/toolDescriptor.js.map +1 -1
  49. package/dist/editor/core/toolLoader.d.ts +1 -1
  50. package/dist/editor/core/toolLoader.d.ts.map +1 -1
  51. package/dist/editor/core/toolOptions.d.ts +19 -2
  52. package/dist/editor/core/toolOptions.d.ts.map +1 -1
  53. package/dist/editor/core/toolOptions.js.map +1 -1
  54. package/dist/editor/core/tools.d.ts +10 -2
  55. package/dist/editor/core/tools.d.ts.map +1 -1
  56. package/dist/editor/core/tools.js +1 -0
  57. package/dist/editor/core/tools.js.map +1 -1
  58. package/dist/editor/features/builtins.d.ts +6 -8
  59. package/dist/editor/features/builtins.d.ts.map +1 -1
  60. package/dist/editor/features/builtins.js +48 -21
  61. package/dist/editor/features/builtins.js.map +1 -1
  62. package/dist/editor/features/code/codeBlockTool.d.ts +5 -6
  63. package/dist/editor/features/code/codeBlockTool.d.ts.map +1 -1
  64. package/dist/editor/features/code/codeBlockTool.js +10 -1
  65. package/dist/editor/features/code/codeBlockTool.js.map +1 -1
  66. package/dist/editor/features/color/colorTools.d.ts +14 -0
  67. package/dist/editor/features/color/colorTools.d.ts.map +1 -0
  68. package/dist/editor/features/color/colorTools.js +39 -0
  69. package/dist/editor/features/color/colorTools.js.map +1 -0
  70. package/dist/editor/features/details/details.d.ts +68 -0
  71. package/dist/editor/features/details/details.d.ts.map +1 -0
  72. package/dist/editor/features/details/details.js +237 -0
  73. package/dist/editor/features/details/details.js.map +1 -0
  74. package/dist/editor/features/details/detailsMarkdown.d.ts +17 -0
  75. package/dist/editor/features/details/detailsMarkdown.d.ts.map +1 -0
  76. package/dist/editor/features/details/detailsMarkdown.js +84 -0
  77. package/dist/editor/features/details/detailsMarkdown.js.map +1 -0
  78. package/dist/editor/features/details/detailsTool.d.ts +16 -0
  79. package/dist/editor/features/details/detailsTool.d.ts.map +1 -0
  80. package/dist/editor/features/details/detailsTool.js +39 -0
  81. package/dist/editor/features/details/detailsTool.js.map +1 -0
  82. package/dist/editor/features/emoji/emojiTool.d.ts +1 -1
  83. package/dist/editor/features/heading/headingTool.d.ts +18 -0
  84. package/dist/editor/features/heading/headingTool.d.ts.map +1 -0
  85. package/dist/editor/features/heading/headingTool.js +59 -0
  86. package/dist/editor/features/heading/headingTool.js.map +1 -0
  87. package/dist/editor/features/history/historyTool.d.ts +15 -0
  88. package/dist/editor/features/history/historyTool.d.ts.map +1 -0
  89. package/dist/editor/features/history/historyTool.js +28 -0
  90. package/dist/editor/features/history/historyTool.js.map +1 -0
  91. package/dist/editor/features/image/imageTool.d.ts +19 -0
  92. package/dist/editor/features/image/imageTool.d.ts.map +1 -0
  93. package/dist/editor/features/image/imageTool.js +28 -0
  94. package/dist/editor/features/image/imageTool.js.map +1 -0
  95. package/dist/editor/features/layout/layoutTool.d.ts +11 -0
  96. package/dist/editor/features/layout/layoutTool.d.ts.map +1 -0
  97. package/dist/editor/features/layout/layoutTool.js +20 -0
  98. package/dist/editor/features/layout/layoutTool.js.map +1 -0
  99. package/dist/editor/features/lists/listTools.d.ts +15 -0
  100. package/dist/editor/features/lists/listTools.d.ts.map +1 -0
  101. package/dist/editor/features/lists/listTools.js +78 -0
  102. package/dist/editor/features/lists/listTools.js.map +1 -0
  103. package/dist/editor/features/marks/markTools.d.ts +16 -0
  104. package/dist/editor/features/marks/markTools.d.ts.map +1 -0
  105. package/dist/editor/features/marks/markTools.js +43 -0
  106. package/dist/editor/features/marks/markTools.js.map +1 -0
  107. package/dist/editor/features/search/searchTool.d.ts +1 -1
  108. package/dist/editor/features/table/tableTool.d.ts +3 -3
  109. package/dist/editor/features/toc/RichTextToc.d.ts.map +1 -1
  110. package/dist/editor/features/toc/RichTextToc.js +9 -2
  111. package/dist/editor/features/toc/RichTextToc.js.map +1 -1
  112. package/dist/editor/features/wrapper/wrapperTool.d.ts +11 -0
  113. package/dist/editor/features/wrapper/wrapperTool.d.ts.map +1 -0
  114. package/dist/editor/features/wrapper/wrapperTool.js +32 -0
  115. package/dist/editor/features/wrapper/wrapperTool.js.map +1 -0
  116. package/dist/editor/index.d.ts +1 -1
  117. package/dist/editor/index.d.ts.map +1 -1
  118. package/dist/editor/index.js.map +1 -1
  119. package/dist/editor/schema-entry.d.ts +1 -1
  120. package/dist/editor/styles/prose.d.ts.map +1 -1
  121. package/dist/editor/styles/prose.js +26 -0
  122. package/dist/editor/styles/prose.js.map +1 -1
  123. package/dist/editor/ui/EditorToolbar.d.ts.map +1 -1
  124. package/dist/editor/ui/EditorToolbar.js +5 -38
  125. package/dist/editor/ui/EditorToolbar.js.map +1 -1
  126. package/dist/editor/ui/SelectionBubble.d.ts.map +1 -1
  127. package/dist/editor/ui/SelectionBubble.js +1 -1
  128. package/dist/editor/ui/SelectionBubble.js.map +1 -1
  129. package/dist/editor/ui/ToolButtonView.d.ts.map +1 -1
  130. package/dist/editor/ui/ToolButtonView.js +1 -1
  131. package/dist/editor/ui/ToolButtonView.js.map +1 -1
  132. package/dist/i18n/defaults.d.ts.map +1 -1
  133. package/dist/i18n/defaults.js +3 -0
  134. package/dist/i18n/defaults.js.map +1 -1
  135. package/dist/i18n/messages.d.ts +16 -1
  136. package/dist/i18n/messages.d.ts.map +1 -1
  137. package/dist/icons.d.ts +8 -1
  138. package/dist/icons.d.ts.map +1 -1
  139. package/dist/icons.js +1 -1
  140. package/dist/icons.js.map +1 -1
  141. package/dist/locales/ru.d.ts.map +1 -1
  142. package/dist/locales/ru.js +3 -0
  143. package/dist/locales/ru.js.map +1 -1
  144. package/docs/api/editor-extension.en.md +56 -56
  145. package/docs/api/editor-extension.md +55 -55
  146. package/docs/api/messages.en.md +4 -1
  147. package/docs/api/messages.md +3 -0
  148. package/docs/api/migration-notes.en.md +3 -3
  149. package/docs/api/migration-notes.md +2 -2
  150. package/docs/components/content/rich-text-view.en.md +18 -12
  151. package/docs/components/content/rich-text-view.md +17 -11
  152. package/docs/components/inputs/rich-text-editor.en.md +140 -87
  153. package/docs/components/inputs/rich-text-editor.md +139 -86
  154. package/docs/conventions.en.md +2 -2
  155. package/docs/conventions.md +1 -1
  156. package/docs/getting-started.en.md +9 -9
  157. package/docs/getting-started.md +8 -8
  158. package/docs/glossary.en.md +80 -52
  159. package/docs/glossary.md +79 -51
  160. package/docs/icons.en.md +4 -1
  161. package/docs/icons.md +3 -0
  162. package/package.json +2 -1
  163. package/src/editor/RichTextEditor.tsx +9 -6
  164. package/src/editor/core/atomText.ts +2 -2
  165. package/src/editor/core/blockTypes.ts +19 -83
  166. package/src/editor/core/containers.ts +4 -2
  167. package/src/editor/core/customMarkdown.ts +2 -2
  168. package/src/editor/core/customTool.ts +6 -6
  169. package/src/editor/core/customToolEngine.ts +9 -9
  170. package/src/editor/core/extensions.ts +165 -110
  171. package/src/editor/core/fieldNotice.ts +1 -1
  172. package/src/editor/core/handle.ts +2 -2
  173. package/src/editor/core/insertItems.ts +12 -158
  174. package/src/editor/core/insertMenuTool.ts +32 -0
  175. package/src/editor/core/jsonDocument.ts +1 -1
  176. package/src/editor/core/schema.ts +42 -7
  177. package/src/editor/core/shortcuts.ts +116 -177
  178. package/src/editor/core/skeleton.ts +4 -3
  179. package/src/editor/core/toolButtons.ts +3 -3
  180. package/src/editor/core/toolDefinition.ts +4 -4
  181. package/src/editor/core/toolDescriptor.ts +65 -52
  182. package/src/editor/core/toolLoader.ts +3 -3
  183. package/src/editor/core/toolOptions.ts +21 -2
  184. package/src/editor/core/tools.ts +10 -1
  185. package/src/editor/core/viewIsland.ts +1 -1
  186. package/src/editor/features/builtins.ts +76 -41
  187. package/src/editor/features/code/codeBlockTool.ts +16 -8
  188. package/src/editor/features/color/colorTools.ts +68 -0
  189. package/src/editor/features/details/details.ts +389 -0
  190. package/src/editor/features/details/detailsMarkdown.ts +158 -0
  191. package/src/editor/features/details/detailsTool.ts +69 -0
  192. package/src/editor/features/emoji/emojiTool.tsx +1 -1
  193. package/src/editor/features/heading/headingTool.ts +96 -0
  194. package/src/editor/features/history/historyTool.ts +42 -0
  195. package/src/editor/features/image/imageTool.ts +49 -0
  196. package/src/editor/features/layout/layoutTool.ts +40 -0
  197. package/src/editor/features/lists/listTools.ts +112 -0
  198. package/src/editor/features/marks/markTools.ts +78 -0
  199. package/src/editor/features/search/searchTool.ts +1 -1
  200. package/src/editor/features/table/tableTool.ts +3 -3
  201. package/src/editor/features/toc/RichTextToc.tsx +14 -3
  202. package/src/editor/features/toc/tocTool.ts +1 -1
  203. package/src/editor/features/wrapper/wrapperTool.ts +52 -0
  204. package/src/editor/index.ts +1 -0
  205. package/src/editor/schema-entry.ts +1 -1
  206. package/src/editor/styles/prose.ts +49 -0
  207. package/src/editor/ui/EditorToolbar.tsx +7 -50
  208. package/src/editor/ui/SelectionBubble.tsx +2 -5
  209. package/src/editor/ui/ToolButtonView.tsx +2 -1
  210. package/src/i18n/defaults.ts +3 -0
  211. package/src/i18n/messages.ts +14 -1
  212. package/src/icons.ts +7 -0
  213. package/src/locales/ru.ts +3 -0
@@ -2,14 +2,14 @@
2
2
  category: api
3
3
  status: stable
4
4
  source: src/editor/index.ts
5
- sourceHash: 82b5217dd20e
5
+ sourceHash: 808244893ee6
6
6
  ---
7
7
 
8
8
  # Editor extension API
9
9
 
10
10
  ## Summary for AI
11
11
 
12
- A map of how a product extends `RichTextEditor` from `@olddevs/ui/editor`, and the stability boundary of this API. The unit of extension is a **custom Tool** (`CustomTool`): the description of one Editor capability, passed in `tools` mixed in with the kit's names. It carries Blocks and Marks with Schema rules (as data), an Engine part (Tiptap extensions, supplied directly or through a Loader) and UI contributions: buttons, Insert items, Block actions, Text cards. A custom Trigger character (`trigger`) is also available: `@` for mentions opens the same list as `/`. The screen's code controls the field through the Handle (`ref`) and the `useRichTextEditorState` hook, learns about Readiness and Field focus through the `onReady`, `onFocus` and `onBlur` callbacks, puts its own content into the Status line (`status`) and reports an error with the `showNotice` command. A Tool has three typed parts, like `options`, `storage` and `commands` of a Tiptap extension: **options** (`tool(name, options)` for the built-in `search` and `toc`, `defineTool` for a custom Tool), **state** (the `useRichTextToolState` hook) and **commands** (`handle.tool(name)`); their types are collected in the extensible `RichTextTools` map, where a custom Tool adds itself through `declare module "@olddevs/ui/editor"`. The same `tools` array is understood by server-side sanitizing (`sanitizeRichText`, `richTextSchema`) and by `RichTextView` with Islands. Everything listed follows the kit's semver from the first release, the HTML convention is frozen, and a Tiptap major is a kit major (section "Stability"). The details of each item live on the [RichTextEditor](../components/inputs/rich-text-editor.md) page; this page covers the map, the contract boundary and the recipes.
12
+ A map of how a product extends `RichTextEditor` from `@olddevs/ui/editor`, and the stability boundary of this API. The unit of extension is a **custom Tool** (`CustomTool`): the description of one Editor capability, passed in `tools` mixed in with the kit's names. It carries Blocks and Marks with Schema rules (as data), Extensions (Tiptap extensions, supplied directly or through a Loader) and UI contributions: buttons, Insert items, Block actions, Text cards. A custom Trigger character (`trigger`) is also available: `@` for mentions opens the same list as `/`. The screen's code controls the field through the Handle (`ref`) and the `useRichTextEditorState` hook, learns about Readiness and Field focus through the `onReady`, `onFocus` and `onBlur` callbacks, puts its own content into the Status line (`status`) and reports an error with the `showNotice` command. A Tool has three typed parts, like `options`, `storage` and `commands` of a Tiptap extension: **options** (`tool(name, options)` for the built-in `search` and `toc`, `defineTool` for a custom Tool), **state** (the `useRichTextToolState` hook) and **commands** (`handle.tool(name)`); their types are collected in the extensible `RichTextTools` map, where a custom Tool adds itself through `declare module "@olddevs/ui/editor"`. The same `tools` array is understood by server-side sanitizing (`sanitizeRichText`, `richTextSchema`) and by `RichTextView` with Islands. Everything listed follows the kit's semver from the first release, the HTML convention is frozen, and a Tiptap major is a kit major (section "Stability"). The details of each item live on the [RichTextEditor](../components/inputs/rich-text-editor.md) page; this page covers the map, the contract boundary and the recipes.
13
13
 
14
14
  ```tsx
15
15
  import {
@@ -40,39 +40,39 @@ The decision is ADR-0058, which supplements ADR-0050. Capitalized terms come fro
40
40
 
41
41
  - What you need is already among the kit's Tools (["Tools and Presets"](../components/inputs/rich-text-editor.md#инструменты-и-пресеты)): pass the name in `tools`, do not write a custom Tool.
42
42
  - To hide a built-in button or item, narrow `tools`. A built-in Tool cannot be replaced by name: turn it off and add a custom Tool under your own name.
43
- - Only `search` and `toc` have options; `tool("bold", …)` does not compile. Options for other built-in Tools will be added one at a time, as consumers ask for them. You cannot change the behavior of a built-in Tool by substitution (there is no `extend()` as in Tiptap): the descriptions of built-in Tools are not exported.
43
+ - Only `search`, `toc` and `details` have options; `tool("bold", …)` does not compile. Options for other built-in Tools will be added one at a time, as consumers ask for them. You cannot change the behavior of a built-in Tool by substitution (there is no `extend()` as in Tiptap): the descriptions of built-in Tools are not exported.
44
44
  - You cannot change the options of a mounted field: they are read once, when the engine is created, together with `tools`. Remount the field with a key.
45
45
  - You cannot put arbitrary React in the Toolbar row or in a menu: the kit renders the UI contributions itself. React is allowed only in the content of a popover (of a button, Insert item or Block action) and in a Text card.
46
- - You cannot intercept paste and drop through a prop: the Engine part of a custom Tool handles them (["Paste and drop order"](../components/inputs/rich-text-editor.md#порядок-вставки-и-drop)).
46
+ - You cannot intercept paste and drop through a prop: the Extensions of a custom Tool handle them (["Paste and drop order"](../components/inputs/rich-text-editor.md#порядок-вставки-и-drop)).
47
47
  - What is not provided until consumers ask for it (ADR-0058, section 13): `insertImage` and the selection's HTML in the Handle, `onSelectionChange`, `onPaste`, `onDrop`, `onEmpty`, `onDestroy`, history events, a signal about removed images, locked template Blocks, a "menu" UI contribution kind, Text cards and the Status line in `RichTextView`. Until then the screen has `ref.current.editor` and its events.
48
48
  - Custom Trigger characters like `@` are no longer on this list: they are supported by the `trigger` field of a Tool (ADR-0064, section "Trigger character" below).
49
49
 
50
50
  ## API map
51
51
 
52
- | What | Where in the API | Details |
53
- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
- | Custom Tool | `CustomTool` in `tools`; Presets — `RICH_TEXT_PRESETS` | ["Custom Tool"](../components/inputs/rich-text-editor.md#свой-инструмент) |
55
- | Schema rules and the HTML convention | `blocks` (`CustomBlock`), `marks` (`CustomMark`), `CustomAttribute`, `PrefixedName` | ["Custom Tool"](../components/inputs/rich-text-editor.md#свой-инструмент) |
56
- | Button | `buttons` (`CustomToolButton`, `CustomToolPopover`, `CustomToolLabel`) | ["Custom Tool's button"](../components/inputs/rich-text-editor.md#кнопка-своего-инструмента) |
57
- | Insert item, Block action | `insertItems` (`CustomInsertItem`), `blockActions` (`CustomBlockAction`) | ["Insert items and Block actions"](../components/inputs/rich-text-editor.md#пункты-вставки-и-действия-над-блоком) |
58
- | Trigger character | `trigger` (`CustomTrigger`, `TriggerItem`, `TriggerContext`) | ["Custom Trigger character"](../components/inputs/rich-text-editor.md#свой-символ-триггер) |
59
- | Text card | `textCards` (`CustomTextCard`), the `markRange` helper | ["Text card"](../components/inputs/rich-text-editor.md#карточка-у-текста) |
60
- | Handle and your own panel | `RichTextEditorHandle`, `useRichTextEditorState(ref, selector)` | ["Handle (`ref`) and your own toolbar outside the field"](../components/inputs/rich-text-editor.md#хэндл-ref-и-своя-панель-вне-поля) |
61
- | Options of a built-in Tool | `tool(name, options)` → `ConfiguredTool` for `search` and `toc`; `SearchToolOptions`, `TocToolOptions`, `TocLevel` | ["Options of a built-in Tool: `tool()`"](../components/inputs/rich-text-editor.md#опции-встроенного-инструмента-tool) |
62
- | A custom Tool with options, state, commands | `defineTool({ name, defaults, create, state, commands })` → `ToolDefinition`, `tool(definition, options)` | ["Options, state and commands"](editor-extension.md#опции-состояние-и-команды) |
63
- | Types of options, state and commands | the extensible `RichTextTools` interface | ["The `RichTextTools` map and declaration merging"](editor-extension.md#карта-richtexttools-и-declaration-merging) |
64
- | Tool state | `useRichTextToolState(ref, name, selector?)`, `SearchToolState`, `TocToolState`, `TocToolHeading` | ["Tool state: `useRichTextToolState`"](../components/inputs/rich-text-editor.md#состояние-инструмента-userichtexttoolstate) |
65
- | Tool commands | `handle.tool(name)`, `SearchToolCommands`, `TocToolCommands` | ["Tool commands: `handle.tool()`"](../components/inputs/rich-text-editor.md#команды-инструмента-handletool) |
66
- | Events | `onReady`, `onFocus`, `onBlur`; paste and drop — by the Engine part | ["Events"](../components/inputs/rich-text-editor.md#события) |
67
- | Status line and Field notice | the `status` prop; the engine command `showNotice`, the `FieldNotice` type | ["Status line and Field notice"](../components/inputs/rich-text-editor.md#строка-статуса-и-сообщение-поля) |
68
- | Loader, Readiness and Skeleton | `engine: () => import(…)` | ["Engine part Loader"](../components/inputs/rich-text-editor.md#загрузчик-части-для-движка), ["Skeleton"](../components/inputs/rich-text-editor.md#скелет) |
69
- | Atom text: `getText`, `maxLength`, emptiness | `renderText` of the Engine part | ["Atom text"](../components/inputs/rich-text-editor.md#текст-атома) |
70
- | Server, Markdown, View | `sanitizeRichText(html, DOMPurify, tools)`, `richTextSchema(tools)`, `RichTextView` | ["Outside the Editor"](../components/inputs/rich-text-editor.md#вне-редактора-сервер-markdown-и-просмотр), [RichTextView, "Custom Tools: the third argument"](../components/content/rich-text-view.md#свои-инструменты-третий-аргумент) |
71
- | Island of a custom Block | `CustomBlock.island`, `CustomIslandProps`, the `tools` prop of `RichTextView` | [RichTextView, "Custom Block's Island"](../components/content/rich-text-view.md#остров-своего-блока) |
52
+ | What | Where in the API | Details |
53
+ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | Custom Tool | `CustomTool` in `tools`; Presets — `RICH_TEXT_PRESETS` | ["Custom Tool"](../components/inputs/rich-text-editor.md#свой-инструмент) |
55
+ | Schema rules and the HTML convention | `blocks` (`CustomBlock`), `marks` (`CustomMark`), `CustomAttribute`, `PrefixedName` | ["Custom Tool"](../components/inputs/rich-text-editor.md#свой-инструмент) |
56
+ | Button | `buttons` (`CustomToolButton`, `CustomToolPopover`, `CustomToolLabel`) | ["Custom Tool's button"](../components/inputs/rich-text-editor.md#кнопка-своего-инструмента) |
57
+ | Insert item, Block action | `insertItems` (`CustomInsertItem`), `blockActions` (`CustomBlockAction`) | ["Insert items and Block actions"](../components/inputs/rich-text-editor.md#пункты-вставки-и-действия-над-блоком) |
58
+ | Trigger character | `trigger` (`CustomTrigger`, `TriggerItem`, `TriggerContext`) | ["Custom Trigger character"](../components/inputs/rich-text-editor.md#свой-символ-триггер) |
59
+ | Text card | `textCards` (`CustomTextCard`), the `markRange` helper | ["Text card"](../components/inputs/rich-text-editor.md#карточка-у-текста) |
60
+ | Handle and your own panel | `RichTextEditorHandle`, `useRichTextEditorState(ref, selector)` | ["Handle (`ref`) and your own toolbar outside the field"](../components/inputs/rich-text-editor.md#хэндл-ref-и-своя-панель-вне-поля) |
61
+ | Options of a built-in Tool | `tool(name, options)` → `ConfiguredTool` for `search`, `toc` and `details`; `SearchToolOptions`, `TocToolOptions`, `TocLevel`, `DetailsToolOptions` | ["Options of a built-in Tool: `tool()`"](../components/inputs/rich-text-editor.md#опции-встроенного-инструмента-tool) |
62
+ | A custom Tool with options, state, commands | `defineTool({ name, defaults, create, state, commands })` → `ToolDefinition`, `tool(definition, options)` | ["Options, state and commands"](editor-extension.md#опции-состояние-и-команды) |
63
+ | Types of options, state and commands | the extensible `RichTextTools` interface | ["The `RichTextTools` map and declaration merging"](editor-extension.md#карта-richtexttools-и-declaration-merging) |
64
+ | Tool state | `useRichTextToolState(ref, name, selector?)`, `SearchToolState`, `TocToolState`, `TocToolHeading` | ["Tool state: `useRichTextToolState`"](../components/inputs/rich-text-editor.md#состояние-инструмента-userichtexttoolstate) |
65
+ | Tool commands | `handle.tool(name)`, `SearchToolCommands`, `TocToolCommands` | ["Tool commands: `handle.tool()`"](../components/inputs/rich-text-editor.md#команды-инструмента-handletool) |
66
+ | Events | `onReady`, `onFocus`, `onBlur`; paste and drop — by the Extensions | ["Events"](../components/inputs/rich-text-editor.md#события) |
67
+ | Status line and Field notice | the `status` prop; the engine command `showNotice`, the `FieldNotice` type | ["Status line and Field notice"](../components/inputs/rich-text-editor.md#строка-статуса-и-сообщение-поля) |
68
+ | Loader, Readiness and Skeleton | `engine: () => import(…)` | ["Extensions Loader"](../components/inputs/rich-text-editor.md#загрузчик-extensions), ["Skeleton"](../components/inputs/rich-text-editor.md#скелет) |
69
+ | Atom text: `getText`, `maxLength`, emptiness | `renderText` of the Extensions | ["Atom text"](../components/inputs/rich-text-editor.md#текст-атома) |
70
+ | Server, Markdown, View | `sanitizeRichText(html, DOMPurify, tools)`, `richTextSchema(tools)`, `RichTextView` | ["Outside the Editor"](../components/inputs/rich-text-editor.md#вне-редактора-сервер-markdown-и-просмотр), [RichTextView, "Custom Tools: the third argument"](../components/content/rich-text-view.md#свои-инструменты-третий-аргумент) |
71
+ | Island of a custom Block | `CustomBlock.island`, `CustomIslandProps`, the `tools` prop of `RichTextView` | [RichTextView, "Custom Block's Island"](../components/content/rich-text-view.md#остров-своего-блока) |
72
72
 
73
73
  ## Custom Tool and the HTML convention
74
74
 
75
- There is one description, with two parts inside. The **Schema rules** are plain data with no Tiptap: the Editor, server-side sanitizing and the View read them. The **Engine part** consists entirely of Tiptap extensions (Node, Mark, Extension, ProseMirror plugins, a React node view): behavior only, while the kit sets up HTML parsing and output. The name, the Engine part and a Schema rule for each of its Nodes and Marks are required; everything else has defaults: a plain Block with no traits, exported to Markdown as its content, paragraph rhythm in the View, no UI contributions. A Tool may carry no Block at all — for example, only a paste filter.
75
+ There is one description, with two parts inside. The **Schema rules** are plain data with no Tiptap: the Editor, server-side sanitizing and the View read them. The **Extensions** are made up entirely of Tiptap extensions (Node, Mark, Extension, ProseMirror plugins, a React node view): behavior only, while the kit sets up HTML parsing and output. The name, the Extensions and a Schema rule for each of their Nodes and Marks are required; everything else has defaults: a plain Block with no traits, exported to Markdown as its content, paragraph rhythm in the View, no UI contributions. A Tool may carry no Block at all — for example, only a paste filter.
76
76
 
77
77
  Every custom name starts with a Consumer prefix followed by an underscore: the Tool `acme_mergeTag`, the attribute `acme_size`. The kit's names have no underscores, so custom and built-in names do not collide, either in the `tools` array or in a saved Document. The kit writes and reads custom HTML:
78
78
 
@@ -83,7 +83,7 @@ Every custom name starts with a Consumer prefix followed by an underscore: the T
83
83
  | Mark | `<span data-mark="acme_comment">…</span>` |
84
84
  | Attribute | `data-acme_size="m"` — the value follows the rule: list, pattern or URL |
85
85
 
86
- The `tools` array is checked once, when the engine is created (with Loaders, after they have run). A name without a prefix, a name clash, an Engine part with a Node or Mark that has no Schema rule (or the reverse), or a UI contribution without a required field produces an "Editor failed to start" field error, not a silent loss of Blocks on the first save. An unknown **string** in `tools` is still dropped silently.
86
+ The `tools` array is checked once, when the engine is created (with Loaders, after they have run). A name without a prefix, a name clash, Extensions with a Node or Mark that has no Schema rule (or the reverse), or a UI contribution without a required field produces an "Editor failed to start" field error, not a silent loss of Blocks on the first save. An unknown **string** in `tools` is still dropped silently.
87
87
 
88
88
  ## UI contributions
89
89
 
@@ -99,7 +99,7 @@ The kit renders, the Tool describes. So the ARIA roles, the Toolbar's single Tab
99
99
  - **The label** is a string or a function that receives `{ locale }` (the `UiProvider` locale); the `UiProvider` message catalog is not extended for third-party Tools, and overriding is through the Tool factory's options (recipe below).
100
100
  - **The icon** is required for a button, item and action: a component with the `IconProps` contract from `@olddevs/ui/icons`, or your own.
101
101
  - **The popover** — a button, Insert item and Block action have exactly one of `run` and `popover`. The content is a function that receives `{ editor, close }` (for an action, also the Block's `pos`), and the kit provides the frame: the overlay layer, the Editor's popover Glass, the Escape stack, the name (the UI contribution's label), and returning focus and selection to the Document. A Text card sits on the same Glass, so your content does not need a solid background: it would cover the Glass backing. When the system transparency or contrast setting is on, the backing becomes solid on its own anyway. The popover opens at the button (click), at the caret (the button's shortcut, an item from "/", "+", "Add ›", "Format ›" and its shortcut) or at the Block (an action from the Block handle menu and its shortcut).
102
- - **The shortcut** (`shortcut`) is the single source: the kit binds the keyboard shortcut and writes it into the tooltip, `aria-keyshortcuts` and the Shortcuts reference. Keyboard shortcuts of the Engine part do not reach the reference.
102
+ - **The shortcut** (`shortcut`) is the single source: the kit binds the keyboard shortcut and writes it into the tooltip, `aria-keyshortcuts` and the Shortcuts reference. Keyboard shortcuts bound by the Extensions do not reach the reference.
103
103
  - **A disabled Tool** removes its UI contributions from every surface.
104
104
 
105
105
  ## Trigger character
@@ -125,11 +125,11 @@ A Tool has three typed parts. They carry Tiptap's `options`, `storage` and `comm
125
125
  | State | A snapshot the screen reads | The kit for built-ins; the `state` field of `defineTool` | `useRichTextToolState(ref, name, selector?)` |
126
126
  | Commands | What the screen calls | The kit for built-ins; the `commands` field of `defineTool` | `ref.current?.tool(name)?.command()` |
127
127
 
128
- The Engine part still follows the Tiptap major (ADR-0058, item 12.4). The three new parts do not depend on Tiptap: their types and behavior follow the kit's semver.
128
+ The Extensions still follow the Tiptap major (ADR-0058, item 12.4). The three new parts do not depend on Tiptap: their types and behavior follow the kit's semver.
129
129
 
130
130
  ### `tool()`: a built-in Tool with options
131
131
 
132
- `tool(name, options)` returns a Configured Tool: an opaque entry for `tools` (only the kit reads its fields). `search` has options (the starting flags) and so does `toc` (`offsetVar`, `levels`, `listWidth`); their values and an example are on the [RichTextEditor](../components/inputs/rich-text-editor.md#опции-встроенного-инструмента-tool) page. An entry switches the Tool on even without the name in `tools`, and a name from a Preset gives way to it. Two `tool()` entries with the same name are a set error.
132
+ `tool(name, options)` returns a Configured Tool: an opaque entry for `tools` (only the kit reads its fields). `search` has options (the starting flags), and so do `toc` (`offsetVar`, `levels`, `listWidth`) and `details` (`persist`: whether the open state of a collapsible Block is written into the Document); their values and an example are on the [RichTextEditor](../components/inputs/rich-text-editor.md#опции-встроенного-инструмента-tool) page. An entry switches the Tool on even without the name in `tools`, and a name from a Preset gives way to it. Two `tool()` entries with the same name are a set error.
133
133
 
134
134
  `tool(definition, options)` configures a `defineTool` definition the same way; the options come from its `defaults`.
135
135
 
@@ -138,17 +138,17 @@ The Engine part still follows the Tiptap major (ADR-0058, item 12.4). The three
138
138
  `defineTool({ name, defaults, create, state?, commands? })` returns a definition: an element of `tools` that works both without `tool()` (with the defaults from `defaults`) and with it.
139
139
 
140
140
  - **`defaults`** is the full set of options. The options type is inferred from it, so you do not declare it a second time. A literal widens to its base type (`tone: "info"` becomes `string`): for a union, give the value a type, `tone: "info" as "info" | "warning"`.
141
- - **`create(options)`** returns the body of the description: the same shape as `CustomTool`, without the name (`CustomToolBody`): the Engine part, Schema rules, UI contributions. It is called once per `tools` entry (the definition itself, or the object that `tool(definition, options)` returned): the kit remembers the result for the pair of the definition and the entry's options object. Anything closed over in the `create` body (a counter, a cache) is therefore shared by every Editor that uses that entry. A `tool(…)` entry created in a component body is new on every render, and the Island in `RichTextView` remounts on every render: take the `tools` set out of the render, into a module constant or `useMemo`. Keep the Engine part Loader a module constant: the Loader's cache lives on the function itself, and a new function on every `create` call would load the part again for every entry.
141
+ - **`create(options)`** returns the body of the description: the same shape as `CustomTool`, without the name (`CustomToolBody`): the Extensions, Schema rules, UI contributions. It is called once per `tools` entry (the definition itself, or the object that `tool(definition, options)` returned): the kit remembers the result for the pair of the definition and the entry's options object. Anything closed over in the `create` body (a counter, a cache) is therefore shared by every Editor that uses that entry. A `tool(…)` entry created in a component body is new on every render, and the Island in `RichTextView` remounts on every render: take the `tools` set out of the render, into a module constant or `useMemo`. Keep the Extensions Loader a module constant: the Loader's cache lives on the function itself, and a new function on every `create` call would load the Extensions again for every entry.
142
142
  - **`state({ editor, options })`** is the state for `useRichTextToolState`. It is called on every transaction and on every hook read, so it must be fast and free of side effects, and it must return data without DOM nodes. Primitives, arrays and plain objects are compared by value, so the screen re-renders only when the snapshot has changed. `Date`, `Map`, `Set` and class instances are compared by reference: a `state` that creates them anew on every call re-renders the screen on every transaction. Return plain data (`date.toISOString()`) or the same reference while the data has not changed. With no `state`, the Tool has no state and the hook returns `null`.
143
143
  - **`commands({ editor, options })`** returns the commands for `handle.tool(name)`. It is called on every access through the Handle: thin wrappers over the engine, no subscriptions. A command returns a `boolean`, like the built-in ones. With no `commands`, `handle.tool(name)` returns `null`.
144
144
  - **Merging options.** Nested plain objects are merged with the defaults, and arrays and functions are replaced whole, like `configure` in Tiptap v3. An `undefined` value is ignored: the existing value stays. The `defaults` object is not changed; the options object is shared by `create`, `state` and `commands`: read it, do not mutate it.
145
145
  - **Options are read once**, when the engine is created, together with the set. To change them, remount the Editor with a key (`key`). The kit does not validate the values of a custom Tool's options; that is up to its author.
146
- - **All the rules of a custom Tool apply** (ADR-0058): the Consumer prefix in the name, a unique name in `tools` (the same definition twice, with `tool()` and without, is also a set error), the set checks, the Engine part Loader. `defineTool` is sugar over the same `CustomTool` shape: it has no build path of its own. A plain `CustomTool` object in `tools` works as before, without options, state and commands.
146
+ - **All the rules of a custom Tool apply** (ADR-0058): the Consumer prefix in the name, a unique name in `tools` (the same definition twice, with `tool()` and without, is also a set error), the set checks, the Extensions Loader. `defineTool` is sugar over the same `CustomTool` shape: it has no build path of its own. A plain `CustomTool` object in `tools` works as before, without options, state and commands.
147
147
  - **Server.** `defineTool` and `tool()` live in a module with no Tiptap or React at run time (Tiptap appears there only as types), so the `tools` set can be built in a server module next to the rest of the screen's configuration. A definition holds functions, like `CustomTool`, so it reaches a client component together with its module (an import), not as a prop across the RSC boundary. A configured built-in Tool is made of data: with data in its options, it can be passed as a prop too.
148
148
 
149
149
  ### The `RichTextTools` map and declaration merging
150
150
 
151
- The types of all three parts are collected in the `RichTextTools` interface, like `Storage` and `Commands` in Tiptap: the key is the Tool's name, the value is `{ options; state; commands }`. The kit declares `search` and `toc` in it, and the consumer adds a custom Tool:
151
+ The types of all three parts are collected in the `RichTextTools` interface, like `Storage` and `Commands` in Tiptap: the key is the Tool's name, the value is `{ options; state; commands }`. The kit declares `search`, `toc` and `details` in it (the last has only `options`), and the consumer adds a custom Tool:
152
152
 
153
153
  ```ts
154
154
  declare module "@olddevs/ui/editor" {
@@ -165,7 +165,7 @@ declare module "@olddevs/ui/editor" {
165
165
  - The map gives the snapshot type to `useRichTextToolState`, the commands type to `handle.tool()` and the options to `tool()` for a built-in Tool. For a custom Tool, `tool()` takes the options from the `defaults` of its definition, so the `options` field in the map describes the options for readers of the map (`RichTextTools["acme_note"]["options"]`), and `tool()` does not use it.
166
166
  - **Typing is optional.** A Tool not added to the map works: its state and commands have the type `unknown`.
167
167
  - The file with `declare module` must be a module (it has an `import` or an `export`); otherwise the declaration does not augment the map but declares a module of its own. Put it next to the Tool's definition.
168
- - Do not confuse the map with typing the engine. If you already type an Engine part through `declare module "@tiptap/core"` (`Commands`, `Storage`), keep doing so: that is the engine layer and follows its major, while `RichTextTools` is the kit layer.
168
+ - Do not confuse the map with typing the engine. If you already type Extensions through `declare module "@tiptap/core"` (`Commands`, `Storage`), keep doing so: that is the engine layer and follows its major, while `RichTextTools` is the kit layer.
169
169
 
170
170
  ### An end-to-end example
171
171
 
@@ -299,12 +299,12 @@ What to note here. The `tool("toc", …)` entry switches the Table of contents o
299
299
 
300
300
  ## Loaders, Readiness and Skeleton
301
301
 
302
- The Engine part can be supplied by a Loader — `engine: () => import("./engine.js").then((m) => m.engine)`: the server then imports the module with the description, and Tiptap goes into a separate chunk. Loading starts on the first render in the browser, and the promise is cached on the Loader function (so a Loader is one function per module). **Readiness** is when the engine is created and the Loaders of all enabled Tools — custom and the heavy built-in ones (`codeBlock`, `table`) — have run. Before it, the field is a **Skeleton**: the frame, the place of the Toolbar and the Document cleaned by the Schema, with no input and no height jump; on the server, the frame without the Document. A Loader failure is a field error with "Retry", and the Document stays visible. For details, see ["Engine part Loader"](../components/inputs/rich-text-editor.md#загрузчик-части-для-движка) and ["Skeleton"](../components/inputs/rich-text-editor.md#скелет).
302
+ The Extensions can be supplied by a Loader — `engine: () => import("./engine.js").then((m) => m.engine)`: the server then imports the module with the description, and Tiptap goes into a separate chunk. Loading starts on the first render in the browser, and the promise is cached on the Loader function (so a Loader is one function per module). **Readiness** is when the engine is created and the Loaders of all enabled Tools — custom and the heavy built-in ones (`codeBlock`, `table`) — have run. Before it, the field is a **Skeleton**: the frame, the place of the Toolbar and the Document cleaned by the Schema, with no input and no height jump; on the server, the frame without the Document. A Loader failure is a field error with "Retry", and the Document stays visible. For details, see ["Extensions Loader"](../components/inputs/rich-text-editor.md#загрузчик-extensions) and ["Skeleton"](../components/inputs/rich-text-editor.md#скелет).
303
303
 
304
304
  ## Server, Markdown, View and Island
305
305
 
306
306
  - **The server** sanitizes the Document with the same `tools` array: `sanitizeRichText(html, DOMPurify, tools)`, the rules as data — `richTextSchema(tools)`. Both are also in the lightweight `@olddevs/ui/editor/schema` without Tiptap and React — together with `markRange`: the description of a custom Tool with a Text card can be built in a server module too. The names of the kit's Tools in `tools` do not narrow the allowlist: sanitizing accepts everything the kit accepts. Without the third argument sanitizing works as before, and custom Blocks are stripped.
307
- - **Markdown** — rules in the Engine part (`renderMarkdown`, `markdownTokenizer`, `parseMarkdown`). Without them a Block is exported as its content, an Atom as Atom text, and the text is not lost.
307
+ - **Markdown** — rules in the Extensions (`renderMarkdown`, `markdownTokenizer`, `parseMarkdown`). Without them a Block is exported as its content, an Atom as Atom text, and the text is not lost.
308
308
  - **`RichTextView`** shows a custom Block as sanitized HTML with paragraph rhythm; styling is your CSS, keyed on `data-block`. An **Island** is a client component in the Block's `island` field: it comes to life after mounting and only if such a Block is in the Document; for this, `RichTextView` receives the same `tools`.
309
309
 
310
310
  ## Stability
@@ -316,34 +316,34 @@ The contract boundary per ADR-0058, item 12. The reviewer checks the changeset t
316
316
  - the description of a custom Tool (`CustomTool` and its fields, `trigger` included), UI contributions and their Slots, Schema rules (`CustomBlock`, `CustomMark`, `CustomAttribute`), Block traits;
317
317
  - the HTML convention (`data-block`, `data-mark`, `data-<prefix>_<name>`);
318
318
  - the Handle's methods, `useRichTextEditorState`, the `onReady`, `onFocus`, `onBlur` callbacks, the `status` prop, the `showNotice` command and the `FieldNotice` type;
319
- - options, state and commands (ADR-0069): the `RichTextTools` map, `tool()`, `defineTool()` and its types (`ToolDefinition`, `ConfiguredTool`), `useRichTextToolState`, `handle.tool()`, and the options, state and command fields of `search` and `toc`;
319
+ - options, state and commands (ADR-0069): the `RichTextTools` map, `tool()`, `defineTool()` and its types (`ToolDefinition`, `ConfiguredTool`), `useRichTextToolState`, `handle.tool()`, and the options, state and command fields of `search` and `toc` and the options of `details`;
320
320
  - the third argument of `sanitizeRichText` and `richTextSchema`, the `tools` prop and the Island of `RichTextView`, `markRange`;
321
321
  - the names of built-in Tools (`ToolName`) and the existence of the Preset arrays `RICH_TEXT_PRESETS` — but not their composition (below).
322
322
 
323
- **Not included:** the kit's DOM and classes around a Slot; the ids of built-in buttons and items; the internal description of built-in Tools (a superset of the public shape) — it is not exported; the exact place of a UI contribution inside a surface; the look of the Skeleton; the shape of a Configured Tool from the inside (the entry is opaque, only the kit reads its fields); the timing of the scroll after the Find commands (it happens a moment after the call); file and chunk names in `dist`, like any path inside the package (["Public contract"](../conventions.md#публичный-контракт)). The API of the raw `editor` and of the Engine part is Tiptap's API, and it follows the engine's major.
323
+ **Not included:** the kit's DOM and classes around a Slot; the ids of built-in buttons and items; the internal description of built-in Tools (a superset of the public shape) — it is not exported; the exact place of a UI contribution inside a surface; the look of the Skeleton; the shape of a Configured Tool from the inside (the entry is opaque, only the kit reads its fields); the timing of the scroll after the Find commands (it happens a moment after the call); file and chunk names in `dist`, like any path inside the package (["Public contract"](../conventions.md#публичный-контракт)). The API of the raw `editor` and of the Extensions is Tiptap's API, and it follows the engine's major.
324
324
 
325
325
  **Neither a minor nor a patch breaks a saved Document.** The HTML convention is frozen: `data-block` and `data-mark` are extended only by addition. If the form has to change, that is a major, and until the next major the kit reads both forms — both in engine parsing and in the sanitizer.
326
326
 
327
327
  **What counts as breaking is a violation of the contract, not a pixel shift:**
328
328
 
329
- | Change | Version |
330
- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------- |
331
- | A new required field of the description | major |
332
- | A new Block trait or a default that changes the behavior of already described Blocks | major |
333
- | Abandoning "one Slot per surface" or "custom UI contributions in the order of `tools`" | major |
334
- | Moving a UI contribution kind to another surface | major |
335
- | Changing the form of the HTML convention | major, and both forms are read until the next major |
336
- | A new Tiptap major — even with no changes in the kit's code: the consumer's Engine parts break | major |
337
- | Removing a Tool from a Preset, renaming a Tool | major |
338
- | Removing a public name | major, after `@deprecated` in a minor (below) |
339
- | A new optional field, a new UI contribution kind, a Handle method or a callback | minor |
340
- | A new option or state field, a new command, an option on another built-in Tool | minor |
341
- | Removing an option, state or command field, changing its meaning | major |
342
- | A new built-in Tool in a Preset | minor, the changeset line is in bold |
343
- | A shift of a Slot inside a surface | minor with a changeset line |
344
- | Raising Tiptap's lower bound within a major | minor |
345
- | Tightening sanitizing for security | patch or minor with a note in migration-notes |
346
- | The look of the Skeleton, DOM and classes around a Slot | outside the contract |
329
+ | Change | Version |
330
+ | -------------------------------------------------------------------------------------------- | --------------------------------------------------- |
331
+ | A new required field of the description | major |
332
+ | A new Block trait or a default that changes the behavior of already described Blocks | major |
333
+ | Abandoning "one Slot per surface" or "custom UI contributions in the order of `tools`" | major |
334
+ | Moving a UI contribution kind to another surface | major |
335
+ | Changing the form of the HTML convention | major, and both forms are read until the next major |
336
+ | A new Tiptap major — even with no changes in the kit's code: the consumer's Extensions break | major |
337
+ | Removing a Tool from a Preset, renaming a Tool | major |
338
+ | Removing a public name | major, after `@deprecated` in a minor (below) |
339
+ | A new optional field, a new UI contribution kind, a Handle method or a callback | minor |
340
+ | A new option or state field, a new command, an option on another built-in Tool | minor |
341
+ | Removing an option, state or command field, changing its meaning | major |
342
+ | A new built-in Tool in a Preset | minor, the changeset line is in bold |
343
+ | A shift of a Slot inside a surface | minor with a changeset line |
344
+ | Raising Tiptap's lower bound within a major | minor |
345
+ | Tightening sanitizing for security | patch or minor with a note in migration-notes |
346
+ | The look of the Skeleton, DOM and classes around a Slot | outside the contract |
347
347
 
348
348
  - **A Tiptap major is a kit major.** The kit supports one Tiptap major at a time; the engine is not in the kit manifest, and the consumer maintains the version range (`^3.31.4`) given on the [RichTextEditor](../components/inputs/rich-text-editor.md#установка) page.
349
349
  - **A Preset** is "what the kit considers a full set", not a frozen list. If you need a stable composition, pass an exact list of names.
@@ -499,7 +499,7 @@ An empty label does not crash the field: in development there is a `console.erro
499
499
 
500
500
  ### `modulepreload` for lazy chunks
501
501
 
502
- The kit does not publish preloads. The chunks of Engine parts (of custom Loaders and of the built-in `codeBlock` and `table` in `full`) start loading on the Editor's first render, and the Skeleton is shown in the meantime. To have a chunk arrive with the page, add a `<link rel="modulepreload">` for it (in React 19, `preloadModule(url)` from `react-dom`); take the hashed URL from your bundler's manifest: the kit's chunk names are not part of the contract. For an example, see [RichTextEditor, "Engine part Loader"](../components/inputs/rich-text-editor.md#загрузчик-части-для-движка); the cost of the "start" and "full" scenarios is in ["Import size"](../getting-started.md#размер-импорта).
502
+ The kit does not publish preloads. The chunks of Extensions (of custom Loaders and of the built-in `codeBlock` and `table` in `full`) start loading on the Editor's first render, and the Skeleton is shown in the meantime. To have a chunk arrive with the page, add a `<link rel="modulepreload">` for it (in React 19, `preloadModule(url)` from `react-dom`); take the hashed URL from your bundler's manifest: the kit's chunk names are not part of the contract. For an example, see [RichTextEditor, "Extensions Loader"](../components/inputs/rich-text-editor.md#загрузчик-extensions); the cost of the "start" and "full" scenarios is in ["Import size"](../getting-started.md#размер-импорта).
503
503
 
504
504
  ## Links
505
505