react-native-enriched-markdown-scaffold 1.0.2-scaffold.4 → 1.0.2-scaffold.6

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 (71) hide show
  1. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +15 -0
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +15 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
  5. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +74 -0
  6. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +68 -0
  7. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +20 -0
  8. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +4 -0
  9. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +107 -0
  10. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +19 -0
  11. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +22 -0
  12. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -0
  13. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +22 -0
  14. package/android/src/main/java/com/swmansion/enriched/markdown/events/SelectionChangeEvent.kt +42 -0
  15. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +14 -0
  16. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +230 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +11 -1
  18. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +8 -1
  19. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +8 -1
  20. package/docs/API_REFERENCE.md +68 -0
  21. package/docs/WEB.md +1 -0
  22. package/ios/EnrichedMarkdown.mm +188 -2
  23. package/ios/EnrichedMarkdownText.mm +117 -1
  24. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +74 -0
  25. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +68 -0
  26. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +20 -0
  27. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +4 -0
  28. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +50 -2
  29. package/ios/utils/ENRMLinkChip.m +38 -20
  30. package/ios/utils/ENRMLinkLayout.m +12 -12
  31. package/ios/utils/ENRMSelectionChange.h +96 -0
  32. package/ios/utils/ENRMSelectionChange.m +204 -0
  33. package/ios/utils/EditMenuUtils+macOS.m +1 -1
  34. package/ios/utils/EditMenuUtils.h +3 -0
  35. package/ios/utils/EditMenuUtils.m +116 -0
  36. package/ios/utils/MarkdownAccessibilityElementBuilder.m +1 -2
  37. package/ios/views/ENRMCodeBlockContainerView.h +3 -0
  38. package/ios/views/ENRMCodeBlockContainerView.m +3 -0
  39. package/ios/views/ENRMMathContainerView.h +3 -0
  40. package/ios/views/ENRMMathContainerView.m +3 -0
  41. package/ios/views/TableContainerView.h +3 -0
  42. package/ios/views/TableContainerView.m +4 -1
  43. package/lib/module/EnrichedMarkdownNativeComponent.ts +70 -1
  44. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +70 -1
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/module/jest/index.js +14 -0
  47. package/lib/module/jest/index.js.map +1 -1
  48. package/lib/module/native/EnrichedMarkdownText.js +46 -4
  49. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  50. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +63 -2
  51. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  52. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +63 -2
  53. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  54. package/lib/typescript/src/index.d.ts +2 -2
  55. package/lib/typescript/src/index.d.ts.map +1 -1
  56. package/lib/typescript/src/jest/index.d.ts +1 -1
  57. package/lib/typescript/src/jest/index.d.ts.map +1 -1
  58. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +5 -5
  59. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  60. package/lib/typescript/src/types/MarkdownTextProps.d.ts +46 -3
  61. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  62. package/lib/typescript/src/types/events.d.ts +36 -0
  63. package/lib/typescript/src/types/events.d.ts.map +1 -1
  64. package/package.json +1 -1
  65. package/src/EnrichedMarkdownNativeComponent.ts +70 -1
  66. package/src/EnrichedMarkdownTextNativeComponent.ts +70 -1
  67. package/src/index.tsx +3 -0
  68. package/src/jest/index.tsx +22 -1
  69. package/src/native/EnrichedMarkdownText.tsx +87 -9
  70. package/src/types/MarkdownTextProps.ts +53 -2
  71. package/src/types/events.ts +38 -0
@@ -180,4 +180,120 @@ UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange ra
180
180
  return [UIMenu menuWithChildren:result];
181
181
  }
182
182
 
