react-native-enriched 0.3.0 → 0.4.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 (202) hide show
  1. package/README.md +6 -4
  2. package/android/build.gradle +3 -3
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +3 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +1 -0
  5. package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
  6. package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
  7. package/{ios/generated/RNEnrichedTextInputViewSpec → android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec}/EventEmitters.cpp +31 -29
  8. package/{ios/generated/RNEnrichedTextInputViewSpec → android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec}/EventEmitters.h +22 -25
  9. package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +57 -0
  10. package/android/gradle.properties +5 -5
  11. package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewPackage.kt → ReactNativeEnrichedPackage.kt} +3 -2
  12. package/android/src/main/java/com/swmansion/enriched/{utils → common}/AsyncDrawable.kt +40 -8
  13. package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
  14. package/android/src/main/java/com/swmansion/enriched/{utils → common}/EnrichedConstants.kt +1 -1
  15. package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
  16. package/android/src/main/java/com/swmansion/enriched/{spans/utils → common}/ForceRedrawSpan.kt +1 -1
  17. package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +7 -0
  18. package/android/src/main/java/com/swmansion/enriched/{utils → common}/ResourceManager.kt +1 -1
  19. package/android/src/main/java/com/swmansion/enriched/{utils → common/parser}/EnrichedParser.java +126 -99
  20. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
  21. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedBlockQuoteSpan.kt +9 -13
  22. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBoldSpan.kt +12 -0
  23. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +91 -0
  24. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedCodeBlockSpan.kt +8 -12
  25. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH1Span.kt +20 -0
  26. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH2Span.kt +20 -0
  27. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH3Span.kt +20 -0
  28. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH4Span.kt +21 -0
  29. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH5Span.kt +20 -0
  30. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH6Span.kt +20 -0
  31. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedImageSpan.kt +43 -38
  32. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedInlineCodeSpan.kt +7 -11
  33. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
  34. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedLinkSpan.kt +7 -11
  35. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedMentionSpan.kt +6 -10
  36. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedOrderedListSpan.kt +12 -21
  37. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedStrikeThroughSpan.kt +11 -0
  38. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnderlineSpan.kt +11 -0
  39. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedUnorderedListSpan.kt +9 -13
  40. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedBlockSpan.kt +1 -1
  41. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedHeadingSpan.kt +1 -1
  42. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
  43. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedParagraphSpan.kt +1 -1
  44. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
  45. package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -1
  46. package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputConnectionWrapper.kt → textinput/EnrichedTextInputConnectionWrapper.kt} +2 -2
  47. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +83 -0
  48. package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputView.kt → textinput/EnrichedTextInputView.kt} +87 -51
  49. package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewLayoutManager.kt → textinput/EnrichedTextInputViewLayoutManager.kt} +1 -1
  50. package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewManager.kt → textinput/EnrichedTextInputViewManager.kt} +24 -17
  51. package/android/src/main/java/com/swmansion/enriched/{MeasurementStore.kt → textinput/MeasurementStore.kt} +5 -4
  52. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/MentionHandler.kt +2 -2
  53. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeHtmlEvent.kt +1 -1
  54. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeSelectionEvent.kt +1 -1
  55. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeStateEvent.kt +1 -1
  56. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeTextEvent.kt +2 -2
  57. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputBlurEvent.kt +1 -1
  58. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputFocusEvent.kt +1 -1
  59. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputKeyPressEvent.kt +1 -1
  60. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnLinkDetectedEvent.kt +1 -1
  61. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionDetectedEvent.kt +1 -1
  62. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionEvent.kt +1 -1
  63. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
  64. package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnRequestHtmlResultEvent.kt +1 -1
  65. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBlockQuoteSpan.kt +14 -0
  66. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBoldSpan.kt +14 -0
  67. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCheckboxListSpan.kt +15 -0
  68. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCodeBlockSpan.kt +14 -0
  69. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH1Span.kt +14 -0
  70. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH2Span.kt +14 -0
  71. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH3Span.kt +14 -0
  72. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH4Span.kt +14 -0
  73. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH5Span.kt +14 -0
  74. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH6Span.kt +14 -0
  75. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputImageSpan.kt +36 -0
  76. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputInlineCodeSpan.kt +14 -0
  77. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputItalicSpan.kt +14 -0
  78. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputLinkSpan.kt +15 -0
  79. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputMentionSpan.kt +18 -0
  80. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputOrderedListSpan.kt +21 -0
  81. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputStrikeThroughSpan.kt +14 -0
  82. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnderlineSpan.kt +14 -0
  83. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnorderedListSpan.kt +14 -0
  84. package/android/src/main/java/com/swmansion/enriched/{spans → textinput/spans}/EnrichedSpans.kt +39 -30
  85. package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
  86. package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/HtmlStyle.kt +58 -43
  87. package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/InlineStyles.kt +4 -4
  88. package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ListStyles.kt +77 -26
  89. package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParagraphStyles.kt +30 -25
  90. package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParametrizedStyles.kt +19 -19
  91. package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedEditableFactory.kt +2 -2
  92. package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSelection.kt +15 -14
  93. package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpanState.kt +15 -50
  94. package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpannable.kt +3 -3
  95. package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpannableStringBuilder.kt +2 -1
  96. package/android/src/main/java/com/swmansion/enriched/textinput/utils/RichContentReceiver.kt +127 -0
  97. package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +106 -0
  98. package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedSpanWatcher.kt +10 -10
  99. package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedTextWatcher.kt +3 -3
  100. package/android/src/main/new_arch/CMakeLists.txt +1 -1
  101. package/android/src/main/new_arch/ReactNativeEnrichedSpec.cpp +11 -0
  102. package/android/src/main/new_arch/ReactNativeEnrichedSpec.h +15 -0
  103. package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputMeasurementManager.h +1 -1
  104. package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputShadowNode.h +2 -2
  105. package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/conversions.h +1 -1
  106. package/ios/EnrichedTextInputView.h +1 -0
  107. package/ios/EnrichedTextInputView.mm +274 -55
  108. package/ios/config/InputConfig.h +10 -0
  109. package/ios/config/InputConfig.mm +119 -0
  110. package/ios/extensions/ImageExtension.h +35 -0
  111. package/ios/extensions/ImageExtension.mm +156 -0
  112. package/ios/extensions/LayoutManagerExtension.mm +115 -95
  113. package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
  114. package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
  115. package/{android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec → ios/generated/ReactNativeEnrichedSpec}/EventEmitters.cpp +31 -29
  116. package/{android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec → ios/generated/ReactNativeEnrichedSpec}/EventEmitters.h +22 -25
  117. package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +57 -0
  118. package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/RCTComponentViewHelpers.h +21 -0
  119. package/ios/inputParser/InputParser.mm +135 -8
  120. package/ios/inputTextView/InputTextView.mm +118 -0
  121. package/ios/interfaces/ImageAttachment.h +1 -0
  122. package/ios/interfaces/ImageAttachment.mm +43 -4
  123. package/ios/interfaces/StyleHeaders.h +13 -2
  124. package/ios/interfaces/StyleTypeEnum.h +1 -0
  125. package/ios/internals/EnrichedTextInputViewState.cpp +6 -6
  126. package/ios/styles/CheckboxListStyle.mm +321 -0
  127. package/ios/styles/H1Style.mm +3 -0
  128. package/ios/styles/H2Style.mm +3 -0
  129. package/ios/styles/H3Style.mm +3 -0
  130. package/ios/styles/H4Style.mm +3 -0
  131. package/ios/styles/H5Style.mm +3 -0
  132. package/ios/styles/H6Style.mm +3 -0
  133. package/ios/styles/HeadingStyleBase.mm +150 -78
  134. package/ios/utils/CheckboxHitTestUtils.h +10 -0
  135. package/ios/utils/CheckboxHitTestUtils.mm +123 -0
  136. package/ios/utils/ParagraphAttributesUtils.mm +83 -53
  137. package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
  138. package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
  139. package/ios/utils/ZeroWidthSpaceUtils.mm +14 -3
  140. package/lib/module/EnrichedTextInput.js +36 -11
  141. package/lib/module/EnrichedTextInput.js.map +1 -1
  142. package/lib/module/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +40 -9
  143. package/lib/module/types.js +4 -0
  144. package/lib/module/types.js.map +1 -0
  145. package/lib/module/utils/normalizeHtmlStyle.js +6 -0
  146. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -1
  147. package/lib/module/utils/nullthrows.js +9 -0
  148. package/lib/module/utils/nullthrows.js.map +1 -0
  149. package/lib/typescript/src/EnrichedTextInput.d.ts +9 -49
  150. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  151. package/lib/typescript/src/index.d.ts +2 -1
  152. package/lib/typescript/src/index.d.ts.map +1 -1
  153. package/lib/typescript/src/{EnrichedTextInputNativeComponent.d.ts → spec/EnrichedTextInputNativeComponent.d.ts} +33 -8
  154. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
  155. package/lib/typescript/src/types.d.ts +58 -0
  156. package/lib/typescript/src/types.d.ts.map +1 -0
  157. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +2 -2
  158. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -1
  159. package/lib/typescript/src/utils/nullthrows.d.ts +2 -0
  160. package/lib/typescript/src/utils/nullthrows.d.ts.map +1 -0
  161. package/lib/typescript/src/utils/regexParser.d.ts +1 -1
  162. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -1
  163. package/package.json +4 -4
  164. package/src/EnrichedTextInput.tsx +49 -62
  165. package/src/index.tsx +3 -1
  166. package/src/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +40 -9
  167. package/src/types.ts +59 -0
  168. package/src/utils/normalizeHtmlStyle.ts +8 -5
  169. package/src/utils/nullthrows.ts +7 -0
  170. package/src/utils/regexParser.ts +1 -1
  171. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +0 -21
  172. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +0 -17
  173. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +0 -24
  174. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +0 -24
  175. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +0 -24
  176. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +0 -24
  177. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +0 -24
  178. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +0 -24
  179. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +0 -16
  180. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +0 -15
  181. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +0 -15
  182. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +0 -3
  183. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +0 -9
  184. package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -21
  185. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +0 -22
  186. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +0 -26
  187. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +0 -1
  188. /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +0 -0
  189. /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.cpp +0 -0
  190. /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.h +0 -0
  191. /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.cpp +0 -0
  192. /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.h +0 -0
  193. /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputComponentDescriptor.h +0 -0
  194. /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputMeasurementManager.cpp +0 -0
  195. /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputShadowNode.cpp +0 -0
  196. /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputState.cpp +0 -0
  197. /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputState.h +0 -0
  198. /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +0 -0
  199. /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.cpp +0 -0
  200. /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.h +0 -0
  201. /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.cpp +0 -0
  202. /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.h +0 -0
