react-native-enriched 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +16 -17
  2. package/android/build.gradle +77 -72
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +21 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +7 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
  6. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
  7. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  8. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +194 -0
  9. package/android/lint.gradle +70 -0
  10. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputConnectionWrapper.kt +140 -0
  11. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +304 -83
  12. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
  13. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +166 -51
  14. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +1 -3
  15. package/android/src/main/java/com/swmansion/enriched/MeasurementStore.kt +70 -21
  16. package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +21 -11
  17. package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +8 -9
  18. package/android/src/main/java/com/swmansion/enriched/events/OnChangeSelectionEvent.kt +10 -9
  19. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +21 -0
  20. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +9 -12
  21. package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +10 -10
  22. package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +7 -9
  23. package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +7 -9
  24. package/android/src/main/java/com/swmansion/enriched/events/OnInputKeyPressEvent.kt +27 -0
  25. package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +13 -11
  26. package/android/src/main/java/com/swmansion/enriched/events/OnMentionDetectedEvent.kt +10 -9
  27. package/android/src/main/java/com/swmansion/enriched/events/OnMentionEvent.kt +9 -8
  28. package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +32 -0
  29. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +24 -5
  30. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +8 -1
  31. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +10 -2
  32. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +8 -1
  33. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +8 -1
  34. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +8 -1
  35. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +24 -0
  36. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +24 -0
  37. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +24 -0
  38. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +34 -17
  39. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +8 -1
  40. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +7 -1
  41. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +10 -4
  42. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +14 -11
  43. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +18 -11
  44. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +174 -72
  45. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +7 -1
  46. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +7 -1
  47. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +11 -5
  48. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +3 -2
  49. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +1 -2
  50. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +1 -2
  51. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +3 -2
  52. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +5 -0
  53. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -2
  54. package/android/src/main/java/com/swmansion/enriched/spans/utils/ForceRedrawSpan.kt +2 -1
  55. package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +155 -20
  56. package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +25 -8
  57. package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +60 -20
  58. package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +161 -25
  59. package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +128 -52
  60. package/android/src/main/java/com/swmansion/enriched/utils/AsyncDrawable.kt +10 -7
  61. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedConstants.kt +11 -0
  62. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedEditableFactory.kt +17 -0
  63. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +136 -87
  64. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +71 -42
  65. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +183 -48
  66. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannable.kt +82 -0
  67. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannableStringBuilder.kt +15 -0
  68. package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -70
  69. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +46 -14
  70. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +34 -11
  71. package/android/src/main/new_arch/CMakeLists.txt +6 -0
  72. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
  73. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
  74. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
  75. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
  76. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
  77. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
  78. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
  79. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
  80. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
  81. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +33 -14
  82. package/ios/EnrichedTextInputView.h +26 -14
  83. package/ios/EnrichedTextInputView.mm +1209 -586
  84. package/ios/config/InputConfig.h +24 -6
  85. package/ios/config/InputConfig.mm +154 -38
  86. package/ios/{utils → extensions}/ColorExtension.mm +7 -5
  87. package/ios/extensions/FontExtension.mm +106 -0
  88. package/ios/{utils → extensions}/LayoutManagerExtension.h +1 -1
  89. package/ios/extensions/LayoutManagerExtension.mm +396 -0
  90. package/ios/{utils → extensions}/StringExtension.mm +19 -16
  91. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
  92. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
  93. package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  94. package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
  95. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +95 -0
  96. package/ios/inputParser/InputParser.h +5 -5
  97. package/ios/inputParser/InputParser.mm +864 -380
  98. package/ios/inputTextView/InputTextView.h +1 -1
  99. package/ios/inputTextView/InputTextView.mm +100 -59
  100. package/ios/{utils → interfaces}/BaseStyleProtocol.h +2 -2
  101. package/ios/interfaces/ImageAttachment.h +10 -0
  102. package/ios/interfaces/ImageAttachment.mm +36 -0
  103. package/ios/interfaces/LinkRegexConfig.h +19 -0
  104. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  105. package/ios/interfaces/MediaAttachment.h +23 -0
  106. package/ios/interfaces/MediaAttachment.mm +31 -0
  107. package/ios/{utils → interfaces}/MentionParams.h +0 -1
  108. package/ios/{utils → interfaces}/MentionStyleProps.mm +27 -20
  109. package/ios/{utils → interfaces}/StyleHeaders.h +37 -15
  110. package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
  111. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
  112. package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
  113. package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
  114. package/ios/internals/EnrichedTextInputViewState.h +3 -1
  115. package/ios/styles/BlockQuoteStyle.mm +189 -118
  116. package/ios/styles/BoldStyle.mm +110 -63
  117. package/ios/styles/CodeBlockStyle.mm +204 -128
  118. package/ios/styles/H1Style.mm +10 -4
  119. package/ios/styles/H2Style.mm +10 -4
  120. package/ios/styles/H3Style.mm +10 -4
  121. package/ios/styles/H4Style.mm +17 -0
  122. package/ios/styles/H5Style.mm +17 -0
  123. package/ios/styles/H6Style.mm +17 -0
  124. package/ios/styles/HeadingStyleBase.mm +148 -86
  125. package/ios/styles/ImageStyle.mm +75 -73
  126. package/ios/styles/InlineCodeStyle.mm +162 -88
  127. package/ios/styles/ItalicStyle.mm +76 -52
  128. package/ios/styles/LinkStyle.mm +411 -232
  129. package/ios/styles/MentionStyle.mm +363 -246
  130. package/ios/styles/OrderedListStyle.mm +171 -106
  131. package/ios/styles/StrikethroughStyle.mm +52 -35
  132. package/ios/styles/UnderlineStyle.mm +68 -46
  133. package/ios/styles/UnorderedListStyle.mm +169 -106
  134. package/ios/utils/OccurenceUtils.h +42 -42
  135. package/ios/utils/OccurenceUtils.mm +142 -119
  136. package/ios/utils/ParagraphAttributesUtils.h +10 -2
  137. package/ios/utils/ParagraphAttributesUtils.mm +182 -71
  138. package/ios/utils/ParagraphsUtils.h +2 -1
  139. package/ios/utils/ParagraphsUtils.mm +41 -27
  140. package/ios/utils/TextInsertionUtils.h +13 -2
  141. package/ios/utils/TextInsertionUtils.mm +38 -20
  142. package/ios/utils/WordsUtils.h +2 -1
  143. package/ios/utils/WordsUtils.mm +32 -22
  144. package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
  145. package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
  146. package/lib/module/EnrichedTextInput.js +61 -2
  147. package/lib/module/EnrichedTextInput.js.map +1 -1
  148. package/lib/module/EnrichedTextInputNativeComponent.ts +149 -12
  149. package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
  150. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  151. package/lib/module/utils/regexParser.js +46 -0
  152. package/lib/module/utils/regexParser.js.map +1 -0
  153. package/lib/typescript/src/EnrichedTextInput.d.ts +24 -14
  154. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  155. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +129 -12
  156. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  157. package/lib/typescript/src/index.d.ts +1 -1
  158. package/lib/typescript/src/index.d.ts.map +1 -1
  159. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  160. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  161. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  162. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  163. package/package.json +17 -6
  164. package/src/EnrichedTextInput.tsx +96 -13
  165. package/src/EnrichedTextInputNativeComponent.ts +149 -12
  166. package/src/index.tsx +2 -0
  167. package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
  168. package/src/utils/regexParser.ts +56 -0
  169. package/ios/utils/FontExtension.mm +0 -91
  170. package/ios/utils/LayoutManagerExtension.mm +0 -286
  171. package/lib/module/normalizeHtmlStyle.js.map +0 -1
  172. package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
  173. package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
  174. package/ios/{utils → extensions}/ColorExtension.h +0 -0
  175. package/ios/{utils → extensions}/FontExtension.h +0 -0
  176. package/ios/{utils → extensions}/StringExtension.h +1 -1
  177. package/ios/{utils → interfaces}/ImageData.h +0 -0
  178. package/ios/{utils → interfaces}/ImageData.mm +0 -0
  179. package/ios/{utils → interfaces}/LinkData.h +0 -0
  180. package/ios/{utils → interfaces}/LinkData.mm +0 -0
  181. package/ios/{utils → interfaces}/MentionParams.mm +0 -0
  182. package/ios/{utils → interfaces}/MentionStyleProps.h +1 -1
  183. /package/ios/{utils → interfaces}/StylePair.h +0 -0
  184. /package/ios/{utils → interfaces}/StylePair.mm +0 -0
  185. /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
  186. /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
