@multiplatform.one/rich-text 6.1.0 → 6.3.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 (649) hide show
  1. package/README.md +60 -0
  2. package/dist/cjs/RichEditor.cjs +84 -9
  3. package/dist/cjs/RichEditor.native.js +422 -35
  4. package/dist/cjs/RichEditor.native.js.map +1 -1
  5. package/dist/cjs/RichTextEditor/index.cjs +18 -2
  6. package/dist/cjs/RichTextEditor/index.native.js +18 -2
  7. package/dist/cjs/RichTextEditor/index.native.js.map +1 -1
  8. package/dist/cjs/constants.cjs +52 -29
  9. package/dist/cjs/constants.native.js +59 -29
  10. package/dist/cjs/constants.native.js.map +1 -1
  11. package/dist/cjs/editor/BlockDragHandle.cjs +22 -7
  12. package/dist/cjs/editor/BlockDragHandle.native.js +41 -7
  13. package/dist/cjs/editor/BlockDragHandle.native.js.map +1 -1
  14. package/dist/cjs/editor/SlashCommands.cjs +249 -293
  15. package/dist/cjs/editor/SlashCommands.native.js +306 -340
  16. package/dist/cjs/editor/SlashCommands.native.js.map +1 -1
  17. package/dist/cjs/editor/TentapEditor.native.js +44 -12
  18. package/dist/cjs/editor/TentapEditor.native.js.map +1 -1
  19. package/dist/cjs/editor/TiptapEditor.cjs +140 -33
  20. package/dist/cjs/editor/TiptapEditor.native.js +153 -33
  21. package/dist/cjs/editor/TiptapEditor.native.js.map +1 -1
  22. package/dist/cjs/editor/blockAnchor.cjs +43 -0
  23. package/dist/cjs/editor/blockAnchor.native.js +68 -0
  24. package/dist/cjs/editor/blockAnchor.native.js.map +1 -0
  25. package/dist/cjs/editor/codeBlockPreview.cjs +230 -0
  26. package/dist/cjs/editor/codeBlockPreview.native.js +265 -0
  27. package/dist/cjs/editor/codeBlockPreview.native.js.map +1 -0
  28. package/dist/cjs/editor/editorStyles.cjs +203 -34
  29. package/dist/cjs/editor/editorStyles.native.js +203 -34
  30. package/dist/cjs/editor/editorStyles.native.js.map +1 -1
  31. package/dist/cjs/editor/emoji.cjs +128 -0
  32. package/dist/cjs/editor/emoji.native.js +184 -0
  33. package/dist/cjs/editor/emoji.native.js.map +1 -0
  34. package/dist/cjs/editor/lazyKatex.cjs +78 -0
  35. package/dist/cjs/editor/lazyKatex.native.js +117 -0
  36. package/dist/cjs/editor/lazyKatex.native.js.map +1 -0
  37. package/dist/cjs/editor/markdown.cjs +216 -0
  38. package/dist/cjs/editor/markdown.native.js +278 -0
  39. package/dist/cjs/editor/markdown.native.js.map +1 -0
  40. package/dist/cjs/editor/mathematics.cjs +168 -0
  41. package/dist/cjs/editor/mathematics.native.js +202 -0
  42. package/dist/cjs/editor/mathematics.native.js.map +1 -0
  43. package/dist/cjs/editor/media.cjs +138 -0
  44. package/dist/cjs/editor/media.native.js +172 -0
  45. package/dist/cjs/editor/media.native.js.map +1 -0
  46. package/dist/cjs/editor/mentions.cjs +73 -0
  47. package/dist/cjs/editor/mentions.native.js +84 -0
  48. package/dist/cjs/editor/mentions.native.js.map +1 -0
  49. package/dist/cjs/editor/pasteCleanup.cjs +83 -0
  50. package/dist/cjs/editor/pasteCleanup.native.js +175 -0
  51. package/dist/cjs/editor/pasteCleanup.native.js.map +1 -0
  52. package/dist/cjs/editor/suggestionPopup.cjs +297 -0
  53. package/dist/cjs/editor/suggestionPopup.native.js +327 -0
  54. package/dist/cjs/editor/suggestionPopup.native.js.map +1 -0
  55. package/dist/cjs/preview.cjs +263 -0
  56. package/dist/cjs/preview.native.js +294 -0
  57. package/dist/cjs/preview.native.js.map +1 -0
  58. package/dist/cjs/shared/t.cjs +53 -0
  59. package/dist/cjs/shared/t.native.js +56 -0
  60. package/dist/cjs/shared/t.native.js.map +1 -0
  61. package/dist/cjs/shared/url.cjs +35 -0
  62. package/dist/cjs/shared/url.native.js +38 -0
  63. package/dist/cjs/shared/url.native.js.map +1 -0
  64. package/dist/cjs/styled.cjs +13 -6
  65. package/dist/cjs/styled.native.js +13 -6
  66. package/dist/cjs/styled.native.js.map +1 -1
  67. package/dist/cjs/toolbar/BubbleToolbar.cjs +10 -8
  68. package/dist/cjs/toolbar/BubbleToolbar.native.js +10 -8
  69. package/dist/cjs/toolbar/BubbleToolbar.native.js.map +1 -1
  70. package/dist/cjs/toolbar/CodeBlockBubble.cjs +59 -23
  71. package/dist/cjs/toolbar/CodeBlockBubble.native.js +71 -25
  72. package/dist/cjs/toolbar/CodeBlockBubble.native.js.map +1 -1
  73. package/dist/cjs/toolbar/ColorPicker.cjs +19 -54
  74. package/dist/cjs/toolbar/ColorPicker.native.js +81 -179
  75. package/dist/cjs/toolbar/ColorPicker.native.js.map +1 -1
  76. package/dist/cjs/toolbar/FixedToolbar.cjs +33 -10
  77. package/dist/cjs/toolbar/FixedToolbar.native.js +46 -54
  78. package/dist/cjs/toolbar/FixedToolbar.native.js.map +1 -1
  79. package/dist/cjs/toolbar/HeadingPicker.cjs +32 -39
  80. package/dist/cjs/toolbar/HeadingPicker.native.js +61 -51
  81. package/dist/cjs/toolbar/HeadingPicker.native.js.map +1 -1
  82. package/dist/cjs/toolbar/ImageBubble.cjs +20 -43
  83. package/dist/cjs/toolbar/ImageBubble.native.js +20 -43
  84. package/dist/cjs/toolbar/ImageBubble.native.js.map +1 -1
  85. package/dist/cjs/toolbar/ImageDialog.cjs +5 -4
  86. package/dist/cjs/toolbar/ImageDialog.native.js +76 -65
  87. package/dist/cjs/toolbar/ImageDialog.native.js.map +1 -1
  88. package/dist/cjs/toolbar/LinkBubble.cjs +23 -70
  89. package/dist/cjs/toolbar/LinkBubble.native.js +23 -70
  90. package/dist/cjs/toolbar/LinkBubble.native.js.map +1 -1
  91. package/dist/cjs/toolbar/LinkDialog.cjs +19 -18
  92. package/dist/cjs/toolbar/LinkDialog.native.js +86 -83
  93. package/dist/cjs/toolbar/LinkDialog.native.js.map +1 -1
  94. package/dist/cjs/toolbar/ListPicker.cjs +32 -43
  95. package/dist/cjs/toolbar/ListPicker.native.js +43 -44
  96. package/dist/cjs/toolbar/ListPicker.native.js.map +1 -1
  97. package/dist/cjs/toolbar/MathBubble.cjs +159 -0
  98. package/dist/cjs/toolbar/MathBubble.native.js +169 -0
  99. package/dist/cjs/toolbar/MathBubble.native.js.map +1 -0
  100. package/dist/cjs/toolbar/MoreDropdown.cjs +51 -98
  101. package/dist/cjs/toolbar/MoreDropdown.native.js +73 -98
  102. package/dist/cjs/toolbar/MoreDropdown.native.js.map +1 -1
  103. package/dist/cjs/toolbar/StatusBar.cjs +19 -10
  104. package/dist/cjs/toolbar/StatusBar.native.js +19 -10
  105. package/dist/cjs/toolbar/StatusBar.native.js.map +1 -1
  106. package/dist/cjs/toolbar/TableBubble.cjs +77 -95
  107. package/dist/cjs/toolbar/TableBubble.native.js +73 -71
  108. package/dist/cjs/toolbar/TableBubble.native.js.map +1 -1
  109. package/dist/cjs/toolbar/ToolbarButton.cjs +86 -21
  110. package/dist/cjs/toolbar/ToolbarButton.native.js +14 -4
  111. package/dist/cjs/toolbar/ToolbarButton.native.js.map +1 -1
  112. package/dist/cjs/toolbar/icons.cjs +111 -468
  113. package/dist/cjs/toolbar/shortcuts.cjs +73 -24
  114. package/dist/cjs/toolbar/shortcuts.native.js +73 -24
  115. package/dist/cjs/toolbar/shortcuts.native.js.map +1 -1
  116. package/dist/cjs/toolbar/useHorizontalScroll.cjs +25 -5
  117. package/dist/cjs/toolbar/useHorizontalScroll.native.js +25 -5
  118. package/dist/cjs/toolbar/useHorizontalScroll.native.js.map +1 -1
  119. package/dist/cjs/toolbar/useRovingFocus.cjs +80 -0
  120. package/dist/cjs/toolbar/useRovingFocus.native.js +113 -0
  121. package/dist/cjs/toolbar/useRovingFocus.native.js.map +1 -0
  122. package/dist/cjs/types.native.js.map +1 -1
  123. package/dist/esm/RichEditor.mjs +85 -10
  124. package/dist/esm/RichEditor.mjs.map +1 -1
  125. package/dist/esm/RichEditor.native.js +425 -38
  126. package/dist/esm/RichEditor.native.js.map +1 -1
  127. package/dist/esm/RichTextEditor/index.mjs +18 -2
  128. package/dist/esm/RichTextEditor/index.mjs.map +1 -1
  129. package/dist/esm/RichTextEditor/index.native.js +18 -2
  130. package/dist/esm/RichTextEditor/index.native.js.map +1 -1
  131. package/dist/esm/constants.mjs +47 -29
  132. package/dist/esm/constants.mjs.map +1 -1
  133. package/dist/esm/constants.native.js +54 -29
  134. package/dist/esm/constants.native.js.map +1 -1
  135. package/dist/esm/editor/BlockDragHandle.mjs +22 -7
  136. package/dist/esm/editor/BlockDragHandle.mjs.map +1 -1
  137. package/dist/esm/editor/BlockDragHandle.native.js +41 -7
  138. package/dist/esm/editor/BlockDragHandle.native.js.map +1 -1
  139. package/dist/esm/editor/SlashCommands.mjs +250 -294
  140. package/dist/esm/editor/SlashCommands.mjs.map +1 -1
  141. package/dist/esm/editor/SlashCommands.native.js +307 -341
  142. package/dist/esm/editor/SlashCommands.native.js.map +1 -1
  143. package/dist/esm/editor/TentapEditor.native.js +45 -13
  144. package/dist/esm/editor/TentapEditor.native.js.map +1 -1
  145. package/dist/esm/editor/TiptapEditor.mjs +142 -35
  146. package/dist/esm/editor/TiptapEditor.mjs.map +1 -1
  147. package/dist/esm/editor/TiptapEditor.native.js +155 -35
  148. package/dist/esm/editor/TiptapEditor.native.js.map +1 -1
  149. package/dist/esm/editor/blockAnchor.mjs +18 -0
  150. package/dist/esm/editor/blockAnchor.mjs.map +1 -0
  151. package/dist/esm/editor/blockAnchor.native.js +40 -0
  152. package/dist/esm/editor/blockAnchor.native.js.map +1 -0
  153. package/dist/esm/editor/codeBlockPreview.mjs +190 -0
  154. package/dist/esm/editor/codeBlockPreview.mjs.map +1 -0
  155. package/dist/esm/editor/codeBlockPreview.native.js +222 -0
  156. package/dist/esm/editor/codeBlockPreview.native.js.map +1 -0
  157. package/dist/esm/editor/editorStyles.mjs +203 -34
  158. package/dist/esm/editor/editorStyles.mjs.map +1 -1
  159. package/dist/esm/editor/editorStyles.native.js +203 -34
  160. package/dist/esm/editor/editorStyles.native.js.map +1 -1
  161. package/dist/esm/editor/emoji.mjs +88 -0
  162. package/dist/esm/editor/emoji.mjs.map +1 -0
  163. package/dist/esm/editor/emoji.native.js +141 -0
  164. package/dist/esm/editor/emoji.native.js.map +1 -0
  165. package/dist/esm/editor/lazyKatex.mjs +40 -0
  166. package/dist/esm/editor/lazyKatex.mjs.map +1 -0
  167. package/dist/esm/editor/lazyKatex.native.js +76 -0
  168. package/dist/esm/editor/lazyKatex.native.js.map +1 -0
  169. package/dist/esm/editor/markdown.mjs +179 -0
  170. package/dist/esm/editor/markdown.mjs.map +1 -0
  171. package/dist/esm/editor/markdown.native.js +238 -0
  172. package/dist/esm/editor/markdown.native.js.map +1 -0
  173. package/dist/esm/editor/mathematics.mjs +142 -0
  174. package/dist/esm/editor/mathematics.mjs.map +1 -0
  175. package/dist/esm/editor/mathematics.native.js +173 -0
  176. package/dist/esm/editor/mathematics.native.js.map +1 -0
  177. package/dist/esm/editor/media.mjs +113 -0
  178. package/dist/esm/editor/media.mjs.map +1 -0
  179. package/dist/esm/editor/media.native.js +144 -0
  180. package/dist/esm/editor/media.native.js.map +1 -0
  181. package/dist/esm/editor/mentions.mjs +37 -0
  182. package/dist/esm/editor/mentions.mjs.map +1 -0
  183. package/dist/esm/editor/mentions.native.js +45 -0
  184. package/dist/esm/editor/mentions.native.js.map +1 -0
  185. package/dist/esm/editor/pasteCleanup.mjs +57 -0
  186. package/dist/esm/editor/pasteCleanup.mjs.map +1 -0
  187. package/dist/esm/editor/pasteCleanup.native.js +146 -0
  188. package/dist/esm/editor/pasteCleanup.native.js.map +1 -0
  189. package/dist/esm/editor/suggestionPopup.mjs +268 -0
  190. package/dist/esm/editor/suggestionPopup.mjs.map +1 -0
  191. package/dist/esm/editor/suggestionPopup.native.js +295 -0
  192. package/dist/esm/editor/suggestionPopup.native.js.map +1 -0
  193. package/dist/esm/preview.mjs +236 -0
  194. package/dist/esm/preview.mjs.map +1 -0
  195. package/dist/esm/preview.native.js +264 -0
  196. package/dist/esm/preview.native.js.map +1 -0
  197. package/dist/esm/shared/t.mjs +17 -0
  198. package/dist/esm/shared/t.mjs.map +1 -0
  199. package/dist/esm/shared/t.native.js +17 -0
  200. package/dist/esm/shared/t.native.js.map +1 -0
  201. package/dist/esm/shared/url.mjs +10 -0
  202. package/dist/esm/shared/url.mjs.map +1 -0
  203. package/dist/esm/shared/url.native.js +10 -0
  204. package/dist/esm/shared/url.native.js.map +1 -0
  205. package/dist/esm/styled.mjs +13 -6
  206. package/dist/esm/styled.mjs.map +1 -1
  207. package/dist/esm/styled.native.js +13 -6
  208. package/dist/esm/styled.native.js.map +1 -1
  209. package/dist/esm/toolbar/BubbleToolbar.mjs +11 -9
  210. package/dist/esm/toolbar/BubbleToolbar.mjs.map +1 -1
  211. package/dist/esm/toolbar/BubbleToolbar.native.js +11 -9
  212. package/dist/esm/toolbar/BubbleToolbar.native.js.map +1 -1
  213. package/dist/esm/toolbar/CodeBlockBubble.mjs +60 -24
  214. package/dist/esm/toolbar/CodeBlockBubble.mjs.map +1 -1
  215. package/dist/esm/toolbar/CodeBlockBubble.native.js +72 -26
  216. package/dist/esm/toolbar/CodeBlockBubble.native.js.map +1 -1
  217. package/dist/esm/toolbar/ColorPicker.mjs +21 -56
  218. package/dist/esm/toolbar/ColorPicker.mjs.map +1 -1
  219. package/dist/esm/toolbar/ColorPicker.native.js +82 -180
  220. package/dist/esm/toolbar/ColorPicker.native.js.map +1 -1
  221. package/dist/esm/toolbar/FixedToolbar.mjs +34 -11
  222. package/dist/esm/toolbar/FixedToolbar.mjs.map +1 -1
  223. package/dist/esm/toolbar/FixedToolbar.native.js +47 -55
  224. package/dist/esm/toolbar/FixedToolbar.native.js.map +1 -1
  225. package/dist/esm/toolbar/HeadingPicker.mjs +34 -41
  226. package/dist/esm/toolbar/HeadingPicker.mjs.map +1 -1
  227. package/dist/esm/toolbar/HeadingPicker.native.js +63 -53
  228. package/dist/esm/toolbar/HeadingPicker.native.js.map +1 -1
  229. package/dist/esm/toolbar/ImageBubble.mjs +20 -43
  230. package/dist/esm/toolbar/ImageBubble.mjs.map +1 -1
  231. package/dist/esm/toolbar/ImageBubble.native.js +20 -43
  232. package/dist/esm/toolbar/ImageBubble.native.js.map +1 -1
  233. package/dist/esm/toolbar/ImageDialog.mjs +5 -4
  234. package/dist/esm/toolbar/ImageDialog.mjs.map +1 -1
  235. package/dist/esm/toolbar/ImageDialog.native.js +75 -64
  236. package/dist/esm/toolbar/ImageDialog.native.js.map +1 -1
  237. package/dist/esm/toolbar/LinkBubble.mjs +23 -70
  238. package/dist/esm/toolbar/LinkBubble.mjs.map +1 -1
  239. package/dist/esm/toolbar/LinkBubble.native.js +23 -70
  240. package/dist/esm/toolbar/LinkBubble.native.js.map +1 -1
  241. package/dist/esm/toolbar/LinkDialog.mjs +17 -16
  242. package/dist/esm/toolbar/LinkDialog.mjs.map +1 -1
  243. package/dist/esm/toolbar/LinkDialog.native.js +84 -80
  244. package/dist/esm/toolbar/LinkDialog.native.js.map +1 -1
  245. package/dist/esm/toolbar/ListPicker.mjs +33 -44
  246. package/dist/esm/toolbar/ListPicker.mjs.map +1 -1
  247. package/dist/esm/toolbar/ListPicker.native.js +44 -45
  248. package/dist/esm/toolbar/ListPicker.native.js.map +1 -1
  249. package/dist/esm/toolbar/MathBubble.mjs +134 -0
  250. package/dist/esm/toolbar/MathBubble.mjs.map +1 -0
  251. package/dist/esm/toolbar/MathBubble.native.js +141 -0
  252. package/dist/esm/toolbar/MathBubble.native.js.map +1 -0
  253. package/dist/esm/toolbar/MoreDropdown.mjs +50 -97
  254. package/dist/esm/toolbar/MoreDropdown.mjs.map +1 -1
  255. package/dist/esm/toolbar/MoreDropdown.native.js +72 -97
  256. package/dist/esm/toolbar/MoreDropdown.native.js.map +1 -1
  257. package/dist/esm/toolbar/StatusBar.mjs +19 -10
  258. package/dist/esm/toolbar/StatusBar.mjs.map +1 -1
  259. package/dist/esm/toolbar/StatusBar.native.js +19 -10
  260. package/dist/esm/toolbar/StatusBar.native.js.map +1 -1
  261. package/dist/esm/toolbar/TableBubble.mjs +77 -95
  262. package/dist/esm/toolbar/TableBubble.mjs.map +1 -1
  263. package/dist/esm/toolbar/TableBubble.native.js +73 -71
  264. package/dist/esm/toolbar/TableBubble.native.js.map +1 -1
  265. package/dist/esm/toolbar/ToolbarButton.mjs +87 -22
  266. package/dist/esm/toolbar/ToolbarButton.mjs.map +1 -1
  267. package/dist/esm/toolbar/ToolbarButton.native.js +14 -4
  268. package/dist/esm/toolbar/ToolbarButton.native.js.map +1 -1
  269. package/dist/esm/toolbar/icons.mjs +109 -469
  270. package/dist/esm/toolbar/icons.mjs.map +1 -1
  271. package/dist/esm/toolbar/shortcuts.mjs +73 -24
  272. package/dist/esm/toolbar/shortcuts.mjs.map +1 -1
  273. package/dist/esm/toolbar/shortcuts.native.js +73 -24
  274. package/dist/esm/toolbar/shortcuts.native.js.map +1 -1
  275. package/dist/esm/toolbar/useHorizontalScroll.mjs +25 -6
  276. package/dist/esm/toolbar/useHorizontalScroll.mjs.map +1 -1
  277. package/dist/esm/toolbar/useHorizontalScroll.native.js +25 -6
  278. package/dist/esm/toolbar/useHorizontalScroll.native.js.map +1 -1
  279. package/dist/esm/toolbar/useRovingFocus.mjs +55 -0
  280. package/dist/esm/toolbar/useRovingFocus.mjs.map +1 -0
  281. package/dist/esm/toolbar/useRovingFocus.native.js +85 -0
  282. package/dist/esm/toolbar/useRovingFocus.native.js.map +1 -0
  283. package/dist/esm/types.mjs.map +1 -1
  284. package/dist/esm/types.native.js.map +1 -1
  285. package/dist/jsx/RichEditor.mjs +85 -10
  286. package/dist/jsx/RichEditor.mjs.map +1 -1
  287. package/dist/jsx/RichEditor.native.js +422 -35
  288. package/dist/jsx/RichEditor.native.js.map +1 -1
  289. package/dist/jsx/RichTextEditor/index.mjs +18 -2
  290. package/dist/jsx/RichTextEditor/index.mjs.map +1 -1
  291. package/dist/jsx/RichTextEditor/index.native.js +18 -2
  292. package/dist/jsx/RichTextEditor/index.native.js.map +1 -1
  293. package/dist/jsx/constants.mjs +47 -29
  294. package/dist/jsx/constants.mjs.map +1 -1
  295. package/dist/jsx/constants.native.js +59 -29
  296. package/dist/jsx/constants.native.js.map +1 -1
  297. package/dist/jsx/editor/BlockDragHandle.mjs +22 -7
  298. package/dist/jsx/editor/BlockDragHandle.mjs.map +1 -1
  299. package/dist/jsx/editor/BlockDragHandle.native.js +41 -7
  300. package/dist/jsx/editor/BlockDragHandle.native.js.map +1 -1
  301. package/dist/jsx/editor/SlashCommands.mjs +250 -294
  302. package/dist/jsx/editor/SlashCommands.mjs.map +1 -1
  303. package/dist/jsx/editor/SlashCommands.native.js +306 -340
  304. package/dist/jsx/editor/SlashCommands.native.js.map +1 -1
  305. package/dist/jsx/editor/TentapEditor.native.js +44 -12
  306. package/dist/jsx/editor/TentapEditor.native.js.map +1 -1
  307. package/dist/jsx/editor/TiptapEditor.mjs +142 -35
  308. package/dist/jsx/editor/TiptapEditor.mjs.map +1 -1
  309. package/dist/jsx/editor/TiptapEditor.native.js +153 -33
  310. package/dist/jsx/editor/TiptapEditor.native.js.map +1 -1
  311. package/dist/jsx/editor/blockAnchor.mjs +18 -0
  312. package/dist/jsx/editor/blockAnchor.mjs.map +1 -0
  313. package/dist/jsx/editor/blockAnchor.native.js +68 -0
  314. package/dist/jsx/editor/blockAnchor.native.js.map +1 -0
  315. package/dist/jsx/editor/codeBlockPreview.mjs +190 -0
  316. package/dist/jsx/editor/codeBlockPreview.mjs.map +1 -0
  317. package/dist/jsx/editor/codeBlockPreview.native.js +265 -0
  318. package/dist/jsx/editor/codeBlockPreview.native.js.map +1 -0
  319. package/dist/jsx/editor/editorStyles.mjs +203 -34
  320. package/dist/jsx/editor/editorStyles.mjs.map +1 -1
  321. package/dist/jsx/editor/editorStyles.native.js +203 -34
  322. package/dist/jsx/editor/editorStyles.native.js.map +1 -1
  323. package/dist/jsx/editor/emoji.mjs +88 -0
  324. package/dist/jsx/editor/emoji.mjs.map +1 -0
  325. package/dist/jsx/editor/emoji.native.js +184 -0
  326. package/dist/jsx/editor/emoji.native.js.map +1 -0
  327. package/dist/jsx/editor/lazyKatex.mjs +40 -0
  328. package/dist/jsx/editor/lazyKatex.mjs.map +1 -0
  329. package/dist/jsx/editor/lazyKatex.native.js +117 -0
  330. package/dist/jsx/editor/lazyKatex.native.js.map +1 -0
  331. package/dist/jsx/editor/markdown.mjs +179 -0
  332. package/dist/jsx/editor/markdown.mjs.map +1 -0
  333. package/dist/jsx/editor/markdown.native.js +278 -0
  334. package/dist/jsx/editor/markdown.native.js.map +1 -0
  335. package/dist/jsx/editor/mathematics.mjs +142 -0
  336. package/dist/jsx/editor/mathematics.mjs.map +1 -0
  337. package/dist/jsx/editor/mathematics.native.js +202 -0
  338. package/dist/jsx/editor/mathematics.native.js.map +1 -0
  339. package/dist/jsx/editor/media.mjs +113 -0
  340. package/dist/jsx/editor/media.mjs.map +1 -0
  341. package/dist/jsx/editor/media.native.js +172 -0
  342. package/dist/jsx/editor/media.native.js.map +1 -0
  343. package/dist/jsx/editor/mentions.mjs +37 -0
  344. package/dist/jsx/editor/mentions.mjs.map +1 -0
  345. package/dist/jsx/editor/mentions.native.js +84 -0
  346. package/dist/jsx/editor/mentions.native.js.map +1 -0
  347. package/dist/jsx/editor/pasteCleanup.mjs +57 -0
  348. package/dist/jsx/editor/pasteCleanup.mjs.map +1 -0
  349. package/dist/jsx/editor/pasteCleanup.native.js +175 -0
  350. package/dist/jsx/editor/pasteCleanup.native.js.map +1 -0
  351. package/dist/jsx/editor/suggestionPopup.mjs +268 -0
  352. package/dist/jsx/editor/suggestionPopup.mjs.map +1 -0
  353. package/dist/jsx/editor/suggestionPopup.native.js +327 -0
  354. package/dist/jsx/editor/suggestionPopup.native.js.map +1 -0
  355. package/dist/jsx/preview.mjs +236 -0
  356. package/dist/jsx/preview.mjs.map +1 -0
  357. package/dist/jsx/preview.native.js +294 -0
  358. package/dist/jsx/preview.native.js.map +1 -0
  359. package/dist/jsx/shared/t.mjs +17 -0
  360. package/dist/jsx/shared/t.mjs.map +1 -0
  361. package/dist/jsx/shared/t.native.js +56 -0
  362. package/dist/jsx/shared/t.native.js.map +1 -0
  363. package/dist/jsx/shared/url.mjs +10 -0
  364. package/dist/jsx/shared/url.mjs.map +1 -0
  365. package/dist/jsx/shared/url.native.js +38 -0
  366. package/dist/jsx/shared/url.native.js.map +1 -0
  367. package/dist/jsx/styled.mjs +13 -6
  368. package/dist/jsx/styled.mjs.map +1 -1
  369. package/dist/jsx/styled.native.js +13 -6
  370. package/dist/jsx/styled.native.js.map +1 -1
  371. package/dist/jsx/toolbar/BubbleToolbar.mjs +11 -9
  372. package/dist/jsx/toolbar/BubbleToolbar.mjs.map +1 -1
  373. package/dist/jsx/toolbar/BubbleToolbar.native.js +10 -8
  374. package/dist/jsx/toolbar/BubbleToolbar.native.js.map +1 -1
  375. package/dist/jsx/toolbar/CodeBlockBubble.mjs +60 -24
  376. package/dist/jsx/toolbar/CodeBlockBubble.mjs.map +1 -1
  377. package/dist/jsx/toolbar/CodeBlockBubble.native.js +71 -25
  378. package/dist/jsx/toolbar/CodeBlockBubble.native.js.map +1 -1
  379. package/dist/jsx/toolbar/ColorPicker.mjs +21 -56
  380. package/dist/jsx/toolbar/ColorPicker.mjs.map +1 -1
  381. package/dist/jsx/toolbar/ColorPicker.native.js +81 -179
  382. package/dist/jsx/toolbar/ColorPicker.native.js.map +1 -1
  383. package/dist/jsx/toolbar/FixedToolbar.mjs +34 -11
  384. package/dist/jsx/toolbar/FixedToolbar.mjs.map +1 -1
  385. package/dist/jsx/toolbar/FixedToolbar.native.js +46 -54
  386. package/dist/jsx/toolbar/FixedToolbar.native.js.map +1 -1
  387. package/dist/jsx/toolbar/HeadingPicker.mjs +34 -41
  388. package/dist/jsx/toolbar/HeadingPicker.mjs.map +1 -1
  389. package/dist/jsx/toolbar/HeadingPicker.native.js +61 -51
  390. package/dist/jsx/toolbar/HeadingPicker.native.js.map +1 -1
  391. package/dist/jsx/toolbar/ImageBubble.mjs +20 -43
  392. package/dist/jsx/toolbar/ImageBubble.mjs.map +1 -1
  393. package/dist/jsx/toolbar/ImageBubble.native.js +20 -43
  394. package/dist/jsx/toolbar/ImageBubble.native.js.map +1 -1
  395. package/dist/jsx/toolbar/ImageDialog.mjs +5 -4
  396. package/dist/jsx/toolbar/ImageDialog.mjs.map +1 -1
  397. package/dist/jsx/toolbar/ImageDialog.native.js +76 -65
  398. package/dist/jsx/toolbar/ImageDialog.native.js.map +1 -1
  399. package/dist/jsx/toolbar/LinkBubble.mjs +23 -70
  400. package/dist/jsx/toolbar/LinkBubble.mjs.map +1 -1
  401. package/dist/jsx/toolbar/LinkBubble.native.js +23 -70
  402. package/dist/jsx/toolbar/LinkBubble.native.js.map +1 -1
  403. package/dist/jsx/toolbar/LinkDialog.mjs +17 -16
  404. package/dist/jsx/toolbar/LinkDialog.mjs.map +1 -1
  405. package/dist/jsx/toolbar/LinkDialog.native.js +86 -83
  406. package/dist/jsx/toolbar/LinkDialog.native.js.map +1 -1
  407. package/dist/jsx/toolbar/ListPicker.mjs +33 -44
  408. package/dist/jsx/toolbar/ListPicker.mjs.map +1 -1
  409. package/dist/jsx/toolbar/ListPicker.native.js +43 -44
  410. package/dist/jsx/toolbar/ListPicker.native.js.map +1 -1
  411. package/dist/jsx/toolbar/MathBubble.mjs +134 -0
  412. package/dist/jsx/toolbar/MathBubble.mjs.map +1 -0
  413. package/dist/jsx/toolbar/MathBubble.native.js +169 -0
  414. package/dist/jsx/toolbar/MathBubble.native.js.map +1 -0
  415. package/dist/jsx/toolbar/MoreDropdown.mjs +50 -97
  416. package/dist/jsx/toolbar/MoreDropdown.mjs.map +1 -1
  417. package/dist/jsx/toolbar/MoreDropdown.native.js +73 -98
  418. package/dist/jsx/toolbar/MoreDropdown.native.js.map +1 -1
  419. package/dist/jsx/toolbar/StatusBar.mjs +19 -10
  420. package/dist/jsx/toolbar/StatusBar.mjs.map +1 -1
  421. package/dist/jsx/toolbar/StatusBar.native.js +19 -10
  422. package/dist/jsx/toolbar/StatusBar.native.js.map +1 -1
  423. package/dist/jsx/toolbar/TableBubble.mjs +77 -95
  424. package/dist/jsx/toolbar/TableBubble.mjs.map +1 -1
  425. package/dist/jsx/toolbar/TableBubble.native.js +73 -71
  426. package/dist/jsx/toolbar/TableBubble.native.js.map +1 -1
  427. package/dist/jsx/toolbar/ToolbarButton.mjs +87 -22
  428. package/dist/jsx/toolbar/ToolbarButton.mjs.map +1 -1
  429. package/dist/jsx/toolbar/ToolbarButton.native.js +14 -4
  430. package/dist/jsx/toolbar/ToolbarButton.native.js.map +1 -1
  431. package/dist/jsx/toolbar/icons.mjs +109 -469
  432. package/dist/jsx/toolbar/icons.mjs.map +1 -1
  433. package/dist/jsx/toolbar/shortcuts.mjs +73 -24
  434. package/dist/jsx/toolbar/shortcuts.mjs.map +1 -1
  435. package/dist/jsx/toolbar/shortcuts.native.js +73 -24
  436. package/dist/jsx/toolbar/shortcuts.native.js.map +1 -1
  437. package/dist/jsx/toolbar/useHorizontalScroll.mjs +25 -6
  438. package/dist/jsx/toolbar/useHorizontalScroll.mjs.map +1 -1
  439. package/dist/jsx/toolbar/useHorizontalScroll.native.js +25 -5
  440. package/dist/jsx/toolbar/useHorizontalScroll.native.js.map +1 -1
  441. package/dist/jsx/toolbar/useRovingFocus.mjs +55 -0
  442. package/dist/jsx/toolbar/useRovingFocus.mjs.map +1 -0
  443. package/dist/jsx/toolbar/useRovingFocus.native.js +113 -0
  444. package/dist/jsx/toolbar/useRovingFocus.native.js.map +1 -0
  445. package/dist/jsx/types.mjs.map +1 -1
  446. package/dist/jsx/types.native.js.map +1 -1
  447. package/package.json +28 -13
  448. package/src/RichEditor.native.tsx +451 -49
  449. package/src/RichEditor.stories.tsx +158 -0
  450. package/src/RichEditor.tsx +121 -7
  451. package/src/RichTextEditor/index.tsx +41 -3
  452. package/src/RichTextEditor/richTextEditor.spec.tsx +11 -4
  453. package/src/constants.ts +86 -24
  454. package/src/editor/BlockDragHandle.ts +30 -5
  455. package/src/editor/SlashCommands.tsx +228 -293
  456. package/src/editor/TentapEditor.native.tsx +68 -17
  457. package/src/editor/TiptapEditor.tsx +187 -22
  458. package/src/editor/blockAnchor.spec.ts +70 -0
  459. package/src/editor/blockAnchor.ts +42 -0
  460. package/src/editor/codeBlockPreview.spec.ts +144 -0
  461. package/src/editor/codeBlockPreview.ts +266 -0
  462. package/src/editor/css.d.ts +2 -0
  463. package/src/editor/details.spec.ts +48 -0
  464. package/src/editor/editorStyles.spec.ts +25 -0
  465. package/src/editor/editorStyles.ts +218 -34
  466. package/src/editor/emoji.spec.ts +88 -0
  467. package/src/editor/emoji.ts +147 -0
  468. package/src/editor/emojilib.d.ts +16 -0
  469. package/src/editor/lazyKatex.spec.ts +38 -0
  470. package/src/editor/lazyKatex.ts +68 -0
  471. package/src/editor/markdown.spec.ts +196 -0
  472. package/src/editor/markdown.ts +249 -0
  473. package/src/editor/mathematics.spec.ts +97 -0
  474. package/src/editor/mathematics.ts +179 -0
  475. package/src/editor/media.spec.ts +121 -0
  476. package/src/editor/media.ts +133 -0
  477. package/src/editor/mentions.spec.ts +41 -0
  478. package/src/editor/mentions.ts +55 -0
  479. package/src/editor/pasteCleanup.spec.ts +84 -0
  480. package/src/editor/pasteCleanup.ts +124 -0
  481. package/src/editor/suggestionPopup.spec.tsx +105 -0
  482. package/src/editor/suggestionPopup.tsx +414 -0
  483. package/src/editor/tiptapEditor.spec.tsx +15 -8
  484. package/src/exports.spec.ts +4 -2
  485. package/src/index.ts +7 -1
  486. package/src/integration.spec.tsx +38 -9
  487. package/src/preview.spec.ts +130 -0
  488. package/src/preview.ts +287 -0
  489. package/src/richEditor.spec.tsx +10 -3
  490. package/src/shared/t.ts +25 -0
  491. package/src/shared/url.ts +16 -0
  492. package/src/styled.ts +13 -6
  493. package/src/toolbar/BubbleToolbar.tsx +11 -8
  494. package/src/toolbar/CodeBlockBubble.tsx +66 -28
  495. package/src/toolbar/ColorPicker.native.tsx +126 -0
  496. package/src/toolbar/ColorPicker.tsx +23 -67
  497. package/src/toolbar/FixedToolbar.native.tsx +51 -51
  498. package/src/toolbar/FixedToolbar.tsx +54 -10
  499. package/src/toolbar/HeadingPicker.tsx +46 -38
  500. package/src/toolbar/ImageBubble.tsx +26 -44
  501. package/src/toolbar/ImageDialog.native.tsx +97 -0
  502. package/src/toolbar/ImageDialog.tsx +5 -4
  503. package/src/toolbar/LinkBubble.tsx +27 -64
  504. package/src/toolbar/LinkDialog.native.tsx +117 -0
  505. package/src/toolbar/LinkDialog.tsx +28 -24
  506. package/src/toolbar/ListPicker.tsx +47 -43
  507. package/src/toolbar/MathBubble.tsx +140 -0
  508. package/src/toolbar/MoreDropdown.tsx +53 -60
  509. package/src/toolbar/StatusBar.tsx +13 -8
  510. package/src/toolbar/TableBubble.tsx +82 -94
  511. package/src/toolbar/ToolbarButton.native.tsx +14 -4
  512. package/src/toolbar/ToolbarButton.tsx +98 -19
  513. package/src/toolbar/bubbleToolbar.spec.tsx +2 -1
  514. package/src/toolbar/fixedToolbar.spec.tsx +4 -2
  515. package/src/toolbar/icons.tsx +113 -323
  516. package/src/toolbar/shortcuts.ts +77 -24
  517. package/src/toolbar/toolbarPrimitives.spec.tsx +29 -1
  518. package/src/toolbar/toolbarSubComponents.spec.tsx +4 -2
  519. package/src/toolbar/useHorizontalScroll.spec.ts +67 -0
  520. package/src/toolbar/useHorizontalScroll.tsx +39 -12
  521. package/src/toolbar/useRovingFocus.spec.tsx +100 -0
  522. package/src/toolbar/useRovingFocus.ts +82 -0
  523. package/src/types.spec.ts +40 -1
  524. package/src/types.ts +28 -0
  525. package/types/RichEditor.d.ts +51 -0
  526. package/types/RichEditor.d.ts.map +1 -0
  527. package/types/RichEditor.native.d.ts +59 -0
  528. package/types/RichEditor.native.d.ts.map +1 -0
  529. package/types/RichTextEditor/index.d.ts +71 -0
  530. package/types/RichTextEditor/index.d.ts.map +1 -0
  531. package/types/constants.d.ts +49 -0
  532. package/types/constants.d.ts.map +1 -0
  533. package/types/context.d.ts +10 -0
  534. package/types/context.d.ts.map +1 -0
  535. package/types/editor/BlockDragHandle.d.ts +8 -0
  536. package/types/editor/BlockDragHandle.d.ts.map +1 -0
  537. package/types/editor/MarkdownPaste.d.ts +8 -0
  538. package/types/editor/MarkdownPaste.d.ts.map +1 -0
  539. package/types/editor/SlashCommands.d.ts +24 -0
  540. package/types/editor/SlashCommands.d.ts.map +1 -0
  541. package/types/editor/TentapEditor.native.d.ts +21 -0
  542. package/types/editor/TentapEditor.native.d.ts.map +1 -0
  543. package/types/editor/TiptapEditor.d.ts +24 -0
  544. package/types/editor/TiptapEditor.d.ts.map +1 -0
  545. package/types/editor/blockAnchor.d.ts +25 -0
  546. package/types/editor/blockAnchor.d.ts.map +1 -0
  547. package/types/editor/codeBlockPreview.d.ts +51 -0
  548. package/types/editor/codeBlockPreview.d.ts.map +1 -0
  549. package/types/editor/editorStyles.d.ts +25 -0
  550. package/types/editor/editorStyles.d.ts.map +1 -0
  551. package/types/editor/emoji.d.ts +45 -0
  552. package/types/editor/emoji.d.ts.map +1 -0
  553. package/types/editor/index.d.ts +11 -0
  554. package/types/editor/index.d.ts.map +1 -0
  555. package/types/editor/lazyKatex.d.ts +33 -0
  556. package/types/editor/lazyKatex.d.ts.map +1 -0
  557. package/types/editor/markdown.d.ts +24 -0
  558. package/types/editor/markdown.d.ts.map +1 -0
  559. package/types/editor/mathematics.d.ts +44 -0
  560. package/types/editor/mathematics.d.ts.map +1 -0
  561. package/types/editor/media.d.ts +32 -0
  562. package/types/editor/media.d.ts.map +1 -0
  563. package/types/editor/mentions.d.ts +15 -0
  564. package/types/editor/mentions.d.ts.map +1 -0
  565. package/types/editor/pasteCleanup.d.ts +24 -0
  566. package/types/editor/pasteCleanup.d.ts.map +1 -0
  567. package/types/editor/suggestionPopup.d.ts +113 -0
  568. package/types/editor/suggestionPopup.d.ts.map +1 -0
  569. package/types/editor/types.d.ts +80 -0
  570. package/types/editor/types.d.ts.map +1 -0
  571. package/types/editor/useEditorState.d.ts +19 -0
  572. package/types/editor/useEditorState.d.ts.map +1 -0
  573. package/types/index.d.ts +11 -0
  574. package/types/index.d.ts.map +1 -0
  575. package/types/preview.d.ts +44 -0
  576. package/types/preview.d.ts.map +1 -0
  577. package/types/shared/t.d.ts +10 -0
  578. package/types/shared/t.d.ts.map +1 -0
  579. package/types/shared/url.d.ts +9 -0
  580. package/types/shared/url.d.ts.map +1 -0
  581. package/types/styled.d.ts +40 -0
  582. package/types/styled.d.ts.map +1 -0
  583. package/types/toolbar/BubbleToolbar.d.ts +23 -0
  584. package/types/toolbar/BubbleToolbar.d.ts.map +1 -0
  585. package/types/toolbar/CodeBlockBubble.d.ts +10 -0
  586. package/types/toolbar/CodeBlockBubble.d.ts.map +1 -0
  587. package/types/toolbar/ColorPicker.d.ts +15 -0
  588. package/types/toolbar/ColorPicker.d.ts.map +1 -0
  589. package/types/toolbar/ColorPicker.native.d.ts +20 -0
  590. package/types/toolbar/ColorPicker.native.d.ts.map +1 -0
  591. package/types/toolbar/FixedToolbar.d.ts +32 -0
  592. package/types/toolbar/FixedToolbar.d.ts.map +1 -0
  593. package/types/toolbar/FixedToolbar.native.d.ts +30 -0
  594. package/types/toolbar/FixedToolbar.native.d.ts.map +1 -0
  595. package/types/toolbar/HeadingPicker.d.ts +14 -0
  596. package/types/toolbar/HeadingPicker.d.ts.map +1 -0
  597. package/types/toolbar/ImageBubble.d.ts +10 -0
  598. package/types/toolbar/ImageBubble.d.ts.map +1 -0
  599. package/types/toolbar/ImageDialog.d.ts +12 -0
  600. package/types/toolbar/ImageDialog.d.ts.map +1 -0
  601. package/types/toolbar/ImageDialog.native.d.ts +15 -0
  602. package/types/toolbar/ImageDialog.native.d.ts.map +1 -0
  603. package/types/toolbar/LinkBubble.d.ts +10 -0
  604. package/types/toolbar/LinkBubble.d.ts.map +1 -0
  605. package/types/toolbar/LinkDialog.d.ts +20 -0
  606. package/types/toolbar/LinkDialog.d.ts.map +1 -0
  607. package/types/toolbar/LinkDialog.native.d.ts +18 -0
  608. package/types/toolbar/LinkDialog.native.d.ts.map +1 -0
  609. package/types/toolbar/ListPicker.d.ts +14 -0
  610. package/types/toolbar/ListPicker.d.ts.map +1 -0
  611. package/types/toolbar/MathBubble.d.ts +11 -0
  612. package/types/toolbar/MathBubble.d.ts.map +1 -0
  613. package/types/toolbar/MoreDropdown.d.ts +13 -0
  614. package/types/toolbar/MoreDropdown.d.ts.map +1 -0
  615. package/types/toolbar/ResizeHandle.d.ts +11 -0
  616. package/types/toolbar/ResizeHandle.d.ts.map +1 -0
  617. package/types/toolbar/StatusBar.d.ts +11 -0
  618. package/types/toolbar/StatusBar.d.ts.map +1 -0
  619. package/types/toolbar/TableBubble.d.ts +10 -0
  620. package/types/toolbar/TableBubble.d.ts.map +1 -0
  621. package/types/toolbar/ToolbarButton.d.ts +35 -0
  622. package/types/toolbar/ToolbarButton.d.ts.map +1 -0
  623. package/types/toolbar/ToolbarButton.native.d.ts +30 -0
  624. package/types/toolbar/ToolbarButton.native.d.ts.map +1 -0
  625. package/types/toolbar/ToolbarGroup.d.ts +14 -0
  626. package/types/toolbar/ToolbarGroup.d.ts.map +1 -0
  627. package/types/toolbar/icons.d.ts +52 -0
  628. package/types/toolbar/icons.d.ts.map +1 -0
  629. package/types/toolbar/icons.native.d.ts +41 -0
  630. package/types/toolbar/icons.native.d.ts.map +1 -0
  631. package/types/toolbar/shortcuts.d.ts +34 -0
  632. package/types/toolbar/shortcuts.d.ts.map +1 -0
  633. package/types/toolbar/useHorizontalScroll.d.ts +43 -0
  634. package/types/toolbar/useHorizontalScroll.d.ts.map +1 -0
  635. package/types/toolbar/useRovingFocus.d.ts +10 -0
  636. package/types/toolbar/useRovingFocus.d.ts.map +1 -0
  637. package/types/types.d.ts +125 -0
  638. package/types/types.d.ts.map +1 -0
  639. package/dist/cjs/RichEditor.stories.cjs +0 -327
  640. package/dist/cjs/RichEditor.stories.native.js +0 -342
  641. package/dist/cjs/RichEditor.stories.native.js.map +0 -1
  642. package/dist/esm/RichEditor.stories.mjs +0 -291
  643. package/dist/esm/RichEditor.stories.mjs.map +0 -1
  644. package/dist/esm/RichEditor.stories.native.js +0 -303
  645. package/dist/esm/RichEditor.stories.native.js.map +0 -1
  646. package/dist/jsx/RichEditor.stories.mjs +0 -291
  647. package/dist/jsx/RichEditor.stories.mjs.map +0 -1
  648. package/dist/jsx/RichEditor.stories.native.js +0 -342
  649. package/dist/jsx/RichEditor.stories.native.js.map +0 -1
