react-native-enriched 0.2.1 → 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 (156) hide show
  1. package/README.md +15 -12
  2. package/android/build.gradle +77 -72
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +18 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +6 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +146 -0
  6. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +140 -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 +245 -116
  12. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
  13. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +162 -53
  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 +20 -10
  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 +1 -2
  29. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +21 -8
  30. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +5 -4
  31. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +7 -5
  32. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +5 -4
  33. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +5 -4
  34. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +5 -4
  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 +29 -17
  39. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +5 -4
  40. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +5 -4
  41. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +7 -7
  42. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +11 -14
  43. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +15 -14
  44. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +167 -71
  45. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +5 -4
  46. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +5 -4
  47. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +8 -8
  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 +1 -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 +78 -21
  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 +86 -26
  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 +128 -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/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +21 -1
  73. package/ios/EnrichedTextInputView.h +1 -1
  74. package/ios/EnrichedTextInputView.mm +381 -49
  75. package/ios/config/InputConfig.h +18 -0
  76. package/ios/config/InputConfig.mm +118 -8
  77. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +146 -0
  78. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +140 -0
  79. package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  80. package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
  81. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +74 -0
  82. package/ios/inputParser/InputParser.mm +83 -10
  83. package/ios/{attachments → interfaces}/ImageAttachment.mm +3 -1
  84. package/ios/interfaces/LinkRegexConfig.h +19 -0
  85. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  86. package/ios/{utils → interfaces}/MentionStyleProps.mm +2 -2
  87. package/ios/{utils → interfaces}/StyleHeaders.h +10 -0
  88. package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
  89. package/ios/styles/BlockQuoteStyle.mm +5 -5
  90. package/ios/styles/BoldStyle.mm +21 -6
  91. package/ios/styles/CodeBlockStyle.mm +5 -5
  92. package/ios/styles/H4Style.mm +17 -0
  93. package/ios/styles/H5Style.mm +17 -0
  94. package/ios/styles/H6Style.mm +17 -0
  95. package/ios/styles/HeadingStyleBase.mm +27 -10
  96. package/ios/styles/ImageStyle.mm +5 -5
  97. package/ios/styles/InlineCodeStyle.mm +30 -19
  98. package/ios/styles/ItalicStyle.mm +5 -5
  99. package/ios/styles/LinkStyle.mm +98 -40
  100. package/ios/styles/MentionStyle.mm +4 -4
  101. package/ios/styles/OrderedListStyle.mm +5 -5
  102. package/ios/styles/StrikethroughStyle.mm +5 -5
  103. package/ios/styles/UnderlineStyle.mm +5 -5
  104. package/ios/styles/UnorderedListStyle.mm +5 -5
  105. package/ios/utils/ParagraphAttributesUtils.h +4 -0
  106. package/ios/utils/ParagraphAttributesUtils.mm +67 -0
  107. package/ios/utils/ParagraphsUtils.mm +4 -4
  108. package/lib/module/EnrichedTextInput.js +22 -1
  109. package/lib/module/EnrichedTextInput.js.map +1 -1
  110. package/lib/module/EnrichedTextInputNativeComponent.ts +138 -12
  111. package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
  112. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  113. package/lib/module/utils/regexParser.js +46 -0
  114. package/lib/module/utils/regexParser.js.map +1 -0
  115. package/lib/typescript/src/EnrichedTextInput.d.ts +23 -14
  116. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  117. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +123 -12
  118. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  119. package/lib/typescript/src/index.d.ts +1 -1
  120. package/lib/typescript/src/index.d.ts.map +1 -1
  121. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  122. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  123. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  124. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  125. package/package.json +10 -6
  126. package/src/EnrichedTextInput.tsx +51 -13
  127. package/src/EnrichedTextInputNativeComponent.ts +138 -12
  128. package/src/index.tsx +2 -0
  129. package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
  130. package/src/utils/regexParser.ts +56 -0
  131. package/lib/module/normalizeHtmlStyle.js.map +0 -1
  132. package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
  133. package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
  134. /package/ios/{utils → extensions}/ColorExtension.h +0 -0
  135. /package/ios/{utils → extensions}/ColorExtension.mm +0 -0
  136. /package/ios/{utils → extensions}/FontExtension.h +0 -0
  137. /package/ios/{utils → extensions}/FontExtension.mm +0 -0
  138. /package/ios/{utils → extensions}/LayoutManagerExtension.h +0 -0
  139. /package/ios/{utils → extensions}/LayoutManagerExtension.mm +0 -0
  140. /package/ios/{utils → extensions}/StringExtension.h +0 -0
  141. /package/ios/{utils → extensions}/StringExtension.mm +0 -0
  142. /package/ios/{utils → interfaces}/BaseStyleProtocol.h +0 -0
  143. /package/ios/{attachments → interfaces}/ImageAttachment.h +0 -0
  144. /package/ios/{utils → interfaces}/ImageData.h +0 -0
  145. /package/ios/{utils → interfaces}/ImageData.mm +0 -0
  146. /package/ios/{utils → interfaces}/LinkData.h +0 -0
  147. /package/ios/{utils → interfaces}/LinkData.mm +0 -0
  148. /package/ios/{attachments → interfaces}/MediaAttachment.h +0 -0
  149. /package/ios/{attachments → interfaces}/MediaAttachment.mm +0 -0
  150. /package/ios/{utils → interfaces}/MentionParams.h +0 -0
  151. /package/ios/{utils → interfaces}/MentionParams.mm +0 -0
  152. /package/ios/{utils → interfaces}/MentionStyleProps.h +0 -0
  153. /package/ios/{utils → interfaces}/StylePair.h +0 -0
  154. /package/ios/{utils → interfaces}/StylePair.mm +0 -0
  155. /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
  156. /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
