react-native-enriched-html 0.0.0 → 1.0.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 (747) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +402 -0
  3. package/ReactNativeEnrichedHtml.podspec +31 -0
  4. package/android/build.gradle +106 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +203 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +74 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextViewManagerDelegate.java +70 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextViewManagerInterface.java +31 -0
  9. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
  10. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
  11. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +456 -0
  12. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +410 -0
  13. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.cpp +272 -0
  14. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.h +1595 -0
  15. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
  16. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
  17. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.cpp +16 -0
  18. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.h +20 -0
  19. package/android/gradle.properties +5 -0
  20. package/android/lint.gradle +70 -0
  21. package/android/src/main/AndroidManifest.xml +3 -0
  22. package/android/src/main/AndroidManifestNew.xml +2 -0
  23. package/android/src/main/java/com/swmansion/enriched/ReactNativeEnrichedPackage.kt +22 -0
  24. package/android/src/main/java/com/swmansion/enriched/common/AllowFontScaling.kt +36 -0
  25. package/android/src/main/java/com/swmansion/enriched/common/AsyncDrawable.kt +126 -0
  26. package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
  27. package/android/src/main/java/com/swmansion/enriched/common/EnrichedConstants.kt +16 -0
  28. package/android/src/main/java/com/swmansion/enriched/common/EnrichedSpanFlags.kt +39 -0
  29. package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
  30. package/android/src/main/java/com/swmansion/enriched/common/ForceRedrawSpan.kt +14 -0
  31. package/android/src/main/java/com/swmansion/enriched/common/GumboNormalizer.kt +5 -0
  32. package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +9 -0
  33. package/android/src/main/java/com/swmansion/enriched/common/ResourceManager.kt +26 -0
  34. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java +1057 -0
  35. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +83 -0
  36. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedAlignmentSpan.kt +19 -0
  37. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBlockQuoteSpan.kt +53 -0
  38. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBoldSpan.kt +12 -0
  39. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +92 -0
  40. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCodeBlockSpan.kt +81 -0
  41. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH1Span.kt +20 -0
  42. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH2Span.kt +20 -0
  43. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH3Span.kt +20 -0
  44. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH4Span.kt +21 -0
  45. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH5Span.kt +20 -0
  46. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH6Span.kt +20 -0
  47. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedImageSpan.kt +185 -0
  48. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedInlineCodeSpan.kt +24 -0
  49. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
  50. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedLinkSpan.kt +29 -0
  51. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedMentionSpan.kt +35 -0
  52. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedOrderedListSpan.kt +79 -0
  53. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedStrikeThroughSpan.kt +11 -0
  54. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnderlineSpan.kt +11 -0
  55. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnorderedListSpan.kt +62 -0
  56. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedBlockSpan.kt +5 -0
  57. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedHeadingSpan.kt +3 -0
  58. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
  59. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedParagraphSpan.kt +5 -0
  60. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
  61. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +4 -0
  62. package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextMovementMethod.kt +75 -0
  63. package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextSpanFactory.kt +84 -0
  64. package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextStyle.kt +202 -0
  65. package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextView.kt +362 -0
  66. package/android/src/main/java/com/swmansion/enriched/text/EnrichedTextViewManager.kt +157 -0
  67. package/android/src/main/java/com/swmansion/enriched/text/MeasurementStore.kt +170 -0
  68. package/android/src/main/java/com/swmansion/enriched/text/events/OnLinkPressEvent.kt +23 -0
  69. package/android/src/main/java/com/swmansion/enriched/text/events/OnMentionPressEvent.kt +32 -0
  70. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextAlignmentSpan.kt +14 -0
  71. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextBlockQuoteSpan.kt +14 -0
  72. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextBoldSpan.kt +14 -0
  73. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextCheckboxListSpan.kt +15 -0
  74. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextCodeBlockSpan.kt +14 -0
  75. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextH1Span.kt +14 -0
  76. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextH2Span.kt +14 -0
  77. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextH3Span.kt +15 -0
  78. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextH4Span.kt +15 -0
  79. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextH5Span.kt +14 -0
  80. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextH6Span.kt +14 -0
  81. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextImageSpan.kt +57 -0
  82. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextInlineCodeSpan.kt +14 -0
  83. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextItalicSpan.kt +14 -0
  84. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextLinkSpan.kt +41 -0
  85. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextMentionSpan.kt +63 -0
  86. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextOrderedListSpan.kt +16 -0
  87. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextStrikeThroughSpan.kt +15 -0
  88. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextUnderlineSpan.kt +15 -0
  89. package/android/src/main/java/com/swmansion/enriched/text/spans/EnrichedTextUnorderedListSpan.kt +15 -0
  90. package/android/src/main/java/com/swmansion/enriched/text/spans/interfaces/EnrichedTextClickableSpan.kt +9 -0
  91. package/android/src/main/java/com/swmansion/enriched/text/spans/interfaces/EnrichedTextSpan.kt +10 -0
  92. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputConnectionWrapper.kt +140 -0
  93. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +86 -0
  94. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +1144 -0
  95. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewLayoutManager.kt +27 -0
  96. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt +500 -0
  97. package/android/src/main/java/com/swmansion/enriched/textinput/MeasurementStore.kt +230 -0
  98. package/android/src/main/java/com/swmansion/enriched/textinput/events/MentionHandler.kt +65 -0
  99. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeHtmlEvent.kt +27 -0
  100. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeSelectionEvent.kt +30 -0
  101. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeStateEvent.kt +21 -0
  102. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeTextEvent.kt +30 -0
  103. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnContextMenuItemPressEvent.kt +35 -0
  104. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputBlurEvent.kt +25 -0
  105. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputFocusEvent.kt +25 -0
  106. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputKeyPressEvent.kt +27 -0
  107. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnLinkDetectedEvent.kt +32 -0
  108. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionDetectedEvent.kt +30 -0
  109. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionEvent.kt +40 -0
  110. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
  111. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnRequestHtmlResultEvent.kt +32 -0
  112. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnSubmitEditingEvent.kt +29 -0
  113. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputAlignmentSpan.kt +14 -0
  114. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBlockQuoteSpan.kt +14 -0
  115. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBoldSpan.kt +14 -0
  116. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCheckboxListSpan.kt +15 -0
  117. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCodeBlockSpan.kt +14 -0
  118. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH1Span.kt +14 -0
  119. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH2Span.kt +14 -0
  120. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH3Span.kt +14 -0
  121. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH4Span.kt +14 -0
  122. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH5Span.kt +14 -0
  123. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH6Span.kt +14 -0
  124. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputImageSpan.kt +36 -0
  125. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputInlineCodeSpan.kt +14 -0
  126. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputItalicSpan.kt +14 -0
  127. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputLinkSpan.kt +16 -0
  128. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputMentionSpan.kt +18 -0
  129. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputOrderedListSpan.kt +21 -0
  130. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputStrikeThroughSpan.kt +14 -0
  131. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnderlineSpan.kt +14 -0
  132. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnorderedListSpan.kt +14 -0
  133. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedLineHeightSpan.kt +45 -0
  134. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedSpans.kt +240 -0
  135. package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
  136. package/android/src/main/java/com/swmansion/enriched/textinput/styles/AlignmentStyles.kt +366 -0
  137. package/android/src/main/java/com/swmansion/enriched/textinput/styles/HtmlStyle.kt +371 -0
  138. package/android/src/main/java/com/swmansion/enriched/textinput/styles/InlineStyles.kt +244 -0
  139. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt +261 -0
  140. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt +440 -0
  141. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +435 -0
  142. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedEditableFactory.kt +17 -0
  143. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSelection.kt +342 -0
  144. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +318 -0
  145. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannable.kt +157 -0
  146. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannableStringBuilder.kt +59 -0
  147. package/android/src/main/java/com/swmansion/enriched/textinput/utils/RichContentReceiver.kt +127 -0
  148. package/android/src/main/java/com/swmansion/enriched/textinput/utils/ShortcutsHandler.kt +150 -0
  149. package/android/src/main/java/com/swmansion/enriched/textinput/utils/StyleUtils.kt +51 -0
  150. package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +107 -0
  151. package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedSpanWatcher.kt +109 -0
  152. package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedTextWatcher.kt +106 -0
  153. package/android/src/main/new_arch/CMakeLists.txt +62 -0
  154. package/android/src/main/new_arch/GumboNormalizerJni.cpp +14 -0
  155. package/android/src/main/new_arch/ReactNativeEnrichedSpec.cpp +11 -0
  156. package/android/src/main/new_arch/ReactNativeEnrichedSpec.h +16 -0
  157. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextComponentDescriptor.h +32 -0
  158. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputComponentDescriptor.h +35 -0
  159. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.cpp +53 -0
  160. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.h +25 -0
  161. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.cpp +35 -0
  162. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.h +53 -0
  163. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.cpp +9 -0
  164. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.h +24 -0
  165. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextMeasurementManager.cpp +45 -0
  166. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextMeasurementManager.h +25 -0
  167. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextShadowNode.cpp +21 -0
  168. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextShadowNode.h +39 -0
  169. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +44 -0
  170. package/android/src/main/res/drawable/broken_image.xml +10 -0
  171. package/cpp/CMakeLists.txt +50 -0
  172. package/cpp/GumboParser/GumboParser.h +34043 -0
  173. package/cpp/README.md +59 -0
  174. package/cpp/parser/GumboNormalizer.c +973 -0
  175. package/cpp/parser/GumboParser.cpp +16 -0
  176. package/cpp/parser/GumboParser.hpp +23 -0
  177. package/cpp/tests/GumboParserTest.cpp +511 -0
  178. package/ios/EnrichedTextInputView.h +54 -0
  179. package/ios/EnrichedTextInputView.mm +2182 -0
  180. package/ios/EnrichedTextInputViewManager.mm +13 -0
  181. package/ios/EnrichedTextView.h +35 -0
  182. package/ios/EnrichedTextView.mm +806 -0
  183. package/ios/EnrichedTextViewManager.mm +13 -0
  184. package/ios/config/EnrichedConfig.h +114 -0
  185. package/ios/config/EnrichedConfig.mm +727 -0
  186. package/ios/enrichedInputTextView/EnrichedInputTextView.h +6 -0
  187. package/ios/enrichedInputTextView/EnrichedInputTextView.mm +334 -0
  188. package/ios/enrichedTextTextView/EnrichedTextTextView.h +16 -0
  189. package/ios/enrichedTextTextView/EnrichedTextTextView.mm +71 -0
  190. package/ios/extensions/ColorExtension.h +8 -0
  191. package/ios/extensions/ColorExtension.mm +48 -0
  192. package/ios/extensions/FontExtension.h +11 -0
  193. package/ios/extensions/FontExtension.mm +72 -0
  194. package/ios/extensions/ImageExtension.h +33 -0
  195. package/ios/extensions/ImageExtension.mm +176 -0
  196. package/ios/extensions/LayoutManagerExtension.h +6 -0
  197. package/ios/extensions/LayoutManagerExtension.mm +465 -0
  198. package/ios/extensions/StringExtension.h +15 -0
  199. package/ios/extensions/StringExtension.mm +144 -0
  200. package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
  201. package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
  202. package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +456 -0
  203. package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +410 -0
  204. package/ios/generated/ReactNativeEnrichedSpec/Props.cpp +272 -0
  205. package/ios/generated/ReactNativeEnrichedSpec/Props.h +1595 -0
  206. package/ios/generated/ReactNativeEnrichedSpec/RCTComponentViewHelpers.h +570 -0
  207. package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
  208. package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
  209. package/ios/generated/ReactNativeEnrichedSpec/States.cpp +16 -0
  210. package/ios/generated/ReactNativeEnrichedSpec/States.h +20 -0
  211. package/ios/htmlParser/HtmlParser.h +14 -0
  212. package/ios/htmlParser/HtmlParser.mm +1486 -0
  213. package/ios/inputAttributesManager/InputAttributesManager.h +18 -0
  214. package/ios/inputAttributesManager/InputAttributesManager.mm +222 -0
  215. package/ios/inputHtmlParser/InputHtmlParser.h +10 -0
  216. package/ios/inputHtmlParser/InputHtmlParser.mm +228 -0
  217. package/ios/interfaces/AlignmentEntry.h +9 -0
  218. package/ios/interfaces/AlignmentEntry.mm +4 -0
  219. package/ios/interfaces/AttributeEntry.h +9 -0
  220. package/ios/interfaces/AttributeEntry.mm +4 -0
  221. package/ios/interfaces/BaseStyleProtocol.h +17 -0
  222. package/ios/interfaces/EnrichedTextStyleHeaders.h +62 -0
  223. package/ios/interfaces/EnrichedViewHost.h +26 -0
  224. package/ios/interfaces/ImageAttachment.h +11 -0
  225. package/ios/interfaces/ImageAttachment.mm +107 -0
  226. package/ios/interfaces/ImageData.h +10 -0
  227. package/ios/interfaces/ImageData.mm +4 -0
  228. package/ios/interfaces/LinkData.h +11 -0
  229. package/ios/interfaces/LinkData.mm +43 -0
  230. package/ios/interfaces/LinkRegexConfig.h +19 -0
  231. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  232. package/ios/interfaces/MediaAttachment.h +23 -0
  233. package/ios/interfaces/MediaAttachment.mm +31 -0
  234. package/ios/interfaces/MentionParams.h +8 -0
  235. package/ios/interfaces/MentionParams.mm +4 -0
  236. package/ios/interfaces/MentionStyleProps.h +17 -0
  237. package/ios/interfaces/MentionStyleProps.mm +80 -0
  238. package/ios/interfaces/StyleBase.h +38 -0
  239. package/ios/interfaces/StyleBase.mm +279 -0
  240. package/ios/interfaces/StyleHeaders.h +114 -0
  241. package/ios/interfaces/StylePair.h +9 -0
  242. package/ios/interfaces/StylePair.mm +4 -0
  243. package/ios/interfaces/StyleTypeEnum.h +27 -0
  244. package/ios/interfaces/TextDecorationLineEnum.h +6 -0
  245. package/ios/interfaces/TextDecorationLineEnum.mm +4 -0
  246. package/ios/internals/EnrichedTextComponentDescriptor.h +19 -0
  247. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +19 -0
  248. package/ios/internals/EnrichedTextInputViewShadowNode.h +44 -0
  249. package/ios/internals/EnrichedTextInputViewShadowNode.mm +103 -0
  250. package/ios/internals/EnrichedTextInputViewState.cpp +10 -0
  251. package/ios/internals/EnrichedTextInputViewState.h +22 -0
  252. package/ios/internals/EnrichedTextViewShadowNode.h +34 -0
  253. package/ios/internals/EnrichedTextViewShadowNode.mm +72 -0
  254. package/ios/internals/EnrichedTextViewState.cpp +7 -0
  255. package/ios/internals/EnrichedTextViewState.h +18 -0
  256. package/ios/styles/AlignmentStyle.mm +203 -0
  257. package/ios/styles/BlockQuoteStyle.mm +54 -0
  258. package/ios/styles/BoldStyle.mm +37 -0
  259. package/ios/styles/CheckboxListStyle.mm +154 -0
  260. package/ios/styles/CodeBlockStyle.mm +49 -0
  261. package/ios/styles/EnrichedTextStyles.mm +61 -0
  262. package/ios/styles/H1Style.mm +20 -0
  263. package/ios/styles/H2Style.mm +20 -0
  264. package/ios/styles/H3Style.mm +20 -0
  265. package/ios/styles/H4Style.mm +20 -0
  266. package/ios/styles/H5Style.mm +20 -0
  267. package/ios/styles/H6Style.mm +20 -0
  268. package/ios/styles/HeadingStyleBase.mm +96 -0
  269. package/ios/styles/ImageStyle.mm +150 -0
  270. package/ios/styles/InlineCodeStyle.mm +65 -0
  271. package/ios/styles/ItalicStyle.mm +37 -0
  272. package/ios/styles/LinkStyle.mm +518 -0
  273. package/ios/styles/MentionStyle.mm +592 -0
  274. package/ios/styles/OrderedListStyle.mm +48 -0
  275. package/ios/styles/StrikethroughStyle.mm +25 -0
  276. package/ios/styles/UnderlineStyle.mm +24 -0
  277. package/ios/styles/UnorderedListStyle.mm +48 -0
  278. package/ios/textHtmlParser/TextHtmlParser.h +10 -0
  279. package/ios/textHtmlParser/TextHtmlParser.mm +182 -0
  280. package/ios/utils/AlignmentUtils.h +20 -0
  281. package/ios/utils/AlignmentUtils.mm +111 -0
  282. package/ios/utils/AttachmentLayoutUtils.h +24 -0
  283. package/ios/utils/AttachmentLayoutUtils.mm +144 -0
  284. package/ios/utils/CheckboxHitTestUtils.h +10 -0
  285. package/ios/utils/CheckboxHitTestUtils.mm +122 -0
  286. package/ios/utils/DotReplacementUtils.h +10 -0
  287. package/ios/utils/DotReplacementUtils.mm +68 -0
  288. package/ios/utils/EnrichedTextTouchHandler.h +14 -0
  289. package/ios/utils/EnrichedTextTouchHandler.mm +152 -0
  290. package/ios/utils/KeyboardUtils.h +7 -0
  291. package/ios/utils/KeyboardUtils.mm +30 -0
  292. package/ios/utils/OccurenceUtils.h +44 -0
  293. package/ios/utils/OccurenceUtils.mm +185 -0
  294. package/ios/utils/ParagraphAttributesUtils.h +18 -0
  295. package/ios/utils/ParagraphAttributesUtils.mm +296 -0
  296. package/ios/utils/RangeUtils.h +12 -0
  297. package/ios/utils/RangeUtils.mm +183 -0
  298. package/ios/utils/ShortcutsUtils.h +21 -0
  299. package/ios/utils/ShortcutsUtils.mm +486 -0
  300. package/ios/utils/StyleUtils.h +33 -0
  301. package/ios/utils/StyleUtils.mm +290 -0
  302. package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
  303. package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
  304. package/ios/utils/TextInsertionUtils.h +17 -0
  305. package/ios/utils/TextInsertionUtils.mm +60 -0
  306. package/ios/utils/TextListsUtils.h +40 -0
  307. package/ios/utils/TextListsUtils.mm +93 -0
  308. package/ios/utils/WeakBox.h +3 -0
  309. package/ios/utils/WeakBox.m +4 -0
  310. package/ios/utils/WordsUtils.h +7 -0
  311. package/ios/utils/WordsUtils.mm +98 -0
  312. package/ios/utils/ZeroWidthSpaceUtils.h +14 -0
  313. package/ios/utils/ZeroWidthSpaceUtils.mm +310 -0
  314. package/lib/module/index.js +5 -0
  315. package/lib/module/index.js.map +1 -0
  316. package/lib/module/index.native.js +7 -0
  317. package/lib/module/index.native.js.map +1 -0
  318. package/lib/module/native/EnrichedText.js +76 -0
  319. package/lib/module/native/EnrichedText.js.map +1 -0
  320. package/lib/module/native/EnrichedTextInput.js +306 -0
  321. package/lib/module/native/EnrichedTextInput.js.map +1 -0
  322. package/lib/module/package.json +1 -0
  323. package/lib/module/spec/EnrichedTextInputNativeComponent.ts +524 -0
  324. package/lib/module/spec/EnrichedTextNativeComponent.ts +110 -0
  325. package/lib/module/types.js +4 -0
  326. package/lib/module/types.js.map +1 -0
  327. package/lib/module/utils/EnrichedTextInputDefaultProps.js +20 -0
  328. package/lib/module/utils/EnrichedTextInputDefaultProps.js.map +1 -0
  329. package/lib/module/utils/defaultHtmlStyle.js +83 -0
  330. package/lib/module/utils/defaultHtmlStyle.js.map +1 -0
  331. package/lib/module/utils/expandMentionStylesForIndicators.js +14 -0
  332. package/lib/module/utils/expandMentionStylesForIndicators.js.map +1 -0
  333. package/lib/module/utils/isMentionStyleRecord.js +10 -0
  334. package/lib/module/utils/isMentionStyleRecord.js.map +1 -0
  335. package/lib/module/utils/normalizeHtmlStyle.js +126 -0
  336. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  337. package/lib/module/utils/nullthrows.js +9 -0
  338. package/lib/module/utils/nullthrows.js.map +1 -0
  339. package/lib/module/utils/regexParser.js +46 -0
  340. package/lib/module/utils/regexParser.js.map +1 -0
  341. package/lib/module/web/EnrichedText.css +343 -0
  342. package/lib/module/web/EnrichedText.js +55 -0
  343. package/lib/module/web/EnrichedText.js.map +1 -0
  344. package/lib/module/web/EnrichedTextInput.js +316 -0
  345. package/lib/module/web/EnrichedTextInput.js.map +1 -0
  346. package/lib/module/web/adaptWebToNativeEvent.js +34 -0
  347. package/lib/module/web/adaptWebToNativeEvent.js.map +1 -0
  348. package/lib/module/web/constants/brokenImageGlyph.js +9 -0
  349. package/lib/module/web/constants/brokenImageGlyph.js.map +1 -0
  350. package/lib/module/web/constants/classNames.js +5 -0
  351. package/lib/module/web/constants/classNames.js.map +1 -0
  352. package/lib/module/web/emitLinkDetected.js +12 -0
  353. package/lib/module/web/emitLinkDetected.js.map +1 -0
  354. package/lib/module/web/formats/EnrichedBlockquote.js +32 -0
  355. package/lib/module/web/formats/EnrichedBlockquote.js.map +1 -0
  356. package/lib/module/web/formats/EnrichedBold.js +22 -0
  357. package/lib/module/web/formats/EnrichedBold.js.map +1 -0
  358. package/lib/module/web/formats/EnrichedCheckboxItem.js +32 -0
  359. package/lib/module/web/formats/EnrichedCheckboxItem.js.map +1 -0
  360. package/lib/module/web/formats/EnrichedCheckboxList.js +35 -0
  361. package/lib/module/web/formats/EnrichedCheckboxList.js.map +1 -0
  362. package/lib/module/web/formats/EnrichedCode.js +15 -0
  363. package/lib/module/web/formats/EnrichedCode.js.map +1 -0
  364. package/lib/module/web/formats/EnrichedCodeBlock.js +43 -0
  365. package/lib/module/web/formats/EnrichedCodeBlock.js.map +1 -0
  366. package/lib/module/web/formats/EnrichedHeading.js +27 -0
  367. package/lib/module/web/formats/EnrichedHeading.js.map +1 -0
  368. package/lib/module/web/formats/EnrichedImage.js +57 -0
  369. package/lib/module/web/formats/EnrichedImage.js.map +1 -0
  370. package/lib/module/web/formats/EnrichedImageNodeView.js +90 -0
  371. package/lib/module/web/formats/EnrichedImageNodeView.js.map +1 -0
  372. package/lib/module/web/formats/EnrichedItalic.js +22 -0
  373. package/lib/module/web/formats/EnrichedItalic.js.map +1 -0
  374. package/lib/module/web/formats/EnrichedLink.js +180 -0
  375. package/lib/module/web/formats/EnrichedLink.js.map +1 -0
  376. package/lib/module/web/formats/EnrichedListItem.js +19 -0
  377. package/lib/module/web/formats/EnrichedListItem.js.map +1 -0
  378. package/lib/module/web/formats/EnrichedMention.js +50 -0
  379. package/lib/module/web/formats/EnrichedMention.js.map +1 -0
  380. package/lib/module/web/formats/EnrichedOrderedList.js +32 -0
  381. package/lib/module/web/formats/EnrichedOrderedList.js.map +1 -0
  382. package/lib/module/web/formats/EnrichedStrike.js +22 -0
  383. package/lib/module/web/formats/EnrichedStrike.js.map +1 -0
  384. package/lib/module/web/formats/EnrichedTextAlign.js +82 -0
  385. package/lib/module/web/formats/EnrichedTextAlign.js.map +1 -0
  386. package/lib/module/web/formats/EnrichedUnderline.js +22 -0
  387. package/lib/module/web/formats/EnrichedUnderline.js.map +1 -0
  388. package/lib/module/web/formats/EnrichedUnorderedList.js +33 -0
  389. package/lib/module/web/formats/EnrichedUnorderedList.js.map +1 -0
  390. package/lib/module/web/formats/applyWrappingListToSelection.js +64 -0
  391. package/lib/module/web/formats/applyWrappingListToSelection.js.map +1 -0
  392. package/lib/module/web/formats/formatRules.js +84 -0
  393. package/lib/module/web/formats/formatRules.js.map +1 -0
  394. package/lib/module/web/formats/listKeyboard.js +53 -0
  395. package/lib/module/web/formats/listKeyboard.js.map +1 -0
  396. package/lib/module/web/formats/wrappedBlockKeyboard.js +58 -0
  397. package/lib/module/web/formats/wrappedBlockKeyboard.js.map +1 -0
  398. package/lib/module/web/normalization/checkboxHtmlNormalizer.js +54 -0
  399. package/lib/module/web/normalization/checkboxHtmlNormalizer.js.map +1 -0
  400. package/lib/module/web/normalization/htmlNormalizer.js +514 -0
  401. package/lib/module/web/normalization/htmlNormalizer.js.map +1 -0
  402. package/lib/module/web/normalization/prepareHtmlForWeb.js +78 -0
  403. package/lib/module/web/normalization/prepareHtmlForWeb.js.map +1 -0
  404. package/lib/module/web/normalization/tiptapHtmlNormalizer.js +34 -0
  405. package/lib/module/web/normalization/tiptapHtmlNormalizer.js.map +1 -0
  406. package/lib/module/web/pasteImages.js +78 -0
  407. package/lib/module/web/pasteImages.js.map +1 -0
  408. package/lib/module/web/pastedImageDimensions.js +49 -0
  409. package/lib/module/web/pastedImageDimensions.js.map +1 -0
  410. package/lib/module/web/pmPlugins/AutolinkPlugin/autolinkRegex.js +27 -0
  411. package/lib/module/web/pmPlugins/AutolinkPlugin/autolinkRegex.js.map +1 -0
  412. package/lib/module/web/pmPlugins/AutolinkPlugin/index.js +178 -0
  413. package/lib/module/web/pmPlugins/AutolinkPlugin/index.js.map +1 -0
  414. package/lib/module/web/pmPlugins/MentionPlugin/index.js +36 -0
  415. package/lib/module/web/pmPlugins/MentionPlugin/index.js.map +1 -0
  416. package/lib/module/web/pmPlugins/MentionPlugin/isCaretInBlockedContext.js +11 -0
  417. package/lib/module/web/pmPlugins/MentionPlugin/isCaretInBlockedContext.js.map +1 -0
  418. package/lib/module/web/pmPlugins/MentionPlugin/makeMentionPluginState.js +86 -0
  419. package/lib/module/web/pmPlugins/MentionPlugin/makeMentionPluginState.js.map +1 -0
  420. package/lib/module/web/pmPlugins/MentionPlugin/mentionPluginKey.js +5 -0
  421. package/lib/module/web/pmPlugins/MentionPlugin/mentionPluginKey.js.map +1 -0
  422. package/lib/module/web/pmPlugins/MentionPlugin/removeMentionMarksIfSpansResized.js +56 -0
  423. package/lib/module/web/pmPlugins/MentionPlugin/removeMentionMarksIfSpansResized.js.map +1 -0
  424. package/lib/module/web/pmPlugins/MentionPlugin/setMention.js +57 -0
  425. package/lib/module/web/pmPlugins/MentionPlugin/setMention.js.map +1 -0
  426. package/lib/module/web/pmPlugins/MentionPlugin/startMention.js +9 -0
  427. package/lib/module/web/pmPlugins/MentionPlugin/startMention.js.map +1 -0
  428. package/lib/module/web/pmPlugins/MentionPlugin/stripPartialMentionMarks.js +9 -0
  429. package/lib/module/web/pmPlugins/MentionPlugin/stripPartialMentionMarks.js.map +1 -0
  430. package/lib/module/web/pmPlugins/MentionPlugin/types.js +4 -0
  431. package/lib/module/web/pmPlugins/MentionPlugin/types.js.map +1 -0
  432. package/lib/module/web/pmPlugins/MentionPlugin/useMentionEvents.js +105 -0
  433. package/lib/module/web/pmPlugins/MentionPlugin/useMentionEvents.js.map +1 -0
  434. package/lib/module/web/pmPlugins/MergeAdjacentSameKindBlocksPlugin.js +42 -0
  435. package/lib/module/web/pmPlugins/MergeAdjacentSameKindBlocksPlugin.js.map +1 -0
  436. package/lib/module/web/pmPlugins/ShortcutPlugin.js +134 -0
  437. package/lib/module/web/pmPlugins/ShortcutPlugin.js.map +1 -0
  438. package/lib/module/web/pmPlugins/StrictMarksPlugin.js +100 -0
  439. package/lib/module/web/pmPlugins/StrictMarksPlugin.js.map +1 -0
  440. package/lib/module/web/pmPlugins/StripBoldInStyledHeadingsPlugin.js +56 -0
  441. package/lib/module/web/pmPlugins/StripBoldInStyledHeadingsPlugin.js.map +1 -0
  442. package/lib/module/web/pmPlugins/StripMarksInCodeBlockPlugin.js +28 -0
  443. package/lib/module/web/pmPlugins/StripMarksInCodeBlockPlugin.js.map +1 -0
  444. package/lib/module/web/pmPlugins/StripMarksOnImagePlugin.js +29 -0
  445. package/lib/module/web/pmPlugins/StripMarksOnImagePlugin.js.map +1 -0
  446. package/lib/module/web/positionMapping.js +76 -0
  447. package/lib/module/web/positionMapping.js.map +1 -0
  448. package/lib/module/web/returnKeyTypeToEnterKeyHint.js +20 -0
  449. package/lib/module/web/returnKeyTypeToEnterKeyHint.js.map +1 -0
  450. package/lib/module/web/sanitization/htmlSanitizer.js +10 -0
  451. package/lib/module/web/sanitization/htmlSanitizer.js.map +1 -0
  452. package/lib/module/web/styleConversion/buildMentionRulesCSS.js +39 -0
  453. package/lib/module/web/styleConversion/buildMentionRulesCSS.js.map +1 -0
  454. package/lib/module/web/styleConversion/enrichedBaseStyleToCSSProperties.js +159 -0
  455. package/lib/module/web/styleConversion/enrichedBaseStyleToCSSProperties.js.map +1 -0
  456. package/lib/module/web/styleConversion/enrichedInputStyleToCSSProperties.js +7 -0
  457. package/lib/module/web/styleConversion/enrichedInputStyleToCSSProperties.js.map +1 -0
  458. package/lib/module/web/styleConversion/enrichedTextStyleToCSSProperties.js +44 -0
  459. package/lib/module/web/styleConversion/enrichedTextStyleToCSSProperties.js.map +1 -0
  460. package/lib/module/web/styleConversion/enrichedThemingToCSSProperties.js +18 -0
  461. package/lib/module/web/styleConversion/enrichedThemingToCSSProperties.js.map +1 -0
  462. package/lib/module/web/styleConversion/htmlStyleToCSSVariables.js +168 -0
  463. package/lib/module/web/styleConversion/htmlStyleToCSSVariables.js.map +1 -0
  464. package/lib/module/web/styleConversion/inlineImageCSSVariables.js +7 -0
  465. package/lib/module/web/styleConversion/inlineImageCSSVariables.js.map +1 -0
  466. package/lib/module/web/styleConversion/mentionIndicatorCssKey.js +15 -0
  467. package/lib/module/web/styleConversion/mentionIndicatorCssKey.js.map +1 -0
  468. package/lib/module/web/styleConversion/toColor.js +18 -0
  469. package/lib/module/web/styleConversion/toColor.js.map +1 -0
  470. package/lib/module/web/useImageErrorFallback.js +33 -0
  471. package/lib/module/web/useImageErrorFallback.js.map +1 -0
  472. package/lib/module/web/useOnChangeHtml.js +8 -0
  473. package/lib/module/web/useOnChangeHtml.js.map +1 -0
  474. package/lib/module/web/useOnChangeState.js +91 -0
  475. package/lib/module/web/useOnChangeState.js.map +1 -0
  476. package/lib/module/web/useOnChangeText.js +11 -0
  477. package/lib/module/web/useOnChangeText.js.map +1 -0
  478. package/lib/module/web/useOnEditorChange.js +25 -0
  479. package/lib/module/web/useOnEditorChange.js.map +1 -0
  480. package/lib/module/web/useOnLinkDetected.js +55 -0
  481. package/lib/module/web/useOnLinkDetected.js.map +1 -0
  482. package/lib/module/web/usePressInteractions.js +19 -0
  483. package/lib/module/web/usePressInteractions.js.map +1 -0
  484. package/lib/module/web/useStableRef.js +13 -0
  485. package/lib/module/web/useStableRef.js.map +1 -0
  486. package/lib/typescript/package.json +1 -0
  487. package/lib/typescript/src/index.d.ts +4 -0
  488. package/lib/typescript/src/index.d.ts.map +1 -0
  489. package/lib/typescript/src/index.native.d.ts +5 -0
  490. package/lib/typescript/src/index.native.d.ts.map +1 -0
  491. package/lib/typescript/src/native/EnrichedText.d.ts +3 -0
  492. package/lib/typescript/src/native/EnrichedText.d.ts.map +1 -0
  493. package/lib/typescript/src/native/EnrichedTextInput.d.ts +3 -0
  494. package/lib/typescript/src/native/EnrichedTextInput.d.ts.map +1 -0
  495. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts +405 -0
  496. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
  497. package/lib/typescript/src/spec/EnrichedTextNativeComponent.d.ts +88 -0
  498. package/lib/typescript/src/spec/EnrichedTextNativeComponent.d.ts.map +1 -0
  499. package/lib/typescript/src/types.d.ts +721 -0
  500. package/lib/typescript/src/types.d.ts.map +1 -0
  501. package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts +13 -0
  502. package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts.map +1 -0
  503. package/lib/typescript/src/utils/defaultHtmlStyle.d.ts +4 -0
  504. package/lib/typescript/src/utils/defaultHtmlStyle.d.ts.map +1 -0
  505. package/lib/typescript/src/utils/expandMentionStylesForIndicators.d.ts +3 -0
  506. package/lib/typescript/src/utils/expandMentionStylesForIndicators.d.ts.map +1 -0
  507. package/lib/typescript/src/utils/isMentionStyleRecord.d.ts +3 -0
  508. package/lib/typescript/src/utils/isMentionStyleRecord.d.ts.map +1 -0
  509. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +6 -0
  510. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  511. package/lib/typescript/src/utils/nullthrows.d.ts +2 -0
  512. package/lib/typescript/src/utils/nullthrows.d.ts.map +1 -0
  513. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  514. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  515. package/lib/typescript/src/web/EnrichedText.d.ts +4 -0
  516. package/lib/typescript/src/web/EnrichedText.d.ts.map +1 -0
  517. package/lib/typescript/src/web/EnrichedTextInput.d.ts +4 -0
  518. package/lib/typescript/src/web/EnrichedTextInput.d.ts.map +1 -0
  519. package/lib/typescript/src/web/adaptWebToNativeEvent.d.ts +3 -0
  520. package/lib/typescript/src/web/adaptWebToNativeEvent.d.ts.map +1 -0
  521. package/lib/typescript/src/web/constants/brokenImageGlyph.d.ts +3 -0
  522. package/lib/typescript/src/web/constants/brokenImageGlyph.d.ts.map +1 -0
  523. package/lib/typescript/src/web/constants/classNames.d.ts +3 -0
  524. package/lib/typescript/src/web/constants/classNames.d.ts.map +1 -0
  525. package/lib/typescript/src/web/emitLinkDetected.d.ts +10 -0
  526. package/lib/typescript/src/web/emitLinkDetected.d.ts.map +1 -0
  527. package/lib/typescript/src/web/formats/EnrichedBlockquote.d.ts +2 -0
  528. package/lib/typescript/src/web/formats/EnrichedBlockquote.d.ts.map +1 -0
  529. package/lib/typescript/src/web/formats/EnrichedBold.d.ts +2 -0
  530. package/lib/typescript/src/web/formats/EnrichedBold.d.ts.map +1 -0
  531. package/lib/typescript/src/web/formats/EnrichedCheckboxItem.d.ts +2 -0
  532. package/lib/typescript/src/web/formats/EnrichedCheckboxItem.d.ts.map +1 -0
  533. package/lib/typescript/src/web/formats/EnrichedCheckboxList.d.ts +9 -0
  534. package/lib/typescript/src/web/formats/EnrichedCheckboxList.d.ts.map +1 -0
  535. package/lib/typescript/src/web/formats/EnrichedCode.d.ts +2 -0
  536. package/lib/typescript/src/web/formats/EnrichedCode.d.ts.map +1 -0
  537. package/lib/typescript/src/web/formats/EnrichedCodeBlock.d.ts +9 -0
  538. package/lib/typescript/src/web/formats/EnrichedCodeBlock.d.ts.map +1 -0
  539. package/lib/typescript/src/web/formats/EnrichedHeading.d.ts +5 -0
  540. package/lib/typescript/src/web/formats/EnrichedHeading.d.ts.map +1 -0
  541. package/lib/typescript/src/web/formats/EnrichedImage.d.ts +2 -0
  542. package/lib/typescript/src/web/formats/EnrichedImage.d.ts.map +1 -0
  543. package/lib/typescript/src/web/formats/EnrichedImageNodeView.d.ts +3 -0
  544. package/lib/typescript/src/web/formats/EnrichedImageNodeView.d.ts.map +1 -0
  545. package/lib/typescript/src/web/formats/EnrichedItalic.d.ts +2 -0
  546. package/lib/typescript/src/web/formats/EnrichedItalic.d.ts.map +1 -0
  547. package/lib/typescript/src/web/formats/EnrichedLink.d.ts +8 -0
  548. package/lib/typescript/src/web/formats/EnrichedLink.d.ts.map +1 -0
  549. package/lib/typescript/src/web/formats/EnrichedListItem.d.ts +2 -0
  550. package/lib/typescript/src/web/formats/EnrichedListItem.d.ts.map +1 -0
  551. package/lib/typescript/src/web/formats/EnrichedMention.d.ts +4 -0
  552. package/lib/typescript/src/web/formats/EnrichedMention.d.ts.map +1 -0
  553. package/lib/typescript/src/web/formats/EnrichedOrderedList.d.ts +2 -0
  554. package/lib/typescript/src/web/formats/EnrichedOrderedList.d.ts.map +1 -0
  555. package/lib/typescript/src/web/formats/EnrichedStrike.d.ts +2 -0
  556. package/lib/typescript/src/web/formats/EnrichedStrike.d.ts.map +1 -0
  557. package/lib/typescript/src/web/formats/EnrichedTextAlign.d.ts +2 -0
  558. package/lib/typescript/src/web/formats/EnrichedTextAlign.d.ts.map +1 -0
  559. package/lib/typescript/src/web/formats/EnrichedUnderline.d.ts +2 -0
  560. package/lib/typescript/src/web/formats/EnrichedUnderline.d.ts.map +1 -0
  561. package/lib/typescript/src/web/formats/EnrichedUnorderedList.d.ts +9 -0
  562. package/lib/typescript/src/web/formats/EnrichedUnorderedList.d.ts.map +1 -0
  563. package/lib/typescript/src/web/formats/applyWrappingListToSelection.d.ts +18 -0
  564. package/lib/typescript/src/web/formats/applyWrappingListToSelection.d.ts.map +1 -0
  565. package/lib/typescript/src/web/formats/formatRules.d.ts +12 -0
  566. package/lib/typescript/src/web/formats/formatRules.d.ts.map +1 -0
  567. package/lib/typescript/src/web/formats/listKeyboard.d.ts +4 -0
  568. package/lib/typescript/src/web/formats/listKeyboard.d.ts.map +1 -0
  569. package/lib/typescript/src/web/formats/wrappedBlockKeyboard.d.ts +12 -0
  570. package/lib/typescript/src/web/formats/wrappedBlockKeyboard.d.ts.map +1 -0
  571. package/lib/typescript/src/web/normalization/checkboxHtmlNormalizer.d.ts +3 -0
  572. package/lib/typescript/src/web/normalization/checkboxHtmlNormalizer.d.ts.map +1 -0
  573. package/lib/typescript/src/web/normalization/htmlNormalizer.d.ts +2 -0
  574. package/lib/typescript/src/web/normalization/htmlNormalizer.d.ts.map +1 -0
  575. package/lib/typescript/src/web/normalization/prepareHtmlForWeb.d.ts +2 -0
  576. package/lib/typescript/src/web/normalization/prepareHtmlForWeb.d.ts.map +1 -0
  577. package/lib/typescript/src/web/normalization/tiptapHtmlNormalizer.d.ts +3 -0
  578. package/lib/typescript/src/web/normalization/tiptapHtmlNormalizer.d.ts.map +1 -0
  579. package/lib/typescript/src/web/pasteImages.d.ts +10 -0
  580. package/lib/typescript/src/web/pasteImages.d.ts.map +1 -0
  581. package/lib/typescript/src/web/pastedImageDimensions.d.ts +9 -0
  582. package/lib/typescript/src/web/pastedImageDimensions.d.ts.map +1 -0
  583. package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/autolinkRegex.d.ts +7 -0
  584. package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/autolinkRegex.d.ts.map +1 -0
  585. package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/index.d.ts +8 -0
  586. package/lib/typescript/src/web/pmPlugins/AutolinkPlugin/index.d.ts.map +1 -0
  587. package/lib/typescript/src/web/pmPlugins/MentionPlugin/index.d.ts +9 -0
  588. package/lib/typescript/src/web/pmPlugins/MentionPlugin/index.d.ts.map +1 -0
  589. package/lib/typescript/src/web/pmPlugins/MentionPlugin/isCaretInBlockedContext.d.ts +3 -0
  590. package/lib/typescript/src/web/pmPlugins/MentionPlugin/isCaretInBlockedContext.d.ts.map +1 -0
  591. package/lib/typescript/src/web/pmPlugins/MentionPlugin/makeMentionPluginState.d.ts +4 -0
  592. package/lib/typescript/src/web/pmPlugins/MentionPlugin/makeMentionPluginState.d.ts.map +1 -0
  593. package/lib/typescript/src/web/pmPlugins/MentionPlugin/mentionPluginKey.d.ts +4 -0
  594. package/lib/typescript/src/web/pmPlugins/MentionPlugin/mentionPluginKey.d.ts.map +1 -0
  595. package/lib/typescript/src/web/pmPlugins/MentionPlugin/removeMentionMarksIfSpansResized.d.ts +9 -0
  596. package/lib/typescript/src/web/pmPlugins/MentionPlugin/removeMentionMarksIfSpansResized.d.ts.map +1 -0
  597. package/lib/typescript/src/web/pmPlugins/MentionPlugin/setMention.d.ts +3 -0
  598. package/lib/typescript/src/web/pmPlugins/MentionPlugin/setMention.d.ts.map +1 -0
  599. package/lib/typescript/src/web/pmPlugins/MentionPlugin/startMention.d.ts +3 -0
  600. package/lib/typescript/src/web/pmPlugins/MentionPlugin/startMention.d.ts.map +1 -0
  601. package/lib/typescript/src/web/pmPlugins/MentionPlugin/stripPartialMentionMarks.d.ts +3 -0
  602. package/lib/typescript/src/web/pmPlugins/MentionPlugin/stripPartialMentionMarks.d.ts.map +1 -0
  603. package/lib/typescript/src/web/pmPlugins/MentionPlugin/types.d.ts +20 -0
  604. package/lib/typescript/src/web/pmPlugins/MentionPlugin/types.d.ts.map +1 -0
  605. package/lib/typescript/src/web/pmPlugins/MentionPlugin/useMentionEvents.d.ts +4 -0
  606. package/lib/typescript/src/web/pmPlugins/MentionPlugin/useMentionEvents.d.ts.map +1 -0
  607. package/lib/typescript/src/web/pmPlugins/MergeAdjacentSameKindBlocksPlugin.d.ts +3 -0
  608. package/lib/typescript/src/web/pmPlugins/MergeAdjacentSameKindBlocksPlugin.d.ts.map +1 -0
  609. package/lib/typescript/src/web/pmPlugins/ShortcutPlugin.d.ts +7 -0
  610. package/lib/typescript/src/web/pmPlugins/ShortcutPlugin.d.ts.map +1 -0
  611. package/lib/typescript/src/web/pmPlugins/StrictMarksPlugin.d.ts +3 -0
  612. package/lib/typescript/src/web/pmPlugins/StrictMarksPlugin.d.ts.map +1 -0
  613. package/lib/typescript/src/web/pmPlugins/StripBoldInStyledHeadingsPlugin.d.ts +15 -0
  614. package/lib/typescript/src/web/pmPlugins/StripBoldInStyledHeadingsPlugin.d.ts.map +1 -0
  615. package/lib/typescript/src/web/pmPlugins/StripMarksInCodeBlockPlugin.d.ts +3 -0
  616. package/lib/typescript/src/web/pmPlugins/StripMarksInCodeBlockPlugin.d.ts.map +1 -0
  617. package/lib/typescript/src/web/pmPlugins/StripMarksOnImagePlugin.d.ts +3 -0
  618. package/lib/typescript/src/web/pmPlugins/StripMarksOnImagePlugin.d.ts.map +1 -0
  619. package/lib/typescript/src/web/positionMapping.d.ts +39 -0
  620. package/lib/typescript/src/web/positionMapping.d.ts.map +1 -0
  621. package/lib/typescript/src/web/returnKeyTypeToEnterKeyHint.d.ts +4 -0
  622. package/lib/typescript/src/web/returnKeyTypeToEnterKeyHint.d.ts.map +1 -0
  623. package/lib/typescript/src/web/sanitization/htmlSanitizer.d.ts +2 -0
  624. package/lib/typescript/src/web/sanitization/htmlSanitizer.d.ts.map +1 -0
  625. package/lib/typescript/src/web/styleConversion/buildMentionRulesCSS.d.ts +3 -0
  626. package/lib/typescript/src/web/styleConversion/buildMentionRulesCSS.d.ts.map +1 -0
  627. package/lib/typescript/src/web/styleConversion/enrichedBaseStyleToCSSProperties.d.ts +8 -0
  628. package/lib/typescript/src/web/styleConversion/enrichedBaseStyleToCSSProperties.d.ts.map +1 -0
  629. package/lib/typescript/src/web/styleConversion/enrichedInputStyleToCSSProperties.d.ts +5 -0
  630. package/lib/typescript/src/web/styleConversion/enrichedInputStyleToCSSProperties.d.ts.map +1 -0
  631. package/lib/typescript/src/web/styleConversion/enrichedTextStyleToCSSProperties.d.ts +4 -0
  632. package/lib/typescript/src/web/styleConversion/enrichedTextStyleToCSSProperties.d.ts.map +1 -0
  633. package/lib/typescript/src/web/styleConversion/enrichedThemingToCSSProperties.d.ts +9 -0
  634. package/lib/typescript/src/web/styleConversion/enrichedThemingToCSSProperties.d.ts.map +1 -0
  635. package/lib/typescript/src/web/styleConversion/htmlStyleToCSSVariables.d.ts +11 -0
  636. package/lib/typescript/src/web/styleConversion/htmlStyleToCSSVariables.d.ts.map +1 -0
  637. package/lib/typescript/src/web/styleConversion/inlineImageCSSVariables.d.ts +3 -0
  638. package/lib/typescript/src/web/styleConversion/inlineImageCSSVariables.d.ts.map +1 -0
  639. package/lib/typescript/src/web/styleConversion/mentionIndicatorCssKey.d.ts +3 -0
  640. package/lib/typescript/src/web/styleConversion/mentionIndicatorCssKey.d.ts.map +1 -0
  641. package/lib/typescript/src/web/styleConversion/toColor.d.ts +3 -0
  642. package/lib/typescript/src/web/styleConversion/toColor.d.ts.map +1 -0
  643. package/lib/typescript/src/web/useImageErrorFallback.d.ts +3 -0
  644. package/lib/typescript/src/web/useImageErrorFallback.d.ts.map +1 -0
  645. package/lib/typescript/src/web/useOnChangeHtml.d.ts +5 -0
  646. package/lib/typescript/src/web/useOnChangeHtml.d.ts.map +1 -0
  647. package/lib/typescript/src/web/useOnChangeState.d.ts +6 -0
  648. package/lib/typescript/src/web/useOnChangeState.d.ts.map +1 -0
  649. package/lib/typescript/src/web/useOnChangeText.d.ts +5 -0
  650. package/lib/typescript/src/web/useOnChangeText.d.ts.map +1 -0
  651. package/lib/typescript/src/web/useOnEditorChange.d.ts +6 -0
  652. package/lib/typescript/src/web/useOnEditorChange.d.ts.map +1 -0
  653. package/lib/typescript/src/web/useOnLinkDetected.d.ts +4 -0
  654. package/lib/typescript/src/web/useOnLinkDetected.d.ts.map +1 -0
  655. package/lib/typescript/src/web/usePressInteractions.d.ts +2 -0
  656. package/lib/typescript/src/web/usePressInteractions.d.ts.map +1 -0
  657. package/lib/typescript/src/web/useStableRef.d.ts +3 -0
  658. package/lib/typescript/src/web/useStableRef.d.ts.map +1 -0
  659. package/package.json +258 -1
  660. package/react-native.config.js +16 -0
  661. package/src/index.native.tsx +34 -0
  662. package/src/index.tsx +25 -0
  663. package/src/native/EnrichedText.tsx +115 -0
  664. package/src/native/EnrichedTextInput.tsx +374 -0
  665. package/src/spec/EnrichedTextInputNativeComponent.ts +524 -0
  666. package/src/spec/EnrichedTextNativeComponent.ts +110 -0
  667. package/src/types.ts +866 -0
  668. package/src/utils/EnrichedTextInputDefaultProps.ts +16 -0
  669. package/src/utils/defaultHtmlStyle.ts +83 -0
  670. package/src/utils/expandMentionStylesForIndicators.ts +19 -0
  671. package/src/utils/isMentionStyleRecord.ts +22 -0
  672. package/src/utils/normalizeHtmlStyle.ts +182 -0
  673. package/src/utils/nullthrows.ts +7 -0
  674. package/src/utils/regexParser.ts +56 -0
  675. package/src/web/EnrichedText.css +343 -0
  676. package/src/web/EnrichedText.tsx +82 -0
  677. package/src/web/EnrichedTextInput.tsx +417 -0
  678. package/src/web/adaptWebToNativeEvent.ts +37 -0
  679. package/src/web/constants/brokenImageGlyph.ts +7 -0
  680. package/src/web/constants/classNames.ts +2 -0
  681. package/src/web/emitLinkDetected.ts +29 -0
  682. package/src/web/formats/EnrichedBlockquote.ts +37 -0
  683. package/src/web/formats/EnrichedBold.ts +16 -0
  684. package/src/web/formats/EnrichedCheckboxItem.ts +35 -0
  685. package/src/web/formats/EnrichedCheckboxList.ts +50 -0
  686. package/src/web/formats/EnrichedCode.ts +13 -0
  687. package/src/web/formats/EnrichedCodeBlock.ts +54 -0
  688. package/src/web/formats/EnrichedHeading.ts +37 -0
  689. package/src/web/formats/EnrichedImage.ts +59 -0
  690. package/src/web/formats/EnrichedImageNodeView.tsx +87 -0
  691. package/src/web/formats/EnrichedItalic.ts +16 -0
  692. package/src/web/formats/EnrichedLink.ts +204 -0
  693. package/src/web/formats/EnrichedListItem.ts +17 -0
  694. package/src/web/formats/EnrichedMention.ts +55 -0
  695. package/src/web/formats/EnrichedOrderedList.ts +43 -0
  696. package/src/web/formats/EnrichedStrike.ts +16 -0
  697. package/src/web/formats/EnrichedTextAlign.ts +88 -0
  698. package/src/web/formats/EnrichedUnderline.ts +16 -0
  699. package/src/web/formats/EnrichedUnorderedList.ts +53 -0
  700. package/src/web/formats/applyWrappingListToSelection.ts +76 -0
  701. package/src/web/formats/formatRules.ts +128 -0
  702. package/src/web/formats/listKeyboard.ts +63 -0
  703. package/src/web/formats/wrappedBlockKeyboard.ts +76 -0
  704. package/src/web/normalization/checkboxHtmlNormalizer.ts +62 -0
  705. package/src/web/normalization/htmlNormalizer.ts +656 -0
  706. package/src/web/normalization/prepareHtmlForWeb.ts +93 -0
  707. package/src/web/normalization/tiptapHtmlNormalizer.ts +43 -0
  708. package/src/web/pasteImages.ts +96 -0
  709. package/src/web/pastedImageDimensions.ts +40 -0
  710. package/src/web/pmPlugins/AutolinkPlugin/autolinkRegex.ts +43 -0
  711. package/src/web/pmPlugins/AutolinkPlugin/index.ts +274 -0
  712. package/src/web/pmPlugins/MentionPlugin/index.ts +45 -0
  713. package/src/web/pmPlugins/MentionPlugin/isCaretInBlockedContext.ts +17 -0
  714. package/src/web/pmPlugins/MentionPlugin/makeMentionPluginState.ts +102 -0
  715. package/src/web/pmPlugins/MentionPlugin/mentionPluginKey.ts +4 -0
  716. package/src/web/pmPlugins/MentionPlugin/removeMentionMarksIfSpansResized.ts +68 -0
  717. package/src/web/pmPlugins/MentionPlugin/setMention.ts +73 -0
  718. package/src/web/pmPlugins/MentionPlugin/startMention.ts +14 -0
  719. package/src/web/pmPlugins/MentionPlugin/stripPartialMentionMarks.ts +20 -0
  720. package/src/web/pmPlugins/MentionPlugin/types.ts +22 -0
  721. package/src/web/pmPlugins/MentionPlugin/useMentionEvents.ts +114 -0
  722. package/src/web/pmPlugins/MergeAdjacentSameKindBlocksPlugin.ts +57 -0
  723. package/src/web/pmPlugins/ShortcutPlugin.ts +105 -0
  724. package/src/web/pmPlugins/StrictMarksPlugin.ts +134 -0
  725. package/src/web/pmPlugins/StripBoldInStyledHeadingsPlugin.ts +84 -0
  726. package/src/web/pmPlugins/StripMarksInCodeBlockPlugin.ts +34 -0
  727. package/src/web/pmPlugins/StripMarksOnImagePlugin.ts +33 -0
  728. package/src/web/positionMapping.ts +81 -0
  729. package/src/web/returnKeyTypeToEnterKeyHint.ts +29 -0
  730. package/src/web/sanitization/htmlSanitizer.ts +8 -0
  731. package/src/web/styleConversion/buildMentionRulesCSS.ts +61 -0
  732. package/src/web/styleConversion/enrichedBaseStyleToCSSProperties.ts +228 -0
  733. package/src/web/styleConversion/enrichedInputStyleToCSSProperties.ts +13 -0
  734. package/src/web/styleConversion/enrichedTextStyleToCSSProperties.ts +53 -0
  735. package/src/web/styleConversion/enrichedThemingToCSSProperties.ts +34 -0
  736. package/src/web/styleConversion/htmlStyleToCSSVariables.ts +277 -0
  737. package/src/web/styleConversion/inlineImageCSSVariables.ts +6 -0
  738. package/src/web/styleConversion/mentionIndicatorCssKey.ts +14 -0
  739. package/src/web/styleConversion/toColor.ts +17 -0
  740. package/src/web/useImageErrorFallback.ts +37 -0
  741. package/src/web/useOnChangeHtml.ts +14 -0
  742. package/src/web/useOnChangeState.ts +127 -0
  743. package/src/web/useOnChangeText.ts +15 -0
  744. package/src/web/useOnEditorChange.ts +33 -0
  745. package/src/web/useOnLinkDetected.ts +70 -0
  746. package/src/web/usePressInteractions.tsx +22 -0
  747. package/src/web/useStableRef.ts +12 -0
