@apollohg/react-native-rich-text-editor 2.0.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 (494) hide show
  1. package/LICENSE +160 -0
  2. package/README.md +259 -0
  3. package/RUST-STANDARD-LIBRARY-NOTICES.html +8266 -0
  4. package/ReactNativeProseEditor.podspec +59 -0
  5. package/THIRD_PARTY_NOTICES.md +31155 -0
  6. package/android/build.gradle +188 -0
  7. package/android/consumer-rules.pro +18 -0
  8. package/android/expo/build.gradle +17 -0
  9. package/android/src/debug/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +7 -0
  10. package/android/src/main/assets/editor-icons/MaterialIcons.json +2236 -0
  11. package/android/src/main/assets/editor-icons/MaterialIcons.ttf +0 -0
  12. package/android/src/main/java/com/apollohg/editor/AndroidApiCompat.kt +19 -0
  13. package/android/src/main/java/com/apollohg/editor/AndroidCollaborationTransport.kt +860 -0
  14. package/android/src/main/java/com/apollohg/editor/CaretGeometry.kt +91 -0
  15. package/android/src/main/java/com/apollohg/editor/CodeHighlighting.kt +141 -0
  16. package/android/src/main/java/com/apollohg/editor/DecodedBitmapBudget.kt +250 -0
  17. package/android/src/main/java/com/apollohg/editor/EditorAddons.kt +133 -0
  18. package/android/src/main/java/com/apollohg/editor/EditorBlockSpacing.kt +51 -0
  19. package/android/src/main/java/com/apollohg/editor/EditorBoxDrawable.kt +16 -0
  20. package/android/src/main/java/com/apollohg/editor/EditorBoxDrawing.kt +234 -0
  21. package/android/src/main/java/com/apollohg/editor/EditorCheckboxSpan.kt +87 -0
  22. package/android/src/main/java/com/apollohg/editor/EditorCodeHighlighting.kt +120 -0
  23. package/android/src/main/java/com/apollohg/editor/EditorDecorationLayer.java +18 -0
  24. package/android/src/main/java/com/apollohg/editor/EditorDocumentLayout.kt +626 -0
  25. package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +1042 -0
  26. package/android/src/main/java/com/apollohg/editor/EditorEditTextAnnotations.kt +191 -0
  27. package/android/src/main/java/com/apollohg/editor/EditorEditTextCaret.kt +100 -0
  28. package/android/src/main/java/com/apollohg/editor/EditorEditTextClipboard.kt +101 -0
  29. package/android/src/main/java/com/apollohg/editor/EditorEditTextComposition.kt +220 -0
  30. package/android/src/main/java/com/apollohg/editor/EditorEditTextConfiguration.kt +316 -0
  31. package/android/src/main/java/com/apollohg/editor/EditorEditTextCorrection.kt +303 -0
  32. package/android/src/main/java/com/apollohg/editor/EditorEditTextDeferredUpdates.kt +327 -0
  33. package/android/src/main/java/com/apollohg/editor/EditorEditTextDeletion.kt +258 -0
  34. package/android/src/main/java/com/apollohg/editor/EditorEditTextDiagnostics.kt +83 -0
  35. package/android/src/main/java/com/apollohg/editor/EditorEditTextDragDrop.kt +67 -0
  36. package/android/src/main/java/com/apollohg/editor/EditorEditTextExternalComposition.kt +357 -0
  37. package/android/src/main/java/com/apollohg/editor/EditorEditTextHardwareInput.kt +277 -0
  38. package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +280 -0
  39. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputLifecycle.kt +183 -0
  40. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputPreparation.kt +79 -0
  41. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputTraits.kt +384 -0
  42. package/android/src/main/java/com/apollohg/editor/EditorEditTextLayout.kt +100 -0
  43. package/android/src/main/java/com/apollohg/editor/EditorEditTextNativeMutation.kt +243 -0
  44. package/android/src/main/java/com/apollohg/editor/EditorEditTextPlaceholder.kt +154 -0
  45. package/android/src/main/java/com/apollohg/editor/EditorEditTextRenderPatch.kt +347 -0
  46. package/android/src/main/java/com/apollohg/editor/EditorEditTextRendering.kt +313 -0
  47. package/android/src/main/java/com/apollohg/editor/EditorEditTextRustCommands.kt +281 -0
  48. package/android/src/main/java/com/apollohg/editor/EditorEditTextSelection.kt +352 -0
  49. package/android/src/main/java/com/apollohg/editor/EditorEditTextState.kt +113 -0
  50. package/android/src/main/java/com/apollohg/editor/EditorEditTextTaskMarkers.kt +92 -0
  51. package/android/src/main/java/com/apollohg/editor/EditorEditTextTextCommit.kt +327 -0
  52. package/android/src/main/java/com/apollohg/editor/EditorEditTextToolbar.kt +84 -0
  53. package/android/src/main/java/com/apollohg/editor/EditorEditTextUpdates.kt +245 -0
  54. package/android/src/main/java/com/apollohg/editor/EditorGlyphHeightCursorDrawable.kt +42 -0
  55. package/android/src/main/java/com/apollohg/editor/EditorHeightBehavior.kt +13 -0
  56. package/android/src/main/java/com/apollohg/editor/EditorInputConnection.kt +923 -0
  57. package/android/src/main/java/com/apollohg/editor/EditorInputCoordinates.kt +191 -0
  58. package/android/src/main/java/com/apollohg/editor/EditorInputCorrection.kt +107 -0
  59. package/android/src/main/java/com/apollohg/editor/EditorInputCursorGeometry.kt +128 -0
  60. package/android/src/main/java/com/apollohg/editor/EditorInputSnapshots.kt +134 -0
  61. package/android/src/main/java/com/apollohg/editor/EditorInputSurroundingDeletion.kt +321 -0
  62. package/android/src/main/java/com/apollohg/editor/EditorKeyboardToolbarView.kt +851 -0
  63. package/android/src/main/java/com/apollohg/editor/EditorMentionStyle.kt +192 -0
  64. package/android/src/main/java/com/apollohg/editor/EditorReconciliationWatcher.kt +46 -0
  65. package/android/src/main/java/com/apollohg/editor/EditorStyleSheet.kt +303 -0
  66. package/android/src/main/java/com/apollohg/editor/EditorStyleSheetSpans.kt +253 -0
  67. package/android/src/main/java/com/apollohg/editor/EditorSurfaceInputConnection.kt +67 -0
  68. package/android/src/main/java/com/apollohg/editor/EditorTextDecorationDrawing.kt +143 -0
  69. package/android/src/main/java/com/apollohg/editor/EditorTextSurface.kt +712 -0
  70. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceDragDrop.kt +94 -0
  71. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceInteraction.kt +708 -0
  72. package/android/src/main/java/com/apollohg/editor/EditorTheme.kt +650 -0
  73. package/android/src/main/java/com/apollohg/editor/EditorV2Adapter.kt +912 -0
  74. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterMutations.kt +402 -0
  75. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterRendering.kt +123 -0
  76. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterSelection.kt +203 -0
  77. package/android/src/main/java/com/apollohg/editor/EditorV2Backend.kt +120 -0
  78. package/android/src/main/java/com/apollohg/editor/EditorV2Driver.kt +87 -0
  79. package/android/src/main/java/com/apollohg/editor/EditorV2Registry.kt +97 -0
  80. package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +409 -0
  81. package/android/src/main/java/com/apollohg/editor/ExpoAutoGrowStyleSizePublisher.kt +34 -0
  82. package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +266 -0
  83. package/android/src/main/java/com/apollohg/editor/ImeTextCoordinateMapper.kt +102 -0
  84. package/android/src/main/java/com/apollohg/editor/KeyboardToolbarImeAnimationController.kt +101 -0
  85. package/android/src/main/java/com/apollohg/editor/MentionSuggestionChipView.kt +234 -0
  86. package/android/src/main/java/com/apollohg/editor/NativeCollaborationTransportRegistry.kt +493 -0
  87. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +813 -0
  88. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewAtoms.kt +68 -0
  89. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewBinding.kt +126 -0
  90. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewDiagnostics.kt +208 -0
  91. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewErrors.kt +146 -0
  92. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewEvents.kt +150 -0
  93. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewExternalComposition.kt +39 -0
  94. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewFocus.kt +176 -0
  95. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewLifecycle.kt +302 -0
  96. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewMentions.kt +259 -0
  97. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewNativeActions.kt +179 -0
  98. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewOutsideTap.kt +214 -0
  99. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPendingUpdates.kt +376 -0
  100. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewProperties.kt +234 -0
  101. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPropertyRetries.kt +197 -0
  102. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewToolbar.kt +285 -0
  103. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewTypes.kt +28 -0
  104. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewUpdates.kt +271 -0
  105. package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +687 -0
  106. package/android/src/main/java/com/apollohg/editor/NativeEditorOutsideTapDispatcher.kt +380 -0
  107. package/android/src/main/java/com/apollohg/editor/NativeEditorV2Numbers.kt +45 -0
  108. package/android/src/main/java/com/apollohg/editor/NativeEditorViewRegistry.kt +372 -0
  109. package/android/src/main/java/com/apollohg/editor/NativeImagePipeline.kt +22 -0
  110. package/android/src/main/java/com/apollohg/editor/NativeToolbar.kt +193 -0
  111. package/android/src/main/java/com/apollohg/editor/NativeToolbarIcons.kt +177 -0
  112. package/android/src/main/java/com/apollohg/editor/NativeToolbarItem.kt +274 -0
  113. package/android/src/main/java/com/apollohg/editor/OkHttpCollaborationSocket.kt +102 -0
  114. package/android/src/main/java/com/apollohg/editor/OrderedListMarkerFormatter.kt +130 -0
  115. package/android/src/main/java/com/apollohg/editor/PointerTransparentView.java +18 -0
  116. package/android/src/main/java/com/apollohg/editor/PositionBridge.kt +128 -0
  117. package/android/src/main/java/com/apollohg/editor/ProseViewerView.kt +854 -0
  118. package/android/src/main/java/com/apollohg/editor/RemoteSelectionOverlayView.kt +314 -0
  119. package/android/src/main/java/com/apollohg/editor/RenderBlockSpans.kt +314 -0
  120. package/android/src/main/java/com/apollohg/editor/RenderBridge.kt +224 -0
  121. package/android/src/main/java/com/apollohg/editor/RenderBridgeBlockStyles.kt +407 -0
  122. package/android/src/main/java/com/apollohg/editor/RenderBridgeElements.kt +544 -0
  123. package/android/src/main/java/com/apollohg/editor/RenderBridgeInlineAndAtoms.kt +631 -0
  124. package/android/src/main/java/com/apollohg/editor/RenderBridgeParagraphs.kt +215 -0
  125. package/android/src/main/java/com/apollohg/editor/RenderImageDecoder.kt +748 -0
  126. package/android/src/main/java/com/apollohg/editor/RenderImageLoader.kt +900 -0
  127. package/android/src/main/java/com/apollohg/editor/RenderLayoutConstants.kt +117 -0
  128. package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +337 -0
  129. package/android/src/main/java/com/apollohg/editor/RenderParagraphSpans.kt +182 -0
  130. package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +951 -0
  131. package/android/src/main/java/com/apollohg/editor/SharedNativeImagePipeline.kt +78 -0
  132. package/android/src/main/java/com/apollohg/editor/UniffiEditorV2Backend.kt +261 -0
  133. package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1656 -0
  134. package/android/src/main/java/com/apollohg/editor/viewer/FabricAttachmentSidecars.kt +80 -0
  135. package/android/src/main/java/com/apollohg/editor/viewer/FabricLeaseHandleBridge.kt +59 -0
  136. package/android/src/main/java/com/apollohg/editor/viewer/FallbackSelectionGeometry.kt +450 -0
  137. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseDrawingView.kt +678 -0
  138. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseInstrumentation.kt +608 -0
  139. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayout.kt +186 -0
  140. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutCache.kt +393 -0
  141. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutRegistry.kt +828 -0
  142. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseTheme.kt +316 -0
  143. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerManager.kt +900 -0
  144. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerPackage.kt +16 -0
  145. package/android/src/main/java/com/apollohg/editor/viewer/PreparedViewerAtoms.kt +89 -0
  146. package/android/src/main/java/com/apollohg/editor/viewer/ViewerCodeHighlighting.kt +91 -0
  147. package/android/src/main/java/com/apollohg/editor/viewer/ViewerDocument.kt +453 -0
  148. package/android/src/main/java/com/apollohg/editor/viewer/ViewerFontEnvironment.kt +282 -0
  149. package/android/src/main/java/com/apollohg/editor/viewer/ViewerImagePipeline.kt +460 -0
  150. package/android/src/main/jni/CMakeLists.txt +85 -0
  151. package/android/src/main/jni/PreparedProseViewerMeasurementsManager.cpp +334 -0
  152. package/android/src/main/jni/ReactNativeProseEditorSpec.h +17 -0
  153. package/android/src/main/jni/reactnativeproseeditor.h +6 -0
  154. package/android/src/main/res/values/attrs.xml +6 -0
  155. package/android/src/release/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +9 -0
  156. package/app.plugin.js +62 -0
  157. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseMeasurementsManager.h +62 -0
  158. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerComponentDescriptor.h +30 -0
  159. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.cpp +192 -0
  160. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.h +46 -0
  161. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerState.h +145 -0
  162. package/dist/AtomHost.d.ts +17 -0
  163. package/dist/AtomHost.js +135 -0
  164. package/dist/DefaultAtomChip.d.ts +2 -0
  165. package/dist/DefaultAtomChip.js +22 -0
  166. package/dist/EditorAddon.d.ts +32 -0
  167. package/dist/EditorAddon.js +29 -0
  168. package/dist/EditorAddonNormalization.d.ts +6 -0
  169. package/dist/EditorAddonNormalization.js +48 -0
  170. package/dist/EditorMentionThemeNormalization.d.ts +8 -0
  171. package/dist/EditorMentionThemeNormalization.js +22 -0
  172. package/dist/EditorMentionThemeValidation.d.ts +12 -0
  173. package/dist/EditorMentionThemeValidation.js +95 -0
  174. package/dist/EditorStyleSheet.d.ts +4 -0
  175. package/dist/EditorStyleSheet.js +10 -0
  176. package/dist/EditorStyleSheetNormalization.d.ts +3 -0
  177. package/dist/EditorStyleSheetNormalization.js +226 -0
  178. package/dist/EditorStyleSheetTypes.d.ts +151 -0
  179. package/dist/EditorStyleSheetTypes.js +2 -0
  180. package/dist/EditorTheme.d.ts +117 -0
  181. package/dist/EditorTheme.js +41 -0
  182. package/dist/EditorToolbar.d.ts +4 -0
  183. package/dist/EditorToolbar.js +17 -0
  184. package/dist/EditorToolbarComponent.d.ts +13 -0
  185. package/dist/EditorToolbarComponent.js +24 -0
  186. package/dist/EditorToolbarItems.d.ts +9 -0
  187. package/dist/EditorToolbarItems.js +58 -0
  188. package/dist/EditorToolbarRegistry.d.ts +59 -0
  189. package/dist/EditorToolbarRegistry.js +175 -0
  190. package/dist/EditorToolbarTypes.d.ts +273 -0
  191. package/dist/EditorToolbarTypes.js +2 -0
  192. package/dist/EditorToolbarVisuals.d.ts +154 -0
  193. package/dist/EditorToolbarVisuals.js +228 -0
  194. package/dist/EditorUpdateRevision.d.ts +8 -0
  195. package/dist/EditorUpdateRevision.js +22 -0
  196. package/dist/ExternalTextComposition.d.ts +45 -0
  197. package/dist/ExternalTextComposition.js +537 -0
  198. package/dist/ImageLoadingPolicy.d.ts +54 -0
  199. package/dist/ImageLoadingPolicy.js +60 -0
  200. package/dist/NativeEditorBoundaryError.d.ts +111 -0
  201. package/dist/NativeEditorBoundaryError.js +268 -0
  202. package/dist/NativeEditorBridge.d.ts +9 -0
  203. package/dist/NativeEditorBridge.js +37 -0
  204. package/dist/NativeEditorCollaborationTransport.d.ts +154 -0
  205. package/dist/NativeEditorCollaborationTransport.js +275 -0
  206. package/dist/NativeEditorCreateConfig.d.ts +16 -0
  207. package/dist/NativeEditorCreateConfig.js +249 -0
  208. package/dist/NativeEditorCreateJson.d.ts +76 -0
  209. package/dist/NativeEditorCreateJson.js +474 -0
  210. package/dist/NativeEditorCreateValidation.d.ts +32 -0
  211. package/dist/NativeEditorCreateValidation.js +150 -0
  212. package/dist/NativeEditorDocumentBridge.d.ts +72 -0
  213. package/dist/NativeEditorDocumentBridge.js +305 -0
  214. package/dist/NativeEditorDocumentHandle.d.ts +70 -0
  215. package/dist/NativeEditorDocumentHandle.js +89 -0
  216. package/dist/NativeEditorLocalAwareness.d.ts +34 -0
  217. package/dist/NativeEditorLocalAwareness.js +153 -0
  218. package/dist/NativeEditorNativeModule.d.ts +48 -0
  219. package/dist/NativeEditorNativeModule.js +34 -0
  220. package/dist/NativeEditorRenderNormalization.d.ts +22 -0
  221. package/dist/NativeEditorRenderNormalization.js +274 -0
  222. package/dist/NativeEditorResultNormalization.d.ts +108 -0
  223. package/dist/NativeEditorResultNormalization.js +400 -0
  224. package/dist/NativeEditorTypes.d.ts +318 -0
  225. package/dist/NativeEditorTypes.js +15 -0
  226. package/dist/NativeEditorV2Decimal.d.ts +5 -0
  227. package/dist/NativeEditorV2Decimal.js +18 -0
  228. package/dist/NativeProseViewer.d.ts +122 -0
  229. package/dist/NativeProseViewer.js +130 -0
  230. package/dist/NativeRichTextEditor.d.ts +3 -0
  231. package/dist/NativeRichTextEditor.js +6 -0
  232. package/dist/ResourceLimits.d.ts +100 -0
  233. package/dist/ResourceLimits.js +80 -0
  234. package/dist/RichTextEditor.d.ts +4 -0
  235. package/dist/RichTextEditor.js +25 -0
  236. package/dist/RichTextEditorNativeTypes.d.ts +122 -0
  237. package/dist/RichTextEditorNativeTypes.js +2 -0
  238. package/dist/RichTextEditorNativeView.d.ts +12 -0
  239. package/dist/RichTextEditorNativeView.js +15 -0
  240. package/dist/RichTextEditorSerialization.d.ts +53 -0
  241. package/dist/RichTextEditorSerialization.js +283 -0
  242. package/dist/RichTextEditorTypes.d.ts +281 -0
  243. package/dist/RichTextEditorTypes.js +2 -0
  244. package/dist/ViewerConfiguration.d.ts +22 -0
  245. package/dist/ViewerConfiguration.js +6 -0
  246. package/dist/YjsCollaboration.d.ts +146 -0
  247. package/dist/YjsCollaboration.js +496 -0
  248. package/dist/addons.d.ts +193 -0
  249. package/dist/addons.js +122 -0
  250. package/dist/atomConstants.d.ts +3 -0
  251. package/dist/atomConstants.js +6 -0
  252. package/dist/atomInstances.d.ts +35 -0
  253. package/dist/atomInstances.js +79 -0
  254. package/dist/atomPolicy.d.ts +4 -0
  255. package/dist/atomPolicy.js +47 -0
  256. package/dist/atomUpdates.d.ts +2 -0
  257. package/dist/atomUpdates.js +38 -0
  258. package/dist/atoms.d.ts +92 -0
  259. package/dist/atoms.js +222 -0
  260. package/dist/attributeValidation.d.ts +4 -0
  261. package/dist/attributeValidation.js +97 -0
  262. package/dist/contentExpression.d.ts +6 -0
  263. package/dist/contentExpression.js +335 -0
  264. package/dist/index.d.ts +21 -0
  265. package/dist/index.js +78 -0
  266. package/dist/listMarkers.d.ts +15 -0
  267. package/dist/listMarkers.js +21 -0
  268. package/dist/schemaDefinition.d.ts +143 -0
  269. package/dist/schemaDefinition.js +206 -0
  270. package/dist/schemaDocument.d.ts +17 -0
  271. package/dist/schemaDocument.js +69 -0
  272. package/dist/schemaDocumentConstruction.d.ts +5 -0
  273. package/dist/schemaDocumentConstruction.js +125 -0
  274. package/dist/schemaNormalization.d.ts +29 -0
  275. package/dist/schemaNormalization.js +313 -0
  276. package/dist/schemaPresets.d.ts +68 -0
  277. package/dist/schemaPresets.js +198 -0
  278. package/dist/schemaResolution.d.ts +9 -0
  279. package/dist/schemaResolution.js +211 -0
  280. package/dist/schemas.d.ts +5 -0
  281. package/dist/schemas.js +28 -0
  282. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +37 -0
  283. package/dist/specs/PreparedProseViewerNativeComponent.js +6 -0
  284. package/dist/useEditorToolbarInteractions.d.ts +12 -0
  285. package/dist/useEditorToolbarInteractions.js +218 -0
  286. package/dist/useEditorToolbarItems.d.ts +8 -0
  287. package/dist/useEditorToolbarItems.js +280 -0
  288. package/dist/useEditorToolbarPresentation.d.ts +4 -0
  289. package/dist/useEditorToolbarPresentation.js +203 -0
  290. package/dist/useEditorToolbarState.d.ts +63 -0
  291. package/dist/useEditorToolbarState.js +108 -0
  292. package/dist/useFocusPreservingFrames.d.ts +17 -0
  293. package/dist/useFocusPreservingFrames.js +108 -0
  294. package/dist/useNativeEditor.d.ts +66 -0
  295. package/dist/useNativeEditor.js +370 -0
  296. package/dist/useRichTextEditorCommands.d.ts +21 -0
  297. package/dist/useRichTextEditorCommands.js +299 -0
  298. package/dist/useRichTextEditorEvents.d.ts +18 -0
  299. package/dist/useRichTextEditorEvents.js +216 -0
  300. package/dist/useRichTextEditorMentions.d.ts +11 -0
  301. package/dist/useRichTextEditorMentions.js +316 -0
  302. package/dist/useRichTextEditorPresentation.d.ts +5 -0
  303. package/dist/useRichTextEditorPresentation.js +178 -0
  304. package/dist/useRichTextEditorState.d.ts +180 -0
  305. package/dist/useRichTextEditorState.js +405 -0
  306. package/dist/useRichTextEditorUpdates.d.ts +10 -0
  307. package/dist/useRichTextEditorUpdates.js +308 -0
  308. package/dist/useViewerAtoms.d.ts +38 -0
  309. package/dist/useViewerAtoms.js +288 -0
  310. package/expo-module.config.json +13 -0
  311. package/ios/EditorAddons.swift +354 -0
  312. package/ios/EditorCodeHighlighting.swift +184 -0
  313. package/ios/EditorCore.xcframework/Info.plist +44 -0
  314. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  315. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  316. package/ios/EditorInteractionOverlays.swift +697 -0
  317. package/ios/EditorLayoutManager.swift +971 -0
  318. package/ios/EditorNodeTypes.swift +37 -0
  319. package/ios/EditorStyleSheet.swift +461 -0
  320. package/ios/EditorTextView+AttributedPatch.swift +305 -0
  321. package/ios/EditorTextView+Binding.swift +61 -0
  322. package/ios/EditorTextView+Caret.swift +333 -0
  323. package/ios/EditorTextView+Commands.swift +203 -0
  324. package/ios/EditorTextView+Delegate.swift +65 -0
  325. package/ios/EditorTextView+Diagnostics.swift +225 -0
  326. package/ios/EditorTextView+DragDrop.swift +290 -0
  327. package/ios/EditorTextView+ExternalComposition.swift +364 -0
  328. package/ios/EditorTextView+Images.swift +354 -0
  329. package/ios/EditorTextView+InputTraits.swift +200 -0
  330. package/ios/EditorTextView+KeyboardInput.swift +318 -0
  331. package/ios/EditorTextView+Layout.swift +245 -0
  332. package/ios/EditorTextView+MarkedText.swift +267 -0
  333. package/ios/EditorTextView+NativeInputLifecycle.swift +372 -0
  334. package/ios/EditorTextView+NativeMutation.swift +471 -0
  335. package/ios/EditorTextView+Reconciliation.swift +97 -0
  336. package/ios/EditorTextView+RenderPatch.swift +573 -0
  337. package/ios/EditorTextView+Rendering.swift +539 -0
  338. package/ios/EditorTextView+Selection.swift +542 -0
  339. package/ios/EditorTextView.swift +953 -0
  340. package/ios/EditorTheme.swift +626 -0
  341. package/ios/EditorV2Adapter+Commands.swift +204 -0
  342. package/ios/EditorV2Adapter+Envelope.swift +238 -0
  343. package/ios/EditorV2Adapter+Mutation.swift +392 -0
  344. package/ios/EditorV2Adapter+Registry.swift +185 -0
  345. package/ios/EditorV2Adapter+RenderState.swift +360 -0
  346. package/ios/EditorV2Adapter+RenderValidation.swift +420 -0
  347. package/ios/EditorV2Adapter+Selection.swift +329 -0
  348. package/ios/EditorV2Adapter+TextCommands.swift +430 -0
  349. package/ios/EditorV2Adapter.swift +376 -0
  350. package/ios/EditorV2Shadow.swift +353 -0
  351. package/ios/Generated_editor_core.swift +2378 -0
  352. package/ios/NativeCodeHighlighting.swift +159 -0
  353. package/ios/NativeCollaborationSocket.swift +144 -0
  354. package/ios/NativeCollaborationTransport+Protocol.swift +258 -0
  355. package/ios/NativeCollaborationTransport+Socket.swift +379 -0
  356. package/ios/NativeCollaborationTransport+Validation.swift +103 -0
  357. package/ios/NativeCollaborationTransport.swift +322 -0
  358. package/ios/NativeCollaborationTransportRegistry.swift +521 -0
  359. package/ios/NativeEditorExpoView+AccessoryRetry.swift +219 -0
  360. package/ios/NativeEditorExpoView+Binding.swift +268 -0
  361. package/ios/NativeEditorExpoView+Diagnostics.swift +66 -0
  362. package/ios/NativeEditorExpoView+Events.swift +131 -0
  363. package/ios/NativeEditorExpoView+Focus.swift +169 -0
  364. package/ios/NativeEditorExpoView+MentionRetry.swift +288 -0
  365. package/ios/NativeEditorExpoView+Mentions.swift +288 -0
  366. package/ios/NativeEditorExpoView+Properties.swift +300 -0
  367. package/ios/NativeEditorExpoView+Toolbar.swift +86 -0
  368. package/ios/NativeEditorExpoView+Updates.swift +312 -0
  369. package/ios/NativeEditorExpoView.swift +349 -0
  370. package/ios/NativeEditorModule.swift +856 -0
  371. package/ios/NativeEditorViewRegistry.swift +226 -0
  372. package/ios/NativeToolbar+ButtonStyle.swift +214 -0
  373. package/ios/NativeToolbar+Buttons.swift +228 -0
  374. package/ios/NativeToolbar+Diagnostics.swift +114 -0
  375. package/ios/NativeToolbar+Menu.swift +101 -0
  376. package/ios/NativeToolbar+Models.swift +519 -0
  377. package/ios/NativeToolbar+Placeholder.swift +39 -0
  378. package/ios/NativeToolbar.swift +612 -0
  379. package/ios/OrderedListMarkerFormatter.swift +103 -0
  380. package/ios/PositionBridge.swift +596 -0
  381. package/ios/ProseViewerView.swift +462 -0
  382. package/ios/RenderBridge+Atoms.swift +288 -0
  383. package/ios/RenderBridge+Attachments.swift +246 -0
  384. package/ios/RenderBridge+BlockBoundaries.swift +313 -0
  385. package/ios/RenderBridge+Style.swift +343 -0
  386. package/ios/RenderBridge.swift +704 -0
  387. package/ios/RichTextEditorView.swift +930 -0
  388. package/ios/SharedNativeImagePipeline+Cache.swift +189 -0
  389. package/ios/SharedNativeImagePipeline+Transport.swift +328 -0
  390. package/ios/SharedNativeImagePipeline.swift +533 -0
  391. package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +436 -0
  392. package/ios/Viewer/CoreTextProseLayoutEngine+Models.swift +322 -0
  393. package/ios/Viewer/CoreTextProseLayoutEngine.swift +635 -0
  394. package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.h +4 -0
  395. package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.mm +767 -0
  396. package/ios/Viewer/Fabric/PreparedProseMeasurementsManager.mm +118 -0
  397. package/ios/Viewer/NativeSVGImageDecoder.h +9 -0
  398. package/ios/Viewer/NativeSVGImageDecoder.mm +106 -0
  399. package/ios/Viewer/NativeSVGPreflight.h +11 -0
  400. package/ios/Viewer/NativeSVGPreflight.mm +219 -0
  401. package/ios/Viewer/PreparedProseDrawingView.swift +639 -0
  402. package/ios/Viewer/PreparedProseInstrumentation.swift +387 -0
  403. package/ios/Viewer/PreparedProseLayout.swift +326 -0
  404. package/ios/Viewer/PreparedProseLayoutCache.swift +766 -0
  405. package/ios/Viewer/PreparedProseLayoutRegistry+Artifacts.swift +377 -0
  406. package/ios/Viewer/PreparedProseLayoutRegistry+Fabric.swift +582 -0
  407. package/ios/Viewer/PreparedProseLayoutRegistry+FabricOwnership.swift +128 -0
  408. package/ios/Viewer/PreparedProseLayoutRegistry.swift +381 -0
  409. package/ios/Viewer/ViewerDocument.swift +575 -0
  410. package/ios/Viewer/ViewerFontEnvironment.swift +283 -0
  411. package/ios/Viewer/ViewerImagePipeline.swift +478 -0
  412. package/ios/editor_coreFFI/editor_coreFFI.h +1023 -0
  413. package/ios/editor_coreFFI/module.modulemap +7 -0
  414. package/package.json +151 -0
  415. package/react-native.config.js +17 -0
  416. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  417. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  418. package/rust/android/x86/libeditor_core.so +0 -0
  419. package/rust/android/x86_64/libeditor_core.so +0 -0
  420. package/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +3146 -0
  421. package/src/AtomHost.tsx +180 -0
  422. package/src/DefaultAtomChip.tsx +27 -0
  423. package/src/EditorAddon.ts +65 -0
  424. package/src/EditorAddonNormalization.ts +49 -0
  425. package/src/EditorMentionThemeNormalization.ts +25 -0
  426. package/src/EditorMentionThemeValidation.ts +133 -0
  427. package/src/EditorStyleSheet.ts +9 -0
  428. package/src/EditorStyleSheetNormalization.ts +219 -0
  429. package/src/EditorStyleSheetTypes.ts +189 -0
  430. package/src/EditorTheme.ts +196 -0
  431. package/src/EditorToolbar.tsx +31 -0
  432. package/src/EditorToolbarComponent.tsx +23 -0
  433. package/src/EditorToolbarItems.tsx +64 -0
  434. package/src/EditorToolbarRegistry.tsx +254 -0
  435. package/src/EditorToolbarTypes.tsx +322 -0
  436. package/src/EditorToolbarVisuals.tsx +270 -0
  437. package/src/EditorUpdateRevision.ts +26 -0
  438. package/src/ExternalTextComposition.ts +658 -0
  439. package/src/ImageLoadingPolicy.ts +125 -0
  440. package/src/NativeEditorBoundaryError.ts +345 -0
  441. package/src/NativeEditorBridge.ts +93 -0
  442. package/src/NativeEditorCollaborationTransport.ts +493 -0
  443. package/src/NativeEditorCreateConfig.ts +326 -0
  444. package/src/NativeEditorCreateJson.ts +579 -0
  445. package/src/NativeEditorCreateValidation.ts +178 -0
  446. package/src/NativeEditorDocumentBridge.ts +485 -0
  447. package/src/NativeEditorDocumentHandle.ts +168 -0
  448. package/src/NativeEditorLocalAwareness.ts +168 -0
  449. package/src/NativeEditorNativeModule.ts +97 -0
  450. package/src/NativeEditorRenderNormalization.ts +320 -0
  451. package/src/NativeEditorResultNormalization.ts +469 -0
  452. package/src/NativeEditorTypes.ts +366 -0
  453. package/src/NativeEditorV2Decimal.ts +13 -0
  454. package/src/NativeProseViewer.tsx +356 -0
  455. package/src/NativeRichTextEditor.tsx +33 -0
  456. package/src/ResourceLimits.ts +187 -0
  457. package/src/RichTextEditor.tsx +27 -0
  458. package/src/RichTextEditorNativeTypes.tsx +144 -0
  459. package/src/RichTextEditorNativeView.tsx +21 -0
  460. package/src/RichTextEditorSerialization.tsx +381 -0
  461. package/src/RichTextEditorTypes.tsx +327 -0
  462. package/src/ViewerConfiguration.ts +23 -0
  463. package/src/YjsCollaboration.ts +692 -0
  464. package/src/addons.ts +311 -0
  465. package/src/atomConstants.ts +3 -0
  466. package/src/atomInstances.ts +123 -0
  467. package/src/atomPolicy.ts +47 -0
  468. package/src/atomUpdates.ts +52 -0
  469. package/src/atoms.ts +379 -0
  470. package/src/attributeValidation.ts +116 -0
  471. package/src/contentExpression.ts +338 -0
  472. package/src/index.ts +295 -0
  473. package/src/listMarkers.ts +18 -0
  474. package/src/schemaDefinition.ts +395 -0
  475. package/src/schemaDocument.ts +92 -0
  476. package/src/schemaDocumentConstruction.ts +148 -0
  477. package/src/schemaNormalization.ts +367 -0
  478. package/src/schemaPresets.ts +250 -0
  479. package/src/schemaResolution.ts +242 -0
  480. package/src/schemas.ts +43 -0
  481. package/src/specs/PreparedProseViewerNativeComponent.ts +40 -0
  482. package/src/useEditorToolbarInteractions.tsx +329 -0
  483. package/src/useEditorToolbarItems.tsx +390 -0
  484. package/src/useEditorToolbarPresentation.tsx +483 -0
  485. package/src/useEditorToolbarState.tsx +172 -0
  486. package/src/useFocusPreservingFrames.ts +171 -0
  487. package/src/useNativeEditor.ts +534 -0
  488. package/src/useRichTextEditorCommands.tsx +478 -0
  489. package/src/useRichTextEditorEvents.tsx +342 -0
  490. package/src/useRichTextEditorMentions.tsx +441 -0
  491. package/src/useRichTextEditorPresentation.tsx +563 -0
  492. package/src/useRichTextEditorState.tsx +620 -0
  493. package/src/useRichTextEditorUpdates.tsx +403 -0
  494. package/src/useViewerAtoms.tsx +427 -0