@@ -16,6 +16,13 @@
16
16
  #import <folly/dynamic.h>
17
17
  #import <react/utils/ManagedObjectWrapper.h>
18
18
 
19
+ #define GET_STYLE_STATE(TYPE_ENUM) \
20
+ { \
21
+ .isActive = [self isStyleActive:TYPE_ENUM], \
22
+ .isBlocking = [self isStyle:TYPE_ENUM activeInMap:blockingStyles], \
23
+ .isConflicting = [self isStyle:TYPE_ENUM activeInMap:conflictingStyles] \
24
+ }
25
+
19
26
  using namespace facebook::react;
20
27
 
21
28
  @interface EnrichedTextInputView () <RCTEnrichedTextInputViewViewProtocol,
@@ -27,6 +34,7 @@ using namespace facebook::react;
27
34
  EnrichedTextInputViewShadowNode::ConcreteState::Shared _state;
28
35
  int _componentViewHeightUpdateCounter;
29
36
  NSMutableSet<NSNumber *> *_activeStyles;
37
+ NSMutableSet<NSNumber *> *_blockedStyles;
30
38
  LinkData *_recentlyActiveLinkData;
31
39
  NSRange _recentlyActiveLinkRange;
32
40
  NSString *_recentInputString;
@@ -37,6 +45,7 @@ using namespace facebook::react;
37
45
  UILabel *_placeholderLabel;
38
46
  UIColor *_placeholderColor;
39
47
  BOOL _emitFocusBlur;
48
+ BOOL _emitTextChange;
40
49
  }
41
50
 
42
51
  // MARK: - Component utils
@@ -72,6 +81,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
72
81
  - (void)setDefaults {
73
82
  _componentViewHeightUpdateCounter = 0;
74
83
  _activeStyles = [[NSMutableSet alloc] init];
84
+ _blockedStyles = [[NSMutableSet alloc] init];
75
85
  _recentlyActiveLinkRange = NSMakeRange(0, 0);
76
86
  _recentlyActiveMentionRange = NSMakeRange(0, 0);
77
87
  recentlyChangedRange = NSMakeRange(0, 0);
@@ -80,6 +90,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
80
90
  _emitHtml = NO;
81
91
  blockEmitting = NO;
82
92
  _emitFocusBlur = YES;
93
+ _emitTextChange = NO;
83
94
 
84
95
  defaultTypingAttributes =
85
96
  [[NSMutableDictionary<NSAttributedStringKey, id> alloc] init];
@@ -98,6 +109,9 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
98
109
  @([H1Style getStyleType]) : [[H1Style alloc] initWithInput:self],
99
110
  @([H2Style getStyleType]) : [[H2Style alloc] initWithInput:self],
100
111
  @([H3Style getStyleType]) : [[H3Style alloc] initWithInput:self],
112
+ @([H4Style getStyleType]) : [[H4Style alloc] initWithInput:self],
113
+ @([H5Style getStyleType]) : [[H5Style alloc] initWithInput:self],
114
+ @([H6Style getStyleType]) : [[H6Style alloc] initWithInput:self],
101
115
  @([UnorderedListStyle getStyleType]) :
102
116
  [[UnorderedListStyle alloc] initWithInput:self],
103
117
  @([OrderedListStyle getStyleType]) :
@@ -124,39 +138,73 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
124
138
  @[ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]) ],
125
139
  @([H1Style getStyleType]) : @[
126
140
  @([H2Style getStyleType]), @([H3Style getStyleType]),
127
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
128
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
141
+ @([H4Style getStyleType]), @([H5Style getStyleType]),
142
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
143
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
144
+ @([CodeBlockStyle getStyleType])
129
145
  ],
130
146
  @([H2Style getStyleType]) : @[
131
147
  @([H1Style getStyleType]), @([H3Style getStyleType]),
132
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
133
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
148
+ @([H4Style getStyleType]), @([H5Style getStyleType]),
149
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
150
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
151
+ @([CodeBlockStyle getStyleType])
134
152
  ],
135
153
  @([H3Style getStyleType]) : @[
136
154
  @([H1Style getStyleType]), @([H2Style getStyleType]),
137
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
138
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
155
+ @([H4Style getStyleType]), @([H5Style getStyleType]),
156
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
157
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
158
+ @([CodeBlockStyle getStyleType])
159
+ ],
160
+ @([H4Style getStyleType]) : @[
161
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
162
+ @([H3Style getStyleType]), @([H5Style getStyleType]),
163
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
164
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
165
+ @([CodeBlockStyle getStyleType])
166
+ ],
167
+ @([H5Style getStyleType]) : @[
168
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
169
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
170
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
171
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
172
+ @([CodeBlockStyle getStyleType])
173
+ ],
174
+ @([H6Style getStyleType]) : @[
175
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
176
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
177
+ @([H5Style getStyleType]), @([UnorderedListStyle getStyleType]),
178
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
179
+ @([CodeBlockStyle getStyleType])
139
180
  ],
