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
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  `EnrichedTextInput`, the rich text editor component is an uncontrolled input. This means that it doesn't use any state or props to store its value, but instead directly interacts with the underlying platform-specific components. Thanks to this, the component is really performant and simple to use while offering complex and advanced features no other solution has.
15
15
 
16
- <https://github.com/user-attachments/assets/4778d541-d967-47e7-8013-6f7c436bcb95>
16
+ ![react-native-enriched-demo](https://github.com/user-attachments/assets/a2c968c0-9b85-492f-ac71-af64ef231fbf)
17
17
 
18
18
  Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues.
19
19
  We can help you build your next dream product –
@@ -40,7 +40,7 @@ We can help you build your next dream product –
40
40
  ## Prerequisites
41
41
 
42
42
  - `react-native-enriched` currently supports only Android and iOS platforms
43
- - It works only with [the React Native New Architecture (Fabric)](https://reactnative.dev/architecture/landing-page) and supports following React Native releases: `0.79`, `0.80`, `0.81` and `0.82`
43
+ - It works only with [the React Native New Architecture (Fabric)](https://reactnative.dev/architecture/landing-page) and supports following React Native releases: `0.79`, `0.80`, `0.81`, `0.82` and `0.83`
44
44
 
45
45
  ## Installation
46
46
 
@@ -101,7 +101,7 @@ export default function App() {
101
101
  <View style={styles.container}>
102
102
  <EnrichedTextInput
103
103
  ref={ref}
104
- onChangeState={e => setStylesState(e.nativeEvent)}
104
+ onChangeState={(e) => setStylesState(e.nativeEvent)}
105
105
  style={styles.input}
106
106
  />
107
107
  <Button
@@ -127,13 +127,16 @@ const styles = StyleSheet.create({
127
127
  backgroundColor: 'lightgray',
128
128
  },
129
129
  });
130
-
131
130
  ```
132
131
 
133
132
  Summary of what happens here:
134
133
 
135
134
  1. Any methods imperatively called on the input to e.g. toggle some style must be used through a `ref` of `EnrichedTextInputInstance` type. Here, `toggleBold` method that is called on the button press calls `ref.current?.toggleBold()`, which toggles the bold styling within the current selection.
136
- 2. All the active styles info is emitted by `onChangeState` event. Set up a proper callback that accepts a `NativeSyntheticEvent<OnChangeStateEvent>` argument, and you can access an object with boolean properties indicating which styles are active, such as `isBold` in the example. Here, this info is stored in a React state and used to change colors on the button.
135
+ 2. All style state information is emitted by the `onChangeState` event. Set up a proper callback that accepts a `NativeSyntheticEvent<OnChangeStateEvent>` argument. The event payload provides a nested object for each style (e.g., `bold`, `italic`), containing three properties to guide your UI logic:
136
+
137
+ - `isActive`: Indicates if the style is currently applied (highlight the button).
138
+ - `isBlocking`: Indicates if the style is blocked by another active style (disable the button).
139
+ - `isConflicting`: Indicates if the style is in conflict with another active style.
137
140
 
138
141
  ## Non Parametrized Styles
139
142
 
@@ -144,9 +147,7 @@ Supported styles:
144
147
  - underline
145
148
  - strikethrough
146
149
  - inline code
147
- - H1 heading
148
- - H2 heading
149
- - H3 heading
150
+ - H1, H2, H3, H4, H5 and H6 headings
150
151
  - codeblock
151
152
  - blockquote
152
153
  - ordered list
@@ -158,8 +159,8 @@ Each call toggles the style within the current text selection. We can still divi
158
159
 
159
160
  - Inline styles (bold, italic, underline, strikethrough, inline code). They are being toggled on exactly the character range that is currently selected. When toggling the style with just the cursor in place (no selection), the style is ready to be used and will be applied to the next characters that the user inputs.
160
161
 
161
- - Paragraph styles (headings, codeblock, blockquote, lists). They are being toggled on the entire paragraph that the selection is in. By paragraph we mean a part of the text between two newlines (enters) or the text's beginning/ending.
162
- If the selection spans more than one paragraph, logically more of them will be affected by the toggle. Toggling these styles with the cursor in place (no selection) makes changes to the very paragraph the cursor is in.
162
+ - Paragraph styles (headings, codeblock, blockquote, lists). They are being toggled on the entire paragraph that the selection is in. By paragraph, we mean a part of the text between two newlines (enters) or the text's beginning/ending.
163
+ If the selection spans more than one paragraph, logically more of them will be affected by the toggle. Toggling these styles with the cursor in place (no selection) makes changes to the very paragraph the cursor is in.
163
164
 
164
165
  ## Links
165
166
 
@@ -167,7 +168,8 @@ The links are here, just like in any other editor, a piece of text with a URL at
167
168
 
168
169
  ### Automatic links detection
169
170
 
170
- `react-native-enriched` automatically detects words that appear to be some URLs and makes them links. Currently, we are using pretty naive approach to detect whether text can be treated as a link or not. On iOS it's a pretty simple regex, on Android we are using URL regex provided by the system.
171
+ `react-native-enriched` automatically detects words that appear to be some URLs and makes them links.
172
+ You can customize this behavior by providing your own regular expression via [linkRegex](docs/API_REFERENCE.md#linkregex) prop.
171
173
 
172
174
  ### Applying links manually
173
175
 
@@ -226,10 +228,11 @@ You can find some examples in the [usage section](#usage) or in the example app.
226
228
  - [onChangeSelection](docs/API_REFERENCE.md#onchangeselection) - returns all the data needed for working with selections (as of now it's mainly useful for [links](#links)).
227
229
  - [onLinkDetected](docs/API_REFERENCE.md#onlinkdetected) - returns link's detailed info whenever user selection is near one.
228
230
  - [onMentionDetected](docs/API_REFERENCE.md#onmentiondetected) - returns mention's detailed info whenever user selection is near one.
231
+ - [onKeyPress](docs/API_REFERENCE.md#onkeypress) - emits whenever a key is pressed. Follows react-native TextInput's onKeyPress event [spec](https://reactnative.dev/docs/textinput#onkeypress).
229
232
 
230
233
  ## Customizing \<EnrichedTextInput /> styles
231
234
 
232
- `react-native-enriched` allows customizing styles of the `<EnrichedTextInput />` component. See [htmlStyle](docs/API_REFERENCE.md#htmlstyle) prop.
235
+ `react-native-enriched` allows customizing styles of the `<EnrichedTextInput />` component. See [htmlStyle](docs/API_REFERENCE.md#htmlstyle) prop.
233
236
 
234
237
  ## API Reference
235
238
 
@@ -238,16 +241,11 @@ See the [API Reference](docs/API_REFERENCE.md) for a detailed overview of all th
238
241
  ## Known limitations
239
242
 
240
243
  - Only one level of lists is supported. We currently do not support nested lists.
241
- - Inline images are supported only on Android.
242
- - Codeblocks are supported only on Android.
243
244
  - iOS headings can't have the same `fontSize` in their config as input's `fontSize`. Doing so results in incorrect headings behavior.
244
245
 
245
246
  ## Future Plans
246
247
 
247
- - Adding Codeblocks and Inline Images to iOS input.
248
- - Making some optimizations around `onChangeHtml` event, maybe some imperative API to get the HTML output.
249
248
  - Creating `EnrichedText` text component that supports our HTML output format with all additional interactions like pressing links or mentions.
250
- - Adding API for custom link detection regex.
251
249
  - Web library implementation via `react-native-web`.
252
250
 
253
251
  ## Contributing
@@ -259,6 +257,7 @@ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
259
257
  `react-native-enriched` library is licensed under [The MIT License](./LICENSE).
260
258
 
261
259
  ---
260
+
262
261
  Built by [Software Mansion](https://swmansion.com/) and sponsored by [Filament](https://filament.dm/).
263
262
 
264
263
  [<img width="128" height="69" alt="Software Mansion Logo" src="https://github.com/user-attachments/assets/f0e18471-a7aa-4e80-86ac-87686a86fe56" />](https://swmansion.com/)
@@ -1,18 +1,21 @@
1
1
  buildscript {
2
- ext.getExtOrDefault = {name ->
3
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['EnrichedTextInput_' + name]
4
- }
5
-
6
- repositories {
7
- google()
8
- mavenCentral()
9
- }
10
-
11
- dependencies {
12
- classpath "com.android.tools.build:gradle:8.7.2"
13
- // noinspection DifferentKotlinGradleVersion
14
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
15
- }
2
+ ext.getExtOrDefault = {name ->
3
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['EnrichedTextInput_' + name]
4
+ }
5
+
6
+ repositories {
7
+ google()
8
+ mavenCentral()
9
+ gradlePluginPortal()
10
+ }
11
+
12
+ dependencies {
13
+ classpath "com.android.tools.build:gradle:8.7.2"
14
+ // noinspection DifferentKotlinGradleVersion
15
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
16
+ classpath "org.jlleitschuh.gradle:ktlint-gradle:14.0.1"
17
+ classpath 'com.diffplug.spotless:spotless-plugin-gradle:8.1.0'
18
+ }
16
19
  }
17
20
 
18
21
 
@@ -21,81 +24,83 @@ apply plugin: "kotlin-android"
21
24
 
22
25
  apply plugin: "com.facebook.react"
23
26
 
27
+ apply from: "lint.gradle"
28
+
24
29
  def getExtOrIntegerDefault(name) {
25
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["EnrichedTextInput_" + name]).toInteger()
30
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["EnrichedTextInput_" + name]).toInteger()
26
31
  }
27
32
 
28
33
  def supportsNamespace() {
29
- def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
30
- def major = parsed[0].toInteger()
31
- def minor = parsed[1].toInteger()
34
+ def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
35
+ def major = parsed[0].toInteger()
36
+ def minor = parsed[1].toInteger()
32
37
 
33
- // Namespace support was added in 7.3.0
34
- return (major == 7 && minor >= 3) || major >= 8
38
+ // Namespace support was added in 7.3.0
39
+ return (major == 7 && minor >= 3) || major >= 8
35
40
  }
36
41
 
37
42
  android {
38
- if (supportsNamespace()) {
39
- namespace "com.swmansion.enriched"
40
-
41
- sourceSets {
42
- main {
43
- manifest.srcFile "src/main/AndroidManifestNew.xml"
44
- }
45
- }
46
- }
47
-
48
- compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
49
-
50
- defaultConfig {
51
- minSdkVersion getExtOrIntegerDefault("minSdkVersion")
52
- targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
53
- }
54
-
55
- buildFeatures {
56
- buildConfig true
57
- }
58
-
59
- buildTypes {
60
- release {
61
- minifyEnabled false
62
- }
63
- }
64
-
65
- lintOptions {
66
- disable "GradleCompatible"
67
- }
68
-
69
- compileOptions {
70
- sourceCompatibility JavaVersion.VERSION_1_8
71
- targetCompatibility JavaVersion.VERSION_1_8
72
- }
73
-
74
- sourceSets {
75
- main {
76
- java.srcDirs += [
77
- "generated/java",
78
- "generated/jni"
79
- ]
80
- }
81
- }
43
+ if (supportsNamespace()) {
44
+ namespace "com.swmansion.enriched"
45
+
46
+ sourceSets {
47
+ main {
48
+ manifest.srcFile "src/main/AndroidManifestNew.xml"
49
+ }
50
+ }
51
+ }
52
+
53
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
54
+
55
+ defaultConfig {
56
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
57
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
58
+ }
59
+
60
+ buildFeatures {
61
+ buildConfig true
62
+ }
63
+
64
+ buildTypes {
65
+ release {
66
+ minifyEnabled false
67
+ }
68
+ }
69
+
70
+ lintOptions {
71
+ disable "GradleCompatible"
72
+ }
73
+
74
+ compileOptions {
75
+ sourceCompatibility JavaVersion.VERSION_1_8
76
+ targetCompatibility JavaVersion.VERSION_1_8
77
+ }
78
+
79
+ sourceSets {
80
+ main {
81
+ java.srcDirs += [
82
+ "generated/java",
83
+ "generated/jni"
84
+ ]
85
+ }
86
+ }
82
87
  }
83
88
 
84
89
  repositories {
85
- mavenCentral()
86
- google()
90
+ mavenCentral()
91
+ google()
87
92
  }
88
93
 
89
94
  def kotlin_version = getExtOrDefault("kotlinVersion")
90
95
 
91
96
  dependencies {
92
- implementation "com.facebook.react:react-android"
93
- implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
94
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
97
+ implementation "com.facebook.react:react-android"
98
+ implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
99
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
95
100
  }
96
101
 
97
102
  react {
98
- jsRootDir = file("../src/")
99
- libraryName = "EnrichedTextInputView"
100
- codegenJavaPackageName = "com.swmansion.enriched"
103
+ jsRootDir = file("../src/")
104
+ libraryName = "EnrichedTextInputView"
105
+ codegenJavaPackageName = "com.swmansion.enriched"
101
106
  }
@@ -58,6 +58,9 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
58
58
  case "scrollEnabled":
59
59
  mViewManager.setScrollEnabled(view, value == null ? false : (boolean) value);
60
60
  break;
61
+ case "linkRegex":
62
+ mViewManager.setLinkRegex(view, (ReadableMap) value);
63
+ break;
61
64
  case "color":
62
65
  mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext()));
63
66
  break;
@@ -76,6 +79,9 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
76
79
  case "isOnChangeHtmlSet":
77
80
  mViewManager.setIsOnChangeHtmlSet(view, value == null ? false : (boolean) value);
78
81
  break;
82
+ case "isOnChangeTextSet":
83
+ mViewManager.setIsOnChangeTextSet(view, value == null ? false : (boolean) value);
84
+ break;
79
85
  case "androidExperimentalSynchronousEvents":
80
86
  mViewManager.setAndroidExperimentalSynchronousEvents(view, value == null ? false : (boolean) value);
81
87
  break;
@@ -96,6 +102,9 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
96
102
  case "setValue":
97
103
  mViewManager.setValue(view, args.getString(0));
98
104
  break;
105
+ case "setSelection":
106
+ mViewManager.setSelection(view, args.getInt(0), args.getInt(1));
107
+ break;
99
108
  case "toggleBold":
100
109
  mViewManager.toggleBold(view);
101
110
  break;
@@ -120,6 +129,15 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
120
129
  case "toggleH3":
121
130
  mViewManager.toggleH3(view);
122
131
  break;
132
+ case "toggleH4":
133
+ mViewManager.toggleH4(view);
134
+ break;
135
+ case "toggleH5":
136
+ mViewManager.toggleH5(view);
137
+ break;
138
+ case "toggleH6":
139
+ mViewManager.toggleH6(view);
140
+ break;
123
141
  case "toggleCodeBlock":
124
142
  mViewManager.toggleCodeBlock(view);
125
143
  break;
@@ -144,6 +162,9 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
144
162
  case "addMention":
145
163
  mViewManager.addMention(view, args.getString(0), args.getString(1), args.getString(2));
146
164
  break;
165
+ case "requestHTML":
166
+ mViewManager.requestHTML(view, args.getInt(0));
167
+ break;
147
168
  }
148
169
  }
149
170
  }
@@ -27,16 +27,19 @@ public interface EnrichedTextInputViewManagerInterface<T extends View> extends V
27
27
  void setAutoCapitalize(T view, @Nullable String value);
28
28
  void setHtmlStyle(T view, @Nullable ReadableMap value);
29
29
  void setScrollEnabled(T view, boolean value);
30
+ void setLinkRegex(T view, @Nullable ReadableMap value);
30
31
  void setColor(T view, @Nullable Integer value);
31
32
  void setFontSize(T view, float value);
32
33
  void setFontFamily(T view, @Nullable String value);
33
34
  void setFontWeight(T view, @Nullable String value);
34
35
  void setFontStyle(T view, @Nullable String value);
35
36
  void setIsOnChangeHtmlSet(T view, boolean value);
37
+ void setIsOnChangeTextSet(T view, boolean value);
36
38
  void setAndroidExperimentalSynchronousEvents(T view, boolean value);
37
39
  void focus(T view);
38
40
  void blur(T view);
39
41
  void setValue(T view, String text);
42
+ void setSelection(T view, int start, int end);
40
43
  void toggleBold(T view);
41
44
  void toggleItalic(T view);
42
45
  void toggleUnderline(T view);
@@ -45,6 +48,9 @@ public interface EnrichedTextInputViewManagerInterface<T extends View> extends V
45
48
  void toggleH1(T view);
46
49
  void toggleH2(T view);
47
50
  void toggleH3(T view);
51
+ void toggleH4(T view);
52
+ void toggleH5(T view);
53
+ void toggleH6(T view);
48
54
  void toggleCodeBlock(T view);
49
55
  void toggleBlockQuote(T view);
50
56
  void toggleOrderedList(T view);
@@ -53,4 +59,5 @@ public interface EnrichedTextInputViewManagerInterface<T extends View> extends V
53
59
  void addImage(T view, String uri, float width, float height);
54
60
  void startMention(T view, String indicator);
55
61
  void addMention(T view, String indicator, String text, String payload);
62
+ void requestHTML(T view, int requestId);
56
63
  }
@@ -51,6 +51,140 @@ void EnrichedTextInputViewEventEmitter::onChangeHtml(OnChangeHtml event) const {
51
51
 
52
52
  void EnrichedTextInputViewEventEmitter::onChangeState(OnChangeState event) const {
53
53
  dispatchEvent("changeState", [event=std::move(event)](jsi::Runtime &runtime) {
54
+ auto payload = jsi::Object(runtime);
55
+ {
56
+ auto bold = jsi::Object(runtime);
57
+ bold.setProperty(runtime, "isActive", event.bold.isActive);
58
+ bold.setProperty(runtime, "isConflicting", event.bold.isConflicting);
59
+ bold.setProperty(runtime, "isBlocking", event.bold.isBlocking);
60
+ payload.setProperty(runtime, "bold", bold);
61
+ }
62
+ {
63
+ auto italic = jsi::Object(runtime);
64
+ italic.setProperty(runtime, "isActive", event.italic.isActive);
65
+ italic.setProperty(runtime, "isConflicting", event.italic.isConflicting);
66
+ italic.setProperty(runtime, "isBlocking", event.italic.isBlocking);
67
+ payload.setProperty(runtime, "italic", italic);
68
+ }
69
+ {
70
+ auto underline = jsi::Object(runtime);
71
+ underline.setProperty(runtime, "isActive", event.underline.isActive);
72
+ underline.setProperty(runtime, "isConflicting", event.underline.isConflicting);
73
+ underline.setProperty(runtime, "isBlocking", event.underline.isBlocking);
74
+ payload.setProperty(runtime, "underline", underline);
75
+ }
76
+ {
77
+ auto strikeThrough = jsi::Object(runtime);
78
+ strikeThrough.setProperty(runtime, "isActive", event.strikeThrough.isActive);
79
+ strikeThrough.setProperty(runtime, "isConflicting", event.strikeThrough.isConflicting);
80
+ strikeThrough.setProperty(runtime, "isBlocking", event.strikeThrough.isBlocking);
81
+ payload.setProperty(runtime, "strikeThrough", strikeThrough);
82
+ }
83
+ {
84
+ auto inlineCode = jsi::Object(runtime);
85
+ inlineCode.setProperty(runtime, "isActive", event.inlineCode.isActive);
86
+ inlineCode.setProperty(runtime, "isConflicting", event.inlineCode.isConflicting);
87
+ inlineCode.setProperty(runtime, "isBlocking", event.inlineCode.isBlocking);
88
+ payload.setProperty(runtime, "inlineCode", inlineCode);
89
+ }
90
+ {
91
+ auto h1 = jsi::Object(runtime);
92
+ h1.setProperty(runtime, "isActive", event.h1.isActive);
93
+ h1.setProperty(runtime, "isConflicting", event.h1.isConflicting);
94
+ h1.setProperty(runtime, "isBlocking", event.h1.isBlocking);
95
+ payload.setProperty(runtime, "h1", h1);
96
+ }
97
+ {
98
+ auto h2 = jsi::Object(runtime);
99
+ h2.setProperty(runtime, "isActive", event.h2.isActive);
100
+ h2.setProperty(runtime, "isConflicting", event.h2.isConflicting);
101
+ h2.setProperty(runtime, "isBlocking", event.h2.isBlocking);
102
+ payload.setProperty(runtime, "h2", h2);
103
+ }
104
+ {
105
+ auto h3 = jsi::Object(runtime);
106
+ h3.setProperty(runtime, "isActive", event.h3.isActive);
107
+ h3.setProperty(runtime, "isConflicting", event.h3.isConflicting);
108
+ h3.setProperty(runtime, "isBlocking", event.h3.isBlocking);
109
+ payload.setProperty(runtime, "h3", h3);
110
+ }
111
+ {
112
+ auto h4 = jsi::Object(runtime);
113
+ h4.setProperty(runtime, "isActive", event.h4.isActive);
114
+ h4.setProperty(runtime, "isConflicting", event.h4.isConflicting);
115
+ h4.setProperty(runtime, "isBlocking", event.h4.isBlocking);
116
+ payload.setProperty(runtime, "h4", h4);
117
+ }
118
+ {
119
+ auto h5 = jsi::Object(runtime);
120
+ h5.setProperty(runtime, "isActive", event.h5.isActive);
121
+ h5.setProperty(runtime, "isConflicting", event.h5.isConflicting);
122
+ h5.setProperty(runtime, "isBlocking", event.h5.isBlocking);
123
+ payload.setProperty(runtime, "h5", h5);
124
+ }
125
+ {
126
+ auto h6 = jsi::Object(runtime);
127
+ h6.setProperty(runtime, "isActive", event.h6.isActive);
128
+ h6.setProperty(runtime, "isConflicting", event.h6.isConflicting);
129
+ h6.setProperty(runtime, "isBlocking", event.h6.isBlocking);
130
+ payload.setProperty(runtime, "h6", h6);
131
+ }
132
+ {
133
+ auto codeBlock = jsi::Object(runtime);
134
+ codeBlock.setProperty(runtime, "isActive", event.codeBlock.isActive);
135
+ codeBlock.setProperty(runtime, "isConflicting", event.codeBlock.isConflicting);
136
+ codeBlock.setProperty(runtime, "isBlocking", event.codeBlock.isBlocking);
137
+ payload.setProperty(runtime, "codeBlock", codeBlock);
138
+ }
139
+ {
140
+ auto blockQuote = jsi::Object(runtime);
141
+ blockQuote.setProperty(runtime, "isActive", event.blockQuote.isActive);
142
+ blockQuote.setProperty(runtime, "isConflicting", event.blockQuote.isConflicting);
143
+ blockQuote.setProperty(runtime, "isBlocking", event.blockQuote.isBlocking);
144
+ payload.setProperty(runtime, "blockQuote", blockQuote);
145
+ }
146
+ {
147
+ auto orderedList = jsi::Object(runtime);
148
+ orderedList.setProperty(runtime, "isActive", event.orderedList.isActive);
149
+ orderedList.setProperty(runtime, "isConflicting", event.orderedList.isConflicting);
150
+ orderedList.setProperty(runtime, "isBlocking", event.orderedList.isBlocking);
151
+ payload.setProperty(runtime, "orderedList", orderedList);
152
+ }
153
+ {
154
+ auto unorderedList = jsi::Object(runtime);
155
+ unorderedList.setProperty(runtime, "isActive", event.unorderedList.isActive);
156
+ unorderedList.setProperty(runtime, "isConflicting", event.unorderedList.isConflicting);
157
+ unorderedList.setProperty(runtime, "isBlocking", event.unorderedList.isBlocking);
158
+ payload.setProperty(runtime, "unorderedList", unorderedList);
159
+ }
160
+ {
161
+ auto link = jsi::Object(runtime);
162
+ link.setProperty(runtime, "isActive", event.link.isActive);
163
+ link.setProperty(runtime, "isConflicting", event.link.isConflicting);
164
+ link.setProperty(runtime, "isBlocking", event.link.isBlocking);
165
+ payload.setProperty(runtime, "link", link);
166
+ }
167
+ {
168
+ auto image = jsi::Object(runtime);
169
+ image.setProperty(runtime, "isActive", event.image.isActive);
170
+ image.setProperty(runtime, "isConflicting", event.image.isConflicting);
171
+ image.setProperty(runtime, "isBlocking", event.image.isBlocking);
172
+ payload.setProperty(runtime, "image", image);
173
+ }
174
+ {
175
+ auto mention = jsi::Object(runtime);
176
+ mention.setProperty(runtime, "isActive", event.mention.isActive);
177
+ mention.setProperty(runtime, "isConflicting", event.mention.isConflicting);
178
+ mention.setProperty(runtime, "isBlocking", event.mention.isBlocking);
179
+ payload.setProperty(runtime, "mention", mention);
180
+ }
181
+ return payload;
182
+ });
183
+ }
184
+
185
+
186
+ void EnrichedTextInputViewEventEmitter::onChangeStateDeprecated(OnChangeStateDeprecated event) const {
187
+ dispatchEvent("changeStateDeprecated", [event=std::move(event)](jsi::Runtime &runtime) {
54
188
  auto payload = jsi::Object(runtime);
55
189
  payload.setProperty(runtime, "isBold", event.isBold);
56
190
  payload.setProperty(runtime, "isItalic", event.isItalic);
@@ -60,6 +194,9 @@ payload.setProperty(runtime, "isInlineCode", event.isInlineCode);
60
194
  payload.setProperty(runtime, "isH1", event.isH1);
61
195
  payload.setProperty(runtime, "isH2", event.isH2);
62
196
  payload.setProperty(runtime, "isH3", event.isH3);
197
+ payload.setProperty(runtime, "isH4", event.isH4);
198
+ payload.setProperty(runtime, "isH5", event.isH5);
199
+ payload.setProperty(runtime, "isH6", event.isH6);
63
200
  payload.setProperty(runtime, "isCodeBlock", event.isCodeBlock);
64
201
  payload.setProperty(runtime, "isBlockQuote", event.isBlockQuote);
65
202
  payload.setProperty(runtime, "isOrderedList", event.isOrderedList);
@@ -115,4 +252,23 @@ payload.setProperty(runtime, "text", event.text);
115
252
  });
116
253
  }
117
254
 
255
+
256
+ void EnrichedTextInputViewEventEmitter::onRequestHtmlResult(OnRequestHtmlResult event) const {
257
+ dispatchEvent("requestHtmlResult", [event=std::move(event)](jsi::Runtime &runtime) {
258
+ auto payload = jsi::Object(runtime);
259
+ payload.setProperty(runtime, "requestId", event.requestId);
260
+ payload.setProperty(runtime, "html", jsi::valueFromDynamic(runtime, event.html));
261
+ return payload;
262
+ });
263
+ }
264
+
265
+
266
+ void EnrichedTextInputViewEventEmitter::onInputKeyPress(OnInputKeyPress event) const {
267
+ dispatchEvent("inputKeyPress", [event=std::move(event)](jsi::Runtime &runtime) {
268
+ auto payload = jsi::Object(runtime);
269
+ payload.setProperty(runtime, "key", event.key);
270
+ return payload;
271
+ });
272
+ }
273
+
118
274
  } // namespace facebook::react