183
+ #import <objc/runtime.h>
184
+
185
+ static const void *kSelectionEditMenuPresenterKey = &kSelectionEditMenuPresenterKey;
186
+
187
+ API_AVAILABLE(ios(16.0))
188
+ @interface ENRMSelectionEditMenuPresenter : NSObject <UIEditMenuInteractionDelegate>
189
+ @property (nonatomic, weak) UITextView *textView;
190
+ @property (nonatomic, strong) UIEditMenuInteraction *interaction;
191
+ @property (nonatomic, assign) NSRange range;
192
+ @end
193
+
194
+ @implementation ENRMSelectionEditMenuPresenter
195
+
196
+ - (UIMenu *)editMenuInteraction:(UIEditMenuInteraction *)interaction
197
+ menuForConfiguration:(UIEditMenuConfiguration *)configuration
198
+ suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions
199
+ {
200
+ UITextView *textView = self.textView;
201
+ id<UITextViewDelegate> delegate = textView.delegate;
202
+ if (!textView || ![delegate respondsToSelector:@selector(textView:editMenuForTextInRange:suggestedActions:)]) {
203
+ return nil;
204
+ }
205
+ return [delegate textView:textView editMenuForTextInRange:textView.selectedRange suggestedActions:suggestedActions];
206
+ }
207
+
208
+ - (CGRect)editMenuInteraction:(UIEditMenuInteraction *)interaction
209
+ targetRectForConfiguration:(UIEditMenuConfiguration *)configuration
210
+ {
211
+ UITextView *textView = self.textView;
212
+ UITextRange *textRange = textView.selectedTextRange;
213
+ if (!textView || !textRange) {
214
+ return CGRectNull;
215
+ }
216
+ return [textView firstRectForRange:textRange];
217
+ }
218
+
219
+ @end
220
+
221
+ static BOOL selectionEditMenuTextViewHasActiveGesture(UITextView *textView)
222
+ {
223
+ for (UIGestureRecognizer *recognizer in textView.gestureRecognizers) {
224
+ if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
225
+ return YES;
226
+ }
227
+ }
228
+ return NO;
229
+ }
230
+
231
+ static void presentSelectionEditMenu(UITextView *textView)
232
+ {
233
+ UITextRange *textRange = textView.selectedTextRange;
234
+ if (!textRange || textRange.isEmpty) {
235
+ return;
236
+ }
237
+ CGRect rect = [textView firstRectForRange:textRange];
238
+ if (CGRectIsNull(rect) || CGRectIsEmpty(rect)) {
239
+ return;
240
+ }
241
+ if (@available(iOS 16.0, *)) {
242
+ ENRMSelectionEditMenuPresenter *presenter = objc_getAssociatedObject(textView, kSelectionEditMenuPresenterKey);
243
+ if (!presenter) {
244
+ presenter = [[ENRMSelectionEditMenuPresenter alloc] init];
245
+ presenter.textView = textView;
246
+ presenter.interaction = [[UIEditMenuInteraction alloc] initWithDelegate:presenter];
247
+ [textView addInteraction:presenter.interaction];
248
+ objc_setAssociatedObject(textView, kSelectionEditMenuPresenterKey, presenter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
249
+ }
250
+ presenter.range = textView.selectedRange;
251
+ UIEditMenuConfiguration *configuration =
252
+ [UIEditMenuConfiguration configurationWithIdentifier:nil
253
+ sourcePoint:CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect))];
254
+ [presenter.interaction presentEditMenuWithConfiguration:configuration];
255
+ return;
256
+ }
257
+ #pragma clang diagnostic push
258
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
259
+ [[UIMenuController sharedMenuController] showMenuFromView:textView rect:rect];
260
+ #pragma clang diagnostic pop
261
+ }
262
+
263
+ static void presentSelectionEditMenuWhenTouchEnds(UITextView *textView, NSRange range, NSUInteger attemptsLeft)
264
+ {
265
+ if (!NSEqualRanges(textView.selectedRange, range)) {
266
+ return;
267
+ }
268
+ if (attemptsLeft > 0 && selectionEditMenuTextViewHasActiveGesture(textView)) {
269
+ __weak UITextView *weakTextView = textView;
270
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(50 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
271
+ UITextView *strongTextView = weakTextView;
272
+ if (strongTextView) {
273
+ presentSelectionEditMenuWhenTouchEnds(strongTextView, range, attemptsLeft - 1);
274
+ }
275
+ });
276
+ return;
277
+ }
278
+ presentSelectionEditMenu(textView);
279
+ }
280
+
281
+ void ENRMSelectRangeAndPresentEditMenu(UITextView *textView, NSRange range)
282
+ {
283
+ [textView becomeFirstResponder];
284
+ textView.selectedRange = range;
285
+ presentSelectionEditMenuWhenTouchEnds(textView, range, 200);
286
+ }
287
+
288
+ void ENRMDismissSelectionEditMenuIfMoved(UITextView *textView)
289
+ {
290
+ if (@available(iOS 16.0, *)) {
291
+ ENRMSelectionEditMenuPresenter *presenter = objc_getAssociatedObject(textView, kSelectionEditMenuPresenterKey);
292
+ if (presenter && !NSEqualRanges(textView.selectedRange, presenter.range)) {
293
+ presenter.range = NSMakeRange(NSNotFound, 0);
294
+ [presenter.interaction dismissMenu];
295
+ }
296
+ }
297
+ }
298
+
183
299
  #endif
@@ -115,8 +115,7 @@ static const CGFloat kFocusRectPadding = 2.0;
115
115
 