@@ -13,12 +13,16 @@ import android.text.InputType
13
13
  import android.text.Spannable
14
14
  import android.util.AttributeSet
15
15
  import android.util.Log
16
+ import android.util.Patterns
16
17
  import android.util.TypedValue
17
18
  import android.view.Gravity
18
19
  import android.view.MotionEvent
20
+ import android.view.inputmethod.EditorInfo
21
+ import android.view.inputmethod.InputConnection
19
22
  import android.view.inputmethod.InputMethodManager
20
23
  import androidx.appcompat.widget.AppCompatEditText
21
24
  import com.facebook.react.bridge.ReactContext
25
+ import com.facebook.react.bridge.ReadableMap
22
26
  import com.facebook.react.common.ReactConstants
23
27
  import com.facebook.react.uimanager.PixelUtil
24
28
  import com.facebook.react.uimanager.StateWrapper
@@ -29,22 +33,30 @@ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
29
33
  import com.swmansion.enriched.events.MentionHandler
30
34
  import com.swmansion.enriched.events.OnInputBlurEvent
31
35
  import com.swmansion.enriched.events.OnInputFocusEvent
36
+ import com.swmansion.enriched.events.OnRequestHtmlResultEvent
37
+ import com.swmansion.enriched.spans.EnrichedH1Span
38
+ import com.swmansion.enriched.spans.EnrichedH2Span
39
+ import com.swmansion.enriched.spans.EnrichedH3Span
32
40
  import com.swmansion.enriched.spans.EnrichedImageSpan
