@fendent/react-native-enriched 0.5.2-fork.1

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 (278) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +343 -0
  3. package/ReactNativeEnriched.podspec +31 -0
  4. package/android/build.gradle +106 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +197 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +72 -0
  7. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
  8. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
  9. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +434 -0
  10. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +391 -0
  11. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.cpp +173 -0
  12. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.h +833 -0
  13. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
  14. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
  15. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.cpp +16 -0
  16. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.h +20 -0
  17. package/android/gradle.properties +5 -0
  18. package/android/lint.gradle +70 -0
  19. package/android/src/main/AndroidManifest.xml +3 -0
  20. package/android/src/main/AndroidManifestNew.xml +2 -0
  21. package/android/src/main/java/com/swmansion/enriched/ReactNativeEnrichedPackage.kt +20 -0
  22. package/android/src/main/java/com/swmansion/enriched/common/AsyncDrawable.kt +126 -0
  23. package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
  24. package/android/src/main/java/com/swmansion/enriched/common/EnrichedConstants.kt +11 -0
  25. package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
  26. package/android/src/main/java/com/swmansion/enriched/common/ForceRedrawSpan.kt +14 -0
  27. package/android/src/main/java/com/swmansion/enriched/common/GumboNormalizer.kt +5 -0
  28. package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +7 -0
  29. package/android/src/main/java/com/swmansion/enriched/common/ResourceManager.kt +26 -0
  30. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java +956 -0
  31. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
  32. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBlockQuoteSpan.kt +53 -0
  33. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBoldSpan.kt +12 -0
  34. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +92 -0
  35. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCodeBlockSpan.kt +81 -0
  36. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH1Span.kt +20 -0
  37. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH2Span.kt +20 -0
  38. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH3Span.kt +20 -0
  39. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH4Span.kt +21 -0
  40. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH5Span.kt +20 -0
  41. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH6Span.kt +20 -0
  42. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedImageSpan.kt +184 -0
  43. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedInlineCodeSpan.kt +24 -0
  44. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
  45. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedLinkSpan.kt +29 -0
  46. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedMentionSpan.kt +35 -0
  47. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedOrderedListSpan.kt +79 -0
  48. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedStrikeThroughSpan.kt +11 -0
  49. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnderlineSpan.kt +11 -0
  50. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnorderedListSpan.kt +62 -0
  51. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedBlockSpan.kt +5 -0
  52. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedHeadingSpan.kt +3 -0
  53. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
  54. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedParagraphSpan.kt +5 -0
  55. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
  56. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +4 -0
  57. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputConnectionWrapper.kt +140 -0
  58. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +83 -0
  59. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +1120 -0
  60. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewLayoutManager.kt +27 -0
  61. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt +478 -0
  62. package/android/src/main/java/com/swmansion/enriched/textinput/MeasurementStore.kt +225 -0
  63. package/android/src/main/java/com/swmansion/enriched/textinput/events/MentionHandler.kt +55 -0
  64. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeHtmlEvent.kt +27 -0
  65. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeSelectionEvent.kt +30 -0
  66. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeStateEvent.kt +21 -0
  67. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeTextEvent.kt +30 -0
  68. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnContextMenuItemPressEvent.kt +35 -0
  69. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputBlurEvent.kt +25 -0
  70. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputFocusEvent.kt +25 -0
  71. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputKeyPressEvent.kt +27 -0
  72. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnLinkDetectedEvent.kt +32 -0
  73. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionDetectedEvent.kt +30 -0
  74. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionEvent.kt +34 -0
  75. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
  76. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnRequestHtmlResultEvent.kt +32 -0
  77. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnSubmitEditingEvent.kt +29 -0
  78. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBlockQuoteSpan.kt +14 -0
  79. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBoldSpan.kt +14 -0
  80. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCheckboxListSpan.kt +15 -0
  81. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCodeBlockSpan.kt +14 -0
  82. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH1Span.kt +14 -0
  83. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH2Span.kt +14 -0
  84. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH3Span.kt +14 -0
  85. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH4Span.kt +14 -0
  86. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH5Span.kt +14 -0
  87. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH6Span.kt +14 -0
  88. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputImageSpan.kt +36 -0
  89. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputInlineCodeSpan.kt +14 -0
  90. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputItalicSpan.kt +14 -0
  91. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputLinkSpan.kt +16 -0
  92. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputMentionSpan.kt +18 -0
  93. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputOrderedListSpan.kt +21 -0
  94. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputStrikeThroughSpan.kt +14 -0
  95. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnderlineSpan.kt +14 -0
  96. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnorderedListSpan.kt +14 -0
  97. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedLineHeightSpan.kt +44 -0
  98. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedSpans.kt +241 -0
  99. package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
  100. package/android/src/main/java/com/swmansion/enriched/textinput/styles/HtmlStyle.kt +372 -0
  101. package/android/src/main/java/com/swmansion/enriched/textinput/styles/InlineStyles.kt +164 -0
  102. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt +263 -0
  103. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt +434 -0
  104. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +394 -0
  105. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedEditableFactory.kt +17 -0
  106. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSelection.kt +320 -0
  107. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +310 -0
  108. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannable.kt +106 -0
  109. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannableStringBuilder.kt +24 -0
  110. package/android/src/main/java/com/swmansion/enriched/textinput/utils/RichContentReceiver.kt +127 -0
  111. package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +106 -0
  112. package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedSpanWatcher.kt +107 -0
  113. package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedTextWatcher.kt +74 -0
  114. package/android/src/main/new_arch/CMakeLists.txt +62 -0
  115. package/android/src/main/new_arch/GumboNormalizerJni.cpp +14 -0
  116. package/android/src/main/new_arch/ReactNativeEnrichedSpec.cpp +11 -0
  117. package/android/src/main/new_arch/ReactNativeEnrichedSpec.h +15 -0
  118. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputComponentDescriptor.h +35 -0
  119. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.cpp +53 -0
  120. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.h +25 -0
  121. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.cpp +35 -0
  122. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.h +53 -0
  123. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.cpp +9 -0
  124. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.h +24 -0
  125. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +27 -0
  126. package/android/src/main/res/drawable/broken_image.xml +10 -0
  127. package/cpp/CMakeLists.txt +50 -0
  128. package/cpp/GumboParser/GumboParser.h +34043 -0
  129. package/cpp/README.md +59 -0
  130. package/cpp/parser/GumboNormalizer.c +915 -0
  131. package/cpp/parser/GumboParser.cpp +16 -0
  132. package/cpp/parser/GumboParser.hpp +23 -0
  133. package/cpp/tests/GumboParserTest.cpp +457 -0
  134. package/ios/EnrichedTextInputView.h +53 -0
  135. package/ios/EnrichedTextInputView.mm +2360 -0
  136. package/ios/EnrichedTextInputViewManager.mm +13 -0
  137. package/ios/attributesManager/AttributesManager.h +17 -0
  138. package/ios/attributesManager/AttributesManager.mm +195 -0
  139. package/ios/config/InputConfig.h +104 -0
  140. package/ios/config/InputConfig.mm +664 -0
  141. package/ios/extensions/ColorExtension.h +7 -0
  142. package/ios/extensions/ColorExtension.mm +38 -0
  143. package/ios/extensions/FontExtension.h +11 -0
  144. package/ios/extensions/FontExtension.mm +72 -0
  145. package/ios/extensions/ImageExtension.h +34 -0
  146. package/ios/extensions/ImageExtension.mm +165 -0
  147. package/ios/extensions/LayoutManagerExtension.h +6 -0
  148. package/ios/extensions/LayoutManagerExtension.mm +443 -0
  149. package/ios/extensions/StringExtension.h +15 -0
  150. package/ios/extensions/StringExtension.mm +69 -0
  151. package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
  152. package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
  153. package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +434 -0
  154. package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +391 -0
  155. package/ios/generated/ReactNativeEnrichedSpec/Props.cpp +173 -0
  156. package/ios/generated/ReactNativeEnrichedSpec/Props.h +833 -0
  157. package/ios/generated/ReactNativeEnrichedSpec/RCTComponentViewHelpers.h +582 -0
  158. package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
  159. package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
  160. package/ios/generated/ReactNativeEnrichedSpec/States.cpp +16 -0
  161. package/ios/generated/ReactNativeEnrichedSpec/States.h +20 -0
  162. package/ios/inputParser/InputParser.h +11 -0
  163. package/ios/inputParser/InputParser.mm +1463 -0
  164. package/ios/inputTextView/InputTextView.h +6 -0
  165. package/ios/inputTextView/InputTextView.mm +285 -0
  166. package/ios/interfaces/AttributeEntry.h +9 -0
  167. package/ios/interfaces/AttributeEntry.mm +4 -0
  168. package/ios/interfaces/BaseStyleProtocol.h +17 -0
  169. package/ios/interfaces/ImageAttachment.h +11 -0
  170. package/ios/interfaces/ImageAttachment.mm +107 -0
  171. package/ios/interfaces/ImageData.h +10 -0
  172. package/ios/interfaces/ImageData.mm +4 -0
  173. package/ios/interfaces/LinkData.h +11 -0
  174. package/ios/interfaces/LinkData.mm +29 -0
  175. package/ios/interfaces/LinkRegexConfig.h +19 -0
  176. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  177. package/ios/interfaces/MediaAttachment.h +23 -0
  178. package/ios/interfaces/MediaAttachment.mm +31 -0
  179. package/ios/interfaces/MentionParams.h +8 -0
  180. package/ios/interfaces/MentionParams.mm +4 -0
  181. package/ios/interfaces/MentionStyleProps.h +13 -0
  182. package/ios/interfaces/MentionStyleProps.mm +63 -0
  183. package/ios/interfaces/StyleBase.h +36 -0
  184. package/ios/interfaces/StyleBase.mm +256 -0
  185. package/ios/interfaces/StyleHeaders.h +102 -0
  186. package/ios/interfaces/StylePair.h +9 -0
  187. package/ios/interfaces/StylePair.mm +4 -0
  188. package/ios/interfaces/StyleTypeEnum.h +26 -0
  189. package/ios/interfaces/TextDecorationLineEnum.h +6 -0
  190. package/ios/interfaces/TextDecorationLineEnum.mm +4 -0
  191. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +19 -0
  192. package/ios/internals/EnrichedTextInputViewShadowNode.h +44 -0
  193. package/ios/internals/EnrichedTextInputViewShadowNode.mm +103 -0
  194. package/ios/internals/EnrichedTextInputViewState.cpp +10 -0
  195. package/ios/internals/EnrichedTextInputViewState.h +22 -0
  196. package/ios/styles/BlockQuoteStyle.mm +55 -0
  197. package/ios/styles/BoldStyle.mm +37 -0
  198. package/ios/styles/CheckboxListStyle.mm +153 -0
  199. package/ios/styles/CodeBlockStyle.mm +49 -0
  200. package/ios/styles/H1Style.mm +20 -0
  201. package/ios/styles/H2Style.mm +20 -0
  202. package/ios/styles/H3Style.mm +20 -0
  203. package/ios/styles/H4Style.mm +20 -0
  204. package/ios/styles/H5Style.mm +20 -0
  205. package/ios/styles/H6Style.mm +20 -0
  206. package/ios/styles/HeadingStyleBase.mm +65 -0
  207. package/ios/styles/ImageStyle.mm +146 -0
  208. package/ios/styles/InlineCodeStyle.mm +65 -0
  209. package/ios/styles/ItalicStyle.mm +37 -0
  210. package/ios/styles/LinkStyle.mm +532 -0
  211. package/ios/styles/MentionStyle.mm +538 -0
  212. package/ios/styles/OrderedListStyle.mm +86 -0
  213. package/ios/styles/StrikethroughStyle.mm +25 -0
  214. package/ios/styles/UnderlineStyle.mm +24 -0
  215. package/ios/styles/UnorderedListStyle.mm +86 -0
  216. package/ios/utils/CheckboxHitTestUtils.h +10 -0
  217. package/ios/utils/CheckboxHitTestUtils.mm +122 -0
  218. package/ios/utils/DotReplacementUtils.h +10 -0
  219. package/ios/utils/DotReplacementUtils.mm +68 -0
  220. package/ios/utils/KeyboardUtils.h +7 -0
  221. package/ios/utils/KeyboardUtils.mm +31 -0
  222. package/ios/utils/OccurenceUtils.h +44 -0
  223. package/ios/utils/OccurenceUtils.mm +179 -0
  224. package/ios/utils/ParagraphAttributesUtils.h +15 -0
  225. package/ios/utils/ParagraphAttributesUtils.mm +257 -0
  226. package/ios/utils/RangeUtils.h +12 -0
  227. package/ios/utils/RangeUtils.mm +183 -0
  228. package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
  229. package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
  230. package/ios/utils/TextInsertionUtils.h +17 -0
  231. package/ios/utils/TextInsertionUtils.mm +64 -0
  232. package/ios/utils/WordsUtils.h +7 -0
  233. package/ios/utils/WordsUtils.mm +98 -0
  234. package/ios/utils/ZeroWidthSpaceUtils.h +9 -0
  235. package/ios/utils/ZeroWidthSpaceUtils.mm +270 -0
  236. package/lib/module/index.js +4 -0
  237. package/lib/module/index.js.map +1 -0
  238. package/lib/module/native/EnrichedTextInput.js +304 -0
  239. package/lib/module/native/EnrichedTextInput.js.map +1 -0
  240. package/lib/module/package.json +1 -0
  241. package/lib/module/spec/EnrichedTextInputNativeComponent.ts +517 -0
  242. package/lib/module/types.js +4 -0
  243. package/lib/module/types.js.map +1 -0
  244. package/lib/module/utils/EnrichedTextInputDefaultProps.js +12 -0
  245. package/lib/module/utils/EnrichedTextInputDefaultProps.js.map +1 -0
  246. package/lib/module/utils/normalizeHtmlStyle.js +155 -0
  247. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  248. package/lib/module/utils/nullthrows.js +9 -0
  249. package/lib/module/utils/nullthrows.js.map +1 -0
  250. package/lib/module/utils/regexParser.js +46 -0
  251. package/lib/module/utils/regexParser.js.map +1 -0
  252. package/lib/typescript/package.json +1 -0
  253. package/lib/typescript/src/index.d.ts +3 -0
  254. package/lib/typescript/src/index.d.ts.map +1 -0
  255. package/lib/typescript/src/native/EnrichedTextInput.d.ts +3 -0
  256. package/lib/typescript/src/native/EnrichedTextInput.d.ts.map +1 -0
  257. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts +397 -0
  258. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
  259. package/lib/typescript/src/types.d.ts +447 -0
  260. package/lib/typescript/src/types.d.ts.map +1 -0
  261. package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts +10 -0
  262. package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts.map +1 -0
  263. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  264. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  265. package/lib/typescript/src/utils/nullthrows.d.ts +2 -0
  266. package/lib/typescript/src/utils/nullthrows.d.ts.map +1 -0
  267. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  268. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  269. package/package.json +226 -0
  270. package/react-native.config.js +13 -0
  271. package/src/index.tsx +20 -0
  272. package/src/native/EnrichedTextInput.tsx +370 -0
  273. package/src/spec/EnrichedTextInputNativeComponent.ts +517 -0
  274. package/src/types.ts +499 -0
  275. package/src/utils/EnrichedTextInputDefaultProps.ts +9 -0
  276. package/src/utils/normalizeHtmlStyle.ts +199 -0
  277. package/src/utils/nullthrows.ts +7 -0
  278. package/src/utils/regexParser.ts +56 -0
