react-native-enriched-markdown-scaffold 1.0.2-scaffold.2 → 1.0.2-scaffold.3
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/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +24 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +18 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +12 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +24 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyRequestEvent.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +21 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +27 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +4 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +3 -1
- package/docs/API_REFERENCE.md +48 -0
- package/docs/COPY_OPTIONS.md +14 -0
- package/ios/EnrichedMarkdown.mm +43 -2
- package/ios/EnrichedMarkdownText.mm +25 -3
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +24 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +18 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +12 -0
- package/ios/utils/ENRMBlockMenu.h +12 -3
- package/ios/utils/EditMenuUtils.h +10 -1
- package/ios/utils/EditMenuUtils.m +18 -4
- package/ios/views/ENRMCodeBlockContainerView.h +4 -0
- package/ios/views/ENRMCodeBlockContainerView.m +8 -1
- package/ios/views/ENRMMathContainerView.h +4 -0
- package/ios/views/ENRMMathContainerView.m +8 -1
- package/ios/views/TableContainerView.h +4 -0
- package/ios/views/TableContainerView.m +9 -3
- package/lib/module/EnrichedMarkdownNativeComponent.ts +16 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +16 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/EnrichedMarkdownText.js +23 -2
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +13 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +13 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.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/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +13 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +22 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/EnrichedMarkdownNativeComponent.ts +16 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +16 -0
- package/src/index.tsx +1 -0
- package/src/native/EnrichedMarkdownText.tsx +24 -1
- package/src/types/MarkdownTextProps.ts +13 -0
- package/src/types/events.ts +23 -0
package/ios/EnrichedMarkdown.mm
CHANGED
|
@@ -75,6 +75,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
75
75
|
- (void)emitLinkLongPress:(NSString *)url;
|
|
76
76
|
- (void)emitTaskListItemPress:(NSInteger)index checked:(BOOL)checked text:(NSString *)text;
|
|
77
77
|
- (void)emitCopyPress:(NSString *)code language:(NSString *)language;
|
|
78
|
+
- (void)emitCopyRequest:(NSString *)source markdown:(NSString *)markdown text:(NSString *)text whole:(BOOL)whole;
|
|
78
79
|
- (void)emitContextMenuItemPress:(NSString *)itemText
|
|
79
80
|
selectedText:(NSString *)selectedText
|
|
80
81
|
selectionStart:(NSUInteger)selectionStart
|
|
@@ -512,6 +513,17 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
512
513
|
.copyWritesMarkdown = _selectionMenuConfig.copyFormatMarkdown,
|
|
513
514
|
.copyAsMarkdownHidden = !_selectionMenuConfig.copyAsMarkdown,
|
|
514
515
|
.copyButtonHidden = !_selectionMenuConfig.codeBlockCopyButton,
|
|
516
|
+
.interceptCopy = _selectionMenuConfig.interceptCopy,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
- (ENRMBlockCopyRequestBlock)blockCopyRequestForSource:(NSString *)source
|
|
521
|
+
{
|
|
522
|
+
__weak EnrichedMarkdown *weakSelf = self;
|
|
523
|
+
return ^(NSString *markdown, NSString *text) {
|
|
524
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
525
|
+
if (strongSelf)
|
|
526
|
+
[strongSelf emitCopyRequest:source markdown:markdown text:text whole:YES];
|
|
515
527
|
};
|
|
516
528
|
}
|
|
517
529
|
|
|
@@ -800,7 +812,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
800
812
|
selectionEnd:selectionEnd];
|
|
801
813
|
});
|
|
802
814
|
return buildEditMenuForSelection(textView.textStorage, textView.selectedRange, segmentMarkdown, strongSelf->_config,
|
|
803
|
-
@[ baseMenu ], customItems, strongSelf
|
|
815
|
+
@[ baseMenu ], customItems, strongSelf->_selectionMenuConfig);
|
|
804
816
|
}];
|
|
805
817
|
#endif
|
|
806
818
|
|
|
@@ -821,6 +833,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
821
833
|
tableView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
822
834
|
tableView.contextMenuHidden = _contextMenuHidden;
|
|
823
835
|
tableView.menuOptions = [self blockMenuOptions];
|
|
836
|
+
tableView.onCopyRequest = [self blockCopyRequestForSource:@"table"];
|
|
824
837
|
|
|
825
838
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
826
839
|
|
|
@@ -862,6 +875,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
862
875
|
mathView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
863
876
|
mathView.contextMenuHidden = _contextMenuHidden;
|
|
864
877
|
mathView.menuOptions = [self blockMenuOptions];
|
|
878
|
+
mathView.onCopyRequest = [self blockCopyRequestForSource:@"math"];
|
|
865
879
|
[mathView applyLatex:mathSegment.latex];
|
|
866
880
|
return mathView;
|
|
867
881
|
}
|
|
@@ -874,6 +888,7 @@ static char kENRMSegmentFadeAnimatorKey;
|
|
|
874
888
|
codeBlockView.copyAsMarkdownLabel = _selectionMenuLabels.copyAsMarkdownLabel;
|
|
875
889
|
codeBlockView.contextMenuHidden = _contextMenuHidden;
|
|
876
890
|
codeBlockView.menuOptions = [self blockMenuOptions];
|
|
891
|
+
codeBlockView.onCopyRequest = [self blockCopyRequestForSource:@"code"];
|
|
877
892
|
|
|
878
893
|
__weak EnrichedMarkdown *weakSelf = self;
|
|
879
894
|
codeBlockView.onCopyPress = ^(NSString *code, NSString *language) {
|
|
@@ -1288,6 +1303,18 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1288
1303
|
{.code = std::string(code.UTF8String ?: ""), .language = std::string(language.UTF8String ?: "")});
|
|
1289
1304
|
}
|
|
1290
1305
|
|
|
1306
|
+
- (void)emitCopyRequest:(NSString *)source markdown:(NSString *)markdown text:(NSString *)text whole:(BOOL)whole
|
|
1307
|
+
{
|
|
1308
|
+
auto emitter = std::static_pointer_cast<EnrichedMarkdownEventEmitter const>(_eventEmitter);
|
|
1309
|
+
if (emitter)
|
|
1310
|
+
emitter->onCopyRequest({
|
|
1311
|
+
.source = std::string(source.UTF8String),
|
|
1312
|
+
.markdown = std::string(markdown.UTF8String ?: ""),
|
|
1313
|
+
.text = std::string(text.UTF8String ?: ""),
|
|
1314
|
+
.whole = (bool)whole,
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1291
1318
|
- (void)emitContextMenuItemPress:(NSString *)itemText
|
|
1292
1319
|
selectedText:(NSString *)selectedText
|
|
1293
1320
|
selectionStart:(NSUInteger)selectionStart
|
|
@@ -1355,8 +1382,22 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownCls(void)
|
|
|
1355
1382
|
ENRMBuildContextMenuActions(_contextMenuItemTexts, _contextMenuItemIcons, textView, range, handler);
|
|
1356
1383
|
|
|
1357
1384
|
NSString *segmentMarkdown = extractMarkdownFromAttributedString(textView.attributedText, range);
|
|
1385
|
+
|
|
1386
|
+
// Segments only see their own text, so a selection is the whole component
|
|
1387
|
+
// only when it spans the sole segment; the markdown is then the original.
|
|
1388
|
+
ENRMCopyRequestHandler onCopyRequest = ^(NSString *markdown, NSString *text, BOOL fullSelection) {
|
|
1389
|
+
EnrichedMarkdown *strongSelf = weakSelf;
|
|
1390
|
+
if (!strongSelf)
|
|
1391
|
+
return;
|
|
1392
|
+
BOOL whole = fullSelection && strongSelf->_segmentViews.count == 1 && strongSelf->_cachedMarkdown.length > 0;
|
|
1393
|
+
[strongSelf emitCopyRequest:@"selection"
|
|
1394
|
+
markdown:whole ? strongSelf->_cachedMarkdown : markdown
|
|
1395
|
+
text:text
|
|
1396
|
+
whole:whole];
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1358
1399
|
return buildEditMenuForSelection(textView.attributedText, range, segmentMarkdown, _config, suggestedActions,
|
|
1359
|
-
customActions, _selectionMenuConfig);
|
|
1400
|
+
customActions, _selectionMenuConfig, onCopyRequest);
|
|
1360
1401
|
}
|
|
1361
1402
|
|
|
1362
1403
|
- (BOOL)textView:(UITextView *)textView
|
|
@@ -61,6 +61,7 @@ typedef NS_OPTIONS(NSUInteger, ENRMDirtyFlags) {
|
|
|
61
61
|
selectedText:(NSString *)selectedText
|
|
62
62
|
selectionStart:(NSUInteger)selectionStart
|
|
63
63
|
selectionEnd:(NSUInteger)selectionEnd;
|
|
64
|
+
- (void)emitCopyRequest:(NSString *)source markdown:(NSString *)markdown text:(NSString *)text whole:(BOOL)whole;
|
|
64
65
|
@end
|
|
65
66
|
|
|
66
67
|
@implementation EnrichedMarkdownText {
|
|
@@ -301,8 +302,7 @@ typedef NS_OPTIONS(NSUInteger, ENRMDirtyFlags) {
|
|
|
301
302
|
selectionEnd:selectionEnd];
|
|
302
303
|
});
|
|
303
304
|
return buildEditMenuForSelection(textView.textStorage, textView.selectedRange, strongSelf->_cachedMarkdown,
|
|
304
|
-
strongSelf->_config, @[ baseMenu ], customItems,
|
|
305
|
-
strongSelf -> _selectionMenuConfig);
|
|
305
|
+
strongSelf->_config, @[ baseMenu ], customItems, strongSelf->_selectionMenuConfig);
|
|
306
306
|
};
|
|
307
307
|
#endif
|
|
308
308
|
|
|
@@ -749,6 +749,18 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownTextCls(void)
|
|
|
749
749
|
emitter->onTaskListItemPress({.index = (int)index, .checked = checked, .text = std::string(text.UTF8String ?: "")});
|
|
750
750
|
}
|
|
751
751
|
|
|
752
|
+
- (void)emitCopyRequest:(NSString *)source markdown:(NSString *)markdown text:(NSString *)text whole:(BOOL)whole
|
|
753
|
+
{
|
|
754
|
+
auto emitter = std::static_pointer_cast<EnrichedMarkdownTextEventEmitter const>(_eventEmitter);
|
|
755
|
+
if (emitter)
|
|
756
|
+
emitter->onCopyRequest({
|
|
757
|
+
.source = std::string(source.UTF8String),
|
|
758
|
+
.markdown = std::string(markdown.UTF8String ?: ""),
|
|
759
|
+
.text = std::string(text.UTF8String ?: ""),
|
|
760
|
+
.whole = (bool)whole,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
|
|
752
764
|
- (void)emitContextMenuItemPress:(NSString *)itemText
|
|
753
765
|
selectedText:(NSString *)selectedText
|
|
754
766
|
selectionStart:(NSUInteger)selectionStart
|
|
@@ -831,8 +843,18 @@ Class<RCTComponentViewProtocol> EnrichedMarkdownTextCls(void)
|
|
|
831
843
|
NSMutableArray<UIAction *> *customActions =
|
|
832
844
|
ENRMBuildContextMenuActions(_contextMenuItemTexts, _contextMenuItemIcons, textView, range, handler);
|
|
833
845
|
|
|
846
|
+
// A full selection already carries the cached (original) markdown.
|
|
847
|
+
ENRMCopyRequestHandler onCopyRequest = ^(NSString *markdown, NSString *text, BOOL fullSelection) {
|
|
848
|
+
EnrichedMarkdownText *strongSelf = weakSelf;
|
|
849
|
+
if (strongSelf)
|
|
850
|
+
[strongSelf emitCopyRequest:@"selection"
|
|
851
|
+
markdown:markdown
|
|
852
|
+
text:text
|
|
853
|
+
whole:fullSelection && strongSelf->_cachedMarkdown.length > 0];
|
|
854
|
+
};
|
|
855
|
+
|
|
834
856
|
return buildEditMenuForSelection(textView.attributedText, range, _cachedMarkdown, _config, suggestedActions,
|
|
835
|
-
customActions, _selectionMenuConfig);
|
|
857
|
+
customActions, _selectionMenuConfig, onCopyRequest);
|
|
836
858
|
}
|
|
837
859
|
#endif
|
|
838
860
|
|
|
@@ -52,6 +52,18 @@ payload.setProperty(runtime, "language", event.language);
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
void EnrichedMarkdownEventEmitter::onCopyRequest(OnCopyRequest event) const {
|
|
56
|
+
dispatchEvent("copyRequest", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
57
|
+
auto payload = jsi::Object(runtime);
|
|
58
|
+
payload.setProperty(runtime, "source", event.source);
|
|
59
|
+
payload.setProperty(runtime, "markdown", event.markdown);
|
|
60
|
+
payload.setProperty(runtime, "text", event.text);
|
|
61
|
+
payload.setProperty(runtime, "whole", event.whole);
|
|
62
|
+
return payload;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
55
67
|
void EnrichedMarkdownEventEmitter::onContextMenuItemPress(OnContextMenuItemPress event) const {
|
|
56
68
|
dispatchEvent("contextMenuItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
57
69
|
auto payload = jsi::Object(runtime);
|
|
@@ -379,6 +391,18 @@ payload.setProperty(runtime, "language", event.language);
|
|
|
379
391
|
}
|
|
380
392
|
|
|
381
393
|
|
|
394
|
+
void EnrichedMarkdownTextEventEmitter::onCopyRequest(OnCopyRequest event) const {
|
|
395
|
+
dispatchEvent("copyRequest", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
396
|
+
auto payload = jsi::Object(runtime);
|
|
397
|
+
payload.setProperty(runtime, "source", event.source);
|
|
398
|
+
payload.setProperty(runtime, "markdown", event.markdown);
|
|
399
|
+
payload.setProperty(runtime, "text", event.text);
|
|
400
|
+
payload.setProperty(runtime, "whole", event.whole);
|
|
401
|
+
return payload;
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
|
|
382
406
|
void EnrichedMarkdownTextEventEmitter::onContextMenuItemPress(OnContextMenuItemPress event) const {
|
|
383
407
|
dispatchEvent("contextMenuItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
384
408
|
auto payload = jsi::Object(runtime);
|
|
@@ -36,6 +36,13 @@ class EnrichedMarkdownEventEmitter : public ViewEventEmitter {
|
|
|
36
36
|
std::string language;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
struct OnCopyRequest {
|
|
40
|
+
std::string source;
|
|
41
|
+
std::string markdown;
|
|
42
|
+
std::string text;
|
|
43
|
+
bool whole;
|
|
44
|
+
};
|
|
45
|
+
|
|
39
46
|
struct OnContextMenuItemPress {
|
|
40
47
|
std::string itemText;
|
|
41
48
|
std::string selectedText;
|
|
@@ -50,6 +57,8 @@ class EnrichedMarkdownEventEmitter : public ViewEventEmitter {
|
|
|
50
57
|
|
|
51
58
|
void onCopyPress(OnCopyPress value) const;
|
|
52
59
|
|
|
60
|
+
void onCopyRequest(OnCopyRequest value) const;
|
|
61
|
+
|
|
53
62
|
void onContextMenuItemPress(OnContextMenuItemPress value) const;
|
|
54
63
|
};
|
|
55
64
|
class EnrichedMarkdownTextInputEventEmitter : public ViewEventEmitter {
|
|
@@ -303,6 +312,13 @@ class EnrichedMarkdownTextEventEmitter : public ViewEventEmitter {
|
|
|
303
312
|
std::string language;
|
|
304
313
|
};
|
|
305
314
|
|
|
315
|
+
struct OnCopyRequest {
|
|
316
|
+
std::string source;
|
|
317
|
+
std::string markdown;
|
|
318
|
+
std::string text;
|
|
319
|
+
bool whole;
|
|
320
|
+
};
|
|
321
|
+
|
|
306
322
|
struct OnContextMenuItemPress {
|
|
307
323
|
std::string itemText;
|
|
308
324
|
std::string selectedText;
|
|
@@ -317,6 +333,8 @@ class EnrichedMarkdownTextEventEmitter : public ViewEventEmitter {
|
|
|
317
333
|
|
|
318
334
|
void onCopyPress(OnCopyPress value) const;
|
|
319
335
|
|
|
336
|
+
void onCopyRequest(OnCopyRequest value) const;
|
|
337
|
+
|
|
320
338
|
void onContextMenuItemPress(OnContextMenuItemPress value) const;
|
|
321
339
|
};
|
|
322
340
|
} // namespace facebook::react
|
|
@@ -2466,6 +2466,7 @@ struct EnrichedMarkdownSelectionMenuConfigStruct {
|
|
|
2466
2466
|
bool copyFormatMarkdown{false};
|
|
2467
2467
|
bool systemItemsNone{false};
|
|
2468
2468
|
bool codeBlockCopyButton{false};
|
|
2469
|
+
bool interceptCopy{false};
|
|
2469
2470
|
|
|
2470
2471
|
|
|
2471
2472
|
#ifdef RN_SERIALIZABLE_STATE
|
|
@@ -2484,6 +2485,7 @@ struct EnrichedMarkdownSelectionMenuConfigStruct {
|
|
|
2484
2485
|
result["copyFormatMarkdown"] = copyFormatMarkdown;
|
|
2485
2486
|
result["systemItemsNone"] = systemItemsNone;
|
|
2486
2487
|
result["codeBlockCopyButton"] = codeBlockCopyButton;
|
|
2488
|
+
result["interceptCopy"] = interceptCopy;
|
|
2487
2489
|
return result;
|
|
2488
2490
|
}
|
|
2489
2491
|
#endif
|
|
@@ -2536,6 +2538,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
2536
2538
|
if (tmp_codeBlockCopyButton != map.end()) {
|
|
2537
2539
|
fromRawValue(context, tmp_codeBlockCopyButton->second, result.codeBlockCopyButton);
|
|
2538
2540
|
}
|
|
2541
|
+
auto tmp_interceptCopy = map.find("interceptCopy");
|
|
2542
|
+
if (tmp_interceptCopy != map.end()) {
|
|
2543
|
+
fromRawValue(context, tmp_interceptCopy->second, result.interceptCopy);
|
|
2544
|
+
}
|
|
2539
2545
|
}
|
|
2540
2546
|
|
|
2541
2547
|
static inline std::string toString(const EnrichedMarkdownSelectionMenuConfigStruct &value) {
|
|
@@ -6443,6 +6449,7 @@ struct EnrichedMarkdownTextSelectionMenuConfigStruct {
|
|
|
6443
6449
|
bool copyFormatMarkdown{false};
|
|
6444
6450
|
bool systemItemsNone{false};
|
|
6445
6451
|
bool codeBlockCopyButton{false};
|
|
6452
|
+
bool interceptCopy{false};
|
|
6446
6453
|
|
|
6447
6454
|
|
|
6448
6455
|
#ifdef RN_SERIALIZABLE_STATE
|
|
@@ -6461,6 +6468,7 @@ struct EnrichedMarkdownTextSelectionMenuConfigStruct {
|
|
|
6461
6468
|
result["copyFormatMarkdown"] = copyFormatMarkdown;
|
|
6462
6469
|
result["systemItemsNone"] = systemItemsNone;
|
|
6463
6470
|
result["codeBlockCopyButton"] = codeBlockCopyButton;
|
|
6471
|
+
result["interceptCopy"] = interceptCopy;
|
|
6464
6472
|
return result;
|
|
6465
6473
|
}
|
|
6466
6474
|
#endif
|
|
@@ -6513,6 +6521,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
6513
6521
|
if (tmp_codeBlockCopyButton != map.end()) {
|
|
6514
6522
|
fromRawValue(context, tmp_codeBlockCopyButton->second, result.codeBlockCopyButton);
|
|
6515
6523
|
}
|
|
6524
|
+
auto tmp_interceptCopy = map.find("interceptCopy");
|
|
6525
|
+
if (tmp_interceptCopy != map.end()) {
|
|
6526
|
+
fromRawValue(context, tmp_interceptCopy->second, result.interceptCopy);
|
|
6527
|
+
}
|
|
6516
6528
|
}
|
|
6517
6529
|
|
|
6518
6530
|
static inline std::string toString(const EnrichedMarkdownTextSelectionMenuConfigStruct &value) {
|
|
@@ -18,20 +18,29 @@ typedef struct {
|
|
|
18
18
|
BOOL copyAsMarkdownHidden;
|
|
19
19
|
// `selectionMenuConfig.codeBlockCopyButton.enabled == false`.
|
|
20
20
|
BOOL copyButtonHidden;
|
|
21
|
+
// JS `onCopy` is set: the Copy item hands the block's content to the view's
|
|
22
|
+
// `onCopyRequest` instead of writing the pasteboard.
|
|
23
|
+
BOOL interceptCopy;
|
|
21
24
|
} ENRMBlockMenuOptions;
|
|
22
25
|
|
|
26
|
+
/// Receives an intercepted block Copy: the block's Markdown and its raw content.
|
|
27
|
+
typedef void (^ENRMBlockCopyRequestBlock)(NSString *markdown, NSString *text);
|
|
28
|
+
|
|
23
29
|
#if !TARGET_OS_OSX
|
|
24
30
|
/// Builds the long-press menu shared by the table, math and code block views.
|
|
25
31
|
/// Returns nil when no item is left — nil is how UIKit suppresses a context
|
|
26
|
-
/// menu, whereas an empty menu would still lift the view.
|
|
32
|
+
/// menu, whereas an empty menu would still lift the view. `requestCopy` replaces
|
|
33
|
+
/// the Copy item's handler when `options.interceptCopy` is set.
|
|
27
34
|
static inline UIContextMenuConfiguration *_Nullable ENRMBlockContextMenuConfiguration(
|
|
28
35
|
ENRMBlockMenuOptions options, NSString *_Nullable copyLabel, NSString *_Nullable copyAsMarkdownLabel,
|
|
29
|
-
void (^copyRaw)(void), void (^copyMarkdown)(void))
|
|
36
|
+
void (^copyRaw)(void), void (^copyMarkdown)(void), void (^_Nullable requestCopy)(void))
|
|
30
37
|
{
|
|
31
38
|
if (options.copyHidden && options.copyAsMarkdownHidden) {
|
|
32
39
|
return nil;
|
|
33
40
|
}
|
|
34
|
-
void (^copyHandler)(void) = options.
|
|
41
|
+
void (^copyHandler)(void) = (options.interceptCopy && requestCopy) ? requestCopy
|
|
42
|
+
: options.copyWritesMarkdown ? copyMarkdown
|
|
43
|
+
: copyRaw;
|
|
35
44
|
return [UIContextMenuConfiguration
|
|
36
45
|
configurationWithIdentifier:nil
|
|
37
46
|
previewProvider:nil
|
|
@@ -15,6 +15,9 @@ typedef struct {
|
|
|
15
15
|
// Drop every system-provided item from the text selection menu.
|
|
16
16
|
BOOL systemItemsNone;
|
|
17
17
|
BOOL codeBlockCopyButton;
|
|
18
|
+
// Copy hands the selection to the owner (JS `onCopy`) instead of writing the
|
|
19
|
+
// pasteboard.
|
|
20
|
+
BOOL interceptCopy;
|
|
18
21
|
// The owner must keep these strings alive for the duration of the call (the
|
|
19
22
|
// view holds them in strong ivars).
|
|
20
23
|
__unsafe_unretained NSString *_Nullable copyLabel;
|
|
@@ -24,6 +27,10 @@ typedef struct {
|
|
|
24
27
|
__unsafe_unretained NSArray<NSString *> *_Nullable copyImageUrlPluralTemplates;
|
|
25
28
|
} ENRMSelectionMenuConfig;
|
|
26
29
|
|
|
30
|
+
/// Receives an intercepted Copy. `fullSelection` is whether the range spans the
|
|
31
|
+
/// whole attributed text, in which case `markdown` is the cached markdown.
|
|
32
|
+
typedef void (^ENRMCopyRequestHandler)(NSString *markdown, NSString *text, BOOL fullSelection);
|
|
33
|
+
|
|
27
34
|
/// Resolves the "Copy Image URL(s)" menu title for a given image count.
|
|
28
35
|
/// Uses the precomputed plural templates (indexed by count, 0..100) when present;
|
|
29
36
|
/// counts > 100 use the "other" form (copyImageUrlsLabel). Otherwise the
|
|
@@ -87,6 +94,7 @@ static inline ENRMSelectionMenuConfig ENRMBuildSelectionMenuConfig(const ENRMSel
|
|
|
87
94
|
.copyFormatMarkdown = src.copyFormatMarkdown,
|
|
88
95
|
.systemItemsNone = src.systemItemsNone,
|
|
89
96
|
.codeBlockCopyButton = src.codeBlockCopyButton,
|
|
97
|
+
.interceptCopy = src.interceptCopy,
|
|
90
98
|
.copyLabel = labels.copyLabel,
|
|
91
99
|
.copyAsMarkdownLabel = labels.copyAsMarkdownLabel,
|
|
92
100
|
.copyImageUrlLabel = labels.copyImageUrlLabel,
|
|
@@ -107,7 +115,8 @@ extern "C" {
|
|
|
107
115
|
UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange range, NSString *_Nullable cachedMarkdown,
|
|
108
116
|
StyleConfig *styleConfig, NSArray<UIMenuElement *> *suggestedActions,
|
|
109
117
|
NSArray<UIAction *> *_Nullable customActions,
|
|
110
|
-
ENRMSelectionMenuConfig selectionMenuConfig
|
|
118
|
+
ENRMSelectionMenuConfig selectionMenuConfig,
|
|
119
|
+
ENRMCopyRequestHandler _Nullable onCopyRequest) API_AVAILABLE(ios(16.0));
|
|
111
120
|
#else
|
|
112
121
|
NSMenu *_Nullable buildEditMenuForSelection(NSAttributedString *attributedText, NSRange range,
|
|
113
122
|
NSString *_Nullable cachedMarkdown, StyleConfig *styleConfig,
|
|
@@ -10,12 +10,22 @@ static NSString *const kActionIdentifierCopy = @"com.swmansion.enriched.markdown
|
|
|
10
10
|
static NSString *const kActionIdentifierCopyMarkdown = @"com.swmansion.enriched.markdown.copyMarkdown";
|
|
11
11
|
static NSString *const kActionIdentifierCopyImageURL = @"com.swmansion.enriched.markdown.copyImageURL";
|
|
12
12
|
|
|
13
|
-
static UIAction *_Nullable createCopyAction(NSAttributedString *selectedText, NSString *markdown,
|
|
14
|
-
StyleConfig *styleConfig, ENRMSelectionMenuConfig selectionMenuConfig
|
|
13
|
+
static UIAction *_Nullable createCopyAction(NSAttributedString *selectedText, NSString *markdown, BOOL fullSelection,
|
|
14
|
+
StyleConfig *styleConfig, ENRMSelectionMenuConfig selectionMenuConfig,
|
|
15
|
+
ENRMCopyRequestHandler _Nullable onCopyRequest)
|
|
15
16
|
{
|
|
16
17
|
if (!selectionMenuConfig.copyEnabled)
|
|
17
18
|
return nil;
|
|
18
19
|
|
|
20
|
+
if (selectionMenuConfig.interceptCopy && onCopyRequest) {
|
|
21
|
+
NSString *text = selectedText.string;
|
|
22
|
+
NSString *copied = markdown.length > 0 ? markdown : text;
|
|
23
|
+
return [UIAction actionWithTitle:selectionMenuConfig.copyLabel
|
|
24
|
+
image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
|
|
25
|
+
identifier:kActionIdentifierCopy
|
|
26
|
+
handler:^(__kindof UIAction *action) { onCopyRequest(copied, text, fullSelection); }];
|
|
27
|
+
}
|
|
28
|
+
|
|
19
29
|
BOOL writesMarkdown = selectionMenuConfig.copyFormatMarkdown;
|
|
20
30
|
return [UIAction actionWithTitle:selectionMenuConfig.copyLabel
|
|
21
31
|
image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
|
|
@@ -108,13 +118,17 @@ static void insertOptionalAction(NSMutableArray<UIMenuElement *> *array, UIActio
|
|
|
108
118
|
UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange range, NSString *_Nullable cachedMarkdown,
|
|
109
119
|
StyleConfig *styleConfig, NSArray<UIMenuElement *> *suggestedActions,
|
|
110
120
|
NSArray<UIAction *> *_Nullable customActions,
|
|
111
|
-
ENRMSelectionMenuConfig selectionMenuConfig
|
|
121
|
+
ENRMSelectionMenuConfig selectionMenuConfig,
|
|
122
|
+
ENRMCopyRequestHandler _Nullable onCopyRequest) API_AVAILABLE(ios(16.0))
|
|
112
123
|
{
|
|
113
124
|
NSAttributedString *selectedText = [attributedText attributedSubstringFromRange:range];
|
|
114
125
|
NSString *markdown = markdownForRange(attributedText, range, cachedMarkdown);
|
|
115
126
|
NSArray<NSString *> *imageURLs = imageURLsInRange(attributedText, range);
|
|
127
|
+
// Same threshold markdownForRange uses to return the cached markdown.
|
|
128
|
+
BOOL fullSelection = range.location == 0 && range.length >= attributedText.length - 1;
|
|
116
129
|
|
|
117
|
-
UIAction *copyAction =
|
|
130
|
+
UIAction *copyAction =
|
|
131
|
+
createCopyAction(selectedText, markdown, fullSelection, styleConfig, selectionMenuConfig, onCopyRequest);
|
|
118
132
|
UIAction *copyMarkdownAction = selectionMenuConfig.copyAsMarkdown
|
|
119
133
|
? createCopyMarkdownAction(markdown, selectionMenuConfig.copyAsMarkdownLabel)
|
|
120
134
|
: nil;
|
|
@@ -42,6 +42,10 @@ typedef void (^ENRMCodeBlockCopyBlock)(NSString *code, NSString *language);
|
|
|
42
42
|
/// the header button and VoiceOver action always copy the raw code.
|
|
43
43
|
@property (nonatomic, assign) ENRMBlockMenuOptions menuOptions;
|
|
44
44
|
|
|
45
|
+
/// Set by the host; receives the Copy item's content when
|
|
46
|
+
/// `menuOptions.interceptCopy` is set.
|
|
47
|
+
@property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
|
|
48
|
+
|
|
45
49
|
// Fired when the code is copied (header button, context-menu Copy, or the
|
|
46
50
|
// VoiceOver copy action); set by the host to bridge up to the JS onCopyPress
|
|
47
51
|
// event. Not fired for "Copy as Markdown", nor for the context-menu Copy when
|
|
@@ -500,7 +500,14 @@ static BOOL ENRMColorIsDark(RCTUIColor *color)
|
|
|
500
500
|
__weak __typeof(self) weakSelf = self;
|
|
501
501
|
return ENRMBlockContextMenuConfiguration(
|
|
502
502
|
self.menuOptions, self.copyLabel, self.copyAsMarkdownLabel, ^{ [weakSelf copyCodeToPasteboard]; },
|
|
503
|
-
^{ [weakSelf copyMarkdownToPasteboard]; });
|
|
503
|
+
^{ [weakSelf copyMarkdownToPasteboard]; }, ^{ [weakSelf requestCopy]; });
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
- (void)requestCopy
|
|
507
|
+
{
|
|
508
|
+
if (self.onCopyRequest) {
|
|
509
|
+
self.onCopyRequest([self fencedMarkdown], _cachedCode ?: @"");
|
|
510
|
+
}
|
|
504
511
|
}
|
|
505
512
|
#endif
|
|
506
513
|
|
|
@@ -39,6 +39,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
39
39
|
/// Copy / Copy as Markdown visibility and Copy format from `selectionMenuConfig`.
|
|
40
40
|
@property (nonatomic, assign) ENRMBlockMenuOptions menuOptions;
|
|
41
41
|
|
|
42
|
+
/// Set by the host; receives the Copy item's content when
|
|
43
|
+
/// `menuOptions.interceptCopy` is set.
|
|
44
|
+
@property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
|
|
45
|
+
|
|
42
46
|
@end
|
|
43
47
|
|
|
44
48
|
NS_ASSUME_NONNULL_END
|
|
@@ -133,7 +133,14 @@
|
|
|
133
133
|
__weak __typeof(self) weakSelf = self;
|
|
134
134
|
return ENRMBlockContextMenuConfiguration(
|
|
135
135
|
self.menuOptions, self.copyLabel, self.copyAsMarkdownLabel, ^{ [weakSelf copyLatexToPasteboard]; },
|
|
136
|
-
^{ [weakSelf copyMarkdownToPasteboard]; });
|
|
136
|
+
^{ [weakSelf copyMarkdownToPasteboard]; }, ^{ [weakSelf requestCopy]; });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
- (void)requestCopy
|
|
140
|
+
{
|
|
141
|
+
if (self.onCopyRequest) {
|
|
142
|
+
self.onCopyRequest([NSString stringWithFormat:@"$$\n%@\n$$", _cachedLatex ?: @""], _cachedLatex ?: @"");
|
|
143
|
+
}
|
|
137
144
|
}
|
|
138
145
|
#endif
|
|
139
146
|
|
|
@@ -60,6 +60,10 @@ typedef void (^TableLinkPressBlock)(NSString *url);
|
|
|
60
60
|
/// Copy / Copy as Markdown visibility and Copy format from `selectionMenuConfig`.
|
|
61
61
|
@property (nonatomic, assign) ENRMBlockMenuOptions menuOptions;
|
|
62
62
|
|
|
63
|
+
/// Set by the host; receives the Copy item's content when
|
|
64
|
+
/// `menuOptions.interceptCopy` is set.
|
|
65
|
+
@property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
|
|
66
|
+
|
|
63
67
|
@property (nonatomic, readonly) NSUInteger rowCount;
|
|
64
68
|
|
|
65
69
|
- (void)animateNewRowsFromPreviousCount:(NSUInteger)previousRowCount duration:(NSTimeInterval)duration;
|
|
@@ -264,8 +264,7 @@ static void ENRMTableComputeLayout(NSArray<NSArray<TableCellData *> *> *rows, NS
|
|
|
264
264
|
// a single drawRect: pass (no subview / layer compositing issues).
|
|
265
265
|
ENRMTableGridView *gridView = [[ENRMTableGridView alloc] initWithFrame:CGRectZero];
|
|
266
266
|
__weak TableContainerView *weakSelf = self;
|
|
267
|
-
gridView.menuProvider = ^NSMenu *
|
|
268
|
-
{
|
|
267
|
+
gridView.menuProvider = ^NSMenu * {
|
|
269
268
|
TableContainerView *strongSelf = weakSelf;
|
|
270
269
|
if (!strongSelf)
|
|
271
270
|
return nil;
|
|
@@ -471,7 +470,14 @@ static void ENRMTableComputeLayout(NSArray<NSArray<TableCellData *> *> *rows, NS
|
|
|
471
470
|
__weak __typeof(self) weakSelf = self;
|
|
472
471
|
return ENRMBlockContextMenuConfiguration(
|
|
473
472
|
self.menuOptions, self.copyLabel, self.copyAsMarkdownLabel, ^{ [weakSelf copyTableToPasteboard]; },
|
|
474
|
-
^{ [weakSelf copyMarkdownToPasteboard]; });
|
|
473
|
+
^{ [weakSelf copyMarkdownToPasteboard]; }, ^{ [weakSelf requestCopy]; });
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
- (void)requestCopy
|
|
477
|
+
{
|
|
478
|
+
if (self.onCopyRequest) {
|
|
479
|
+
self.onCopyRequest(_cachedMarkdown ?: @"", [self buildPlainTextFromRows] ?: @"");
|
|
480
|
+
}
|
|
475
481
|
}
|
|
476
482
|
#endif // !TARGET_OS_OSX
|
|
477
483
|
|
|
@@ -256,6 +256,14 @@ export interface CopyPressEvent {
|
|
|
256
256
|
language: string;
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
export interface CopyRequestEvent {
|
|
260
|
+
// 'selection' | 'math' | 'table' | 'code'
|
|
261
|
+
source: string;
|
|
262
|
+
markdown: string;
|
|
263
|
+
text: string;
|
|
264
|
+
whole: boolean;
|
|
265
|
+
}
|
|
266
|
+
|
|
259
267
|
export interface ContextMenuItemConfig {
|
|
260
268
|
text: string;
|
|
261
269
|
icon?: string;
|
|
@@ -284,6 +292,8 @@ export interface SelectionMenuConfig {
|
|
|
284
292
|
systemItemsNone: boolean;
|
|
285
293
|
// false hides the copy button in the code block header.
|
|
286
294
|
codeBlockCopyButton: boolean;
|
|
295
|
+
// true: the Copy item emits onCopyRequest instead of writing the clipboard.
|
|
296
|
+
interceptCopy: boolean;
|
|
287
297
|
}
|
|
288
298
|
|
|
289
299
|
export interface OnContextMenuItemPressEvent {
|
|
@@ -410,6 +420,12 @@ export interface NativeProps extends ViewProps {
|
|
|
410
420
|
* action. Receives the copied code and its language.
|
|
411
421
|
*/
|
|
412
422
|
onCopyPress?: CodegenTypes.BubblingEventHandler<CopyPressEvent>;
|
|
423
|
+
/**
|
|
424
|
+
* Fired instead of writing the clipboard when the Copy item of the text
|
|
425
|
+
* selection menu or a table / math / code block menu is pressed while
|
|
426
|
+
* `selectionMenuConfig.interceptCopy` is set.
|
|
427
|
+
*/
|
|
428
|
+
onCopyRequest?: CodegenTypes.BubblingEventHandler<CopyRequestEvent>;
|
|
413
429
|
/**
|
|
414
430
|
* Controls whether the system link preview is shown on long press (iOS only).
|
|
415
431
|
*
|
|
@@ -257,6 +257,14 @@ export interface CopyPressEvent {
|
|
|
257
257
|
language: string;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
export interface CopyRequestEvent {
|
|
261
|
+
// 'selection' | 'math' | 'table' | 'code'
|
|
262
|
+
source: string;
|
|
263
|
+
markdown: string;
|
|
264
|
+
text: string;
|
|
265
|
+
whole: boolean;
|
|
266
|
+
}
|
|
267
|
+
|
|
260
268
|
export interface ContextMenuItemConfig {
|
|
261
269
|
text: string;
|
|
262
270
|
icon?: string;
|
|
@@ -285,6 +293,8 @@ export interface SelectionMenuConfig {
|
|
|
285
293
|
systemItemsNone: boolean;
|
|
286
294
|
// false hides the copy button in the code block header.
|
|
287
295
|
codeBlockCopyButton: boolean;
|
|
296
|
+
// true: the Copy item emits onCopyRequest instead of writing the clipboard.
|
|
297
|
+
interceptCopy: boolean;
|
|
288
298
|
}
|
|
289
299
|
|
|
290
300
|
export interface OnContextMenuItemPressEvent {
|
|
@@ -411,6 +421,12 @@ export interface NativeProps extends ViewProps {
|
|
|
411
421
|
* action. Receives the copied code and its language.
|
|
412
422
|
*/
|
|
413
423
|
onCopyPress?: CodegenTypes.BubblingEventHandler<CopyPressEvent>;
|
|
424
|
+
/**
|
|
425
|
+
* Fired instead of writing the clipboard when the Copy item of the text
|
|
426
|
+
* selection menu or a table / math / code block menu is pressed while
|
|
427
|
+
* `selectionMenuConfig.interceptCopy` is set.
|
|
428
|
+
*/
|
|
429
|
+
onCopyRequest?: CodegenTypes.BubblingEventHandler<CopyRequestEvent>;
|
|
414
430
|
/**
|
|
415
431
|
* Controls whether the system link preview is shown on long press (iOS only).
|
|
416
432
|
*
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["default","EnrichedMarkdownText","DEFAULT_ACCESSIBILITY_LABELS","resolveAccessibilityLabels","EnrichedMarkdownTextInput"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,OAAO,IAAIC,oBAAoB,QAAQ,kCAA+B;
|
|
1
|
+
{"version":3,"names":["default","EnrichedMarkdownText","DEFAULT_ACCESSIBILITY_LABELS","resolveAccessibilityLabels","EnrichedMarkdownTextInput"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,OAAO,IAAIC,oBAAoB,QAAQ,kCAA+B;AAsB/E,SACEC,4BAA4B,EAC5BC,0BAA0B,QACrB,iCAA8B;AAErC,SAASC,yBAAyB,QAAQ,gCAA6B","ignoreList":[]}
|
|
@@ -73,6 +73,7 @@ export const EnrichedMarkdownText = ({
|
|
|
73
73
|
onTaskListItemPress,
|
|
74
74
|
enableTaskListItemToggle = true,
|
|
75
75
|
onCopyPress,
|
|
76
|
+
onCopy,
|
|
76
77
|
enableLinkPreview,
|
|
77
78
|
selectable = true,
|
|
78
79
|
md4cFlags = defaultMd4cFlags,
|
|
@@ -183,6 +184,24 @@ export const EnrichedMarkdownText = ({
|
|
|
183
184
|
language
|
|
184
185
|
});
|
|
185
186
|
}, [onCopyPress]);
|
|
187
|
+
const handleCopyRequest = useCallback(
|
|
188
|
+
// Codegen types `source` as a plain string; native only sends the four
|
|
189
|
+
// values of CopyEvent['source'].
|
|
190
|
+
e => {
|
|
191
|
+
const {
|
|
192
|
+
source,
|
|
193
|
+
markdown: copied,
|
|
194
|
+
text,
|
|
195
|
+
whole
|
|
196
|
+
} = e.nativeEvent;
|
|
197
|
+
onCopy?.({
|
|
198
|
+
source: source,
|
|
199
|
+
markdown: copied,
|
|
200
|
+
text,
|
|
201
|
+
whole
|
|
202
|
+
});
|
|
203
|
+
}, [onCopy]);
|
|
204
|
+
const interceptCopy = onCopy != null;
|
|
186
205
|
const tableMode = streamingConfig?.tableMode ?? 'progressive';
|
|
187
206
|
const codeBlockMode = streamingConfig?.codeBlockMode ?? 'progressive';
|
|
188
207
|
const normalizedStreamingConfig = useMemo(() => ({
|
|
@@ -210,9 +229,10 @@ export const EnrichedMarkdownText = ({
|
|
|
210
229
|
copyEnabled: copy.enabled,
|
|
211
230
|
copyFormatMarkdown: copyFormat === 'markdown',
|
|
212
231
|
systemItemsNone: config?.systemItems === 'none',
|
|
213
|
-
codeBlockCopyButton: codeBlockCopyButton.enabled
|
|
232
|
+
codeBlockCopyButton: codeBlockCopyButton.enabled,
|
|
233
|
+
interceptCopy
|
|
214
234
|
};
|
|
215
|
-
}, [selectionMenuConfig]);
|
|
235
|
+
}, [selectionMenuConfig, interceptCopy]);
|
|
216
236
|
const resolvedAccessibilityLabels = useMemo(() => resolveAccessibilityLabels(accessibilityLabels), [accessibilityLabels]);
|
|
217
237
|
const sharedProps = {
|
|
218
238
|
markdown,
|
|
@@ -222,6 +242,7 @@ export const EnrichedMarkdownText = ({
|
|
|
222
242
|
onTaskListItemPress: handleTaskListItemPress,
|
|
223
243
|
enableTaskListItemToggle,
|
|
224
244
|
onCopyPress: handleCopyPress,
|
|
245
|
+
onCopyRequest: handleCopyRequest,
|
|
225
246
|
enableLinkPreview: onLinkLongPress == null && (enableLinkPreview ?? true),
|
|
226
247
|
selectable,
|
|
227
248
|
md4cFlags: normalizedMd4cFlags,
|