@@ -13,7 +13,14 @@
13
13
  * No BubbleToolbar (10Tap does not support floating menus).
14
14
  */
15
15
 
16
- import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from "react";
16
+ import {
17
+ forwardRef,
18
+ useCallback,
19
+ useEffect,
20
+ useImperativeHandle,
21
+ useRef,
22
+ type ForwardedRef,
23
+ } from "react";
17
24
  import { StyleSheet, useColorScheme } from "react-native";
18
25
  import {
19
26
  RichText,
@@ -29,15 +36,17 @@ import {
29
36
  darkEditorCss,
30
37
  darkEditorTheme,
31
38
  } from "@10play/tentap-editor";
32
- import { View, useThemeName } from "tamagui";
39
+ import { View, useTheme, useThemeName } from "tamagui";
33
40
  import type { RichEditorProps, RichEditorRef, EditorCommand } from "../types";
34
41
  import { RichEditorContext } from "../context";
42
+ import { PALETTE_THEME_TOKENS } from "../constants";
43
+ import { t } from "../shared/t";
35
44
  import { getEditorStateFromBridge } from "./useEditorState";
36
45
 
37
46
  function useNativeEditorDarkMode(): boolean {
38
47
  const themeName = useThemeName();
39
48
  const osScheme = useColorScheme();
40
- if (themeName != null && `${themeName}` !== "") {
49
+ if (themeName) {
41
50
  return String(themeName).startsWith("dark");
42
51
  }
43
52
  return osScheme === "dark";
@@ -47,23 +56,32 @@ function useNativeEditorDarkMode(): boolean {
47
56
  // TentapEditor
48
57
  // ===========================================================================
49
58
 
50
- export const TentapEditor = forwardRef<RichEditorRef, RichEditorProps>(
59
+ export interface TentapEditorProps extends RichEditorProps {
60
+ /** Fill the available space (fullscreen modal) instead of using minHeight */
61
+ fill?: boolean;
62
+ }
63
+
64
+ // Avoid `forwardRef<A, B>(...)` — Metro/Babel TSX can parse the `>` as JSX and
65
+ // throw "Missing initializer in const declaration". Cast instead.
66
+ export const TentapEditor = forwardRef(
51
67
  (
52
68
  {
53
69
  initialContent = "",
54
70
  initialJSON,
55
- placeholder = "Start writing...",
71
+ placeholder: placeholderProp,
56
72
  editable = true,
57
73
  autoFocus = false,
58
74
  onChange,
59
75
  onStateChange,
60
76
  minHeight = 150,
61
77
  maxHeight,
78
+ fill = false,
62
79
  hasError: _hasError,
63
- },
64
- ref,
80
+ }: TentapEditorProps,
81
+ ref: ForwardedRef<RichEditorRef>,
65
82
  ) => {
66
83
  const ctx = RichEditorContext.useStyledContext();
84
+ const placeholder = placeholderProp ?? t("Start writing...");
67
85
  const isDarkMode = useNativeEditorDarkMode();
68
86
  const cachedHtml = useRef<string>("");
69
87
  const cachedJson = useRef<any>(null);
@@ -82,7 +100,9 @@ export const TentapEditor = forwardRef<RichEditorRef, RichEditorProps>(
82
100
  }),
83
101
  ],
84
102
  theme: isDarkMode ? darkEditorTheme : undefined,
85
- initialContent: initialJSON ? JSON.stringify(initialJSON) : initialContent,
103
+ // Tentap accepts HTML string OR a ProseMirror JSON object. Never
104
+ // JSON.stringify the object — that loads as broken HTML and wipes the doc.
105
+ initialContent: (initialJSON as any) ?? initialContent,
86
106
  autofocus: autoFocus,
87
107
  editable,
88
108
  onChange: async () => {
@@ -111,6 +131,22 @@ export const TentapEditor = forwardRef<RichEditorRef, RichEditorProps>(
111
131
  return () => clearTimeout(id);
112
132
  }, [editor, isDarkMode]);
113
133
 
134
+ // Web-authored color/highlight marks store theme custom properties
135
+ // (`var(--red11)`); the 10Tap webview has no tamagui stylesheet, so
136
+ // define the palette vars there from the active theme (Axiom 5: same
137
+ // tokens, resolved once per scheme).
138
+ const theme = useTheme();
139
+ useEffect(() => {
140
+ const id = setTimeout(() => {
141
+ const decls = PALETTE_THEME_TOKENS.map((token) => {
142
+ const value = (theme as any)[token]?.val;
143
+ return value ? `--${token}: ${value};` : "";
144
+ }).join(" ");
145
+ editor.injectCSS(`:root { ${decls} }`, "multiplatform-tentap-palette");
146
+ }, 150);
147
+ return () => clearTimeout(id);
148
+ }, [editor, theme]);
149
+
114
150
  // Subscribe to editor state updates
115
151
  useEffect(() => {
116
152
  const unsubscribe = editor._subscribeToEditorStateUpdate((state: any) => {
@@ -209,13 +245,24 @@ export const TentapEditor = forwardRef<RichEditorRef, RichEditorProps>(
209
245
  break;
210
246
 
211
247
  case "textColor":
212
- if (payload?.color) {
213
- editor.setColor(payload.color);
248
+ // null clears (Default swatch); undefined/missing is a no-op so a
249
+ // bare toolbar tap cannot call setColor(undefined) and wipe content
250
+ // (SB-N-ios-25).
251
+ if (payload && "color" in payload) {
252
+ if (typeof payload.color === "string" && payload.color.length > 0) {
253
+ editor.setColor(payload.color);
254
+ } else {
255
+ editor.unsetColor();
256
+ }
214
257
  }
215
258
  break;
216
259
  case "highlight":
217
- if (payload?.color) {
218
- editor.setHighlight(payload.color);
260
+ if (payload && "color" in payload) {
261
+ if (typeof payload.color === "string" && payload.color.length > 0) {
262
+ editor.setHighlight(payload.color);
263
+ } else {
264
+ editor.unsetHighlight();
265
+ }
219
266
  }
220
267
  break;
221
268
 
@@ -238,7 +285,7 @@ export const TentapEditor = forwardRef<RichEditorRef, RichEditorProps>(
238
285
  getHTML: () => cachedHtml.current,
239
286
  getJSON: () => cachedJson.current,
240
287
  setHTML: (html: string) => editor.setContent(html),
241
- setJSON: (json: any) => editor.setContent(JSON.stringify(json)),
288
+ setJSON: (json: any) => editor.setContent(json),
242
289
  focus: () => editor.focus(),
243
290
  blur: () => editor.blur(),
244
291
  }),
@@ -247,13 +294,14 @@ export const TentapEditor = forwardRef<RichEditorRef, RichEditorProps>(
247
294
 
248
295
  return (
249
296
  <View
250
- minHeight={minHeight}
251
- maxHeight={maxHeight}
252
- backgroundColor={ctx.disabled ? "$color3" : "$color2"}
297
+ flex={fill ? 1 : undefined}
298
+ minHeight={fill ? undefined : minHeight}
299
+ maxHeight={fill ? undefined : maxHeight}
300
+ backgroundColor={ctx.disabled ? "$color3" : fill ? "$background" : "$color2"}
253
301
  overflow="hidden"
254
302
  opacity={ctx.disabled ? 0.5 : 1}
255
303
  >
256
- <RichText editor={editor} style={styles.editor} />
304
+ <RichText editor={editor} style={fill ? styles.editorFill : styles.editor} />
257
305
  </View>
258
306
  );
259
307
  },
@@ -266,4 +314,7 @@ const styles = StyleSheet.create({
266
314
  flex: 1,
267
315
  minHeight: 150,
268
316
  },
317
+ editorFill: {
318
+ flex: 1,
319
+ },
269
320
  });
@@ -13,6 +13,7 @@ import {
13
13
  memo,
14
14
  useCallback,
15
15
  useEffect,
16
+ useId,
16
17
  useImperativeHandle,
17
18
  useMemo,
18
19
  useRef,
@@ -31,35 +32,51 @@ import { Superscript } from "@tiptap/extension-superscript";
31
32
  import TaskList from "@tiptap/extension-task-list";
32
33
  import TaskItem from "@tiptap/extension-task-item";
33
34
  import Image from "@tiptap/extension-image";
34
- import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
35
35
  import Typography from "@tiptap/extension-typography";
36
36
  import CharacterCount from "@tiptap/extension-character-count";
37
+ import { Details, DetailsContent, DetailsSummary } from "@tiptap/extension-details";
37
38
 
38
39
  import { Table } from "@tiptap/extension-table";
39
40
  import { TableRow } from "@tiptap/extension-table-row";
40
41
  import { TableHeader } from "@tiptap/extension-table-header";
41
42
  import { TableCell } from "@tiptap/extension-table-cell";
42
43
  import { common, createLowlight } from "lowlight";
43
- import TurndownService from "turndown";
44
- import { marked } from "marked";
45
- import { View, styled } from "tamagui";
44
+ import { View, getTokens, styled, useTheme, useThemeName } from "tamagui";
46
45
  import { isWeb } from "@tamagui/constants";
46
+ import { menuRowFrame, useResolvedKnobs } from "@multiplatform.one/theme";
47
+ import { clampRadiusForLargeComponent } from "@multiplatform.one/forms";
47
48
  import type { RichEditorProps, RichEditorRef, EditorCommand } from "../types";
48
49
  import { defaultEditorState } from "../types";
49
50
  import { RichEditorContext } from "../context";
51
+ import { t } from "../shared/t";
50
52
  import { getEditorCSS } from "./editorStyles";
51
53
  import { SlashCommands } from "./SlashCommands";
52
54
  import { MarkdownPaste } from "./MarkdownPaste";
53
55
  import { BlockDragHandle } from "./BlockDragHandle";
56
+ import { MediaUpload } from "./media";
57
+ import { createMentionExtension } from "./mentions";
58
+ import { EmojiSuggestion } from "./emoji";
59
+ import { InlineMath } from "./mathematics";
60
+ import { CodeBlockWithPreview, PreviewChromeStore, setPreviewChrome } from "./codeBlockPreview";
61
+ import { htmlToMarkdown, markdownToHtml } from "./markdown";
62
+ import { cleanPastedHtml } from "./pasteCleanup";
63
+ import {
64
+ SuggestionChromeStore,
65
+ fallbackSuggestionChrome,
66
+ type SuggestionChrome,
67
+ } from "./suggestionPopup";
54
68
  import { getEditorStateFromTiptap } from "./useEditorState";
55
69
  import { BubbleToolbar } from "../toolbar/BubbleToolbar";
56
70
  import { LinkBubble } from "../toolbar/LinkBubble";
57
71
  import { CodeBlockBubble } from "../toolbar/CodeBlockBubble";
58
72
  import { ImageBubble } from "../toolbar/ImageBubble";
59
73
  import { TableBubble } from "../toolbar/TableBubble";
74
+ import { MathBubble } from "../toolbar/MathBubble";
60
75
 
61
76
  const lowlight = createLowlight(common);
62
- const turndownService = new TurndownService({ headingStyle: "atx", codeBlockStyle: "fenced" });
77
+
78
+ /** Enter/exit fade for bubbles and suggestion popups (0 when animation none) */
79
+ const MOTION_MS = 120;
63
80
 
64
81
  /**
65
82
  * Tab / Shift-Tab indentation inside code blocks.
@@ -222,6 +239,8 @@ export interface TiptapEditorProps extends RichEditorProps {
222
239
  headingFontFamily?: string;
223
240
  /** Current editing mode: richtext (WYSIWYG) or markdown (raw source) */
224
241
  editorMode?: "richtext" | "markdown";
242
+ /** Fullscreen mode: content fills the flex parent and scrolls internally */
243
+ fullscreen?: boolean;
225
244
  }
226
245
 
227
246
  // ===========================================================================
@@ -245,7 +264,7 @@ export const TiptapEditor = memo(
245
264
  {
246
265
  initialContent = "",
247
266
  initialJSON,
248
- placeholder = "Start writing...",
267
+ placeholder: placeholderProp,
249
268
  editable = true,
250
269
  autoFocus = false,
251
270
  onChange,
@@ -259,10 +278,15 @@ export const TiptapEditor = memo(
259
278
  bodyFontFamily,
260
279
  headingFontFamily,
261
280
  editorMode = "richtext",
281
+ fullscreen = false,
282
+ onImageUpload,
283
+ onFileUpload,
284
+ mentions,
262
285
  },
263
286
  ref,
264
287
  ) => {
265
288
  const _ctx = RichEditorContext.useStyledContext();
289
+ const placeholder = placeholderProp ?? t("Start writing...");
266
290
  const internalRef = useRef<RichEditorRef>(null);
267
291
  const stateRafRef = useRef<number>(0);
268
292
  const changeRafRef = useRef<number>(0);
@@ -270,6 +294,24 @@ export const TiptapEditor = memo(
270
294
  const onChangeRef = useRef(onChange);
271
295
  const [markdownSource, setMarkdownSource] = useState("");
272
296
  const prevModeRef = useRef(editorMode);
297
+ const theme = useTheme();
298
+ const themeName = useThemeName();
299
+ const { knobProps } = useResolvedKnobs();
300
+ const motionMs = knobProps.transition !== undefined ? MOTION_MS : 0;
301
+ const scopeClass = `rt-scope-${useId().replace(/[^a-zA-Z0-9-]/g, "")}`;
302
+
303
+ // Mention wiring is captured at mount (the extension list is fixed);
304
+ // the items function stays live through this ref.
305
+ const mentionsRef = useRef(mentions);
306
+ mentionsRef.current = mentions;
307
+ const [mentionExtension] = useState(() =>
308
+ mentions
309
+ ? createMentionExtension({
310
+ trigger: mentions.trigger,
311
+ items: (query) => mentionsRef.current?.items(query) ?? [],
312
+ })
313
+ : null,
314
+ );
273
315
 
274
316
  useEffect(() => {
275
317
  onStateChangeRef.current = onStateChange;
@@ -302,7 +344,7 @@ export const TiptapEditor = memo(
302
344
  codeBlock: false,
303
345
  hardBreak: false,
304
346
  }),
305
- CodeBlockLowlight.configure({
347
+ CodeBlockWithPreview.configure({
306
348
  lowlight,
307
349
  exitOnTripleEnter: true,
308
350
  exitOnArrowDown: false,
@@ -310,10 +352,30 @@ export const TiptapEditor = memo(
310
352
  ParagraphEnterKeys,
311
353
  CodeBlockTabIndent,
312
354
  ListItemKeys,
313
- Typography,
355
+ // superscriptTwo/Three would mangle typed TeX (`$E=mc^2$` became
356
+ // `E=mc²` before the math input rule ran) — off, rest stays.
357
+ Typography.configure({
358
+ superscriptTwo: false,
359
+ superscriptThree: false,
360
+ }),
314
361
  CharacterCount,
315
362
  SlashCommands,
316
363
  MarkdownPaste,
364
+ MediaUpload,
365
+ SuggestionChromeStore,
366
+ PreviewChromeStore,
367
+ EmojiSuggestion,
368
+ InlineMath,
369
+ // Collapsible sections (GitLab <details> parity). persist: true
370
+ // is the extension's supported mode: its node view re-syncs the
371
+ // open state from node.attrs on every update, so ephemeral
372
+ // (persist: false) toggles get reverted by the next transaction.
373
+ // The open state therefore lives in the doc and serializes as
374
+ // `<details open>` — valid GitLab markdown.
375
+ Details.configure({ persist: true }),
376
+ DetailsSummary,
377
+ DetailsContent,
378
+ ...(mentionExtension ? [mentionExtension] : []),
317
379
  BlockDragHandle,
318
380
  Table.configure({ resizable: true }),
319
381
  TableRow,
@@ -345,6 +407,17 @@ export const TiptapEditor = memo(
345
407
  content: initialJSON || initialContent,
346
408
  editable,
347
409
  autofocus: autoFocus,
410
+ // No htmlFor target exists for the contenteditable — name it directly
411
+ // (axe aria-input-field-name); placeholder doubles as the name.
412
+ editorProps: {
413
+ attributes: {
414
+ role: "textbox",
415
+ "aria-multiline": "true",
416
+ "aria-label": placeholder || t("Rich text editor"),
417
+ },
418
+ // Strip Google Docs / Word clipboard junk before ProseMirror parses
419
+ transformPastedHTML: cleanPastedHtml,
420
+ },
348
421
  injectCSS: false,
349
422
  immediatelyRender: false,
350
423
  shouldRerenderOnTransaction: false,
@@ -366,24 +439,76 @@ export const TiptapEditor = memo(
366
439
  onBlur: () => onBlur?.(),
367
440
  });
368
441
 
442
+ // Keep upload handlers live in editor storage (paste/drop + slash image)
443
+ useEffect(() => {
444
+ if (!editor) return;
445
+ editor.storage.mediaUpload.handlers = { onImageUpload, onFileUpload };
446
+ }, [editor, onImageUpload, onFileUpload]);
447
+
448
+ // Push resolved theme + knob chrome for the DOM-portaled suggestion
449
+ // popups (slash / mention): every color and structural role arrives
450
+ // resolved -- the popups never invent their own values.
451
+ useEffect(() => {
452
+ if (!editor) return;
453
+ const radiusToken = clampRadiusForLargeComponent(knobProps.borderRadius.borderRadius, 4);
454
+ const radiusValue =
455
+ typeof radiusToken === "number"
456
+ ? radiusToken
457
+ : ((getTokens().radius as any)?.[radiusToken]?.val ?? fallbackSuggestionChrome.radius);
458
+ // LC-16: the DOM popup rows share menuRowFrame geometry — resolve
459
+ // its paddingHorizontal token to px here (theme scope) and push it.
460
+ const rowPadToken = menuRowFrame.paddingHorizontal as string;
461
+ const rowPaddingX =
462
+ (getTokens().space as any)?.[rowPadToken]?.val ?? fallbackSuggestionChrome.rowPaddingX;
463
+ // Elevation rides the theme's scheme-aware shadow tokens (Axiom 5) —
464
+ // the same channel the popover family resolves, never a raw rgba.
465
+ const shadowMain = theme.shadow2?.val;
466
+ const shadowSoft = theme.shadow1?.val;
467
+ const chrome: SuggestionChrome = {
468
+ background: theme.background?.val ?? fallbackSuggestionChrome.background,
469
+ borderColor: theme.borderColor?.val ?? fallbackSuggestionChrome.borderColor,
470
+ activeBackground: theme.color4?.val ?? fallbackSuggestionChrome.activeBackground,
471
+ iconTileBackground: theme.color3?.val ?? fallbackSuggestionChrome.iconTileBackground,
472
+ titleColor: theme.color12?.val ?? fallbackSuggestionChrome.titleColor,
473
+ descriptionColor: theme.color11?.val ?? fallbackSuggestionChrome.descriptionColor,
474
+ radius: typeof radiusValue === "number" ? radiusValue : fallbackSuggestionChrome.radius,
475
+ shadow:
476
+ shadowMain && shadowSoft
477
+ ? `0px 8px 28px ${shadowMain}, 0px 2px 6px ${shadowSoft}`
478
+ : fallbackSuggestionChrome.shadow,
479
+ motionMs,
480
+ rowPaddingX:
481
+ typeof rowPaddingX === "number" ? rowPaddingX : fallbackSuggestionChrome.rowPaddingX,
482
+ };
483
+ editor.storage.suggestionChrome.value = chrome;
484
+ }, [editor, theme, knobProps.borderRadius.borderRadius, motionMs]);
485
+
486
+ // Push the resolved color scheme for block previews (mermaid/math):
487
+ // the node views subscribe and re-render diagrams on a theme flip.
488
+ useEffect(() => {
489
+ if (!editor) return;
490
+ setPreviewChrome(editor, {
491
+ scheme: String(themeName).startsWith("dark") ? "dark" : "light",
492
+ fontFamily: bodyFontFamily,
493
+ });
494
+ }, [editor, themeName, bodyFontFamily]);
495
+
369
496
  useEffect(() => {
370
497
  if (!editor) return;
371
498
  if (prevModeRef.current === editorMode) return;
372
499
  prevModeRef.current = editorMode;
373
500
 
374
501
  if (editorMode === "markdown") {
375
- setMarkdownSource(turndownService.turndown(editor.getHTML()));
502
+ setMarkdownSource(htmlToMarkdown(editor.getHTML()));
376
503
  } else {
377
- const html = marked.parse(markdownSource, { async: false }) as string;
378
- editor.commands.setContent(html);
504
+ editor.commands.setContent(markdownToHtml(markdownSource));
379
505
  }
380
506
  }, [editorMode, editor, markdownSource]);
381
507
 
382
508
  const handleMarkdownChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
383
509
  const md = e.target.value;
384
510
  setMarkdownSource(md);
385
- const html = marked.parse(md, { async: false }) as string;
386
- onChangeRef.current?.(html, null);
511
+ onChangeRef.current?.(markdownToHtml(md), null);
387
512
  }, []);
388
513
 
389
514
  const executeCommand = useCallback(
@@ -457,9 +582,22 @@ export const TiptapEditor = memo(
457
582
  break;
458
583
  case "link":
459
584
  if (payload?.href) {
460
- chain.setLink({ href: payload.href }).run();
585
+ if (editor.state.selection.empty && !editor.isActive("link")) {
586
+ // GitLab parity: with nothing selected, insert the URL
587
+ // itself as linked text instead of silently no-oping
588
+ chain
589
+ .insertContent({
590
+ type: "text",
591
+ text: payload.text ?? payload.href,
592
+ marks: [{ type: "link", attrs: { href: payload.href } }],
593
+ })
594
+ .run();
595
+ } else {
596
+ // Cursor inside an existing link updates the whole link
597
+ chain.extendMarkRange("link").setLink({ href: payload.href }).run();
598
+ }
461
599
  } else {
462
- chain.unsetLink().run();
600
+ chain.extendMarkRange("link").unsetLink().run();
463
601
  }
464
602
  break;
465
603
  case "undo":
@@ -562,20 +700,35 @@ export const TiptapEditor = memo(
562
700
  (internalRef as any).current = refMethods;
563
701
 
564
702
  const editorCSS = useMemo(
565
- () => getEditorCSS({ minHeight, maxHeight, bodyFontFamily, headingFontFamily }),
566
- [minHeight, maxHeight, bodyFontFamily, headingFontFamily],
703
+ () =>
704
+ getEditorCSS({
705
+ minHeight,
706
+ maxHeight,
707
+ bodyFontFamily,
708
+ headingFontFamily,
709
+ fullscreen,
710
+ motionMs,
711
+ scopeClass,
712
+ }),
713
+ [minHeight, maxHeight, bodyFontFamily, headingFontFamily, fullscreen, motionMs, scopeClass],
567
714
  );
568
715
 
569
716
  if (editorMode === "markdown") {
570
717
  return (
571
- <EditorContainer minHeight={minHeight} maxHeight={maxHeight} overflow="hidden">
718
+ <EditorContainer
719
+ minHeight={fullscreen ? 0 : minHeight}
720
+ maxHeight={fullscreen ? undefined : maxHeight}
721
+ overflow="hidden"
722
+ >
572
723
  <textarea
573
724
  value={markdownSource}
574
725
  onChange={handleMarkdownChange}
726
+ aria-label={t("Markdown source")}
575
727
  style={{
576
728
  width: "100%",
577
- minHeight: minHeight,
578
- maxHeight: maxHeight || undefined,
729
+ minHeight: fullscreen ? 0 : minHeight,
730
+ maxHeight: fullscreen ? undefined : maxHeight || undefined,
731
+ flex: fullscreen ? "1 1 0%" : undefined,
579
732
  padding: "12px 12px 12px 16px",
580
733
  border: "none",
581
734
  outline: "none",
@@ -595,7 +748,12 @@ export const TiptapEditor = memo(
595
748
  }
596
749
 
597
750
  return (
598
- <EditorContainer minHeight={minHeight} maxHeight={maxHeight} overflow="hidden">
751
+ <EditorContainer
752
+ className={scopeClass}
753
+ minHeight={fullscreen ? 0 : minHeight}
754
+ maxHeight={fullscreen ? undefined : maxHeight}
755
+ overflow="hidden"
756
+ >
599
757
  {isWeb && <style>{editorCSS}</style>}
600
758
  {showBubbleToolbar && (
601
759
  <>
@@ -606,7 +764,14 @@ export const TiptapEditor = memo(
606
764
  <TableBubble editor={editor} />
607
765
  </>
608
766
  )}
609
- <EditorContent editor={editor} />
767
+ {/* Always mounted (unlike the optional bubbles): it is the ONLY
768
+ edit path for inline math atoms — without it a typed `$x$`
769
+ node would be a dead end. */}
770
+ {editable && <MathBubble editor={editor} />}
771
+ <EditorContent
772
+ editor={editor}
773
+ style={fullscreen ? { flex: "1 1 0%", minHeight: 0, overflowY: "auto" } : undefined}
774
+ />
610
775
  </EditorContainer>
611
776
  );
612
777
  },
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Block-rect bubble anchoring against a headless Tiptap editor.
3
+ */
4
+
5
+ import { describe, expect, it } from "vitest";
6
+ import { Editor } from "@tiptap/core";
7
+ import StarterKit from "@tiptap/starter-kit";
8
+ import { Table } from "@tiptap/extension-table";
9
+ import { TableRow } from "@tiptap/extension-table-row";
10
+ import { TableHeader } from "@tiptap/extension-table-header";
11
+ import { TableCell } from "@tiptap/extension-table-cell";
12
+ import { TextSelection } from "@tiptap/pm/state";
13
+ import { getBlockVirtualElement } from "./blockAnchor";
14
+
15
+ function createEditor(content: string) {
16
+ return new Editor({
17
+ element: document.createElement("div"),
18
+ extensions: [StarterKit, Table, TableRow, TableHeader, TableCell],
19
+ content,
20
+ });
21
+ }
22
+
23
+ /** Places the text cursor inside the first node of the given type */
24
+ function placeCursorIn(editor: Editor, nodeTypeName: string) {
25
+ let target = -1;
26
+ editor.state.doc.descendants((node, pos) => {
27
+ if (target === -1 && node.type.name === nodeTypeName) target = pos + 1;
28
+ return target === -1;
29
+ });
30
+ if (target === -1) throw new Error(`no ${nodeTypeName} in doc`);
31
+ const selection = TextSelection.near(editor.state.doc.resolve(target + 1));
32
+ editor.view.dispatch(editor.state.tr.setSelection(selection));
33
+ }
34
+
35
+ describe("getBlockVirtualElement", () => {
36
+ it("returns the table DOM element when the cursor is inside a table", () => {
37
+ const editor = createEditor(
38
+ "<p>before</p><table><tr><th>h</th></tr><tr><td>cell</td></tr></table>",
39
+ );
40
+ placeCursorIn(editor, "table");
41
+
42
+ const ref = getBlockVirtualElement(editor, "table");
43
+ expect(ref).not.toBeNull();
44
+ expect((ref!.contextElement as HTMLElement).tagName).toBe("TABLE");
45
+ // The anchor rect delegates to the block's live rect
46
+ expect(typeof ref!.getBoundingClientRect().width).toBe("number");
47
+ editor.destroy();
48
+ });
49
+
50
+ it("returns the pre element when the cursor is inside a code block", () => {
51
+ const editor = createEditor("<p>before</p><pre><code>const a = 1;</code></pre>");
52
+ placeCursorIn(editor, "codeBlock");
53
+
54
+ const ref = getBlockVirtualElement(editor, "codeBlock");
55
+ expect(ref).not.toBeNull();
56
+ expect((ref!.contextElement as HTMLElement).tagName).toBe("PRE");
57
+ editor.destroy();
58
+ });
59
+
60
+ it("returns null when the selection is outside the block type", () => {
61
+ const editor = createEditor("<p>plain paragraph</p><table><tr><td>cell</td></tr></table>");
62
+ // Cursor starts in the first paragraph by default
63
+ const selection = TextSelection.near(editor.state.doc.resolve(1));
64
+ editor.view.dispatch(editor.state.tr.setSelection(selection));
65
+
66
+ expect(getBlockVirtualElement(editor, "table")).toBeNull();
67
+ expect(getBlockVirtualElement(editor, "codeBlock")).toBeNull();
68
+ editor.destroy();
69
+ });
70
+ });
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Block-rect anchoring for bubble menus (web).
3
+ *
4
+ * Tiptap's BubbleMenu anchors to the text caret by default. For tall blocks
5
+ * (tables, code blocks) that puts the bubble INSIDE the block box — hovering
6
+ * over the first table row / first code line, where it traps pointer events
7
+ * and chases the caret on every keystroke. Anchoring to the block's own DOM
8
+ * rect keeps the bubble outside the block (above it, or flipped below by
9
+ * floating-ui), so block content stays clickable and the bubble holds still
10
+ * while typing. GitLab's content editor anchors its table/code chrome the
11
+ * same way.
12
+ */
13
+
14
+ import type { Editor } from "@tiptap/core";
15
+
16
+ interface BlockVirtualElement {
17
+ getBoundingClientRect: () => DOMRect;
18
+ contextElement: Element;
19
+ }
20
+
21
+ /**
22
+ * Returns a floating-ui VirtualElement for the nearest ancestor node of
23
+ * `nodeTypeName` containing the selection, or null when the selection is
24
+ * not inside one (the bubble is hidden by `shouldShow` in that case).
25
+ */
26
+ export function getBlockVirtualElement(
27
+ editor: Editor,
28
+ nodeTypeName: string,
29
+ ): BlockVirtualElement | null {
30
+ const { $from } = editor.state.selection;
31
+ for (let depth = $from.depth; depth > 0; depth--) {
32
+ if ($from.node(depth).type.name !== nodeTypeName) continue;
33
+ const dom = editor.view.nodeDOM($from.before(depth));
34
+ if (dom instanceof HTMLElement) {
35
+ return {
36
+ getBoundingClientRect: () => dom.getBoundingClientRect(),
37
+ contextElement: dom,
38
+ };
39
+ }
40
+ }
41
+ return null;
42
+ }