@gravity-ui/markdown-editor 15.36.0 → 15.38.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 (245) hide show
  1. package/README.md +87 -0
  2. package/build/cjs/core/ExtensionBuilder.d.ts +21 -0
  3. package/build/cjs/core/ExtensionBuilder.js +306 -4
  4. package/build/cjs/core/ExtensionBuilder.js.map +1 -1
  5. package/build/cjs/core/markdown/MarkdownSerializer.d.ts +4 -1
  6. package/build/cjs/core/markdown/MarkdownSerializer.js +86 -23
  7. package/build/cjs/core/markdown/MarkdownSerializer.js.map +1 -1
  8. package/build/cjs/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js +1 -0
  9. package/build/cjs/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js.map +1 -1
  10. package/build/cjs/extensions/behavior/Clipboard/clipboard.js +2 -13
  11. package/build/cjs/extensions/behavior/Clipboard/clipboard.js.map +1 -1
  12. package/build/cjs/extensions/behavior/Clipboard/selection-content.d.ts +1 -0
  13. package/build/cjs/extensions/behavior/Clipboard/selection-content.js +35 -0
  14. package/build/cjs/extensions/behavior/Clipboard/selection-content.js.map +1 -0
  15. package/build/cjs/extensions/behavior/Selection/commands.d.ts +2 -1
  16. package/build/cjs/extensions/behavior/Selection/commands.js +47 -1
  17. package/build/cjs/extensions/behavior/Selection/commands.js.map +1 -1
  18. package/build/cjs/extensions/behavior/Selection/selection.d.ts +15 -0
  19. package/build/cjs/extensions/behavior/Selection/selection.js +1 -0
  20. package/build/cjs/extensions/behavior/Selection/selection.js.map +1 -1
  21. package/build/cjs/extensions/behavior/SelectionContext/TextSelectionTooltip.d.ts +13 -0
  22. package/build/cjs/extensions/behavior/SelectionContext/TextSelectionTooltip.js +42 -0
  23. package/build/cjs/extensions/behavior/SelectionContext/TextSelectionTooltip.js.map +1 -0
  24. package/build/cjs/extensions/behavior/SelectionContext/index.js +10 -7
  25. package/build/cjs/extensions/behavior/SelectionContext/index.js.map +1 -1
  26. package/build/cjs/extensions/behavior/SelectionContext/tooltip.d.ts +11 -15
  27. package/build/cjs/extensions/behavior/SelectionContext/tooltip.js +24 -56
  28. package/build/cjs/extensions/behavior/SelectionContext/tooltip.js.map +1 -1
  29. package/build/cjs/extensions/behavior/SelectionContext/types.d.ts +10 -0
  30. package/build/cjs/extensions/behavior/SelectionContext/types.js +3 -0
  31. package/build/cjs/extensions/behavior/SelectionContext/types.js.map +1 -0
  32. package/build/cjs/extensions/markdown/Blockquote/BlockquoteSpecs/index.js +1 -0
  33. package/build/cjs/extensions/markdown/Blockquote/BlockquoteSpecs/index.js.map +1 -1
  34. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.d.ts +2 -2
  35. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js +17 -75
  36. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js.map +1 -1
  37. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.d.ts +14 -0
  38. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js +117 -0
  39. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js.map +1 -0
  40. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.d.ts +9 -0
  41. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js +22 -0
  42. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js.map +1 -0
  43. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.d.ts +2 -3
  44. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js +5 -93
  45. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js.map +1 -1
  46. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.d.ts +23 -0
  47. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js +88 -0
  48. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js.map +1 -0
  49. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js +24 -34
  50. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js.map +1 -1
  51. package/build/cjs/extensions/markdown/Deflist/DeflistSpecs/schema.js +2 -0
  52. package/build/cjs/extensions/markdown/Deflist/DeflistSpecs/schema.js.map +1 -1
  53. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/const.d.ts +4 -0
  54. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/const.js +9 -0
  55. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/const.js.map +1 -0
  56. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/index.d.ts +3 -5
  57. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/index.js +22 -25
  58. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/index.js.map +1 -1
  59. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/utils.d.ts +7 -0
  60. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/utils.js +15 -0
  61. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/utils.js.map +1 -0
  62. package/build/cjs/extensions/markdown/Heading/actions.d.ts +2 -2
  63. package/build/cjs/extensions/markdown/Heading/actions.js +3 -4
  64. package/build/cjs/extensions/markdown/Heading/actions.js.map +1 -1
  65. package/build/cjs/extensions/markdown/Heading/commands.d.ts +3 -1
  66. package/build/cjs/extensions/markdown/Heading/commands.js +16 -1
  67. package/build/cjs/extensions/markdown/Heading/commands.js.map +1 -1
  68. package/build/cjs/extensions/markdown/Heading/index.js +7 -9
  69. package/build/cjs/extensions/markdown/Heading/index.js.map +1 -1
  70. package/build/cjs/extensions/markdown/Lists/index.js +1 -0
  71. package/build/cjs/extensions/markdown/Lists/index.js.map +1 -1
  72. package/build/cjs/extensions/markdown/Lists/plugins/CollapseListsPlugin.d.ts +14 -2
  73. package/build/cjs/extensions/markdown/Lists/plugins/CollapseListsPlugin.js +97 -51
  74. package/build/cjs/extensions/markdown/Lists/plugins/CollapseListsPlugin.js.map +1 -1
  75. package/build/cjs/extensions/markdown/Table/TableSpecs/schema.js +1 -0
  76. package/build/cjs/extensions/markdown/Table/TableSpecs/schema.js.map +1 -1
  77. package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +2 -0
  78. package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js.map +1 -1
  79. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.d.ts +1 -1
  80. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js +2 -2
  81. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js.map +1 -1
  82. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.d.ts +3 -7
  83. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js +72 -90
  84. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js.map +1 -1
  85. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.d.ts +3 -0
  86. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js +14 -1
  87. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js.map +1 -1
  88. package/build/cjs/extensions/yfm/YfmHeading/actions.js +2 -10
  89. package/build/cjs/extensions/yfm/YfmHeading/actions.js.map +1 -1
  90. package/build/cjs/extensions/yfm/YfmHeading/commands.d.ts +1 -4
  91. package/build/cjs/extensions/yfm/YfmHeading/commands.js +3 -21
  92. package/build/cjs/extensions/yfm/YfmHeading/commands.js.map +1 -1
  93. package/build/cjs/extensions/yfm/YfmHeading/index.d.ts +3 -22
  94. package/build/cjs/extensions/yfm/YfmHeading/index.js +2 -33
  95. package/build/cjs/extensions/yfm/YfmHeading/index.js.map +1 -1
  96. package/build/cjs/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js +2 -0
  97. package/build/cjs/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js.map +1 -1
  98. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.css +20 -0
  99. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.d.ts +9 -0
  100. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js +77 -0
  101. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js.map +1 -0
  102. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.d.ts +1 -2
  103. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js +5 -65
  104. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js.map +1 -1
  105. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +2 -0
  106. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js.map +1 -1
  107. package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +3 -0
  108. package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js.map +1 -1
  109. package/build/cjs/plugins/BaseTooltip/index.d.ts +1 -0
  110. package/build/cjs/plugins/BaseTooltip/index.js +4 -3
  111. package/build/cjs/plugins/BaseTooltip/index.js.map +1 -1
  112. package/build/cjs/presets/yfm-specs.js +5 -1
  113. package/build/cjs/presets/yfm-specs.js.map +1 -1
  114. package/build/cjs/presets/yfm.js +5 -1
  115. package/build/cjs/presets/yfm.js.map +1 -1
  116. package/build/cjs/toolbar/ToolbarGroup.js +4 -3
  117. package/build/cjs/toolbar/ToolbarGroup.js.map +1 -1
  118. package/build/cjs/toolbar/types.d.ts +2 -0
  119. package/build/cjs/toolbar/types.js.map +1 -1
  120. package/build/cjs/version.js +1 -1
  121. package/build/cjs/version.js.map +1 -1
  122. package/build/esm/core/ExtensionBuilder.d.ts +21 -0
  123. package/build/esm/core/ExtensionBuilder.js +306 -4
  124. package/build/esm/core/ExtensionBuilder.js.map +1 -1
  125. package/build/esm/core/markdown/MarkdownSerializer.d.ts +4 -1
  126. package/build/esm/core/markdown/MarkdownSerializer.js +86 -23
  127. package/build/esm/core/markdown/MarkdownSerializer.js.map +1 -1
  128. package/build/esm/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js +1 -0
  129. package/build/esm/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js.map +1 -1
  130. package/build/esm/extensions/behavior/Clipboard/clipboard.js +1 -12
  131. package/build/esm/extensions/behavior/Clipboard/clipboard.js.map +1 -1
  132. package/build/esm/extensions/behavior/Clipboard/selection-content.d.ts +1 -0
  133. package/build/esm/extensions/behavior/Clipboard/selection-content.js +32 -0
  134. package/build/esm/extensions/behavior/Clipboard/selection-content.js.map +1 -0
  135. package/build/esm/extensions/behavior/Selection/commands.d.ts +2 -1
  136. package/build/esm/extensions/behavior/Selection/commands.js +47 -2
  137. package/build/esm/extensions/behavior/Selection/commands.js.map +1 -1
  138. package/build/esm/extensions/behavior/Selection/selection.d.ts +15 -0
  139. package/build/esm/extensions/behavior/Selection/selection.js +2 -1
  140. package/build/esm/extensions/behavior/Selection/selection.js.map +1 -1
  141. package/build/esm/extensions/behavior/SelectionContext/TextSelectionTooltip.d.ts +13 -0
  142. package/build/esm/extensions/behavior/SelectionContext/TextSelectionTooltip.js +38 -0
  143. package/build/esm/extensions/behavior/SelectionContext/TextSelectionTooltip.js.map +1 -0
  144. package/build/esm/extensions/behavior/SelectionContext/index.js +10 -7
  145. package/build/esm/extensions/behavior/SelectionContext/index.js.map +1 -1
  146. package/build/esm/extensions/behavior/SelectionContext/tooltip.d.ts +11 -15
  147. package/build/esm/extensions/behavior/SelectionContext/tooltip.js +24 -56
  148. package/build/esm/extensions/behavior/SelectionContext/tooltip.js.map +1 -1
  149. package/build/esm/extensions/behavior/SelectionContext/types.d.ts +10 -0
  150. package/build/esm/extensions/behavior/SelectionContext/types.js +2 -0
  151. package/build/esm/extensions/behavior/SelectionContext/types.js.map +1 -0
  152. package/build/esm/extensions/markdown/Blockquote/BlockquoteSpecs/index.js +1 -0
  153. package/build/esm/extensions/markdown/Blockquote/BlockquoteSpecs/index.js.map +1 -1
  154. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.d.ts +2 -2
  155. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js +17 -75
  156. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js.map +1 -1
  157. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.d.ts +14 -0
  158. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js +114 -0
  159. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js.map +1 -0
  160. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.d.ts +9 -0
  161. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js +19 -0
  162. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js.map +1 -0
  163. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.d.ts +2 -3
  164. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js +6 -94
  165. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js.map +1 -1
  166. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.d.ts +23 -0
  167. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js +83 -0
  168. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js.map +1 -0
  169. package/build/esm/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js +24 -34
  170. package/build/esm/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js.map +1 -1
  171. package/build/esm/extensions/markdown/Deflist/DeflistSpecs/schema.js +2 -0
  172. package/build/esm/extensions/markdown/Deflist/DeflistSpecs/schema.js.map +1 -1
  173. package/build/esm/extensions/markdown/Heading/HeadingSpecs/const.d.ts +4 -0
  174. package/build/esm/extensions/markdown/Heading/HeadingSpecs/const.js +6 -0
  175. package/build/esm/extensions/markdown/Heading/HeadingSpecs/const.js.map +1 -0
  176. package/build/esm/extensions/markdown/Heading/HeadingSpecs/index.d.ts +3 -5
  177. package/build/esm/extensions/markdown/Heading/HeadingSpecs/index.js +5 -10
  178. package/build/esm/extensions/markdown/Heading/HeadingSpecs/index.js.map +1 -1
  179. package/build/esm/extensions/markdown/Heading/HeadingSpecs/utils.d.ts +7 -0
  180. package/build/esm/extensions/markdown/Heading/HeadingSpecs/utils.js +12 -0
  181. package/build/esm/extensions/markdown/Heading/HeadingSpecs/utils.js.map +1 -0
  182. package/build/esm/extensions/markdown/Heading/actions.d.ts +2 -2
  183. package/build/esm/extensions/markdown/Heading/actions.js +3 -4
  184. package/build/esm/extensions/markdown/Heading/actions.js.map +1 -1
  185. package/build/esm/extensions/markdown/Heading/commands.d.ts +3 -1
  186. package/build/esm/extensions/markdown/Heading/commands.js +15 -1
  187. package/build/esm/extensions/markdown/Heading/commands.js.map +1 -1
  188. package/build/esm/extensions/markdown/Heading/index.js +9 -11
  189. package/build/esm/extensions/markdown/Heading/index.js.map +1 -1
  190. package/build/esm/extensions/markdown/Lists/index.js +1 -0
  191. package/build/esm/extensions/markdown/Lists/index.js.map +1 -1
  192. package/build/esm/extensions/markdown/Lists/plugins/CollapseListsPlugin.d.ts +14 -2
  193. package/build/esm/extensions/markdown/Lists/plugins/CollapseListsPlugin.js +95 -49
  194. package/build/esm/extensions/markdown/Lists/plugins/CollapseListsPlugin.js.map +1 -1
  195. package/build/esm/extensions/markdown/Table/TableSpecs/schema.js +1 -0
  196. package/build/esm/extensions/markdown/Table/TableSpecs/schema.js.map +1 -1
  197. package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +2 -0
  198. package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js.map +1 -1
  199. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.d.ts +1 -1
  200. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js +3 -3
  201. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js.map +1 -1
  202. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.d.ts +3 -7
  203. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js +70 -90
  204. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js.map +1 -1
  205. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.d.ts +3 -0
  206. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js +11 -0
  207. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js.map +1 -1
  208. package/build/esm/extensions/yfm/YfmHeading/actions.js +2 -10
  209. package/build/esm/extensions/yfm/YfmHeading/actions.js.map +1 -1
  210. package/build/esm/extensions/yfm/YfmHeading/commands.d.ts +1 -4
  211. package/build/esm/extensions/yfm/YfmHeading/commands.js +3 -21
  212. package/build/esm/extensions/yfm/YfmHeading/commands.js.map +1 -1
  213. package/build/esm/extensions/yfm/YfmHeading/index.d.ts +3 -22
  214. package/build/esm/extensions/yfm/YfmHeading/index.js +0 -31
  215. package/build/esm/extensions/yfm/YfmHeading/index.js.map +1 -1
  216. package/build/esm/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js +2 -0
  217. package/build/esm/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js.map +1 -1
  218. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.css +20 -0
  219. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.d.ts +9 -0
  220. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js +74 -0
  221. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js.map +1 -0
  222. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.d.ts +1 -2
  223. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js +4 -64
  224. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js.map +1 -1
  225. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +2 -0
  226. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js.map +1 -1
  227. package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +3 -0
  228. package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js.map +1 -1
  229. package/build/esm/plugins/BaseTooltip/index.d.ts +1 -0
  230. package/build/esm/plugins/BaseTooltip/index.js +4 -3
  231. package/build/esm/plugins/BaseTooltip/index.js.map +1 -1
  232. package/build/esm/presets/yfm-specs.js +5 -1
  233. package/build/esm/presets/yfm-specs.js.map +1 -1
  234. package/build/esm/presets/yfm.js +5 -1
  235. package/build/esm/presets/yfm.js.map +1 -1
  236. package/build/esm/toolbar/ToolbarGroup.js +4 -3
  237. package/build/esm/toolbar/ToolbarGroup.js.map +1 -1
  238. package/build/esm/toolbar/types.d.ts +2 -0
  239. package/build/esm/toolbar/types.js.map +1 -1
  240. package/build/esm/version.js +1 -1
  241. package/build/esm/version.js.map +1 -1
  242. package/build/styles.css +9 -5
  243. package/package.json +5 -4
  244. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.css +0 -16
  245. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.css +0 -16
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSelectionContent = getSelectionContent;
4
+ /**
5
+ * @internal
6
+ *
7
+ * Like `selection.content()`, but smarter.
8
+ * Copy a structure of complex nodes,
9
+ * e.g. if select part of cut title it creates slice with yfm-cut –> yfm-cut-title -> selected text
10
+ * it works well with simple nodes, but to handle cases as described above, custom logic needed
11
+ */
12
+ function getSelectionContent(sel) {
13
+ const sharedDepth = sel.$from.sharedDepth(sel.$to.pos);
14
+ const sharedNode = sel.$from.node(sharedDepth);
15
+ const sharedNodeComplex = sharedNode.type.spec.complex;
16
+ if (sharedNodeComplex && sharedNodeComplex !== 'leaf') {
17
+ // Find the nearest ancestor with complex='root' to avoid
18
+ // wrapping copied content in outer containers (blockquote, table cell, etc.)
19
+ let rootDepth = sharedDepth;
20
+ for (let d = sharedDepth; d >= 0; d--) {
21
+ if (sel.$from.node(d).type.spec.complex === 'root') {
22
+ rootDepth = d;
23
+ break;
24
+ }
25
+ }
26
+ // Slice from the parent of the root node so that the root node itself
27
+ // (e.g. bullet_list) is included in the slice, but its outer containers are not.
28
+ const parentDepth = Math.max(0, rootDepth - 1);
29
+ const parentNode = sel.$from.node(parentDepth);
30
+ const parentStart = sel.$from.start(parentDepth);
31
+ return parentNode.slice(sel.$from.pos - parentStart, sel.$to.pos - parentStart, true);
32
+ }
33
+ return sel.$from.doc.slice(sel.$from.pos, sel.to, false);
34
+ }
35
+ //# sourceMappingURL=selection-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-content.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Clipboard/selection-content.ts"],"names":[],"mappings":";;AAUA,kDAyBC;AAjCD;;;;;;;GAOG;AACH,SAAgB,mBAAmB,CAAC,GAAc;IAC9C,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAEvD,IAAI,iBAAiB,IAAI,iBAAiB,KAAK,MAAM,EAAE,CAAC;QACpD,yDAAyD;QACzD,6EAA6E;QAC7E,IAAI,SAAS,GAAG,WAAW,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;gBACjD,SAAS,GAAG,CAAC,CAAC;gBACd,MAAM;YACV,CAAC;QACL,CAAC;QAED,sEAAsE;QACtE,iFAAiF;QACjF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACjD,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,WAAW,EAAE,IAAI,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["import type {Selection} from '#pm/state';\n\n/**\n * @internal\n *\n * Like `selection.content()`, but smarter.\n * Copy a structure of complex nodes,\n * e.g. if select part of cut title it creates slice with yfm-cut –> yfm-cut-title -> selected text\n * it works well with simple nodes, but to handle cases as described above, custom logic needed\n */\nexport function getSelectionContent(sel: Selection) {\n const sharedDepth = sel.$from.sharedDepth(sel.$to.pos);\n const sharedNode = sel.$from.node(sharedDepth);\n const sharedNodeComplex = sharedNode.type.spec.complex;\n\n if (sharedNodeComplex && sharedNodeComplex !== 'leaf') {\n // Find the nearest ancestor with complex='root' to avoid\n // wrapping copied content in outer containers (blockquote, table cell, etc.)\n let rootDepth = sharedDepth;\n for (let d = sharedDepth; d >= 0; d--) {\n if (sel.$from.node(d).type.spec.complex === 'root') {\n rootDepth = d;\n break;\n }\n }\n\n // Slice from the parent of the root node so that the root node itself\n // (e.g. bullet_list) is included in the slice, but its outer containers are not.\n const parentDepth = Math.max(0, rootDepth - 1);\n const parentNode = sel.$from.node(parentDepth);\n const parentStart = sel.$from.start(parentDepth);\n return parentNode.slice(sel.$from.pos - parentStart, sel.$to.pos - parentStart, true);\n }\n\n return sel.$from.doc.slice(sel.$from.pos, sel.to, false);\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedPos } from 'prosemirror-model';
2
- import type { Command, NodeSelection, TextSelection, Transaction } from 'prosemirror-state';
2
+ import { type Command, type NodeSelection, TextSelection, type Transaction } from 'prosemirror-state';
3
3
  import { GapCursorSelection } from "../Cursor/GapCursorSelection.js";
