rayo-editor 0.0.1 → 0.0.3

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 (463) hide show
  1. package/README.md +563 -563
  2. package/dist/cloudinaryUpload-16fe0b7d.js +35 -0
  3. package/dist/components/project/blog-writer/hooks/useAutoRecovery.d.ts +63 -0
  4. package/dist/components/project/blog-writer/hooks/useAutoRecovery.d.ts.map +1 -0
  5. package/dist/components/project/blog-writer/hooks/useTypingEffect.d.ts +5 -0
  6. package/dist/components/project/blog-writer/hooks/useTypingEffect.d.ts.map +1 -0
  7. package/dist/components/project/blog-writer/index.d.ts +2 -0
  8. package/dist/components/project/blog-writer/index.d.ts.map +1 -0
  9. package/dist/components/project/blog-writer/shared/BlogEditor.d.ts +57 -0
  10. package/dist/components/project/blog-writer/shared/BlogEditor.d.ts.map +1 -0
  11. package/dist/components/project/blog-writer/shared/BlogMinimap.d.ts +36 -0
  12. package/dist/components/project/blog-writer/shared/BlogMinimap.d.ts.map +1 -0
  13. package/dist/components/project/blog-writer/shared/EditorErrorFallback.d.ts +8 -0
  14. package/dist/components/project/blog-writer/shared/EditorErrorFallback.d.ts.map +1 -0
  15. package/dist/components/project/blog-writer/shared/ImageGallery.d.ts +3 -0
  16. package/dist/components/project/blog-writer/shared/ImageGallery.d.ts.map +1 -0
  17. package/dist/components/project/blog-writer/shared/ImageGenerationLoader.d.ts +8 -0
  18. package/dist/components/project/blog-writer/shared/ImageGenerationLoader.d.ts.map +1 -0
  19. package/dist/components/project/blog-writer/shared/SkeletonEditor.d.ts +12 -0
  20. package/dist/components/project/blog-writer/shared/SkeletonEditor.d.ts.map +1 -0
  21. package/dist/components/project/blog-writer/shared/StreamingProgressOverlay.d.ts +9 -0
  22. package/dist/components/project/blog-writer/shared/StreamingProgressOverlay.d.ts.map +1 -0
  23. package/dist/components/project/blog-writer/shared/__tests__/AgentChatPanel.perf.test.d.ts +14 -0
  24. package/dist/components/project/blog-writer/shared/__tests__/AgentChatPanel.perf.test.d.ts.map +1 -0
  25. package/dist/components/project/blog-writer/shared/__tests__/BlogEditor.perf.test.d.ts +14 -0
  26. package/dist/components/project/blog-writer/shared/__tests__/BlogEditor.perf.test.d.ts.map +1 -0
  27. package/dist/components/project/blog-writer/shared/wordCountUtils.d.ts +30 -0
  28. package/dist/components/project/blog-writer/shared/wordCountUtils.d.ts.map +1 -0
  29. package/dist/components/shared/editor/CustomEditorSkeleton.d.ts +3 -0
  30. package/dist/components/shared/editor/CustomEditorSkeleton.d.ts.map +1 -0
  31. package/dist/components/tiptap-extension/ari-score-extension.d.ts +6 -0
  32. package/dist/components/tiptap-extension/ari-score-extension.d.ts.map +1 -0
  33. package/dist/components/tiptap-extension/code-block-extension.d.ts +7 -0
  34. package/dist/components/tiptap-extension/code-block-extension.d.ts.map +1 -0
  35. package/dist/components/tiptap-extension/diff-marks-extension.d.ts +4 -0
  36. package/dist/components/tiptap-extension/diff-marks-extension.d.ts.map +1 -0
  37. package/dist/components/tiptap-extension/drag-handle-extension.d.ts +16 -0
  38. package/dist/components/tiptap-extension/drag-handle-extension.d.ts.map +1 -0
  39. package/dist/components/tiptap-extension/instagram-extension.d.ts +26 -0
  40. package/dist/components/tiptap-extension/instagram-extension.d.ts.map +1 -0
  41. package/dist/components/tiptap-extension/link-extension.d.ts +3 -0
  42. package/dist/components/tiptap-extension/link-extension.d.ts.map +1 -0
  43. package/dist/components/tiptap-extension/reference-manager-extension.d.ts +17 -0
  44. package/dist/components/tiptap-extension/reference-manager-extension.d.ts.map +1 -0
  45. package/dist/components/tiptap-extension/resizable-image-extension.d.ts +2 -0
  46. package/dist/components/tiptap-extension/resizable-image-extension.d.ts.map +1 -0
  47. package/dist/components/tiptap-extension/selection-extension.d.ts +4 -0
  48. package/dist/components/tiptap-extension/selection-extension.d.ts.map +1 -0
  49. package/dist/components/tiptap-extension/table-extension.d.ts +10 -0
  50. package/dist/components/tiptap-extension/table-extension.d.ts.map +1 -0
  51. package/dist/components/tiptap-extension/trailing-node-extension.d.ts +8 -0
  52. package/dist/components/tiptap-extension/trailing-node-extension.d.ts.map +1 -0
  53. package/dist/components/tiptap-extension/x-extension.d.ts +26 -0
  54. package/dist/components/tiptap-extension/x-extension.d.ts.map +1 -0
  55. package/dist/components/tiptap-extension/youtube-extension.d.ts +42 -0
  56. package/dist/components/tiptap-extension/youtube-extension.d.ts.map +1 -0
  57. package/dist/components/tiptap-icons/align-center-icon.d.ts +3 -0
  58. package/dist/components/tiptap-icons/align-center-icon.d.ts.map +1 -0
  59. package/dist/components/tiptap-icons/align-justify-icon.d.ts +3 -0
  60. package/dist/components/tiptap-icons/align-justify-icon.d.ts.map +1 -0
  61. package/dist/components/tiptap-icons/align-left-icon.d.ts +3 -0
  62. package/dist/components/tiptap-icons/align-left-icon.d.ts.map +1 -0
  63. package/dist/components/tiptap-icons/align-right-icon.d.ts +3 -0
  64. package/dist/components/tiptap-icons/align-right-icon.d.ts.map +1 -0
  65. package/dist/components/tiptap-icons/arrow-left-icon.d.ts +3 -0
  66. package/dist/components/tiptap-icons/arrow-left-icon.d.ts.map +1 -0
  67. package/dist/components/tiptap-icons/ban-icon.d.ts +3 -0
  68. package/dist/components/tiptap-icons/ban-icon.d.ts.map +1 -0
  69. package/dist/components/tiptap-icons/block-quote-icon.d.ts +3 -0
  70. package/dist/components/tiptap-icons/block-quote-icon.d.ts.map +1 -0
  71. package/dist/components/tiptap-icons/bold-icon.d.ts +3 -0
  72. package/dist/components/tiptap-icons/bold-icon.d.ts.map +1 -0
  73. package/dist/components/tiptap-icons/check-icon.d.ts +3 -0
  74. package/dist/components/tiptap-icons/check-icon.d.ts.map +1 -0
  75. package/dist/components/tiptap-icons/chevron-down-icon.d.ts +3 -0
  76. package/dist/components/tiptap-icons/chevron-down-icon.d.ts.map +1 -0
  77. package/dist/components/tiptap-icons/close-icon.d.ts +3 -0
  78. package/dist/components/tiptap-icons/close-icon.d.ts.map +1 -0
  79. package/dist/components/tiptap-icons/code-block-icon.d.ts +3 -0
  80. package/dist/components/tiptap-icons/code-block-icon.d.ts.map +1 -0
  81. package/dist/components/tiptap-icons/code2-icon.d.ts +3 -0
  82. package/dist/components/tiptap-icons/code2-icon.d.ts.map +1 -0
  83. package/dist/components/tiptap-icons/corner-down-left-icon.d.ts +3 -0
  84. package/dist/components/tiptap-icons/corner-down-left-icon.d.ts.map +1 -0
  85. package/dist/components/tiptap-icons/edit-icon.d.ts +3 -0
  86. package/dist/components/tiptap-icons/edit-icon.d.ts.map +1 -0
  87. package/dist/components/tiptap-icons/external-link-icon.d.ts +3 -0
  88. package/dist/components/tiptap-icons/external-link-icon.d.ts.map +1 -0
  89. package/dist/components/tiptap-icons/heading-five-icon.d.ts +3 -0
  90. package/dist/components/tiptap-icons/heading-five-icon.d.ts.map +1 -0
  91. package/dist/components/tiptap-icons/heading-four-icon.d.ts +3 -0
  92. package/dist/components/tiptap-icons/heading-four-icon.d.ts.map +1 -0
  93. package/dist/components/tiptap-icons/heading-icon.d.ts +3 -0
  94. package/dist/components/tiptap-icons/heading-icon.d.ts.map +1 -0
  95. package/dist/components/tiptap-icons/heading-one-icon.d.ts +3 -0
  96. package/dist/components/tiptap-icons/heading-one-icon.d.ts.map +1 -0
  97. package/dist/components/tiptap-icons/heading-six-icon.d.ts +3 -0
  98. package/dist/components/tiptap-icons/heading-six-icon.d.ts.map +1 -0
  99. package/dist/components/tiptap-icons/heading-three-icon.d.ts +3 -0
  100. package/dist/components/tiptap-icons/heading-three-icon.d.ts.map +1 -0
  101. package/dist/components/tiptap-icons/heading-two-icon.d.ts +3 -0
  102. package/dist/components/tiptap-icons/heading-two-icon.d.ts.map +1 -0
  103. package/dist/components/tiptap-icons/highlighter-icon.d.ts +3 -0
  104. package/dist/components/tiptap-icons/highlighter-icon.d.ts.map +1 -0
  105. package/dist/components/tiptap-icons/image-plus-icon.d.ts +3 -0
  106. package/dist/components/tiptap-icons/image-plus-icon.d.ts.map +1 -0
  107. package/dist/components/tiptap-icons/italic-icon.d.ts +3 -0
  108. package/dist/components/tiptap-icons/italic-icon.d.ts.map +1 -0
  109. package/dist/components/tiptap-icons/link-icon.d.ts +3 -0
  110. package/dist/components/tiptap-icons/link-icon.d.ts.map +1 -0
  111. package/dist/components/tiptap-icons/list-icon.d.ts +3 -0
  112. package/dist/components/tiptap-icons/list-icon.d.ts.map +1 -0
  113. package/dist/components/tiptap-icons/list-ordered-icon.d.ts +3 -0
  114. package/dist/components/tiptap-icons/list-ordered-icon.d.ts.map +1 -0
  115. package/dist/components/tiptap-icons/list-todo-icon.d.ts +3 -0
  116. package/dist/components/tiptap-icons/list-todo-icon.d.ts.map +1 -0
  117. package/dist/components/tiptap-icons/magic-icon.d.ts +5 -0
  118. package/dist/components/tiptap-icons/magic-icon.d.ts.map +1 -0
  119. package/dist/components/tiptap-icons/moon-star-icon.d.ts +3 -0
  120. package/dist/components/tiptap-icons/moon-star-icon.d.ts.map +1 -0
  121. package/dist/components/tiptap-icons/redo2-icon.d.ts +3 -0
  122. package/dist/components/tiptap-icons/redo2-icon.d.ts.map +1 -0
  123. package/dist/components/tiptap-icons/strike-icon.d.ts +3 -0
  124. package/dist/components/tiptap-icons/strike-icon.d.ts.map +1 -0
  125. package/dist/components/tiptap-icons/subscript-icon.d.ts +3 -0
  126. package/dist/components/tiptap-icons/subscript-icon.d.ts.map +1 -0
  127. package/dist/components/tiptap-icons/sun-icon.d.ts +3 -0
  128. package/dist/components/tiptap-icons/sun-icon.d.ts.map +1 -0
  129. package/dist/components/tiptap-icons/superscript-icon.d.ts +3 -0
  130. package/dist/components/tiptap-icons/superscript-icon.d.ts.map +1 -0
  131. package/dist/components/tiptap-icons/table-icon.d.ts +3 -0
  132. package/dist/components/tiptap-icons/table-icon.d.ts.map +1 -0
  133. package/dist/components/tiptap-icons/trash-icon.d.ts +3 -0
  134. package/dist/components/tiptap-icons/trash-icon.d.ts.map +1 -0
  135. package/dist/components/tiptap-icons/underline-icon.d.ts +3 -0
  136. package/dist/components/tiptap-icons/underline-icon.d.ts.map +1 -0
  137. package/dist/components/tiptap-icons/undo2-icon.d.ts +3 -0
  138. package/dist/components/tiptap-icons/undo2-icon.d.ts.map +1 -0
  139. package/dist/components/tiptap-icons/x-icon.d.ts +3 -0
  140. package/dist/components/tiptap-icons/x-icon.d.ts.map +1 -0
  141. package/dist/components/tiptap-node/image-upload-node/image-upload-node-extension.d.ts +47 -0
  142. package/dist/components/tiptap-node/image-upload-node/image-upload-node-extension.d.ts.map +1 -0
  143. package/dist/components/tiptap-node/image-upload-node/image-upload-node.d.ts +12 -0
  144. package/dist/components/tiptap-node/image-upload-node/image-upload-node.d.ts.map +1 -0
  145. package/dist/components/tiptap-node/image-upload-node/index.d.ts +2 -0
  146. package/dist/components/tiptap-node/image-upload-node/index.d.ts.map +1 -0
  147. package/dist/components/tiptap-node/resizable-image-node/image-cropper.d.ts +10 -0
  148. package/dist/components/tiptap-node/resizable-image-node/image-cropper.d.ts.map +1 -0
  149. package/dist/components/tiptap-node/resizable-image-node/resizable-image-node.d.ts +4 -0
  150. package/dist/components/tiptap-node/resizable-image-node/resizable-image-node.d.ts.map +1 -0
  151. package/dist/components/tiptap-templates/simple/blog-simple-editor.d.ts +62 -0
  152. package/dist/components/tiptap-templates/simple/blog-simple-editor.d.ts.map +1 -0
  153. package/dist/components/tiptap-templates/simple/demo-animated-editor.d.ts +2 -0
  154. package/dist/components/tiptap-templates/simple/demo-animated-editor.d.ts.map +1 -0
  155. package/dist/components/tiptap-templates/simple/link-bubble.d.ts +9 -0
  156. package/dist/components/tiptap-templates/simple/link-bubble.d.ts.map +1 -0
  157. package/dist/components/tiptap-templates/simple/simple-editor-animated.d.ts +2 -0
  158. package/dist/components/tiptap-templates/simple/simple-editor-animated.d.ts.map +1 -0
  159. package/dist/components/tiptap-templates/simple/simple-editor.d.ts +13 -0
  160. package/dist/components/tiptap-templates/simple/simple-editor.d.ts.map +1 -0
  161. package/dist/components/tiptap-templates/simple/table-bubble.d.ts +7 -0
  162. package/dist/components/tiptap-templates/simple/table-bubble.d.ts.map +1 -0
  163. package/dist/components/tiptap-templates/simple/text-selection-bubble.d.ts +8 -0
  164. package/dist/components/tiptap-templates/simple/text-selection-bubble.d.ts.map +1 -0
  165. package/dist/components/tiptap-templates/simple/theme-toggle.d.ts +2 -0
  166. package/dist/components/tiptap-templates/simple/theme-toggle.d.ts.map +1 -0
  167. package/dist/components/tiptap-ui/ai/AIBubbleMenu.d.ts +8 -0
  168. package/dist/components/tiptap-ui/ai/AIBubbleMenu.d.ts.map +1 -0
  169. package/dist/components/tiptap-ui/ai/AICompletionCommands.d.ts +10 -0
  170. package/dist/components/tiptap-ui/ai/AICompletionCommands.d.ts.map +1 -0
  171. package/dist/components/tiptap-ui/ai/AIInput.d.ts +12 -0
  172. package/dist/components/tiptap-ui/ai/AIInput.d.ts.map +1 -0
  173. package/dist/components/tiptap-ui/ai/AISelector.d.ts +10 -0
  174. package/dist/components/tiptap-ui/ai/AISelector.d.ts.map +1 -0
  175. package/dist/components/tiptap-ui/ai/AISelectorCommands.d.ts +9 -0
  176. package/dist/components/tiptap-ui/ai/AISelectorCommands.d.ts.map +1 -0
  177. package/dist/components/tiptap-ui/ai/GenerativeMenuSwitch.d.ts +13 -0
  178. package/dist/components/tiptap-ui/ai/GenerativeMenuSwitch.d.ts.map +1 -0
  179. package/dist/components/tiptap-ui/ai/LinkSelector.d.ts +18 -0
  180. package/dist/components/tiptap-ui/ai/LinkSelector.d.ts.map +1 -0
  181. package/dist/components/tiptap-ui/ai/TextButtons.d.ts +10 -0
  182. package/dist/components/tiptap-ui/ai/TextButtons.d.ts.map +1 -0
  183. package/dist/components/tiptap-ui/ai/ai-request-context.d.ts +14 -0
  184. package/dist/components/tiptap-ui/ai/ai-request-context.d.ts.map +1 -0
  185. package/dist/components/tiptap-ui/ai/useAICompletion.d.ts +25 -0
  186. package/dist/components/tiptap-ui/ai/useAICompletion.d.ts.map +1 -0
  187. package/dist/components/tiptap-ui/blockquote-button/blockquote-button.d.ts +43 -0
  188. package/dist/components/tiptap-ui/blockquote-button/blockquote-button.d.ts.map +1 -0
  189. package/dist/components/tiptap-ui/blockquote-button/index.d.ts +2 -0
  190. package/dist/components/tiptap-ui/blockquote-button/index.d.ts.map +1 -0
  191. package/dist/components/tiptap-ui/code-block-button/code-block-button.d.ts +43 -0
  192. package/dist/components/tiptap-ui/code-block-button/code-block-button.d.ts.map +1 -0
  193. package/dist/components/tiptap-ui/code-block-button/index.d.ts +2 -0
  194. package/dist/components/tiptap-ui/code-block-button/index.d.ts.map +1 -0
  195. package/dist/components/tiptap-ui/color-highlight-button/color-highlight-button.d.ts +78 -0
  196. package/dist/components/tiptap-ui/color-highlight-button/color-highlight-button.d.ts.map +1 -0
  197. package/dist/components/tiptap-ui/color-highlight-button/index.d.ts +2 -0
  198. package/dist/components/tiptap-ui/color-highlight-button/index.d.ts.map +1 -0
  199. package/dist/components/tiptap-ui/color-highlight-popover/color-highlight-popover.d.ts +29 -0
  200. package/dist/components/tiptap-ui/color-highlight-popover/color-highlight-popover.d.ts.map +1 -0
  201. package/dist/components/tiptap-ui/color-highlight-popover/index.d.ts +2 -0
  202. package/dist/components/tiptap-ui/color-highlight-popover/index.d.ts.map +1 -0
  203. package/dist/components/tiptap-ui/drag-handle/drag-handle.d.ts +8 -0
  204. package/dist/components/tiptap-ui/drag-handle/drag-handle.d.ts.map +1 -0
  205. package/dist/components/tiptap-ui/drag-handle/index.d.ts +3 -0
  206. package/dist/components/tiptap-ui/drag-handle/index.d.ts.map +1 -0
  207. package/dist/components/tiptap-ui/font-family-dropdown/font-family-dropdown.d.ts +43 -0
  208. package/dist/components/tiptap-ui/font-family-dropdown/font-family-dropdown.d.ts.map +1 -0
  209. package/dist/components/tiptap-ui/font-family-dropdown/index.d.ts +2 -0
  210. package/dist/components/tiptap-ui/font-family-dropdown/index.d.ts.map +1 -0
  211. package/dist/components/tiptap-ui/font-family-dropdown-menu/font-family-dropdown-menu.d.ts +10 -0
  212. package/dist/components/tiptap-ui/font-family-dropdown-menu/font-family-dropdown-menu.d.ts.map +1 -0
  213. package/dist/components/tiptap-ui/font-family-dropdown-menu/index.d.ts +2 -0
  214. package/dist/components/tiptap-ui/font-family-dropdown-menu/index.d.ts.map +1 -0
  215. package/dist/components/tiptap-ui/heading-button/heading-button.d.ts +56 -0
  216. package/dist/components/tiptap-ui/heading-button/heading-button.d.ts.map +1 -0
  217. package/dist/components/tiptap-ui/heading-button/index.d.ts +2 -0
  218. package/dist/components/tiptap-ui/heading-button/index.d.ts.map +1 -0
  219. package/dist/components/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.d.ts +13 -0
  220. package/dist/components/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.d.ts.map +1 -0
  221. package/dist/components/tiptap-ui/heading-dropdown-menu/index.d.ts +2 -0
  222. package/dist/components/tiptap-ui/heading-dropdown-menu/index.d.ts.map +1 -0
  223. package/dist/components/tiptap-ui/image-gallery/ImageGalleryDialog.d.ts +34 -0
  224. package/dist/components/tiptap-ui/image-gallery/ImageGalleryDialog.d.ts.map +1 -0
  225. package/dist/components/tiptap-ui/image-upload-button/image-upload-button.d.ts +26 -0
  226. package/dist/components/tiptap-ui/image-upload-button/image-upload-button.d.ts.map +1 -0
  227. package/dist/components/tiptap-ui/image-upload-button/index.d.ts +2 -0
  228. package/dist/components/tiptap-ui/image-upload-button/index.d.ts.map +1 -0
  229. package/dist/components/tiptap-ui/link-popover/index.d.ts +2 -0
  230. package/dist/components/tiptap-ui/link-popover/index.d.ts.map +1 -0
  231. package/dist/components/tiptap-ui/link-popover/link-popover.d.ts +50 -0
  232. package/dist/components/tiptap-ui/link-popover/link-popover.d.ts.map +1 -0
  233. package/dist/components/tiptap-ui/list-button/index.d.ts +2 -0
  234. package/dist/components/tiptap-ui/list-button/index.d.ts.map +1 -0
  235. package/dist/components/tiptap-ui/list-button/list-button.d.ts +51 -0
  236. package/dist/components/tiptap-ui/list-button/list-button.d.ts.map +1 -0
  237. package/dist/components/tiptap-ui/list-dropdown-menu/index.d.ts +2 -0
  238. package/dist/components/tiptap-ui/list-dropdown-menu/index.d.ts.map +1 -0
  239. package/dist/components/tiptap-ui/list-dropdown-menu/list-dropdown-menu.d.ts +43 -0
  240. package/dist/components/tiptap-ui/list-dropdown-menu/list-dropdown-menu.d.ts.map +1 -0
  241. package/dist/components/tiptap-ui/mark-button/index.d.ts +2 -0
  242. package/dist/components/tiptap-ui/mark-button/index.d.ts.map +1 -0
  243. package/dist/components/tiptap-ui/mark-button/mark-button.d.ts +56 -0
  244. package/dist/components/tiptap-ui/mark-button/mark-button.d.ts.map +1 -0
  245. package/dist/components/tiptap-ui/search-and-replace/search-and-replace.d.ts +28 -0
  246. package/dist/components/tiptap-ui/search-and-replace/search-and-replace.d.ts.map +1 -0
  247. package/dist/components/tiptap-ui/table-dropdown-menu/index.d.ts +3 -0
  248. package/dist/components/tiptap-ui/table-dropdown-menu/index.d.ts.map +1 -0
  249. package/dist/components/tiptap-ui/table-dropdown-menu/table-dropdown-menu.d.ts +34 -0
  250. package/dist/components/tiptap-ui/table-dropdown-menu/table-dropdown-menu.d.ts.map +1 -0
  251. package/dist/components/tiptap-ui/text-align-button/index.d.ts +2 -0
  252. package/dist/components/tiptap-ui/text-align-button/index.d.ts.map +1 -0
  253. package/dist/components/tiptap-ui/text-align-button/text-align-button.d.ts +56 -0
  254. package/dist/components/tiptap-ui/text-align-button/text-align-button.d.ts.map +1 -0
  255. package/dist/components/tiptap-ui/text-align-dropdown-menu/index.d.ts +2 -0
  256. package/dist/components/tiptap-ui/text-align-dropdown-menu/index.d.ts.map +1 -0
  257. package/dist/components/tiptap-ui/text-align-dropdown-menu/text-align-dropdown-menu.d.ts +52 -0
  258. package/dist/components/tiptap-ui/text-align-dropdown-menu/text-align-dropdown-menu.d.ts.map +1 -0
  259. package/dist/components/tiptap-ui/text-format-dropdown-menu/index.d.ts +3 -0
  260. package/dist/components/tiptap-ui/text-format-dropdown-menu/index.d.ts.map +1 -0
  261. package/dist/components/tiptap-ui/text-format-dropdown-menu/text-format-dropdown-menu.d.ts +54 -0
  262. package/dist/components/tiptap-ui/text-format-dropdown-menu/text-format-dropdown-menu.d.ts.map +1 -0
  263. package/dist/components/tiptap-ui/undo-redo-button/index.d.ts +2 -0
  264. package/dist/components/tiptap-ui/undo-redo-button/index.d.ts.map +1 -0
  265. package/dist/components/tiptap-ui/undo-redo-button/undo-redo-button.d.ts +76 -0
  266. package/dist/components/tiptap-ui/undo-redo-button/undo-redo-button.d.ts.map +1 -0
  267. package/dist/components/tiptap-ui-primitive/button/button.d.ts +19 -0
  268. package/dist/components/tiptap-ui-primitive/button/button.d.ts.map +1 -0
  269. package/dist/components/tiptap-ui-primitive/button/index.d.ts +2 -0
  270. package/dist/components/tiptap-ui-primitive/button/index.d.ts.map +1 -0
  271. package/dist/components/tiptap-ui-primitive/dropdown-menu/dropdown-menu.d.ts +49 -0
  272. package/dist/components/tiptap-ui-primitive/dropdown-menu/dropdown-menu.d.ts.map +1 -0
  273. package/dist/components/tiptap-ui-primitive/dropdown-menu/index.d.ts +2 -0
  274. package/dist/components/tiptap-ui-primitive/dropdown-menu/index.d.ts.map +1 -0
  275. package/dist/components/tiptap-ui-primitive/loading-circle.d.ts +5 -0
  276. package/dist/components/tiptap-ui-primitive/loading-circle.d.ts.map +1 -0
  277. package/dist/components/tiptap-ui-primitive/popover/index.d.ts +2 -0
  278. package/dist/components/tiptap-ui-primitive/popover/index.d.ts.map +1 -0
  279. package/dist/components/tiptap-ui-primitive/popover/popover.d.ts +36 -0
  280. package/dist/components/tiptap-ui-primitive/popover/popover.d.ts.map +1 -0
  281. package/dist/components/tiptap-ui-primitive/separator/index.d.ts +2 -0
  282. package/dist/components/tiptap-ui-primitive/separator/index.d.ts.map +1 -0
  283. package/dist/components/tiptap-ui-primitive/separator/separator.d.ts +11 -0
  284. package/dist/components/tiptap-ui-primitive/separator/separator.d.ts.map +1 -0
  285. package/dist/components/tiptap-ui-primitive/spacer/index.d.ts +2 -0
  286. package/dist/components/tiptap-ui-primitive/spacer/index.d.ts.map +1 -0
  287. package/dist/components/tiptap-ui-primitive/spacer/spacer.d.ts +11 -0
  288. package/dist/components/tiptap-ui-primitive/spacer/spacer.d.ts.map +1 -0
  289. package/dist/components/tiptap-ui-primitive/toolbar/animated-toolbar-button.d.ts +15 -0
  290. package/dist/components/tiptap-ui-primitive/toolbar/animated-toolbar-button.d.ts.map +1 -0
  291. package/dist/components/tiptap-ui-primitive/toolbar/animated-toolbar.d.ts +28 -0
  292. package/dist/components/tiptap-ui-primitive/toolbar/animated-toolbar.d.ts.map +1 -0
  293. package/dist/components/tiptap-ui-primitive/toolbar/index.d.ts +2 -0
  294. package/dist/components/tiptap-ui-primitive/toolbar/index.d.ts.map +1 -0
  295. package/dist/components/tiptap-ui-primitive/toolbar/toolbar.d.ts +16 -0
  296. package/dist/components/tiptap-ui-primitive/toolbar/toolbar.d.ts.map +1 -0
  297. package/dist/components/tiptap-ui-primitive/tooltip/index.d.ts +2 -0
  298. package/dist/components/tiptap-ui-primitive/tooltip/index.d.ts.map +1 -0
  299. package/dist/components/tiptap-ui-primitive/tooltip/tooltip.d.ts +31 -0
  300. package/dist/components/tiptap-ui-primitive/tooltip/tooltip.d.ts.map +1 -0
  301. package/dist/components/ui/AnimatedGradientText.d.ts +10 -0
  302. package/dist/components/ui/AnimatedGradientText.d.ts.map +1 -0
  303. package/dist/components/ui/badge.d.ts +7 -0
  304. package/dist/components/ui/badge.d.ts.map +1 -0
  305. package/dist/components/ui/button.d.ts +11 -0
  306. package/dist/components/ui/button.d.ts.map +1 -0
  307. package/dist/components/ui/card.d.ts +15 -0
  308. package/dist/components/ui/card.d.ts.map +1 -0
  309. package/dist/components/ui/dialog.d.ts +22 -0
  310. package/dist/components/ui/dialog.d.ts.map +1 -0
  311. package/dist/components/ui/input.d.ts +8 -0
  312. package/dist/components/ui/input.d.ts.map +1 -0
  313. package/dist/components/ui/label.d.ts +9 -0
  314. package/dist/components/ui/label.d.ts.map +1 -0
  315. package/dist/components/ui/loading.d.ts +13 -0
  316. package/dist/components/ui/loading.d.ts.map +1 -0
  317. package/dist/components/ui/modal.d.ts +11 -0
  318. package/dist/components/ui/modal.d.ts.map +1 -0
  319. package/dist/components/ui/popover.d.ts +9 -0
  320. package/dist/components/ui/popover.d.ts.map +1 -0
  321. package/dist/components/ui/simple-modal.d.ts +11 -0
  322. package/dist/components/ui/simple-modal.d.ts.map +1 -0
  323. package/dist/components/ui/textarea.d.ts +8 -0
  324. package/dist/components/ui/textarea.d.ts.map +1 -0
  325. package/dist/components/ui/toast.d.ts +15 -0
  326. package/dist/components/ui/toast.d.ts.map +1 -0
  327. package/dist/constants/index.d.ts +4 -0
  328. package/dist/constants/index.d.ts.map +1 -0
  329. package/dist/extensions/DiffMarks/DeletionMark.d.ts +6 -0
  330. package/dist/extensions/DiffMarks/DeletionMark.d.ts.map +1 -0
  331. package/dist/extensions/DiffMarks/InsertionMark.d.ts +6 -0
  332. package/dist/extensions/DiffMarks/InsertionMark.d.ts.map +1 -0
  333. package/dist/extensions/DiffMarks/index.d.ts +6 -0
  334. package/dist/extensions/DiffMarks/index.d.ts.map +1 -0
  335. package/dist/extensions/VersionComparison/VersionComparisonExtension.d.ts +44 -0
  336. package/dist/extensions/VersionComparison/VersionComparisonExtension.d.ts.map +1 -0
  337. package/dist/extensions/search-and-replace.d.ts +42 -0
  338. package/dist/extensions/search-and-replace.d.ts.map +1 -0
  339. package/dist/hooks/use-cursor-visibility.d.ts +35 -0
  340. package/dist/hooks/use-cursor-visibility.d.ts.map +1 -0
  341. package/dist/hooks/use-menu-navigation.d.ts +19 -0
  342. package/dist/hooks/use-menu-navigation.d.ts.map +1 -0
  343. package/dist/hooks/use-mobile.d.ts +2 -0
  344. package/dist/hooks/use-mobile.d.ts.map +1 -0
  345. package/dist/hooks/use-tiptap-editor.d.ts +3 -0
  346. package/dist/hooks/use-tiptap-editor.d.ts.map +1 -0
  347. package/dist/hooks/use-window-size.d.ts +12 -0
  348. package/dist/hooks/use-window-size.d.ts.map +1 -0
  349. package/dist/hooks/useIsMobile.d.ts +4 -0
  350. package/dist/hooks/useIsMobile.d.ts.map +1 -0
  351. package/dist/hooks/useKeywordToast.d.ts +10 -0
  352. package/dist/hooks/useKeywordToast.d.ts.map +1 -0
  353. package/dist/hooks/useToast.d.ts +10 -0
  354. package/dist/hooks/useToast.d.ts.map +1 -0
  355. package/dist/index.d.ts +4 -212
  356. package/dist/index.d.ts.map +1 -1
  357. package/dist/index.mjs +54533 -958
  358. package/dist/index.umd.js +1561 -20
  359. package/dist/lib/editor-formatting/extensions/resizable-image-caption-extension.d.ts +36 -0
  360. package/dist/lib/editor-formatting/extensions/resizable-image-caption-extension.d.ts.map +1 -0
  361. package/dist/lib/editor-formatting/extensions/spacing-normalization-extension.d.ts +35 -0
  362. package/dist/lib/editor-formatting/extensions/spacing-normalization-extension.d.ts.map +1 -0
  363. package/dist/lib/editor-formatting/extensions/table-formatting-extension.d.ts +48 -0
  364. package/dist/lib/editor-formatting/extensions/table-formatting-extension.d.ts.map +1 -0
  365. package/dist/lib/editor-formatting/index.d.ts +88 -0
  366. package/dist/lib/editor-formatting/index.d.ts.map +1 -0
  367. package/dist/lib/editor-formatting/nodes/resizable-image-caption-node.d.ts +5 -0
  368. package/dist/lib/editor-formatting/nodes/resizable-image-caption-node.d.ts.map +1 -0
  369. package/dist/lib/editor-formatting/types.d.ts +70 -0
  370. package/dist/lib/editor-formatting/types.d.ts.map +1 -0
  371. package/dist/lib/editor-formatting/utils/image-utils.d.ts +66 -0
  372. package/dist/lib/editor-formatting/utils/image-utils.d.ts.map +1 -0
  373. package/dist/lib/editor-formatting/utils/spacing-utils.d.ts +41 -0
  374. package/dist/lib/editor-formatting/utils/spacing-utils.d.ts.map +1 -0
  375. package/dist/lib/editor-formatting/utils/table-utils.d.ts +86 -0
  376. package/dist/lib/editor-formatting/utils/table-utils.d.ts.map +1 -0
  377. package/dist/lib/routes.d.ts +6 -0
  378. package/dist/lib/routes.d.ts.map +1 -0
  379. package/dist/lib/supabase-types.d.ts +42 -0
  380. package/dist/lib/supabase-types.d.ts.map +1 -0
  381. package/dist/lib/tiptap-utils.d.ts +90 -0
  382. package/dist/lib/tiptap-utils.d.ts.map +1 -0
  383. package/dist/lib/utils.d.ts +3 -0
  384. package/dist/lib/utils.d.ts.map +1 -0
  385. package/dist/style.css +1 -0
  386. package/dist/styles.css +1 -1150
  387. package/dist/types/analytics.d.ts +14 -0
  388. package/dist/types/analytics.d.ts.map +1 -0
  389. package/dist/types/cms.d.ts +12 -0
  390. package/dist/types/cms.d.ts.map +1 -0
  391. package/dist/types/diff.types.d.ts +18 -65
  392. package/dist/types/diff.types.d.ts.map +1 -1
  393. package/dist/types/index.d.ts +78 -0
  394. package/dist/types/index.d.ts.map +1 -0
  395. package/dist/utils/cloudinaryUpload.d.ts +34 -0
  396. package/dist/utils/cloudinaryUpload.d.ts.map +1 -0
  397. package/dist/utils/cn.d.ts +3 -0
  398. package/dist/utils/cn.d.ts.map +1 -0
  399. package/dist/utils/codeBlockHandling.d.ts +12 -0
  400. package/dist/utils/codeBlockHandling.d.ts.map +1 -0
  401. package/dist/utils/consoleManager.d.ts +80 -0
  402. package/dist/utils/consoleManager.d.ts.map +1 -0
  403. package/dist/utils/countryCode.d.ts +5 -0
  404. package/dist/utils/countryCode.d.ts.map +1 -0
  405. package/dist/utils/countryCodes.d.ts +17 -0
  406. package/dist/utils/countryCodes.d.ts.map +1 -0
  407. package/dist/utils/countryEmoji.d.ts +35 -0
  408. package/dist/utils/countryEmoji.d.ts.map +1 -0
  409. package/dist/utils/debugSources.d.ts +2 -0
  410. package/dist/utils/debugSources.d.ts.map +1 -0
  411. package/dist/utils/eventBus.d.ts +26 -0
  412. package/dist/utils/eventBus.d.ts.map +1 -0
  413. package/dist/utils/localStorageManager.d.ts +78 -0
  414. package/dist/utils/localStorageManager.d.ts.map +1 -0
  415. package/dist/utils/logger.d.ts +42 -0
  416. package/dist/utils/logger.d.ts.map +1 -0
  417. package/dist/utils/modalTestUtils.d.ts +5 -0
  418. package/dist/utils/modalTestUtils.d.ts.map +1 -0
  419. package/dist/utils/smoothScroll.d.ts +6 -0
  420. package/dist/utils/smoothScroll.d.ts.map +1 -0
  421. package/dist/utils/tableHandling.d.ts +12 -0
  422. package/dist/utils/tableHandling.d.ts.map +1 -0
  423. package/dist/utils/url.d.ts +13 -0
  424. package/dist/utils/url.d.ts.map +1 -0
  425. package/dist/utils/urlUtils.d.ts +14 -0
  426. package/dist/utils/urlUtils.d.ts.map +1 -0
  427. package/dist/utils/urlValidator.d.ts +13 -0
  428. package/dist/utils/urlValidator.d.ts.map +1 -0
  429. package/package.json +137 -70
  430. package/dist/components/BlogEditor.d.ts +0 -4
  431. package/dist/components/BlogEditor.d.ts.map +0 -1
  432. package/dist/components/DiffOverlay.d.ts +0 -4
  433. package/dist/components/DiffOverlay.d.ts.map +0 -1
  434. package/dist/components/ImageGenerationLoader.d.ts +0 -5
  435. package/dist/components/ImageGenerationLoader.d.ts.map +0 -1
  436. package/dist/components/RayoEditor.d.ts +0 -74
  437. package/dist/components/RayoEditor.d.ts.map +0 -1
  438. package/dist/components/ReviewButtons.d.ts +0 -4
  439. package/dist/components/ReviewButtons.d.ts.map +0 -1
  440. package/dist/components/TitleTextarea.d.ts +0 -4
  441. package/dist/components/TitleTextarea.d.ts.map +0 -1
  442. package/dist/components/index.d.ts +0 -7
  443. package/dist/components/index.d.ts.map +0 -1
  444. package/dist/hooks/index.d.ts +0 -3
  445. package/dist/hooks/index.d.ts.map +0 -1
  446. package/dist/hooks/useContentProcessing.d.ts +0 -83
  447. package/dist/hooks/useContentProcessing.d.ts.map +0 -1
  448. package/dist/hooks/useEditorDiff.d.ts +0 -65
  449. package/dist/hooks/useEditorDiff.d.ts.map +0 -1
  450. package/dist/types/editor.types.d.ts +0 -59
  451. package/dist/types/editor.types.d.ts.map +0 -1
  452. package/dist/utils/contentProcessing.d.ts +0 -81
  453. package/dist/utils/contentProcessing.d.ts.map +0 -1
  454. package/dist/utils/diffDetection.d.ts +0 -85
  455. package/dist/utils/diffDetection.d.ts.map +0 -1
  456. package/dist/utils/errorHandling.d.ts +0 -57
  457. package/dist/utils/errorHandling.d.ts.map +0 -1
  458. package/dist/utils/imageHandling.d.ts +0 -52
  459. package/dist/utils/imageHandling.d.ts.map +0 -1
  460. package/dist/utils/index.d.ts +0 -6
  461. package/dist/utils/index.d.ts.map +0 -1
  462. package/dist/utils/proximityMatching.d.ts +0 -80
  463. package/dist/utils/proximityMatching.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,563 +1,563 @@