140
181
  @([UnorderedListStyle getStyleType]) : @[
141
182
  @([H1Style getStyleType]), @([H2Style getStyleType]),
142
- @([H3Style getStyleType]), @([OrderedListStyle getStyleType]),
143
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
183
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
184
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
185
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
186
+ @([CodeBlockStyle getStyleType])
144
187
  ],
145
188
  @([OrderedListStyle getStyleType]) : @[
146
189
  @([H1Style getStyleType]), @([H2Style getStyleType]),
147
- @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]),
148
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
190
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
191
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
192
+ @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
193
+ @([CodeBlockStyle getStyleType])
149
194
  ],
150
195
  @([BlockQuoteStyle getStyleType]) : @[
151
196
  @([H1Style getStyleType]), @([H2Style getStyleType]),
152
- @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]),
153
- @([OrderedListStyle getStyleType]), @([CodeBlockStyle getStyleType])
197
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
198
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
199
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
200
+ @([CodeBlockStyle getStyleType])
154
201
  ],
155
202
  @([CodeBlockStyle getStyleType]) : @[
156
203
  @([H1Style getStyleType]), @([H2Style getStyleType]),
157
- @([H3Style getStyleType]), @([BoldStyle getStyleType]),
158
- @([ItalicStyle getStyleType]), @([UnderlineStyle getStyleType]),
159
- @([StrikethroughStyle getStyleType]),
204
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
205
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
206
+ @([BoldStyle getStyleType]), @([ItalicStyle getStyleType]),
207
+ @([UnderlineStyle getStyleType]), @([StrikethroughStyle getStyleType]),
160
208
  @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
161
209
  @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]),
162
210
  @([MentionStyle getStyleType]), @([LinkStyle getStyleType])
@@ -165,7 +213,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
165
213
  @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ]
166
214
  };
167
215
 