4
4
  export type Direction = 'before' | 'after';
5
5
  type TextSelectionFinder = (selection: TextSelection, dir: Direction) => ResolvedPos | null;
@@ -16,4 +16,5 @@ export declare const arrowDown: Command;
16
16
  export declare const arrowUp: Command;
17
17
  export declare const arrowRight: Command;
18
18
  export declare const backspace: Command;
19
+ export declare const selectAll: Command;
19
20
  export {};
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.backspace = exports.arrowRight = exports.arrowUp = exports.arrowDown = exports.arrowLeft = exports.findFakeParaPosForTextSelection = exports.findFakeParaPosForCodeBlock = exports.findFakeParaPosForNodeSelection = exports.findNextFakeParaPosForGapCursorSelection = void 0;
3
+ exports.selectAll = exports.backspace = exports.arrowRight = exports.arrowUp = exports.arrowDown = exports.arrowLeft = exports.findFakeParaPosForTextSelection = exports.findFakeParaPosForCodeBlock = exports.findFakeParaPosForNodeSelection = exports.findNextFakeParaPosForGapCursorSelection = void 0;
4
4
  exports.findFakeParaPosClosestToPos = findFakeParaPosClosestToPos;
5
5
  exports.createFakeParagraph = createFakeParagraph;
6
6
  const prosemirror_state_1 = require("prosemirror-state");
