react-native-enriched-markdown-scaffold 0.6.0-scaffold.6 → 0.7.4-scaffold.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.
Files changed (190) hide show
  1. package/ReactNativeEnrichedMarkdown.podspec +62 -11
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +3 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +1 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +9 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +3 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +3 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +1 -0
  8. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +20 -0
  9. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +744 -36
  10. package/android/src/main/baseline-prof.txt +75 -2
  11. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +62 -0
  12. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +10 -2
  13. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +10 -0
  14. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +9 -2
  15. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +10 -0
  16. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +0 -1
  17. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt +15 -0
  18. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +44 -7
  19. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +52 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +55 -3
  21. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +19 -0
  22. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +22 -3
  23. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputRemend.kt +1 -0
  24. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +7 -1
  25. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +0 -3
  26. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +54 -13
  27. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +17 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +4 -4
  29. package/android/src/main/java/com/swmansion/enriched/markdown/spans/MathModels.kt +0 -1
  30. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +1 -3
  31. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +1 -3
  32. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +30 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +0 -14
  34. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkEvents.kt +22 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +36 -7
  36. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +73 -3
  37. package/android/src/main/jni/CMakeLists.txt +15 -1
  38. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +0 -1
  39. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -2
  40. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +1 -3
  41. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +1 -2
  42. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +25 -10
  43. package/app.plugin.js +2 -1
  44. package/cpp/parser/MD4CParser.cpp +1 -1
  45. package/cpp/wasm/build.sh +9 -9
  46. package/docs/ACCESSIBILITY.md +172 -0
  47. package/docs/API_REFERENCE.md +948 -0
  48. package/docs/COPY_OPTIONS.md +127 -0
  49. package/docs/ELEMENTS_STRUCTURE.md +112 -0
  50. package/docs/IMAGE_CACHING.md +25 -0
  51. package/docs/INPUT.md +233 -0
  52. package/docs/LATEX_MATH.md +136 -0
  53. package/docs/MACOS.md +19 -0
  54. package/docs/MARKDOWN_STREAMING.md +36 -0
  55. package/docs/MENTIONS.md +97 -0
  56. package/docs/RTL.md +82 -0
  57. package/docs/STYLES.md +519 -0
  58. package/docs/TEXT.md +110 -0
  59. package/docs/WEB.md +49 -0
  60. package/ios/EnrichedMarkdown.mm +82 -25
  61. package/ios/EnrichedMarkdownText.mm +37 -5
  62. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +1 -5
  63. package/ios/attachments/ENRMMathInlineAttachment.h +0 -3
  64. package/ios/attachments/ENRMMathInlineAttachment.m +1 -2
  65. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +20 -0
  66. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +744 -36
  67. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +15 -0
  68. package/ios/input/ENRMFormattingStore.h +5 -0
  69. package/ios/input/ENRMFormattingStore.mm +34 -0
  70. package/ios/input/ENRMInputFormatter.h +0 -6
  71. package/ios/input/ENRMInputFormatter.mm +0 -2
  72. package/ios/input/ENRMInputTextView.h +2 -0
  73. package/ios/input/ENRMInputTextView.mm +8 -17
  74. package/ios/input/ENRMMarkdownSerializer.mm +1 -1
  75. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +71 -53
  76. package/ios/input/EnrichedMarkdownTextInput+Internal.h +26 -0
  77. package/ios/input/EnrichedMarkdownTextInput.h +1 -0
  78. package/ios/input/EnrichedMarkdownTextInput.mm +207 -12
  79. package/ios/input/InputStylePropsUtils.h +0 -8
  80. package/ios/input/styles/ENRMBoldStyleHandler.mm +3 -2
  81. package/ios/input/styles/ENRMItalicStyleHandler.mm +3 -2
  82. package/ios/math/ENRMRaTeXBridge.swift +2 -16
  83. package/ios/renderer/AttributedRenderer.m +51 -6
  84. package/ios/renderer/ENRMMathInlineRenderer.m +5 -2
  85. package/ios/styles/ENRMFontSlot.h +1 -1
  86. package/ios/styles/StyleConfig.h +0 -4
  87. package/ios/styles/StyleConfig.mm +0 -24
  88. package/ios/utils/ENRMAccessibilityLabels.h +36 -0
  89. package/ios/utils/ENRMAccessibilityLabels.m +5 -0
  90. package/ios/utils/EditMenuUtils+macOS.m +4 -5
  91. package/ios/utils/EditMenuUtils.h +70 -0
  92. package/ios/utils/EditMenuUtils.m +14 -11
  93. package/ios/utils/LastElementUtils.h +39 -2
  94. package/ios/utils/MarkdownAccessibilityElementBuilder.h +18 -16
  95. package/ios/utils/MarkdownAccessibilityElementBuilder.m +64 -32
  96. package/ios/utils/ParagraphStyleUtils.m +21 -2
  97. package/ios/utils/StylePropsUtils.h +0 -10
  98. package/ios/views/ENRMMathContainerView.h +8 -0
  99. package/ios/views/ENRMMathContainerView.m +8 -7
  100. package/ios/views/ENRMTableIOSGridView.h +40 -0
  101. package/ios/views/ENRMTableIOSGridView.m +216 -0
  102. package/ios/views/EnrichedMarkdownInternalText.h +2 -0
  103. package/ios/views/EnrichedMarkdownInternalText.m +2 -0
  104. package/ios/views/TableContainerView.h +8 -0
  105. package/ios/views/TableContainerView.m +72 -128
  106. package/lib/module/EnrichedMarkdownNativeComponent.ts +37 -2
  107. package/lib/module/EnrichedMarkdownTextInput.js +48 -1
  108. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  109. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +35 -1
  110. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +37 -2
  111. package/lib/module/accessibilityLabelDefaults.js +64 -0
  112. package/lib/module/accessibilityLabelDefaults.js.map +1 -0
  113. package/lib/module/index.js +1 -0
  114. package/lib/module/index.js.map +1 -1
  115. package/lib/module/native/EnrichedMarkdownText.js +72 -4
  116. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  117. package/lib/module/normalizeMarkdownStyle.js +2 -4
  118. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  119. package/lib/module/normalizeMarkdownStyle.web.js +2 -4
  120. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  121. package/lib/module/normalizeMarkdownTextInputStyle.js +3 -10
  122. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  123. package/lib/module/normalizeMenuItem.js +38 -0
  124. package/lib/module/normalizeMenuItem.js.map +1 -0
  125. package/lib/module/types/AccessibilityLabels.js +2 -0
  126. package/lib/module/types/AccessibilityLabels.js.map +1 -0
  127. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +34 -2
  128. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  129. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +55 -13
  130. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  131. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +30 -1
  132. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  133. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +34 -2
  134. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  135. package/lib/typescript/src/accessibilityLabelDefaults.d.ts +16 -0
  136. package/lib/typescript/src/accessibilityLabelDefaults.d.ts.map +1 -0
  137. package/lib/typescript/src/index.d.ts +4 -2
  138. package/lib/typescript/src/index.d.ts.map +1 -1
  139. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
  140. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  141. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  142. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  143. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +0 -2
  144. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  145. package/lib/typescript/src/normalizeMenuItem.d.ts +7 -0
  146. package/lib/typescript/src/normalizeMenuItem.d.ts.map +1 -0
  147. package/lib/typescript/src/types/AccessibilityLabels.d.ts +114 -0
  148. package/lib/typescript/src/types/AccessibilityLabels.d.ts.map +1 -0
  149. package/lib/typescript/src/types/MarkdownStyle.d.ts +0 -14
  150. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  151. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +0 -3
  152. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  153. package/lib/typescript/src/types/MarkdownTextProps.d.ts +78 -9
  154. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  155. package/package.json +4 -2
  156. package/plugin/build/withAndroidMath.js +19 -0
  157. package/plugin/build/withIosMath.js +28 -0
  158. package/plugin/build/withReactNativeEnrichedMarkdown.js +11 -0
  159. package/plugin/tsconfig.build.json +16 -0
  160. package/src/EnrichedMarkdownNativeComponent.ts +37 -2
  161. package/src/EnrichedMarkdownTextInput.tsx +117 -13
  162. package/src/EnrichedMarkdownTextInputNativeComponent.ts +35 -1
  163. package/src/EnrichedMarkdownTextNativeComponent.ts +37 -2
  164. package/src/accessibilityLabelDefaults.ts +83 -0
  165. package/src/index.tsx +11 -0
  166. package/src/native/EnrichedMarkdownText.tsx +120 -6
  167. package/src/normalizeMarkdownStyle.ts +1 -6
  168. package/src/normalizeMarkdownStyle.web.ts +1 -6
  169. package/src/normalizeMarkdownTextInputStyle.ts +0 -14
  170. package/src/normalizeMenuItem.ts +52 -0
  171. package/src/types/AccessibilityLabels.ts +118 -0
  172. package/src/types/MarkdownStyle.ts +0 -14
  173. package/src/types/MarkdownStyleInternal.ts +0 -4
  174. package/src/types/MarkdownTextProps.ts +74 -9
  175. package/android/src/math/java/com/swmansion/enriched/markdown/utils/math/LatexWeightWrapper.kt +0 -23
  176. package/lib/module/plugin/withAndroidMath.js +0 -20
  177. package/lib/module/plugin/withAndroidMath.js.map +0 -1
  178. package/lib/module/plugin/withIosMath.js +0 -23
  179. package/lib/module/plugin/withIosMath.js.map +0 -1
  180. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js +0 -16
  181. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js.map +0 -1
  182. package/lib/typescript/src/plugin/withAndroidMath.d.ts +0 -5
  183. package/lib/typescript/src/plugin/withAndroidMath.d.ts.map +0 -1
  184. package/lib/typescript/src/plugin/withIosMath.d.ts +0 -5
  185. package/lib/typescript/src/plugin/withIosMath.d.ts.map +0 -1
  186. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts +0 -6
  187. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts.map +0 -1
  188. /package/{src/plugin → plugin/src}/withAndroidMath.ts +0 -0
  189. /package/{src/plugin → plugin/src}/withIosMath.ts +0 -0
  190. /package/{src/plugin → plugin/src}/withReactNativeEnrichedMarkdown.ts +0 -0
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const withIosMath_1 = require("./withIosMath");
4
+ const withAndroidMath_1 = require("./withAndroidMath");
5
+ const withEnrichedMarkdown = (config, props) => {
6
+ const enableMath = props?.enableMath !== false;
7
+ config = (0, withAndroidMath_1.withAndroidMath)(config, { enableMath });
8
+ config = (0, withIosMath_1.withIosMath)(config, { enableMath });
9
+ return config;
10
+ };
11
+ exports.default = withEnrichedMarkdown;
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "moduleResolution": "node",
5
+ "ignoreDeprecations": "6.0",
6
+ "target": "ES2020",
7
+ "outDir": "./build",
8
+ "rootDir": "./src",
9
+ "esModuleInterop": true,
10
+ "strict": true,
11
+ "skipLibCheck": true,
12
+ "declaration": false,
13
+ "types": ["node"]
14
+ },
15
+ "include": ["./src/**/*.ts"]
16
+ }
@@ -141,12 +141,10 @@ interface MathStyleInternal {
141
141
  marginTop: CodegenTypes.Float;
142
142
  marginBottom: CodegenTypes.Float;
143
143
  textAlign: string;
144
- fontWeight: string;
145
144
  }