@@ -0,0 +1,1144 @@
1
+ package com.swmansion.enriched.textinput
2
+
3
+ import android.content.ClipData
4
+ import android.content.ClipboardManager
5
+ import android.content.Context
6
+ import android.graphics.BlendMode
7
+ import android.graphics.BlendModeColorFilter
8
+ import android.graphics.Color
9
+ import android.graphics.Rect
10
+ import android.graphics.text.LineBreaker
11
+ import android.os.Build
12
+ import android.text.Editable
13
+ import android.text.InputType
14
+ import android.text.Spannable
15
+ import android.text.SpannableString
16
+ import android.util.AttributeSet
17
+ import android.util.Log
18
+ import android.util.Patterns
19
+ import android.util.TypedValue
20
+ import android.view.ActionMode
21
+ import android.view.Gravity
22
+ import android.view.KeyEvent
23
+ import android.view.Menu
24
+ import android.view.MenuItem
25
+ import android.view.MotionEvent
26
+ import android.view.inputmethod.EditorInfo
27
+ import android.view.inputmethod.InputConnection
28
+ import android.view.inputmethod.InputMethodManager
29
+ import android.widget.TextView
30
+ import androidx.appcompat.widget.AppCompatEditText
31
+ import androidx.core.view.ViewCompat
32
+ import com.facebook.react.bridge.ReactContext
33
+ import com.facebook.react.bridge.ReadableArray
34
+ import com.facebook.react.bridge.ReadableMap
35
+ import com.facebook.react.common.ReactConstants
36
+ import com.facebook.react.uimanager.StateWrapper
37
+ import com.facebook.react.uimanager.UIManagerHelper
38
+ import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
39
+ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
40
+ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
41
+ import com.swmansion.enriched.common.EnrichedConstants
42
+ import com.swmansion.enriched.common.EnrichedSpanFlags
43
+ import com.swmansion.enriched.common.GumboNormalizer
44
+ import com.swmansion.enriched.common.parser.EnrichedParser
45
+ import com.swmansion.enriched.common.pixelFromSpOrDp
46
+ import com.swmansion.enriched.textinput.events.MentionHandler
47
+ import com.swmansion.enriched.textinput.events.OnContextMenuItemPressEvent
48
+ import com.swmansion.enriched.textinput.events.OnInputBlurEvent
49
+ import com.swmansion.enriched.textinput.events.OnInputFocusEvent
50
+ import com.swmansion.enriched.textinput.events.OnRequestHtmlResultEvent
51
+ import com.swmansion.enriched.textinput.events.OnSubmitEditingEvent
52
+ import com.swmansion.enriched.textinput.spans.EnrichedInputH1Span
53
+ import com.swmansion.enriched.textinput.spans.EnrichedInputH2Span
54
+ import com.swmansion.enriched.textinput.spans.EnrichedInputH3Span
55
+ import com.swmansion.enriched.textinput.spans.EnrichedInputH4Span
56
+ import com.swmansion.enriched.textinput.spans.EnrichedInputH5Span
57
+ import com.swmansion.enriched.textinput.spans.EnrichedInputH6Span
58
+ import com.swmansion.enriched.textinput.spans.EnrichedInputImageSpan
59
+ import com.swmansion.enriched.textinput.spans.EnrichedLineHeightSpan
60
+ import com.swmansion.enriched.textinput.spans.EnrichedSpans
61
+ import com.swmansion.enriched.textinput.spans.interfaces.EnrichedInputSpan
62
+ import com.swmansion.enriched.textinput.styles.AlignmentStyles
63
+ import com.swmansion.enriched.textinput.styles.HtmlStyle
64
+ import com.swmansion.enriched.textinput.styles.InlineStyles
65
+ import com.swmansion.enriched.textinput.styles.ListStyles
66
+ import com.swmansion.enriched.textinput.styles.ParagraphStyles
67
+ import com.swmansion.enriched.textinput.styles.ParametrizedStyles
68
+ import com.swmansion.enriched.textinput.utils.EnrichedEditableFactory
69
+ import com.swmansion.enriched.textinput.utils.EnrichedSelection
70
+ import com.swmansion.enriched.textinput.utils.EnrichedSpanState
71
+ import com.swmansion.enriched.textinput.utils.RichContentReceiver
72
+ import com.swmansion.enriched.textinput.utils.ShortcutsHandler
73
+ import com.swmansion.enriched.textinput.utils.mergeSpannables
74
+ import com.swmansion.enriched.textinput.utils.setCheckboxClickListener
75
+ import com.swmansion.enriched.textinput.utils.zwsCountBefore
76
+ import com.swmansion.enriched.textinput.watchers.EnrichedSpanWatcher
77
+ import com.swmansion.enriched.textinput.watchers.EnrichedTextWatcher
78
+ import java.util.regex.Pattern
79
+ import java.util.regex.PatternSyntaxException
80
+ import kotlin.math.ceil
81
+
82
+ class EnrichedTextInputView :
83
+ AppCompatEditText,
84
+ TextView.OnEditorActionListener {
85
+ var stateWrapper: StateWrapper? = null
86
+ val selection: EnrichedSelection? = EnrichedSelection(this)
87
+ val spanState: EnrichedSpanState? = EnrichedSpanState(this)
88
+ val inlineStyles: InlineStyles? = InlineStyles(this)
89
+ val paragraphStyles: ParagraphStyles? = ParagraphStyles(this)
90
+ val listStyles: ListStyles? = ListStyles(this)
91
+ val shortcutsHandler: ShortcutsHandler? = ShortcutsHandler(this)
92
+ val parametrizedStyles: ParametrizedStyles? = ParametrizedStyles(this)
93
+ val alignmentStyles: AlignmentStyles? = AlignmentStyles(this)
94
+ var isDuringTransaction: Boolean = false
95
+ var isRemovingMany: Boolean = false
96
+ var scrollEnabled: Boolean = true
97
+ var allowFontScaling: Boolean = EnrichedConstants.ALLOW_FONT_SCALING_DEFAULT
98
+ set(value) {
99
+ if (field != value) {
100
+ field = value
101
+ val raw = fontSizeRaw
102
+ if (raw != null) {
103
+ setFontSize(raw) // re-invokes invalidateStyles internally
104
+ } else {
105
+ htmlStyle.invalidateStyles()
106
+ }
107
+ applyLineSpacing()
108
+ reApplyHtmlStyleForSpans(htmlStyle, htmlStyle) // force re-apply
109
+ }
110
+ }
111
+
112
+ val mentionHandler: MentionHandler? = MentionHandler(this)
113
+ var htmlStyle: HtmlStyle = HtmlStyle(this, null)
114
+ set(value) {
115
+ if (field != value) {
116
+ val prev = field
117
+ field = value
118
+ reApplyHtmlStyleForSpans(prev, value)
119
+ }
120
+ }
121
+
122
+ var linkRegex: Pattern? = Patterns.WEB_URL
123
+ var spanWatcher: EnrichedSpanWatcher? = null
124
+ var layoutManager: EnrichedTextInputViewLayoutManager = EnrichedTextInputViewLayoutManager(this)
125
+
126
+ var shouldEmitHtml: Boolean = false
127
+ var shouldEmitOnChangeText: Boolean = false
128
+ var experimentalSynchronousEvents: Boolean = false
129
+ var useHtmlNormalizer: Boolean = false
130
+
131
+ // Pair: (trigger, style)
132
+ var textShortcuts: List<Pair<String, String>> = emptyList()
133
+
134
+ private var fontSizeRaw: Float? = null
135
+ var fontSize: Float? = null
136
+ private var lineHeight: Float? = null
137
+ var submitBehavior: String? = null
138
+ private var autoFocus = false
139
+ private var typefaceDirty = false
140
+ private var didAttachToWindow = false
141
+ private var detectScrollMovement = false
142
+ private var fontFamily: String? = null
143
+ private var fontStyle: Int = ReactConstants.UNSET
144
+ private var fontWeight: Int = ReactConstants.UNSET
145
+ private var defaultValue: CharSequence? = null
146
+ private var defaultValueDirty: Boolean = false
147
+
148
+ private var inputMethodManager: InputMethodManager? = null
149
+ private val spannableFactory = EnrichedTextInputSpannableFactory()
150
+ private var contextMenuItems: List<Pair<Int, String>> = emptyList()
151
+
152
+ constructor(context: Context) : super(context) {
153
+ prepareComponent()
154
+ }
155
+
156
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
157
+ prepareComponent()
158
+ }
159
+
160
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
161
+ context,
162
+ attrs,
163
+ defStyleAttr,
164
+ ) {
165
+ prepareComponent()
166
+ }
167
+
168
+ override fun scrollTo(
169
+ x: Int,
170
+ y: Int,
171
+ ) {
172
+ // Android's internal cursor tracker gets confused by ALIGN_CENTER + LeadingMarginSpan
173
+ // and attempts to scroll the text horizontally.
174
+ // We lock the horizontal scroll to 0 to prevent the view from shifting.
175
+ super.scrollTo(0, y)
176
+ }
177
+
178
+ override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
179
+ var inputConnection = super.onCreateInputConnection(outAttrs)
180
+
181
+ if (shouldSubmitOnReturn()) {
182
+ // Remove the "No Enter Action" flag if it exists
183
+ outAttrs.imeOptions = outAttrs.imeOptions and EditorInfo.IME_FLAG_NO_ENTER_ACTION.inv()
184
+
185
+ // Force the key to be "Done" (or whatever label you set) instead of "Return"
186
+ // This ensures onEditorAction gets called instead of just inserting \n
187
+ if (outAttrs.imeOptions and EditorInfo.IME_MASK_ACTION == EditorInfo.IME_ACTION_UNSPECIFIED) {
188
+ outAttrs.imeOptions = outAttrs.imeOptions or EditorInfo.IME_ACTION_DONE
189
+ }
190
+ }
191
+
192
+ if (inputConnection != null) {
193
+ inputConnection =
194
+ EnrichedTextInputConnectionWrapper(
195
+ inputConnection,
196
+ context as ReactContext,
197
+ this,
198
+ experimentalSynchronousEvents,
199
+ )
200
+ }
201
+
202
+ return inputConnection
203
+ }
204
+
205
+ init {
206
+ inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
207
+ ViewCompat.setOnReceiveContentListener(
208
+ this,
209
+ RichContentReceiver.MIME_TYPES,
210
+ RichContentReceiver(this, context as ReactContext),
211
+ )
212
+ }
213
+
214
+ private fun prepareComponent() {
215
+ isSingleLine = false
216
+ isHorizontalScrollBarEnabled = false
217
+ isVerticalScrollBarEnabled = true
218
+ gravity = Gravity.TOP or Gravity.START
219
+ inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE
220
+
221
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
222
+ breakStrategy = LineBreaker.BREAK_STRATEGY_HIGH_QUALITY
223
+ }
224
+
225
+ setPadding(0, 0, 0, 0)
226
+ setBackgroundColor(Color.TRANSPARENT)
227
+
228
+ // Ensure that every time new editable is created, it has EnrichedSpanWatcher attached
229
+ val spanWatcher = EnrichedSpanWatcher(this)
230
+ this.spanWatcher = spanWatcher
231
+
232
+ setEditableFactory(EnrichedEditableFactory(spanWatcher))
233
+ addTextChangedListener(EnrichedTextWatcher(this))
234
+
235
+ // Handle checkbox list item clicks
236
+ this.setCheckboxClickListener()
237
+
238
+ setOnEditorActionListener(this)
239
+ setReturnKeyLabel(DEFAULT_IME_ACTION_LABEL)
240
+ }
241
+
242
+ // Similar implementation to: https://github.com/facebook/react-native/blob/c1f5445f4a59d0035389725e47da58eb3d2c267c/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt#L940
243
+ override fun onEditorAction(
244
+ v: TextView?,
245
+ actionId: Int,
246
+ event: KeyEvent?,
247
+ ): Boolean {
248
+ // Check if it's a valid keyboard action (Done, Next, etc.) or the Enter key (IME_NULL)
249
+ val isAction = (actionId and EditorInfo.IME_MASK_ACTION) != 0 || actionId == EditorInfo.IME_NULL
250
+
251
+ if (isAction) {
252
+ val shouldSubmit = shouldSubmitOnReturn()
253
+ val shouldBlur = shouldBlurOnReturn()
254
+
255
+ if (shouldSubmit) {
256
+ emitSubmitEditing()
257
+ }
258
+
259
+ if (shouldBlur) {
260
+ clearFocus()
261
+ }
262
+
263
+ if (shouldSubmit || shouldBlur) {
264
+ return true
265
+ }
266
+ }
267
+
268
+ // Return false to let the system handle default behavior (like inserting \n)
269
+ return false
270
+ }
271
+
272
+ private fun emitSubmitEditing() {
273
+ val context = context as ReactContext
274
+ val surfaceId = UIManagerHelper.getSurfaceId(context)
275
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, id)
276
+ dispatcher?.dispatchEvent(
277
+ OnSubmitEditingEvent(
278
+ surfaceId,
279
+ id,
280
+ text,
281
+ experimentalSynchronousEvents,
282
+ ),
283
+ )
284
+ }
285
+
286
+ // https://github.com/facebook/react-native/blob/36df97f500aa0aa8031098caf7526db358b6ddc1/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt#L295C1-L296C1
287
+ override fun onTouchEvent(ev: MotionEvent): Boolean {
288
+ when (ev.action) {
289
+ MotionEvent.ACTION_DOWN -> {
290
+ detectScrollMovement = true
291
+ // Disallow parent views to intercept touch events, until we can detect if we should be
292
+ // capturing these touches or not.
293
+ this.parent.requestDisallowInterceptTouchEvent(true)
294
+ }
295
+
296
+ MotionEvent.ACTION_MOVE -> {
297
+ if (detectScrollMovement) {
298
+ if (!canScrollVertically(-1) &&
299
+ !canScrollVertically(1) &&
300
+ !canScrollHorizontally(-1) &&
301
+ !canScrollHorizontally(1)
302
+ ) {
303
+ // We cannot scroll, let parent views take care of these touches.
304
+ this.parent.requestDisallowInterceptTouchEvent(false)
305
+ }
306
+ detectScrollMovement = false
307
+ }
308
+ }
309
+ }
310
+
311
+ return super.onTouchEvent(ev)
312
+ }
313
+
314
+ override fun canScrollVertically(direction: Int): Boolean = scrollEnabled
315
+
316
+ override fun canScrollHorizontally(direction: Int): Boolean = scrollEnabled
317
+
318
+ override fun onSelectionChanged(
319
+ selStart: Int,
320
+ selEnd: Int,
321
+ ) {
322
+ super.onSelectionChanged(selStart, selEnd)
323
+ selection?.onSelection(selStart, selEnd)
324
+ }
325
+
326
+ override fun clearFocus() {
327
+ super.clearFocus()
328
+ inputMethodManager?.hideSoftInputFromWindow(windowToken, 0)
329
+ }
330
+
331
+ override fun onFocusChanged(
332
+ focused: Boolean,
333
+ direction: Int,
334
+ previouslyFocusedRect: Rect?,
335
+ ) {
336
+ super.onFocusChanged(focused, direction, previouslyFocusedRect)
337
+ val context = context as ReactContext
338
+ val surfaceId = UIManagerHelper.getSurfaceId(context)
339
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, id)
340
+
341
+ if (focused) {
342
+ dispatcher?.dispatchEvent(OnInputFocusEvent(surfaceId, id, experimentalSynchronousEvents))
343
+ } else {
344
+ dispatcher?.dispatchEvent(OnInputBlurEvent(surfaceId, id, experimentalSynchronousEvents))
345
+ }
346
+ }
347
+
348
+ override fun onTextContextMenuItem(id: Int): Boolean {
349
+ when (id) {
350
+ android.R.id.copy -> {
351
+ handleCustomCopy()
352
+ return true
353
+ }
354
+ }
355
+ return super.onTextContextMenuItem(id)
356
+ }
357
+
358
+ private fun handleCustomCopy() {
359
+ val start = selectionStart
360
+ val end = selectionEnd
361
+ val spannable = text as Spannable
362
+
363
+ if (start < end) {
364
+ val selectedText = spannable.subSequence(start, end) as Spannable
365
+ val selectedHtml = EnrichedParser.toHtml(selectedText)
366
+
367
+ val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
368
+ val clip = ClipData.newHtmlText(EnrichedConstants.CLIPBOARD_TAG, selectedText, selectedHtml)
369
+ clipboard.setPrimaryClip(clip)
370
+ }
371
+ }
372
+
373
+ fun handleTextPaste(item: ClipData.Item) {
374
+ val currentText = text as Spannable
375
+ val start = selectionStart.coerceAtLeast(0)
376
+ val end = selectionEnd.coerceAtLeast(0)
377
+ val lengthBefore = currentText.length
378
+
379
+ val pastedSpannable: Spannable =
380
+ when {
381
+ item.htmlText != null -> {
382
+ val parsed = parseText(item.htmlText)
383
+ (parsed as? Spannable) ?: return
384
+ }
385
+
386
+ item.text != null -> {
387
+ SpannableString(item.text.toString())
388
+ }
389
+
390
+ else -> {
391
+ return
392
+ }
393
+ }
394
+
395
+ val finalText = currentText.mergeSpannables(start, end, pastedSpannable, htmlStyle)
396
+ setValue(finalText, false)
397
+
398
+ // replacement-safe: oldLength - removed + inserted
399
+ val insertedLength = finalText.length - (lengthBefore - (end - start))
400
+ val pasteEnd = (start + insertedLength).coerceIn(0, finalText.length)
401
+ setSelection(pasteEnd)
402
+
403
+ // Update links and mentions in the newly pasted range
404
+ val editable = text as? Editable ?: return
405
+ parametrizedStyles?.afterTextChanged(editable, start.coerceAtMost(pasteEnd), pasteEnd)
406
+ }
407
+
408
+ fun requestFocusProgrammatically() {
409
+ requestFocus()
410
+ inputMethodManager?.showSoftInput(this, 0)
411
+ setSelection(selection?.start ?: text?.length ?: 0)
412
+ }
413
+
414
+ private fun normalizeHtmlIfNeeded(text: CharSequence): CharSequence {
415
+ if (!useHtmlNormalizer) return text
416
+ val normalized = GumboNormalizer.normalizeHtml(text.toString()) ?: return text
417
+
418
+ return try {
419
+ val parsed = EnrichedParser.fromHtml(normalized, htmlStyle, spannableFactory, linkRegex)
420
+ parsed.trimEnd('\n')
421
+ } catch (e: Exception) {
422
+ Log.e(TAG, "Error parsing normalized HTML: ${e.message}")
423
+ text
424
+ }
425
+ }
426
+
427
+ private fun parseText(text: CharSequence): CharSequence {
428
+ val isInternalHtml = text.startsWith("<html>") && text.endsWith("</html>")
429
+
430
+ if (isInternalHtml) {
431
+ try {
432
+ val parsed = EnrichedParser.fromHtml(text.toString(), htmlStyle, spannableFactory, linkRegex)
433
+ return parsed.trimEnd('\n')
434
+ } catch (e: Exception) {
435
+ Log.e(TAG, "Error parsing HTML: ${e.message}")
436
+ return normalizeHtmlIfNeeded(text)
437
+ }
438
+ }
439
+
440
+ return normalizeHtmlIfNeeded(text)
441
+ }
442
+
443
+ fun setValue(
444
+ value: CharSequence?,
445
+ shouldParseHtml: Boolean = true,
446
+ ) {
447
+ if (value == null) return
448
+
449
+ runAsATransaction {
450
+ val newText = if (shouldParseHtml) parseText(value) else value
451
+ setText(newText)
452
+ applyLineSpacing()
453
+
454
+ observeAsyncImages()
455
+
456
+ // Scroll to the last line of text
457
+ setSelection(text?.length ?: 0)
458
+ }
459
+ layoutManager.invalidateLayout()
460
+ }
461
+
462
+ fun setCustomSelection(
463
+ visibleStart: Int,
464
+ visibleEnd: Int,
465
+ ) {
466
+ val actualStart = getActualIndex(visibleStart)
467
+ val actualEnd = getActualIndex(visibleEnd)
468
+
469
+ setSelection(actualStart, actualEnd)
470
+ }
471
+
472
+ // Helper: Walks through the string skipping ZWSPs to find the Nth visible character
473
+ private fun getActualIndex(visibleIndex: Int): Int {
474
+ val currentText = text as Spannable
475
+ var currentVisibleCount = 0
476
+ var actualIndex = 0
477
+
478
+ while (actualIndex < currentText.length) {
479
+ if (currentVisibleCount == visibleIndex) {
480
+ return actualIndex
481
+ }
482
+
483
+ // If the current char is not a hidden space, it counts towards our visible index
484
+ if (currentText[actualIndex] != EnrichedConstants.ZWS) {
485
+ currentVisibleCount++
486
+ }
487
+ actualIndex++
488
+ }
489
+
490
+ return actualIndex
491
+ }
492
+
493
+ /**
494
+ * Finds all async images in the current text and sets up listeners
495
+ * to redraw the text layout when they finish downloading.
496
+ */
497
+ private fun observeAsyncImages() {
498
+ val liveText = text ?: return
499
+
500
+ val spans = liveText.getSpans(0, liveText.length, EnrichedInputImageSpan::class.java)
501
+
502
+ for (span in spans) {
503
+ span.observeAsyncDrawableLoaded(liveText)
504
+ }
505
+ }
506
+
507
+ fun setAutoFocus(autoFocus: Boolean) {
508
+ this.autoFocus = autoFocus
509
+ }
510
+
511
+ fun setPlaceholder(placeholder: String?) {
512
+ if (placeholder == null) return
513
+
514
+ hint = placeholder
515
+ }
516
+
517
+ fun setPlaceholderTextColor(colorInt: Int?) {
518
+ if (colorInt == null) return
519
+
520
+ setHintTextColor(colorInt)
521
+ }
522
+
523
+ fun setSelectionColor(colorInt: Int?) {
524
+ if (colorInt == null) return
525
+
526
+ highlightColor = colorInt
527
+ }
528
+
529
+ fun setCursorColor(colorInt: Int?) {
530
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
531
+ val cursorDrawable = textCursorDrawable ?: return
532
+
533
+ if (colorInt != null) {
534
+ cursorDrawable.colorFilter = BlendModeColorFilter(colorInt, BlendMode.SRC_IN)
535
+ } else {
536
+ cursorDrawable.clearColorFilter()
537
+ }
538
+
539
+ textCursorDrawable = cursorDrawable
540
+ }
541
+ }
542
+
543
+ fun setReturnKeyLabel(returnKeyLabel: String?) {
544
+ setImeActionLabel(returnKeyLabel, EditorInfo.IME_ACTION_UNSPECIFIED)
545
+ }
546
+
547
+ fun setColor(colorInt: Int?) {
548
+ if (colorInt == null) {
549
+ setTextColor(Color.BLACK)
550
+ return
551
+ }
552
+
553
+ setTextColor(colorInt)
554
+ }
555
+
556
+ fun setFontSize(size: Float) {
557
+ if (size == 0f) return
558
+ fontSizeRaw = size
559
+
560
+ val sizeInt = ceil(pixelFromSpOrDp(size, allowFontScaling))
561
+ fontSize = sizeInt
562
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, sizeInt)
563
+
564
+ // This ensured that newly created spans will take the new font size into account
565
+ htmlStyle.invalidateStyles()
566
+ layoutManager.invalidateLayout()
567
+ forceScrollToSelection()
568
+ }
569
+
570
+ fun setLineHeight(height: Float) {
571
+ lineHeight = if (height == 0f) null else height
572
+ applyLineSpacing()
573
+ layoutManager.invalidateLayout()
574
+ forceScrollToSelection()
575
+ }
576
+
577
+ private fun applyLineSpacing() {
578
+ val spannable = text as? Spannable ?: return
579
+ spannable
580
+ .getSpans(0, spannable.length, EnrichedLineHeightSpan::class.java)
581
+ .forEach { spannable.removeSpan(it) }
582
+
583
+ val lh = lineHeight ?: return
584
+ spannable.setSpan(
585
+ EnrichedLineHeightSpan(lh, allowFontScaling),
586
+ 0,
587
+ spannable.length,
588
+ Spannable.SPAN_INCLUSIVE_INCLUSIVE,
589
+ )
590
+ }
591
+
592
+ fun setFontFamily(family: String?) {
593
+ if (family != fontFamily) {
594
+ fontFamily = family
595
+ typefaceDirty = true
596
+ }
597
+ }
598
+
599
+ fun setFontWeight(weight: String?) {
600
+ val fontWeight = parseFontWeight(weight)
601
+
602
+ if (fontWeight != fontStyle) {
603
+ this.fontWeight = fontWeight
604
+ typefaceDirty = true
605
+ }
606
+ }
607
+
608
+ fun setFontStyle(style: String?) {
609
+ val fontStyle = parseFontStyle(style)
610
+
611
+ if (fontStyle != this.fontStyle) {
612
+ this.fontStyle = fontStyle
613
+ typefaceDirty = true
614
+ }
615
+ }
616
+
617
+ fun setAutoCapitalize(flagName: String?) {
618
+ val flag =
619
+ when (flagName) {
620
+ "none" -> InputType.TYPE_NULL
621
+ "sentences" -> InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
622
+ "words" -> InputType.TYPE_TEXT_FLAG_CAP_WORDS
623
+ "characters" -> InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
624
+ else -> InputType.TYPE_NULL
625
+ }
626
+
627
+ inputType = (
628
+ inputType and
629
+ InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS.inv() and
630
+ InputType.TYPE_TEXT_FLAG_CAP_WORDS.inv() and
631
+ InputType.TYPE_TEXT_FLAG_CAP_SENTENCES.inv()
632
+ ) or if (flag == InputType.TYPE_NULL) 0 else flag
633
+ }
634
+
635
+ fun setLinkRegex(config: ReadableMap?) {
636
+ val patternStr = config?.getString("pattern")
637
+ if (patternStr == null) {
638
+ linkRegex = Patterns.WEB_URL
639
+ return
640
+ }
641
+
642
+ if (config.getBoolean("isDefault")) {
643
+ linkRegex = Patterns.WEB_URL
644
+ return
645
+ }
646
+
647
+ if (config.getBoolean("isDisabled")) {
648
+ linkRegex = null
649
+ return
650
+ }
651
+
652
+ var flags = 0
653
+ if (config.getBoolean("caseInsensitive")) flags = flags or Pattern.CASE_INSENSITIVE
654
+ if (config.getBoolean("dotAll")) flags = flags or Pattern.DOTALL
655
+
656
+ try {
657
+ linkRegex = Pattern.compile("(?s).*?($patternStr).*", flags)
658
+ } catch (_: PatternSyntaxException) {
659
+ Log.w(TAG, "Invalid link regex pattern: $patternStr")
660
+ linkRegex = Patterns.WEB_URL
661
+ }
662
+ }
663
+
664
+ fun setContextMenuItems(items: ReadableArray?) {
665
+ if (items == null) {
666
+ contextMenuItems = emptyList()
667
+ return
668
+ }
669
+
670
+ val result = mutableListOf<Pair<Int, String>>()
671
+ for (i in 0 until items.size()) {
672
+ val item = items.getMap(i) ?: continue
673
+ val text = item.getString("text") ?: continue
674
+ result.add(Pair(i, text))
675
+ }
676
+
677
+ contextMenuItems = result
678
+ }
679
+
680
+ override fun startActionMode(
681
+ callback: ActionMode.Callback?,
682
+ type: Int,
683
+ ): ActionMode? {
684
+ if (contextMenuItems.isEmpty()) {
685
+ return super.startActionMode(callback, type)
686
+ }
687
+
688
+ val wrappedCallback =
689
+ object : ActionMode.Callback2() {
690
+ override fun onCreateActionMode(
691
+ mode: ActionMode,
692
+ menu: Menu,
693
+ ): Boolean {
694
+ val result = callback?.onCreateActionMode(mode, menu) ?: false
695
+ for ((index, text) in contextMenuItems) {
696
+ menu.add(Menu.NONE, CONTEXT_MENU_ITEM_ID + index, Menu.NONE, text)
697
+ }
698
+
699
+ return result
700
+ }
701
+
702
+ override fun onPrepareActionMode(
703
+ mode: ActionMode,
704
+ menu: Menu,
705
+ ) = callback?.onPrepareActionMode(mode, menu) ?: false
706
+
707
+ override fun onActionItemClicked(
708
+ mode: ActionMode,
709
+ menuItem: MenuItem,
710
+ ): Boolean {
711
+ val itemId = menuItem.itemId
712
+ if (itemId < CONTEXT_MENU_ITEM_ID) {
713
+ return callback?.onActionItemClicked(mode, menuItem) ?: false
714
+ }
715
+
716
+ val selStart = selection?.start ?: 0
717
+ val selEnd = selection?.end ?: 0
718
+ val itemText = contextMenuItems.getOrNull(itemId - CONTEXT_MENU_ITEM_ID)?.second ?: return false
719
+ emitContextMenuItemPressEvent(itemText)
720
+ mode.finish()
721
+ post {
722
+ // Ensures selection is not lost after the action mode is finished
723
+ if (selStart in 0..selEnd) {
724
+ setSelection(selStart, selEnd)
725
+ }
726
+ }
727
+ return true
728
+ }
729
+
730
+ override fun onDestroyActionMode(mode: ActionMode) {
731
+ callback?.onDestroyActionMode(mode)
732
+ }
733
+ }
734
+
735
+ return super.startActionMode(wrappedCallback, type)
736
+ }
737
+
738
+ private fun emitContextMenuItemPressEvent(itemText: String) {
739
+ val start = selection?.start ?: return
740
+ val end = selection.end
741
+ val styleState = spanState?.getStyleStatePayload() ?: return
742
+ val currentText = text ?: return
743
+ val selectedText = currentText.subSequence(start, end).toString().replace(EnrichedConstants.ZWS_STRING, "")
744
+
745
+ val visibleStart = start - currentText.zwsCountBefore(start)
746
+ val visibleEnd = end - currentText.zwsCountBefore(end)
747
+
748
+ val reactContext = context as ReactContext
749
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
750
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
751
+ dispatcher?.dispatchEvent(
752
+ OnContextMenuItemPressEvent(
753
+ surfaceId,
754
+ id,
755
+ itemText,
756
+ selectedText,
757
+ visibleStart,
758
+ visibleEnd,
759
+ styleState,
760
+ experimentalSynchronousEvents,
761
+ ),
762
+ )
763
+ }
764
+
765
+ // https://github.com/facebook/react-native/blob/36df97f500aa0aa8031098caf7526db358b6ddc1/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt#L283C2-L284C1
766
+ // After the text changes inside an EditText, TextView checks if a layout() has been requested.
767
+ // If it has, it will not scroll the text to the end of the new text inserted, but wait for the
768
+ // next layout() to be called. However, we do not perform a layout() after a requestLayout(), so
769
+ // we need to override isLayoutRequested to force EditText to scroll to the end of the new text
770
+ // immediately.
771
+ override fun isLayoutRequested(): Boolean = false
772
+
773
+ fun afterUpdateTransaction() {
774
+ updateTypeface()
775
+ updateDefaultValue()
776
+ }
777
+
778
+ fun setDefaultValue(value: CharSequence?) {
779
+ defaultValue = value
780
+ defaultValueDirty = true
781
+ }
782
+
783
+ fun shouldBlurOnReturn(): Boolean = submitBehavior == "blurAndSubmit"
784
+
785
+ fun shouldSubmitOnReturn(): Boolean = submitBehavior == "submit" || submitBehavior == "blurAndSubmit"
786
+
787
+ private fun updateDefaultValue() {
788
+ if (!defaultValueDirty) return
789
+
790
+ defaultValueDirty = false
791
+ setValue(defaultValue ?: "")
792
+ }
793
+
794
+ private fun updateTypeface() {
795
+ if (!typefaceDirty) return
796
+ typefaceDirty = false
797
+
798
+ val newTypeface = applyStyles(typeface, fontStyle, fontWeight, fontFamily, context.assets)
799
+ typeface = newTypeface
800
+ paint.typeface = newTypeface
801
+
802
+ layoutManager.invalidateLayout()
803
+ }
804
+
805
+ internal fun toggleStyle(name: String) {
806
+ when (name) {
807
+ EnrichedSpans.BOLD -> inlineStyles?.toggleStyle(EnrichedSpans.BOLD)
808
+ EnrichedSpans.ITALIC -> inlineStyles?.toggleStyle(EnrichedSpans.ITALIC)
809
+ EnrichedSpans.UNDERLINE -> inlineStyles?.toggleStyle(EnrichedSpans.UNDERLINE)
810
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.toggleStyle(EnrichedSpans.STRIKETHROUGH)
811
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.toggleStyle(EnrichedSpans.INLINE_CODE)
812
+ EnrichedSpans.H1 -> paragraphStyles?.toggleStyle(EnrichedSpans.H1)
813
+ EnrichedSpans.H2 -> paragraphStyles?.toggleStyle(EnrichedSpans.H2)
814
+ EnrichedSpans.H3 -> paragraphStyles?.toggleStyle(EnrichedSpans.H3)
815
+ EnrichedSpans.H4 -> paragraphStyles?.toggleStyle(EnrichedSpans.H4)
816
+ EnrichedSpans.H5 -> paragraphStyles?.toggleStyle(EnrichedSpans.H5)
817
+ EnrichedSpans.H6 -> paragraphStyles?.toggleStyle(EnrichedSpans.H6)
818
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.toggleStyle(EnrichedSpans.CODE_BLOCK)
819
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.toggleStyle(EnrichedSpans.BLOCK_QUOTE)
820
+ EnrichedSpans.ORDERED_LIST -> listStyles?.toggleStyle(EnrichedSpans.ORDERED_LIST)
821
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.toggleStyle(EnrichedSpans.UNORDERED_LIST)
822
+ EnrichedSpans.CHECKBOX_LIST -> listStyles?.toggleStyle(EnrichedSpans.CHECKBOX_LIST)
823
+ else -> Log.w(TAG, "Unknown style: $name")
824
+ }
825
+
826
+ layoutManager.invalidateLayout()
827
+ }
828
+
829
+ private fun removeStyle(
830
+ name: String,
831
+ start: Int,
832
+ end: Int,
833
+ ): Boolean {
834
+ val removed =
835
+ when (name) {
836
+ EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
837
+ EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
838
+ EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
839
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
840
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
841
+ EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
842
+ EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
843
+ EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
844
+ EnrichedSpans.H4 -> paragraphStyles?.removeStyle(EnrichedSpans.H4, start, end)
845
+ EnrichedSpans.H5 -> paragraphStyles?.removeStyle(EnrichedSpans.H5, start, end)
846
+ EnrichedSpans.H6 -> paragraphStyles?.removeStyle(EnrichedSpans.H6, start, end)
847
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
848
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
849
+ EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
850
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
851
+ EnrichedSpans.CHECKBOX_LIST -> listStyles?.removeStyle(EnrichedSpans.CHECKBOX_LIST, start, end)
852
+ EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
853
+ EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
854
+ EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
855
+ else -> false
856
+ }
857
+
858
+ return removed == true
859
+ }
860
+
861
+ private fun getTargetRange(name: String): Pair<Int, Int> {
862
+ val result =
863
+ when (name) {
864
+ EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
865
+ EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
866
+ EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
867
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
868
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
869
+ EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
870
+ EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
871
+ EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
872
+ EnrichedSpans.H4 -> paragraphStyles?.getStyleRange()
873
+ EnrichedSpans.H5 -> paragraphStyles?.getStyleRange()
874
+ EnrichedSpans.H6 -> paragraphStyles?.getStyleRange()
875
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
876
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
877
+ EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
878
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
879
+ EnrichedSpans.CHECKBOX_LIST -> listStyles?.getStyleRange()
880
+ EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
881
+ EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
882
+ EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
883
+ else -> Pair(0, 0)
884
+ }
885
+
886
+ return result ?: Pair(0, 0)
887
+ }
888
+
889
+ private fun verifyStyle(name: String): Boolean {
890
+ val mergingConfig = EnrichedSpans.getMergingConfigForStyle(name, htmlStyle) ?: return true
891
+ val conflictingStyles = mergingConfig.conflictingStyles
892
+ val blockingStyles = mergingConfig.blockingStyles
893
+ val isEnabling = spanState?.getStart(name) == null
894
+ if (!isEnabling) return true
895
+
896
+ for (style in blockingStyles) {
897
+ if (spanState?.getStart(style) != null) {
898
+ spanState.setStart(name, null)
899
+ return false
900
+ }
901
+ }
902
+
903
+ for (style in conflictingStyles) {
904
+ val start = selection?.start ?: 0
905
+ val end = selection?.end ?: 0
906
+ val lengthBefore = text?.length ?: 0
907
+
908
+ runAsATransaction {
909
+ val targetRange = getTargetRange(name)
910
+ val removed = removeStyle(style, targetRange.first, targetRange.second)
911
+ if (removed) {
912
+ spanState?.setStart(style, null)
913
+ }
914
+ }
915
+
916
+ val lengthAfter = text?.length ?: 0
917
+ val charactersRemoved = lengthBefore - lengthAfter
918
+ val finalEnd =
919
+ if (charactersRemoved > 0) {
920
+ (end - charactersRemoved).coerceAtLeast(0)
921
+ } else {
922
+ end
923
+ }
924
+
925
+ val finalStart = start.coerceAtLeast(0).coerceAtMost(finalEnd)
926
+ selection?.onSelection(finalStart, finalEnd)
927
+ }
928
+
929
+ return true
930
+ }
931
+
932
+ fun verifyAndToggleStyle(name: String) {
933
+ val isValid = verifyStyle(name)
934
+ if (!isValid) return
935
+
936
+ val (rangeStart, rangeEnd) = getTargetRange(name)
937
+
938
+ runAsATransaction {
939
+ toggleStyle(name)
940
+ }
941
+
942
+ parametrizedStyles?.onStyleToggled(name, rangeStart, rangeEnd)
943
+ }
944
+
945
+ fun toggleCheckboxListItem(checked: Boolean) {
946
+ val isValid = verifyStyle(EnrichedSpans.CHECKBOX_LIST)
947
+ if (!isValid) return
948
+
949
+ listStyles?.toggleCheckboxListStyle(checked)
950
+ }
951
+
952
+ fun addLink(
953
+ start: Int,
954
+ end: Int,
955
+ text: String,
956
+ url: String,
957
+ ) {
958
+ val isValid = verifyStyle(EnrichedSpans.LINK)
959
+ if (!isValid) return
960
+
961
+ parametrizedStyles?.setLinkSpan(getActualIndex(start), getActualIndex(end), text, url)
962
+ }
963
+
964
+ fun removeLink(
965
+ start: Int,
966
+ end: Int,
967
+ ) {
968
+ parametrizedStyles?.removeLinkSpans(getActualIndex(start), getActualIndex(end))
969
+ }
970
+
971
+ fun addImage(
972
+ src: String,
973
+ width: Float,
974
+ height: Float,
975
+ ) {
976
+ val isValid = verifyStyle(EnrichedSpans.IMAGE)
977
+ if (!isValid) return
978
+
979
+ parametrizedStyles?.setImageSpan(src, width, height)
980
+ layoutManager.invalidateLayout()
981
+ }
982
+
983
+ fun startMention(indicator: String) {
984
+ val isValid = verifyStyle(EnrichedSpans.MENTION)
985
+ if (!isValid) return
986
+
987
+ parametrizedStyles?.startMention(indicator)
988
+ }
989
+
990
+ fun addMention(
991
+ indicator: String,
992
+ text: String,
993
+ attributes: Map<String, String>,
994
+ ) {
995
+ val isValid = verifyStyle(EnrichedSpans.MENTION)
996
+ if (!isValid) return
997
+
998
+ parametrizedStyles?.setMentionSpan(text, indicator, attributes)
999
+ }
1000
+
1001
+ fun setTextAlignment(alignment: String) {
1002
+ runAsATransaction {
1003
+ alignmentStyles?.setAlignment(alignment)
1004
+ }
1005
+ selection?.validateStyles()
1006
+ }
1007
+
1008
+ fun requestHTML(requestId: Int) {
1009
+ val html =
1010
+ try {
1011
+ EnrichedParser.toHtmlWithDefault(text)
1012
+ } catch (_: Exception) {
1013
+ null
1014
+ }
1015
+
1016
+ val reactContext = context as ReactContext
1017
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
1018
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
1019
+ dispatcher?.dispatchEvent(OnRequestHtmlResultEvent(surfaceId, id, requestId, html, experimentalSynchronousEvents))
1020
+ }
1021
+
1022
+ // Sometimes setting up style triggers many changes in sequence
1023
+ // Eg. removing conflicting styles -> changing text -> applying spans
1024
+ // In such scenario we want to prevent from handling side effects (eg. onTextChanged)
1025
+ fun runAsATransaction(block: () -> Unit) {
1026
+ try {
1027
+ isDuringTransaction = true
1028
+ block()
1029
+ } finally {
1030
+ isDuringTransaction = false
1031
+ }
1032
+ }
1033
+
1034
+ private fun forceScrollToSelection() {
1035
+ val textLayout = layout ?: return
1036
+ val cursorOffset = selectionStart
1037
+ if (cursorOffset <= 0) return
1038
+
1039
+ val selectedLineIndex = textLayout.getLineForOffset(cursorOffset)
1040
+ val selectedLineTop = textLayout.getLineTop(selectedLineIndex)
1041
+ val selectedLineBottom = textLayout.getLineBottom(selectedLineIndex)
1042
+ val visibleTextHeight = height - paddingTop - paddingBottom
1043
+
1044
+ if (visibleTextHeight <= 0) return
1045
+
1046
+ val visibleTop = scrollY
1047
+ val visibleBottom = scrollY + visibleTextHeight
1048
+ var targetScrollY = scrollY
1049
+
1050
+ if (selectedLineTop < visibleTop) {
1051
+ targetScrollY = selectedLineTop
1052
+ } else if (selectedLineBottom > visibleBottom) {
1053
+ targetScrollY = selectedLineBottom - visibleTextHeight
1054
+ }
1055
+
1056
+ val maxScrollY = (textLayout.height - visibleTextHeight).coerceAtLeast(0)
1057
+ targetScrollY = targetScrollY.coerceIn(0, maxScrollY)
1058
+ scrollTo(scrollX, targetScrollY)
1059
+ }
1060
+
1061
+ private fun isHeadingBold(
1062
+ style: HtmlStyle,
1063
+ span: EnrichedInputSpan,
1064
+ ): Boolean =
1065
+ when (span) {
1066
+ is EnrichedInputH1Span -> style.h1Bold
1067
+ is EnrichedInputH2Span -> style.h2Bold
1068
+ is EnrichedInputH3Span -> style.h3Bold
1069
+ is EnrichedInputH4Span -> style.h4Bold
1070
+ is EnrichedInputH5Span -> style.h5Bold
1071
+ is EnrichedInputH6Span -> style.h6Bold
1072
+ else -> false
1073
+ }
1074
+
1075
+ private fun shouldRemoveBoldFromHeading(
1076
+ span: EnrichedInputSpan,
1077
+ prevStyle: HtmlStyle,
1078
+ nextStyle: HtmlStyle,
1079
+ ): Boolean {
1080
+ val wasBold = isHeadingBold(prevStyle, span)
1081
+ val isNowBold = isHeadingBold(nextStyle, span)
1082
+
1083
+ return !wasBold && isNowBold
1084
+ }
1085
+
1086
+ private fun reApplyHtmlStyleForSpans(
1087
+ previousHtmlStyle: HtmlStyle,
1088
+ nextHtmlStyle: HtmlStyle,
1089
+ ) {
1090
+ val spannable = text as? Spannable ?: return
1091
+ if (spannable.isEmpty()) return
1092
+
1093
+ var shouldEmitStateChange = false
1094
+
1095
+ runAsATransaction {
1096
+ val spans = spannable.getSpans(0, spannable.length, EnrichedInputSpan::class.java)
1097
+ for (span in spans) {
1098
+ if (!span.dependsOnHtmlStyle) continue
1099
+
1100
+ val start = spannable.getSpanStart(span)
1101
+ val end = spannable.getSpanEnd(span)
1102
+ val flags = spannable.getSpanFlags(span)
1103
+
1104
+ if (start == -1 || end == -1) continue
1105
+
1106
+ // Check if we need to remove explicit bold spans
1107
+ if (shouldRemoveBoldFromHeading(span, previousHtmlStyle, nextHtmlStyle)) {
1108
+ val isRemoved = removeStyle(EnrichedSpans.BOLD, start, end)
1109
+ if (isRemoved) shouldEmitStateChange = true
1110
+ }
1111
+
1112
+ spannable.removeSpan(span)
1113
+ val newSpan = span.rebuildWithStyle(htmlStyle)
1114
+ spannable.setSpan(newSpan, start, end, EnrichedSpanFlags.forSpan(newSpan, flags))
1115
+ }
1116
+
1117
+ if (shouldEmitStateChange) {
1118
+ selection?.validateStyles()
1119
+ }
1120
+ }
1121
+ layoutManager.invalidateLayout()
1122
+ forceScrollToSelection()
1123
+ }
1124
+
1125
+ override fun onAttachedToWindow() {
1126
+ super.onAttachedToWindow()
1127
+
1128
+ // https://github.com/facebook/react-native/blob/36df97f500aa0aa8031098caf7526db358b6ddc1/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt#L946
1129
+ // setTextIsSelectable internally calls setText(), which fires afterTextChanged that should be marked as a transaction to avoid unwanted side effects
1130
+ runAsATransaction { super.setTextIsSelectable(true) }
1131
+
1132
+ if (autoFocus && !didAttachToWindow) {
1133
+ requestFocusProgrammatically()
1134
+ }
1135
+
1136
+ didAttachToWindow = true
1137
+ }
1138
+
1139
+ companion object {
1140
+ const val TAG = "EnrichedTextInputView"
1141
+ private const val CONTEXT_MENU_ITEM_ID = 10000
1142
+ const val DEFAULT_IME_ACTION_LABEL = "DONE"
1143
+ }
1144
+ }