7
7
  const nodes_1 = require("../../../utils/nodes.js");
8
8
  const selection_1 = require("../../../utils/selection.js");
9
9
  const GapCursorSelection_1 = require("../Cursor/GapCursorSelection.js");
10
+ const SelectionContext_1 = require("../SelectionContext/index.js");
10
11
  const isUp = (dir) => dir === 'left' || dir === 'up';
11
12
  function isTextblock(node) {
12
13
  return node.isTextblock && !(0, nodes_1.isCodeBlock)(node);
@@ -153,4 +154,49 @@ const backspace = (state, dispatch) => {
153
154
  return false;
154
155
  };
155
156
  exports.backspace = backspace;
157
+ function hasContentToSelect(node) {
158
+ if (node.isTextblock)
159
+ return node.content.size > 0;
160
+ return !(0, nodes_1.isNodeEmpty)(node);
161
+ }
162
+ const selectAll = (state, dispatch) => {
163
+ const { selection } = state;
164
+ const { $from, $to } = selection;
165
+ const sharedDepth = $from.sharedDepth($to.pos);
166
+ for (let depth = sharedDepth; depth > 0; depth--) {
167
+ const node = $from.node(depth);
168
+ const { spec } = node.type;
169
+ if (spec.selectAll === false)
170
+ continue;
171
+ let mode;
172
+ if (spec.selectAll)
173
+ mode = spec.selectAll;
174
+ else if (node.isTextblock || spec.code)
175
+ mode = 'content';
176
+ else
177
+ continue;
178
+ if (!hasContentToSelect(node))
179
+ continue;
180
+ if (mode === 'node') {
181
+ const selAroundNode = prosemirror_state_1.TextSelection.create(state.doc, $from.before(depth), $from.after(depth));
182
+ if (selection.from <= selAroundNode.from && selection.to >= selAroundNode.to)
183
+ continue;
184
+ dispatch?.((0, SelectionContext_1.hideSelectionMenu)(state.tr.setSelection(selAroundNode)));
185
+ return true;
186
+ }
187
+ const start = $from.start(depth);
188
+ const end = start + node.content.size;
189
+ const startCursor = prosemirror_state_1.Selection.findFrom(state.doc.resolve(start), 1);
190
+ const endCursor = prosemirror_state_1.Selection.findFrom(state.doc.resolve(end), -1);
191
+ if (startCursor &&
192
+ endCursor &&
193
+ selection.from <= startCursor.from &&
194
+ selection.to >= endCursor.to)
195
+ continue;
196
+ dispatch?.(state.tr.setSelection(prosemirror_state_1.TextSelection.create(state.doc, start, end)));
197
+ return true;
198
+ }
199
+ return false;
200
+ };
201
+ exports.selectAll = selectAll;
156
202
  //# sourceMappingURL=commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Selection/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Node, ResolvedPos} from 'prosemirror-model';\nimport type {Command, NodeSelection, TextSelection, Transaction} from 'prosemirror-state';\nimport {Selection} from 'prosemirror-state';\n\nimport {isCodeBlock} from '../../../utils/nodes';\nimport {isNodeSelection, isTextSelection} from '../../../utils/selection';\nimport {GapCursorSelection, isGapCursorSelection} from '../Cursor/GapCursorSelection';\n\nexport type Direction = 'before' | 'after';\ntype ArrowDirection = 'up' | 'right' | 'down' | 'left';\n\ntype TextSelectionFinder = (selection: TextSelection, dir: Direction) => ResolvedPos | null;\ntype NodeSelectionFinder = (selection: NodeSelection, dir: Direction) => ResolvedPos | null;\ntype GapCursorSelectionFinder = (\n selection: GapCursorSelection,\n dir: Direction,\n) => ResolvedPos | null;\n\ntype GapCursorMeta = {direction: Direction};\n\nconst isUp = (dir: ArrowDirection) => dir === 'left' || dir === 'up';\n\nfunction isTextblock(node: Node): boolean {\n return node.isTextblock && !isCodeBlock(node);\n}\n\nfunction isEdgeTextblock($cursor: ResolvedPos, dir: Direction): boolean {\n const index = $cursor.index($cursor.depth - 1);\n if (dir === 'before') return index === 0;\n if (dir === 'after') return index === $cursor.node($cursor.depth - 1).childCount - 1;\n return false;\n}\n\nexport const findNextFakeParaPosForGapCursorSelection: GapCursorSelectionFinder = ({$pos}, dir) => {\n if ($pos.pos !== $pos.start() && $pos.pos !== $pos.end()) return null;\n return findFakeParaPosClosestToPos($pos, $pos.depth, dir);\n};\n\nexport const findFakeParaPosForNodeSelection: NodeSelectionFinder = (selection, dir) => {\n const selectedNode = selection.node;\n if (selectedNode.isInline || isTextblock(selectedNode)) return null;\n\n const {$from} = selection;\n const index = $from.index();\n const parentNode = $from.parent;\n if (dir === 'before') {\n if (parentNode.firstChild === selectedNode || !isTextblock(parentNode.child(index - 1))) {\n return $from;\n }\n } else if (dir === 'after') {\n if (parentNode.lastChild === selectedNode || !isTextblock(parentNode.child(index + 1))) {\n return selection.$to;\n }\n }\n\n return null;\n};\n\nexport const findFakeParaPosForCodeBlock = ($cursor: ResolvedPos, dir: Direction) => {\n if (!isCodeBlock($cursor.parent)) return null;\n\n let foundPos = -1;\n const index = $cursor.index($cursor.depth - 1);\n const parent = $cursor.node($cursor.depth - 1);\n if (dir === 'before') {\n if (index === 0 || !isTextblock(parent.child(index - 1))) {\n foundPos = $cursor.before();\n }\n } else if (dir === 'after') {\n if (index === parent.childCount - 1 || !isTextblock(parent.child(index + 1))) {\n foundPos = $cursor.after();\n }\n }\n\n return foundPos !== -1 ? $cursor.doc.resolve(foundPos) : null;\n};\n\nexport const findFakeParaPosForTextSelection: TextSelectionFinder = (selection, dir) => {\n const $cursor = dir === 'before' ? selection.$from : selection.$to;\n if ($cursor.parent.isInline) return null;\n\n const $pos = findFakeParaPosForCodeBlock($cursor, dir);\n if ($pos) return $pos;\n\n if (!isEdgeTextblock($cursor, dir)) return null;\n\n return findFakeParaPosClosestToPos($cursor, $cursor.depth - 1, dir);\n};\n\nexport function findFakeParaPosClosestToPos(\n $pos: ResolvedPos,\n depth: number,\n dir: Direction,\n): ResolvedPos | null {\n depth++;\n while (--depth > 0) {\n const node = $pos.node(depth);\n const index = $pos.index(depth - 1);\n const parent = $pos.node(depth - 1);\n\n const isFirstChild = index === 0;\n const isLastChild = index === parent.childCount - 1;\n\n const isComplexChild =\n node.type.spec.complex === 'inner' || node.type.spec.complex === 'leaf';\n\n const disabledGapCursor = parent.type.spec.gapcursor === false;\n\n if (isComplexChild || disabledGapCursor) {\n if (dir === 'before' && isFirstChild) continue;\n if (dir === 'after' && isLastChild) continue;\n return null;\n }\n\n if (dir === 'before') {\n if (isFirstChild || !isTextblock(parent.child(index - 1))) {\n return $pos.doc.resolve($pos.before(depth));\n }\n } else if (dir === 'after') {\n if (isLastChild || !isTextblock(parent.child(index + 1))) {\n return $pos.doc.resolve($pos.after(depth));\n }\n }\n\n return null;\n }\n return null;\n}\n\nconst arrow =\n (dir: ArrowDirection): Command =>\n (state, dispatch, view) => {\n const {selection} = state;\n const direction: Direction = isUp(dir) ? 'before' : 'after';\n let $pos: ResolvedPos | null = null;\n\n if (isGapCursorSelection<GapCursorMeta>(selection)) {\n if (selection.meta?.direction !== direction) {\n return false;\n }\n\n // if gap selection is at start or end of doc\n if (dir === 'up' && selection.pos === 0) return true;\n if (dir === 'down' && selection.pos === state.doc.nodeSize - 2) return true;\n\n $pos = findNextFakeParaPosForGapCursorSelection(selection, direction);\n }\n\n if (isNodeSelection(selection)) {\n $pos = findFakeParaPosForNodeSelection(selection, direction);\n }\n\n if (isTextSelection(selection) && view?.endOfTextblock(dir)) {\n $pos = findFakeParaPosForTextSelection(selection, direction);\n }\n\n if ($pos) {\n dispatch?.(createFakeParagraph(state.tr, $pos, direction).scrollIntoView());\n return true;\n }\n\n return false;\n };\n\nexport function createFakeParagraph(\n tr: Transaction,\n $pos: ResolvedPos,\n direction: Direction,\n): Transaction {\n return tr.setSelection(new GapCursorSelection<GapCursorMeta>($pos, {meta: {direction}}));\n}\n\nexport const arrowLeft = arrow('left');\nexport const arrowDown = arrow('down');\nexport const arrowUp = arrow('up');\nexport const arrowRight = arrow('right');\n\nexport const backspace: Command = (state, dispatch) => {\n const sel = state.selection;\n if (isGapCursorSelection(sel)) {\n const newSel = Selection.findFrom(sel.$pos, -1);\n if (newSel) {\n dispatch?.(state.tr.setSelection(newSel).scrollIntoView());\n return true;\n }\n }\n return false;\n};\n"]}
1
+ {"version":3,"file":"commands.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Selection/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Node, ResolvedPos} from 'prosemirror-model';\nimport {\n type Command,\n type NodeSelection,\n Selection,\n TextSelection as TextSel,\n TextSelection,\n type Transaction,\n} from 'prosemirror-state';\n\nimport {isCodeBlock, isNodeEmpty} from '../../../utils/nodes';\nimport {isNodeSelection, isTextSelection} from '../../../utils/selection';\nimport {GapCursorSelection, isGapCursorSelection} from '../Cursor/GapCursorSelection';\nimport {hideSelectionMenu} from '../SelectionContext';\n\nexport type Direction = 'before' | 'after';\ntype ArrowDirection = 'up' | 'right' | 'down' | 'left';\n\ntype TextSelectionFinder = (selection: TextSelection, dir: Direction) => ResolvedPos | null;\ntype NodeSelectionFinder = (selection: NodeSelection, dir: Direction) => ResolvedPos | null;\ntype GapCursorSelectionFinder = (\n selection: GapCursorSelection,\n dir: Direction,\n) => ResolvedPos | null;\n\ntype GapCursorMeta = {direction: Direction};\n\nconst isUp = (dir: ArrowDirection) => dir === 'left' || dir === 'up';\n\nfunction isTextblock(node: Node): boolean {\n return node.isTextblock && !isCodeBlock(node);\n}\n\nfunction isEdgeTextblock($cursor: ResolvedPos, dir: Direction): boolean {\n const index = $cursor.index($cursor.depth - 1);\n if (dir === 'before') return index === 0;\n if (dir === 'after') return index === $cursor.node($cursor.depth - 1).childCount - 1;\n return false;\n}\n\nexport const findNextFakeParaPosForGapCursorSelection: GapCursorSelectionFinder = ({$pos}, dir) => {\n if ($pos.pos !== $pos.start() && $pos.pos !== $pos.end()) return null;\n return findFakeParaPosClosestToPos($pos, $pos.depth, dir);\n};\n\nexport const findFakeParaPosForNodeSelection: NodeSelectionFinder = (selection, dir) => {\n const selectedNode = selection.node;\n if (selectedNode.isInline || isTextblock(selectedNode)) return null;\n\n const {$from} = selection;\n const index = $from.index();\n const parentNode = $from.parent;\n if (dir === 'before') {\n if (parentNode.firstChild === selectedNode || !isTextblock(parentNode.child(index - 1))) {\n return $from;\n }\n } else if (dir === 'after') {\n if (parentNode.lastChild === selectedNode || !isTextblock(parentNode.child(index + 1))) {\n return selection.$to;\n }\n }\n\n return null;\n};\n\nexport const findFakeParaPosForCodeBlock = ($cursor: ResolvedPos, dir: Direction) => {\n if (!isCodeBlock($cursor.parent)) return null;\n\n let foundPos = -1;\n const index = $cursor.index($cursor.depth - 1);\n const parent = $cursor.node($cursor.depth - 1);\n if (dir === 'before') {\n if (index === 0 || !isTextblock(parent.child(index - 1))) {\n foundPos = $cursor.before();\n }\n } else if (dir === 'after') {\n if (index === parent.childCount - 1 || !isTextblock(parent.child(index + 1))) {\n foundPos = $cursor.after();\n }\n }\n\n return foundPos !== -1 ? $cursor.doc.resolve(foundPos) : null;\n};\n\nexport const findFakeParaPosForTextSelection: TextSelectionFinder = (selection, dir) => {\n const $cursor = dir === 'before' ? selection.$from : selection.$to;\n if ($cursor.parent.isInline) return null;\n\n const $pos = findFakeParaPosForCodeBlock($cursor, dir);\n if ($pos) return $pos;\n\n if (!isEdgeTextblock($cursor, dir)) return null;\n\n return findFakeParaPosClosestToPos($cursor, $cursor.depth - 1, dir);\n};\n\nexport function findFakeParaPosClosestToPos(\n $pos: ResolvedPos,\n depth: number,\n dir: Direction,\n): ResolvedPos | null {\n depth++;\n while (--depth > 0) {\n const node = $pos.node(depth);\n const index = $pos.index(depth - 1);\n const parent = $pos.node(depth - 1);\n\n const isFirstChild = index === 0;\n const isLastChild = index === parent.childCount - 1;\n\n const isComplexChild =\n node.type.spec.complex === 'inner' || node.type.spec.complex === 'leaf';\n\n const disabledGapCursor = parent.type.spec.gapcursor === false;\n\n if (isComplexChild || disabledGapCursor) {\n if (dir === 'before' && isFirstChild) continue;\n if (dir === 'after' && isLastChild) continue;\n return null;\n }\n\n if (dir === 'before') {\n if (isFirstChild || !isTextblock(parent.child(index - 1))) {\n return $pos.doc.resolve($pos.before(depth));\n }\n } else if (dir === 'after') {\n if (isLastChild || !isTextblock(parent.child(index + 1))) {\n return $pos.doc.resolve($pos.after(depth));\n }\n }\n\n return null;\n }\n return null;\n}\n\nconst arrow =\n (dir: ArrowDirection): Command =>\n (state, dispatch, view) => {\n const {selection} = state;\n const direction: Direction = isUp(dir) ? 'before' : 'after';\n let $pos: ResolvedPos | null = null;\n\n if (isGapCursorSelection<GapCursorMeta>(selection)) {\n if (selection.meta?.direction !== direction) {\n return false;\n }\n\n // if gap selection is at start or end of doc\n if (dir === 'up' && selection.pos === 0) return true;\n if (dir === 'down' && selection.pos === state.doc.nodeSize - 2) return true;\n\n $pos = findNextFakeParaPosForGapCursorSelection(selection, direction);\n }\n\n if (isNodeSelection(selection)) {\n $pos = findFakeParaPosForNodeSelection(selection, direction);\n }\n\n if (isTextSelection(selection) && view?.endOfTextblock(dir)) {\n $pos = findFakeParaPosForTextSelection(selection, direction);\n }\n\n if ($pos) {\n dispatch?.(createFakeParagraph(state.tr, $pos, direction).scrollIntoView());\n return true;\n }\n\n return false;\n };\n\nexport function createFakeParagraph(\n tr: Transaction,\n $pos: ResolvedPos,\n direction: Direction,\n): Transaction {\n return tr.setSelection(new GapCursorSelection<GapCursorMeta>($pos, {meta: {direction}}));\n}\n\nexport const arrowLeft = arrow('left');\nexport const arrowDown = arrow('down');\nexport const arrowUp = arrow('up');\nexport const arrowRight = arrow('right');\n\nexport const backspace: Command = (state, dispatch) => {\n const sel = state.selection;\n if (isGapCursorSelection(sel)) {\n const newSel = Selection.findFrom(sel.$pos, -1);\n if (newSel) {\n dispatch?.(state.tr.setSelection(newSel).scrollIntoView());\n return true;\n }\n }\n return false;\n};\n\nfunction hasContentToSelect(node: Node): boolean {\n if (node.isTextblock) return node.content.size > 0;\n return !isNodeEmpty(node);\n}\n\nexport const selectAll: Command = (state, dispatch) => {\n const {selection} = state;\n const {$from, $to} = selection;\n const sharedDepth = $from.sharedDepth($to.pos);\n\n for (let depth = sharedDepth; depth > 0; depth--) {\n const node = $from.node(depth);\n const {spec} = node.type;\n\n if (spec.selectAll === false) continue;\n\n let mode: 'content' | 'node';\n if (spec.selectAll) mode = spec.selectAll;\n else if (node.isTextblock || spec.code) mode = 'content';\n else continue;\n\n if (!hasContentToSelect(node)) continue;\n\n if (mode === 'node') {\n const selAroundNode = TextSelection.create(\n state.doc,\n $from.before(depth),\n $from.after(depth),\n );\n\n if (selection.from <= selAroundNode.from && selection.to >= selAroundNode.to) continue;\n\n dispatch?.(hideSelectionMenu(state.tr.setSelection(selAroundNode)));\n return true;\n }\n\n const start = $from.start(depth);\n const end = start + node.content.size;\n\n const startCursor = Selection.findFrom(state.doc.resolve(start), 1);\n const endCursor = Selection.findFrom(state.doc.resolve(end), -1);\n\n if (\n startCursor &&\n endCursor &&\n selection.from <= startCursor.from &&\n selection.to >= endCursor.to\n )\n continue;\n\n dispatch?.(state.tr.setSelection(TextSel.create(state.doc, start, end)));\n return true;\n }\n\n return false;\n};\n"]}
@@ -3,6 +3,21 @@ import "./selection.css";
3
3
  export declare const selection: () => Plugin<any>;