146
145
 
147
146
  interface InlineMathStyleInternal {
148
147
  color: ColorValue;
149
- fontWeight: string;
150
148
  }
151
149
 
152
150
  interface SpoilerParticlesStyleInternal {
@@ -232,6 +230,13 @@ export interface ContextMenuItemConfig {
232
230
  export interface SelectionMenuConfig {
233
231
  copyAsMarkdown: boolean;
234
232
  copyImageUrl: boolean;
233
+ copyLabel: string;
234
+ copyAsMarkdownLabel: string;
235
+ copyImageUrlLabel: string;
236
+ copyImageUrlsLabel: string;
237
+ // Precomputed plural templates indexed by image count (0..100). Empty when no
238
+ // pluralLabels are set; native then uses copyImageUrlLabel/copyImageUrlsLabel.
239
+ copyImageUrlPluralTemplates: ReadonlyArray<string>;
235
240
  }
236
241
 
237
242
  export interface OnContextMenuItemPressEvent {
@@ -241,6 +246,35 @@ export interface OnContextMenuItemPressEvent {
241
246
  selectionEnd: CodegenTypes.Int32;
242
247
  }
243
248
 
249
+ export interface AccessibilityLabelsListProps {
250
+ bulletPoint: string;
251
+ nestedBulletPoint: string;
252
+ orderedItem: string;
253
+ nestedOrderedItem: string;
254
+ }
255
+ export interface AccessibilityLabelsBlockquoteProps {
256
+ quote: string;
257
+ nestedQuote: string;
258
+ }
259
+ export interface AccessibilityLabelsTableProps {
260
+ row: string;
261
+ }
262
+ export interface AccessibilityLabelsMathProps {
263
+ equation: string;
264
+ }
265
+ export interface AccessibilityLabelsRotorProps {
266
+ headings: string;
267
+ links: string;
268
+ images: string;
269
+ }
270
+ export interface AccessibilityLabelsProps {
271
+ list: Readonly<AccessibilityLabelsListProps>;
272
+ blockquote: Readonly<AccessibilityLabelsBlockquoteProps>;
273
+ table: Readonly<AccessibilityLabelsTableProps>;
274
+ math: Readonly<AccessibilityLabelsMathProps>;
275
+ rotor: Readonly<AccessibilityLabelsRotorProps>;
276
+ }
277
+
244
278
  /**
245
279
  * MD4C parser flags configuration.
246
280
  * Controls how the markdown parser interprets certain syntax.
@@ -396,6 +430,7 @@ export interface NativeProps extends ViewProps {
396
430
  * Built-in items to show in the text selection context menu.
397
431
  */
398
432
  selectionMenuConfig: Readonly<SelectionMenuConfig>;
433
+ accessibilityLabels: Readonly<AccessibilityLabelsProps>;
399
434
  /**
400
435
  * Fired when a custom context menu item is pressed.
401
436
  * Receives the item label, the currently selected text, and the selection range.
@@ -38,6 +38,7 @@ import type {
38
38
  ColorValue,
39
39
  } from 'react-native';
40
40
  import { normalizeMarkdownTextInputStyle } from './normalizeMarkdownTextInputStyle';
41
+ import { normalizeMenuItem } from './normalizeMenuItem';
41
42
  import { toNativeRegexConfig } from './utils/regexParser';
42
43
  import type { RefObject } from 'react';
43
44
 
@@ -60,18 +61,6 @@ export interface MathStyle {
60
61
  paddingVertical?: number;
61
62
  selectedBackgroundColor?: string;
62
63
  selectedBorderColor?: string;
63
- /**
64
- * Renders math glyphs with KaTeX's bold variant (KaTeX_Main-Bold /
65
- * KaTeX_Math-BoldItalic). Wraps the LaTeX in `\mathbf{…}` at render time
66
- * only — chip storage and serialized markdown stay untouched.
67
- *
68
- * Caveat: large operators (`\sum`, `\int`, `\prod`), AMS symbols, Script
69
- * and Typewriter glyphs have no bold variant in KaTeX and stay at regular
70
- * weight even when `fontWeight: 'bold'`.
71
- *
72
- * @default 'normal'
73
- */
74
- fontWeight?: 'normal' | 'bold';
75
64
  }
76
65
 
77
66
  export interface MathBlockStyle extends MathStyle {
@@ -161,10 +150,48 @@ export interface EnrichedMarkdownTextInputInstance {
161
150
  options?: InsertMathOptions
162
151
  ) => void;
163
152
  removeMath: (start: number) => void;
153
+ copyToClipboard: () => void;
164
154
  getMarkdown: () => Promise<string>;
165
155
  getCaretRect: () => Promise<CaretRect>;
166
156
  }
167
157
 
158
+ /**
159
+ * Per-item shape: `{ enabled }` toggles visibility, `label` overrides the
160
+ * English default. Wire `label` to your i18n library to localize the menu.
161
+ */
162
+ type MenuItem = { enabled?: boolean; label?: string };
163
+
164
+ export interface InputSelectionMenuConfig {
165
+ /**
166
+ * The built-in "Format" submenu (Bold, Italic, Underline, etc.) in the
167
+ * text selection context menu. `label` overrides the submenu title.
168
+ * @default { enabled: true, label: "Format" }
169
+ */
170
+ format?: MenuItem;
171
+ /**
172
+ * The built-in "Copy as Markdown" action in the text selection context
173
+ * menu. `label` overrides the action title.
174
+ * @default { enabled: true, label: "Copy as Markdown" }
175
+ */
176
+ copyAsMarkdown?: MenuItem;
177
+ }
178
+
179
+ /** Controls the individual items inside the Format submenu. */
180
+ export interface FormatMenuConfig {
181
+ /** @default { enabled: true, label: "Bold" } */
182
+ bold?: MenuItem;
183
+ /** @default { enabled: true, label: "Italic" } */
184
+ italic?: MenuItem;
185
+ /** @default { enabled: true, label: "Underline" } */
186
+ underline?: MenuItem;
187
+ /** @default { enabled: true, label: "Strikethrough" } */
188
+ strikethrough?: MenuItem;
189
+ /** @default { enabled: true, label: "Spoiler" } */
190
+ spoiler?: MenuItem;
191
+ /** @default { enabled: true, label: "Link" } */
192
+ link?: MenuItem;
193
+ }
194
+
168
195
  export interface EnrichedMarkdownTextInputProps extends Omit<
169
196
  ViewProps,
170
197
  'style' | 'children'
@@ -196,6 +223,22 @@ export interface EnrichedMarkdownTextInputProps extends Omit<
196
223
  onFocus?: () => void;
197
224
  onBlur?: () => void;
198
225
  contextMenuItems?: ContextMenuItem[];
226
+ /**
227
+ * Controls built-in items in the text selection context menu.
228
+ * Omitting the prop or any field reproduces today's exact menu.
229
+ * Custom app-provided actions are controlled separately via `contextMenuItems`.
230
+ * @default { format: true, copyAsMarkdown: true }
231
+ * @platform ios, android, macos
232
+ */
233
+ selectionMenuConfig?: InputSelectionMenuConfig;
234
+ /**
235
+ * Controls which items appear inside the Format submenu.
236
+ * Only effective when `selectionMenuConfig.format` is `true` (the default).
237
+ * Omitting the prop or any field shows all items.
238
+ * @default { bold: true, italic: true, underline: true, strikethrough: true, spoiler: true, link: true }
239
+ * @platform ios, android, macos
240
+ */
241
+ formatMenuConfig?: FormatMenuConfig;
199
242
  linkRegex?: RegExp | null;
200
243
  /**
201
244
  * Paragraph writing direction.
@@ -258,11 +301,15 @@ export const EnrichedMarkdownTextInput = ({
258
301
  onFocus,
259
302
  onBlur,
260
303
  contextMenuItems,
304
+ selectionMenuConfig,
305
+ formatMenuConfig,
261
306
  linkRegex: _linkRegex,
262
307
  writingDirection = 'first-strong',
263
308
  ...rest
264
309
  }: EnrichedMarkdownTextInputProps) => {
265
310
  const nativeRef = useRef<NativeRef | null>(null);
311
+ // Freeze `defaultValue` at mount (RN TextInput semantics): post-mount changes are ignored.
312
+ const initialDefaultValue = useRef(defaultValue).current;
266
313
 
267
314
  const nextRequestId = useRef(1);
268
315
  const pendingRequests = useRef(new Map<number, PendingRequest<string>>());
@@ -306,6 +353,60 @@ export const EnrichedMarkdownTextInput = ({
306
353
 
307
354
  const normalizedStyle = normalizeMarkdownTextInputStyle(markdownStyle);
308
355
 
356
+ const normalizedSelectionMenuConfig = useMemo(() => {
357
+ const format = normalizeMenuItem(
358
+ selectionMenuConfig?.format,
359
+ true,
360
+ 'Format'
361
+ );
362
+ const copyAsMarkdown = normalizeMenuItem(
363
+ selectionMenuConfig?.copyAsMarkdown,
364
+ true,
365
+ 'Copy as Markdown'
366
+ );
367
+ return {
368
+ format: format.enabled,
369
+ formatLabel: format.label,
370
+ copyAsMarkdown: copyAsMarkdown.enabled,
371
+ copyAsMarkdownLabel: copyAsMarkdown.label,
372
+ };
373
+ }, [selectionMenuConfig]);
374
+
375
+ const normalizedFormatMenuConfig = useMemo(() => {
376
+ const bold = normalizeMenuItem(formatMenuConfig?.bold, true, 'Bold');
377
+ const italic = normalizeMenuItem(formatMenuConfig?.italic, true, 'Italic');
378
+ const underline = normalizeMenuItem(
379
+ formatMenuConfig?.underline,
380
+ true,
381
+ 'Underline'
382
+ );
383
+ const strikethrough = normalizeMenuItem(
384
+ formatMenuConfig?.strikethrough,
385
+ true,
386
+ 'Strikethrough'
387
+ );
388
+ const spoiler = normalizeMenuItem(
389
+ formatMenuConfig?.spoiler,
390
+ true,
391
+ 'Spoiler'
392
+ );
393
+ const link = normalizeMenuItem(formatMenuConfig?.link, true, 'Link');
394
+ return {
395
+ bold: bold.enabled,
396
+ boldLabel: bold.label,
397
+ italic: italic.enabled,
398
+ italicLabel: italic.label,
399
+ underline: underline.enabled,
400
+ underlineLabel: underline.label,
401
+ strikethrough: strikethrough.enabled,
402
+ strikethroughLabel: strikethrough.label,
403
+ spoiler: spoiler.enabled,
404
+ spoilerLabel: spoiler.label,
405
+ link: link.enabled,
406
+ linkLabel: link.label,
407
+ };
408
+ }, [formatMenuConfig]);
409
+
309
410
  const linkRegex = useMemo(
310
411
  () => toNativeRegexConfig(_linkRegex),
311
412
  [_linkRegex]
@@ -488,6 +589,7 @@ export const EnrichedMarkdownTextInput = ({
488
589
  options?.display ?? false
489
590
  ),
490
591
  removeMath: (start) => Commands.removeMath(commandRef, start),
592
+ copyToClipboard: () => Commands.copyToClipboard(commandRef),
491
593
  getMarkdown: () =>
492
594
  new Promise<string>((resolve, reject) => {
493
595
  const requestId = nextRequestId.current++;
@@ -511,7 +613,7 @@ export const EnrichedMarkdownTextInput = ({
511
613
  ref={nativeRef}
512
614
  style={style}
513
615
  markdownStyle={normalizedStyle}
514
- defaultValue={defaultValue}
616
+ defaultValue={initialDefaultValue}
515
617
  placeholder={placeholder}
516
618
  placeholderTextColor={placeholderTextColor}
517
619
  editable={editable}
@@ -542,6 +644,8 @@ export const EnrichedMarkdownTextInput = ({
542
644
  handleCaretRectChange as NativeProps['onCaretRectChange']
543
645
  }
544
646
  contextMenuItems={nativeContextMenuItems}
647
+ selectionMenuConfig={normalizedSelectionMenuConfig}
648
+ formatMenuConfig={normalizedFormatMenuConfig}
545
649
  mentionIndicators={mentionIndicators}
546
650
  onContextMenuItemPress={
547
651
  handleContextMenuItemPress as NativeProps['onContextMenuItemPress']
@@ -19,7 +19,6 @@ interface MathStyleInternal {
19
19
  paddingVertical: CodegenTypes.Float;
20
20
  selectedBackgroundColor: ColorValue;
21
21
  selectedBorderColor: ColorValue;
22
- fontWeight: string;
23
22
  }
24
23
 
25
24
  interface MathBlockStyleInternal extends MathStyleInternal {
@@ -146,6 +145,28 @@ export interface ContextMenuItemConfig {
146
145
  icon?: string;
147
146
  }
148
147
 
148
+ export interface InputSelectionMenuConfigInternal {
149
+ format: boolean;
150
+ formatLabel: string;
151
+ copyAsMarkdown: boolean;
152
+ copyAsMarkdownLabel: string;
153
+ }
154
+
155
+ export interface FormatMenuConfigInternal {
156
+ bold: boolean;
157
+ boldLabel: string;
158
+ italic: boolean;
159
+ italicLabel: string;
160
+ underline: boolean;
161
+ underlineLabel: string;
162
+ strikethrough: boolean;
163
+ strikethroughLabel: string;
164
+ spoiler: boolean;
165
+ spoilerLabel: string;
166
+ link: boolean;
167
+ linkLabel: string;
168
+ }
169
+
149
170
  export interface OnContextMenuItemPressEvent {
150
171
  itemText: string;
151
172
  selectedText: string;
@@ -231,6 +252,17 @@ export interface NativeProps extends ViewProps {
231
252
  */
232
253
  contextMenuItems?: ReadonlyArray<Readonly<ContextMenuItemConfig>>;
233
254
 
255
+ /**
256
+ * Controls built-in items in the text selection context menu.
257
+ * `format` toggles the Format submenu; `copyAsMarkdown` toggles the Copy as Markdown action.
258
+ */
259
+ selectionMenuConfig: Readonly<InputSelectionMenuConfigInternal>;
260
+
261
+ /**
262
+ * Controls which items appear inside the Format submenu.
263
+ */
264
+ formatMenuConfig: Readonly<FormatMenuConfigInternal>;
265
+
234
266
  /**
235
267
  * Regex configuration for automatic link detection.
236
268
  * Omit or pass undefined to use platform defaults.
@@ -323,6 +355,7 @@ interface NativeCommands {
323
355
  viewRef: React.ElementRef<ComponentType>,
324
356
  start: CodegenTypes.Int32
325
357
  ) => void;
358
+ copyToClipboard: (viewRef: React.ElementRef<ComponentType>) => void;
326
359
  requestMarkdown: (
327
360
  viewRef: React.ElementRef<ComponentType>,
328
361
  requestId: CodegenTypes.Int32
@@ -352,6 +385,7 @@ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
352
385
  'insertMath',
353
386
  'updateMath',
354
387
  'removeMath',
388
+ 'copyToClipboard',
355
389
  'requestMarkdown',
356
390
  'requestCaretRect',
357
391
  ],
@@ -141,12 +141,10 @@ interface MathStyleInternal {
141
141
  marginTop: CodegenTypes.Float;
142
142
  marginBottom: CodegenTypes.Float;
143
143
  textAlign: string;
144
- fontWeight: string;
145
144
  }
146
145
 
147
146
  interface InlineMathStyleInternal {
148
147
  color: ColorValue;
149
- fontWeight: string;
150
148
  }
151
149
 
152
150
  interface SpoilerParticlesStyleInternal {
@@ -232,6 +230,13 @@ export interface ContextMenuItemConfig {
232
230
  export interface SelectionMenuConfig {
233
231
  copyAsMarkdown: boolean;
234
232
  copyImageUrl: boolean;
233
+ copyLabel: string;
234
+ copyAsMarkdownLabel: string;
235
+ copyImageUrlLabel: string;
236
+ copyImageUrlsLabel: string;
237
+ // Precomputed plural templates indexed by image count (0..100). Empty when no
238
+ // pluralLabels are set; native then uses copyImageUrlLabel/copyImageUrlsLabel.
239
+ copyImageUrlPluralTemplates: ReadonlyArray<string>;
235
240
  }
236
241
 
237
242
  export interface OnContextMenuItemPressEvent {
@@ -241,6 +246,35 @@ export interface OnContextMenuItemPressEvent {
241
246
  selectionEnd: CodegenTypes.Int32;
242
247
  }
243
248
 
249
+ export interface AccessibilityLabelsListProps {
250
+ bulletPoint: string;
251
+ nestedBulletPoint: string;
252
+ orderedItem: string;
253
+ nestedOrderedItem: string;
254
+ }
255
+ export interface AccessibilityLabelsBlockquoteProps {
256
+ quote: string;
257
+ nestedQuote: string;
258
+ }
259
+ export interface AccessibilityLabelsTableProps {
260
+ row: string;
261
+ }
262
+ export interface AccessibilityLabelsMathProps {
263
+ equation: string;
264
+ }
265
+ export interface AccessibilityLabelsRotorProps {
266
+ headings: string;
267
+ links: string;
268
+ images: string;
269
+ }
270
+ export interface AccessibilityLabelsProps {
271
+ list: Readonly<AccessibilityLabelsListProps>;
272
+ blockquote: Readonly<AccessibilityLabelsBlockquoteProps>;
273
+ table: Readonly<AccessibilityLabelsTableProps>;
274
+ math: Readonly<AccessibilityLabelsMathProps>;
275
+ rotor: Readonly<AccessibilityLabelsRotorProps>;
276
+ }
277
+
244
278
  /**
245
279
  * MD4C parser flags configuration.
246
280
  * Controls how the markdown parser interprets certain syntax.
@@ -395,6 +429,7 @@ export interface NativeProps extends ViewProps {
395
429
  * Built-in items to show in the text selection context menu.
396
430
  */
397
431
  selectionMenuConfig: Readonly<SelectionMenuConfig>;
432
+ accessibilityLabels: Readonly<AccessibilityLabelsProps>;
398
433
  /**
399
434
  * Fired when a custom context menu item is pressed.
400
435
  * Receives the item label, the currently selected text, and the selection range.
@@ -0,0 +1,83 @@
1
+ import type {
2
+ AccessibilityLabels,
3
+ ResolvedAccessibilityLabels,
4
+ } from './types/AccessibilityLabels';
5
+
6
+ /**
7
+ * Default strings spoken by VoiceOver / TalkBack when the consumer does not
8
+ * provide an override. See `AccessibilityLabels` for the placeholder syntax
9
+ * and the rationale for the no-plural cardinal form.
10
+ */
11
+ export const DEFAULT_ACCESSIBILITY_LABELS: ResolvedAccessibilityLabels = {
12
+ list: {
13
+ bulletPoint: 'Bullet point',
14
+ nestedBulletPoint: 'Nested bullet point',
15
+ orderedItem: 'List item {n}',
16
+ nestedOrderedItem: 'Nested list item {n}',
17
+ },
18
+ blockquote: {
19
+ quote: 'Blockquote',
20
+ nestedQuote: 'Nested blockquote',
21
+ },
22
+ table: {
23
+ row: 'Row {n}: {content}',
24
+ },
25
+ math: {
26
+ equation: 'Math: {latex}',
27
+ },
28
+ rotor: {
29
+ headings: 'Headings',
30
+ links: 'Links',
31
+ images: 'Images',
32
+ },
33
+ };
34
+
35
+ /**
36
+ * Resolves a partial `AccessibilityLabels` against `DEFAULT_ACCESSIBILITY_LABELS`,
37
+ * returning a fully-populated struct that native code can consume without any
38
+ * null checks. Override resolution is shallow per sub-group: if a consumer
39
+ * passes `{ list: { bulletPoint: 'Punkt' } }`, only that one field changes and
40
+ * the other list entries fall back to the defaults.
41
+ */
42
+ export function resolveAccessibilityLabels(
43
+ labels: AccessibilityLabels | undefined
44
+ ): ResolvedAccessibilityLabels {
45
+ return {
46
+ list: {
47
+ bulletPoint:
48
+ labels?.list?.bulletPoint ??
49
+ DEFAULT_ACCESSIBILITY_LABELS.list.bulletPoint,
50
+ nestedBulletPoint:
51
+ labels?.list?.nestedBulletPoint ??
52
+ DEFAULT_ACCESSIBILITY_LABELS.list.nestedBulletPoint,
53
+ orderedItem:
54
+ labels?.list?.orderedItem ??
55
+ DEFAULT_ACCESSIBILITY_LABELS.list.orderedItem,
56
+ nestedOrderedItem:
57
+ labels?.list?.nestedOrderedItem ??
58
+ DEFAULT_ACCESSIBILITY_LABELS.list.nestedOrderedItem,
59
+ },
60
+ blockquote: {
61
+ quote:
62
+ labels?.blockquote?.quote ??
63
+ DEFAULT_ACCESSIBILITY_LABELS.blockquote.quote,
64
+ nestedQuote:
65
+ labels?.blockquote?.nestedQuote ??
66
+ DEFAULT_ACCESSIBILITY_LABELS.blockquote.nestedQuote,
67
+ },
68
+ table: {
69
+ row: labels?.table?.row ?? DEFAULT_ACCESSIBILITY_LABELS.table.row,
70
+ },
71
+ math: {
72
+ equation:
73
+ labels?.math?.equation ?? DEFAULT_ACCESSIBILITY_LABELS.math.equation,
74
+ },
75
+ rotor: {
76
+ headings:
77
+ labels?.rotor?.headings ?? DEFAULT_ACCESSIBILITY_LABELS.rotor.headings,
78
+ links: labels?.rotor?.links ?? DEFAULT_ACCESSIBILITY_LABELS.rotor.links,
79
+ images:
80
+ labels?.rotor?.images ?? DEFAULT_ACCESSIBILITY_LABELS.rotor.images,
81
+ },
82
+ };
83
+ }
package/src/index.tsx CHANGED
@@ -6,12 +6,21 @@ export type {
6
6
  Md4cFlags,
7
7
  ContextMenuItem as TextContextMenuItem,
8
8
  SelectionMenuConfig as TextSelectionMenuConfig,
9
+ SelectionMenuPluralLabels as TextSelectionMenuPluralLabels,
9
10
  } from './native/EnrichedMarkdownText';
10
11
  export type {
11
12
  LinkPressEvent,
12
13
  LinkLongPressEvent,
13
14
  TaskListItemPressEvent,
14
15
  } from './types/events';
16
+ export type {
17
+ AccessibilityLabels,
18
+ ResolvedAccessibilityLabels,
19
+ } from './types/AccessibilityLabels';
20
+ export {
21
+ DEFAULT_ACCESSIBILITY_LABELS,
22
+ resolveAccessibilityLabels,
23
+ } from './accessibilityLabelDefaults';
15
24
 
16
25
  export { EnrichedMarkdownTextInput } from './EnrichedMarkdownTextInput';
17
26
  export type {
@@ -20,6 +29,8 @@ export type {
20
29
  MarkdownTextInputStyle,
21
30
  StyleState,
22
31
  ContextMenuItem,
32
+ InputSelectionMenuConfig,
33
+ FormatMenuConfig,
23
34
  OnLinkDetected,
24
35
  OnStartMentionEvent,
25
36
  OnChangeMentionEvent,