react-native-enriched 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -2
- package/ReactNativeEnriched.podspec +5 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +12 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +4 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +149 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +146 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.cpp +16 -1
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.h +46 -0
- package/android/src/main/java/com/swmansion/enriched/common/GumboNormalizer.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnorderedListSpan.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +166 -20
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/MeasurementStore.kt +19 -2
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnContextMenuItemPressEvent.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedLineHeightSpan.kt +44 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +18 -12
- package/android/src/main/new_arch/CMakeLists.txt +9 -13
- package/android/src/main/new_arch/GumboNormalizerJni.cpp +14 -0
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +2 -21
- package/cpp/CMakeLists.txt +50 -0
- package/cpp/GumboParser/GumboParser.h +34043 -0
- package/cpp/README.md +59 -0
- package/cpp/parser/GumboNormalizer.c +915 -0
- package/cpp/parser/GumboParser.cpp +16 -0
- package/cpp/parser/GumboParser.hpp +23 -0
- package/cpp/tests/GumboParserTest.cpp +457 -0
- package/ios/EnrichedTextInputView.h +2 -0
- package/ios/EnrichedTextInputView.mm +152 -2
- package/ios/config/InputConfig.h +3 -0
- package/ios/config/InputConfig.mm +15 -0
- package/ios/extensions/LayoutManagerExtension.mm +34 -11
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +149 -0
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +146 -0
- package/ios/generated/ReactNativeEnrichedSpec/Props.cpp +16 -1
- package/ios/generated/ReactNativeEnrichedSpec/Props.h +46 -0
- package/ios/generated/ReactNativeEnrichedSpec/RCTComponentViewHelpers.h +29 -0
- package/ios/inputParser/InputParser.mm +27 -0
- package/ios/inputTextView/InputTextView.mm +3 -3
- package/lib/module/EnrichedTextInput.js +43 -30
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/spec/EnrichedTextInputNativeComponent.ts +118 -22
- package/lib/typescript/src/EnrichedTextInput.d.ts +24 -6
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts +111 -21
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/EnrichedTextInput.tsx +79 -40
- package/src/index.tsx +0 -1
- package/src/spec/EnrichedTextInputNativeComponent.ts +118 -22
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<img src="https://github.com/user-attachments/assets/
|
|
1
|
+
<img src="https://github.com/user-attachments/assets/c8ba03bc-4ea8-48f4-9566-02ebac0c19d3" alt="react-native-enriched by Software Mansion" width="100%">
|
|
2
2
|
|
|
3
3
|
# react-native-enriched
|
|
4
4
|
|
|
@@ -30,6 +30,7 @@ We can help you build your next dream product –
|
|
|
30
30
|
- [Inline Images](#inline-images)
|
|
31
31
|
- [Style Detection](#style-detection)
|
|
32
32
|
- [Other Events](#other-events)
|
|
33
|
+
- [Context Menu Items](#context-menu-items)
|
|
33
34
|
- [Customizing \<EnrichedTextInput /> styles](#customizing-enrichedtextinput--styles)
|
|
34
35
|
- [API Reference](#api-reference)
|
|
35
36
|
- [Known limitations](#known-limitations)
|
|
@@ -40,7 +41,8 @@ We can help you build your next dream product –
|
|
|
40
41
|
## Prerequisites
|
|
41
42
|
|
|
42
43
|
- `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.
|
|
44
|
+
- It works only with [the React Native New Architecture (Fabric)](https://reactnative.dev/architecture/landing-page) and supports following React Native releases: `0.81`, `0.82`, `0.83` and `0.84`.
|
|
45
|
+
- If you would like to use `react-native-enriched` in React Native `0.79` or `0.80` use `react-native-enriched 0.4.x`.
|
|
44
46
|
|
|
45
47
|
## Installation
|
|
46
48
|
|
|
@@ -232,6 +234,29 @@ You can find some examples in the [usage section](#usage) or in the example app.
|
|
|
232
234
|
- [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).
|
|
233
235
|
- [onPasteImages](docs/API_REFERENCE.md#onpasteimages) - returns an array of images details whenever an image/GIF is pasted into the input.
|
|
234
236
|
|
|
237
|
+
## Context Menu Items
|
|
238
|
+
|
|
239
|
+
> **Note:** This feature is currently supported on Android and iOS 16+.
|
|
240
|
+
|
|
241
|
+
You can extend the native text editing menu with custom items using the [contextMenuItems](docs/API_REFERENCE.md#contextmenuitems) prop. Each item has a `text` (title), `visible` flag and an `onPress` callback. Items appear in the specified order, before the system actions.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
<EnrichedTextInput
|
|
245
|
+
ref={ref}
|
|
246
|
+
contextMenuItems={[
|
|
247
|
+
{
|
|
248
|
+
text: 'Paste Link',
|
|
249
|
+
onPress: ({ text, selection, styleState }) => {
|
|
250
|
+
if (!styleState.link.isBlocking) {
|
|
251
|
+
ref.current?.setLink(selection.start, selection.end, text, url);
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
visible: true,
|
|
255
|
+
},
|
|
256
|
+
]}
|
|
257
|
+
/>
|
|
258
|
+
```
|
|
259
|
+
|
|
235
260
|
## Customizing \<EnrichedTextInput /> styles
|
|
236
261
|
|
|
237
262
|
`react-native-enriched` allows customizing styles of the `<EnrichedTextInput />` component. See [htmlStyle](docs/API_REFERENCE.md#htmlstyle) prop.
|
|
@@ -13,8 +13,12 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.platforms = { :ios => min_ios_version_supported }
|
|
14
14
|
s.source = { :git => "https://github.com/software-mansion/react-native-enriched.git", :tag => "#{s.version}" }
|
|
15
15
|
|
|
16
|
-
s.source_files = "ios/**/*.{h,m,mm,cpp}"
|
|
16
|
+
s.source_files = ["ios/**/*.{h,m,mm,cpp}", "cpp/**/*.{h,hpp,c,cpp}"]
|
|
17
|
+
s.exclude_files = ["cpp/tests/**"]
|
|
17
18
|
s.private_header_files = "ios/**/*.h"
|
|
19
|
+
s.pod_target_xcconfig = {
|
|
20
|
+
'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}/cpp/parser" "${PODS_TARGET_SRCROOT}/cpp/GumboParser"'
|
|
21
|
+
}
|
|
18
22
|
|
|
19
23
|
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
20
24
|
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
@@ -61,12 +61,18 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
|
|
|
61
61
|
case "linkRegex":
|
|
62
62
|
mViewManager.setLinkRegex(view, (ReadableMap) value);
|
|
63
63
|
break;
|
|
64
|
+
case "contextMenuItems":
|
|
65
|
+
mViewManager.setContextMenuItems(view, (ReadableArray) value);
|
|
66
|
+
break;
|
|
64
67
|
case "color":
|
|
65
68
|
mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
|
66
69
|
break;
|
|
67
70
|
case "fontSize":
|
|
68
71
|
mViewManager.setFontSize(view, value == null ? 0f : ((Double) value).floatValue());
|
|
69
72
|
break;
|
|
73
|
+
case "lineHeight":
|
|
74
|
+
mViewManager.setLineHeight(view, value == null ? 0f : ((Double) value).floatValue());
|
|
75
|
+
break;
|
|
70
76
|
case "fontFamily":
|
|
71
77
|
mViewManager.setFontFamily(view, value == null ? null : (String) value);
|
|
72
78
|
break;
|
|
@@ -85,6 +91,9 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
|
|
|
85
91
|
case "androidExperimentalSynchronousEvents":
|
|
86
92
|
mViewManager.setAndroidExperimentalSynchronousEvents(view, value == null ? false : (boolean) value);
|
|
87
93
|
break;
|
|
94
|
+
case "useHtmlNormalizer":
|
|
95
|
+
mViewManager.setUseHtmlNormalizer(view, value == null ? false : (boolean) value);
|
|
96
|
+
break;
|
|
88
97
|
default:
|
|
89
98
|
super.setProperty(view, propName, value);
|
|
90
99
|
}
|
|
@@ -156,6 +165,9 @@ public class EnrichedTextInputViewManagerDelegate<T extends View, U extends Base
|
|
|
156
165
|
case "addLink":
|
|
157
166
|
mViewManager.addLink(view, args.getInt(0), args.getInt(1), args.getString(2), args.getString(3));
|
|
158
167
|
break;
|
|
168
|
+
case "removeLink":
|
|
169
|
+
mViewManager.removeLink(view, args.getInt(0), args.getInt(1));
|
|
170
|
+
break;
|
|
159
171
|
case "addImage":
|
|
160
172
|
mViewManager.addImage(view, args.getString(0), (float) args.getDouble(1), (float) args.getDouble(2));
|
|
161
173
|
break;
|
|
@@ -28,14 +28,17 @@ public interface EnrichedTextInputViewManagerInterface<T extends View> extends V
|
|
|
28
28
|
void setHtmlStyle(T view, @Nullable ReadableMap value);
|
|
29
29
|
void setScrollEnabled(T view, boolean value);
|
|
30
30
|
void setLinkRegex(T view, @Nullable ReadableMap value);
|
|
31
|
+
void setContextMenuItems(T view, @Nullable ReadableArray value);
|
|
31
32
|
void setColor(T view, @Nullable Integer value);
|
|
32
33
|
void setFontSize(T view, float value);
|
|
34
|
+
void setLineHeight(T view, float value);
|
|
33
35
|
void setFontFamily(T view, @Nullable String value);
|
|
34
36
|
void setFontWeight(T view, @Nullable String value);
|
|
35
37
|
void setFontStyle(T view, @Nullable String value);
|
|
36
38
|
void setIsOnChangeHtmlSet(T view, boolean value);
|
|
37
39
|
void setIsOnChangeTextSet(T view, boolean value);
|
|
38
40
|
void setAndroidExperimentalSynchronousEvents(T view, boolean value);
|
|
41
|
+
void setUseHtmlNormalizer(T view, boolean value);
|
|
39
42
|
void focus(T view);
|
|
40
43
|
void blur(T view);
|
|
41
44
|
void setValue(T view, String text);
|
|
@@ -57,6 +60,7 @@ public interface EnrichedTextInputViewManagerInterface<T extends View> extends V
|
|
|
57
60
|
void toggleUnorderedList(T view);
|
|
58
61
|
void toggleCheckboxList(T view, boolean checked);
|
|
59
62
|
void addLink(T view, int start, int end, String text, String url);
|
|
63
|
+
void removeLink(T view, int start, int end);
|
|
60
64
|
void addImage(T view, String uri, float width, float height);
|
|
61
65
|
void startMention(T view, String indicator);
|
|
62
66
|
void addMention(T view, String indicator, String text, String payload);
|
package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp
CHANGED
|
@@ -273,4 +273,153 @@ imagesObject.setProperty(runtime, "height", imagesValue.height);
|
|
|
273
273
|
});
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
+
|
|
277
|
+
void EnrichedTextInputViewEventEmitter::onContextMenuItemPress(OnContextMenuItemPress event) const {
|
|
278
|
+
dispatchEvent("contextMenuItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
279
|
+
auto payload = jsi::Object(runtime);
|
|
280
|
+
payload.setProperty(runtime, "itemText", event.itemText);
|
|
281
|
+
payload.setProperty(runtime, "selectedText", event.selectedText);
|
|
282
|
+
payload.setProperty(runtime, "selectionStart", event.selectionStart);
|
|
283
|
+
payload.setProperty(runtime, "selectionEnd", event.selectionEnd);
|
|
284
|
+
{
|
|
285
|
+
auto styleState = jsi::Object(runtime);
|
|
286
|
+
{
|
|
287
|
+
auto bold = jsi::Object(runtime);
|
|
288
|
+
bold.setProperty(runtime, "isActive", event.styleState.bold.isActive);
|
|
289
|
+
bold.setProperty(runtime, "isConflicting", event.styleState.bold.isConflicting);
|
|
290
|
+
bold.setProperty(runtime, "isBlocking", event.styleState.bold.isBlocking);
|
|
291
|
+
styleState.setProperty(runtime, "bold", bold);
|
|
292
|
+
}
|
|
293
|
+
{
|
|
294
|
+
auto italic = jsi::Object(runtime);
|
|
295
|
+
italic.setProperty(runtime, "isActive", event.styleState.italic.isActive);
|
|
296
|
+
italic.setProperty(runtime, "isConflicting", event.styleState.italic.isConflicting);
|
|
297
|
+
italic.setProperty(runtime, "isBlocking", event.styleState.italic.isBlocking);
|
|
298
|
+
styleState.setProperty(runtime, "italic", italic);
|
|
299
|
+
}
|
|
300
|
+
{
|
|
301
|
+
auto underline = jsi::Object(runtime);
|
|
302
|
+
underline.setProperty(runtime, "isActive", event.styleState.underline.isActive);
|
|
303
|
+
underline.setProperty(runtime, "isConflicting", event.styleState.underline.isConflicting);
|
|
304
|
+
underline.setProperty(runtime, "isBlocking", event.styleState.underline.isBlocking);
|
|
305
|
+
styleState.setProperty(runtime, "underline", underline);
|
|
306
|
+
}
|
|
307
|
+
{
|
|
308
|
+
auto strikeThrough = jsi::Object(runtime);
|
|
309
|
+
strikeThrough.setProperty(runtime, "isActive", event.styleState.strikeThrough.isActive);
|
|
310
|
+
strikeThrough.setProperty(runtime, "isConflicting", event.styleState.strikeThrough.isConflicting);
|
|
311
|
+
strikeThrough.setProperty(runtime, "isBlocking", event.styleState.strikeThrough.isBlocking);
|
|
312
|
+
styleState.setProperty(runtime, "strikeThrough", strikeThrough);
|
|
313
|
+
}
|
|
314
|
+
{
|
|
315
|
+
auto inlineCode = jsi::Object(runtime);
|
|
316
|
+
inlineCode.setProperty(runtime, "isActive", event.styleState.inlineCode.isActive);
|
|
317
|
+
inlineCode.setProperty(runtime, "isConflicting", event.styleState.inlineCode.isConflicting);
|
|
318
|
+
inlineCode.setProperty(runtime, "isBlocking", event.styleState.inlineCode.isBlocking);
|
|
319
|
+
styleState.setProperty(runtime, "inlineCode", inlineCode);
|
|
320
|
+
}
|
|
321
|
+
{
|
|
322
|
+
auto h1 = jsi::Object(runtime);
|
|
323
|
+
h1.setProperty(runtime, "isActive", event.styleState.h1.isActive);
|
|
324
|
+
h1.setProperty(runtime, "isConflicting", event.styleState.h1.isConflicting);
|
|
325
|
+
h1.setProperty(runtime, "isBlocking", event.styleState.h1.isBlocking);
|
|
326
|
+
styleState.setProperty(runtime, "h1", h1);
|
|
327
|
+
}
|
|
328
|
+
{
|
|
329
|
+
auto h2 = jsi::Object(runtime);
|
|
330
|
+
h2.setProperty(runtime, "isActive", event.styleState.h2.isActive);
|
|
331
|
+
h2.setProperty(runtime, "isConflicting", event.styleState.h2.isConflicting);
|
|
332
|
+
h2.setProperty(runtime, "isBlocking", event.styleState.h2.isBlocking);
|
|
333
|
+
styleState.setProperty(runtime, "h2", h2);
|
|
334
|
+
}
|
|
335
|
+
{
|
|
336
|
+
auto h3 = jsi::Object(runtime);
|
|
337
|
+
h3.setProperty(runtime, "isActive", event.styleState.h3.isActive);
|
|
338
|
+
h3.setProperty(runtime, "isConflicting", event.styleState.h3.isConflicting);
|
|
339
|
+
h3.setProperty(runtime, "isBlocking", event.styleState.h3.isBlocking);
|
|
340
|
+
styleState.setProperty(runtime, "h3", h3);
|
|
341
|
+
}
|
|
342
|
+
{
|
|
343
|
+
auto h4 = jsi::Object(runtime);
|
|
344
|
+
h4.setProperty(runtime, "isActive", event.styleState.h4.isActive);
|
|
345
|
+
h4.setProperty(runtime, "isConflicting", event.styleState.h4.isConflicting);
|
|
346
|
+
h4.setProperty(runtime, "isBlocking", event.styleState.h4.isBlocking);
|
|
347
|
+
styleState.setProperty(runtime, "h4", h4);
|
|
348
|
+
}
|
|
349
|
+
{
|
|
350
|
+
auto h5 = jsi::Object(runtime);
|
|
351
|
+
h5.setProperty(runtime, "isActive", event.styleState.h5.isActive);
|
|
352
|
+
h5.setProperty(runtime, "isConflicting", event.styleState.h5.isConflicting);
|
|
353
|
+
h5.setProperty(runtime, "isBlocking", event.styleState.h5.isBlocking);
|
|
354
|
+
styleState.setProperty(runtime, "h5", h5);
|
|
355
|
+
}
|
|
356
|
+
{
|
|
357
|
+
auto h6 = jsi::Object(runtime);
|
|
358
|
+
h6.setProperty(runtime, "isActive", event.styleState.h6.isActive);
|
|
359
|
+
h6.setProperty(runtime, "isConflicting", event.styleState.h6.isConflicting);
|
|
360
|
+
h6.setProperty(runtime, "isBlocking", event.styleState.h6.isBlocking);
|
|
361
|
+
styleState.setProperty(runtime, "h6", h6);
|
|
362
|
+
}
|
|
363
|
+
{
|
|
364
|
+
auto codeBlock = jsi::Object(runtime);
|
|
365
|
+
codeBlock.setProperty(runtime, "isActive", event.styleState.codeBlock.isActive);
|
|
366
|
+
codeBlock.setProperty(runtime, "isConflicting", event.styleState.codeBlock.isConflicting);
|
|
367
|
+
codeBlock.setProperty(runtime, "isBlocking", event.styleState.codeBlock.isBlocking);
|
|
368
|
+
styleState.setProperty(runtime, "codeBlock", codeBlock);
|
|
369
|
+
}
|
|
370
|
+
{
|
|
371
|
+
auto blockQuote = jsi::Object(runtime);
|
|
372
|
+
blockQuote.setProperty(runtime, "isActive", event.styleState.blockQuote.isActive);
|
|
373
|
+
blockQuote.setProperty(runtime, "isConflicting", event.styleState.blockQuote.isConflicting);
|
|
374
|
+
blockQuote.setProperty(runtime, "isBlocking", event.styleState.blockQuote.isBlocking);
|
|
375
|
+
styleState.setProperty(runtime, "blockQuote", blockQuote);
|
|
376
|
+
}
|
|
377
|
+
{
|
|
378
|
+
auto orderedList = jsi::Object(runtime);
|
|
379
|
+
orderedList.setProperty(runtime, "isActive", event.styleState.orderedList.isActive);
|
|
380
|
+
orderedList.setProperty(runtime, "isConflicting", event.styleState.orderedList.isConflicting);
|
|
381
|
+
orderedList.setProperty(runtime, "isBlocking", event.styleState.orderedList.isBlocking);
|
|
382
|
+
styleState.setProperty(runtime, "orderedList", orderedList);
|
|
383
|
+
}
|
|
384
|
+
{
|
|
385
|
+
auto unorderedList = jsi::Object(runtime);
|
|
386
|
+
unorderedList.setProperty(runtime, "isActive", event.styleState.unorderedList.isActive);
|
|
387
|
+
unorderedList.setProperty(runtime, "isConflicting", event.styleState.unorderedList.isConflicting);
|
|
388
|
+
unorderedList.setProperty(runtime, "isBlocking", event.styleState.unorderedList.isBlocking);
|
|
389
|
+
styleState.setProperty(runtime, "unorderedList", unorderedList);
|
|
390
|
+
}
|
|
391
|
+
{
|
|
392
|
+
auto link = jsi::Object(runtime);
|
|
393
|
+
link.setProperty(runtime, "isActive", event.styleState.link.isActive);
|
|
394
|
+
link.setProperty(runtime, "isConflicting", event.styleState.link.isConflicting);
|
|
395
|
+
link.setProperty(runtime, "isBlocking", event.styleState.link.isBlocking);
|
|
396
|
+
styleState.setProperty(runtime, "link", link);
|
|
397
|
+
}
|
|
398
|
+
{
|
|
399
|
+
auto image = jsi::Object(runtime);
|
|
400
|
+
image.setProperty(runtime, "isActive", event.styleState.image.isActive);
|
|
401
|
+
image.setProperty(runtime, "isConflicting", event.styleState.image.isConflicting);
|
|
402
|
+
image.setProperty(runtime, "isBlocking", event.styleState.image.isBlocking);
|
|
403
|
+
styleState.setProperty(runtime, "image", image);
|
|
404
|
+
}
|
|
405
|
+
{
|
|
406
|
+
auto mention = jsi::Object(runtime);
|
|
407
|
+
mention.setProperty(runtime, "isActive", event.styleState.mention.isActive);
|
|
408
|
+
mention.setProperty(runtime, "isConflicting", event.styleState.mention.isConflicting);
|
|
409
|
+
mention.setProperty(runtime, "isBlocking", event.styleState.mention.isBlocking);
|
|
410
|
+
styleState.setProperty(runtime, "mention", mention);
|
|
411
|
+
}
|
|
412
|
+
{
|
|
413
|
+
auto checkboxList = jsi::Object(runtime);
|
|
414
|
+
checkboxList.setProperty(runtime, "isActive", event.styleState.checkboxList.isActive);
|
|
415
|
+
checkboxList.setProperty(runtime, "isConflicting", event.styleState.checkboxList.isConflicting);
|
|
416
|
+
checkboxList.setProperty(runtime, "isBlocking", event.styleState.checkboxList.isBlocking);
|
|
417
|
+
styleState.setProperty(runtime, "checkboxList", checkboxList);
|
|
418
|
+
}
|
|
419
|
+
payload.setProperty(runtime, "styleState", styleState);
|
|
420
|
+
}
|
|
421
|
+
return payload;
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
276
425
|
} // namespace facebook::react
|
package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h
CHANGED
|
@@ -212,6 +212,150 @@ class EnrichedTextInputViewEventEmitter : public ViewEventEmitter {
|
|
|
212
212
|
struct OnPasteImages {
|
|
213
213
|
std::vector<OnPasteImagesImages> images;
|
|
214
214
|
};
|
|
215
|
+
|
|
216
|
+
struct OnContextMenuItemPressStyleStateBold {
|
|
217
|
+
bool isActive;
|
|
218
|
+
bool isConflicting;
|
|
219
|
+
bool isBlocking;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
struct OnContextMenuItemPressStyleStateItalic {
|
|
223
|
+
bool isActive;
|
|
224
|
+
bool isConflicting;
|
|
225
|
+
bool isBlocking;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
struct OnContextMenuItemPressStyleStateUnderline {
|
|
229
|
+
bool isActive;
|
|
230
|
+
bool isConflicting;
|
|
231
|
+
bool isBlocking;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
struct OnContextMenuItemPressStyleStateStrikeThrough {
|
|
235
|
+
bool isActive;
|
|
236
|
+
bool isConflicting;
|
|
237
|
+
bool isBlocking;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
struct OnContextMenuItemPressStyleStateInlineCode {
|
|
241
|
+
bool isActive;
|
|
242
|
+
bool isConflicting;
|
|
243
|
+
bool isBlocking;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
struct OnContextMenuItemPressStyleStateH1 {
|
|
247
|
+
bool isActive;
|
|
248
|
+
bool isConflicting;
|
|
249
|
+
bool isBlocking;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
struct OnContextMenuItemPressStyleStateH2 {
|
|
253
|
+
bool isActive;
|
|
254
|
+
bool isConflicting;
|
|
255
|
+
bool isBlocking;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
struct OnContextMenuItemPressStyleStateH3 {
|
|
259
|
+
bool isActive;
|
|
260
|
+
bool isConflicting;
|
|
261
|
+
bool isBlocking;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
struct OnContextMenuItemPressStyleStateH4 {
|
|
265
|
+
bool isActive;
|
|
266
|
+
bool isConflicting;
|
|
267
|
+
bool isBlocking;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
struct OnContextMenuItemPressStyleStateH5 {
|
|
271
|
+
bool isActive;
|
|
272
|
+
bool isConflicting;
|
|
273
|
+
bool isBlocking;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
struct OnContextMenuItemPressStyleStateH6 {
|
|
277
|
+
bool isActive;
|
|
278
|
+
bool isConflicting;
|
|
279
|
+
bool isBlocking;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
struct OnContextMenuItemPressStyleStateCodeBlock {
|
|
283
|
+
bool isActive;
|
|
284
|
+
bool isConflicting;
|
|
285
|
+
bool isBlocking;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
struct OnContextMenuItemPressStyleStateBlockQuote {
|
|
289
|
+
bool isActive;
|
|
290
|
+
bool isConflicting;
|
|
291
|
+
bool isBlocking;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
struct OnContextMenuItemPressStyleStateOrderedList {
|
|
295
|
+
bool isActive;
|
|
296
|
+
bool isConflicting;
|
|
297
|
+
bool isBlocking;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
struct OnContextMenuItemPressStyleStateUnorderedList {
|
|
301
|
+
bool isActive;
|
|
302
|
+
bool isConflicting;
|
|
303
|
+
bool isBlocking;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
struct OnContextMenuItemPressStyleStateLink {
|
|
307
|
+
bool isActive;
|
|
308
|
+
bool isConflicting;
|
|
309
|
+
bool isBlocking;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
struct OnContextMenuItemPressStyleStateImage {
|
|
313
|
+
bool isActive;
|
|
314
|
+
bool isConflicting;
|
|
315
|
+
bool isBlocking;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
struct OnContextMenuItemPressStyleStateMention {
|
|
319
|
+
bool isActive;
|
|
320
|
+
bool isConflicting;
|
|
321
|
+
bool isBlocking;
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
struct OnContextMenuItemPressStyleStateCheckboxList {
|
|
325
|
+
bool isActive;
|
|
326
|
+
bool isConflicting;
|
|
327
|
+
bool isBlocking;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
struct OnContextMenuItemPressStyleState {
|
|
331
|
+
OnContextMenuItemPressStyleStateBold bold;
|
|
332
|
+
OnContextMenuItemPressStyleStateItalic italic;
|
|
333
|
+
OnContextMenuItemPressStyleStateUnderline underline;
|
|
334
|
+
OnContextMenuItemPressStyleStateStrikeThrough strikeThrough;
|
|
335
|
+
OnContextMenuItemPressStyleStateInlineCode inlineCode;
|
|
336
|
+
OnContextMenuItemPressStyleStateH1 h1;
|
|
337
|
+
OnContextMenuItemPressStyleStateH2 h2;
|
|
338
|
+
OnContextMenuItemPressStyleStateH3 h3;
|
|
339
|
+
OnContextMenuItemPressStyleStateH4 h4;
|
|
340
|
+
OnContextMenuItemPressStyleStateH5 h5;
|
|
341
|
+
OnContextMenuItemPressStyleStateH6 h6;
|
|
342
|
+
OnContextMenuItemPressStyleStateCodeBlock codeBlock;
|
|
343
|
+
OnContextMenuItemPressStyleStateBlockQuote blockQuote;
|
|
344
|
+
OnContextMenuItemPressStyleStateOrderedList orderedList;
|
|
345
|
+
OnContextMenuItemPressStyleStateUnorderedList unorderedList;
|
|
346
|
+
OnContextMenuItemPressStyleStateLink link;
|
|
347
|
+
OnContextMenuItemPressStyleStateImage image;
|
|
348
|
+
OnContextMenuItemPressStyleStateMention mention;
|
|
349
|
+
OnContextMenuItemPressStyleStateCheckboxList checkboxList;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
struct OnContextMenuItemPress {
|
|
353
|
+
std::string itemText;
|
|
354
|
+
std::string selectedText;
|
|
355
|
+
int selectionStart;
|
|
356
|
+
int selectionEnd;
|
|
357
|
+
OnContextMenuItemPressStyleState styleState;
|
|
358
|
+
};
|
|
215
359
|
void onInputFocus(OnInputFocus value) const;
|
|
216
360
|
|
|
217
361
|
void onInputBlur(OnInputBlur value) const;
|
|
@@ -235,5 +379,7 @@ class EnrichedTextInputViewEventEmitter : public ViewEventEmitter {
|
|
|
235
379
|
void onInputKeyPress(OnInputKeyPress value) const;
|
|
236
380
|
|
|
237
381
|
void onPasteImages(OnPasteImages value) const;
|
|
382
|
+
|
|
383
|
+
void onContextMenuItemPress(OnContextMenuItemPress value) const;
|
|
238
384
|
};
|
|
239
385
|
} // namespace facebook::react
|
|
@@ -32,14 +32,17 @@ EnrichedTextInputViewProps::EnrichedTextInputViewProps(
|
|
|
32
32
|
htmlStyle(convertRawProp(context, rawProps, "htmlStyle", sourceProps.htmlStyle, {})),
|
|
33
33
|
scrollEnabled(convertRawProp(context, rawProps, "scrollEnabled", sourceProps.scrollEnabled, {false})),
|
|
34
34
|
linkRegex(convertRawProp(context, rawProps, "linkRegex", sourceProps.linkRegex, {})),
|
|
35
|
+
contextMenuItems(convertRawProp(context, rawProps, "contextMenuItems", sourceProps.contextMenuItems, {})),
|
|
35
36
|
color(convertRawProp(context, rawProps, "color", sourceProps.color, {})),
|
|
36
37
|
fontSize(convertRawProp(context, rawProps, "fontSize", sourceProps.fontSize, {0.0})),
|
|
38
|
+
lineHeight(convertRawProp(context, rawProps, "lineHeight", sourceProps.lineHeight, {0.0})),
|
|
37
39
|
fontFamily(convertRawProp(context, rawProps, "fontFamily", sourceProps.fontFamily, {})),
|
|
38
40
|
fontWeight(convertRawProp(context, rawProps, "fontWeight", sourceProps.fontWeight, {})),
|
|
39
41
|
fontStyle(convertRawProp(context, rawProps, "fontStyle", sourceProps.fontStyle, {})),
|
|
40
42
|
isOnChangeHtmlSet(convertRawProp(context, rawProps, "isOnChangeHtmlSet", sourceProps.isOnChangeHtmlSet, {false})),
|
|
41
43
|
isOnChangeTextSet(convertRawProp(context, rawProps, "isOnChangeTextSet", sourceProps.isOnChangeTextSet, {false})),
|
|
42
|
-
androidExperimentalSynchronousEvents(convertRawProp(context, rawProps, "androidExperimentalSynchronousEvents", sourceProps.androidExperimentalSynchronousEvents, {false}))
|
|
44
|
+
androidExperimentalSynchronousEvents(convertRawProp(context, rawProps, "androidExperimentalSynchronousEvents", sourceProps.androidExperimentalSynchronousEvents, {false})),
|
|
45
|
+
useHtmlNormalizer(convertRawProp(context, rawProps, "useHtmlNormalizer", sourceProps.useHtmlNormalizer, {false})) {}
|
|
43
46
|
|
|
44
47
|
#ifdef RN_SERIALIZABLE_STATE
|
|
45
48
|
ComponentName EnrichedTextInputViewProps::getDiffPropsImplementationTarget() const {
|
|
@@ -105,6 +108,10 @@ folly::dynamic EnrichedTextInputViewProps::getDiffProps(
|
|
|
105
108
|
result["linkRegex"] = toDynamic(linkRegex);
|
|
106
109
|
}
|
|
107
110
|
|
|
111
|
+
if (contextMenuItems != oldProps->contextMenuItems) {
|
|
112
|
+
result["contextMenuItems"] = toDynamic(contextMenuItems);
|
|
113
|
+
}
|
|
114
|
+
|
|
108
115
|
if (color != oldProps->color) {
|
|
109
116
|
result["color"] = *color;
|
|
110
117
|
}
|
|
@@ -113,6 +120,10 @@ folly::dynamic EnrichedTextInputViewProps::getDiffProps(
|
|
|
113
120
|
result["fontSize"] = fontSize;
|
|
114
121
|
}
|
|
115
122
|
|
|
123
|
+
if ((lineHeight != oldProps->lineHeight) && !(std::isnan(lineHeight) && std::isnan(oldProps->lineHeight))) {
|
|
124
|
+
result["lineHeight"] = lineHeight;
|
|
125
|
+
}
|
|
126
|
+
|
|
116
127
|
if (fontFamily != oldProps->fontFamily) {
|
|
117
128
|
result["fontFamily"] = fontFamily;
|
|
118
129
|
}
|
|
@@ -136,6 +147,10 @@ folly::dynamic EnrichedTextInputViewProps::getDiffProps(
|
|
|
136
147
|
if (androidExperimentalSynchronousEvents != oldProps->androidExperimentalSynchronousEvents) {
|
|
137
148
|
result["androidExperimentalSynchronousEvents"] = androidExperimentalSynchronousEvents;
|
|
138
149
|
}
|
|
150
|
+
|
|
151
|
+
if (useHtmlNormalizer != oldProps->useHtmlNormalizer) {
|
|
152
|
+
result["useHtmlNormalizer"] = useHtmlNormalizer;
|
|
153
|
+
}
|
|
139
154
|
return result;
|
|
140
155
|
}
|
|
141
156
|
#endif
|
|
@@ -746,6 +746,49 @@ static inline folly::dynamic toDynamic(const EnrichedTextInputViewLinkRegexStruc
|
|
|
746
746
|
return value.toDynamic();
|
|
747
747
|
}
|
|
748
748
|
#endif
|
|
749
|
+
|
|
750
|
+
struct EnrichedTextInputViewContextMenuItemsStruct {
|
|
751
|
+
std::string text{};
|
|
752
|
+
|
|
753
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
754
|
+
bool operator==(const EnrichedTextInputViewContextMenuItemsStruct&) const = default;
|
|
755
|
+
|
|
756
|
+
folly::dynamic toDynamic() const {
|
|
757
|
+
folly::dynamic result = folly::dynamic::object();
|
|
758
|
+
result["text"] = text;
|
|
759
|
+
return result;
|
|
760
|
+
}
|
|
761
|
+
#endif
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, EnrichedTextInputViewContextMenuItemsStruct &result) {
|
|
765
|
+
auto map = (std::unordered_map<std::string, RawValue>)value;
|
|
766
|
+
|
|
767
|
+
auto tmp_text = map.find("text");
|
|
768
|
+
if (tmp_text != map.end()) {
|
|
769
|
+
fromRawValue(context, tmp_text->second, result.text);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
static inline std::string toString(const EnrichedTextInputViewContextMenuItemsStruct &value) {
|
|
774
|
+
return "[Object EnrichedTextInputViewContextMenuItemsStruct]";
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
778
|
+
static inline folly::dynamic toDynamic(const EnrichedTextInputViewContextMenuItemsStruct &value) {
|
|
779
|
+
return value.toDynamic();
|
|
780
|
+
}
|
|
781
|
+
#endif
|
|
782
|
+
|
|
783
|
+
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, std::vector<EnrichedTextInputViewContextMenuItemsStruct> &result) {
|
|
784
|
+
auto items = (std::vector<RawValue>)value;
|
|
785
|
+
for (const auto &item : items) {
|
|
786
|
+
EnrichedTextInputViewContextMenuItemsStruct newItem;
|
|
787
|
+
fromRawValue(context, item, newItem);
|
|
788
|
+
result.emplace_back(newItem);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
749
792
|
class EnrichedTextInputViewProps final : public ViewProps {
|
|
750
793
|
public:
|
|
751
794
|
EnrichedTextInputViewProps() = default;
|
|
@@ -765,14 +808,17 @@ class EnrichedTextInputViewProps final : public ViewProps {
|
|
|
765
808
|
EnrichedTextInputViewHtmlStyleStruct htmlStyle{};
|
|
766
809
|
bool scrollEnabled{false};
|
|
767
810
|
EnrichedTextInputViewLinkRegexStruct linkRegex{};
|
|
811
|
+
std::vector<EnrichedTextInputViewContextMenuItemsStruct> contextMenuItems{};
|
|
768
812
|
SharedColor color{};
|
|
769
813
|
Float fontSize{0.0};
|
|
814
|
+
Float lineHeight{0.0};
|
|
770
815
|
std::string fontFamily{};
|
|
771
816
|
std::string fontWeight{};
|
|
772
817
|
std::string fontStyle{};
|
|
773
818
|
bool isOnChangeHtmlSet{false};
|
|
774
819
|
bool isOnChangeTextSet{false};
|
|
775
820
|
bool androidExperimentalSynchronousEvents{false};
|
|
821
|
+
bool useHtmlNormalizer{false};
|
|
776
822
|
|
|
777
823
|
#ifdef RN_SERIALIZABLE_STATE
|
|
778
824
|
ComponentName getDiffPropsImplementationTarget() const override;
|
package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt
CHANGED
|
@@ -80,8 +80,9 @@ open class EnrichedCheckboxListSpan(
|
|
|
80
80
|
if (spannedText.getSpanStart(this) == start) {
|
|
81
81
|
checkboxDrawable.update(isChecked)
|
|
82
82
|
|
|
83
|
-
val
|
|
84
|
-
val
|
|
83
|
+
val fm = paint.fontMetricsInt
|
|
84
|
+
val textCenter = baseline + (fm.ascent + fm.descent) / 2f
|
|
85
|
+
val drawableTop = textCenter - (enrichedStyle.ulCheckboxBoxSize / 2f)
|
|
85
86
|
|
|
86
87
|
canvas.withTranslation(x.toFloat() + enrichedStyle.ulCheckboxMarginLeft, drawableTop) {
|
|
87
88
|
checkboxDrawable.draw(this)
|
package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnorderedListSpan.kt
CHANGED
|
@@ -49,7 +49,8 @@ open class EnrichedUnorderedListSpan(
|
|
|
49
49
|
paint.style = Paint.Style.FILL
|
|
50
50
|
|
|
51
51
|
val bulletRadius = enrichedStyle.ulBulletSize / 2f
|
|
52
|
-
val
|
|
52
|
+
val fm = paint.fontMetricsInt
|
|
53
|
+
val yPosition = baseline + (fm.ascent + fm.descent) / 2f
|
|
53
54
|
val xPosition = x + dir * bulletRadius + enrichedStyle.ulMarginLeft
|
|
54
55
|
|
|
55
56
|
canvas.drawCircle(xPosition, yPosition, bulletRadius, paint)
|