@@ -0,0 +1,257 @@
1
+ #import "ParagraphAttributesUtils.h"
2
+ #import "EnrichedTextInputView.h"
3
+ #import "RangeUtils.h"
4
+ #import "StyleHeaders.h"
5
+ #import "TextInsertionUtils.h"
6
+
7
+ @implementation ParagraphAttributesUtils
8
+
9
+ // if the user backspaces the last character in a line, the iOS applies typing
10
+ // attributes from the previous line in the case of some paragraph styles it
11
+ // works especially bad when a list point just appears this method handles that
12
+ // case differently with or without present paragraph styles
13
+ + (BOOL)handleBackspaceInRange:(NSRange)range
14
+ replacementText:(NSString *)text
15
+ input:(id)input {
16
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
17
+ if (typedInput == nullptr) {
18
+ return NO;
19
+ }
20
+
21
+ // we make sure it was a backspace (text with 0 length) and it deleted
22
+ // something (range longer than 0)
23
+ if (text.length > 0 || range.length == 0) {
24
+ return NO;
25
+ }
26
+
27
+ // find a non-newline range of the paragraph
28
+ NSRange paragraphRange =
29
+ [typedInput->textView.textStorage.string paragraphRangeForRange:range];
30
+
31
+ NSArray *paragraphs = [RangeUtils getNonNewlineRangesIn:typedInput->textView
32
+ range:paragraphRange];
33
+ if (paragraphs.count == 0) {
34
+ return NO;
35
+ }
36
+
37
+ NSRange nonNewlineRange = [(NSValue *)paragraphs.firstObject rangeValue];
38
+ CheckboxListStyle *cbLStyle =
39
+ typedInput->stylesDict[@([CheckboxListStyle getType])];
40
+
41
+ // the backspace removes the whole content of a paragraph (possibly more but
42
+ // has to start where the paragraph starts)
43
+ if (range.location == nonNewlineRange.location &&
44
+ range.length >= nonNewlineRange.length) {
45
+
46
+ // for styles that need ZWS (lists, quotes, etc.) we do the following:
47
+ // - manually do the removing
48
+ // - reset typing attributes so that the previous line styles don't get
49
+ // applied
50
+ // - reapply the paragraph style that was present so that a zero width space
51
+ // appears here
52
+ for (NSNumber *type in typedInput->stylesDict) {
53
+ StyleBase *style = typedInput->stylesDict[type];
54
+ if ([style needsZWS] && [style detect:nonNewlineRange]) {
55
+ BOOL isCurrentlyChecked = [cbLStyle getCheckboxStateAt:range.location];
56
+ [TextInsertionUtils replaceText:text
57
+ at:range
58
+ additionalAttributes:nullptr
59
+ input:typedInput
60
+ withSelection:YES];
61
+ typedInput->textView.typingAttributes =
62
+ typedInput->defaultTypingAttributes;
63
+
64
+ if (style == cbLStyle) {
65
+ [cbLStyle addWithChecked:isCurrentlyChecked
66
+ range:NSMakeRange(range.location, 0)
67
+ withTyping:YES
68
+ withDirtyRange:YES];
69
+ } else {
70
+ [style add:NSMakeRange(range.location, 0)
71
+ withTyping:YES
72
+ withDirtyRange:YES];
73
+ }
74
+ return YES;
75
+ }
76
+ }
77
+
78
+ // otherwise (no paragraph styles present), we just do the replacement
79
+ // manually and reset typing attribtues
80
+ [TextInsertionUtils replaceText:text
81
+ at:range
82
+ additionalAttributes:nullptr
83
+ input:typedInput
84
+ withSelection:YES];
85
+ typedInput->textView.typingAttributes = typedInput->defaultTypingAttributes;
86
+ return YES;
87
+ }
88
+
89
+ return NO;
90
+ }
91
+
92
+ /**
93
+ * Handles the specific case of backspacing a newline character, which results
94
+ * in merging two paragraphs.
95
+ *
96
+ * THE PROBLEM:
97
+ * When merging a bottom paragraph (Source) into a top paragraph (Destination),
98
+ * the bottom paragraph normally brings all its attributes with it. If the top
99
+ * paragraph is a restrictive style (like a CodeBlock), and the bottom paragraph
100
+ * contains a conflicting style (like an H1 Header), a standard merge would
101
+ * create an invalid state (e.g., a CodeBlock that is also a Header).
102
+ *
103
+ * THE SOLUTION:
104
+ * 1. Identifies the dominant style of the paragraph ABOVE the deleted newline
105
+ * (`leftParagraphStyle`).
106
+ * 2. Checks the paragraph BELOW the newline (`rightRange`) for any styles that
107
+ * conflict with or are blocked by the top style.
108
+ * 3. Explicitly removes those forbidden styles from the bottom paragraph
109
+ * *before* the merge occurs.
110
+ * 4. Performs the merge (deletes the newline).
111
+ *
112
+ * @return YES if the newline backspace was handled and sanitized; NO otherwise.
113
+ */
114
+ + (BOOL)handleParagraphStylesMergeOnBackspace:(NSRange)range
115
+ replacementText:(NSString *)text
116
+ input:(id)input {
117
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
118
+ if (typedInput == nullptr) {
119
+ return NO;
120
+ }
121
+
122
+ // Must be a backspace.
123
+ if (text.length > 0) {
124
+ return NO;
125
+ }
126
+
127
+ // Backspace must have removed a newline character.
128
+ NSString *removedString =
129
+ [typedInput->textView.textStorage.string substringWithRange:range];
130
+ if ([removedString
131
+ rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]]
132
+ .location == NSNotFound) {
133
+ return NO;
134
+ }
135
+
136
+ NSRange leftRange = [typedInput->textView.textStorage.string
137
+ paragraphRangeForRange:NSMakeRange(range.location, 0)];
138
+
139
+ StyleBase *leftParagraphStyle = nullptr;
140
+ for (NSNumber *key in typedInput->stylesDict) {
141
+ StyleBase *style = typedInput->stylesDict[key];
142
+ if ([style isParagraph] && [style detect:leftRange]) {
143
+ leftParagraphStyle = style;
144
+ }
145
+ }
146
+
147
+ if (leftParagraphStyle == nullptr) {
148
+ return NO;
149
+ }
150
+
151
+ // index out of bounds
152
+ NSUInteger rightRangeStart = range.location + range.length;
153
+ if (rightRangeStart >= typedInput->textView.textStorage.string.length) {
154
+ return NO;
155
+ }
156
+
157
+ NSRange rightRange = [typedInput->textView.textStorage.string
158
+ paragraphRangeForRange:NSMakeRange(rightRangeStart, 1)];
159
+
160
+ StyleType type = [[leftParagraphStyle class] getType];
161
+
162
+ NSArray *conflictingStyles = [typedInput
163
+ getPresentStyleTypesFrom:typedInput->conflictingStyles[@(type)]
164
+ range:rightRange];
165
+ NSArray *blockingStyles =
166
+ [typedInput getPresentStyleTypesFrom:typedInput->blockingStyles[@(type)]
167
+ range:rightRange];
168
+ NSArray *allToBeRemoved =
169
+ [conflictingStyles arrayByAddingObjectsFromArray:blockingStyles];
170
+
171
+ for (NSNumber *style in allToBeRemoved) {
172
+ StyleBase *styleToRemove = typedInput->stylesDict[style];
173
+
174
+ // for ranges, we need to remove each occurence
175
+ NSArray<StylePair *> *allOccurences = [styleToRemove all:rightRange];
176
+
177
+ for (StylePair *pair in allOccurences) {
178
+ [styleToRemove remove:[pair.rangeValue rangeValue] withDirtyRange:YES];
179
+ }
180
+ }
181
+
182
+ [TextInsertionUtils replaceText:text
183
+ at:range
184
+ additionalAttributes:nullptr
185
+ input:typedInput
186
+ withSelection:YES];
187
+ return YES;
188
+ }
189
+
190
+ /**
191
+ * Resets typing attributes to defaults when the cursor lands on an empty line
192
+ * after a deletion.
193
+ *
194
+ * This override is necessary because `UITextView` automatically inherits
195
+ * attributes from the preceding newline. This prevents scenarios where a
196
+ * restrictive style (like CodeBlock) "leaks" into the next empty paragraph.
197
+ */
198
+ + (BOOL)handleResetTypingAttributesOnBackspace:(NSRange)range
199
+ replacementText:(NSString *)text
200
+ input:(id)input {
201
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
202
+ if (typedInput == nullptr) {
203
+ return NO;
204
+ }
205
+
206
+ NSString *storageString = typedInput->textView.textStorage.string;
207
+
208
+ if (text.length > 0 || range.location >= storageString.length) {
209
+ return NO;
210
+ }
211
+
212
+ unichar firstCharToDelete = [storageString characterAtIndex:range.location];
213
+ if (![[NSCharacterSet newlineCharacterSet]
214
+ characterIsMember:firstCharToDelete]) {
215
+ return NO;
216
+ }
217
+
218
+ NSRange leftParagraphRange =
219
+ [storageString paragraphRangeForRange:NSMakeRange(range.location, 0)];
220
+ BOOL isLeftLineEmpty = [self isParagraphEmpty:leftParagraphRange
221
+ inString:storageString];
222
+
223
+ BOOL isRightLineEmpty = YES;
224
+ NSUInteger rightRangeStart = range.location + range.length;
225
+
226
+ if (rightRangeStart < storageString.length) {
227
+ NSRange rightParagraphRange =
228
+ [storageString paragraphRangeForRange:NSMakeRange(rightRangeStart, 0)];
229
+ isRightLineEmpty = [self isParagraphEmpty:rightParagraphRange
230
+ inString:storageString];
231
+ }
232
+
233
+ if (isLeftLineEmpty && isRightLineEmpty) {
234
+ [TextInsertionUtils replaceText:text
235
+ at:range
236
+ additionalAttributes:nullptr
237
+ input:typedInput
238
+ withSelection:YES];
239
+
240
+ typedInput->textView.typingAttributes = typedInput->defaultTypingAttributes;
241
+ return YES;
242
+ }
243
+
244
+ return NO;
245
+ }
246
+
247
+ + (BOOL)isParagraphEmpty:(NSRange)range inString:(NSString *)string {
248
+ if (range.length == 0)
249
+ return YES;
250
+
251
+ NSString *paragraphText = [string substringWithRange:range];
252
+ NSString *trimmed = [paragraphText
253
+ stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
254
+ return trimmed.length == 0;
255
+ }
256
+
257
+ @end
@@ -0,0 +1,12 @@
1
+ #pragma once
2
+ #import <UIKit/UIKit.h>
3
+
4
+ @interface RangeUtils : NSObject
5
+ + (NSArray *)getSeparateParagraphsRangesIn:(UITextView *)textView
6
+ range:(NSRange)range;
7
+ + (NSArray *)getNonNewlineRangesIn:(UITextView *)textView range:(NSRange)range;
8
+ + (NSArray *)connectAndDedupeRanges:(NSArray *)ranges;
9
+ + (NSArray *)shiftRanges:(NSArray *)ranges
10
+ withEditedRange:(NSRange)editedRange
11
+ changeInLength:(NSInteger)delta;
12
+ @end
@@ -0,0 +1,183 @@
1
+ #import "RangeUtils.h"
2
+
3
+ @implementation RangeUtils
4
+
5
+ + (NSArray *)getSeparateParagraphsRangesIn:(UITextView *)textView
6
+ range:(NSRange)range {
7
+ // just in case, get full paragraphs range
8
+ NSRange fullRange =
9
+ [textView.textStorage.string paragraphRangeForRange:range];
10
+
11
+ // we are in an empty paragraph
12
+ if (fullRange.length == 0) {
13
+ return @[ [NSValue valueWithRange:fullRange] ];
14
+ }
15
+
16
+ NSMutableArray *results = [[NSMutableArray alloc] init];
17
+
18
+ NSInteger lastStart = fullRange.location;
19
+ for (int i = int(fullRange.location);
20
+ i < fullRange.location + fullRange.length; i++) {
21
+ unichar currentChar = [textView.textStorage.string characterAtIndex:i];
22
+ if ([[NSCharacterSet newlineCharacterSet] characterIsMember:currentChar]) {
23
+ NSRange paragraphRange = [textView.textStorage.string
24
+ paragraphRangeForRange:NSMakeRange(lastStart, i - lastStart)];
25
+ [results addObject:[NSValue valueWithRange:paragraphRange]];
26
+ lastStart = i + 1;
27
+ }
28
+ }
29
+
30
+ if (lastStart < fullRange.location + fullRange.length) {
31
+ NSRange paragraphRange = [textView.textStorage.string
32
+ paragraphRangeForRange:NSMakeRange(lastStart, fullRange.location +
33
+ fullRange.length -
34
+ lastStart)];
35
+ [results addObject:[NSValue valueWithRange:paragraphRange]];
36
+ }
37
+
38
+ return results;
39
+ }
40
+
41
+ + (NSArray *)getNonNewlineRangesIn:(UITextView *)textView range:(NSRange)range {
42
+ NSMutableArray *nonNewlineRanges = [[NSMutableArray alloc] init];
43
+ int lastRangeLocation = int(range.location);
44
+
45
+ for (int i = int(range.location); i < range.location + range.length; i++) {
46
+ unichar currentChar = [textView.textStorage.string characterAtIndex:i];
47
+ if ([[NSCharacterSet newlineCharacterSet] characterIsMember:currentChar]) {
48
+ if (i - lastRangeLocation > 0) {
49
+ [nonNewlineRanges
50
+ addObject:[NSValue
51
+ valueWithRange:NSMakeRange(lastRangeLocation,
52
+ i - lastRangeLocation)]];
53
+ }
54
+ lastRangeLocation = i + 1;
55
+ }
56
+ }
57
+ if (lastRangeLocation < range.location + range.length) {
58
+ [nonNewlineRanges
59
+ addObject:[NSValue
60
+ valueWithRange:NSMakeRange(lastRangeLocation,
61
+ range.location + range.length -
62
+ lastRangeLocation)]];
63
+ }
64
+
65
+ return nonNewlineRanges;
66
+ }
67
+
68
+ // Condenses an array of NSRange to make sure the overlapping ones are connected
69
+ // + sorted based on NSRange.location
70
+ + (NSArray *)connectAndDedupeRanges:(NSArray *)ranges {
71
+ if (ranges.count == 0) {
72
+ return @[];
73
+ }
74
+
75
+ // We sort primarily by location. If locations match, shorter length goes
76
+ // first
77
+ NSArray<NSValue *> *sortedRanges =
78
+ [ranges sortedArrayUsingComparator:^NSComparisonResult(NSValue *obj1,
79
+ NSValue *obj2) {
80
+ NSRange range1 = obj1.rangeValue;
81
+ NSRange range2 = obj2.rangeValue;
82
+
83
+ if (range1.location < range2.location)
84
+ return NSOrderedAscending;
85
+ if (range1.location > range2.location)
86
+ return NSOrderedDescending;
87
+
88
+ if (range1.length < range2.length)
89
+ return NSOrderedAscending;
90
+ if (range1.length > range2.length)
91
+ return NSOrderedDescending;
92
+
93
+ return NSOrderedSame;
94
+ }];
95
+
96
+ NSMutableArray<NSValue *> *mergedRanges = [[NSMutableArray alloc] init];
97
+
98
+ // We work by comparing each two ranges.
99
+ // If we connected some ranges, the newly created one is still compared with
100
+ // the next ranges from the sorted list.
101
+ NSRange currentRange = sortedRanges[0].rangeValue;
102
+
103
+ for (NSUInteger i = 1; i < sortedRanges.count; i++) {
104
+ NSRange nextRange = sortedRanges[i].rangeValue;
105
+
106
+ // Calculate the end points
107
+ NSUInteger currentMax = currentRange.location + currentRange.length;
108
+ NSUInteger nextMax = nextRange.location + nextRange.length;
109
+
110
+ // If next range starts before (or exactly when) the current one ends.
111
+ if (nextRange.location <= currentMax) {
112
+ // Merge them; the new end is the maximum of the two ends
113
+ NSUInteger newMax = MAX(currentMax, nextMax);
114
+ currentRange.length = newMax - currentRange.location;
115
+ } else {
116
+ // No overlap; push the current range and start a new one
117
+ [mergedRanges addObject:[NSValue valueWithRange:currentRange]];
118
+ currentRange = nextRange;
119
+ }
120
+ }
121
+
122
+ // Add the final range
123
+ [mergedRanges addObject:[NSValue valueWithRange:currentRange]];
124
+
125
+ return [mergedRanges copy];
126
+ }
127
+
128
+ // Updates a list of NSRanges based on a text change, so that they are still
129
+ // pointing to the same characters. editedRange is the post-change range of the
130
+ // edited fragment. delta tells what is the length change of the edited
131
+ // fragment. While the ranges outside of the change are being just shifted, the
132
+ // ones intersecting with it are just merging with the change.
133
+ + (NSArray *)shiftRanges:(NSArray *)ranges
134
+ withEditedRange:(NSRange)editedRange
135
+ changeInLength:(NSInteger)delta {
136
+ NSMutableArray *result = [[NSMutableArray alloc] init];
137
+
138
+ // Calculate what the changed range was like before being edited
139
+ NSUInteger oldEditLength = editedRange.length - delta;
140
+ NSUInteger oldEditEnd = editedRange.location + oldEditLength;
141
+
142
+ NSUInteger newEditEnd = editedRange.location + editedRange.length;
143
+
144
+ for (NSValue *value in ranges) {
145
+ NSRange range = [value rangeValue];
146
+ NSUInteger rangeEnd = range.location + range.length;
147
+
148
+ if (rangeEnd <= editedRange.location) {
149
+ // Range was strictly before the old edit range.
150
+ // Do nothing.
151
+ [result addObject:value];
152
+ } else if (range.location >= oldEditEnd) {
153
+ // Range was strictly after the old edit range.
154
+ // Shift it by the delta.
155
+ [result
156
+ addObject:[NSValue valueWithRange:NSMakeRange(range.location + delta,
157
+ range.length)]];
158
+ } else {
159
+ // Range overlaps the old edit range in some way.
160
+ // Our best bet is to merge it with the edit range.
161
+
162
+ NSUInteger newStart = MIN(range.location, editedRange.location);
163
+
164
+ NSUInteger newEnd;
165
+ if (rangeEnd <= oldEditEnd) {
166
+ // The range was inside the editedRange before.
167
+ // So we use the newer editRange as the end here.
168
+ newEnd = newEditEnd;
169
+ } else {
170
+ // The range sticked outside of the editedRange before.
171
+ // It is safe to shift its end and use it.
172
+ newEnd = rangeEnd + delta;
173
+ }
174
+
175
+ NSRange adjustedRange = NSMakeRange(newStart, newEnd - newStart);
176
+ [result addObject:[NSValue valueWithRange:adjustedRange]];
177
+ }
178
+ }
179
+
180
+ return result;
181
+ }
182
+
183
+ @end
@@ -0,0 +1,17 @@
1
+ typedef NS_ENUM(NSInteger, TextBlockTapKind) {
2
+ TextBlockTapKindNone = 0,
3
+ TextBlockTapKindCheckbox,
4
+ };
5
+
6
+ @class EnrichedTextInputView;
7
+
8
+ @interface TextBlockTapGestureRecognizer : UITapGestureRecognizer
9
+ - (instancetype _Nonnull)initWithInput:(id _Nonnull)input
10
+ action:(SEL _Nonnull)action;
11
+
12
+ @property(nonatomic, weak) EnrichedTextInputView *input;
13
+
14
+ @property(nonatomic, assign, readonly) TextBlockTapKind tapKind;
15
+ @property(nonatomic, assign, readonly) NSInteger characterIndex;
16
+
17
+ @end
@@ -0,0 +1,56 @@
1
+ #import "TextBlockTapGestureRecognizer.h"
2
+ #import "CheckboxHitTestUtils.h"
3
+ #import "EnrichedTextInputView.h"
4
+
5
+ @implementation TextBlockTapGestureRecognizer {
6
+ TextBlockTapKind _tapKind;
7
+ NSInteger _characterIndex;
8
+ }
9
+
10
+ - (instancetype)initWithInput:(id)input action:(SEL)action {
11
+ self = [super initWithTarget:input action:action];
12
+ _input = input;
13
+
14
+ self.cancelsTouchesInView = YES;
15
+ self.delaysTouchesBegan = YES;
16
+ self.delaysTouchesEnded = YES;
17
+
18
+ for (UIGestureRecognizer *gr in _input->textView.gestureRecognizers) {
19
+ [gr requireGestureRecognizerToFail:self];
20
+ }
21
+
22
+ return self;
23
+ }
24
+
25
+ - (TextBlockTapKind)tapKind {
26
+ return _tapKind;
27
+ }
28
+
29
+ - (NSInteger)characterIndex {
30
+ return _characterIndex;
31
+ }
32
+
33
+ - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
34
+ _tapKind = TextBlockTapKindNone;
35
+ _characterIndex = NSNotFound;
36
+
37
+ if (!self.input) {
38
+ self.state = UIGestureRecognizerStateFailed;
39
+ return;
40
+ }
41
+
42
+ UITouch *touch = touches.anyObject;
43
+ CGPoint point = [touch locationInView:self.input->textView];
44
+ NSInteger checkboxIndex =
45
+ [CheckboxHitTestUtils hitTestCheckboxAtPoint:point inInput:self.input];
46
+
47
+ if (checkboxIndex >= 0) {
48
+ _tapKind = TextBlockTapKindCheckbox;
49
+ _characterIndex = checkboxIndex;
50
+ [super touchesBegan:touches withEvent:event];
51
+ return;
52
+ }
53
+ self.state = UIGestureRecognizerStateFailed;
54
+ }
55
+
56
+ @end
@@ -0,0 +1,17 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ @interface TextInsertionUtils : NSObject
4
+ + (void)insertText:(NSString *)text
5
+ at:(NSInteger)index
6
+ additionalAttributes:
7
+ (NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
8
+ input:(id)input
9
+ withSelection:(BOOL)withSelection;
10
+ + (void)replaceText:(NSString *)text
11
+ at:(NSRange)range
12
+ additionalAttributes:
13
+ (NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
14
+ input:(id)input
15
+ withSelection:(BOOL)withSelection;
16
+ ;
17
+ @end
@@ -0,0 +1,64 @@
1
+ #import "TextInsertionUtils.h"
2
+ #import "EnrichedTextInputView.h"
3
+ #import "UIView+React.h"
4
+
5
+ @implementation TextInsertionUtils
6
+ + (void)insertText:(NSString *)text
7
+ at:(NSInteger)index
8
+ additionalAttributes:
9
+ (NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
10
+ input:(id)input
11
+ withSelection:(BOOL)withSelection {
12
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
13
+ if (typedInput == nullptr) {
14
+ return;
15
+ }
16
+
17
+ UITextView *textView = typedInput->textView;
18
+
19
+ NSMutableDictionary<NSAttributedStringKey, id> *copiedAttrs =
20
+ [textView.typingAttributes mutableCopy];
21
+ if (additionalAttrs != nullptr) {
22
+ [copiedAttrs addEntriesFromDictionary:additionalAttrs];
23
+ }
24
+
25
+ NSAttributedString *newAttrStr =
26
+ [[NSAttributedString alloc] initWithString:text attributes:copiedAttrs];
27
+ [textView.textStorage insertAttributedString:newAttrStr atIndex:index];
28
+
29
+ if (withSelection) {
30
+ if (![textView isFirstResponder]) {
31
+ [textView reactFocus];
32
+ }
33
+ textView.selectedRange = NSMakeRange(index + text.length, 0);
34
+ }
35
+ }
36
+
37
+ + (void)replaceText:(NSString *)text
38
+ at:(NSRange)range
39
+ additionalAttributes:
40
+ (NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
41
+ input:(id)input
42
+ withSelection:(BOOL)withSelection {
43
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
44
+ if (typedInput == nullptr) {
45
+ return;
46
+ }
47
+
48
+ UITextView *textView = typedInput->textView;
49
+
50
+ [textView.textStorage replaceCharactersInRange:range withString:text];
51
+ if (additionalAttrs != nullptr) {
52
+ [textView.textStorage
53
+ addAttributes:additionalAttrs
54
+ range:NSMakeRange(range.location, [text length])];
55
+ }
56
+
57
+ if (withSelection) {
58
+ if (![textView isFirstResponder]) {
59
+ [textView reactFocus];
60
+ }
61
+ textView.selectedRange = NSMakeRange(range.location + text.length, 0);
62
+ }
63
+ }
64
+ @end
@@ -0,0 +1,7 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ @interface WordsUtils : NSObject
4
+ + (NSArray<NSDictionary *> *)getAffectedWordsFromText:(NSString *)text
5
+ modificationRange:(NSRange)range;
6
+ + (NSDictionary *)getCurrentWord:(NSString *)text range:(NSRange)range;
7
+ @end