168
- blockingStyles = @{
216
+ blockingStyles = [@{
169
217
  @([BoldStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
170
218
  @([ItalicStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
171
219
  @([UnderlineStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
@@ -180,12 +228,15 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
180
228
  @([H1Style getStyleType]) : @[],
181
229
  @([H2Style getStyleType]) : @[],
182
230
  @([H3Style getStyleType]) : @[],
231
+ @([H4Style getStyleType]) : @[],
232
+ @([H5Style getStyleType]) : @[],
233
+ @([H6Style getStyleType]) : @[],
183
234
  @([UnorderedListStyle getStyleType]) : @[],
184
235
  @([OrderedListStyle getStyleType]) : @[],
185
236
  @([BlockQuoteStyle getStyleType]) : @[],
186
237
  @([CodeBlockStyle getStyleType]) : @[],
187
238
  @([ImageStyle getStyleType]) : @[ @([InlineCodeStyle getStyleType]) ]
188
- };
239
+ } mutableCopy];
189
240
 
190
241
  parser = [[InputParser alloc] initWithInput:self];
191
242
  }
@@ -198,6 +249,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
198
249
  textView.delegate = self;
199
250
  textView.input = self;
200
251
  textView.layoutManager.input = self;
252
+ textView.adjustsFontForContentSizeCategory = YES;
201
253
  }
202
254
 
203
255
  - (void)setupPlaceholderLabel {
@@ -216,6 +268,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
216
268
  _placeholderLabel.lineBreakMode = NSLineBreakByTruncatingTail;
217
269
  _placeholderLabel.text = @"";
218
270
  _placeholderLabel.hidden = YES;
271
+ _placeholderLabel.adjustsFontForContentSizeCategory = YES;
219
272
  }
220
273
 
221
274
  // MARK: - Props
@@ -292,6 +345,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
292
345
 
293
346
  if (newViewProps.htmlStyle.h1.bold != oldViewProps.htmlStyle.h1.bold) {
294
347
  [newConfig setH1Bold:newViewProps.htmlStyle.h1.bold];
348
+
349
+ // Update style blocks for bold
350
+ newViewProps.htmlStyle.h1.bold ? [self addStyleBlock:H1 to:Bold]
351
+ : [self removeStyleBlock:H1 from:Bold];
352
+
295
353
  stylePropChanged = YES;
296
354
  }
297
355
 
@@ -303,6 +361,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
303
361
 
304
362
  if (newViewProps.htmlStyle.h2.bold != oldViewProps.htmlStyle.h2.bold) {
305
363
  [newConfig setH2Bold:newViewProps.htmlStyle.h2.bold];
364
+
365
+ // Update style blocks for bold
366
+ newViewProps.htmlStyle.h2.bold ? [self addStyleBlock:H2 to:Bold]
367
+ : [self removeStyleBlock:H2 from:Bold];
368
+
306
369
  stylePropChanged = YES;
307
370
  }
308
371
 
@@ -314,6 +377,59 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
314
377
 
315
378
  if (newViewProps.htmlStyle.h3.bold != oldViewProps.htmlStyle.h3.bold) {
316
379
  [newConfig setH3Bold:newViewProps.htmlStyle.h3.bold];
380
+
381
+ // Update style blocks for bold
382
+ newViewProps.htmlStyle.h3.bold ? [self addStyleBlock:H3 to:Bold]
383
+ : [self removeStyleBlock:H3 from:Bold];
384
+
385
+ stylePropChanged = YES;
386
+ }
387
+
388
+ if (newViewProps.htmlStyle.h4.fontSize !=
389
+ oldViewProps.htmlStyle.h4.fontSize) {
390
+ [newConfig setH4FontSize:newViewProps.htmlStyle.h4.fontSize];
391
+ stylePropChanged = YES;
392
+ }
393
+
394
+ if (newViewProps.htmlStyle.h4.bold != oldViewProps.htmlStyle.h4.bold) {
395
+ [newConfig setH4Bold:newViewProps.htmlStyle.h4.bold];
396
+
397
+ // Update style blocks for bold
398
+ newViewProps.htmlStyle.h4.bold ? [self addStyleBlock:H4 to:Bold]
399
+ : [self removeStyleBlock:H4 from:Bold];
400
+
401
+ stylePropChanged = YES;
402
+ }
403
+
404
+ if (newViewProps.htmlStyle.h5.fontSize !=
405
+ oldViewProps.htmlStyle.h5.fontSize) {
406
+ [newConfig setH5FontSize:newViewProps.htmlStyle.h5.fontSize];
407
+ stylePropChanged = YES;
408
+ }
409
+
410
+ if (newViewProps.htmlStyle.h5.bold != oldViewProps.htmlStyle.h5.bold) {
411
+ [newConfig setH5Bold:newViewProps.htmlStyle.h5.bold];
412
+
413
+ // Update style blocks for bold
414
+ newViewProps.htmlStyle.h5.bold ? [self addStyleBlock:H5 to:Bold]
415
+ : [self removeStyleBlock:H5 from:Bold];
416
+
417
+ stylePropChanged = YES;
418
+ }
419
+
420
+ if (newViewProps.htmlStyle.h6.fontSize !=
421
+ oldViewProps.htmlStyle.h6.fontSize) {
422
+ [newConfig setH6FontSize:newViewProps.htmlStyle.h6.fontSize];
423
+ stylePropChanged = YES;
424
+ }
425
+
426
+ if (newViewProps.htmlStyle.h6.bold != oldViewProps.htmlStyle.h6.bold) {
427
+ [newConfig setH6Bold:newViewProps.htmlStyle.h6.bold];
428
+
429
+ // Update style blocks for bold
430
+ newViewProps.htmlStyle.h6.bold ? [self addStyleBlock:H6 to:Bold]
431
+ : [self removeStyleBlock:H6 from:Bold];
432
+
317
433
  stylePropChanged = YES;
318
434
  }
319
435
 
@@ -539,6 +655,8 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
539
655
  NSString *currentHtml = [parser
540
656
  parseToHtmlFromRange:NSMakeRange(0,
541
657
  textView.textStorage.string.length)];
658
+ // we want to preserve the selection between props changes
659
+ NSRange prevSelectedRange = textView.selectedRange;
542
660
 
543
661
  // now set the new config
544
662
  config = newConfig;
@@ -566,6 +684,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
566
684
  defaultTypingAttributes[NSParagraphStyleAttributeName] =
567
685
  [[NSParagraphStyle alloc] init];
568
686
  textView.typingAttributes = defaultTypingAttributes;
687
+ textView.selectedRange = prevSelectedRange;
569
688
 
570
689
  // update the placeholder as well
571
690
  [self refreshPlaceholderLabelStyles];
@@ -591,6 +710,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
591
710
  // we've got some seemingly proper html
592
711
  [parser replaceWholeFromHtml:initiallyProcessedHtml];
593
712
  }
713
+ textView.selectedRange = NSRange(textView.textStorage.string.length, 0);
594
714
  }
595
715
 
596
716
  // placeholderTextColor
@@ -631,6 +751,15 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
631
751
  [config setMentionIndicators:newIndicators];
632
752
  }
633
753
 
754
+ // linkRegex
755
+ LinkRegexConfig *oldRegexConfig =
756
+ [[LinkRegexConfig alloc] initWithLinkRegexProp:oldViewProps.linkRegex];
757
+ LinkRegexConfig *newRegexConfig =
758
+ [[LinkRegexConfig alloc] initWithLinkRegexProp:newViewProps.linkRegex];
759
+ if (![newRegexConfig isEqualToConfig:oldRegexConfig]) {
760
+ [config setLinkRegexConfig:newRegexConfig];
761
+ }
762
+
634
763
  // selection color sets both selection and cursor on iOS (just as in RN)
635
764
  if (newViewProps.selectionColor != oldViewProps.selectionColor) {
636
765
  if (isColorMeaningful(newViewProps.selectionColor)) {
@@ -668,6 +797,9 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
668
797
  // isOnChangeHtmlSet
669
798
  _emitHtml = newViewProps.isOnChangeHtmlSet;
670
799
 
800
+ // isOnChangeTextSet
801
+ _emitTextChange = newViewProps.isOnChangeTextSet;
802
+
671
803
  [super updateProps:props oldProps:oldProps];
672
804
  // run the changes callback
673
805
  [self anyTextMayHaveBeenModified];
@@ -782,6 +914,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
782
914
  // emitted
783
915
  NSMutableSet *newActiveStyles = [_activeStyles mutableCopy];
784
916
 
917
+ // currently blocked styles are subject to change (e.g. bold being blocked by
918
+ // headings might change in reaction to prop change) so they also are kept
919
+ // separately
920
+ NSMutableSet *newBlockedStyles = [_blockedStyles mutableCopy];
921
+
785
922
  // data for onLinkDetected event
786
923
  LinkData *detectedLinkData;
787
924
  NSRange detectedLinkRange = NSMakeRange(0, 0);
@@ -792,8 +929,14 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
792
929
 
793
930
  for (NSNumber *type in stylesDict) {
794
931
  id<BaseStyleProtocol> style = stylesDict[type];
932
+
795
933
  BOOL wasActive = [newActiveStyles containsObject:type];
796
934
  BOOL isActive = [style detectStyle:textView.selectedRange];
935
+
936
+ BOOL wasBlocked = [newBlockedStyles containsObject:type];
937
+ BOOL isBlocked = [self isStyle:(StyleType)[type integerValue]
938
+ activeInMap:blockingStyles];
939
+
797
940
  if (wasActive != isActive) {
798
941
  updateNeeded = YES;
799
942
  if (isActive) {
@@ -803,6 +946,16 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
803
946
  }
804
947
  }
805
948
 
949
+ // blocked state change for a style also needs an update
950
+ if (wasBlocked != isBlocked) {
951
+ updateNeeded = YES;
952
+ if (isBlocked) {
953
+ [newBlockedStyles addObject:type];
954
+ } else {
955
+ [newBlockedStyles removeObject:type];
956
+ }
957
+ }
958
+
806
959
  // onLinkDetected event
807
960
  if (isActive && [type intValue] == [LinkStyle getStyleType]) {
808
961
  // get the link data
@@ -867,35 +1020,51 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
867
1020
  if (updateNeeded) {
868
1021
  auto emitter = [self getEventEmitter];
869
1022
  if (emitter != nullptr) {
870
- // update activeStyles only if emitter is available
1023
+ // update activeStyles and blockedStyles only if emitter is available
871
1024
  _activeStyles = newActiveStyles;
872
-
873
- emitter->onChangeState({
874
- .isBold = [_activeStyles containsObject:@([BoldStyle getStyleType])],
875
- .isItalic =
876
- [_activeStyles containsObject:@([ItalicStyle getStyleType])],
877
- .isUnderline =
878
- [_activeStyles containsObject:@([UnderlineStyle getStyleType])],
879
- .isStrikeThrough =
880
- [_activeStyles containsObject:@([StrikethroughStyle getStyleType])],
881
- .isInlineCode =
882
- [_activeStyles containsObject:@([InlineCodeStyle getStyleType])],
883
- .isLink = [_activeStyles containsObject:@([LinkStyle getStyleType])],
884
- .isMention =
885
- [_activeStyles containsObject:@([MentionStyle getStyleType])],
886
- .isH1 = [_activeStyles containsObject:@([H1Style getStyleType])],
887
- .isH2 = [_activeStyles containsObject:@([H2Style getStyleType])],
888
- .isH3 = [_activeStyles containsObject:@([H3Style getStyleType])],
889
- .isUnorderedList =
890
- [_activeStyles containsObject:@([UnorderedListStyle getStyleType])],
891
- .isOrderedList =
892
- [_activeStyles containsObject:@([OrderedListStyle getStyleType])],
893
- .isBlockQuote =
894
- [_activeStyles containsObject:@([BlockQuoteStyle getStyleType])],
895
- .isCodeBlock =
896
- [_activeStyles containsObject:@([CodeBlockStyle getStyleType])],
897
- .isImage = [_activeStyles containsObject:@([ImageStyle getStyleType])],
1025
+ _blockedStyles = newBlockedStyles;
1026
+
1027
+ emitter->onChangeStateDeprecated({
1028
+ .isBold = [self isStyleActive:[BoldStyle getStyleType]],
1029
+ .isItalic = [self isStyleActive:[ItalicStyle getStyleType]],
1030
+ .isUnderline = [self isStyleActive:[UnderlineStyle getStyleType]],
1031
+ .isStrikeThrough =
1032
+ [self isStyleActive:[StrikethroughStyle getStyleType]],
1033
+ .isInlineCode = [self isStyleActive:[InlineCodeStyle getStyleType]],
1034
+ .isLink = [self isStyleActive:[LinkStyle getStyleType]],
1035
+ .isMention = [self isStyleActive:[MentionStyle getStyleType]],
1036
+ .isH1 = [self isStyleActive:[H1Style getStyleType]],
1037
+ .isH2 = [self isStyleActive:[H2Style getStyleType]],
1038
+ .isH3 = [self isStyleActive:[H3Style getStyleType]],
1039
+ .isH4 = [self isStyleActive:[H4Style getStyleType]],
1040
+ .isH5 = [self isStyleActive:[H5Style getStyleType]],
1041
+ .isH6 = [self isStyleActive:[H6Style getStyleType]],
1042
+ .isUnorderedList =
1043
+ [self isStyleActive:[UnorderedListStyle getStyleType]],
1044
+ .isOrderedList = [self isStyleActive:[OrderedListStyle getStyleType]],
1045
+ .isBlockQuote = [self isStyleActive:[BlockQuoteStyle getStyleType]],
1046
+ .isCodeBlock = [self isStyleActive:[CodeBlockStyle getStyleType]],
1047
+ .isImage = [self isStyleActive:[ImageStyle getStyleType]],
898
1048
  });
1049
+ emitter->onChangeState(
1050
+ {.bold = GET_STYLE_STATE([BoldStyle getStyleType]),
1051
+ .italic = GET_STYLE_STATE([ItalicStyle getStyleType]),
1052
+ .underline = GET_STYLE_STATE([UnderlineStyle getStyleType]),
1053
+ .strikeThrough = GET_STYLE_STATE([StrikethroughStyle getStyleType]),
1054
+ .inlineCode = GET_STYLE_STATE([InlineCodeStyle getStyleType]),
1055
+ .link = GET_STYLE_STATE([LinkStyle getStyleType]),
1056
+ .mention = GET_STYLE_STATE([MentionStyle getStyleType]),
1057
+ .h1 = GET_STYLE_STATE([H1Style getStyleType]),
1058
+ .h2 = GET_STYLE_STATE([H2Style getStyleType]),
1059
+ .h3 = GET_STYLE_STATE([H3Style getStyleType]),
1060
+ .h4 = GET_STYLE_STATE([H4Style getStyleType]),
1061
+ .h5 = GET_STYLE_STATE([H5Style getStyleType]),
1062
+ .h6 = GET_STYLE_STATE([H6Style getStyleType]),
1063
+ .unorderedList = GET_STYLE_STATE([UnorderedListStyle getStyleType]),
1064
+ .orderedList = GET_STYLE_STATE([OrderedListStyle getStyleType]),
1065
+ .blockQuote = GET_STYLE_STATE([BlockQuoteStyle getStyleType]),
1066
+ .codeBlock = GET_STYLE_STATE([CodeBlockStyle getStyleType]),
1067
+ .image = GET_STYLE_STATE([ImageStyle getStyleType])});
899
1068
  }
900
1069
  }
901
1070
 
@@ -920,6 +1089,42 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
920
1089
  [self tryEmittingOnChangeHtmlEvent];
921
1090
  }
922
1091
 
1092
+ - (bool)isStyleActive:(StyleType)type {
1093
+ return [_activeStyles containsObject:@(type)];
1094
+ }
1095
+
1096
+ - (bool)isStyle:(StyleType)type activeInMap:(NSDictionary *)styleMap {
1097
+ NSArray *relatedStyles = styleMap[@(type)];
1098
+
1099
+ if (!relatedStyles) {
1100
+ return false;
1101
+ }
1102
+
1103
+ for (NSNumber *style in relatedStyles) {
1104
+ if ([_activeStyles containsObject:style]) {
1105
+ return true;
1106
+ }
1107
+ }
1108
+
1109
+ return false;
1110
+ }
1111
+
1112
+ - (void)addStyleBlock:(StyleType)blocking to:(StyleType)blocked {
1113
+ NSMutableArray *blocksArr = [blockingStyles[@(blocked)] mutableCopy];
1114
+ if (![blocksArr containsObject:@(blocking)]) {
1115
+ [blocksArr addObject:@(blocking)];
1116
+ blockingStyles[@(blocked)] = blocksArr;
1117
+ }
1118
+ }
1119
+
1120
+ - (void)removeStyleBlock:(StyleType)blocking from:(StyleType)blocked {
1121
+ NSMutableArray *blocksArr = [blockingStyles[@(blocked)] mutableCopy];
1122
+ if ([blocksArr containsObject:@(blocking)]) {
1123
+ [blocksArr removeObject:@(blocking)];
1124
+ blockingStyles[@(blocked)] = blocksArr;
1125
+ }
1126
+ }
1127
+
923
1128
  // MARK: - Native commands and events
924
1129
 
925
1130
  - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
@@ -960,6 +1165,12 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
960
1165
  [self toggleParagraphStyle:[H2Style getStyleType]];
961
1166
  } else if ([commandName isEqualToString:@"toggleH3"]) {
962
1167
  [self toggleParagraphStyle:[H3Style getStyleType]];
1168
+ } else if ([commandName isEqualToString:@"toggleH4"]) {
1169
+ [self toggleParagraphStyle:[H4Style getStyleType]];
1170
+ } else if ([commandName isEqualToString:@"toggleH5"]) {
1171
+ [self toggleParagraphStyle:[H5Style getStyleType]];
1172
+ } else if ([commandName isEqualToString:@"toggleH6"]) {
1173
+ [self toggleParagraphStyle:[H6Style getStyleType]];
963
1174
  } else if ([commandName isEqualToString:@"toggleUnorderedList"]) {
964
1175
  [self toggleParagraphStyle:[UnorderedListStyle getStyleType]];
965
1176
  } else if ([commandName isEqualToString:@"toggleOrderedList"]) {
@@ -974,6 +1185,10 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
974
1185
  CGFloat imgHeight = [(NSNumber *)args[2] floatValue];
975
1186
 
976
1187
  [self addImage:uri width:imgWidth height:imgHeight];
1188
+ } else if ([commandName isEqualToString:@"setSelection"]) {
1189
+ NSInteger start = [((NSNumber *)args[0]) integerValue];
1190
+ NSInteger end = [((NSNumber *)args[1]) integerValue];
1191
+ [self setCustomSelection:start end:end];
977
1192
  } else if ([commandName isEqualToString:@"requestHTML"]) {
978
1193
  NSInteger requestId = [((NSNumber *)args[0]) integerValue];
979
1194
  [self requestHTML:requestId];
@@ -1010,9 +1225,42 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1010
1225
 
1011
1226
  // set recentlyChangedRange and check for changes
1012
1227
  recentlyChangedRange = NSMakeRange(0, textView.textStorage.string.length);
1228
+ textView.selectedRange = NSRange(textView.textStorage.string.length, 0);
1013
1229
  [self anyTextMayHaveBeenModified];
1014
1230
  }
1015
1231
 
1232
+ - (void)setCustomSelection:(NSInteger)visibleStart end:(NSInteger)visibleEnd {
1233
+ NSString *text = textView.textStorage.string;
1234
+
1235
+ NSUInteger actualStart = [self getActualIndex:visibleStart text:text];
1236
+ NSUInteger actualEnd = [self getActualIndex:visibleEnd text:text];
1237
+
1238
+ textView.selectedRange = NSMakeRange(actualStart, actualEnd - actualStart);
1239
+ }
1240
+
1241
+ // Helper: Walks through the string skipping ZWSPs to find the Nth visible
1242
+ // character
1243
+ - (NSUInteger)getActualIndex:(NSInteger)visibleIndex text:(NSString *)text {
1244
+ NSUInteger currentVisibleCount = 0;
1245
+ NSUInteger actualIndex = 0;
1246
+
1247
+ while (actualIndex < text.length) {
1248
+ if (currentVisibleCount == visibleIndex) {
1249
+ return actualIndex;
1250
+ }
1251
+
1252
+ // If the current char is not a hidden space, it counts towards our visible
1253
+ // index.
1254
+ if ([text characterAtIndex:actualIndex] != 0x200B) {
1255
+ currentVisibleCount++;
1256
+ }
1257
+
1258
+ actualIndex++;
1259
+ }
1260
+
1261
+ return actualIndex;
1262
+ }
1263
+
1016
1264
  - (void)emitOnLinkDetectedEvent:(NSString *)text
1017
1265
  url:(NSString *)url
1018
1266
  range:(NSRange)range {
@@ -1091,6 +1339,13 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1091
1339
  }
1092
1340
  }
1093
1341
 
1342
+ - (void)emitOnKeyPressEvent:(NSString *)key {
1343
+ auto emitter = [self getEventEmitter];
1344
+ if (emitter != nullptr) {
1345
+ emitter->onInputKeyPress({.key = [key toCppString]});
1346
+ }
1347
+ }
1348
+
1094
1349
  // MARK: - Styles manipulation
1095
1350
 
1096
1351
  - (void)toggleRegularStyle:(StyleType)type {
@@ -1247,6 +1502,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1247
1502
  if (linkStyleClass != nullptr) {
1248
1503
  [linkStyleClass manageLinkTypingAttributes];
1249
1504
  }
1505
+ NSString *currentString = [textView.textStorage.string copy];
1250
1506
 
1251
1507
  // mention typing attribtues fix and active editing
1252
1508
  MentionStyle *mentionStyleClass =
@@ -1257,14 +1513,12 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1257
1513
  // mention editing runs if only a selection was done (no text change)
1258
1514
  // otherwise we would double-emit with a second call in the
1259
1515
  // anyTextMayHaveBeenModified method
1260
- if ([_recentInputString
1261
- isEqualToString:[textView.textStorage.string copy]]) {
1516
+ if ([_recentInputString isEqualToString:currentString]) {
1262
1517
  [mentionStyleClass manageMentionEditing];
1263
1518
  }
1264
1519
  }
1265
1520
 
1266
1521
  // typing attributes for empty lines selection reset
1267
- NSString *currentString = [textView.textStorage.string copy];
1268
1522
  if (textView.selectedRange.length == 0 &&
1269
1523
  [_recentInputString isEqualToString:currentString]) {
1270
1524
  // no string change means only a selection changed with no character changes
@@ -1337,10 +1591,21 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1337
1591
  H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
1338
1592
  H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
1339
1593
  H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
1340
- if (h1Style != nullptr && h2Style != nullptr && h3Style != nullptr) {
1594
+ H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
1595
+ H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
1596
+ H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
1597
+
1598
+ bool headingStylesDefined = h1Style != nullptr && h2Style != nullptr &&
1599
+ h3Style != nullptr && h4Style != nullptr &&
1600
+ h5Style != nullptr && h6Style != nullptr;
1601
+
1602
+ if (headingStylesDefined) {
1341
1603
  [h1Style handleImproperHeadings];
1342
1604
  [h2Style handleImproperHeadings];
1343
1605
  [h3Style handleImproperHeadings];
1606
+ [h4Style handleImproperHeadings];
1607
+ [h5Style handleImproperHeadings];
1608
+ [h6Style handleImproperHeadings];
1344
1609
  }
1345
1610
 
1346
1611
  // mentions management: removal and editing
@@ -1380,7 +1645,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1380
1645
 
1381
1646
  // emit onChangeText event
1382
1647
  auto emitter = [self getEventEmitter];
1383
- if (emitter != nullptr) {
1648
+ if (emitter != nullptr && _emitTextChange) {
1384
1649
  // set the recent input string only if the emitter is defined
1385
1650
  _recentInputString = [textView.textStorage.string copy];
1386
1651
 
@@ -1477,10 +1742,29 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1477
1742
  }
1478
1743
  }
1479
1744
 
1745
+ - (void)handleKeyPressInRange:(NSString *)text range:(NSRange)range {
1746
+ NSString *key = nil;
1747
+
1748
+ if (text.length == 0 && range.length > 0) {
1749
+ key = @"Backspace";
1750
+ } else if ([text isEqualToString:@"\n"]) {
1751
+ key = @"Enter";
1752
+ } else if ([text isEqualToString:@"\t"]) {
1753
+ key = @"Tab";
1754
+ } else if (text.length == 1) {
1755
+ key = text;
1756
+ }
1757
+
1758
+ if (key != nil) {
1759
+ [self emitOnKeyPressEvent:key];
1760
+ }
1761
+ }
1762
+
1480
1763
  - (bool)textView:(UITextView *)textView
1481
1764
  shouldChangeTextInRange:(NSRange)range
1482
1765
  replacementText:(NSString *)text {
1483
1766
  recentlyChangedRange = NSMakeRange(range.location, text.length);
1767
+ [self handleKeyPressInRange:text range:range];
1484
1768
 
1485
1769
  UnorderedListStyle *uStyle = stylesDict[@([UnorderedListStyle getStyleType])];
1486
1770
  OrderedListStyle *oStyle = stylesDict[@([OrderedListStyle getStyleType])];
@@ -1491,6 +1775,9 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1491
1775
  H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
1492
1776
  H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
1493
1777
  H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
1778
+ H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
1779
+ H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
1780
+ H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
1494
1781
 
1495
1782
  // some of the changes these checks do could interfere with later checks and
1496
1783
  // cause a crash so here I rely on short circuiting evaluation of the logical
@@ -1508,12 +1795,18 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1508
1795
  [h1Style handleNewlinesInRange:range replacementText:text] ||
1509
1796
  [h2Style handleNewlinesInRange:range replacementText:text] ||
1510
1797
  [h3Style handleNewlinesInRange:range replacementText:text] ||
1798
+ [h4Style handleNewlinesInRange:range replacementText:text] ||
1799
+ [h5Style handleNewlinesInRange:range replacementText:text] ||
1800
+ [h6Style handleNewlinesInRange:range replacementText:text] ||
1511
1801
  [ZeroWidthSpaceUtils handleBackspaceInRange:range
1512
1802
  replacementText:text
1513
1803
  input:self] ||
1514
1804
  [ParagraphAttributesUtils handleBackspaceInRange:range
1515
1805
  replacementText:text
1516
1806
  input:self] ||
1807
+ [ParagraphAttributesUtils handleResetTypingAttributesOnBackspace:range
1808
+ replacementText:text
1809
+ input:self] ||
1517
1810
  // CRITICAL: This callback HAS TO be always evaluated last.
1518
1811
  //
1519
1812
  // This function is the "Generic Fallback": if no specific style claims
@@ -1558,6 +1851,45 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1558
1851
  [self anyTextMayHaveBeenModified];
1559
1852
  }
1560
1853
 
1854
+ /**
1855
+ * Handles iOS Dynamic Type changes (User changing font size in System
1856
+ * Settings).
1857
+ *
1858
+ * Unlike Android, iOS Views do not automatically rescale existing
1859
+ * NSAttributedStrings when the system font size changes. The text attributes
1860
+ * are static once drawn.
1861
+ *
1862
+ * This method detects the change and performs a "Hard Refresh" of the content.
1863
+ */
1864
+ - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
1865
+ [super traitCollectionDidChange:previousTraitCollection];
1866
+
1867
+ if (previousTraitCollection.preferredContentSizeCategory !=
1868
+ self.traitCollection.preferredContentSizeCategory) {
1869
+ [config invalidateFonts];
1870
+
1871
+ NSMutableDictionary *newTypingAttrs = [defaultTypingAttributes mutableCopy];
1872
+ newTypingAttrs[NSFontAttributeName] = [config primaryFont];
1873
+
1874
+ defaultTypingAttributes = newTypingAttrs;
1875
+ textView.typingAttributes = defaultTypingAttributes;
1876
+
1877
+ [self refreshPlaceholderLabelStyles];
1878
+
1879
+ NSRange prevSelectedRange = textView.selectedRange;
1880
+
1881
+ NSString *currentHtml = [parser
1882
+ parseToHtmlFromRange:NSMakeRange(0,
1883
+ textView.textStorage.string.length)];
1884
+ NSString *initiallyProcessedHtml =
1885
+ [parser initiallyProcessHtml:currentHtml];
1886
+ [parser replaceWholeFromHtml:initiallyProcessedHtml];
1887
+
1888
+ textView.selectedRange = prevSelectedRange;
1889
+ [self anyTextMayHaveBeenModified];
1890
+ }
1891
+ }
1892
+
1561
1893
  // MARK: - Media attachments delegate
1562
1894
 
1563
1895
  - (void)mediaAttachmentDidUpdate:(NSTextAttachment *)attachment {