@@ -1,20 +1,18 @@
1
- package com.swmansion.enriched.utils
1
+ package com.swmansion.enriched.textinput.utils
2
2
 
3
3
  import com.facebook.react.bridge.Arguments
4
4
  import com.facebook.react.bridge.ReactContext
5
5
  import com.facebook.react.bridge.WritableMap
6
6
  import com.facebook.react.uimanager.UIManagerHelper
7
7
  import com.facebook.react.uimanager.events.EventDispatcher
8
- import com.swmansion.enriched.EnrichedTextInputView
9
- import com.swmansion.enriched.events.OnChangeStateDeprecatedEvent
10
- import com.swmansion.enriched.events.OnChangeStateEvent
11
- import com.swmansion.enriched.spans.EnrichedSpans
8
+ import com.swmansion.enriched.textinput.EnrichedTextInputView
9
+ import com.swmansion.enriched.textinput.events.OnChangeStateEvent
10
+ import com.swmansion.enriched.textinput.spans.EnrichedSpans
12
11
 
13
12
  class EnrichedSpanState(
14
13
  private val view: EnrichedTextInputView,
15
14
  ) {
16
15
  private var previousPayload: WritableMap? = null
17
- private var previousDeprecatedPayload: WritableMap? = null
18
16
 
19
17
  var boldStart: Int? = null
20
18
  private set
@@ -46,6 +44,8 @@ class EnrichedSpanState(
46
44
  private set
47
45
  var unorderedListStart: Int? = null
48
46
  private set
47
+ var checkboxListStart: Int? = null
48
+ private set
49
49
  var linkStart: Int? = null
50
50
  private set
51
51
  var imageStart: Int? = null
@@ -128,6 +128,11 @@ class EnrichedSpanState(
128
128
  emitStateChangeEvent()
129
129
  }
130
130
 
131
+ fun setCheckboxListStart(start: Int?) {
132
+ this.checkboxListStart = start
133
+ emitStateChangeEvent()
134
+ }
135
+
131
136
  fun setLinkStart(start: Int?) {
132
137
  this.linkStart = start
133
138
  emitStateChangeEvent()
@@ -161,6 +166,7 @@ class EnrichedSpanState(
161
166
  EnrichedSpans.BLOCK_QUOTE -> blockQuoteStart
162
167
  EnrichedSpans.ORDERED_LIST -> orderedListStart
163
168
  EnrichedSpans.UNORDERED_LIST -> unorderedListStart
169
+ EnrichedSpans.CHECKBOX_LIST -> checkboxListStart
164
170
  EnrichedSpans.LINK -> linkStart
165
171
  EnrichedSpans.IMAGE -> imageStart
166
172
  EnrichedSpans.MENTION -> mentionStart
@@ -190,6 +196,7 @@ class EnrichedSpanState(
190
196
  EnrichedSpans.BLOCK_QUOTE -> setBlockQuoteStart(start)
191
197
  EnrichedSpans.ORDERED_LIST -> setOrderedListStart(start)
192
198
  EnrichedSpans.UNORDERED_LIST -> setUnorderedListStart(start)
199
+ EnrichedSpans.CHECKBOX_LIST -> setCheckboxListStart(start)
193
200
  EnrichedSpans.LINK -> setLinkStart(start)
194
201
  EnrichedSpans.IMAGE -> setImageStart(start)
195
202
  EnrichedSpans.MENTION -> setMentionStart(start)
@@ -201,53 +208,9 @@ class EnrichedSpanState(
201
208
  val surfaceId = UIManagerHelper.getSurfaceId(context)
202
209
  val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.id)
203
210
 
204
- dispatchDeprecatedPayload(dispatcher, surfaceId)
205
211
  dispatchPayload(dispatcher, surfaceId)
206
212
  }
207
213
 
208
- private fun dispatchDeprecatedPayload(
209
- dispatcher: EventDispatcher?,
210
- surfaceId: Int,
211
- ) {
212
- val deprecatedPayload = Arguments.createMap()
213
- deprecatedPayload.putBoolean("isBold", boldStart != null)
214
- deprecatedPayload.putBoolean("isItalic", italicStart != null)
215
- deprecatedPayload.putBoolean("isUnderline", underlineStart != null)
216
- deprecatedPayload.putBoolean("isStrikeThrough", strikethroughStart != null)
217
- deprecatedPayload.putBoolean("isInlineCode", inlineCodeStart != null)
218
- deprecatedPayload.putBoolean("isH1", h1Start != null)
219
- deprecatedPayload.putBoolean("isH2", h2Start != null)
220
- deprecatedPayload.putBoolean("isH3", h3Start != null)
221
- deprecatedPayload.putBoolean("isH4", h4Start != null)
222
- deprecatedPayload.putBoolean("isH5", h5Start != null)
223
- deprecatedPayload.putBoolean("isH6", h6Start != null)
224
- deprecatedPayload.putBoolean("isCodeBlock", codeBlockStart != null)
225
- deprecatedPayload.putBoolean("isBlockQuote", blockQuoteStart != null)
226
- deprecatedPayload.putBoolean("isOrderedList", orderedListStart != null)
227
- deprecatedPayload.putBoolean("isUnorderedList", unorderedListStart != null)
228
- deprecatedPayload.putBoolean("isLink", linkStart != null)
229
- deprecatedPayload.putBoolean("isImage", imageStart != null)
230
- deprecatedPayload.putBoolean("isMention", mentionStart != null)
231
-
232
- if (previousDeprecatedPayload == deprecatedPayload) {
233
- return
234
- }
235
-
236
- previousDeprecatedPayload =
237
- Arguments.createMap().apply {
238
- merge(deprecatedPayload)
239
- }
240
-
241
- dispatcher?.dispatchEvent(
242
- OnChangeStateDeprecatedEvent(
243
- surfaceId,
244
- view.id,
245
- deprecatedPayload,
246
- view.experimentalSynchronousEvents,
247
- ),
248
- )
249
- }
250
-
251
214
  private fun dispatchPayload(
252
215
  dispatcher: EventDispatcher?,
253
216
  surfaceId: Int,
@@ -269,6 +232,7 @@ class EnrichedSpanState(
269
232
  if (blockQuoteStart != null) EnrichedSpans.BLOCK_QUOTE else null,
270
233
  if (orderedListStart != null) EnrichedSpans.ORDERED_LIST else null,
271
234
  if (unorderedListStart != null) EnrichedSpans.UNORDERED_LIST else null,
235
+ if (checkboxListStart != null) EnrichedSpans.CHECKBOX_LIST else null,
272
236
  if (linkStart != null) EnrichedSpans.LINK else null,
273
237
  if (imageStart != null) EnrichedSpans.IMAGE else null,
274
238
  if (mentionStart != null) EnrichedSpans.MENTION else null,
@@ -292,6 +256,7 @@ class EnrichedSpanState(
292
256
  payload.putMap("link", getStyleState(activeStyles, EnrichedSpans.LINK))
293
257
  payload.putMap("image", getStyleState(activeStyles, EnrichedSpans.IMAGE))
294
258
  payload.putMap("mention", getStyleState(activeStyles, EnrichedSpans.MENTION))
259
+ payload.putMap("checkboxList", getStyleState(activeStyles, EnrichedSpans.CHECKBOX_LIST))
295
260
 
296
261
  // Do not emit event if payload is the same
297
262
  if (previousPayload == payload) {
@@ -1,10 +1,10 @@
1
- package com.swmansion.enriched.utils
1
+ package com.swmansion.enriched.textinput.utils
2
2
 
3
3
  import android.text.Spannable
4
4
  import android.text.SpannableString
5
5
  import android.text.SpannableStringBuilder
6
- import com.swmansion.enriched.spans.interfaces.EnrichedBlockSpan
7
- import com.swmansion.enriched.spans.interfaces.EnrichedParagraphSpan
6
+ import com.swmansion.enriched.common.spans.interfaces.EnrichedBlockSpan
7
+ import com.swmansion.enriched.common.spans.interfaces.EnrichedParagraphSpan
8
8
 
9
9
  fun Spannable.getSafeSpanBoundaries(
10
10
  start: Int,
@@ -1,6 +1,7 @@
1
- package com.swmansion.enriched.utils
1
+ package com.swmansion.enriched.textinput.utils
2
2
 
3
3
  import android.text.SpannableStringBuilder
4
+ import com.swmansion.enriched.common.EnrichedConstants
4
5
 
5
6
  // Removes zero-width spaces from the given range in the SpannableStringBuilder without affecting spans
6
7
  fun SpannableStringBuilder.removeZWS(
@@ -0,0 +1,127 @@
1
+ package com.swmansion.enriched.textinput.utils
2
+
3
+ import android.content.ClipData
4
+ import android.content.Context
5
+ import android.graphics.BitmapFactory
6
+ import android.net.Uri
7
+ import android.os.Handler
8
+ import android.os.Looper
9
+ import android.util.Log
10
+ import android.view.View
11
+ import android.webkit.MimeTypeMap
12
+ import androidx.core.view.ContentInfoCompat
13
+ import androidx.core.view.OnReceiveContentListener
14
+ import com.facebook.react.bridge.ReactContext
15
+ import com.facebook.react.uimanager.UIManagerHelper
16
+ import com.swmansion.enriched.textinput.EnrichedTextInputView
17
+ import com.swmansion.enriched.textinput.events.OnPasteImagesEvent
18
+ import java.io.File
19
+ import java.io.FileOutputStream
20
+ import kotlin.io.copyTo
21
+
22
+ class RichContentReceiver(
23
+ private val view: EnrichedTextInputView,
24
+ private val context: ReactContext,
25
+ ) : OnReceiveContentListener {
26
+ override fun onReceiveContent(
27
+ view: View,
28
+ contentInfo: ContentInfoCompat,
29
+ ): ContentInfoCompat? {
30
+ val split = contentInfo.partition { item: ClipData.Item -> item.uri != null }
31
+ val uriContent = split.first
32
+ val remaining = split.second
33
+
34
+ if (uriContent != null) {
35
+ processClipDataInBackground(uriContent.clip)
36
+ }
37
+
38
+ if (remaining != null && remaining.clip.itemCount > 0) {
39
+ val item = remaining.clip.getItemAt(0)
40
+
41
+ this.view.handleTextPaste(item)
42
+ }
43
+
44
+ return null
45
+ }
46
+
47
+ private fun processClipDataInBackground(clip: ClipData) {
48
+ Thread {
49
+ val results = mutableListOf<OnPasteImagesEvent.Companion.PastedImage>()
50
+
51
+ for (i in 0 until clip.itemCount) {
52
+ val item = clip.getItemAt(i)
53
+ val uri = item.uri ?: continue
54
+ val mimeType = getMimeTypeFromUri(uri) ?: continue
55
+
56
+ if (mimeType.startsWith("image/")) {
57
+ val result = saveUriToTempFile(context, uri, mimeType)
58
+ if (result != null) {
59
+ results.add(result)
60
+ }
61
+ }
62
+ }
63
+
64
+ if (results.isNotEmpty()) {
65
+ Handler(Looper.getMainLooper()).post {
66
+ emitOnPasteImageEvent(results)
67
+ }
68
+ }
69
+ }.start()
70
+ }
71
+
72
+ private fun emitOnPasteImageEvent(images: List<OnPasteImagesEvent.Companion.PastedImage>) {
73
+ val surfaceId = UIManagerHelper.getSurfaceId(context)
74
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.id)
75
+ dispatcher?.dispatchEvent(OnPasteImagesEvent(surfaceId, view.id, images, false))
76
+ }
77
+
78
+ private fun saveUriToTempFile(
79
+ context: Context,
80
+ uri: Uri,
81
+ mimeType: String,
82
+ ): OnPasteImagesEvent.Companion.PastedImage? {
83
+ return try {
84
+ val resolver = context.contentResolver
85
+ val ext = MimeTypeMap.getFileExtensionFromUrl(uri.toString())
86
+ val file = File.createTempFile("temp", ".$ext", context.cacheDir)
87
+
88
+ // Copy Stream
89
+ resolver.openInputStream(uri).use { input ->
90
+ if (input == null) return null
91
+ FileOutputStream(file).use { output ->
92
+ input.copyTo(output)
93
+ }
94
+ }
95
+
96
+ // Decode Dimensions
97
+ val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
98
+ BitmapFactory.decodeFile(file.absolutePath, options)
99
+
100
+ OnPasteImagesEvent.Companion.PastedImage(
101
+ uri = "file://${file.absolutePath}",
102
+ type = mimeType,
103
+ width = options.outWidth.toDouble(),
104
+ height = options.outHeight.toDouble(),
105
+ )
106
+ } catch (e: Exception) {
107
+ Log.e("RichContentReceiver", "Failed to save URI: $uri", e)
108
+ null
109
+ }
110
+ }
111
+
112
+ private fun getMimeTypeFromUri(uri: Uri): String? {
113
+ var mimeType = context.contentResolver.getType(uri)
114
+
115
+ if (mimeType == null) {
116
+ val extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString())
117
+
118
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
119
+ }
120
+
121
+ return mimeType
122
+ }
123
+
124
+ companion object {
125
+ val MIME_TYPES = arrayOf("image/*", "text/*")
126
+ }
127
+ }
@@ -0,0 +1,106 @@
1
+ package com.swmansion.enriched.textinput.utils
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.text.Selection
5
+ import android.text.Spannable
6
+ import android.text.Spanned
7
+ import android.util.Log
8
+ import android.view.MotionEvent
9
+ import android.widget.TextView
10
+ import com.swmansion.enriched.textinput.spans.EnrichedInputCheckboxListSpan
11
+ import org.json.JSONObject
12
+
13
+ fun jsonStringToStringMap(json: String): Map<String, String> {
14
+ val result = mutableMapOf<String, String>()
15
+ try {
16
+ val jsonObject = JSONObject(json)
17
+ for (key in jsonObject.keys()) {
18
+ val value = jsonObject.opt(key)
19
+ if (value is String) {
20
+ result[key] = value
21
+ }
22
+ }
23
+ } catch (e: Exception) {
24
+ Log.w("ReactNativeEnrichedView", "Failed to parse JSON string to Map: $json", e)
25
+ }
26
+
27
+ return result
28
+ }
29
+
30
+ // Sets a touch listener on TextView which is responsible for detecting touches on checkbox icons
31
+ // We don't use ClickableSpan because it works fine only when LinkMovementMethod is set on TextView
32
+ // Which breaks text selection and other features
33
+ @SuppressLint("ClickableViewAccessibility")
34
+ fun TextView.setCheckboxClickListener() {
35
+ var isDownOnCheckbox = false
36
+
37
+ setOnTouchListener { v, event ->
38
+ val tv = v as TextView
39
+ val layout = tv.layout ?: return@setOnTouchListener false
40
+ val spannable = tv.text as? Spanned ?: return@setOnTouchListener false
41
+
42
+ // Get touch coordinates relative to the text content
43
+ val x = event.x.toInt() - tv.totalPaddingLeft + tv.scrollX
44
+ val y = event.y.toInt() - tv.totalPaddingTop + tv.scrollY
45
+
46
+ // Identify the line and whether it's the first line of the span
47
+ val line = layout.getLineForVertical(y)
48
+ val lineStart = layout.getLineStart(line)
49
+
50
+ // Find spans for specific line
51
+ val spans = spannable.getSpans(lineStart, lineStart, EnrichedInputCheckboxListSpan::class.java)
52
+ if (spans.isEmpty()) return@setOnTouchListener false
53
+
54
+ // There should be only one span per line as we don't support nested lists
55
+ val span = spans[0]
56
+ val isFirstLine = spannable.getSpanStart(span) == lineStart
57
+ val marginWidth = span.getLeadingMargin(true)
58
+
59
+ // Check if touch is on checkbox icon area (which is in the leading margin on the first line)
60
+ val isInHotZone = isFirstLine && x in 0..marginWidth
61
+
62
+ when (event.action) {
63
+ MotionEvent.ACTION_DOWN -> {
64
+ if (isInHotZone) {
65
+ isDownOnCheckbox = true
66
+ return@setOnTouchListener true
67
+ }
68
+ }
69
+
70
+ MotionEvent.ACTION_UP -> {
71
+ if (isDownOnCheckbox && isInHotZone) {
72
+ val spannable = tv.text as? Spannable
73
+ if (spannable != null) {
74
+ val start = spannable.getSpanStart(span)
75
+ val end = spannable.getSpanEnd(span)
76
+ val flags = spannable.getSpanFlags(span)
77
+ span.isChecked = !span.isChecked
78
+
79
+ // Reapply span so changes are visible without need to redraw entire TextView
80
+ spannable.removeSpan(span)
81
+ spannable.setSpan(span, start, end, flags)
82
+
83
+ // For focused input, ensure cursor is active for affected paragraph
84
+ if (tv.isFocused) {
85
+ val currentCursor = Selection.getSelectionEnd(spannable)
86
+ if (currentCursor < start || currentCursor > end) {
87
+ Selection.setSelection(spannable, end)
88
+ }
89
+ }
90
+ }
91
+
92
+ isDownOnCheckbox = false
93
+ return@setOnTouchListener true
94
+ }
95
+ isDownOnCheckbox = false
96
+ }
97
+
98
+ MotionEvent.ACTION_CANCEL -> {
99
+ isDownOnCheckbox = false
100
+ }
101
+ }
102
+
103
+ // Let TextView handle other touches (e.g., for selection)
104
+ false
105
+ }
106
+ }
@@ -1,17 +1,17 @@
1
- package com.swmansion.enriched.watchers
1
+ package com.swmansion.enriched.textinput.watchers
2
2
 
3
3
  import android.text.SpanWatcher
4
4
  import android.text.Spannable
5
5
  import android.text.style.ParagraphStyle
6
6
  import com.facebook.react.bridge.ReactContext
7
7
  import com.facebook.react.uimanager.UIManagerHelper
8
- import com.swmansion.enriched.EnrichedTextInputView
9
- import com.swmansion.enriched.events.OnChangeHtmlEvent
10
- import com.swmansion.enriched.spans.EnrichedOrderedListSpan
11
- import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
12
- import com.swmansion.enriched.spans.interfaces.EnrichedSpan
13
- import com.swmansion.enriched.utils.EnrichedParser
14
- import com.swmansion.enriched.utils.getSafeSpanBoundaries
8
+ import com.swmansion.enriched.common.parser.EnrichedParser
9
+ import com.swmansion.enriched.common.spans.interfaces.EnrichedHeadingSpan
10
+ import com.swmansion.enriched.textinput.EnrichedTextInputView
11
+ import com.swmansion.enriched.textinput.events.OnChangeHtmlEvent
12
+ import com.swmansion.enriched.textinput.spans.EnrichedInputOrderedListSpan
13
+ import com.swmansion.enriched.textinput.spans.interfaces.EnrichedInputSpan
14
+ import com.swmansion.enriched.textinput.utils.getSafeSpanBoundaries
15
15
 
16
16
  class EnrichedSpanWatcher(
17
17
  private val view: EnrichedTextInputView,
@@ -56,7 +56,7 @@ class EnrichedSpanWatcher(
56
56
  text: Spannable,
57
57
  end: Int,
58
58
  ) {
59
- if (what is EnrichedOrderedListSpan) {
59
+ if (what is EnrichedInputOrderedListSpan) {
60
60
  view.listStyles?.updateOrderedListIndexes(text, end)
61
61
  }
62
62
  }
@@ -86,7 +86,7 @@ class EnrichedSpanWatcher(
86
86
  if (!view.shouldEmitHtml) return
87
87
 
88
88
  // Emit event only if we change one of ours spans
89
- if (what != null && what !is EnrichedSpan) return
89
+ if (what != null && what !is EnrichedInputSpan) return
90
90
 
91
91
  val html = EnrichedParser.toHtml(s)
92
92
  if (html == previousHtml) return
@@ -1,11 +1,11 @@
1
- package com.swmansion.enriched.watchers
1
+ package com.swmansion.enriched.textinput.watchers
2
2
 
3
3
  import android.text.Editable
4
4
  import android.text.TextWatcher
5
5
  import com.facebook.react.bridge.ReactContext
6
6
  import com.facebook.react.uimanager.UIManagerHelper
7
- import com.swmansion.enriched.EnrichedTextInputView
8
- import com.swmansion.enriched.events.OnChangeTextEvent
7
+ import com.swmansion.enriched.textinput.EnrichedTextInputView
8
+ import com.swmansion.enriched.textinput.events.OnChangeTextEvent
9
9
 
10
10
  class EnrichedTextWatcher(
11
11
  private val view: EnrichedTextInputView,
@@ -1,7 +1,7 @@
1
1
  cmake_minimum_required(VERSION 3.13)
2
2
  set(CMAKE_VERBOSE_MAKEFILE on)
3
3
 
4
- set(LIB_LITERAL RNEnrichedTextInputViewSpec)
4
+ set(LIB_LITERAL ReactNativeEnrichedSpec)
5
5
  set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL})
6
6
 
7
7
  set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
@@ -0,0 +1,11 @@
1
+ #include "ReactNativeEnrichedSpec.h"
2
+
3
+ namespace facebook::react {
4
+
5
+ std::shared_ptr<TurboModule> ReactNativeEnrichedSpec_ModuleProvider(
6
+ const std::string &moduleName, const JavaTurboModule::InitParams &params) {
7
+
8
+ return nullptr;
9
+ }
10
+
11
+ } // namespace facebook::react
@@ -0,0 +1,15 @@
1
+ #pragma once
2
+
3
+ #include <ReactCommon/JavaTurboModule.h>
4
+ #include <ReactCommon/TurboModule.h>
5
+ #include <jsi/jsi.h>
6
+
7
+ #include <react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputComponentDescriptor.h>
8
+
9
+ namespace facebook::react {
10
+
11
+ JSI_EXPORT
12
+ std::shared_ptr<TurboModule> ReactNativeEnrichedSpec_ModuleProvider(
13
+ const std::string &moduleName, const JavaTurboModule::InitParams &params);
14
+
15
+ } // namespace facebook::react
@@ -2,7 +2,7 @@
2
2
 
3
3
  #include "ComponentDescriptors.h"
4
4
 
5
- #include <react/renderer/components/RNEnrichedTextInputViewSpec/Props.h>
5
+ #include <react/renderer/components/ReactNativeEnrichedSpec/Props.h>
6
6
  #include <react/renderer/core/LayoutConstraints.h>
7
7
  #include <react/utils/ContextContainer.h>
8
8
 
@@ -3,8 +3,8 @@
3
3
  #include "EnrichedTextInputMeasurementManager.h"
4
4
  #include "EnrichedTextInputState.h"
5
5
 
6
- #include <react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h>
7
- #include <react/renderer/components/RNEnrichedTextInputViewSpec/Props.h>
6
+ #include <react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h>
7
+ #include <react/renderer/components/ReactNativeEnrichedSpec/Props.h>
8
8
  #include <react/renderer/components/view/ConcreteViewShadowNode.h>
9
9
 
10
10
  namespace facebook::react {
@@ -1,7 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  #include <folly/dynamic.h>
4
- #include <react/renderer/components/RNEnrichedTextInputViewSpec/Props.h>
4
+ #include <react/renderer/components/ReactNativeEnrichedSpec/Props.h>
5
5
  #include <react/renderer/core/propsConversions.h>
6
6
 
7
7
  #if REACT_NATIVE_MINOR_VERSION >= 81
@@ -36,6 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
36
36
  url:(NSString *)url
37
37
  range:(NSRange)range;
38
38
  - (void)emitOnMentionEvent:(NSString *)indicator text:(nullable NSString *)text;
39
+ - (void)emitOnPasteImagesEvent:(NSArray<NSDictionary *> *)images;
39
40
  - (void)anyTextMayHaveBeenModified;
40
41
  - (BOOL)handleStyleBlocksAndConflicts:(StyleType)type range:(NSRange)range;
41
42
  - (NSArray<NSNumber *> *)getPresentStyleTypesFrom:(NSArray<NSNumber *> *)types