33
41
  import com.swmansion.enriched.spans.EnrichedSpans
42
+ import com.swmansion.enriched.spans.interfaces.EnrichedSpan
43
+ import com.swmansion.enriched.styles.HtmlStyle
34
44
  import com.swmansion.enriched.styles.InlineStyles
35
45
  import com.swmansion.enriched.styles.ListStyles
36
46
  import com.swmansion.enriched.styles.ParagraphStyles
37
47
  import com.swmansion.enriched.styles.ParametrizedStyles
38
- import com.swmansion.enriched.styles.HtmlStyle
48
+ import com.swmansion.enriched.utils.EnrichedConstants
49
+ import com.swmansion.enriched.utils.EnrichedEditableFactory
39
50
  import com.swmansion.enriched.utils.EnrichedParser
40
51
  import com.swmansion.enriched.utils.EnrichedSelection
41
52
  import com.swmansion.enriched.utils.EnrichedSpanState
42
53
  import com.swmansion.enriched.utils.mergeSpannables
43
54
  import com.swmansion.enriched.watchers.EnrichedSpanWatcher
44
55
  import com.swmansion.enriched.watchers.EnrichedTextWatcher
56
+ import java.util.regex.Pattern
57
+ import java.util.regex.PatternSyntaxException
45
58
  import kotlin.math.ceil
46
59
 