116
116
  BOOL isImg = item[@"altText"] != nil;
117
117
  // Link chips pad their text with spacer characters; keep them out of the spoken label.
118
- NSString *label = isImg ? item[@"altText"]
119
- : ENRMPlainTextByRemovingLinkSpacers(textView.attributedText, itemRange);
118
+ NSString *label = isImg ? item[@"altText"] : ENRMPlainTextByRemovingLinkSpacers(textView.attributedText, itemRange);
120
119
  [elements addObject:[self createElementForRange:itemRange
121
120
  type:isImg ? ElementTypeImage : ElementTypeLink
122
121
  text:label
@@ -45,6 +45,9 @@ typedef void (^ENRMCodeBlockCopyBlock)(NSString *code, NSString *language);
45
45
  /// Set by the host; receives the Copy item's content when
46
46
  /// `menuOptions.interceptCopy` is set.
47
47
  @property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
48
+ /// Called instead of the menu on long press while `contextMenuHidden` is on, so
49
+ /// the owner can report the block (`onSelectionChange`) and show its own UI.
50
+ @property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onMenuSuppressed;
48
51
 
49
52
  // Fired when the code is copied (header button, context-menu Copy, or the
50
53
  // VoiceOver copy action); set by the host to bridge up to the JS onCopyPress
@@ -495,6 +495,9 @@ static BOOL ENRMColorIsDark(RCTUIColor *color)
495
495
  {
496
496
  // Returning nil is the UIKit-sanctioned way to suppress a context menu.
497
497
  if (_pending || self.contextMenuHidden) {
498
+ if (!_pending && self.onMenuSuppressed) {
499
+ self.onMenuSuppressed([self fencedMarkdown], _cachedCode ?: @"");
500
+ }
498
501
  return nil;
499
502
  }
500
503
  __weak __typeof(self) weakSelf = self;
@@ -42,6 +42,9 @@ NS_ASSUME_NONNULL_BEGIN
42
42
  /// Set by the host; receives the Copy item's content when
43
43
  /// `menuOptions.interceptCopy` is set.
44
44
  @property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
45
+ /// Called instead of the menu on long press while `contextMenuHidden` is on, so
46
+ /// the owner can report the block (`onSelectionChange`) and show its own UI.
47
+ @property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onMenuSuppressed;
45
48
 
46
49
  @end
47
50
 
@@ -128,6 +128,9 @@
128
128
  {
129
129
  // Returning nil is the UIKit-sanctioned way to suppress a context menu.
130
130
  if (self.contextMenuHidden) {
131
+ if (self.onMenuSuppressed) {
132
+ self.onMenuSuppressed([NSString stringWithFormat:@"$$\n%@\n$$", _cachedLatex ?: @""], _cachedLatex ?: @"");
133
+ }
131
134
  return nil;
132
135
  }
133
136
  __weak __typeof(self) weakSelf = self;
@@ -63,6 +63,9 @@ typedef void (^TableLinkPressBlock)(NSString *url);
63
63
  /// Set by the host; receives the Copy item's content when
64
64
  /// `menuOptions.interceptCopy` is set.
65
65
  @property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
66
+ /// Called instead of the menu on long press while `contextMenuHidden` is on, so
67
+ /// the owner can report the block (`onSelectionChange`) and show its own UI.
68
+ @property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onMenuSuppressed;
66
69
 
67
70
  @property (nonatomic, readonly) NSUInteger rowCount;
68
71
  /// Number of links across all cells. Tables are not reported by `onLinkLayout`,
@@ -1,7 +1,7 @@
1
1
  #import "TableContainerView.h"
2
- #import "ENRMLinkChip.h"
3
2
  #import "AttributedRenderer.h"
4
3
  #import "ENRMAccessibilityLabels.h"
4
+ #import "ENRMLinkChip.h"
5
5
  #import "HTMLGenerator.h"
6
6
  #import "LinkTapUtils.h"
7
7
  #import "MarkdownASTNode.h"
@@ -486,6 +486,9 @@ static void ENRMTableComputeLayout(NSArray<NSArray<TableCellData *> *> *rows, NS
486
486
  {
487
487
  // Returning nil is the UIKit-sanctioned way to suppress a context menu.
488
488
  if (self.contextMenuHidden) {
489
+ if (self.onMenuSuppressed) {
490
+ self.onMenuSuppressed(_cachedMarkdown ?: @"", [self buildPlainTextFromRows] ?: @"");
491
+ }
489
492
  return nil;
490
493
  }
491
494
  __weak __typeof(self) weakSelf = self;
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  codegenNativeComponent,
3
+ codegenNativeCommands,
3
4
  type ViewProps,
4
5
  type CodegenTypes,
5
6
  type ColorValue,
7
+ type HostComponent,
6
8
  } from 'react-native';
9
+ import type React from 'react';
7
10
 
8
11
  // All block styles extend this interface
9
12
  interface BaseBlockStyleInternal {
@@ -274,6 +277,39 @@ export interface LinkLayoutEvent {
274
277
  }[];
275
278
  }
276
279
 
280
+ /**
281
+ * Current text selection, or a long-pressed table / math / code block while
282
+ * `contextMenuHidden` is on. `active: false` means the selection was cleared
283
+ * (every other field is then empty / zero). Rects are in dp / pt, relative to
284
+ * the native view's origin; rect objects are written inline because codegen
285
+ * only accepts inline object literals in event payloads.
286
+ */
287
+ export interface SelectionChangeEvent {
288
+ active: boolean;
289
+ source: string;
290
+ text: string;
291
+ markdown: string;
292
+ whole: boolean;
293
+ rect: {
294
+ x: CodegenTypes.Double;
295
+ y: CodegenTypes.Double;
296
+ width: CodegenTypes.Double;
297
+ height: CodegenTypes.Double;
298
+ };
299
+ startRect: {
300
+ x: CodegenTypes.Double;
301
+ y: CodegenTypes.Double;
302
+ width: CodegenTypes.Double;
303
+ height: CodegenTypes.Double;
304
+ };
305
+ endRect: {
306
+ x: CodegenTypes.Double;
307
+ y: CodegenTypes.Double;
308
+ width: CodegenTypes.Double;
309
+ height: CodegenTypes.Double;
310
+ };
311
+ }
312
+
277
313
  export interface TaskListItemPressEvent {
278
314
  index: CodegenTypes.Int32;
279
315
  checked: boolean;
@@ -441,6 +477,18 @@ export interface NativeProps extends ViewProps {
441
477
  * Deduplicated: not re-fired when the payload is unchanged.
442
478
  */
443
479
  onLinkLayout?: CodegenTypes.DirectEventHandler<LinkLayoutEvent>;
480
+ /**
481
+ * When true, the view reports selection changes (and, with
482
+ * `contextMenuHidden`, block long-presses) through `onSelectionChange`.
483
+ * Set by the JS wrapper only when `onSelectionChange` is provided.
484
+ * @default false
485
+ */
486
+ emitSelectionChange?: CodegenTypes.WithDefault<boolean, false>;
487
+ /**
488
+ * Fired while `emitSelectionChange` is on: coalesced to one event per frame,
489
+ * deduplicated, and `active: false` once the selection is gone.
490
+ */
491
+ onSelectionChange?: CodegenTypes.DirectEventHandler<SelectionChangeEvent>;
444
492
  /**
445
493
  * Callback fired when a task list checkbox is tapped.
446
494
  * Receives the 0-based task index, current checked state, and the item's plain text.
@@ -480,6 +528,16 @@ export interface NativeProps extends ViewProps {
480
528
  * @default true
481
529
  */
482
530
  enableLinkPreview?: CodegenTypes.WithDefault<boolean, true>;
531
+ /**
532
+ * When `true`, long-pressing a link selects its label and shows the
533
+ * selection edit menu instead of the system link preview (iOS only).
534
+ * Takes precedence over `enableLinkPreview` and `onLinkLongPress`.
535
+ *
536
+ * Android: No-op.
537
+ *
538
+ * @default false
539
+ */
540
+ linkLongPressSelects?: CodegenTypes.WithDefault<boolean, false>;
483
541
  /**
484
542
  * - iOS: Controls text selection and link previews on long press.
485
543
  * - Android: Controls text selection.
@@ -594,6 +652,17 @@ export interface NativeProps extends ViewProps {
594
652
  writingDirection?: CodegenTypes.WithDefault<string, 'first-strong'>;
595
653
  }
596
654
 
655
+ type ComponentType = HostComponent<NativeProps>;
656
+
657
+ interface NativeCommands {
658
+ /** Clears the text selection (and any active block) and fires `onSelectionChange` with `active: false`. */
659
+ clearSelection: (viewRef: React.ElementRef<ComponentType>) => void;
660
+ }
661
+
662
+ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
663
+ supportedCommands: ['clearSelection'],
664
+ });
665
+
597
666
  export default codegenNativeComponent<NativeProps>('EnrichedMarkdown', {
598
667
  interfaceOnly: true,
599
- });
668
+ }) as HostComponent<NativeProps>;
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  codegenNativeComponent,
3
+ codegenNativeCommands,
3
4
  type ViewProps,
4
5
  type CodegenTypes,
5
6
  type ColorValue,
7
+ type HostComponent,
6
8
  } from 'react-native';
9
+ import type React from 'react';
7
10
 
8
11
  // All block styles extend this interface
9
12
  interface BaseBlockStyleInternal {
@@ -275,6 +278,39 @@ export interface LinkLayoutEvent {
275
278
  }[];
276
279
  }
277
280
 
281
+ /**
282
+ * Current text selection, or a long-pressed table / math / code block while
283
+ * `contextMenuHidden` is on. `active: false` means the selection was cleared
284
+ * (every other field is then empty / zero). Rects are in dp / pt, relative to
285
+ * the native view's origin; rect objects are written inline because codegen
286
+ * only accepts inline object literals in event payloads.
287
+ */
288
+ export interface SelectionChangeEvent {
289
+ active: boolean;
290
+ source: string;
291
+ text: string;
292
+ markdown: string;
293
+ whole: boolean;
294
+ rect: {
295
+ x: CodegenTypes.Double;
296
+ y: CodegenTypes.Double;
297
+ width: CodegenTypes.Double;
298
+ height: CodegenTypes.Double;
299
+ };
300
+ startRect: {
301
+ x: CodegenTypes.Double;
302
+ y: CodegenTypes.Double;
303
+ width: CodegenTypes.Double;
304
+ height: CodegenTypes.Double;
305
+ };
306
+ endRect: {
307
+ x: CodegenTypes.Double;
308
+ y: CodegenTypes.Double;
309
+ width: CodegenTypes.Double;
310
+ height: CodegenTypes.Double;
311
+ };
312
+ }
313
+
278
314
  export interface TaskListItemPressEvent {
279
315
  index: CodegenTypes.Int32;
280
316
  checked: boolean;
@@ -442,6 +478,18 @@ export interface NativeProps extends ViewProps {
442
478
  * Deduplicated: not re-fired when the payload is unchanged.
443
479
  */
444
480
  onLinkLayout?: CodegenTypes.DirectEventHandler<LinkLayoutEvent>;
481
+ /**
482
+ * When true, the view reports selection changes (and, with
483
+ * `contextMenuHidden`, block long-presses) through `onSelectionChange`.
484
+ * Set by the JS wrapper only when `onSelectionChange` is provided.
485
+ * @default false
486
+ */
487
+ emitSelectionChange?: CodegenTypes.WithDefault<boolean, false>;
488
+ /**
489
+ * Fired while `emitSelectionChange` is on: coalesced to one event per frame,
490
+ * deduplicated, and `active: false` once the selection is gone.
491
+ */
492
+ onSelectionChange?: CodegenTypes.DirectEventHandler<SelectionChangeEvent>;
445
493
  /**
446
494
  * Callback fired when a task list checkbox is tapped.
447
495
  * Receives the 0-based task index, current checked state, and the item's plain text.
@@ -481,6 +529,16 @@ export interface NativeProps extends ViewProps {
481
529
  * @default true
482
530
  */
483
531
  enableLinkPreview?: CodegenTypes.WithDefault<boolean, true>;
532
+ /**
533
+ * When `true`, long-pressing a link selects its label and shows the
534
+ * selection edit menu instead of the system link preview (iOS only).
535
+ * Takes precedence over `enableLinkPreview` and `onLinkLongPress`.
536
+ *
537
+ * Android: No-op.
538
+ *
539
+ * @default false
540
+ */
541
+ linkLongPressSelects?: CodegenTypes.WithDefault<boolean, false>;
484
542
  /**
485
543
  * - iOS: Controls text selection and link previews on long press.
486
544
  * - Android: Controls text selection.
@@ -594,6 +652,17 @@ export interface NativeProps extends ViewProps {
594
652
  writingDirection?: CodegenTypes.WithDefault<string, 'first-strong'>;
595
653
  }
596
654
 
655
+ type ComponentType = HostComponent<NativeProps>;
656
+
657
+ interface NativeCommands {
658
+ /** Clears the text selection (and any active block) and fires `onSelectionChange` with `active: false`. */
659
+ clearSelection: (viewRef: React.ElementRef<ComponentType>) => void;
660
+ }
661
+
662
+ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
663
+ supportedCommands: ['clearSelection'],
664
+ });
665
+
597
666
  export default codegenNativeComponent<NativeProps>('EnrichedMarkdownText', {
598
667
  interfaceOnly: true,
599
- });
668
+ }) as HostComponent<NativeProps>;
@@ -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;AAwB/E,SACEC,4BAA4B,EAC5BC,0BAA0B,QACrB,iCAA8B;AAErC,SAASC,yBAAyB,QAAQ,gCAA6B","ignoreList":[]}
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;AA2B/E,SACEC,4BAA4B,EAC5BC,0BAA0B,QACrB,iCAA8B;AAErC,SAASC,yBAAyB,QAAQ,gCAA6B","ignoreList":[]}
@@ -143,6 +143,7 @@ export const EnrichedMarkdownTextInput = ({
143
143
  });
