@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,318 @@
1
+ import os
2
+ import UIKit
3
+
4
+ extension EditorTextView {
5
+ @objc func handleIndentKeyCommand() {
6
+ handleListDepthKeyCommand(outdent: false)
7
+ }
8
+
9
+ @objc func handleHardBreakKeyCommand() {
10
+ guard !isApplyingRustState, editorId != 0, isEditable else { return }
11
+ guard finishExternalTextCompositionBeforeInteractionIfNeeded() else { return }
12
+ guard flushPendingNativeTextMutationCommitIfNeeded() else { return }
13
+ guard !isCollapsedAtomBoundary(selectedUtf16Range()) else { return }
14
+ performInterceptedInput {
15
+ insertNodeInRust(preferredHardBreakNodeType())
16
+ }
17
+ }
18
+
19
+ @objc func handleOutdentKeyCommand() {
20
+ handleListDepthKeyCommand(outdent: true)
21
+ }
22
+
23
+ func adjacentVoidBlockDeleteRangeForBackwardDelete(
24
+ cursorUtf16Offset: Int,
25
+ cursorScalar: UInt32
26
+ ) -> (from: UInt32, to: UInt32)? {
27
+ guard cursorUtf16Offset >= 0, cursorUtf16Offset < textStorage.length else {
28
+ return nil
29
+ }
30
+ let attrs = textStorage.attributes(at: cursorUtf16Offset, effectiveRange: nil)
31
+ guard attrs[.attachment] is NSTextAttachment,
32
+ attrs[RenderBridgeAttributes.voidNodeType] is String,
33
+ cursorScalar < UInt32.max
34
+ else {
35
+ return nil
36
+ }
37
+ return (from: cursorScalar, to: cursorScalar + 1)
38
+ }
39
+
40
+ func trailingVoidBlockDeleteRangeForBackwardDelete(
41
+ cursorUtf16Offset: Int
42
+ ) -> (from: UInt32, to: UInt32)? {
43
+ let text = textStorage.string as NSString
44
+ guard text.length > 0 else { return nil }
45
+
46
+ let clampedCursor = min(max(cursorUtf16Offset, 0), text.length)
47
+ let paragraphProbe = min(max(clampedCursor - 1, 0), text.length - 1)
48
+ let paragraphRange = text.paragraphRange(for: NSRange(location: paragraphProbe, length: 0))
49
+
50
+ let placeholderRange = NSRange(location: paragraphRange.location, length: 1)
51
+ guard placeholderRange.location + placeholderRange.length <= text.length else {
52
+ return nil
53
+ }
54
+
55
+ let paragraphText = text.substring(with: placeholderRange)
56
+ guard paragraphText == "\u{200B}" else { return nil }
57
+ guard paragraphRange.location >= 2 else { return nil }
58
+ guard text.character(at: paragraphRange.location - 1) == 0x000A else { return nil }
59
+
60
+ let attachmentIndex = paragraphRange.location - 2
61
+ guard
62
+ let deleteRange = scalarDeleteRangeForVoidAttachment(at: attachmentIndex)
63
+ else {
64
+ return nil
65
+ }
66
+
67
+ return deleteRange
68
+ }
69
+
70
+ private func scalarDeleteRangeForVoidAttachment(
71
+ at utf16Offset: Int
72
+ ) -> (from: UInt32, to: UInt32)? {
73
+ guard utf16Offset >= 0, utf16Offset < textStorage.length else {
74
+ return nil
75
+ }
76
+ let attrs = textStorage.attributes(at: utf16Offset, effectiveRange: nil)
77
+ guard let attachment = attrs[.attachment] as? NSTextAttachment,
78
+ !(attachment is AtomBlockAttachment),
79
+ attrs[RenderBridgeAttributes.voidNodeType] is String
80
+ else {
81
+ return nil
82
+ }
83
+
84
+ let attachmentEndScalar = PositionBridge.utf16OffsetToScalar(
85
+ utf16Offset + 1,
86
+ in: self
87
+ )
88
+ guard attachmentEndScalar > 0 else { return nil }
89
+ return (from: attachmentEndScalar - 1, to: attachmentEndScalar)
90
+ }
91
+
92
+ private func handleListDepthKeyCommand(outdent: Bool) {
93
+ guard !isApplyingRustState else { return }
94
+ guard editorId != 0 else { return }
95
+ guard isEditable else { return }
96
+ guard finishExternalTextCompositionBeforeInteractionIfNeeded() else { return }
97
+ guard flushPendingNativeTextMutationCommitIfNeeded() else { return }
98
+ guard isCaretInsideList() else { return }
99
+ guard let selection = currentScalarSelection() else { return }
100
+
101
+ performInterceptedInput {
102
+ let updateJSON = outdent
103
+ ? EditorV2Shadow.outdentListItemAtSelectionScalar(
104
+ id: editorId,
105
+ scalarAnchor: selection.anchor,
106
+ scalarHead: selection.head
107
+ )
108
+ : EditorV2Shadow.indentListItemAtSelectionScalar(
109
+ id: editorId,
110
+ scalarAnchor: selection.anchor,
111
+ scalarHead: selection.head
112
+ )
113
+ applyUpdateJSON(updateJSON)
114
+ }
115
+ }
116
+
117
+ private func isCaretInsideList() -> Bool {
118
+ guard editorId != 0 else { return false }
119
+ guard
120
+ let data = EditorV2Shadow.getCurrentState(id: editorId).data(using: .utf8),
121
+ let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
122
+ let activeState = object["activeState"] as? [String: Any],
123
+ let nodes = activeState["nodes"] as? [String: Any]
124
+ else {
125
+ return false
126
+ }
127
+
128
+ return nodes.contains { nodeType, value in
129
+ EditorNodeTypes.isListContainer(nodeType) && value as? Bool == true
130
+ }
131
+ }
132
+
133
+ private func preferredHardBreakNodeType() -> String {
134
+ guard
135
+ let data = EditorV2Shadow.getCurrentState(id: editorId).data(using: .utf8),
136
+ let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
137
+ let activeState = object["activeState"] as? [String: Any],
138
+ let insertableNodes = activeState["insertableNodes"] as? [String]
139
+ else {
140
+ return "hardBreak"
141
+ }
142
+
143
+ return EditorNodeTypes.preferredHardBreak(in: Set(insertableNodes))
144
+ }
145
+
146
+ func ensureInternalTextViewDelegate() {
147
+ // Some keyboard integrations replace UITextView's private delegate ivar
148
+ // directly. The editor must own delegate callbacks so external observers
149
+ // cannot inspect transient TextKit state during Rust-driven edits.
150
+ // The delegate is a dedicated object rather than the text view itself;
151
+ // see EditorTextViewInternalDelegate for why (APOLLO-REACT-56).
152
+ guard (delegate as AnyObject?) !== internalTextViewDelegate else { return }
153
+ delegate = internalTextViewDelegate
154
+ }
155
+
156
+ func performInterceptedInput(
157
+ flushPendingNativeTextMutation: Bool = true,
158
+ _ action: () -> Void
159
+ ) {
160
+ if flushPendingNativeTextMutation, interceptedInputDepth == 0 {
161
+ guard flushPendingNativeTextMutationCommitIfNeeded() else { return }
162
+ }
163
+ interceptedInputDepth += 1
164
+ Self.inputLog.debug(
165
+ "[intercept.begin] depth=\(self.interceptedInputDepth) selection=\(self.selectionSummary(), privacy: .public) textState=\(self.textSnapshotSummary(), privacy: .public)"
166
+ )
167
+ action()
168
+ DispatchQueue.main.async { [weak self] in
169
+ guard let self else { return }
170
+ self.interceptedInputDepth = max(0, self.interceptedInputDepth - 1)
171
+ Self.inputLog.debug(
172
+ "[intercept.end] depth=\(self.interceptedInputDepth) selection=\(self.selectionSummary(), privacy: .public) textState=\(self.textSnapshotSummary(), privacy: .public)"
173
+ )
174
+ if self.interceptedInputDepth == 0 {
175
+ _ = self.drainPendingNativeTextMutation(
176
+ allowAfterBlur: false,
177
+ allowWhileIntercepting: false
178
+ )
179
+ self.drainDeferredInsertTextIfReady()
180
+ }
181
+ }
182
+ }
183
+
184
+ func enqueueDeferredInsertText(_ text: String) {
185
+ deferredInsertTexts.append(text)
186
+ scheduleDeferredInsertDrain()
187
+ }
188
+
189
+ private func scheduleDeferredInsertDrain() {
190
+ guard !deferredInsertDrainScheduled else { return }
191
+ deferredInsertDrainScheduled = true
192
+ DispatchQueue.main.async { [weak self] in
193
+ self?.drainDeferredInsertTextIfReady()
194
+ }
195
+ }
196
+
197
+ private func drainDeferredInsertTextIfReady() {
198
+ deferredInsertDrainScheduled = false
199
+ guard !deferredInsertTexts.isEmpty else { return }
200
+ guard editorId != 0 else {
201
+ deferredInsertTexts.removeAll()
202
+ return
203
+ }
204
+ guard !isApplyingRustState,
205
+ interceptedInputDepth == 0,
206
+ pendingNativeTextMutation == nil,
207
+ !nativeTextMutationCommitScheduled
208
+ else {
209
+ scheduleDeferredInsertDrain()
210
+ return
211
+ }
212
+
213
+ let text = deferredInsertTexts.removeFirst()
214
+ isReplayingDeferredInsertText = true
215
+ defer { isReplayingDeferredInsertText = false }
216
+ insertText(text)
217
+ if !deferredInsertTexts.isEmpty {
218
+ scheduleDeferredInsertDrain()
219
+ }
220
+ }
221
+
222
+ /// Handle return key press as a block split operation.
223
+ private func handleReturnKey() {
224
+ if let selectedRange = selectedTextRange, !selectedRange.isEmpty {
225
+ let range = PositionBridge.textRangeToScalarRange(selectedRange, in: self)
226
+ let updateJSON = EditorV2Shadow.deleteAndSplitScalar(
227
+ id: editorId,
228
+ scalarFrom: range.from,
229
+ scalarTo: range.to
230
+ )
231
+ applyUpdateJSON(updateJSON)
232
+ } else {
233
+ let scalarPos = PositionBridge.cursorScalarOffset(in: self)
234
+ splitBlockInRust(at: scalarPos)
235
+ }
236
+ }
237
+
238
+ func interceptReturnInput(
239
+ _ text: String,
240
+ replacing replacementRange: UITextRange? = nil
241
+ ) -> Bool {
242
+ guard text == "\n" || text == "\r" else { return false }
243
+ let scalarRange = replacementRange.map {
244
+ PositionBridge.textRangeToScalarRange($0, in: self)
245
+ }
246
+ guard commitActiveMarkedTextBeforeReturn() else { return true }
247
+ performInterceptedInput {
248
+ if let scalarRange {
249
+ if scalarRange.from == scalarRange.to {
250
+ splitBlockInRust(at: scalarRange.from)
251
+ } else {
252
+ let updateJSON = EditorV2Shadow.deleteAndSplitScalar(
253
+ id: editorId,
254
+ scalarFrom: scalarRange.from,
255
+ scalarTo: scalarRange.to
256
+ )
257
+ applyUpdateJSON(updateJSON)
258
+ }
259
+ } else {
260
+ handleReturnKey()
261
+ }
262
+ }
263
+ return true
264
+ }
265
+
266
+ /// Split a block at a scalar position via the Rust editor.
267
+ private func splitBlockInRust(at scalarPos: UInt32) {
268
+ Self.inputLog.debug(
269
+ "[rust.splitBlockScalar] scalarPos=\(scalarPos) selection=\(self.selectionSummary(), privacy: .public)"
270
+ )
271
+ let updateJSON = EditorV2Shadow.splitBlockScalar(id: editorId, scalarPos: scalarPos)
272
+ applyUpdateJSON(updateJSON)
273
+ }
274
+
275
+ /// Paste HTML content through Rust.
276
+ @discardableResult
277
+ func pasteHTML(_ html: String, detectContentChange: Bool = false) -> Bool {
278
+ let previousHTML = detectContentChange ? EditorV2Shadow.getHtml(id: editorId) : nil
279
+ syncCurrentUIKitSelectionToRust()
280
+ Self.inputLog.debug(
281
+ "[rust.pasteHTML] html=\(self.preview(html), privacy: .public) selection=\(self.selectionSummary(), privacy: .public)"
282
+ )
283
+ let updateJSON = EditorV2Shadow.insertContentHtml(id: editorId, html: html)
284
+ applyUpdateJSON(updateJSON)
285
+ guard let previousHTML else { return true }
286
+ return EditorV2Shadow.getHtml(id: editorId) != previousHTML
287
+ }
288
+
289
+ private func syncCurrentUIKitSelectionToRust() {
290
+ guard editorId != 0, let range = selectedTextRange else { return }
291
+ let anchor = PositionBridge.textViewToScalar(range.start, in: self)
292
+ let head = PositionBridge.textViewToScalar(range.end, in: self)
293
+ EditorV2Shadow.setSelectionScalar(id: editorId, scalarAnchor: anchor, scalarHead: head)
294
+ }
295
+
296
+ /// Paste plain text through Rust.
297
+ func pastePlainText(_ text: String) {
298
+ if let selectedRange = selectedTextRange, !selectedRange.isEmpty {
299
+ let range = PositionBridge.textRangeToScalarRange(selectedRange, in: self)
300
+ Self.inputLog.debug(
301
+ "[rust.pastePlainText.replace] text=\(self.preview(text), privacy: .public) scalar=\(range.from)-\(range.to) selection=\(self.selectionSummary(), privacy: .public)"
302
+ )
303
+ let updateJSON = EditorV2Shadow.replaceTextScalar(
304
+ id: editorId,
305
+ scalarFrom: range.from,
306
+ scalarTo: range.to,
307
+ text: text
308
+ )
309
+ applyUpdateJSON(updateJSON)
310
+ } else {
311
+ Self.inputLog.debug(
312
+ "[rust.pastePlainText.insert] text=\(self.preview(text), privacy: .public) selection=\(self.selectionSummary(), privacy: .public)"
313
+ )
314
+ insertTextInRust(text, at: PositionBridge.cursorScalarOffset(in: self))
315
+ }
316
+ }
317
+
318
+ }
@@ -0,0 +1,245 @@
1
+ import os
2
+ import UIKit
3
+
4
+ extension EditorTextView {
5
+ @objc func handleKeyboardFrameChange(_ notification: Notification) {
6
+ guard isFirstResponder || keyboardFrameInScreen != nil else { return }
7
+ if notification.name == UIResponder.keyboardWillHideNotification {
8
+ keyboardFrameInScreen = nil
9
+ } else {
10
+ keyboardFrameInScreen = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
11
+ }
12
+ let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
13
+ let curve = (notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue ?? 0
14
+ UIView.animate(
15
+ withDuration: duration,
16
+ delay: 0,
17
+ options: [UIView.AnimationOptions(rawValue: curve << 16), .beginFromCurrentState]
18
+ ) {
19
+ self.updateKeyboardInset()
20
+ }
21
+ }
22
+
23
+ func updateKeyboardInset() {
24
+ var overlap: CGFloat = 0
25
+ if isScrollEnabled, let window, let keyboardFrameInScreen {
26
+ let frameInWindow = window.convert(keyboardFrameInScreen, from: window.screen.coordinateSpace)
27
+ let keyboardFrame = convert(frameInWindow, from: window)
28
+ let intersection = bounds.intersection(keyboardFrame)
29
+ if !intersection.isNull, intersection.maxY >= bounds.maxY - 1 {
30
+ overlap = intersection.height
31
+ }
32
+ }
33
+ let baseBottomInset = contentInset.bottom - keyboardBottomInset
34
+ let automaticBottomInset = adjustedContentInset.bottom - contentInset.bottom
35
+ let nextInset = max(0, overlap - automaticBottomInset - baseBottomInset)
36
+ guard abs(nextInset - keyboardBottomInset) > 0.5 else { return }
37
+ let delta = nextInset - keyboardBottomInset
38
+ keyboardBottomInset = nextInset
39
+ contentInset.bottom += delta
40
+ verticalScrollIndicatorInsets.bottom += delta
41
+ if overlap > 0, isFirstResponder, let selection = selectedTextRange {
42
+ let caret = caretRect(for: selection.end)
43
+ if !caret.isEmpty {
44
+ scrollRectToVisible(caret.insetBy(dx: 0, dy: -8), animated: false)
45
+ }
46
+ }
47
+ }
48
+
49
+ /// Whether the document holds nothing the user authored.
50
+ ///
51
+ /// Taken verbatim from the core. Deriving it cannot work: an empty list
52
+ /// item contributes no characters, so scanning the storage reports empty
53
+ /// and leaves the placeholder over a visible bullet. The scan below is
54
+ /// only the fallback for renders with no editor update (the viewer).
55
+ private func isRenderedContentEmpty() -> Bool {
56
+ if let coreReportedDocumentIsEmpty {
57
+ return coreReportedDocumentIsEmpty
58
+ }
59
+
60
+ let renderedText = textStorage.string
61
+ guard !renderedText.isEmpty else { return true }
62
+
63
+ for scalar in renderedText.unicodeScalars {
64
+ switch scalar {
65
+ case Self.emptyBlockPlaceholderScalar, "\n", "\r":
66
+ continue
67
+ default:
68
+ return false
69
+ }
70
+ }
71
+
72
+ return true
73
+ }
74
+
75
+ @discardableResult
76
+ func normalizeSelectionForEmptyBlockAutocapitalizationIfNeeded() -> Bool {
77
+ guard textStorage.length == 1 else { return false }
78
+ guard textStorage.string.unicodeScalars.elementsEqual([Self.emptyBlockPlaceholderScalar]) else {
79
+ return false
80
+ }
81
+
82
+ let currentRange = selectedRange
83
+ guard currentRange.location != NSNotFound, currentRange.length == 0 else { return false }
84
+ guard currentRange.location == textStorage.length else { return false }
85
+
86
+ let adjustedRange = NSRange(location: 0, length: 0)
87
+ guard currentRange != adjustedRange else { return false }
88
+ selectedRange = adjustedRange
89
+ noteSelectionDidChange()
90
+ return true
91
+ }
92
+
93
+ func refreshPlaceholderVisibility() {
94
+ let hasProvisionalText = externalTextComposition?.latestText.isEmpty == false
95
+ placeholderLabel.isHidden = placeholder.isEmpty
96
+ || hasProvisionalText
97
+ || !isRenderedContentEmpty()
98
+ }
99
+
100
+ func preserveScrollOffset(_ previousOffset: CGPoint) {
101
+ let restore = { [weak self] in
102
+ guard let self else { return }
103
+ self.layoutIfNeeded()
104
+
105
+ let maxOffsetX = max(
106
+ -self.adjustedContentInset.left,
107
+ self.contentSize.width - self.bounds.width + self.adjustedContentInset.right
108
+ )
109
+ let maxOffsetY = max(
110
+ -self.adjustedContentInset.top,
111
+ self.contentSize.height - self.bounds.height + self.adjustedContentInset.bottom
112
+ )
113
+
114
+ let clampedOffset = CGPoint(
115
+ x: min(max(previousOffset.x, -self.adjustedContentInset.left), maxOffsetX),
116
+ y: min(max(previousOffset.y, -self.adjustedContentInset.top), maxOffsetY)
117
+ )
118
+ self.setContentOffset(clampedOffset, animated: false)
119
+ }
120
+
121
+ restore()
122
+ DispatchQueue.main.async(execute: restore)
123
+ }
124
+
125
+ func defaultTypingAttributes() -> [NSAttributedString.Key: Any] {
126
+ [
127
+ .font: resolvedDefaultFont(),
128
+ .foregroundColor: resolvedDefaultTextColor()
129
+ ]
130
+ }
131
+
132
+ func resolvedDefaultFont() -> UIFont {
133
+ theme?.effectiveTextStyle(for: "paragraph").resolvedFont(fallback: baseFont)
134
+ ?? baseFont
135
+ }
136
+
137
+ func resolvedDefaultTextColor() -> UIColor {
138
+ theme?.effectiveTextStyle(for: "paragraph").color ?? baseTextColor
139
+ }
140
+
141
+ func notifyHeightChangeIfNeeded(force: Bool = false) {
142
+ guard heightBehavior == .autoGrow else { return }
143
+ let width = bounds.width > 0 ? bounds.width : UIScreen.main.bounds.width
144
+ guard width > 0 else { return }
145
+ if !force {
146
+ let measuredWidth = ceil(width)
147
+ if !autoGrowHeightCheckIsDirty && abs(measuredWidth - lastAutoGrowMeasuredWidth) <= 0.5 {
148
+ return
149
+ }
150
+ }
151
+ lastHeightNotifyEnsureLayoutNanosForTesting = 0
152
+ lastHeightNotifyUsedRectNanosForTesting = 0
153
+ lastHeightNotifyContentSizeNanosForTesting = 0
154
+ lastHeightNotifySizeThatFitsNanosForTesting = 0
155
+ let measurementStartedAt = DispatchTime.now().uptimeNanoseconds
156
+ let measuredHeight = measuredAutoGrowHeight(forWidth: width)
157
+ lastHeightNotifyMeasureNanosForTesting =
158
+ DispatchTime.now().uptimeNanoseconds - measurementStartedAt
159
+ autoGrowHeightCheckIsDirty = false
160
+ lastAutoGrowMeasuredWidth = ceil(width)
161
+ guard force || abs(measuredHeight - lastAutoGrowMeasuredHeight) > 0.5 else { return }
162
+ lastAutoGrowMeasuredHeight = measuredHeight
163
+ let callbackStartedAt = DispatchTime.now().uptimeNanoseconds
164
+ onHeightMayChange?(measuredHeight)
165
+ lastHeightNotifyCallbackNanosForTesting =
166
+ DispatchTime.now().uptimeNanoseconds - callbackStartedAt
167
+ }
168
+
169
+ func measuredAutoGrowHeight(forWidth width: CGFloat) -> CGFloat {
170
+ guard width > 0 else { return 0 }
171
+
172
+ if abs(bounds.width - width) <= 0.5 {
173
+ let currentHeight = ceil(bounds.height)
174
+ let ensureLayoutStartedAt = DispatchTime.now().uptimeNanoseconds
175
+ editorLayoutManager.ensureLayout(for: textContainer)
176
+ lastHeightNotifyEnsureLayoutNanosForTesting =
177
+ DispatchTime.now().uptimeNanoseconds - ensureLayoutStartedAt
178
+
179
+ let usedRectStartedAt = DispatchTime.now().uptimeNanoseconds
180
+ var usedRect = editorLayoutManager.usedRect(for: textContainer)
181
+ let extraLineFragmentRect = editorLayoutManager.extraLineFragmentRect
182
+ if !extraLineFragmentRect.isEmpty {
183
+ usedRect = usedRect.union(extraLineFragmentRect)
184
+ }
185
+ lastHeightNotifyUsedRectNanosForTesting =
186
+ DispatchTime.now().uptimeNanoseconds - usedRectStartedAt
187
+ let layoutHeight = ceil(
188
+ usedRect.height
189
+ + textContainerInset.top
190
+ + textContainerInset.bottom
191
+ )
192
+
193
+ let contentSizeStartedAt = DispatchTime.now().uptimeNanoseconds
194
+ let contentHeight = ceil(contentSize.height)
195
+ lastHeightNotifyContentSizeNanosForTesting =
196
+ DispatchTime.now().uptimeNanoseconds - contentSizeStartedAt
197
+ if currentHeight > 0 {
198
+ if layoutHeight > currentHeight + 0.5 {
199
+ return layoutHeight
200
+ }
201
+ let hostIsTrackingMeasuredHeight =
202
+ autoGrowHostHeight > 0
203
+ && abs(currentHeight - ceil(autoGrowHostHeight)) <= 1.0
204
+ guard hostIsTrackingMeasuredHeight else {
205
+ return layoutHeight
206
+ }
207
+ let measuredFromLayout = max(layoutHeight, contentHeight)
208
+ if measuredFromLayout > currentHeight + 0.5 {
209
+ return measuredFromLayout
210
+ }
211
+ let sizeThatFitsStartedAt = DispatchTime.now().uptimeNanoseconds
212
+ let fittedHeight = ceil(
213
+ sizeThatFits(
214
+ CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
215
+ ).height
216
+ )
217
+ lastHeightNotifySizeThatFitsNanosForTesting =
218
+ DispatchTime.now().uptimeNanoseconds - sizeThatFitsStartedAt
219
+ if fittedHeight > currentHeight + 0.5 {
220
+ return max(measuredFromLayout, fittedHeight)
221
+ }
222
+ return layoutHeight
223
+ }
224
+ return max(layoutHeight, contentHeight)
225
+ }
226
+
227
+ let sizeThatFitsStartedAt = DispatchTime.now().uptimeNanoseconds
228
+ let fittedHeight = ceil(
229
+ sizeThatFits(CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)).height
230
+ )
231
+ lastHeightNotifySizeThatFitsNanosForTesting =
232
+ DispatchTime.now().uptimeNanoseconds - sizeThatFitsStartedAt
233
+ return fittedHeight
234
+ }
235
+
236
+ func updateAutoGrowHostHeight(_ height: CGFloat) {
237
+ autoGrowHostHeight = max(0, ceil(height))
238
+ }
239
+
240
+ func invalidateAutoGrowHeightMeasurement() {
241
+ autoGrowHeightCheckIsDirty = true
242
+ lastAutoGrowMeasuredWidth = 0
243
+ }
244
+
245
+ }