47
-
48
60
  class EnrichedTextInputView : AppCompatEditText {
49
61
  var stateWrapper: StateWrapper? = null
50
62
  val selection: EnrichedSelection? = EnrichedSelection(this)
@@ -59,10 +71,20 @@ class EnrichedTextInputView : AppCompatEditText {
59
71
 
60
72
  val mentionHandler: MentionHandler? = MentionHandler(this)
61
73
  var htmlStyle: HtmlStyle = HtmlStyle(this, null)
74
+ set(value) {
75
+ if (field != value) {
76
+ val prev = field
77
+ field = value
78
+ reApplyHtmlStyleForSpans(prev, value)
79
+ }
80
+ }
81
+
82
+ var linkRegex: Pattern? = Patterns.WEB_URL
62
83
  var spanWatcher: EnrichedSpanWatcher? = null
63
84
  var layoutManager: EnrichedTextInputViewLayoutManager = EnrichedTextInputViewLayoutManager(this)
64
85
 
65
- var shouldEmitHtml: Boolean = true
86
+ var shouldEmitHtml: Boolean = false
87
+ var shouldEmitOnChangeText: Boolean = false
66
88
  var experimentalSynchronousEvents: Boolean = false
67
89
 
68
90
  var fontSize: Float? = null
@@ -89,11 +111,26 @@ class EnrichedTextInputView : AppCompatEditText {
89
111
  constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
90
112
  context,
91
113
  attrs,
92
- defStyleAttr
114
+ defStyleAttr,
93
115
  ) {
94
116
  prepareComponent()
95
117
  }
96
118
 
119
+ override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
120
+ var inputConnection = super.onCreateInputConnection(outAttrs)
121
+ if (inputConnection != null) {
122
+ inputConnection =
123
+ EnrichedTextInputConnectionWrapper(
124
+ inputConnection,
125
+ context as ReactContext,
126
+ this,
127
+ experimentalSynchronousEvents,
128
+ )
129
+ }
130
+
131
+ return inputConnection
132
+ }
133
+
97
134
  init {
98
135
  inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
99
136
  }
@@ -112,7 +149,11 @@ class EnrichedTextInputView : AppCompatEditText {
112
149
  setPadding(0, 0, 0, 0)
113
150
  setBackgroundColor(Color.TRANSPARENT)
114
151
 
115
- addSpanWatcher(EnrichedSpanWatcher(this))
152
+ // Ensure that every time new editable is created, it has EnrichedSpanWatcher attached
153
+ val spanWatcher = EnrichedSpanWatcher(this)
154
+ this.spanWatcher = spanWatcher
155
+ setEditableFactory(EnrichedEditableFactory(spanWatcher))
156
+
116
157
  addTextChangedListener(EnrichedTextWatcher(this))
117
158
  }
118
159
 
@@ -126,31 +167,32 @@ class EnrichedTextInputView : AppCompatEditText {
126
167
  this.parent.requestDisallowInterceptTouchEvent(true)
127
168
  }
128
169
 
129
- MotionEvent.ACTION_MOVE ->
170
+ MotionEvent.ACTION_MOVE -> {
130
171
  if (detectScrollMovement) {
131
172
  if (!canScrollVertically(-1) &&
132
173
  !canScrollVertically(1) &&
133
174
  !canScrollHorizontally(-1) &&
134
- !canScrollHorizontally(1)) {
175
+ !canScrollHorizontally(1)
176
+ ) {
135
177
  // We cannot scroll, let parent views take care of these touches.
136
178
  this.parent.requestDisallowInterceptTouchEvent(false)
137
179
  }
138
180
  detectScrollMovement = false
139
181
  }
182
+ }
140
183
  }
141
184
 
142
185
  return super.onTouchEvent(ev)
143
186
  }
144
187
 
145
- override fun canScrollVertically(direction: Int): Boolean {
146
- return scrollEnabled
147
- }
188
+ override fun canScrollVertically(direction: Int): Boolean = scrollEnabled
148
189
 
149
- override fun canScrollHorizontally(direction: Int): Boolean {
150
- return scrollEnabled
151
- }
190
+ override fun canScrollHorizontally(direction: Int): Boolean = scrollEnabled
152
191
 
