@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,542 @@
1
+ import os
2
+ import UIKit
3
+
4
+ class CaretPlacementTapRecognizer: UITapGestureRecognizer {
5
+ private weak var trackedTouch: UITouch?
6
+
7
+ // UIKit can publish selection after recognition, before tap actions run.
8
+ var pendingCaretPoint: CGPoint? {
9
+ guard state == .possible || state == .ended,
10
+ let touch = trackedTouch,
11
+ touch.tapCount == 1,
12
+ touch.phase != .moved,
13
+ touch.phase != .cancelled
14
+ else { return nil }
15
+ return touch.location(in: view)
16
+ }
17
+
18
+ override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
19
+ trackedTouch = touches.count == 1 ? touches.first : nil
20
+ super.touchesBegan(touches, with: event)
21
+ }
22
+
23
+ override func reset() {
24
+ trackedTouch = nil
25
+ super.reset()
26
+ }
27
+ }
28
+
29
+ extension EditorTextView {
30
+ @objc
31
+ func handleCaretPlacementTap(_ recognizer: UITapGestureRecognizer) {
32
+ guard recognizer.state == .ended else { return }
33
+ // UIKit single taps otherwise snap to word boundaries.
34
+ _ = placeCaret(at: recognizer.location(in: self))
35
+ }
36
+
37
+ func canPlaceCaret(at point: CGPoint) -> Bool {
38
+ isEditable && isSelectable
39
+ && editorId != 0
40
+ && !hasImageAttachment(at: point)
41
+ && !hasTaskListMarker(at: point)
42
+ && atomAttachmentRange(at: point) == nil
43
+ }
44
+
45
+ @discardableResult
46
+ func placeCaret(at point: CGPoint) -> Bool {
47
+ guard canPlaceCaret(at: point),
48
+ finishExternalTextCompositionBeforeInteractionIfNeeded(),
49
+ prepareForExternalEditorUpdate(),
50
+ let position = closestPosition(to: point)
51
+ else { return false }
52
+ let offset = self.offset(from: beginningOfDocument, to: position)
53
+ guard !isAtomBoundaryCaretOffset(offset) else { return false }
54
+ _ = becomeFirstResponder()
55
+ logicalSelectionScalarRange = nil
56
+ logicalSelectionUtf16Range = nil
57
+ selectedRange = NSRange(location: offset, length: 0)
58
+ textViewDidChangeSelection(self)
59
+ return true
60
+ }
61
+
62
+ func selectedUtf16Range() -> NSRange? {
63
+ guard let range = selectedTextRange else { return nil }
64
+ let location = offset(from: beginningOfDocument, to: range.start)
65
+ let length = offset(from: range.start, to: range.end)
66
+ guard location >= 0, length >= 0 else { return nil }
67
+ return NSRange(location: location, length: length)
68
+ }
69
+
70
+ func isAtomBoundaryCaretOffset(_ offset: Int) -> Bool {
71
+ guard offset >= 0, offset <= textStorage.length else { return false }
72
+ if offset < textStorage.length,
73
+ textStorage.attribute(.attachment, at: offset, effectiveRange: nil) is AtomBlockAttachment {
74
+ return true
75
+ }
76
+ return offset > 0
77
+ && textStorage.attribute(.attachment, at: offset - 1, effectiveRange: nil)
78
+ is AtomBlockAttachment
79
+ }
80
+
81
+ func isCollapsedAtomBoundary(_ range: NSRange?) -> Bool {
82
+ guard let range, range.length == 0 else { return false }
83
+ return isAtomBoundaryCaretOffset(range.location)
84
+ }
85
+
86
+ @discardableResult
87
+ private func restoreSelectionFromAtomBoundaryIfNeeded() -> Bool {
88
+ guard isCollapsedAtomBoundary(selectedUtf16Range()) else { return false }
89
+ logicalSelectionScalarRange = nil
90
+ logicalSelectionUtf16Range = nil
91
+ if let authorized = lastAuthorizedSelectedUtf16Range,
92
+ NSMaxRange(authorized) <= textStorage.length,
93
+ !isCollapsedAtomBoundary(authorized) {
94
+ performTransientTextMutation {
95
+ selectedRange = authorized
96
+ noteSelectionDidChange()
97
+ }
98
+ }
99
+ refreshNativeSelectionChromeVisibility()
100
+ onSelectionOrContentMayChange?()
101
+ return true
102
+ }
103
+
104
+ func noteSelectionDidChange() {
105
+ selectionRevision &+= 1
106
+ }
107
+
108
+ func recordAuthorizedSelectionIfPossible() {
109
+ guard editorId != 0 else {
110
+ lastAuthorizedSelectedUtf16Range = nil
111
+ lastAuthorizedSelectionIsBackward = false
112
+ return
113
+ }
114
+ let currentText = textStorage.string
115
+ guard currentText.utf16.count == lastAuthorizedTextStorage.length,
116
+ currentText == lastAuthorizedText
117
+ else {
118
+ return
119
+ }
120
+ lastAuthorizedSelectedUtf16Range = selectedUtf16Range()
121
+ lastAuthorizedSelectionIsBackward = currentLogicalScalarSelection().map {
122
+ $0.anchor > $0.head
123
+ } ?? false
124
+ }
125
+
126
+ func scalarRange(forUtf16Range range: NSRange) -> (from: UInt32, to: UInt32) {
127
+ let start = PositionBridge.utf16OffsetToScalar(range.location, in: self)
128
+ let end = PositionBridge.utf16OffsetToScalar(NSMaxRange(range), in: self)
129
+ return (from: min(start, end), to: max(start, end))
130
+ }
131
+
132
+ func scalarRange(
133
+ forUtf16Range range: NSRange,
134
+ in storage: NSAttributedString
135
+ ) -> (from: UInt32, to: UInt32) {
136
+ let start = PositionBridge.utf16OffsetToScalar(range.location, in: storage)
137
+ let end = PositionBridge.utf16OffsetToScalar(NSMaxRange(range), in: storage)
138
+ return (from: min(start, end), to: max(start, end))
139
+ }
140
+
141
+ /// UITextViewDelegate hook for user-driven selection updates.
142
+ ///
143
+ /// Using the delegate callback is more reliable than observing
144
+ /// `selectedTextRange` directly because UIKit can adjust selection
145
+ /// internally during tap handling and word-boundary resolution.
146
+ func textViewDidChangeSelection(_ textView: UITextView) {
147
+ guard textView === self else { return }
148
+ ensureInternalTextViewDelegate()
149
+ if !isApplyingRustState,
150
+ !isComposing,
151
+ externalTextComposition == nil,
152
+ !nativeTextMutationCommitScheduled,
153
+ pendingNativeTextMutation == nil,
154
+ selectedRange.length == 0,
155
+ let point = caretPlacementTapRecognizer.pendingCaretPoint,
156
+ let position = closestPosition(to: point) {
157
+ let offset = self.offset(from: beginningOfDocument, to: position)
158
+ if selectedRange.location != offset, !isAtomBoundaryCaretOffset(offset) {
159
+ // Correct UIKit's word snap before publishing or drawing the selection.
160
+ selectedRange = NSRange(location: offset, length: 0)
161
+ }
162
+ }
163
+ noteSelectionDidChange()
164
+ if externalTextComposition != nil {
165
+ guard !isApplyingRustState else { return }
166
+ let interactionSelection = selectedRange
167
+ guard finishExternalTextCompositionBeforeInteractionIfNeeded() else { return }
168
+ if interactionSelection.location != NSNotFound,
169
+ interactionSelection.location >= 0,
170
+ interactionSelection.length >= 0,
171
+ interactionSelection.location + interactionSelection.length <= textStorage.length {
172
+ logicalSelectionScalarRange = nil
173
+ logicalSelectionUtf16Range = nil
174
+ performTransientTextMutation {
175
+ selectedRange = interactionSelection
176
+ noteSelectionDidChange()
177
+ }
178
+ }
179
+ }
180
+ guard !isApplyingRustState,
181
+ !isComposing,
182
+ !nativeTextMutationCommitScheduled,
183
+ pendingNativeTextMutation == nil
184
+ else {
185
+ return
186
+ }
187
+ if restoreSelectionFromAtomBoundaryIfNeeded() {
188
+ return
189
+ }
190
+ if normalizeSelectionForEmptyBlockAutocapitalizationIfNeeded() {
191
+ return
192
+ }
193
+ recordAuthorizedSelectionIfPossible()
194
+ refreshNativeSelectionChromeVisibility()
195
+ onSelectionOrContentMayChange?()
196
+ scheduleSelectionSync()
197
+ }
198
+
199
+ func textView(
200
+ _ textView: UITextView,
201
+ shouldInteractWith URL: URL,
202
+ in characterRange: NSRange,
203
+ interaction: UITextItemInteraction
204
+ ) -> Bool {
205
+ return false
206
+ }
207
+
208
+ func textView(
209
+ _ textView: UITextView,
210
+ shouldInteractWith textAttachment: NSTextAttachment,
211
+ in characterRange: NSRange,
212
+ interaction: UITextItemInteraction
213
+ ) -> Bool {
214
+ guard textView === self,
215
+ characterRange.location >= 0,
216
+ characterRange.location < textStorage.length
217
+ else {
218
+ return false
219
+ }
220
+
221
+ let attrs = textStorage.attributes(at: characterRange.location, effectiveRange: nil)
222
+ guard (attrs[RenderBridgeAttributes.voidNodeType] as? String) == "image",
223
+ let start = position(from: beginningOfDocument, offset: characterRange.location),
224
+ let end = position(from: start, offset: characterRange.length)
225
+ else {
226
+ return false
227
+ }
228
+
229
+ selectedTextRange = textRange(from: start, to: end)
230
+ noteSelectionDidChange()
231
+ refreshNativeSelectionChromeVisibility()
232
+ onSelectionOrContentMayChange?()
233
+ scheduleSelectionSync()
234
+ return false
235
+ }
236
+
237
+ func refreshTypingAttributesForSelection() {
238
+ guard let range = selectedTextRange else {
239
+ typingAttributes = defaultTypingAttributes()
240
+ return
241
+ }
242
+
243
+ if textStorage.length == 0 {
244
+ typingAttributes = defaultTypingAttributes()
245
+ return
246
+ }
247
+
248
+ let startOffset = offset(from: beginningOfDocument, to: range.start)
249
+ let attributeIndex: Int
250
+ if startOffset < textStorage.length {
251
+ attributeIndex = max(0, startOffset)
252
+ } else {
253
+ attributeIndex = textStorage.length - 1
254
+ }
255
+
256
+ var attrs = textStorage.attributes(at: attributeIndex, effectiveRange: nil)
257
+ attrs[.font] = attrs[.font] ?? resolvedDefaultFont()
258
+ attrs[.foregroundColor] = attrs[.foregroundColor] ?? resolvedDefaultTextColor()
259
+ typingAttributes = attrs
260
+ }
261
+
262
+ private func setNativeSelectionChromeHidden(_ hidden: Bool) {
263
+ guard hidesNativeSelectionChrome != hidden else { return }
264
+ hidesNativeSelectionChrome = hidden
265
+ super.tintColor = hidden ? .clear : visibleSelectionTintColor
266
+ }
267
+
268
+ func refreshNativeSelectionChromeVisibility() {
269
+ let hidden = selectedImageSelectionState() != nil
270
+ if !hidden, tintColor.cgColor.alpha > 0 {
271
+ visibleSelectionTintColor = tintColor
272
+ }
273
+ setNativeSelectionChromeHidden(hidden)
274
+ }
275
+
276
+ private func showNativeSelectionChromeIfNeeded() {
277
+ if tintColor.cgColor.alpha > 0 {
278
+ visibleSelectionTintColor = tintColor
279
+ }
280
+ setNativeSelectionChromeHidden(false)
281
+ }
282
+
283
+ func refreshSelectionVisualState() {
284
+ _ = normalizeSelectionForEmptyBlockAutocapitalizationIfNeeded()
285
+ refreshNativeSelectionChromeVisibility()
286
+ refreshTypingAttributesForSelection()
287
+ onSelectionOrContentMayChange?()
288
+ }
289
+
290
+ func scheduleSelectionSync() {
291
+ pendingSelectionSyncGeneration &+= 1
292
+ let generation = pendingSelectionSyncGeneration
293
+ DispatchQueue.main.async { [weak self] in
294
+ guard let self else { return }
295
+ guard self.pendingSelectionSyncGeneration == generation else { return }
296
+ self.syncSelectionToRustAndNotifyDelegate()
297
+ }
298
+ }
299
+
300
+ private func syncSelectionToRustAndNotifyDelegate() {
301
+ guard !isApplyingRustState,
302
+ !isComposing,
303
+ !nativeTextMutationCommitScheduled,
304
+ pendingNativeTextMutation == nil,
305
+ editorId != 0
306
+ else {
307
+ return
308
+ }
309
+ guard let selection = currentLogicalScalarSelection() else { return }
310
+
311
+ let anchor = selection.anchor
312
+ let head = selection.head
313
+ let sync: EditorV2SelectionSync?
314
+ if let image = selectedImageSelectionState() {
315
+ sync = EditorV2Shadow.setNodeSelection(id: editorId, docPos: image.docPos)
316
+ } else {
317
+ sync = EditorV2Shadow.setSelectionScalar(
318
+ id: editorId,
319
+ scalarAnchor: anchor,
320
+ scalarHead: head
321
+ )
322
+ }
323
+ guard let sync else { return }
324
+ Self.selectionLog.debug(
325
+ "[textViewDidChangeSelection] scalar=\(anchor)-\(head) doc=\(sync.docAnchor)-\(sync.docHead) textState=\(self.textSnapshotSummary(), privacy: .public)"
326
+ )
327
+ if let refreshed = sync.refreshedUpdateJSON {
328
+ applyUpdateJSON(refreshed, notifyDelegate: false)
329
+ }
330
+ recordAuthorizedSelectionIfPossible()
331
+ refreshTypingAttributesForSelection()
332
+ editorDelegate?.editorTextView(
333
+ self,
334
+ selectionDidChange: sync.docAnchor,
335
+ head: sync.docHead
336
+ )
337
+ }
338
+
339
+ func currentLogicalScalarSelection() -> (anchor: UInt32, head: UInt32)? {
340
+ guard let range = selectedTextRange else { return nil }
341
+ let scalarRange = PositionBridge.textRangeToScalarRange(range, in: self)
342
+ if let logicalSelectionScalarRange,
343
+ min(logicalSelectionScalarRange.anchor, logicalSelectionScalarRange.head) == scalarRange.from,
344
+ max(logicalSelectionScalarRange.anchor, logicalSelectionScalarRange.head) == scalarRange.to {
345
+ return logicalSelectionScalarRange
346
+ }
347
+ // A lone empty block parks the caret ahead of the placeholder so UIKit
348
+ // offers autocapitalization, which makes the UIKit caret disagree with
349
+ // the engine scalar by exactly the placeholder. Matching the range that
350
+ // nudge produced keeps the engine authoritative.
351
+ //
352
+ // Confined to that block: a matching UTF-16 range is not evidence a
353
+ // scalar is current. Wrapping a line in a list shifts every scalar
354
+ // while leaving UTF-16 offsets untouched, so a stale pre-wrap caret
355
+ // would match here and place the next character inside the word.
356
+ if let logicalSelectionScalarRange,
357
+ let logicalSelectionUtf16Range,
358
+ logicalSelectionUtf16Range == selectedRange,
359
+ isLoneEmptyPlaceholderBlock {
360
+ return logicalSelectionScalarRange
361
+ }
362
+ logicalSelectionScalarRange = nil
363
+ logicalSelectionUtf16Range = nil
364
+ return (anchor: scalarRange.from, head: scalarRange.to)
365
+ }
366
+
367
+ func currentScalarSelection() -> (anchor: UInt32, head: UInt32)? {
368
+ currentLogicalScalarSelection()
369
+ }
370
+
371
+ /// Apply a selection from a parsed JSON selection object.
372
+ ///
373
+ /// The selection JSON matches the format from `serialize_editor_update`:
374
+ /// ```json
375
+ /// {"type": "text", "anchor": 5, "head": 5}
376
+ /// {"type": "node", "pos": 10}
377
+ /// {"type": "all"}
378
+ /// ```
379
+ func applySelectionFromJSON(_ selection: [String: Any]) -> SelectionApplyTrace {
380
+ guard let type = selection["type"] as? String else {
381
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
382
+ }
383
+
384
+ let totalStartedAt = DispatchTime.now().uptimeNanoseconds
385
+ isApplyingRustState = true
386
+ delegate = nil
387
+ defer {
388
+ ensureInternalTextViewDelegate()
389
+ isApplyingRustState = false
390
+ }
391
+
392
+ switch type {
393
+ case "text":
394
+ let resolveStartedAt = DispatchTime.now().uptimeNanoseconds
395
+ guard let anchor = v2ExactUInt32(selection["anchor"] as? NSNumber),
396
+ let head = v2ExactUInt32(selection["head"] as? NSNumber)
397
+ else {
398
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
399
+ }
400
+ // anchor/head from Rust are document positions; convert to scalar offsets first.
401
+ let anchorScalar: UInt32
402
+ if let rawAnchorScalar = selection["anchorScalar"] {
403
+ guard let exactAnchorScalar = v2ExactUInt32(rawAnchorScalar as? NSNumber) else {
404
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
405
+ }
406
+ anchorScalar = exactAnchorScalar
407
+ } else {
408
+ anchorScalar = EditorV2Shadow.docToScalar(id: editorId, docPos: anchor)
409
+ }
410
+ let headScalar: UInt32
411
+ if let rawHeadScalar = selection["headScalar"] {
412
+ guard let exactHeadScalar = v2ExactUInt32(rawHeadScalar as? NSNumber) else {
413
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
414
+ }
415
+ headScalar = exactHeadScalar
416
+ } else {
417
+ headScalar = EditorV2Shadow.docToScalar(id: editorId, docPos: head)
418
+ }
419
+ let startUtf16 = PositionBridge.scalarToUtf16Offset(
420
+ min(anchorScalar, headScalar),
421
+ in: self
422
+ )
423
+ let endUtf16 = PositionBridge.scalarToUtf16Offset(
424
+ max(anchorScalar, headScalar),
425
+ in: self
426
+ )
427
+ let resolveNanos = DispatchTime.now().uptimeNanoseconds - resolveStartedAt
428
+
429
+ let assignmentStartedAt = DispatchTime.now().uptimeNanoseconds
430
+ logicalSelectionScalarRange = (anchor: anchorScalar, head: headScalar)
431
+ if anchorScalar == headScalar {
432
+ let endPos = position(from: beginningOfDocument, offset: endUtf16) ?? endOfDocument
433
+ if let adjustedPosition = autocapitalizationFriendlyEmptyBlockPosition(for: endPos) {
434
+ let adjustedOffset = offset(from: beginningOfDocument, to: adjustedPosition)
435
+ let adjustedRange = NSRange(location: adjustedOffset, length: 0)
436
+ if selectedRange != adjustedRange {
437
+ selectedRange = adjustedRange
438
+ noteSelectionDidChange()
439
+ }
440
+ } else {
441
+ let targetRange = NSRange(location: endUtf16, length: 0)
442
+ if selectedRange != targetRange {
443
+ selectedRange = targetRange
444
+ noteSelectionDidChange()
445
+ }
446
+ }
447
+ } else {
448
+ let targetRange = NSRange(location: startUtf16, length: endUtf16 - startUtf16)
449
+ if selectedRange != targetRange {
450
+ selectedRange = targetRange
451
+ noteSelectionDidChange()
452
+ }
453
+ }
454
+ logicalSelectionUtf16Range = selectedRange
455
+ let assignmentNanos = DispatchTime.now().uptimeNanoseconds - assignmentStartedAt
456
+ let chromeStartedAt = DispatchTime.now().uptimeNanoseconds
457
+ showNativeSelectionChromeIfNeeded()
458
+ let chromeNanos = DispatchTime.now().uptimeNanoseconds - chromeStartedAt
459
+ Self.selectionLog.debug(
460
+ "[applySelectionFromJSON.text] doc=\(anchor)-\(head) scalar=\(anchorScalar)-\(headScalar) final=\(self.selectionSummary(), privacy: .public)"
461
+ )
462
+ return SelectionApplyTrace(
463
+ totalNanos: DispatchTime.now().uptimeNanoseconds - totalStartedAt,
464
+ resolveNanos: resolveNanos,
465
+ assignmentNanos: assignmentNanos,
466
+ chromeNanos: chromeNanos
467
+ )
468
+
469
+ case "node":
470
+ let resolveStartedAt = DispatchTime.now().uptimeNanoseconds
471
+ guard let pos = v2ExactUInt32(selection["pos"] as? NSNumber) else {
472
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
473
+ }
474
+ let posScalar: UInt32
475
+ if let rawPosScalar = selection["posScalar"] {
476
+ guard let exactPosScalar = v2ExactUInt32(rawPosScalar as? NSNumber) else {
477
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
478
+ }
479
+ posScalar = exactPosScalar
480
+ } else {
481
+ posScalar = EditorV2Shadow.docToScalar(id: editorId, docPos: pos)
482
+ }
483
+ let startUtf16 = PositionBridge.scalarToUtf16Offset(posScalar, in: self)
484
+ let targetRange = NSRange(location: startUtf16, length: 1)
485
+ let resolveNanos = DispatchTime.now().uptimeNanoseconds - resolveStartedAt
486
+ let assignmentStartedAt = DispatchTime.now().uptimeNanoseconds
487
+ logicalSelectionScalarRange = nil
488
+ logicalSelectionUtf16Range = nil
489
+ if selectedRange != targetRange {
490
+ selectedRange = targetRange
491
+ noteSelectionDidChange()
492
+ }
493
+ let assignmentNanos = DispatchTime.now().uptimeNanoseconds - assignmentStartedAt
494
+ let chromeStartedAt = DispatchTime.now().uptimeNanoseconds
495
+ refreshNativeSelectionChromeVisibility()
496
+ let chromeNanos = DispatchTime.now().uptimeNanoseconds - chromeStartedAt
497
+ Self.selectionLog.debug(
498
+ "[applySelectionFromJSON.node] doc=\(pos) scalar=\(posScalar) final=\(self.selectionSummary(), privacy: .public)"
499
+ )
500
+ return SelectionApplyTrace(
501
+ totalNanos: DispatchTime.now().uptimeNanoseconds - totalStartedAt,
502
+ resolveNanos: resolveNanos,
503
+ assignmentNanos: assignmentNanos,
504
+ chromeNanos: chromeNanos
505
+ )
506
+
507
+ case "all":
508
+ let assignmentStartedAt = DispatchTime.now().uptimeNanoseconds
509
+ logicalSelectionScalarRange = nil
510
+ logicalSelectionUtf16Range = nil
511
+ selectedTextRange = textRange(from: beginningOfDocument, to: endOfDocument)
512
+ noteSelectionDidChange()
513
+ let assignmentNanos = DispatchTime.now().uptimeNanoseconds - assignmentStartedAt
514
+ let chromeStartedAt = DispatchTime.now().uptimeNanoseconds
515
+ showNativeSelectionChromeIfNeeded()
516
+ let chromeNanos = DispatchTime.now().uptimeNanoseconds - chromeStartedAt
517
+ Self.selectionLog.debug(
518
+ "[applySelectionFromJSON.all] final=\(self.selectionSummary(), privacy: .public)"
519
+ )
520
+ return SelectionApplyTrace(
521
+ totalNanos: DispatchTime.now().uptimeNanoseconds - totalStartedAt,
522
+ resolveNanos: 0,
523
+ assignmentNanos: assignmentNanos,
524
+ chromeNanos: chromeNanos
525
+ )
526
+
527
+ default:
528
+ return SelectionApplyTrace(totalNanos: 0, resolveNanos: 0, assignmentNanos: 0, chromeNanos: 0)
529
+ }
530
+ }
531
+
532
+ private func autocapitalizationFriendlyEmptyBlockPosition(
533
+ for position: UITextPosition
534
+ ) -> UITextPosition? {
535
+ guard isLoneEmptyPlaceholderBlock else { return nil }
536
+
537
+ let utf16Offset = offset(from: beginningOfDocument, to: position)
538
+ guard utf16Offset == textStorage.length else { return nil }
539
+ return beginningOfDocument
540
+ }
541
+
542
+ }