4
4
  declare module 'prosemirror-model' {
5
5
  interface NodeSpec {
6
+ /**
7
+ * Whether clicking directly on this node creates a NodeSelection for it.
8
+ * Typically `true` for root complex nodes (tables, cuts, notes)
9
+ * and `false` for their inner parts and leaf elements.
10
+ */
6
11
  allowSelection?: boolean | undefined;
12
+ /**
13
+ * Controls how this node participates in hierarchical select-all (Cmd+A / Ctrl+A).
14
+ * Each press of select-all walks up the node tree and selects the nearest matching ancestor.
15
+ *
16
+ * - `'content'` — select the node's content (TextSelection over inner content range)
17
+ * - `'node'` — select the node itself (NodeSelection)
18
+ * - `false` — skip this node during select-all traversal
19
+ * - `undefined` — default: textblocks and code nodes select their content, others are skipped
20
+ */
21
+ selectAll?: false | 'node' | 'content' | undefined;
7
22
  }
8
23
  }
@@ -17,6 +17,7 @@ const selection = () => new prosemirror_state_1.Plugin({
17
17
  ArrowUp: commands_1.arrowUp,
18
18
  ArrowDown: commands_1.arrowDown,
19
19
  Backspace: commands_1.backspace,
20
+ 'Mod-a': commands_1.selectAll,
20
21
  }),