1
- # rayo-editor
2
-
3
- ![npm version](https://img.shields.io/npm/v/rayo-editor) ![license](https://img.shields.io/npm/l/rayo-editor) ![coverage](https://img.shields.io/badge/coverage-96.3%25-brightgreen)
4
-
5
- A professional-grade rich text editor component for React, built with TipTap and optimized for blog content creation. Drop-in replacement for BlogEditor with advanced diff highlighting, collaborative editing support, and real-time content processing.
6
-
7
- ## Features
8
-
9
- - **Rich Text Editing** - Full-featured editor with support for headings, lists, code blocks, tables, and images
10
- - **Diff Highlighting** - Visual diff overlays showing changes in green (additions) and red (deletions)
11
- - **Review UI** - Accept/reject individual changes or bulk approve all modifications
12
- - **Image Handling** - Integrated image management with generation loader
13
- - **TypeScript Support** - Fully typed API with comprehensive JSDoc documentation
14
- - **React 18+** - Modern React patterns with hooks and ref forwarding
15
- - **Zero Configuration** - Works out of the box, no setup required
16
- - **Rive Animations** - Smooth loading and generation states
17
- - **96.3% Test Coverage** - Comprehensive test suite with 271+ tests
18
-
19
- ## Installation
20
-
21
- ```bash
22
- npm install rayo-editor
23
- # or
24
- yarn add rayo-editor
25
- # or
26
- pnpm add rayo-editor
27
- ```
28
-
29
- ## Quick Start
30
-
31
- ### Basic Usage
32
-
33
- ```tsx
34
- import React, { useRef } from 'react';
35
- import { RayoEditor, BlogSimpleEditorRef } from 'rayo-editor';
36
- import 'rayo-editor/styles';
37
-
38
- export function MyBlogEditor() {
39
- const editorRef = useRef<BlogSimpleEditorRef>(null);
40
- const [content, setContent] = React.useState('');
41
- const [title, setTitle] = React.useState('');
42
-
43
- return (
44
- <RayoEditor
45
- content={content}
46
- title={title}
47
- onChange={setContent}
48
- onTitleChange={setTitle}
49
- isLoading={false}
50
- editorRef={editorRef}
51
- />
52
- );
53
- }
54
- ```
55
-
56
- ### With Diff Highlighting
57
-
58
- ```tsx
59
- <RayoEditor
60
- content={content}
61
- title={title}
62
- onChange={setContent}
63
- onTitleChange={setTitle}
64
- showDiffs={true}
65
- pendingChanges={true}
66
- onAcceptChanges={() => {
67
- // Handle accepting all changes
68
- console.log('Changes accepted');
69
- }}
70
- onRejectChanges={() => {
71
- // Handle rejecting all changes
72
- console.log('Changes rejected');
73
- }}
74
- isLoading={false}
75
- editorRef={editorRef}
76
- />
77
- ```
78
-
79
- ### Read-Only Mode
80
-
81
- ```tsx
82
- <RayoEditor
83
- content={publishedContent}
84
- title={publishedTitle}
85
- onChange={() => {}} // No-op
86
- readOnly={true}
87
- isLoading={false}
88
- editorRef={editorRef}
89
- />
90
- ```
91
-
92
- ### With Callbacks
93
-
94
- ```tsx
95
- <RayoEditor
96
- content={content}
97
- title={title}
98
- onChange={setContent}
99
- onTitleChange={setTitle}
100
- onAcceptSingleChange={(greenRange, redRange) => {
101
- console.log('Single change accepted', greenRange, redRange);
102
- }}
103
- onRejectSingleChange={(greenRange, redRange) => {
104
- console.log('Single change rejected', greenRange, redRange);
105
- }}
106
- onDiffPairsChange={(pairs) => {
107
- console.log('Diff pairs updated', pairs);
108
- }}
109
- isLoading={false}
110
- editorRef={editorRef}
111
- />
112
- ```
113
-
114
- ## API Reference
115
-
116
- ### Components
117
-
118
- #### RayoEditor
119
-
120
- Main editor component providing a complete rich text editing experience.
121
-
122
- ```tsx
123
- <RayoEditor {...props} />
124
- ```
125
-
126
- **Props:**
127
-
128
- ```typescript
129
- interface RayoEditorProps {
130
- // Content management
131
- content: string;
132
- title: string;
133
- onChange: (content: string) => void;
134
- onTitleChange?: (title: string) => void;
135
-
136
- // State management
137
- isLoading: boolean;
138
- isStreaming?: boolean;
139
- isAgentThinking?: boolean;
140
- readOnly?: boolean;
141
- focusMode?: boolean;
142
-
143
- // Diff & Review features
144
- pendingChanges?: boolean;
145
- showDiffs?: boolean;
146
- hideReviewUI?: boolean;
147
- editedLinesCount?: number;
148
- onAcceptChanges?: () => void;
149
- onRejectChanges?: () => void;
150
- onAcceptSingleChange?: (greenRange: DiffRange, redRange?: DiffRange) => void;
151
- onRejectSingleChange?: (greenRange: DiffRange, redRange?: DiffRange) => void;
152
- onDiffPairsChange?: (diffPairs: DiffPair[]) => void;
153
-
154
- // Image management
155
- featuredImageUrl?: string;
156
- onEditFeaturedImage?: () => void;
157
- isGeneratingImage?: boolean;
158
-
159
- // Advanced options
160
- editorRef: RefObject<BlogSimpleEditorRef>;
161
- onAriScoreChange?: (score: number) => void;
162
- disableAutoScroll?: boolean;
163
- onUserScrollChange?: (isScrolledUp: boolean) => void;
164
- showToolbarAnimation?: boolean;
165
- streamingPhase?: string;
166
- }
167
- ```
168
-
169
- #### BlogEditor
170
-
171
- Legacy component wrapper - identical to RayoEditor, maintained for backward compatibility.
172
-
173
- ```tsx
174
- import { BlogEditor } from 'rayo-editor';
175
- ```
176
-
177
- #### TitleTextarea
178
-
179
- Standalone title input component.
180
-
181
- ```tsx
182
- <TitleTextarea
183
- title={title}
184
- onTitleChange={setTitle}
185
- readOnly={false}
186
- />
187
- ```
188
-
189
- #### DiffOverlay
190
-
191
- Visual overlay component for displaying diff highlights.
192
-
193
- ```tsx
194
- <DiffOverlay
195
- diffPairs={diffPairs}
196
- overlayHoleRect={rect}
197
- onPairHover={(index) => console.log(index)}
198
- onPairClick={(index) => console.log(index)}
199
- />
200
- ```
201
-
202
- #### ReviewButtons
203
-
204
- Accept/reject buttons for review operations.
205
-
206
- ```tsx
207
- <ReviewButtons
208
- onAccept={() => console.log('Accepted')}
209
- onReject={() => console.log('Rejected')}
210
- position={{ top: 100, left: 50 }}
211
- />
212
- ```
213
-
214
- ### Hooks
215
-
216
- #### useEditorDiff
217
-
218
- Hook for managing diff detection and overlay state.
219
-
220
- ```tsx
221
- const {
222
- diffPairs,
223
- setDiffPairs,
224
- activePairIndex,
225
- setActivePairIndex,
226
- hoverPairIndex,
227
- setHoverPairIndex,
228
- overlayHoleRect,
229
- setOverlayHoleRect,
230
- updateDiffRanges
231
- } = useEditorDiff(editorRef, { focusMode: false });
232
- ```
233
-
234
- **Returns:**
235
- - `diffPairs: DiffPair[]` - Array of detected diff pairs
236
- - `activePairIndex: number` - Currently active pair index
237
- - `hoverPairIndex: number` - Currently hovered pair index
238
- - `overlayHoleRect: Rect | null` - Rectangle for overlay positioning
239
- - `updateDiffRanges: () => void` - Function to trigger diff update
240
-
241
- #### useContentProcessing
242
-
243
- Hook for content transformation and processing.
244
-
245
- ```tsx
246
- const {
247
- content,
248
- setContent,
249
- isProcessing,
250
- error,
251
- processContent
252
- } = useContentProcessing(initialContent);
253
- ```
254
-
255
- **Returns:**
256
- - `content: string` - Current processed content
257
- - `setContent: (content: string) => void` - Direct content setter
258
- - `isProcessing: boolean` - Processing state flag
259
- - `error: Error | null` - Last processing error
260
- - `processContent: (content: string) => void` - Process and update content
261
-
262
- ### Utility Functions
263
-
264
- #### Diff Detection
265
-
266
- ```typescript
267
- // Detect diff markers in content
268
- detectDiffMarkers(content: string): DiffMarkerResult;
269
-
270
- // Normalize diff text for comparison
271
- normalizeDiffText(text: string): string;
272
-
273
- // Extract diff ranges from content
274
- extractDiffRanges(content: string, type?: 'all' | 'green' | 'red'): DiffRange[];
275
- ```
276
-
277
- #### Content Processing
278
-
279
- ```typescript
280
- // Merge consecutive or overlapping ranges
281
- mergeConsecutiveRanges(ranges: DiffRange[]): DiffRange[];
282
-
283
- // Extract plain text from HTML content
284
- extractTextContent(html: string): string;
285
-
286
- // Optimize ranges for rendering
287
- optimizeRanges(ranges: DiffRange[]): DiffRange[];
288
- ```
289
-
290
- #### Image Handling
291
-
292
- ```typescript
293
- // Group consecutive images in content
294
- groupConsecutiveImages(content: string): ImageOperation[];
295
-
296
- // Match image replacements in diff pairs
297
- matchImageReplacements(content: string): Array<{old: string, new: string}>;
298
- ```
299
-
300
- #### Proximity Matching
301
-
302
- ```typescript
303
- // Calculate proximity score between text segments
304
- calculateProximity(text1: string, text2: string): number;
305
-
306
- // Find the best matching text pair
307
- findOwnerTextPair(target: string, candidates: string[]): string | null;
308
-
309
- // Group items by proximity
310
- groupConsecutiveItems<T>(items: T[], key: string): T[][];
311
- ```
312
-
313
- #### Error Handling
314
-
315
- ```typescript
316
- // Safe execution wrapper
317
- safeExecute<T>(fn: () => T, errorHandler?: (error: Error) => void): T | null;
318
-
319
- // Custom error class
320
- class DiffProcessingError extends Error {
321
- constructor(message: string, public originalError?: Error) {}
322
- }
323
- ```
324
-
325
- ## Props Documentation
326
-
327
- ### RayoEditorProps
328
-
329
- All props are documented below with their purposes and default values:
330
-
331
- | Prop | Type | Required | Default | Description |
332
- |------|------|----------|---------|-------------|
333
- | `content` | `string` | Yes | - | Current editor content (HTML) |
334
- | `title` | `string` | Yes | - | Blog post title |
335
- | `onChange` | `(content: string) => void` | Yes | - | Callback fired on content changes |
336
- | `onTitleChange` | `(title: string) => void` | No | - | Callback fired on title changes |
337
- | `isLoading` | `boolean` | Yes | - | Shows loading state |
338
- | `editorRef` | `RefObject<BlogSimpleEditorRef>` | Yes | - | Reference to editor instance |
339
- | `isStreaming` | `boolean` | No | `false` | Indicates streaming in progress |
340
- | `isAgentThinking` | `boolean` | No | `false` | Shows agent thinking state |
341
- | `readOnly` | `boolean` | No | `false` | Disables editing |
342
- | `focusMode` | `boolean` | No | `false` | Minimal UI focus mode |
343
- | `pendingChanges` | `boolean` | No | `false` | Indicates pending changes exist |
344
- | `showDiffs` | `boolean` | No | `false` | Show diff highlighting |
345
- | `hideReviewUI` | `boolean` | No | `false` | Hide review buttons |
346
- | `editedLinesCount` | `number` | No | - | Number of edited lines |
347
- | `onAcceptChanges` | `() => void` | No | - | Accept all changes callback |
348
- | `onRejectChanges` | `() => void` | No | - | Reject all changes callback |
349
- | `onAcceptSingleChange` | `(green, red?) => void` | No | - | Accept single change |
350
- | `onRejectSingleChange` | `(green, red?) => void` | No | - | Reject single change |
351
- | `onDiffPairsChange` | `(pairs) => void` | No | - | Diff pairs updated |
352
- | `featuredImageUrl` | `string` | No | - | Featured image URL |
353
- | `onEditFeaturedImage` | `() => void` | No | - | Edit featured image callback |
354
- | `isGeneratingImage` | `boolean` | No | `false` | Image generation in progress |
355
- | `onAriScoreChange` | `(score: number) => void` | No | - | ARI score updated |
356
- | `disableAutoScroll` | `boolean` | No | `false` | Disable auto-scroll |
357
- | `onUserScrollChange` | `(scrolledUp: boolean) => void` | No | - | User scroll state |
358
- | `showToolbarAnimation` | `boolean` | No | `true` | Show toolbar animations |
359
- | `streamingPhase` | `string` | No | - | Current streaming phase |
360
-
361
- ## Examples
362
-
363
- ### Advanced: Collaborative Editing
364
-
365
- ```tsx
366
- import React, { useRef, useState } from 'react';
367
- import { RayoEditor, BlogSimpleEditorRef, useEditorDiff } from 'rayo-editor';
368
-
369
- export function CollaborativeEditor() {
370
- const editorRef = useRef<BlogSimpleEditorRef>(null);
371
- const [content, setContent] = useState('');
372
- const [title, setTitle] = useState('');
373
- const [pendingChanges, setPendingChanges] = useState(false);
374
-
375
- const { diffPairs, updateDiffRanges } = useEditorDiff(editorRef);
376
-
377
- const handleAcceptChanges = async () => {
378
- // Apply changes and send to server
379
- await fetch('/api/changes/accept', {
380
- method: 'POST',
381
- body: JSON.stringify({ content, diffPairs })
382
- });
383
- setPendingChanges(false);
384
- };
385
-
386
- return (
387
- <RayoEditor
388
- content={content}
389
- title={title}
390
- onChange={setContent}
391
- onTitleChange={setTitle}
392
- showDiffs={pendingChanges}
393
- pendingChanges={pendingChanges}
394
- onAcceptChanges={handleAcceptChanges}
395
- onRejectChanges={() => setContent(content)}
396
- isLoading={false}
397
- editorRef={editorRef}
398
- />
399
- );
400
- }
401
- ```
402
-
403
- ### Advanced: With Content Processing
404
-
405
- ```tsx
406
- import { RayoEditor, useContentProcessing } from 'rayo-editor';
407
-
408
- export function SmartEditor() {
409
- const editorRef = useRef<BlogSimpleEditorRef>(null);
410
- const {
411
- content,
412
- setContent,
413
- isProcessing,
414
- error,
415
- processContent
416
- } = useContentProcessing('');
417
-
418
- const handleAIEnhance = async () => {
419
- const enhanced = await fetch('/api/enhance', {
420
- method: 'POST',
421
- body: JSON.stringify({ content })
422
- }).then(r => r.json());
423
-
424
- processContent(enhanced.content);
425
- };
426
-
427
- return (
428
- <>
429
- <RayoEditor
430
- content={content}
431
- title=""
432
- onChange={processContent}
433
- isLoading={isProcessing}
434
- editorRef={editorRef}
435
- />
436
- {error && <div className="error">{error.message}</div>}
437
- <button onClick={handleAIEnhance} disabled={isProcessing}>
438
- {isProcessing ? 'Processing...' : 'Enhance with AI'}
439
- </button>
440
- </>
441
- );
442
- }
443
- ```
444
-
445
- ### Advanced: Real-time Diff Highlighting
446
-
447
- ```tsx
448
- import React, { useRef, useState, useEffect } from 'react';
449
- import { RayoEditor, useEditorDiff, detectDiffMarkers } from 'rayo-editor';
450
-
451
- export function RealtimeDiffEditor() {
452
- const editorRef = useRef<BlogSimpleEditorRef>(null);
453
- const [content, setContent] = useState('');
454
- const { diffPairs, setDiffPairs } = useEditorDiff(editorRef);
455
-
456
- useEffect(() => {
457
- const { hasDiffs } = detectDiffMarkers(content);
458
- if (hasDiffs) {
459
- // Process and set diff pairs
460
- setDiffPairs([]);
461
- }
462
- }, [content, setDiffPairs]);
463
-
464
- return (
465
- <RayoEditor
466
- content={content}
467
- title=""
468
- onChange={setContent}
469
- showDiffs={diffPairs.length > 0}
470
- isLoading={false}
471
- editorRef={editorRef}
472
- />
473
- );
474
- }
475
- ```
476
-
477
- ## Architecture
478
-
479
- ### Component Hierarchy
480
-
481
- ```
482
- RayoEditor (Main Component)
483
- ├── BlogEditor (Core Editor Implementation)
484
- ├── TitleTextarea (Title Input)
485
- ├── DiffOverlay (Diff Visualization)
486
- ├── ReviewButtons (Accept/Reject Controls)
487
- └── ImageGenerationLoader (Image Loading State)
488
- ```
489
-
490
- ### Hook System
491
-
492
- - **useEditorDiff** - Manages diff state and detection
493
- - **useContentProcessing** - Handles content transformation
494
- - **Internal hooks** - TipTap editor instance management
495
-
496
- ### Utility Pipeline
497
-
498
- ```
499
- Content Input
500
-
501
- Diff Detection (detectDiffMarkers)
502
-
503
- Normalization (normalizeDiffText)
504
-
505
- Range Extraction (extractDiffRanges)
506
-
507
- Range Optimization (mergeConsecutiveRanges, optimizeRanges)
508
-
509
- Rendering (DiffOverlay)
510
- ```
511
-
512
- ## Testing
513
-
514
- The package includes comprehensive tests covering all functionality:
515
-
516
- ```bash
517
- # Run all tests
518
- npm run test
519
-
520
- # Run with UI
521
- npm run test:ui
522
-
523
- # Generate coverage report
524
- npm run test:coverage
525
- ```
526
-
527
- **Test Statistics:**
528
- - 271+ test cases
529
- - 96.3% code coverage
530
- - All critical paths covered
531
- - Edge cases and error scenarios tested
532
-
533
- ## Contributing
534
-
535
- Contributions are welcome! Please follow these guidelines:
536
-
537
- 1. Fork the repository
538
- 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
539
- 3. Make your changes with tests
540
- 4. Ensure all tests pass (`npm run test`)
541
- 5. Commit with clear messages (`git commit -m 'feat: add amazing feature'`)
542
- 6. Push to the branch (`git push origin feature/amazing-feature`)
543
- 7. Open a Pull Request
544
-
545
- ### Code Standards
546
-
547
- - Use TypeScript for type safety
548
- - Add JSDoc comments for public APIs
549
- - Write tests for new features
550
- - Maintain >95% code coverage
551
- - Follow eslint configuration
552
-
553
- ## Changelog
554
-
555
- See [CHANGELOG.md](./CHANGELOG.md) for version history and release notes.
556
-
557
- ## License
558
-
559
- MIT License - see LICENSE file for details.
560
-
561
- ---
562
-
563
- **Built with ❤️ for content creators**
1
+ # rayo-editor
2
+
3
+ ![npm version](https://img.shields.io/npm/v/rayo-editor) ![license](https://img.shields.io/npm/l/rayo-editor) ![coverage](https://img.shields.io/badge/coverage-96.3%25-brightgreen)
4
+
5
+ A professional-grade rich text editor component for React, built with TipTap and optimized for blog content creation. Drop-in replacement for BlogEditor with advanced diff highlighting, collaborative editing support, and real-time content processing.
6
+
7
+ ## Features
8
+
9
+ - **Rich Text Editing** - Full-featured editor with support for headings, lists, code blocks, tables, and images
10
+ - **Diff Highlighting** - Visual diff overlays showing changes in green (additions) and red (deletions)
11
+ - **Review UI** - Accept/reject individual changes or bulk approve all modifications
12
+ - **Image Handling** - Integrated image management with generation loader
13
+ - **TypeScript Support** - Fully typed API with comprehensive JSDoc documentation
14
+ - **React 18+** - Modern React patterns with hooks and ref forwarding
15
+ - **Zero Configuration** - Works out of the box, no setup required
16
+ - **Rive Animations** - Smooth loading and generation states
17
+ - **96.3% Test Coverage** - Comprehensive test suite with 271+ tests
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install rayo-editor
23
+ # or
24
+ yarn add rayo-editor
25
+ # or
26
+ pnpm add rayo-editor
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ### Basic Usage
32
+
33
+ ```tsx
34
+ import React, { useRef } from 'react';
35
+ import { RayoEditor, BlogSimpleEditorRef } from 'rayo-editor';
36
+ import 'rayo-editor/styles';
37
+
38
+ export function MyBlogEditor() {
39
+ const editorRef = useRef<BlogSimpleEditorRef>(null);
40
+ const [content, setContent] = React.useState('');
41
+ const [title, setTitle] = React.useState('');
42
+
43
+ return (
44
+ <RayoEditor
45
+ content={content}
46
+ title={title}
47
+ onChange={setContent}
48
+ onTitleChange={setTitle}
49
+ isLoading={false}
50
+ editorRef={editorRef}
51
+ />
52
+ );
53
+ }
54
+ ```
55
+
56
+ ### With Diff Highlighting
57
+
58
+ ```tsx
59
+ <RayoEditor
60
+ content={content}
61
+ title={title}
62
+ onChange={setContent}
63
+ onTitleChange={setTitle}
64
+ showDiffs={true}
65
+ pendingChanges={true}
66
+ onAcceptChanges={() => {
67
+ // Handle accepting all changes
68
+ console.log('Changes accepted');
69
+ }}
70
+ onRejectChanges={() => {
71
+ // Handle rejecting all changes
72
+ console.log('Changes rejected');
73
+ }}
74
+ isLoading={false}
75
+ editorRef={editorRef}
76
+ />
77
+ ```
78
+
79
+ ### Read-Only Mode
80
+
81
+ ```tsx
82
+ <RayoEditor
83
+ content={publishedContent}
84
+ title={publishedTitle}
85
+ onChange={() => {}} // No-op
86
+ readOnly={true}
87
+ isLoading={false}
88
+ editorRef={editorRef}
89
+ />
90
+ ```
91
+
92
+ ### With Callbacks
93
+
94
+ ```tsx
95
+ <RayoEditor
96
+ content={content}
97
+ title={title}
98
+ onChange={setContent}
99
+ onTitleChange={setTitle}
100
+ onAcceptSingleChange={(greenRange, redRange) => {
101
+ console.log('Single change accepted', greenRange, redRange);
102
+ }}
103
+ onRejectSingleChange={(greenRange, redRange) => {
104
+ console.log('Single change rejected', greenRange, redRange);
105
+ }}
106
+ onDiffPairsChange={(pairs) => {
107
+ console.log('Diff pairs updated', pairs);
108
+ }}
109
+ isLoading={false}
110
+ editorRef={editorRef}
111
+ />
112
+ ```
113
+
114
+ ## API Reference
115
+
116
+ ### Components
117
+
118
+ #### RayoEditor
119
+
120
+ Main editor component providing a complete rich text editing experience.
121
+
122
+ ```tsx
123
+ <RayoEditor {...props} />
124
+ ```
125
+
126
+ **Props:**
127
+
128
+ ```typescript
129
+ interface RayoEditorProps {
130
+ // Content management
131
+ content: string;
132
+ title: string;
133
+ onChange: (content: string) => void;
134
+ onTitleChange?: (title: string) => void;
135
+
136
+ // State management
137
+ isLoading: boolean;
138
+ isStreaming?: boolean;
139
+ isAgentThinking?: boolean;
140
+ readOnly?: boolean;
141
+ focusMode?: boolean;
142
+
143
+ // Diff & Review features
144
+ pendingChanges?: boolean;
145
+ showDiffs?: boolean;
146
+ hideReviewUI?: boolean;
147
+ editedLinesCount?: number;
148
+ onAcceptChanges?: () => void;
149
+ onRejectChanges?: () => void;
150
+ onAcceptSingleChange?: (greenRange: DiffRange, redRange?: DiffRange) => void;
151
+ onRejectSingleChange?: (greenRange: DiffRange, redRange?: DiffRange) => void;
152
+ onDiffPairsChange?: (diffPairs: DiffPair[]) => void;
153
+
154
+ // Image management
155
+ featuredImageUrl?: string;
156
+ onEditFeaturedImage?: () => void;
157
+ isGeneratingImage?: boolean;
158
+
159
+ // Advanced options
160
+ editorRef: RefObject<BlogSimpleEditorRef>;
161
+ onAriScoreChange?: (score: number) => void;
162
+ disableAutoScroll?: boolean;
163
+ onUserScrollChange?: (isScrolledUp: boolean) => void;
164
+ showToolbarAnimation?: boolean;
165
+ streamingPhase?: string;
166
+ }
167
+ ```
168
+
169
+ #### BlogEditor
170
+
171
+ Legacy component wrapper - identical to RayoEditor, maintained for backward compatibility.
172
+
173
+ ```tsx
174
+ import { BlogEditor } from 'rayo-editor';
175
+ ```
176
+
177
+ #### TitleTextarea
178
+
179
+ Standalone title input component.
180
+
181
+ ```tsx
182
+ <TitleTextarea
183
+ title={title}
184
+ onTitleChange={setTitle}
185
+ readOnly={false}
186
+ />
187
+ ```
188
+
189
+ #### DiffOverlay
190
+
191
+ Visual overlay component for displaying diff highlights.
192
+
193
+ ```tsx
194
+ <DiffOverlay
195
+ diffPairs={diffPairs}
196
+ overlayHoleRect={rect}
197
+ onPairHover={(index) => console.log(index)}
198
+ onPairClick={(index) => console.log(index)}
199
+ />
200
+ ```
201
+
202
+ #### ReviewButtons
203
+
204
+ Accept/reject buttons for review operations.
205
+
206
+ ```tsx
207
+ <ReviewButtons
208
+ onAccept={() => console.log('Accepted')}
209
+ onReject={() => console.log('Rejected')}
210
+ position={{ top: 100, left: 50 }}
211
+ />
212
+ ```
213
+
214
+ ### Hooks
215
+
216
+ #### useEditorDiff
217
+
218
+ Hook for managing diff detection and overlay state.
219
+
220
+ ```tsx
221
+ const {
222
+ diffPairs,
223
+ setDiffPairs,
224
+ activePairIndex,
225
+ setActivePairIndex,
226
+ hoverPairIndex,
227
+ setHoverPairIndex,
228
+ overlayHoleRect,
229
+ setOverlayHoleRect,
230
+ updateDiffRanges
231
+ } = useEditorDiff(editorRef, { focusMode: false });
232
+ ```
233
+
234
+ **Returns:**
235
+ - `diffPairs: DiffPair[]` - Array of detected diff pairs
236
+ - `activePairIndex: number` - Currently active pair index
237
+ - `hoverPairIndex: number` - Currently hovered pair index
238
+ - `overlayHoleRect: Rect | null` - Rectangle for overlay positioning
239
+ - `updateDiffRanges: () => void` - Function to trigger diff update
240
+
241
+ #### useContentProcessing
242
+
243
+ Hook for content transformation and processing.
244
+
245
+ ```tsx
246
+ const {
247
+ content,
248
+ setContent,
249
+ isProcessing,
250
+ error,
251
+ processContent
252
+ } = useContentProcessing(initialContent);
253
+ ```
254
+
255
+ **Returns:**
256
+ - `content: string` - Current processed content
257
+ - `setContent: (content: string) => void` - Direct content setter
258
+ - `isProcessing: boolean` - Processing state flag
259
+ - `error: Error | null` - Last processing error
260
+ - `processContent: (content: string) => void` - Process and update content
261
+
262
+ ### Utility Functions
263
+
264
+ #### Diff Detection
265
+
266
+ ```typescript
267
+ // Detect diff markers in content
268
+ detectDiffMarkers(content: string): DiffMarkerResult;
269
+
270
+ // Normalize diff text for comparison
271
+ normalizeDiffText(text: string): string;
272
+
273
+ // Extract diff ranges from content
274
+ extractDiffRanges(content: string, type?: 'all' | 'green' | 'red'): DiffRange[];
275
+ ```
276
+
277
+ #### Content Processing
278
+
279
+ ```typescript
280
+ // Merge consecutive or overlapping ranges
281
+ mergeConsecutiveRanges(ranges: DiffRange[]): DiffRange[];
282
+
283
+ // Extract plain text from HTML content
284
+ extractTextContent(html: string): string;
285
+
286
+ // Optimize ranges for rendering
287
+ optimizeRanges(ranges: DiffRange[]): DiffRange[];
288
+ ```
289
+
290
+ #### Image Handling
291
+
292
+ ```typescript
293
+ // Group consecutive images in content
294
+ groupConsecutiveImages(content: string): ImageOperation[];
295
+
296
+ // Match image replacements in diff pairs
297
+ matchImageReplacements(content: string): Array<{old: string, new: string}>;
298
+ ```
299
+
300
+ #### Proximity Matching
301
+
302
+ ```typescript
303
+ // Calculate proximity score between text segments
304
+ calculateProximity(text1: string, text2: string): number;
305
+
306
+ // Find the best matching text pair
307
+ findOwnerTextPair(target: string, candidates: string[]): string | null;
308
+
309
+ // Group items by proximity
310
+ groupConsecutiveItems<T>(items: T[], key: string): T[][];
311
+ ```
312
+
313
+ #### Error Handling
314
+
315
+ ```typescript
316
+ // Safe execution wrapper
317
+ safeExecute<T>(fn: () => T, errorHandler?: (error: Error) => void): T | null;
318
+
319
+ // Custom error class
320
+ class DiffProcessingError extends Error {
321
+ constructor(message: string, public originalError?: Error) {}
322
+ }
323
+ ```
324
+
325
+ ## Props Documentation
326
+
327
+ ### RayoEditorProps
328
+
329
+ All props are documented below with their purposes and default values:
330
+
331
+ | Prop | Type | Required | Default | Description |
332
+ |------|------|----------|---------|-------------|
333
+ | `content` | `string` | Yes | - | Current editor content (HTML) |
334
+ | `title` | `string` | Yes | - | Blog post title |
335
+ | `onChange` | `(content: string) => void` | Yes | - | Callback fired on content changes |
336
+ | `onTitleChange` | `(title: string) => void` | No | - | Callback fired on title changes |
337
+ | `isLoading` | `boolean` | Yes | - | Shows loading state |
338
+ | `editorRef` | `RefObject<BlogSimpleEditorRef>` | Yes | - | Reference to editor instance |
339
+ | `isStreaming` | `boolean` | No | `false` | Indicates streaming in progress |
340
+ | `isAgentThinking` | `boolean` | No | `false` | Shows agent thinking state |
341
+ | `readOnly` | `boolean` | No | `false` | Disables editing |
342
+ | `focusMode` | `boolean` | No | `false` | Minimal UI focus mode |
343
+ | `pendingChanges` | `boolean` | No | `false` | Indicates pending changes exist |
344
+ | `showDiffs` | `boolean` | No | `false` | Show diff highlighting |
345
+ | `hideReviewUI` | `boolean` | No | `false` | Hide review buttons |
346
+ | `editedLinesCount` | `number` | No | - | Number of edited lines |
347
+ | `onAcceptChanges` | `() => void` | No | - | Accept all changes callback |
348
+ | `onRejectChanges` | `() => void` | No | - | Reject all changes callback |
349
+ | `onAcceptSingleChange` | `(green, red?) => void` | No | - | Accept single change |
350
+ | `onRejectSingleChange` | `(green, red?) => void` | No | - | Reject single change |
351
+ | `onDiffPairsChange` | `(pairs) => void` | No | - | Diff pairs updated |
352
+ | `featuredImageUrl` | `string` | No | - | Featured image URL |
353
+ | `onEditFeaturedImage` | `() => void` | No | - | Edit featured image callback |
354
+ | `isGeneratingImage` | `boolean` | No | `false` | Image generation in progress |
355
+ | `onAriScoreChange` | `(score: number) => void` | No | - | ARI score updated |
356
+ | `disableAutoScroll` | `boolean` | No | `false` | Disable auto-scroll |
357
+ | `onUserScrollChange` | `(scrolledUp: boolean) => void` | No | - | User scroll state |
358
+ | `showToolbarAnimation` | `boolean` | No | `true` | Show toolbar animations |
359
+ | `streamingPhase` | `string` | No | - | Current streaming phase |
360
+
361
+ ## Examples
362
+
363
+ ### Advanced: Collaborative Editing
364
+
365
+ ```tsx
366
+ import React, { useRef, useState } from 'react';
367
+ import { RayoEditor, BlogSimpleEditorRef, useEditorDiff } from 'rayo-editor';
368
+
369
+ export function CollaborativeEditor() {
370
+ const editorRef = useRef<BlogSimpleEditorRef>(null);
371
+ const [content, setContent] = useState('');
372
+ const [title, setTitle] = useState('');
373
+ const [pendingChanges, setPendingChanges] = useState(false);
374
+
375
+ const { diffPairs, updateDiffRanges } = useEditorDiff(editorRef);
376
+
377
+ const handleAcceptChanges = async () => {
378
+ // Apply changes and send to server
379
+ await fetch('/api/changes/accept', {
380
+ method: 'POST',
381
+ body: JSON.stringify({ content, diffPairs })
382
+ });
383
+ setPendingChanges(false);
384
+ };
385
+
386
+ return (
387
+ <RayoEditor
388
+ content={content}
389
+ title={title}
390
+ onChange={setContent}
391
+ onTitleChange={setTitle}
392
+ showDiffs={pendingChanges}
393
+ pendingChanges={pendingChanges}
394
+ onAcceptChanges={handleAcceptChanges}
395
+ onRejectChanges={() => setContent(content)}
396
+ isLoading={false}
397
+ editorRef={editorRef}
398
+ />
399
+ );
400
+ }
401
+ ```
402
+
403
+ ### Advanced: With Content Processing
404
+
405
+ ```tsx
406
+ import { RayoEditor, useContentProcessing } from 'rayo-editor';
407
+
408
+ export function SmartEditor() {
409
+ const editorRef = useRef<BlogSimpleEditorRef>(null);
410
+ const {
411
+ content,
412
+ setContent,
413
+ isProcessing,
414
+ error,
415
+ processContent
416
+ } = useContentProcessing('');
417
+
418
+ const handleAIEnhance = async () => {
419
+ const enhanced = await fetch('/api/enhance', {
420
+ method: 'POST',
421
+ body: JSON.stringify({ content })
422
+ }).then(r => r.json());
423
+
424
+ processContent(enhanced.content);
425
+ };
426
+
427
+ return (
428
+ <>
429
+ <RayoEditor
430
+ content={content}
431
+ title=""
432
+ onChange={processContent}
433
+ isLoading={isProcessing}
434
+ editorRef={editorRef}
435
+ />
436
+ {error && <div className="error">{error.message}</div>}
437
+ <button onClick={handleAIEnhance} disabled={isProcessing}>
438
+ {isProcessing ? 'Processing...' : 'Enhance with AI'}
439
+ </button>
440
+ </>
441
+ );
442
+ }
443
+ ```
444
+
445
+ ### Advanced: Real-time Diff Highlighting
446
+
447
+ ```tsx
448
+ import React, { useRef, useState, useEffect } from 'react';
449
+ import { RayoEditor, useEditorDiff, detectDiffMarkers } from 'rayo-editor';
450
+
451
+ export function RealtimeDiffEditor() {
452
+ const editorRef = useRef<BlogSimpleEditorRef>(null);
453
+ const [content, setContent] = useState('');
454
+ const { diffPairs, setDiffPairs } = useEditorDiff(editorRef);
455
+
456
+ useEffect(() => {
457
+ const { hasDiffs } = detectDiffMarkers(content);
458
+ if (hasDiffs) {
459
+ // Process and set diff pairs
460
+ setDiffPairs([]);
461
+ }
462
+ }, [content, setDiffPairs]);
463
+
464
+ return (
465
+ <RayoEditor
466
+ content={content}
467
+ title=""
468
+ onChange={setContent}
469
+ showDiffs={diffPairs.length > 0}
470
+ isLoading={false}
471
+ editorRef={editorRef}
472
+ />
473
+ );
474
+ }
475
+ ```
476
+
477
+ ## Architecture
478
+
479
+ ### Component Hierarchy
480
+
481
+ ```
482
+ RayoEditor (Main Component)
483
+ ├── BlogEditor (Core Editor Implementation)
484
+ ├── TitleTextarea (Title Input)
485
+ ├── DiffOverlay (Diff Visualization)
486
+ ├── ReviewButtons (Accept/Reject Controls)
487
+ └── ImageGenerationLoader (Image Loading State)
488
+ ```
489
+
490
+ ### Hook System
491
+
492
+ - **useEditorDiff** - Manages diff state and detection
493
+ - **useContentProcessing** - Handles content transformation
494
+ - **Internal hooks** - TipTap editor instance management
495
+
496
+ ### Utility Pipeline
497
+
498
+ ```
499
+ Content Input
500
+
501
+ Diff Detection (detectDiffMarkers)
502
+
503
+ Normalization (normalizeDiffText)
504
+
505
+ Range Extraction (extractDiffRanges)
506
+
507
+ Range Optimization (mergeConsecutiveRanges, optimizeRanges)
508
+
509
+ Rendering (DiffOverlay)
510
+ ```
511
+
512
+ ## Testing
513
+
514
+ The package includes comprehensive tests covering all functionality:
515
+
516
+ ```bash
517
+ # Run all tests
518
+ npm run test
519
+
520
+ # Run with UI
521
+ npm run test:ui
522
+
523
+ # Generate coverage report
524
+ npm run test:coverage
525
+ ```
526
+
527
+ **Test Statistics:**
528
+ - 271+ test cases
529
+ - 96.3% code coverage
530
+ - All critical paths covered
531
+ - Edge cases and error scenarios tested
532
+
533
+ ## Contributing
534
+
535
+ Contributions are welcome! Please follow these guidelines:
536
+
537
+ 1. Fork the repository
538
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
539
+ 3. Make your changes with tests
540
+ 4. Ensure all tests pass (`npm run test`)
541
+ 5. Commit with clear messages (`git commit -m 'feat: add amazing feature'`)
542
+ 6. Push to the branch (`git push origin feature/amazing-feature`)
543
+ 7. Open a Pull Request
544
+
545
+ ### Code Standards
546
+
547
+ - Use TypeScript for type safety
548
+ - Add JSDoc comments for public APIs
549
+ - Write tests for new features
550
+ - Maintain >95% code coverage
551
+ - Follow eslint configuration
552
+
553
+ ## Changelog
554
+
555
+ See [CHANGELOG.md](./CHANGELOG.md) for version history and release notes.
556
+
557
+ ## License
558
+
559
+ MIT License - see LICENSE file for details.
560
+
561
+ ---
562
+
563
+ **Built with ❤️ for content creators**