153
- override fun onSelectionChanged(selStart: Int, selEnd: Int) {
192
+ override fun onSelectionChanged(
193
+ selStart: Int,
194
+ selEnd: Int,
195
+ ) {
154
196
  super.onSelectionChanged(selStart, selEnd)
155
197
  selection?.onSelection(selStart, selEnd)
156
198
  }
@@ -160,7 +202,11 @@ class EnrichedTextInputView : AppCompatEditText {
160
202
  inputMethodManager?.hideSoftInputFromWindow(windowToken, 0)
161
203
  }
162
204
 
163
- override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
205
+ override fun onFocusChanged(
206
+ focused: Boolean,
207
+ direction: Int,
208
+ previouslyFocusedRect: Rect?,
209
+ ) {
164
210
  super.onFocusChanged(focused, direction, previouslyFocusedRect)
165
211
  val context = context as ReactContext
166
212
  val surfaceId = UIManagerHelper.getSurfaceId(context)
@@ -179,6 +225,7 @@ class EnrichedTextInputView : AppCompatEditText {
179
225
  handleCustomCopy()
180
226
  return true
181
227
  }
228
+
182
229
  android.R.id.paste -> {
183
230
  handleCustomPaste()
184
231
  return true
@@ -224,9 +271,13 @@ class EnrichedTextInputView : AppCompatEditText {
224
271
 
225
272
  // Currently, we do not support pasting images
226
273
  if (item?.text == null) return
274
+ val lengthBefore = currentText.length
227
275
  val finalText = currentText.mergeSpannables(start, end, item.text.toString())
228
276
  setValue(finalText)
229
- parametrizedStyles?.detectAllLinks()
277
+
278
+ // Detect links in the newly pasted range
279
+ val finalEndIndex = start + finalText.length - lengthBefore
280
+ parametrizedStyles?.detectLinksInRange(finalText, start, finalEndIndex)
230
281
  }
231
282
 
232
283
  fun requestFocusProgrammatically() {
@@ -257,14 +308,43 @@ class EnrichedTextInputView : AppCompatEditText {
257
308
  setText(newText)
258
309
 
259
310
  observeAsyncImages()
260
- // Assign SpanWatcher one more time as our previous spannable has been replaced
261
- addSpanWatcher(EnrichedSpanWatcher(this))
262
311
 
263
312
  // Scroll to the last line of text
264
313
  setSelection(text?.length ?: 0)
265
314
  }
266
315
  }
267
316
 
317
+ fun setCustomSelection(
318
+ visibleStart: Int,
319
+ visibleEnd: Int,
320
+ ) {
321
+ val actualStart = getActualIndex(visibleStart)
322
+ val actualEnd = getActualIndex(visibleEnd)
323
+
324
+ setSelection(actualStart, actualEnd)
325
+ }
326
+
327
+ // Helper: Walks through the string skipping ZWSPs to find the Nth visible character
328
+ private fun getActualIndex(visibleIndex: Int): Int {
329
+ val currentText = text as Spannable
330
+ var currentVisibleCount = 0
331
+ var actualIndex = 0
332
+
333
+ while (actualIndex < currentText.length) {
334
+ if (currentVisibleCount == visibleIndex) {
335
+ return actualIndex
336
+ }
337
+
338
+ // If the current char is not a hidden space, it counts towards our visible index
339
+ if (currentText[actualIndex] != EnrichedConstants.ZWS) {
340
+ currentVisibleCount++
341
+ }
342
+ actualIndex++
343
+ }
344
+
345
+ return actualIndex
346
+ }
347
+
268
348
  /**
269
349
  * Finds all async images in the current text and sets up listeners
270
350
  * to redraw the text layout when they finish downloading.
@@ -335,6 +415,7 @@ class EnrichedTextInputView : AppCompatEditText {
335
415
  // This ensured that newly created spans will take the new font size into account
336
416
  htmlStyle.invalidateStyles()
337
417
  layoutManager.invalidateLayout()
418
+ forceScrollToSelection()
338
419
  }
339
420
 
340
421
  fun setFontFamily(family: String?) {
@@ -363,19 +444,50 @@ class EnrichedTextInputView : AppCompatEditText {
363
444
  }
364
445
 
365
446
  fun setAutoCapitalize(flagName: String?) {
366
- val flag = when (flagName) {
367
- "none" -> InputType.TYPE_NULL
368
- "sentences" -> InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
369
- "words" -> InputType.TYPE_TEXT_FLAG_CAP_WORDS
370
- "characters" -> InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
371
- else -> InputType.TYPE_NULL
447
+ val flag =
448
+ when (flagName) {
449
+ "none" -> InputType.TYPE_NULL
450
+ "sentences" -> InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
451
+ "words" -> InputType.TYPE_TEXT_FLAG_CAP_WORDS
452
+ "characters" -> InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
453
+ else -> InputType.TYPE_NULL
454
+ }
455
+
456
+ inputType = (
457
+ inputType and
458
+ InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS.inv() and
459
+ InputType.TYPE_TEXT_FLAG_CAP_WORDS.inv() and
460
+ InputType.TYPE_TEXT_FLAG_CAP_SENTENCES.inv()
461
+ ) or if (flag == InputType.TYPE_NULL) 0 else flag
462
+ }
463
+
464
+ fun setLinkRegex(config: ReadableMap?) {
465
+ val patternStr = config?.getString("pattern")
466
+ if (patternStr == null) {
467
+ linkRegex = Patterns.WEB_URL
468
+ return
469
+ }
470
+
471
+ if (config.getBoolean("isDefault")) {
472
+ linkRegex = Patterns.WEB_URL
473
+ return
372
474
  }
373
475
 
374
- inputType = (inputType and
375
- InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS.inv() and
376
- InputType.TYPE_TEXT_FLAG_CAP_WORDS.inv() and
377
- InputType.TYPE_TEXT_FLAG_CAP_SENTENCES.inv()
378
- ) or if (flag == InputType.TYPE_NULL) 0 else flag
476
+ if (config.getBoolean("isDisabled")) {
477
+ linkRegex = null
478
+ return
479
+ }
480
+
481
+ var flags = 0
482
+ if (config.getBoolean("caseInsensitive")) flags = flags or Pattern.CASE_INSENSITIVE
483
+ if (config.getBoolean("dotAll")) flags = flags or Pattern.DOTALL
484
+
485
+ try {
486
+ linkRegex = Pattern.compile("(?s).*?($patternStr).*", flags)
487
+ } catch (e: PatternSyntaxException) {
488
+ Log.w("EnrichedTextInputView", "Invalid link regex pattern: $patternStr")
489
+ linkRegex = Patterns.WEB_URL
490
+ }
379
491
  }
380
492
 
381
493
  // https://github.com/facebook/react-native/blob/36df97f500aa0aa8031098caf7526db358b6ddc1/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt#L283C2-L284C1
@@ -384,9 +496,7 @@ class EnrichedTextInputView : AppCompatEditText {
384
496
  // next layout() to be called. However, we do not perform a layout() after a requestLayout(), so
385
497
  // we need to override isLayoutRequested to force EditText to scroll to the end of the new text
386
498
  // immediately.
387
- override fun isLayoutRequested(): Boolean {
388
- return false
389
- }
499
+ override fun isLayoutRequested(): Boolean = false
390
500
 
391
501
  fun afterUpdateTransaction() {
392
502
  updateTypeface()
@@ -426,6 +536,9 @@ class EnrichedTextInputView : AppCompatEditText {
426
536
  EnrichedSpans.H1 -> paragraphStyles?.toggleStyle(EnrichedSpans.H1)
427
537
  EnrichedSpans.H2 -> paragraphStyles?.toggleStyle(EnrichedSpans.H2)
428
538
  EnrichedSpans.H3 -> paragraphStyles?.toggleStyle(EnrichedSpans.H3)
539
+ EnrichedSpans.H4 -> paragraphStyles?.toggleStyle(EnrichedSpans.H4)
540
+ EnrichedSpans.H5 -> paragraphStyles?.toggleStyle(EnrichedSpans.H5)
541
+ EnrichedSpans.H6 -> paragraphStyles?.toggleStyle(EnrichedSpans.H6)
429
542
  EnrichedSpans.CODE_BLOCK -> paragraphStyles?.toggleStyle(EnrichedSpans.CODE_BLOCK)
430
543
  EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.toggleStyle(EnrichedSpans.BLOCK_QUOTE)
431
544
  EnrichedSpans.ORDERED_LIST -> listStyles?.toggleStyle(EnrichedSpans.ORDERED_LIST)
@@ -436,48 +549,60 @@ class EnrichedTextInputView : AppCompatEditText {
436
549
  layoutManager.invalidateLayout()
437
550
  }
438
551
 
439
- private fun removeStyle(name: String, start: Int, end: Int): Boolean {
440
- val removed = when (name) {
441
- EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
442
- EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
443
- EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
444
- EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
445
- EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
446
- EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
447
- EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
448
- EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
449
- EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
450
- EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
451
- EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
452
- EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
453
- EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
454
- EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
455
- EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
456
- else -> false
457
- }
552
+ private fun removeStyle(
553
+ name: String,
554
+ start: Int,
555
+ end: Int,
556
+ ): Boolean {
557
+ val removed =
558
+ when (name) {
559
+ EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
560
+ EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
561
+ EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
562
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
563
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
564
+ EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
565
+ EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
566
+ EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
567
+ EnrichedSpans.H4 -> paragraphStyles?.removeStyle(EnrichedSpans.H4, start, end)
568
+ EnrichedSpans.H5 -> paragraphStyles?.removeStyle(EnrichedSpans.H5, start, end)
569
+ EnrichedSpans.H6 -> paragraphStyles?.removeStyle(EnrichedSpans.H6, start, end)
570
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
571
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
572
+ EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
573
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
574
+ EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
575
+ EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
576
+ EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
577
+ else -> false
578
+ }
458
579
 
459
580
  return removed == true
460
581
  }
461
582
 
462
583
  private fun getTargetRange(name: String): Pair<Int, Int> {
463
- val result = when (name) {
464
- EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
465
- EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
466
- EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
467
- EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
468
- EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
469
- EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
470
- EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
471
- EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
472
- EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
473
- EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
474
- EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
475
- EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
476
- EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
477
- EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
478
- EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
479
- else -> Pair(0, 0)
480
- }
584
+ val result =
585
+ when (name) {
586
+ EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
587
+ EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
588
+ EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
589
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
590
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
591
+ EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
592
+ EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
593
+ EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
594
+ EnrichedSpans.H4 -> paragraphStyles?.getStyleRange()
595
+ EnrichedSpans.H5 -> paragraphStyles?.getStyleRange()
596
+ EnrichedSpans.H6 -> paragraphStyles?.getStyleRange()
597
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
598
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
599
+ EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
600
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
601
+ EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
602
+ EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
603
+ EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
604
+ else -> Pair(0, 0)
605
+ }
481
606
 
482
607
  return result ?: Pair(0, 0)
483
608
  }
@@ -511,11 +636,12 @@ class EnrichedTextInputView : AppCompatEditText {
511
636
 
512
637
  val lengthAfter = text?.length ?: 0
513
638
  val charactersRemoved = lengthBefore - lengthAfter
514
- val finalEnd = if (charactersRemoved > 0) {
515
- (end - charactersRemoved).coerceAtLeast(0)
516
- } else {
517
- end
518
- }
639
+ val finalEnd =
640
+ if (charactersRemoved > 0) {
641
+ (end - charactersRemoved).coerceAtLeast(0)
642
+ } else {
643
+ end
644
+ }
519
645
 
520
646
  val finalStart = start.coerceAtLeast(0).coerceAtMost(finalEnd)
521
647
  selection?.onSelection(finalStart, finalEnd)
@@ -524,12 +650,6 @@ class EnrichedTextInputView : AppCompatEditText {
524
650
  return true
525
651
  }
526
652
 
527
- private fun addSpanWatcher(watcher: EnrichedSpanWatcher) {
528
- val spannable = text as Spannable
529
- spannable.setSpan(watcher, 0, spannable.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
530
- spanWatcher = watcher
531
- }
532
-
533
653
  fun verifyAndToggleStyle(name: String) {
534
654
  val isValid = verifyStyle(name)
535
655
  if (!isValid) return
@@ -537,14 +657,23 @@ class EnrichedTextInputView : AppCompatEditText {
537
657
  toggleStyle(name)
538
658
  }
539
659
 
540
- fun addLink(start: Int, end: Int, text: String, url: String) {
660
+ fun addLink(
661
+ start: Int,
662
+ end: Int,
663
+ text: String,
664
+ url: String,
665
+ ) {
541
666
  val isValid = verifyStyle(EnrichedSpans.LINK)
542
667
  if (!isValid) return
543
668
 
544
669
  parametrizedStyles?.setLinkSpan(start, end, text, url)
545
670
  }
546
671
 
547
- fun addImage(src: String, width: Float, height: Float) {
672
+ fun addImage(
673
+ src: String,
674
+ width: Float,
675
+ height: Float,
676
+ ) {
548
677
  val isValid = verifyStyle(EnrichedSpans.IMAGE)
549
678
  if (!isValid) return
550
679
 
@@ -559,13 +688,31 @@ class EnrichedTextInputView : AppCompatEditText {
559
688
  parametrizedStyles?.startMention(indicator)
560
689
  }
561
690
 
562
- fun addMention(indicator: String, text: String, attributes: Map<String, String>) {
691
+ fun addMention(
692
+ indicator: String,
693
+ text: String,
694
+ attributes: Map<String, String>,
695
+ ) {
563
696
  val isValid = verifyStyle(EnrichedSpans.MENTION)
564
697
  if (!isValid) return
565
698
 
566
699
  parametrizedStyles?.setMentionSpan(text, indicator, attributes)
567
700
  }
568
701
 
702
+ fun requestHTML(requestId: Int) {
703
+ val html =
704
+ try {
705
+ EnrichedParser.toHtmlWithDefault(text)
706
+ } catch (e: Exception) {
707
+ null
708
+ }
709
+
710
+ val reactContext = context as ReactContext
711
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
712
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
713
+ dispatcher?.dispatchEvent(OnRequestHtmlResultEvent(surfaceId, id, requestId, html, experimentalSynchronousEvents))
714
+ }
715
+
569
716
  // Sometimes setting up style triggers many changes in sequence
570
717
  // Eg. removing conflicting styles -> changing text -> applying spans
571
718
  // In such scenario we want to prevent from handling side effects (eg. onTextChanged)
@@ -578,9 +725,83 @@ class EnrichedTextInputView : AppCompatEditText {
578
725
  }
579
726
  }
580
727
 
728
+ private fun forceScrollToSelection() {
729
+ val textLayout = layout ?: return
730
+ val cursorOffset = selectionStart
731
+ if (cursorOffset <= 0) return
732
+
733
+ val selectedLineIndex = textLayout.getLineForOffset(cursorOffset)
734
+ val selectedLineTop = textLayout.getLineTop(selectedLineIndex)
735
+ val selectedLineBottom = textLayout.getLineBottom(selectedLineIndex)
736
+ val visibleTextHeight = height - paddingTop - paddingBottom
737
+
738
+ if (visibleTextHeight <= 0) return
739
+
740
+ val visibleTop = scrollY
741
+ val visibleBottom = scrollY + visibleTextHeight
742
+ var targetScrollY = scrollY
743
+
744
+ if (selectedLineTop < visibleTop) {
745
+ targetScrollY = selectedLineTop
746
+ } else if (selectedLineBottom > visibleBottom) {
747
+ targetScrollY = selectedLineBottom - visibleTextHeight
748
+ }
749
+
750
+ val maxScrollY = (textLayout.height - visibleTextHeight).coerceAtLeast(0)
751
+ targetScrollY = targetScrollY.coerceIn(0, maxScrollY)
752
+ scrollTo(scrollX, targetScrollY)
753
+ }
754
+
755
+ private fun reApplyHtmlStyleForSpans(
756
+ previousHtmlStyle: HtmlStyle,
757
+ nextHtmlStyle: HtmlStyle,
758
+ ) {
759
+ val shouldRemoveBoldSpanFromH1Span = !previousHtmlStyle.h1Bold && nextHtmlStyle.h1Bold
760
+ val shouldRemoveBoldSpanFromH2Span = !previousHtmlStyle.h2Bold && nextHtmlStyle.h2Bold
761
+ val shouldRemoveBoldSpanFromH3Span = !previousHtmlStyle.h3Bold && nextHtmlStyle.h3Bold
762
+
763
+ val spannable = text as? Spannable ?: return
764
+ if (spannable.isEmpty()) return
765
+
766
+ var shouldEmitStateChange = false
767
+
768
+ runAsATransaction {
769
+ val spans = spannable.getSpans(0, spannable.length, EnrichedSpan::class.java)
770
+ for (span in spans) {
771
+ if (!span.dependsOnHtmlStyle) continue
772
+
773
+ val start = spannable.getSpanStart(span)
774
+ val end = spannable.getSpanEnd(span)
775
+ val flags = spannable.getSpanFlags(span)
776
+
777
+ if (start == -1 || end == -1) continue
778
+
779
+ if ((span is EnrichedH1Span && shouldRemoveBoldSpanFromH1Span) || (span is EnrichedH2Span && shouldRemoveBoldSpanFromH2Span) ||
780
+ (span is EnrichedH3Span && shouldRemoveBoldSpanFromH3Span)
781
+ ) {
782
+ val isRemoved = removeStyle(EnrichedSpans.BOLD, start, end)
783
+ if (isRemoved) shouldEmitStateChange = true
784
+ }
785
+
786
+ spannable.removeSpan(span)
787
+ val newSpan = span.rebuildWithStyle(htmlStyle)
788
+ spannable.setSpan(newSpan, start, end, flags)
789
+ }
790
+
791
+ if (shouldEmitStateChange) {
792
+ selection?.validateStyles()
793
+ }
794
+ }
795
+ layoutManager.invalidateLayout()
796
+ forceScrollToSelection()
797
+ }
798
+
581
799
  override fun onAttachedToWindow() {
582
800
  super.onAttachedToWindow()
583
801
 
802
+ // https://github.com/facebook/react-native/blob/36df97f500aa0aa8031098caf7526db358b6ddc1/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt#L946
803
+ super.setTextIsSelectable(true)
804
+
584
805
  if (autoFocus && !didAttachToWindow) {
585
806
  requestFocusProgrammatically()
586
807
  }
@@ -2,7 +2,9 @@ package com.swmansion.enriched
2
2
 
3
3
  import com.facebook.react.bridge.Arguments
4
4
 
5
- class EnrichedTextInputViewLayoutManager(private val view: EnrichedTextInputView) {
5
+ class EnrichedTextInputViewLayoutManager(
6
+ private val view: EnrichedTextInputView,
7
+ ) {
6
8
  private var forceHeightRecalculationCounter: Int = 0
7
9
 
8
10
  fun invalidateLayout() {