@@ -0,0 +1,305 @@
1
+ import os
2
+ import UIKit
3
+
4
+ extension EditorTextView {
5
+ func shouldUseSmallPatchTextMutation(
6
+ for attributedString: NSAttributedString,
7
+ replaceRange: NSRange?
8
+ ) -> Bool {
9
+ attributedString.length > 0
10
+ && attributedString.length <= 512
11
+ && (replaceRange?.length ?? 0) <= 512
12
+ && !attributedStringContainsAttachment(attributedString)
13
+ }
14
+
15
+ private func attributesEqualForPatchTrimming(
16
+ _ lhs: [NSAttributedString.Key: Any],
17
+ _ rhs: [NSAttributedString.Key: Any]
18
+ ) -> Bool {
19
+ // `docPos` and `topLevelChildIndex` are positional metadata consumed
20
+ // by atom actions and future patch-range resolution. Trimming across
21
+ // either change would preserve stale attributed metadata.
22
+ NSDictionary(dictionary: lhs).isEqual(to: rhs)
23
+ }
24
+
25
+ func applyAttributes(from attributedString: NSAttributedString, to destinationRange: NSRange) {
26
+ guard attributedString.length == destinationRange.length else { return }
27
+ if let uniformAttributes = uniformAttributes(in: attributedString) {
28
+ textStorage.setAttributes(uniformAttributes, range: destinationRange)
29
+ return
30
+ }
31
+ let sourceRange = NSRange(location: 0, length: attributedString.length)
32
+ attributedString.enumerateAttributes(
33
+ in: sourceRange,
34
+ options: [.longestEffectiveRangeNotRequired]
35
+ ) { attrs, range, _ in
36
+ let targetRange = NSRange(location: destinationRange.location + range.location, length: range.length)
37
+ textStorage.setAttributes(attrs, range: targetRange)
38
+ }
39
+ }
40
+
41
+ private func uniformAttributes(in attributedString: NSAttributedString) -> [NSAttributedString.Key: Any]? {
42
+ guard attributedString.length > 0 else { return [:] }
43
+ let firstAttributes = attributedString.attributes(at: 0, effectiveRange: nil)
44
+ var isUniform = true
45
+ attributedString.enumerateAttributes(
46
+ in: NSRange(location: 0, length: attributedString.length),
47
+ options: [.longestEffectiveRangeNotRequired]
48
+ ) { attrs, _, stop in
49
+ guard (attrs as NSDictionary).isEqual(firstAttributes) else {
50
+ isUniform = false
51
+ stop.pointee = true
52
+ return
53
+ }
54
+ }
55
+ return isUniform ? firstAttributes : nil
56
+ }
57
+
58
+ func attributedStringContainsAttachment(_ attributedString: NSAttributedString) -> Bool {
59
+ guard attributedString.length > 0 else { return false }
60
+ var hasAttachment = false
61
+ attributedString.enumerateAttribute(
62
+ .attachment,
63
+ in: NSRange(location: 0, length: attributedString.length),
64
+ options: [.longestEffectiveRangeNotRequired]
65
+ ) { value, _, stop in
66
+ if value != nil {
67
+ hasAttachment = true
68
+ stop.pointee = true
69
+ }
70
+ }
71
+ return hasAttachment
72
+ }
73
+
74
+ func attributedStringContainsPositionAdjustments(_ attributedString: NSAttributedString) -> Bool {
75
+ guard attributedString.length > 0 else { return false }
76
+ var hasAdjustments = false
77
+ attributedString.enumerateAttributes(
78
+ in: NSRange(location: 0, length: attributedString.length),
79
+ options: [.longestEffectiveRangeNotRequired]
80
+ ) { attrs, _, stop in
81
+ if attrs[RenderBridgeAttributes.syntheticPlaceholder] as? Bool == true
82
+ || attrs[RenderBridgeAttributes.listMarkerContext] != nil {
83
+ hasAdjustments = true
84
+ stop.pointee = true
85
+ }
86
+ }
87
+ return hasAdjustments
88
+ }
89
+
90
+ func attributedStringContainsListMarkerContext(_ attributedString: NSAttributedString) -> Bool {
91
+ guard attributedString.length > 0 else { return false }
92
+ var hasListMarkerContext = false
93
+ attributedString.enumerateAttribute(
94
+ RenderBridgeAttributes.listMarkerContext,
95
+ in: NSRange(location: 0, length: attributedString.length),
96
+ options: [.longestEffectiveRangeNotRequired]
97
+ ) { value, _, stop in
98
+ if value != nil {
99
+ hasListMarkerContext = true
100
+ stop.pointee = true
101
+ }
102
+ }
103
+ return hasListMarkerContext
104
+ }
105
+
106
+ func textStorageRangeContainsPositionAdjustments(_ range: NSRange) -> Bool {
107
+ guard range.length > 0,
108
+ range.location >= 0,
109
+ range.location + range.length <= textStorage.length
110
+ else {
111
+ return false
112
+ }
113
+
114
+ var hasAdjustments = false
115
+ textStorage.enumerateAttributes(
116
+ in: range,
117
+ options: [.longestEffectiveRangeNotRequired]
118
+ ) { attrs, _, stop in
119
+ if attrs[RenderBridgeAttributes.syntheticPlaceholder] as? Bool == true
120
+ || attrs[RenderBridgeAttributes.listMarkerContext] != nil {
121
+ hasAdjustments = true
122
+ stop.pointee = true
123
+ }
124
+ }
125
+ return hasAdjustments
126
+ }
127
+
128
+ func textStorageRangeContainsListMarkerContext(_ range: NSRange) -> Bool {
129
+ guard range.length > 0,
130
+ range.location >= 0,
131
+ range.location + range.length <= textStorage.length
132
+ else {
133
+ return false
134
+ }
135
+
136
+ var hasListMarkerContext = false
137
+ textStorage.enumerateAttribute(
138
+ RenderBridgeAttributes.listMarkerContext,
139
+ in: range,
140
+ options: [.longestEffectiveRangeNotRequired]
141
+ ) { value, _, stop in
142
+ if value != nil {
143
+ hasListMarkerContext = true
144
+ stop.pointee = true
145
+ }
146
+ }
147
+ return hasListMarkerContext
148
+ }
149
+
150
+ func textStorageRangeContainsAttachment(_ range: NSRange) -> Bool {
151
+ guard range.length > 0,
152
+ range.location >= 0,
153
+ range.location + range.length <= textStorage.length
154
+ else {
155
+ return false
156
+ }
157
+
158
+ var hasAttachment = false
159
+ textStorage.enumerateAttribute(
160
+ .attachment,
161
+ in: range,
162
+ options: [.longestEffectiveRangeNotRequired]
163
+ ) { value, _, stop in
164
+ if value != nil {
165
+ hasAttachment = true
166
+ stop.pointee = true
167
+ }
168
+ }
169
+ return hasAttachment
170
+ }
171
+
172
+ func topLevelChildrenContainAttachment(
173
+ startIndex: Int,
174
+ deleteCount: Int
175
+ ) -> Bool {
176
+ guard deleteCount > 0,
177
+ let currentTopLevelChildMetadata,
178
+ startIndex >= 0,
179
+ startIndex + deleteCount <= currentTopLevelChildMetadata.count
180
+ else {
181
+ return false
182
+ }
183
+ return currentTopLevelChildMetadata[startIndex..<(startIndex + deleteCount)]
184
+ .contains(where: \.containsAttachment)
185
+ }
186
+
187
+ func topLevelChildrenContainPositionAdjustments(
188
+ startIndex: Int,
189
+ deleteCount: Int
190
+ ) -> Bool {
191
+ guard deleteCount > 0,
192
+ let currentTopLevelChildMetadata,
193
+ startIndex >= 0,
194
+ startIndex + deleteCount <= currentTopLevelChildMetadata.count
195
+ else {
196
+ return false
197
+ }
198
+ return currentTopLevelChildMetadata[startIndex..<(startIndex + deleteCount)]
199
+ .contains(where: \.containsPositionAdjustments)
200
+ }
201
+
202
+ func trimmedAttributedPatch(
203
+ replacing fullReplaceRange: NSRange,
204
+ with replacement: NSAttributedString
205
+ ) -> (replaceRange: NSRange, replacement: NSAttributedString) {
206
+ guard fullReplaceRange.length > 0 else {
207
+ return (fullReplaceRange, replacement)
208
+ }
209
+
210
+ let existing = textStorage.attributedSubstring(from: fullReplaceRange)
211
+ let existingRawString = existing.string
212
+ let replacementRawString = replacement.string
213
+ let existingString = existingRawString as NSString
214
+ let replacementString = replacementRawString as NSString
215
+ let sharedLength = min(existing.length, replacement.length)
216
+
217
+ var prefix = 0
218
+ while prefix < sharedLength {
219
+ var existingRange = NSRange()
220
+ let existingAttrs = existing.attributes(
221
+ at: prefix,
222
+ longestEffectiveRange: &existingRange,
223
+ in: NSRange(location: prefix, length: sharedLength - prefix)
224
+ )
225
+ var replacementRange = NSRange()
226
+ let replacementAttrs = replacement.attributes(
227
+ at: prefix,
228
+ longestEffectiveRange: &replacementRange,
229
+ in: NSRange(location: prefix, length: sharedLength - prefix)
230
+ )
231
+ guard attributesEqualForPatchTrimming(existingAttrs, replacementAttrs) else { break }
232
+ let runEnd = min(NSMaxRange(existingRange), NSMaxRange(replacementRange), sharedLength)
233
+ while prefix < runEnd,
234
+ existingString.character(at: prefix) == replacementString.character(at: prefix) {
235
+ prefix += 1
236
+ }
237
+ if prefix < runEnd {
238
+ break
239
+ }
240
+ }
241
+
242
+ var suffix = 0
243
+ while suffix < (sharedLength - prefix) {
244
+ let existingIndex = existing.length - suffix - 1
245
+ let replacementIndex = replacement.length - suffix - 1
246
+ var existingRange = NSRange()
247
+ let existingAttrs = existing.attributes(
248
+ at: existingIndex,
249
+ longestEffectiveRange: &existingRange,
250
+ in: NSRange(location: prefix, length: existingIndex - prefix + 1)
251
+ )
252
+ var replacementRange = NSRange()
253
+ let replacementAttrs = replacement.attributes(
254
+ at: replacementIndex,
255
+ longestEffectiveRange: &replacementRange,
256
+ in: NSRange(location: prefix, length: replacementIndex - prefix + 1)
257
+ )
258
+ guard attributesEqualForPatchTrimming(existingAttrs, replacementAttrs) else { break }
259
+ let maxComparableLength = min(
260
+ existingIndex - max(existingRange.location, prefix) + 1,
261
+ replacementIndex - max(replacementRange.location, prefix) + 1,
262
+ sharedLength - prefix - suffix
263
+ )
264
+ var matchedLength = 0
265
+ while matchedLength < maxComparableLength,
266
+ existingString.character(at: existingIndex - matchedLength)
267
+ == replacementString.character(at: replacementIndex - matchedLength) {
268
+ matchedLength += 1
269
+ }
270
+ suffix += matchedLength
271
+ if matchedLength < maxComparableLength {
272
+ break
273
+ }
274
+ }
275
+ prefix = sharedUtf16ScalarBoundary(atOrBefore: prefix, in: existingRawString, and: replacementRawString)
276
+ while suffix > 0 {
277
+ let existingSuffixStart = existing.length - suffix
278
+ let replacementSuffixStart = replacement.length - suffix
279
+ if suffix <= sharedLength - prefix,
280
+ isUtf16ScalarBoundary(existingSuffixStart, in: existingRawString),
281
+ isUtf16ScalarBoundary(replacementSuffixStart, in: replacementRawString) {
282
+ break
283
+ }
284
+ suffix -= 1
285
+ }
286
+
287
+ guard prefix > 0 || suffix > 0 else {
288
+ return (fullReplaceRange, replacement)
289
+ }
290
+
291
+ let trimmedReplaceRange = NSRange(
292
+ location: fullReplaceRange.location + prefix,
293
+ length: fullReplaceRange.length - prefix - suffix
294
+ )
295
+ let trimmedReplacementRange = NSRange(
296
+ location: prefix,
297
+ length: replacement.length - prefix - suffix
298
+ )
299
+ return (
300
+ trimmedReplaceRange,
301
+ replacement.attributedSubstring(from: trimmedReplacementRange)
302
+ )
303
+ }
304
+
305
+ }
@@ -0,0 +1,61 @@
1
+ import os
2
+ import UIKit
3
+
4
+ extension EditorTextView {
5
+ func ownsNativeBinding(_ adapter: EditorV2Adapter) -> Bool {
6
+ adapter.isNativeBindingOwner(token: nativeBindingToken)
7
+ }
8
+
9
+ /// Bind this text view to a Rust editor instance and apply initial content.
10
+ ///
11
+ /// - Parameters:
12
+ /// - id: The editor ID from `editor_create()`.
13
+ /// - initialHTML: Optional HTML to set as initial content.
14
+ func bindEditor(
15
+ id: UInt64,
16
+ initialHTML: String? = nil,
17
+ initialUpdateJSON: String? = nil
18
+ ) {
19
+ ensureInternalTextViewDelegate()
20
+ if editorId == id, initialHTML == nil {
21
+ return
22
+ }
23
+ localTextDragState = .idle
24
+ if editorId != id {
25
+ EditorV2Registry.adapter(forLegacyId: editorId)?
26
+ .releaseNativeBindingOwner(token: nativeBindingToken)
27
+ discardTransientNativeInputForEditorRebind()
28
+ invalidateCurrentRenderBlocks()
29
+ }
30
+ editorId = id
31
+ EditorV2Registry.adapter(forLegacyId: id)?
32
+ .claimNativeBindingIfUnowned(token: nativeBindingToken)
33
+
34
+ if let initialUpdateJSON {
35
+ applyUpdateJSON(initialUpdateJSON, notifyDelegate: false)
36
+ } else if let html = initialHTML, !html.isEmpty {
37
+ let updateJSON = EditorV2Shadow.setHtml(id: editorId, html: html)
38
+ if !applyUpdateJSON(updateJSON, notifyDelegate: false) {
39
+ let stateJSON = EditorV2Shadow.getCurrentState(id: editorId)
40
+ applyUpdateJSON(stateJSON, notifyDelegate: false)
41
+ }
42
+ } else {
43
+ // Pull current state from Rust (content may already be loaded via bridge).
44
+ let stateJSON = EditorV2Shadow.getCurrentState(id: editorId)
45
+ applyUpdateJSON(stateJSON, notifyDelegate: false)
46
+ }
47
+ replayDesiredInputTraitsIfNeeded()
48
+ }
49
+
50
+ /// Unbind from the current editor instance.
51
+ func unbindEditor() {
52
+ codeHighlightingSession.cancel()
53
+ restoreCodeHighlighting()
54
+ discardTransientNativeInputForEditorRebind()
55
+ EditorV2Registry.adapter(forLegacyId: editorId)?
56
+ .releaseNativeBindingOwner(token: nativeBindingToken)
57
+ invalidateCurrentRenderBlocks()
58
+ editorId = 0
59
+ }
60
+
61
+ }
@@ -0,0 +1,333 @@
1
+ import os
2
+ import UIKit
3
+
4
+ extension EditorTextView {
5
+ func resolvedCaretReferenceRect(for position: UITextPosition) -> CGRect {
6
+ let directRect = super.caretRect(for: position)
7
+ if let horizontalRuleRect = resolvedHorizontalRuleAdjacentCaretRect(
8
+ for: position,
9
+ directRect: directRect
10
+ ) {
11
+ return horizontalRuleRect
12
+ }
13
+ guard directRect.height <= 0 || directRect.isEmpty else {
14
+ return directRect
15
+ }
16
+
17
+ let caretWidth = max(directRect.width, 2)
18
+
19
+ if let nextPosition = self.position(from: position, offset: 1),
20
+ let nextRange = textRange(from: position, to: nextPosition),
21
+ let nextRect = selectionRects(for: nextRange)
22
+ .map(\.rect)
23
+ .first(where: { !$0.isEmpty && $0.width > 0 && $0.height > 0 }) {
24
+ return CGRect(
25
+ x: nextRect.minX,
26
+ y: nextRect.minY,
27
+ width: caretWidth,
28
+ height: max(directRect.height, nextRect.height)
29
+ )
30
+ }
31
+
32
+ if let previousPosition = self.position(from: position, offset: -1),
33
+ let previousRange = textRange(from: previousPosition, to: position),
34
+ let previousRect = selectionRects(for: previousRange)
35
+ .map(\.rect)
36
+ .last(where: { !$0.isEmpty && $0.width > 0 && $0.height > 0 }) {
37
+ return CGRect(
38
+ x: previousRect.maxX,
39
+ y: previousRect.minY,
40
+ width: caretWidth,
41
+ height: max(directRect.height, previousRect.height)
42
+ )
43
+ }
44
+
45
+ return directRect
46
+ }
47
+
48
+ private func resolvedHorizontalRuleAdjacentCaretRect(
49
+ for position: UITextPosition,
50
+ directRect: CGRect
51
+ ) -> CGRect? {
52
+ guard textStorage.length > 0 else { return nil }
53
+
54
+ let utf16Offset = offset(from: beginningOfDocument, to: position)
55
+ let caretWidth = max(directRect.width, 2)
56
+
57
+ if isHorizontalRuleAttachment(at: utf16Offset),
58
+ let previousCharacterIndex = nearestVisibleCharacterIndex(
59
+ from: utf16Offset - 1,
60
+ direction: -1
61
+ ),
62
+ let previousRect = visibleSelectionRect(forCharacterAt: previousCharacterIndex) {
63
+ return CGRect(
64
+ x: previousRect.maxX,
65
+ y: previousRect.minY,
66
+ width: caretWidth,
67
+ height: max(directRect.height, previousRect.height)
68
+ )
69
+ }
70
+
71
+ if isHorizontalRuleAttachment(at: utf16Offset - 1),
72
+ let nextCharacterIndex = nearestVisibleCharacterIndex(
73
+ from: utf16Offset,
74
+ direction: 1
75
+ ),
76
+ let nextRect = visibleSelectionRect(forCharacterAt: nextCharacterIndex) {
77
+ return CGRect(
78
+ x: nextRect.minX,
79
+ y: nextRect.minY,
80
+ width: caretWidth,
81
+ height: max(directRect.height, nextRect.height)
82
+ )
83
+ }
84
+
85
+ return nil
86
+ }
87
+
88
+ static func adjustedCaretRect(
89
+ from rect: CGRect,
90
+ targetHeight: CGFloat,
91
+ screenScale: CGFloat
92
+ ) -> CGRect {
93
+ guard rect.height > 0, targetHeight > 0, targetHeight < rect.height else {
94
+ return rect
95
+ }
96
+
97
+ let scale = max(screenScale, 1)
98
+ let alignedHeight = ceil(targetHeight * scale) / scale
99
+ let centeredY = rect.minY + ((rect.height - alignedHeight) / 2.0)
100
+ let alignedY = (centeredY * scale).rounded() / scale
101
+
102
+ var adjusted = rect
103
+ adjusted.origin.y = alignedY
104
+ adjusted.size.height = alignedHeight
105
+ return adjusted
106
+ }
107
+
108
+ static func adjustedCaretRect(
109
+ from rect: CGRect,
110
+ font: UIFont,
111
+ screenScale: CGFloat
112
+ ) -> CGRect {
113
+ let scale = max(screenScale, 1)
114
+ let lineHeight = max(font.lineHeight, 0)
115
+ let alignedHeight = ceil(lineHeight * scale) / scale
116
+ let alignedY = ((rect.maxY - alignedHeight) * scale).rounded() / scale
117
+
118
+ var adjusted = rect
119
+ adjusted.origin.y = alignedY
120
+ adjusted.size.height = alignedHeight
121
+ return adjusted
122
+ }
123
+
124
+ static func adjustedCaretRect(
125
+ from rect: CGRect,
126
+ baselineY: CGFloat,
127
+ font: UIFont,
128
+ screenScale: CGFloat
129
+ ) -> CGRect {
130
+ let scale = max(screenScale, 1)
131
+ let lineHeight = max(font.lineHeight, 0)
132
+ let alignedHeight = ceil(lineHeight * scale) / scale
133
+ let typographicHeight = font.ascender - font.descender
134
+ let leading = max(lineHeight - typographicHeight, 0)
135
+ let topY = baselineY - font.ascender - (leading / 2.0)
136
+ let alignedY = (topY * scale).rounded() / scale
137
+
138
+ var adjusted = rect
139
+ adjusted.origin.y = alignedY
140
+ adjusted.size.height = alignedHeight
141
+ return adjusted
142
+ }
143
+
144
+ func caretBaselineY(for position: UITextPosition, referenceRect: CGRect) -> CGFloat? {
145
+ guard textStorage.length > 0 else { return nil }
146
+
147
+ let rawOffset = offset(from: beginningOfDocument, to: position)
148
+ let clampedOffset = min(max(rawOffset, 0), textStorage.length)
149
+
150
+ if let horizontalRuleBaselineY = horizontalRuleAdjacentBaselineY(at: clampedOffset) {
151
+ return horizontalRuleBaselineY
152
+ }
153
+
154
+ if let hardBreakBaselineY = hardBreakBaselineY(after: clampedOffset) {
155
+ return hardBreakBaselineY
156
+ }
157
+
158
+ var candidateCharacters = Set<Int>()
159
+
160
+ if clampedOffset < textStorage.length {
161
+ candidateCharacters.insert(clampedOffset)
162
+ }
163
+ if clampedOffset > 0 {
164
+ candidateCharacters.insert(clampedOffset - 1)
165
+ }
166
+ if clampedOffset + 1 < textStorage.length {
167
+ candidateCharacters.insert(clampedOffset + 1)
168
+ }
169
+
170
+ guard !candidateCharacters.isEmpty else { return nil }
171
+
172
+ let referenceMidY = referenceRect.midY
173
+ let referenceMinY = referenceRect.minY
174
+ var bestMatch: (score: CGFloat, baselineY: CGFloat)?
175
+
176
+ for characterIndex in candidateCharacters.sorted() {
177
+ let glyphIndex = layoutManager.glyphIndexForCharacter(at: characterIndex)
178
+ guard glyphIndex < layoutManager.numberOfGlyphs else { continue }
179
+
180
+ let lineFragmentRect = layoutManager.lineFragmentRect(
181
+ forGlyphAt: glyphIndex,
182
+ effectiveRange: nil
183
+ )
184
+ let lineRectInView = lineFragmentRect.offsetBy(dx: 0, dy: textContainerInset.top)
185
+ let score = abs(lineRectInView.midY - referenceMidY) * 10
186
+ + abs(lineRectInView.minY - referenceMinY)
187
+ let glyphLocation = layoutManager.location(forGlyphAt: glyphIndex)
188
+ let baselineY = textContainerInset.top + lineFragmentRect.minY + glyphLocation.y
189
+
190
+ if let currentBest = bestMatch, currentBest.score <= score {
191
+ continue
192
+ }
193
+ bestMatch = (score, baselineY)
194
+ }
195
+
196
+ return bestMatch?.baselineY
197
+ }
198
+
199
+ private func horizontalRuleAdjacentBaselineY(at utf16Offset: Int) -> CGFloat? {
200
+ guard textStorage.length > 0 else { return nil }
201
+
202
+ if isHorizontalRuleAttachment(at: utf16Offset),
203
+ let previousCharacterIndex = nearestVisibleCharacterIndex(
204
+ from: utf16Offset - 1,
205
+ direction: -1
206
+ ) {
207
+ return baselineY(forCharacterAt: previousCharacterIndex)
208
+ }
209
+
210
+ if isHorizontalRuleAttachment(at: utf16Offset - 1),
211
+ let nextCharacterIndex = nearestVisibleCharacterIndex(
212
+ from: utf16Offset,
213
+ direction: 1
214
+ ) {
215
+ return baselineY(forCharacterAt: nextCharacterIndex)
216
+ }
217
+
218
+ return nil
219
+ }
220
+
221
+ func baselineY(forCharacterAt characterIndex: Int) -> CGFloat? {
222
+ guard characterIndex >= 0, characterIndex < textStorage.length else { return nil }
223
+
224
+ let glyphIndex = layoutManager.glyphIndexForCharacter(at: characterIndex)
225
+ guard glyphIndex < layoutManager.numberOfGlyphs else { return nil }
226
+
227
+ let lineFragmentRect = layoutManager.lineFragmentRect(
228
+ forGlyphAt: glyphIndex,
229
+ effectiveRange: nil
230
+ )
231
+ let glyphLocation = layoutManager.location(forGlyphAt: glyphIndex)
232
+ return textContainerInset.top + lineFragmentRect.minY + glyphLocation.y
233
+ }
234
+
235
+ private func visibleSelectionRect(forCharacterAt characterIndex: Int) -> CGRect? {
236
+ guard characterIndex >= 0, characterIndex < textStorage.length else { return nil }
237
+ guard let start = position(from: beginningOfDocument, offset: characterIndex),
238
+ let end = position(from: start, offset: 1),
239
+ let range = textRange(from: start, to: end)
240
+ else {
241
+ return nil
242
+ }
243
+
244
+ return selectionRects(for: range)
245
+ .map(\.rect)
246
+ .first(where: { !$0.isEmpty && $0.width > 0 && $0.height > 0 })
247
+ }
248
+
249
+ private func nearestVisibleCharacterIndex(from startIndex: Int, direction: Int) -> Int? {
250
+ guard direction == -1 || direction == 1 else { return nil }
251
+ guard textStorage.length > 0 else { return nil }
252
+
253
+ let text = textStorage.string as NSString
254
+ var index = startIndex
255
+
256
+ while index >= 0, index < text.length {
257
+ let attrs = textStorage.attributes(at: index, effectiveRange: nil)
258
+ let character = text.substring(with: NSRange(location: index, length: 1))
259
+
260
+ if attrs[.attachment] == nil,
261
+ character != "\n",
262
+ character != "\r",
263
+ visibleSelectionRect(forCharacterAt: index) != nil {
264
+ return index
265
+ }
266
+
267
+ index += direction
268
+ }
269
+
270
+ return nil
271
+ }
272
+
273
+ private func isHorizontalRuleAttachment(at utf16Offset: Int) -> Bool {
274
+ guard utf16Offset >= 0, utf16Offset < textStorage.length else { return false }
275
+
276
+ let attrs = textStorage.attributes(at: utf16Offset, effectiveRange: nil)
277
+ return attrs[.attachment] is NSTextAttachment
278
+ && EditorNodeTypes.isHorizontalRule(attrs[RenderBridgeAttributes.voidNodeType] as? String)
279
+ }
280
+
281
+ private func hardBreakBaselineY(after utf16Offset: Int) -> CGFloat? {
282
+ guard utf16Offset > 0, utf16Offset <= textStorage.length else { return nil }
283
+ let previousVoidType = textStorage.attribute(
284
+ RenderBridgeAttributes.voidNodeType,
285
+ at: utf16Offset - 1,
286
+ effectiveRange: nil
287
+ ) as? String
288
+ guard EditorNodeTypes.isHardBreak(previousVoidType) else { return nil }
289
+
290
+ let previousGlyphIndex = layoutManager.glyphIndexForCharacter(at: utf16Offset - 1)
291
+ guard previousGlyphIndex < layoutManager.numberOfGlyphs else { return nil }
292
+
293
+ let lineFragmentRect = layoutManager.lineFragmentRect(
294
+ forGlyphAt: previousGlyphIndex,
295
+ effectiveRange: nil
296
+ )
297
+ let glyphLocation = layoutManager.location(forGlyphAt: previousGlyphIndex)
298
+ let previousBaselineY = textContainerInset.top + lineFragmentRect.minY + glyphLocation.y
299
+
300
+ let paragraphStyle = textStorage.attribute(
301
+ .paragraphStyle,
302
+ at: utf16Offset - 1,
303
+ effectiveRange: nil
304
+ ) as? NSParagraphStyle
305
+ let configuredLineHeight = max(
306
+ paragraphStyle?.minimumLineHeight ?? 0,
307
+ paragraphStyle?.maximumLineHeight ?? 0
308
+ )
309
+ let lineAdvance = configuredLineHeight > 0
310
+ ? configuredLineHeight
311
+ : lineFragmentRect.height
312
+
313
+ return previousBaselineY + lineAdvance
314
+ }
315
+
316
+ func resolvedCaretFont(for position: UITextPosition) -> UIFont {
317
+ guard textStorage.length > 0 else { return resolvedDefaultFont() }
318
+
319
+ let offset = offset(from: beginningOfDocument, to: position)
320
+ let attributeIndex: Int
321
+ if offset <= 0 {
322
+ attributeIndex = 0
323
+ } else if offset < textStorage.length {
324
+ attributeIndex = offset
325
+ } else {
326
+ attributeIndex = textStorage.length - 1
327
+ }
328
+
329
+ return (textStorage.attribute(.font, at: attributeIndex, effectiveRange: nil) as? UIFont)
330
+ ?? resolvedDefaultFont()
331
+ }
332
+
333
+ }