21
22
  decorations(state) {
22
23
  return getDecorations(state.tr);
@@ -1 +1 @@
1
- {"version":3,"file":"selection.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Selection/selection.ts"],"names":[],"mappings":"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","sourcesContent":["import {selectParentNode} from 'prosemirror-commands';\nimport {keydownHandler} from 'prosemirror-keymap';\nimport type {Node} from 'prosemirror-model';\nimport {\n AllSelection,\n type Command,\n NodeSelection,\n Plugin,\n type Selection,\n TextSelection,\n type Transaction,\n} from 'prosemirror-state';\nimport {Decoration, DecorationSet, type EditorView} from 'prosemirror-view';\n\nimport {isSelectableNode} from '../../../utils/nodes';\nimport {isNodeSelection} from '../../../utils/selection';\n\nimport {arrowDown, arrowLeft, arrowRight, arrowUp, backspace} from './commands';\n\nimport './selection.scss';\n\nexport const selection = () =>\n new Plugin({\n props: {\n handleKeyDown: keydownHandler({\n ArrowLeft: arrowLeft,\n ArrowRight: arrowRight,\n ArrowUp: arrowUp,\n ArrowDown: arrowDown,\n Backspace: backspace,\n }),\n decorations(state) {\n return getDecorations(state.tr);\n },\n handleClickOn(view, _pos, node, nodePos, _event, direct) {\n if (direct && node.type.spec.allowSelection) {\n return selectNode(nodePos)(view.state, view.dispatch);\n }\n\n return false;\n },\n },\n view(view) {\n reselect(view);\n return {\n update(view) {\n reselect(view);\n },\n };\n },\n });\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n allowSelection?: boolean | undefined;\n }\n}\n\nconst reselect = (view: EditorView) => {\n const {selection: sel} = view.state;\n if (!sel.empty && isNodeSelection(sel) && !isSelectableNode(sel.node)) {\n return selectParentNode(view.state, view.dispatch);\n }\n return false;\n};\n\nconst selectNode =\n (pos: number): Command =>\n (state, dispatch) => {\n if (dispatch) {\n dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(pos))));\n }\n return true;\n };\n\nconst getDecorations = (tr: Transaction): DecorationSet => {\n if (tr.selection instanceof NodeSelection) {\n return DecorationSet.create(tr.doc, [\n Decoration.node(tr.selection.from, tr.selection.to, {\n class: 'pm-node-selected',\n }),\n ]);\n }\n\n if (tr.selection instanceof TextSelection || tr.selection instanceof AllSelection) {\n const decorations = getTopLevelNodesFromSelection(tr.selection, tr.doc).map(\n ({node, pos}) => {\n return Decoration.node(pos, pos + node.nodeSize, {\n class: 'pm-node-selected',\n });\n },\n );\n return DecorationSet.create(tr.doc, decorations);\n }\n return DecorationSet.empty;\n};\n\nconst getTopLevelNodesFromSelection = (selection: Selection, doc: Node) => {\n const nodes: {node: Node; pos: number}[] = [];\n if (selection.from !== selection.to) {\n const {from, to} = selection;\n\n doc.nodesBetween(from, to, (node, pos) => {\n const withinSelection = from <= pos && pos + node.nodeSize <= to;\n\n if (node && !node.isText && node.type.spec.selectable !== false && withinSelection) {\n nodes.push({node, pos});\n\n return false;\n }\n\n return true;\n });\n }\n return nodes;\n};\n"]}
1
+ {"version":3,"file":"selection.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/Selection/selection.ts"],"names":[],"mappings":"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","sourcesContent":["import {selectParentNode} from 'prosemirror-commands';\nimport {keydownHandler} from 'prosemirror-keymap';\nimport type {Node} from 'prosemirror-model';\nimport {\n AllSelection,\n type Command,\n NodeSelection,\n Plugin,\n type Selection,\n TextSelection,\n type Transaction,\n} from 'prosemirror-state';\nimport {Decoration, DecorationSet, type EditorView} from 'prosemirror-view';\n\nimport {isSelectableNode} from '../../../utils/nodes';\nimport {isNodeSelection} from '../../../utils/selection';\n\nimport {arrowDown, arrowLeft, arrowRight, arrowUp, backspace, selectAll} from './commands';\n\nimport './selection.scss';\n\nexport const selection = () =>\n new Plugin({\n props: {\n handleKeyDown: keydownHandler({\n ArrowLeft: arrowLeft,\n ArrowRight: arrowRight,\n ArrowUp: arrowUp,\n ArrowDown: arrowDown,\n Backspace: backspace,\n 'Mod-a': selectAll,\n }),\n decorations(state) {\n return getDecorations(state.tr);\n },\n handleClickOn(view, _pos, node, nodePos, _event, direct) {\n if (direct && node.type.spec.allowSelection) {\n return selectNode(nodePos)(view.state, view.dispatch);\n }\n\n return false;\n },\n },\n view(view) {\n reselect(view);\n return {\n update(view) {\n reselect(view);\n },\n };\n },\n });\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n /**\n * Whether clicking directly on this node creates a NodeSelection for it.\n * Typically `true` for root complex nodes (tables, cuts, notes)\n * and `false` for their inner parts and leaf elements.\n */\n allowSelection?: boolean | undefined;\n /**\n * Controls how this node participates in hierarchical select-all (Cmd+A / Ctrl+A).\n * Each press of select-all walks up the node tree and selects the nearest matching ancestor.\n *\n * - `'content'` — select the node's content (TextSelection over inner content range)\n * - `'node'` — select the node itself (NodeSelection)\n * - `false` — skip this node during select-all traversal\n * - `undefined` — default: textblocks and code nodes select their content, others are skipped\n */\n selectAll?: false | 'node' | 'content' | undefined;\n }\n}\n\nconst reselect = (view: EditorView) => {\n const {selection: sel} = view.state;\n if (!sel.empty && isNodeSelection(sel) && !isSelectableNode(sel.node)) {\n return selectParentNode(view.state, view.dispatch);\n }\n return false;\n};\n\nconst selectNode =\n (pos: number): Command =>\n (state, dispatch) => {\n if (dispatch) {\n dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(pos))));\n }\n return true;\n };\n\nconst getDecorations = (tr: Transaction): DecorationSet => {\n if (tr.selection instanceof NodeSelection) {\n return DecorationSet.create(tr.doc, [\n Decoration.node(tr.selection.from, tr.selection.to, {\n class: 'pm-node-selected',\n }),\n ]);\n }\n\n if (tr.selection instanceof TextSelection || tr.selection instanceof AllSelection) {\n const decorations = getTopLevelNodesFromSelection(tr.selection, tr.doc).map(\n ({node, pos}) => {\n return Decoration.node(pos, pos + node.nodeSize, {\n class: 'pm-node-selected',\n });\n },\n );\n return DecorationSet.create(tr.doc, decorations);\n }\n return DecorationSet.empty;\n};\n\nconst getTopLevelNodesFromSelection = (selection: Selection, doc: Node) => {\n const nodes: {node: Node; pos: number}[] = [];\n if (selection.from !== selection.to) {\n const {from, to} = selection;\n\n doc.nodesBetween(from, to, (node, pos) => {\n const withinSelection = from <= pos && pos + node.nodeSize <= to;\n\n if (node && !node.isText && node.type.spec.selectable !== false && withinSelection) {\n nodes.push({node, pos});\n\n return false;\n }\n\n return true;\n });\n }\n return nodes;\n};\n"]}
@@ -0,0 +1,13 @@
1
+ import { type PopupPlacement, type PopupProps } from '@gravity-ui/uikit';
2
+ import type { ActionStorage } from "../../../core/index.js";
3
+ import type { EditorView } from "../../../pm/view.js";
4
+ import { type ToolbarProps } from "../../../toolbar/index.js";
5
+ import type { ContextConfig } from "./types.js";
6
+ export type TextSelectionTooltipProps = Pick<ToolbarProps<ActionStorage>, 'onClick' | 'editor' | 'focus'> & {
7
+ config: ContextConfig;
8
+ editorView: EditorView;
9
+ popupPlacement: PopupPlacement;
10
+ popupAnchor: PopupProps['anchorElement'];
11
+ popupOnOpenChange: PopupProps['onOpenChange'];
12
+ };
13
+ export declare const TextSelectionTooltip: React.FC<TextSelectionTooltipProps>;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TextSelectionTooltip = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const uikit_1 = require("@gravity-ui/uikit");
7
+ const lodash_1 = require("../../../lodash.js");
8
+ const memo_1 = require("../../../react-utils/memo.js");
9
+ const toolbar_1 = require("../../../toolbar/index.js");
10
+ const ToolbarRerender_1 = require("../../../toolbar/ToolbarRerender.js");
11
+ const ToolbarMemoized = (0, memo_1.typedMemo)(toolbar_1.Toolbar);
12
+ const KEY_SEP = '|||';
13
+ const TextSelectionTooltip = function TextSelectionTooltip({ popupAnchor, popupPlacement, popupOnOpenChange, config, focus, editor, onClick, editorView, }) {
14
+ const [conditionKey, setConditionKey] = (0, react_1.useState)(() => calcConditionKey(config, editor, editorView));
15
+ (0, react_1.useEffect)(() => {
16
+ const newKey = calcConditionKey(config, editor, editorView);
17
+ if (conditionKey !== newKey)
18
+ setConditionKey(newKey);
19
+ });
20
+ const toolbarData = (0, react_1.useMemo)(() => {
21
+ const results = conditionKey.split(KEY_SEP);
22
+ let idx = 0;
23
+ return config
24
+ .map((groupData) => groupData.filter(() => results[idx++] === 'true'))
25
+ .filter((groupData) => Boolean(groupData.length));
26
+ }, [config, conditionKey]);
27
+ return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: true, className: (0, uikit_1.sp)({ p: '0.5' }), placement: popupPlacement, anchorElement: popupAnchor, onOpenChange: popupOnOpenChange, children: (0, jsx_runtime_1.jsx)(ToolbarRerender_1.ToolbarWrapToContext, { editor: editor, children: (0, jsx_runtime_1.jsx)(ToolbarMemoized, { focus: focus, editor: editor, onClick: onClick, data: toolbarData, qa: "g-md-toolbar-selection" }) }) }));
28
+ };
29
+ exports.TextSelectionTooltip = TextSelectionTooltip;
30
+ function calcConditionKey(config, editor, editorView) {
31
+ return config
32
+ .flatMap((groupData) => groupData.map((item) => {
33
+ const { condition } = item;
34
+ if (condition === 'enabled')
35
+ return item.isEnable(editor);
36
+ if ((0, lodash_1.isFunction)(condition))
37
+ return condition(editorView.state);
38
+ return true;
39
+ }))
40
+ .join(KEY_SEP);
41
+ }
42
+ //# sourceMappingURL=TextSelectionTooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextSelectionTooltip.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/SelectionContext/TextSelectionTooltip.tsx"],"names":[],"mappings":";;;;AAAA,iCAAmD;AAEnD,6CAAkF;AAIlF,+CAAsC;AACtC,uDAA+C;AAC/C,uDAAyE;AACzE,yEAAiE;AAIjE,MAAM,eAAe,GAAG,IAAA,gBAAS,EAAC,iBAAO,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,KAAK,CAAC;AAaf,MAAM,oBAAoB,GAC7B,SAAS,oBAAoB,CAAC,EAC1B,WAAW,EACX,cAAc,EACd,iBAAiB,EAEjB,MAAM,EACN,KAAK,EACL,MAAM,EACN,OAAO,EACP,UAAU,GACb;IACG,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAC,GAAG,EAAE,CAClD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAC/C,CAAC;IAEF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACX,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;QAC5D,IAAI,YAAY,KAAK,MAAM;YAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,IAAA,eAAO,EAA6B,GAAG,EAAE;QACzD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,OAAO,MAAM;aACR,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC;aACrE,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3B,OAAO,CACH,uBAAC,aAAK,IACF,IAAI,QACJ,SAAS,EAAE,IAAA,UAAE,EAAC,EAAC,CAAC,EAAE,KAAK,EAAC,CAAC,EACzB,SAAS,EAAE,cAAc,EACzB,aAAa,EAAE,WAAW,EAC1B,YAAY,EAAE,iBAAiB,YAE/B,uBAAC,sCAAoB,IAAC,MAAM,EAAE,MAAM,YAChC,uBAAC,eAAe,IACZ,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,EAAE,EAAC,wBAAwB,GAC7B,GACiB,GACnB,CACX,CAAC;AACN,CAAC,CAAC;AAhDO,QAAA,oBAAoB,wBAgD3B;AAEN,SAAS,gBAAgB,CACrB,MAAqB,EACrB,MAAqB,EACrB,UAAsB;IAEtB,OAAO,MAAM;SACR,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CACnB,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACnB,MAAM,EAAC,SAAS,EAAC,GAAG,IAAI,CAAC;QACzB,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,IAAA,mBAAU,EAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC,CACL;SACA,IAAI,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC","sourcesContent":["import {useEffect, useMemo, useState} from 'react';\n\nimport {Popup, type PopupPlacement, type PopupProps, sp} from '@gravity-ui/uikit';\n\nimport type {ActionStorage} from '#core';\nimport type {EditorView} from '#pm/view';\nimport {isFunction} from 'src/lodash';\nimport {typedMemo} from 'src/react-utils/memo';\nimport {Toolbar, type ToolbarData, type ToolbarProps} from 'src/toolbar';\nimport {ToolbarWrapToContext} from 'src/toolbar/ToolbarRerender';\n\nimport type {ContextConfig} from './types';\n\nconst ToolbarMemoized = typedMemo(Toolbar);\nconst KEY_SEP = '|||';\n\nexport type TextSelectionTooltipProps = Pick<\n ToolbarProps<ActionStorage>,\n 'onClick' | 'editor' | 'focus'\n> & {\n config: ContextConfig;\n editorView: EditorView;\n popupPlacement: PopupPlacement;\n popupAnchor: PopupProps['anchorElement'];\n popupOnOpenChange: PopupProps['onOpenChange'];\n};\n\nexport const TextSelectionTooltip: React.FC<TextSelectionTooltipProps> =\n function TextSelectionTooltip({\n popupAnchor,\n popupPlacement,\n popupOnOpenChange,\n\n config,\n focus,\n editor,\n onClick,\n editorView,\n }) {\n const [conditionKey, setConditionKey] = useState(() =>\n calcConditionKey(config, editor, editorView),\n );\n\n useEffect(() => {\n const newKey = calcConditionKey(config, editor, editorView);\n if (conditionKey !== newKey) setConditionKey(newKey);\n });\n\n const toolbarData = useMemo<ToolbarData<ActionStorage>>(() => {\n const results = conditionKey.split(KEY_SEP);\n let idx = 0;\n return config\n .map((groupData) => groupData.filter(() => results[idx++] === 'true'))\n .filter((groupData) => Boolean(groupData.length));\n }, [config, conditionKey]);\n\n return (\n <Popup\n open\n className={sp({p: '0.5'})}\n placement={popupPlacement}\n anchorElement={popupAnchor}\n onOpenChange={popupOnOpenChange}\n >\n <ToolbarWrapToContext editor={editor}>\n <ToolbarMemoized\n focus={focus}\n editor={editor}\n onClick={onClick}\n data={toolbarData}\n qa=\"g-md-toolbar-selection\"\n />\n </ToolbarWrapToContext>\n </Popup>\n );\n };\n\nfunction calcConditionKey(\n config: ContextConfig,\n editor: ActionStorage,\n editorView: EditorView,\n): string {\n return config\n .flatMap((groupData) =>\n groupData.map((item) => {\n const {condition} = item;\n if (condition === 'enabled') return item.isEnable(editor);\n if (isFunction(condition)) return condition(editorView.state);\n return true;\n }),\n )\n .join(KEY_SEP);\n}\n"]}
@@ -23,10 +23,17 @@ const pluginKey = new prosemirror_state_1.PluginKey('selection-context');
23
23
  class SelectionTooltip {
24
24
  destroyed = false;
25
25
  tooltip;
26
+ editorView = null;
26
27
  hideTimeoutRef = null;
27
28
  _isMousePressed = false;
28
29
  constructor(actions, menuConfig, logger, options) {
29
- this.tooltip = new tooltip_1.TooltipView(actions, menuConfig, logger, options);
30
+ this.tooltip = new tooltip_1.TooltipView(actions, menuConfig, logger, {
31
+ ...options,
32
+ onPopupOpenChange: (_open, _event, reason) => {
33
+ if (reason !== 'escape-key' && this.editorView)
34
+ this.scheduleTooltipHiding(this.editorView);
35
+ },
36
+ });
30
37
  }
31
38
  get key() {
32
39
  return pluginKey;
@@ -84,6 +91,7 @@ class SelectionTooltip {
84
91
  };
85
92
  }
86
93
  update(view, prevState) {
94
+ this.editorView = view;
87
95
  if (this._isMousePressed)
88
96
  return;
89
97
  this.cancelTooltipHiding();
@@ -119,12 +127,7 @@ class SelectionTooltip {
119
127
  this.tooltip.hide(view);
120
128
  return;
121
129
  }
122
- this.tooltip.show(view, {
123
- onOpenChange: (_open, _event, reason) => {
124
- if (reason !== 'escape-key')
125
- this.scheduleTooltipHiding(view);
126
- },
127
- });
130
+ this.tooltip.show(view);
128
131
  }
129
132
  scheduleTooltipHiding(view) {
130
133
  this.hideTimeoutRef = setTimeout(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/SelectionContext/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {keydownHandler} from 'prosemirror-keymap';\nimport type {Node} from 'prosemirror-model';\nimport {\n AllSelection,\n type EditorState,\n Plugin,\n PluginKey,\n type PluginSpec,\n type StateField,\n TextSelection,\n type Transaction,\n} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {hasParentNode} from 'prosemirror-utils';\nimport type {EditorProps, EditorView} from 'prosemirror-view';\n\nimport type {ActionStorage, ExtensionAuto} from '../../../core';\nimport type {Logger2} from '../../../logger';\nimport {isCodeBlock} from '../../../utils/nodes';\n\nimport {type ContextConfig, TooltipView} from './tooltip';\n\nexport type {\n ContextConfig as SelectionContextConfig,\n ContextGroupItemData as SelectionContextItemData,\n} from './tooltip';\n\nexport type SelectionContextOptions = {\n config?: ContextConfig;\n /**\n * Placement of context popup\n * @default 'bottom'\n */\n placement?: 'top' | 'bottom';\n /**\n * Prevents context popup from overflowing\n * @default false\n */\n flip?: boolean;\n};\n\nexport const SelectionContext: ExtensionAuto<SelectionContextOptions> = (builder, opts) => {\n const {config} = opts;\n if (Array.isArray(config) && config.length > 0) {\n builder.addPlugin(\n ({actions}) => new Plugin(new SelectionTooltip(actions, config, builder.logger, opts)),\n );\n }\n};\n\nconst HideMetaKey = 'hide-selection-menu';\n\nexport const hideSelectionMenu = (tr: Transaction) => {\n return tr.setMeta(HideMetaKey, true);\n};\n\nconst pluginKey = new PluginKey<PluginState>('selection-context');\n\ntype PluginState = {\n disabled: boolean;\n};\n\ntype TinyState = Pick<EditorState, 'doc' | 'selection'>;\n\nclass SelectionTooltip implements PluginSpec<PluginState> {\n private destroyed = false;\n\n private tooltip: TooltipView;\n private hideTimeoutRef: ReturnType<typeof setTimeout> | null = null;\n\n private _isMousePressed = false;\n\n constructor(\n actions: ActionStorage,\n menuConfig: ContextConfig,\n logger: Logger2.ILogger,\n options: SelectionContextOptions,\n ) {\n this.tooltip = new TooltipView(actions, menuConfig, logger, options);\n }\n\n get key(): PluginKey<PluginState> {\n return pluginKey;\n }\n\n get props(): EditorProps {\n return {\n // same as keymap({})\n handleKeyDown: keydownHandler({\n // hide context menu when Esc was pressed\n Escape: (_state, _dispatch, view) => {\n if (this.tooltip.isTooltipOpen) {\n this.tooltip.hide(view!);\n return true;\n }\n return false;\n },\n }),\n handleDOMEvents: {\n mousedown: (view) => {\n const startState: TinyState = {\n doc: view.state.doc,\n selection: view.state.selection,\n };\n this._isMousePressed = true;\n this.cancelTooltipHiding();\n this.tooltip.hide(view);\n\n const onMouseUp = () => {\n if (this.destroyed) return;\n this._isMousePressed = false;\n this.update(view, startState);\n };\n\n document.addEventListener('mouseup', onMouseUp, {once: true});\n },\n },\n };\n }\n\n get state(): StateField<PluginState> {\n return {\n init: () => ({disabled: false}),\n apply(tr) {\n return {disabled: Boolean(tr.getMeta(HideMetaKey))};\n },\n };\n }\n\n view(view: EditorView) {\n this.update(view);\n return {\n update: this.update.bind(this),\n destroy: () => {\n this.destroyed = true;\n this.cancelTooltipHiding();\n this.tooltip.destroy();\n },\n };\n }\n\n private update(view: EditorView, prevState?: TinyState) {\n if (this._isMousePressed) return;\n\n this.cancelTooltipHiding();\n\n const hideFromTr = pluginKey.getState(view.state)?.disabled;\n\n // Don't show tooltip if editor not mounted to the DOM\n if (hideFromTr || !view.dom.parentNode) {\n this.tooltip.hide(view);\n return;\n }\n\n const {state} = view;\n // Don't do anything if the document/selection didn't change\n if (prevState && prevState.doc.eq(state.doc) && prevState.selection.eq(state.selection)) {\n return;\n }\n\n // Don't show tooltip if editor out of focus\n if (!view.hasFocus()) {\n this.tooltip.hide(view);\n return;\n }\n\n const {selection} = state;\n // Hide the tooltip if the selection is empty\n if (\n selection.empty ||\n !(selection instanceof TextSelection || selection instanceof AllSelection)\n ) {\n this.tooltip.hide(view);\n return;\n }\n\n if (\n // Hide tooltip when one side of selection is inside a codeblock\n isCodeBlock(selection.$from.parent) ||\n isCodeBlock(selection.$to.parent) ||\n // or when selection is inside node where context menu is disabled\n hasParentNode((node: Node) => node.type.spec.selectionContext === false)(selection)\n ) {\n this.tooltip.hide(view);\n return;\n }\n\n this.tooltip.show(view, {\n onOpenChange: (_open, _event, reason) => {\n if (reason !== 'escape-key') this.scheduleTooltipHiding(view);\n },\n });\n }\n\n private scheduleTooltipHiding(view: EditorView) {\n this.hideTimeoutRef = setTimeout(() => {\n // hide tooltip if view is out of focus after 30 ms\n if (!view.hasFocus()) {\n this.tooltip.hide(view);\n }\n }, 30);\n }\n\n private cancelTooltipHiding() {\n if (this.hideTimeoutRef !== null) {\n clearTimeout(this.hideTimeoutRef);\n this.hideTimeoutRef = null;\n }\n }\n}\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n /** Set false to disable the selection-context menu within this node */\n selectionContext?: boolean | undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/behavior/SelectionContext/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {keydownHandler} from 'prosemirror-keymap';\nimport type {Node} from 'prosemirror-model';\nimport {\n AllSelection,\n type EditorState,\n Plugin,\n PluginKey,\n type PluginSpec,\n type StateField,\n TextSelection,\n type Transaction,\n} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {hasParentNode} from 'prosemirror-utils';\nimport type {EditorProps, EditorView} from 'prosemirror-view';\n\nimport type {ActionStorage, ExtensionAuto} from '../../../core';\nimport type {Logger2} from '../../../logger';\nimport {isCodeBlock} from '../../../utils/nodes';\n\nimport {type ContextConfig, TooltipView} from './tooltip';\n\nexport type {\n ContextConfig as SelectionContextConfig,\n ContextGroupItemData as SelectionContextItemData,\n} from './tooltip';\n\nexport type SelectionContextOptions = {\n config?: ContextConfig;\n /**\n * Placement of context popup\n * @default 'bottom'\n */\n placement?: 'top' | 'bottom';\n /**\n * Prevents context popup from overflowing\n * @default false\n */\n flip?: boolean;\n};\n\nexport const SelectionContext: ExtensionAuto<SelectionContextOptions> = (builder, opts) => {\n const {config} = opts;\n if (Array.isArray(config) && config.length > 0) {\n builder.addPlugin(\n ({actions}) => new Plugin(new SelectionTooltip(actions, config, builder.logger, opts)),\n );\n }\n};\n\nconst HideMetaKey = 'hide-selection-menu';\n\nexport const hideSelectionMenu = (tr: Transaction) => {\n return tr.setMeta(HideMetaKey, true);\n};\n\nconst pluginKey = new PluginKey<PluginState>('selection-context');\n\ntype PluginState = {\n disabled: boolean;\n};\n\ntype TinyState = Pick<EditorState, 'doc' | 'selection'>;\n\nclass SelectionTooltip implements PluginSpec<PluginState> {\n private destroyed = false;\n\n private tooltip: TooltipView;\n private editorView: EditorView | null = null;\n private hideTimeoutRef: ReturnType<typeof setTimeout> | null = null;\n\n private _isMousePressed = false;\n\n constructor(\n actions: ActionStorage,\n menuConfig: ContextConfig,\n logger: Logger2.ILogger,\n options: SelectionContextOptions,\n ) {\n this.tooltip = new TooltipView(actions, menuConfig, logger, {\n ...options,\n onPopupOpenChange: (_open, _event, reason) => {\n if (reason !== 'escape-key' && this.editorView)\n this.scheduleTooltipHiding(this.editorView);\n },\n });\n }\n\n get key(): PluginKey<PluginState> {\n return pluginKey;\n }\n\n get props(): EditorProps {\n return {\n // same as keymap({})\n handleKeyDown: keydownHandler({\n // hide context menu when Esc was pressed\n Escape: (_state, _dispatch, view) => {\n if (this.tooltip.isTooltipOpen) {\n this.tooltip.hide(view!);\n return true;\n }\n return false;\n },\n }),\n handleDOMEvents: {\n mousedown: (view) => {\n const startState: TinyState = {\n doc: view.state.doc,\n selection: view.state.selection,\n };\n this._isMousePressed = true;\n this.cancelTooltipHiding();\n this.tooltip.hide(view);\n\n const onMouseUp = () => {\n if (this.destroyed) return;\n this._isMousePressed = false;\n this.update(view, startState);\n };\n\n document.addEventListener('mouseup', onMouseUp, {once: true});\n },\n },\n };\n }\n\n get state(): StateField<PluginState> {\n return {\n init: () => ({disabled: false}),\n apply(tr) {\n return {disabled: Boolean(tr.getMeta(HideMetaKey))};\n },\n };\n }\n\n view(view: EditorView) {\n this.update(view);\n return {\n update: this.update.bind(this),\n destroy: () => {\n this.destroyed = true;\n this.cancelTooltipHiding();\n this.tooltip.destroy();\n },\n };\n }\n\n private update(view: EditorView, prevState?: TinyState) {\n this.editorView = view;\n\n if (this._isMousePressed) return;\n\n this.cancelTooltipHiding();\n\n const hideFromTr = pluginKey.getState(view.state)?.disabled;\n\n // Don't show tooltip if editor not mounted to the DOM\n if (hideFromTr || !view.dom.parentNode) {\n this.tooltip.hide(view);\n return;\n }\n\n const {state} = view;\n // Don't do anything if the document/selection didn't change\n if (prevState && prevState.doc.eq(state.doc) && prevState.selection.eq(state.selection)) {\n return;\n }\n\n // Don't show tooltip if editor out of focus\n if (!view.hasFocus()) {\n this.tooltip.hide(view);\n return;\n }\n\n const {selection} = state;\n // Hide the tooltip if the selection is empty\n if (\n selection.empty ||\n !(selection instanceof TextSelection || selection instanceof AllSelection)\n ) {\n this.tooltip.hide(view);\n return;\n }\n\n if (\n // Hide tooltip when one side of selection is inside a codeblock\n isCodeBlock(selection.$from.parent) ||\n isCodeBlock(selection.$to.parent) ||\n // or when selection is inside node where context menu is disabled\n hasParentNode((node: Node) => node.type.spec.selectionContext === false)(selection)\n ) {\n this.tooltip.hide(view);\n return;\n }\n\n this.tooltip.show(view);\n }\n\n private scheduleTooltipHiding(view: EditorView) {\n this.hideTimeoutRef = setTimeout(() => {\n // hide tooltip if view is out of focus after 30 ms\n if (!view.hasFocus()) {\n this.tooltip.hide(view);\n }\n }, 30);\n }\n\n private cancelTooltipHiding() {\n if (this.hideTimeoutRef !== null) {\n clearTimeout(this.hideTimeoutRef);\n this.hideTimeoutRef = null;\n }\n }\n}\n\ndeclare module 'prosemirror-model' {\n interface NodeSpec {\n /** Set false to disable the selection-context menu within this node */\n selectionContext?: boolean | undefined;\n }\n}\n"]}
@@ -1,21 +1,15 @@
1
- import { type PopupProps } from '@gravity-ui/uikit';
2
- import type { EditorState } from 'prosemirror-state';
1
+ import type { PopupProps } from '@gravity-ui/uikit';
3
2
  import type { EditorView } from 'prosemirror-view';
4
3
  import type { ActionStorage } from "../../../core/index.js";
5
4
  import { type Logger2 } from "../../../logger.js";
6
- import type { ToolbarButtonPopupData, ToolbarGroupItemData, ToolbarSingleItemData } from "../../../toolbar/index.js";
7
- export type ContextGroupItemData = (ToolbarGroupItemData<ActionStorage> & {
8
- condition?: (state: EditorState) => void;
9
- }) | ((ToolbarSingleItemData<ActionStorage> | ToolbarButtonPopupData<ActionStorage>) & {
10
- condition?: 'enabled';
11
- });
12
- export type ContextGroupData = ContextGroupItemData[];
13
- export type ContextConfig = ContextGroupData[];
5
+ import type { ContextConfig } from "./types.js";
6
+ export type { ContextGroupItemData, ContextGroupData, ContextConfig } from "./types.js";
14
7
  export type TooltipViewParams = {
15
8
  /** @default 'bottom' */
16
9
  placement?: 'top' | 'bottom';
17
10
  /** @default false */
18
11
  flip?: boolean;
12
+ onPopupOpenChange: PopupProps['onOpenChange'];
19
13
  };
20
14
  export declare class TooltipView {
21
15
  #private;
@@ -23,17 +17,19 @@ export declare class TooltipView {
23
17
  private readonly actions;
24
18
  private readonly menuConfig;
25
19
  private readonly placement;
20
+ private readonly onPopupOpenChange;
26
21
  private view;
27
- private baseProps;
22
+ private visible;
23
+ private anchor;
28
24
  private _tooltipRenderItem;
29
25
  constructor(actions: ActionStorage, menuConfig: ContextConfig, logger: Logger2.ILogger, params: TooltipViewParams);
30
26
  get isTooltipOpen(): boolean;
31
- show(view: EditorView, popupProps?: PopupProps): void;
27
+ show(view: EditorView): void;
32
28
  hide(view: EditorView): void;
33
29
  destroy(): void;
34
- private getSelectionTooltipProps;
35
- private getFilteredConfig;
30
+ private readonly handleFocus;
31
+ private readonly handleClick;
36
32
  private renderPopup;
37
33
  private get tooltipRenderItem();
38
- private calcPosition;
34
+ private createVirtualElement;
39
35
  }
@@ -2,102 +2,74 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TooltipView = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const uikit_1 = require("@gravity-ui/uikit");
6
- const lodash_1 = require("../../../lodash.js");
7
5
  const logger_1 = require("../../../logger.js");
8
6
  const ErrorBoundary_1 = require("../../../react-utils/ErrorBoundary.js");
9
- const toolbar_1 = require("../../../toolbar/index.js");
10
7
  const ReactRenderer_1 = require("../ReactRenderer/index.js");
11
- const SelectionTooltip = ({ show, poppupProps, ...toolbarProps }) => {
12
- if (!show)
13
- return null;
14
- return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: true, ...poppupProps, style: { padding: '4px 8px' }, children: (0, jsx_runtime_1.jsx)(toolbar_1.Toolbar, { ...toolbarProps }) }));
15
- };
8
+ const TextSelectionTooltip_1 = require("./TextSelectionTooltip.js");
16
9
  class TooltipView {
17
10
  #isTooltipOpen = false;
18
11
  logger;
19
12
  actions;
20
13
  menuConfig;
21
14
  placement;
15
+ onPopupOpenChange;
22
16
  view;
23
- baseProps = { show: false, poppupProps: {} };
17
+ visible = false;
18
+ anchor = undefined;
24
19
  _tooltipRenderItem = null;
25
20
  constructor(actions, menuConfig, logger, params) {
26
21
  this.logger = logger;
27
22
  this.actions = actions;
28
23
  this.menuConfig = menuConfig;
29
- const { flip, placement = 'bottom' } = params;
24
+ const { flip, placement = 'bottom', onPopupOpenChange } = params;
30
25
  this.placement = flip ? placement : [placement];
26
+ this.onPopupOpenChange = onPopupOpenChange;
31
27
  }
32
28
  get isTooltipOpen() {
33
29
  return this.#isTooltipOpen;
34
30
  }
35
- show(view, popupProps) {
31
+ show(view) {
36
32
  this.view = view;
37
33
  this.#isTooltipOpen = true;
38
- this.baseProps = {
39
- show: true,
40
- poppupProps: {
41
- ...popupProps,
42
- ...this.calcPosition(view),
43
- },
44
- };
34
+ this.visible = true;
35
+ this.anchor ??= this.createVirtualElement(view);
45
36
  this.renderPopup();
46
37
  }
47
38
  hide(view) {
48
39
  this.view = view;
49
40
  // do not rerender popup if it is already hidden
50
- if (!this.#isTooltipOpen && !this.baseProps.show)
41
+ if (!this.#isTooltipOpen && !this.visible)
51
42
  return;
52
43
  this.#isTooltipOpen = false;
53
- this.baseProps = { show: false, poppupProps: {} };
44
+ this.visible = false;
45
+ this.anchor = undefined;
54
46
  this.renderPopup();
55
47
  }
56
48
  destroy() {
57
49
  this._tooltipRenderItem?.remove();
58
50
  this._tooltipRenderItem = null;
59
51
  }
60
- getSelectionTooltipProps() {
61
- return {
62
- ...this.baseProps,
63
- qa: 'g-md-toolbar-selection',
64
- focus: () => this.view.focus(),
65
- data: this.getFilteredConfig(),
66
- editor: this.actions,
67
- onClick: (id) => {
68
- logger_1.globalLogger.action({ mode: 'wysiwyg', source: 'context-menu', action: id });
69
- this.logger.action({ source: 'context-menu', action: id });
70
- },
71
- };
72
- }
73
- getFilteredConfig() {
74
- return this.baseProps.show
75
- ? this.menuConfig
76
- .map((groupData) => groupData.filter((item) => {
77
- const { condition } = item;
78
- if (condition === 'enabled') {
79
- return item.isEnable(this.actions);
80
- }
81
- if ((0, lodash_1.isFunction)(condition)) {
82
- return condition(this.view.state);
83
- }
84
- return true;
85
- }))
86
- .filter((groupData) => Boolean(groupData.length))
87
- : [];
88
- }
52
+ handleFocus = () => this.view.focus();
53
+ handleClick = (id) => {
54
+ logger_1.globalLogger.action({ mode: 'wysiwyg', source: 'context-menu', action: id });
55
+ this.logger.action({ source: 'context-menu', action: id });
56
+ };
89
57
  renderPopup() {
90
58
  this.tooltipRenderItem.rerender();
91
59
  }
92
60
  get tooltipRenderItem() {
93
61
  if (!this._tooltipRenderItem) {
94
62
  const reactRenderer = (0, ReactRenderer_1.getReactRendererFromState)(this.view.state);
95
- this._tooltipRenderItem = reactRenderer.createItem('selection_context', () => ((0, jsx_runtime_1.jsx)(ErrorBoundary_1.ErrorLoggerBoundary, { children: (0, jsx_runtime_1.jsx)(SelectionTooltip, { ...this.getSelectionTooltipProps() }) })));
63
+ this._tooltipRenderItem = reactRenderer.createItem('selection_context', () => {
64
+ if (!this.visible)
65
+ return null;
66
+ return ((0, jsx_runtime_1.jsx)(ErrorBoundary_1.ErrorLoggerBoundary, { children: (0, jsx_runtime_1.jsx)(TextSelectionTooltip_1.TextSelectionTooltip, { config: this.menuConfig, editor: this.actions, editorView: this.view, focus: this.handleFocus, onClick: this.handleClick, popupPlacement: this.placement, popupAnchor: this.anchor, popupOnOpenChange: this.onPopupOpenChange }) }));
67
+ });
96
68
  }
97
69
  return this._tooltipRenderItem;
98
70
  }
99
- calcPosition(view) {
100
- const virtualElem = {
71
+ createVirtualElement(view) {
72
+ return {
101
73
  getBoundingClientRect() {
102
74
  // These are in screen coordinates
103
75
  const start = view.coordsAtPos(view.state.selection.from);
@@ -121,10 +93,6 @@ class TooltipView {
121
93
  };
122
94
  },
123
95
  };
124
- return {
125
- placement: this.placement,
126
- anchorElement: virtualElem,
127
- };
128
96
  }
129
97
  }
130
98
  exports.TooltipView = TooltipView;