144
144
  };
145
145
  export const EnrichedMarkdownText = ({
146
+ ref,
146
147
  markdown,
147
148
  containerStyle,
148
149
  testID,
@@ -156,7 +157,9 @@ export const EnrichedMarkdownText = ({
156
157
  onLinkPress: _onLinkPress,
157
158
  onLinkLongPress: _onLinkLongPress,
158
159
  onTaskListItemPress: _onTaskListItemPress,
160
+ onSelectionChange: _onSelectionChange,
159
161
  enableLinkPreview: _enableLinkPreview,
162
+ linkLongPressSelects: _linkLongPressSelects,
160
163
  selectable: _selectable,
161
164
  md4cFlags: _md4cFlags,
162
165
  allowFontScaling: _allowFontScaling,
@@ -176,6 +179,17 @@ export const EnrichedMarkdownText = ({
176
179
  lineBreakStrategyIOS: _lineBreakStrategyIOS,
177
180
  writingDirection: _writingDirection
178
181
  }) => {
182
+ const instanceRef = useRef(null);
183
+ if (instanceRef.current === null) {
184
+ instanceRef.current = {
185
+ // No native selection under Jest; the mock records the call.
186
+ clearSelection: spy(() => {}),
187
+ measure: spy(callback => callback(0, 0, 0, 0, 0, 0)),
188
+ measureInWindow: spy(callback => callback(0, 0, 0, 0)),
189
+ measureLayout: spy((_relativeToNativeNode, onSuccess) => onSuccess(0, 0, 0, 0))
190
+ };
191
+ }
192
+ useImperativeHandle(ref, () => instanceRef.current);
179
193
  return /*#__PURE__*/_jsx(Text, {
180
194
  style: containerStyle,
181
195
  testID: testID,
@@ -1 +1 @@
1
- {"version":3,"names":["useImperativeHandle","useRef","useState","Text","TextInput","jsx","_jsx","DEFAULT_ACCESSIBILITY_LABELS","resolveAccessibilityLabels","spy","impl","jest","fn","EMPTY_CARET_RECT","x","y","width","height","EnrichedMarkdownTextInput","ref","defaultValue","onChangeText","onChangeMarkdown","onFocus","onBlur","editable","placeholder","placeholderTextColor","autoFocus","multiline","scrollEnabled","style","testID","accessible","accessibilityLabel","accessibilityHint","accessibilityRole","accessibilityState","nativeID","markdownStyle","_markdownStyle","cursorColor","_cursorColor","selectionColor","_selectionColor","autoCapitalize","_autoCapitalize","onChangeSelection","_onChangeSelection","onChangeState","_onChangeState","onKeyPress","_onKeyPress","onCaretRectChange","_onCaretRectChange","onLinkDetected","_onLinkDetected","mentionIndicators","_mentionIndicators","onStartMention","_onStartMention","onChangeMention","_onChangeMention","onEndMention","_onEndMention","contextMenuItems","_contextMenuItems","selectionMenuConfig","_selectionMenuConfig","formatMenuConfig","_formatMenuConfig","linkRegex","_linkRegex","writingDirection","_writingDirection","text","setText","textRef","inputRef","applyText","next","current","handleChangeText","instanceRef","focus","blur","measure","callback","measureInWindow","measureLayout","_relativeToNativeNode","onSuccess","setValue","markdown","setSelection","_start","_end","toggleBold","toggleItalic","toggleUnderline","toggleStrikethrough","toggleSpoiler","toggleHeading","_level","toggleUnorderedList","toggleOrderedList","indentList","outdentList","setLink","_url","insertLink","_text","insertText","insertMention","_displayText","startMention","_indicator","removeLink","copyToClipboard","resolvePaste","_markdown","insertMath","_latex","_options","updateMath","removeMath","getMarkdown","Promise","resolve","getCaretRect","value","EnrichedMarkdownText","containerStyle","onLinkPress","_onLinkPress","onLinkLongPress","_onLinkLongPress","onTaskListItemPress","_onTaskListItemPress","enableLinkPreview","_enableLinkPreview","selectable","_selectable","md4cFlags","_md4cFlags","allowFontScaling","_allowFontScaling","maxFontSizeMultiplier","_maxFontSizeMultiplier","allowTrailingMargin","_allowTrailingMargin","flavor","_flavor","streamingAnimation","_streamingAnimation","streamingConfig","_streamingConfig","spoilerOverlay","_spoilerOverlay","imageRequestHeaders","_imageRequestHeaders","accessibilityLabels","_accessibilityLabels","selectionHandleColor","_selectionHandleColor","textBreakStrategy","_textBreakStrategy","lineBreakStrategyIOS","_lineBreakStrategyIOS","children"],"sourceRoot":"../../../src","sources":["jest/index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useImperativeHandle","useRef","useState","Text","TextInput","jsx","_jsx","DEFAULT_ACCESSIBILITY_LABELS","resolveAccessibilityLabels","spy","impl","jest","fn","EMPTY_CARET_RECT","x","y","width","height","EnrichedMarkdownTextInput","ref","defaultValue","onChangeText","onChangeMarkdown","onFocus","onBlur","editable","placeholder","placeholderTextColor","autoFocus","multiline","scrollEnabled","style","testID","accessible","accessibilityLabel","accessibilityHint","accessibilityRole","accessibilityState","nativeID","markdownStyle","_markdownStyle","cursorColor","_cursorColor","selectionColor","_selectionColor","autoCapitalize","_autoCapitalize","onChangeSelection","_onChangeSelection","onChangeState","_onChangeState","onKeyPress","_onKeyPress","onCaretRectChange","_onCaretRectChange","onLinkDetected","_onLinkDetected","mentionIndicators","_mentionIndicators","onStartMention","_onStartMention","onChangeMention","_onChangeMention","onEndMention","_onEndMention","contextMenuItems","_contextMenuItems","selectionMenuConfig","_selectionMenuConfig","formatMenuConfig","_formatMenuConfig","linkRegex","_linkRegex","writingDirection","_writingDirection","text","setText","textRef","inputRef","applyText","next","current","handleChangeText","instanceRef","focus","blur","measure","callback","measureInWindow","measureLayout","_relativeToNativeNode","onSuccess","setValue","markdown","setSelection","_start","_end","toggleBold","toggleItalic","toggleUnderline","toggleStrikethrough","toggleSpoiler","toggleHeading","_level","toggleUnorderedList","toggleOrderedList","indentList","outdentList","setLink","_url","insertLink","_text","insertText","insertMention","_displayText","startMention","_indicator","removeLink","copyToClipboard","resolvePaste","_markdown","insertMath","_latex","_options","updateMath","removeMath","getMarkdown","Promise","resolve","getCaretRect","value","EnrichedMarkdownText","containerStyle","onLinkPress","_onLinkPress","onLinkLongPress","_onLinkLongPress","onTaskListItemPress","_onTaskListItemPress","onSelectionChange","_onSelectionChange","enableLinkPreview","_enableLinkPreview","linkLongPressSelects","_linkLongPressSelects","selectable","_selectable","md4cFlags","_md4cFlags","allowFontScaling","_allowFontScaling","maxFontSizeMultiplier","_maxFontSizeMultiplier","allowTrailingMargin","_allowTrailingMargin","flavor","_flavor","streamingAnimation","_streamingAnimation","streamingConfig","_streamingConfig","spoilerOverlay","_spoilerOverlay","imageRequestHeaders","_imageRequestHeaders","accessibilityLabels","_accessibilityLabels","selectionHandleColor","_selectionHandleColor","textBreakStrategy","_textBreakStrategy","lineBreakStrategyIOS","_lineBreakStrategyIOS","clearSelection","children"],"sourceRoot":"../../../src","sources":["jest/index.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
 
3
- import { useMemo, useCallback, useRef, useEffect, useState } from 'react';
4
- import EnrichedMarkdownTextNativeComponent from '../EnrichedMarkdownTextNativeComponent';
5
- import EnrichedMarkdownNativeComponent from '../EnrichedMarkdownNativeComponent';
3
+ import { useMemo, useCallback, useRef, useEffect, useState, useImperativeHandle } from 'react';
4
+ import EnrichedMarkdownTextNativeComponent, { Commands as TextCommands } from '../EnrichedMarkdownTextNativeComponent';
5
+ import EnrichedMarkdownNativeComponent, { Commands as MarkdownCommands } from '../EnrichedMarkdownNativeComponent';
6
6
  import { normalizeMarkdownStyle } from '../normalizeMarkdownStyle';
7
7
  import { resolveAccessibilityLabels } from "../accessibilityLabelDefaults.js";
8
8
  import { normalizeMenuItem, normalizeLegacyBooleanMenuItem } from "../normalizeMenuItem.js";
@@ -104,6 +104,7 @@ const defaultMd4cFlags = {
104
104
  hardSoftBreaks: false
105
105
  };
106
106
  export const EnrichedMarkdownText = ({
107
+ ref,
107
108
  markdown,
108
109
  markdownStyle = {},
109
110
  containerStyle,
@@ -113,7 +114,9 @@ export const EnrichedMarkdownText = ({
113
114
  enableTaskListItemToggle = true,
114
115
  onCopyPress,
115
116
  onCopy,
117
+ onSelectionChange,
116
118
  enableLinkPreview,
119
+ linkLongPressSelects = false,
117
120
  selectable = true,
118
121
  md4cFlags = defaultMd4cFlags,
119
122
  allowFontScaling = true,
@@ -260,6 +263,40 @@ export const EnrichedMarkdownText = ({
260
263
  y
261
264
  });
262
265
  }, []);
266
+
267
+ // Rects stay relative to the native view — the view the ref's
268
+ // `measureInWindow` measures — even when decorations wrap it.
269
+ const handleSelectionChange = useCallback(
270
+ // Codegen types `source` as a plain string; native only sends the four
271
+ // values of SelectionChangeEvent['source'].
272
+ e => {
273
+ const {
274
+ source,
275
+ ...payload
276
+ } = e.nativeEvent;
277
+ onSelectionChange?.({
278
+ ...payload,
279
+ source: source
280
+ });
281
+ }, [onSelectionChange]);
282
+ const nativeRef = useRef(null);
283
+ const isGithubFlavor = flavor === 'github';
284
+ useImperativeHandle(ref, () => ({
285
+ clearSelection: () => {
286
+ const node = nativeRef.current;
287
+ if (node == null) return;
288
+ // Codegen's ViewRef resolves to `never` with RN 0.84's function-based
289
+ // HostComponent type — the cast is safe at runtime.
290
+ if (isGithubFlavor) {
291
+ MarkdownCommands.clearSelection(node);
292
+ } else {
293
+ TextCommands.clearSelection(node);
294
+ }
295
+ },
296
+ measure: callback => nativeRef.current?.measure(callback),
297
+ measureInWindow: callback => nativeRef.current?.measureInWindow(callback),
298
+ measureLayout: (relativeToNativeNode, onSuccess, onFail) => nativeRef.current?.measureLayout(relativeToNativeNode, onSuccess, onFail)
299
+ }), [isGithubFlavor]);
263
300
  const tableMode = streamingConfig?.tableMode ?? 'progressive';
264
301
  const codeBlockMode = streamingConfig?.codeBlockMode ?? 'progressive';
265
302
  const normalizedStreamingConfig = useMemo(() => ({
@@ -301,7 +338,10 @@ export const EnrichedMarkdownText = ({
301
338
  enableTaskListItemToggle,
302
339
  onCopyPress: handleCopyPress,
303
340
  onCopyRequest: handleCopyRequest,
341
+ emitSelectionChange: onSelectionChange != null,
342
+ onSelectionChange: handleSelectionChange,
304
343
  enableLinkPreview: onLinkLongPress == null && (enableLinkPreview ?? true),
344
+ linkLongPressSelects,
305
345
  selectable,
306
346
  md4cFlags: normalizedMd4cFlags,
307
347
  allowFontScaling,
@@ -324,13 +364,14 @@ export const EnrichedMarkdownText = ({
324
364
  writingDirection,
325
365
  ...rest
326
366
  };
327
- const NativeComponent = flavor === 'github' ? EnrichedMarkdownNativeComponent : EnrichedMarkdownTextNativeComponent;
367
+ const NativeComponent = isGithubFlavor ? EnrichedMarkdownNativeComponent : EnrichedMarkdownTextNativeComponent;
328
368
 
329
369
  // Without decorations the native view is returned as-is (no wrapper, no
330
370
  // layout events) so existing layouts are untouched.
331
371
  if (!decorated) {
332
372
  return /*#__PURE__*/_jsx(NativeComponent, {
333
373
  ...sharedProps,
374
+ ref: nativeRef,
334
375
  onLayout: onLayout
335
376
  });
336
377
  }
@@ -339,6 +380,7 @@ export const EnrichedMarkdownText = ({
339
380
  onLayout: onLayout,
340
381
  children: [/*#__PURE__*/_jsx(NativeComponent, {
341
382
  ...sharedProps,
383
+ ref: nativeRef,
342
384
  style: undefined,
343
385
  emitLinkLayout: true,
344
386
  onLinkLayout: handleLinkLayout,