@apollohg/react-native-rich-text-editor 2.0.0 → 2.0.2

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 (180) hide show
  1. package/README.md +8 -116
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/android/build.gradle +3 -0
  4. package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +25 -0
  5. package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +1 -0
  6. package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +101 -33
  7. package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +15 -3
  8. package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +14 -0
  9. package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1 -1
  10. package/app.plugin.js +42 -39
  11. package/dist/AtomHost.js +18 -11
  12. package/dist/EditorAddon.js +4 -2
  13. package/dist/EditorAddonNormalization.js +17 -9
  14. package/dist/EditorMentionThemeNormalization.js +6 -3
  15. package/dist/EditorMentionThemeValidation.js +28 -11
  16. package/dist/EditorStyleSheetNormalization.js +85 -38
  17. package/dist/EditorStyleSheetTypes.d.ts +1 -1
  18. package/dist/EditorTheme.d.ts +4 -0
  19. package/dist/EditorTheme.js +5 -3
  20. package/dist/EditorToolbarComponent.d.ts +1 -1
  21. package/dist/EditorToolbarComponent.js +1 -1
  22. package/dist/EditorToolbarRegistry.js +5 -5
  23. package/dist/EditorToolbarTypes.d.ts +12 -12
  24. package/dist/EditorToolbarVisuals.js +1 -1
  25. package/dist/ExternalTextComposition.js +89 -43
  26. package/dist/ImageLoadingPolicy.d.ts +1 -1
  27. package/dist/NativeEditorBoundaryError.d.ts +7 -7
  28. package/dist/NativeEditorBoundaryError.js +9 -5
  29. package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
  30. package/dist/NativeEditorCollaborationTransport.js +28 -15
  31. package/dist/NativeEditorCreateConfig.js +11 -6
  32. package/dist/NativeEditorCreateJson.js +51 -25
  33. package/dist/NativeEditorCreateValidation.js +11 -6
  34. package/dist/NativeEditorDocumentBridge.d.ts +1 -1
  35. package/dist/NativeEditorDocumentBridge.js +32 -18
  36. package/dist/NativeEditorDocumentHandle.d.ts +4 -4
  37. package/dist/NativeEditorDocumentHandle.js +1 -1
  38. package/dist/NativeEditorLocalAwareness.js +25 -13
  39. package/dist/NativeEditorNativeModule.d.ts +8 -1
  40. package/dist/NativeEditorNativeModule.js +7 -5
  41. package/dist/NativeEditorRenderNormalization.js +66 -25
  42. package/dist/NativeEditorResultNormalization.js +53 -29
  43. package/dist/NativeEditorTypes.d.ts +10 -10
  44. package/dist/NativeEditorV2Decimal.js +6 -3
  45. package/dist/NativeProseViewer.js +11 -3
  46. package/dist/ResourceLimits.d.ts +2 -2
  47. package/dist/ResourceLimits.js +7 -2
  48. package/dist/RichTextEditor.js +1 -1
  49. package/dist/RichTextEditorNativeTypes.d.ts +1 -1
  50. package/dist/RichTextEditorNativeView.d.ts +1 -3
  51. package/dist/RichTextEditorSerialization.js +24 -14
  52. package/dist/RichTextEditorTypes.d.ts +1 -1
  53. package/dist/YjsCollaboration.d.ts +7 -7
  54. package/dist/YjsCollaboration.js +42 -26
  55. package/dist/addons.d.ts +4 -4
  56. package/dist/addons.js +3 -3
  57. package/dist/atomInstances.js +6 -3
  58. package/dist/atomUpdates.js +7 -4
  59. package/dist/atoms.js +20 -12
  60. package/dist/attributeValidation.js +55 -24
  61. package/dist/contentExpression.js +80 -42
  62. package/dist/listMarkers.d.ts +1 -1
  63. package/dist/listMarkers.js +1 -1
  64. package/dist/schemaDefinition.d.ts +1 -1
  65. package/dist/schemaDefinition.js +23 -14
  66. package/dist/schemaDocument.js +1 -1
  67. package/dist/schemaDocumentConstruction.js +25 -14
  68. package/dist/schemaNormalization.js +51 -29
  69. package/dist/schemaPresets.d.ts +1 -1
  70. package/dist/schemaPresets.js +9 -4
  71. package/dist/schemaResolution.js +46 -25
  72. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
  73. package/dist/useEditorToolbarInteractions.d.ts +2 -2
  74. package/dist/useEditorToolbarInteractions.js +45 -23
  75. package/dist/useEditorToolbarItems.d.ts +1 -1
  76. package/dist/useEditorToolbarItems.js +4 -3
  77. package/dist/useEditorToolbarPresentation.d.ts +3 -3
  78. package/dist/useEditorToolbarPresentation.js +4 -4
  79. package/dist/useEditorToolbarState.d.ts +1 -1
  80. package/dist/useEditorToolbarState.js +1 -1
  81. package/dist/useFocusPreservingFrames.js +11 -8
  82. package/dist/useNativeEditor.d.ts +1 -1
  83. package/dist/useNativeEditor.js +21 -11
  84. package/dist/useRichTextEditorCommands.d.ts +2 -2
  85. package/dist/useRichTextEditorCommands.js +59 -29
  86. package/dist/useRichTextEditorEvents.d.ts +3 -3
  87. package/dist/useRichTextEditorEvents.js +75 -32
  88. package/dist/useRichTextEditorMentions.d.ts +4 -4
  89. package/dist/useRichTextEditorMentions.js +48 -29
  90. package/dist/useRichTextEditorPresentation.d.ts +4 -4
  91. package/dist/useRichTextEditorPresentation.js +25 -23
  92. package/dist/useRichTextEditorState.d.ts +3 -3
  93. package/dist/useRichTextEditorState.js +20 -15
  94. package/dist/useRichTextEditorUpdates.d.ts +1 -1
  95. package/dist/useRichTextEditorUpdates.js +99 -41
  96. package/dist/useViewerAtoms.js +63 -36
  97. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  98. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  99. package/ios/EditorInteractionOverlays.swift +114 -122
  100. package/ios/EditorLayoutManager.swift +13 -3
  101. package/ios/EditorStyleSheet.swift +12 -1
  102. package/ios/EditorTextView+Images.swift +32 -10
  103. package/ios/EditorTextView.swift +1 -1
  104. package/ios/EditorV2Adapter+RenderValidation.swift +2 -2
  105. package/ios/NativeToolbar+ButtonStyle.swift +17 -5
  106. package/ios/NativeToolbar+Diagnostics.swift +15 -0
  107. package/ios/RenderBridge+Atoms.swift +0 -1
  108. package/ios/RenderBridge+Attachments.swift +0 -29
  109. package/ios/RichTextEditorView.swift +4 -12
  110. package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +3 -2
  111. package/package.json +11 -3
  112. package/react-native.config.js +1 -1
  113. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  114. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  115. package/rust/android/x86/libeditor_core.so +0 -0
  116. package/rust/android/x86_64/libeditor_core.so +0 -0
  117. package/src/AtomHost.tsx +58 -28
  118. package/src/EditorAddon.ts +18 -8
  119. package/src/EditorAddonNormalization.ts +40 -11
  120. package/src/EditorMentionThemeNormalization.ts +15 -4
  121. package/src/EditorMentionThemeValidation.ts +51 -14
  122. package/src/EditorStyleSheet.ts +1 -0
  123. package/src/EditorStyleSheetNormalization.ts +195 -64
  124. package/src/EditorStyleSheetTypes.ts +1 -1
  125. package/src/EditorTheme.ts +13 -5
  126. package/src/EditorToolbarComponent.tsx +2 -1
  127. package/src/EditorToolbarRegistry.tsx +23 -13
  128. package/src/EditorToolbarTypes.tsx +12 -12
  129. package/src/EditorToolbarVisuals.tsx +6 -3
  130. package/src/EditorUpdateRevision.ts +1 -0
  131. package/src/ExternalTextComposition.ts +259 -49
  132. package/src/ImageLoadingPolicy.ts +3 -1
  133. package/src/NativeEditorBoundaryError.ts +38 -11
  134. package/src/NativeEditorCollaborationTransport.ts +108 -27
  135. package/src/NativeEditorCreateConfig.ts +92 -19
  136. package/src/NativeEditorCreateJson.ts +163 -26
  137. package/src/NativeEditorCreateValidation.ts +33 -12
  138. package/src/NativeEditorDocumentBridge.ts +111 -19
  139. package/src/NativeEditorDocumentHandle.ts +9 -4
  140. package/src/NativeEditorLocalAwareness.ts +70 -15
  141. package/src/NativeEditorNativeModule.ts +13 -9
  142. package/src/NativeEditorRenderNormalization.ts +128 -29
  143. package/src/NativeEditorResultNormalization.ts +143 -32
  144. package/src/NativeEditorTypes.ts +12 -11
  145. package/src/NativeEditorV2Decimal.ts +12 -3
  146. package/src/NativeProseViewer.tsx +46 -16
  147. package/src/ResourceLimits.ts +15 -8
  148. package/src/RichTextEditor.tsx +3 -1
  149. package/src/RichTextEditorNativeTypes.tsx +1 -1
  150. package/src/RichTextEditorNativeView.tsx +2 -8
  151. package/src/RichTextEditorSerialization.tsx +70 -24
  152. package/src/RichTextEditorTypes.tsx +1 -1
  153. package/src/YjsCollaboration.ts +143 -47
  154. package/src/addons.ts +12 -8
  155. package/src/atomInstances.ts +25 -5
  156. package/src/atomUpdates.ts +23 -6
  157. package/src/atoms.ts +85 -18
  158. package/src/attributeValidation.ts +97 -33
  159. package/src/contentExpression.ts +218 -63
  160. package/src/listMarkers.ts +1 -1
  161. package/src/schemaDefinition.ts +82 -20
  162. package/src/schemaDocument.ts +15 -1
  163. package/src/schemaDocumentConstruction.ts +80 -16
  164. package/src/schemaNormalization.ts +155 -41
  165. package/src/schemaPresets.ts +37 -31
  166. package/src/schemaResolution.ts +126 -27
  167. package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
  168. package/src/useEditorToolbarInteractions.tsx +85 -36
  169. package/src/useEditorToolbarItems.tsx +50 -22
  170. package/src/useEditorToolbarPresentation.tsx +81 -58
  171. package/src/useEditorToolbarState.tsx +8 -6
  172. package/src/useFocusPreservingFrames.ts +43 -15
  173. package/src/useNativeEditor.ts +111 -51
  174. package/src/useRichTextEditorCommands.tsx +127 -54
  175. package/src/useRichTextEditorEvents.tsx +144 -42
  176. package/src/useRichTextEditorMentions.tsx +118 -37
  177. package/src/useRichTextEditorPresentation.tsx +128 -114
  178. package/src/useRichTextEditorState.tsx +76 -40
  179. package/src/useRichTextEditorUpdates.tsx +207 -56
  180. package/src/useViewerAtoms.tsx +162 -66
@@ -8,7 +8,7 @@ import { NativeEditorBoundaryError } from './NativeEditorBoundaryError';
8
8
  * Every field is optional; an omitted one uses
9
9
  * {@link DEFAULT_EDITOR_RESOURCE_LIMITS}. Each value must be a positive
10
10
  * integer no greater than the matching {@link HARD_EDITOR_RESOURCE_LIMITS}
11
- * ceiling anything else throws `NativeEditorBoundaryError`
11
+ * ceiling : anything else throws `NativeEditorBoundaryError`
12
12
  * (`INVALID_RESOURCE_LIMIT`). Exceeding a limit at runtime raises
13
13
  * `INPUT_LIMIT_EXCEEDED`, `DOCUMENT_LIMIT_EXCEEDED`, or `SCHEMA_INVALID`.
14
14
  */
@@ -25,7 +25,7 @@ export interface EditorResourceLimits {
25
25
  maxSchemaExpressionBytes?: number;
26
26
  /** Byte ceiling for one inbound collaboration message. */
27
27
  maxCollaborationMessageBytes?: number;
28
- /** Byte ceiling for an encoded Yjs state imported room snapshots and exported ones. */
28
+ /** Byte ceiling for an encoded Yjs state : imported room snapshots and exported ones. */
29
29
  maxEncodedStateBytes?: number;
30
30
  }
31
31
 
@@ -142,6 +142,7 @@ function validateLimit(name: string, value: number, ceiling: number): void {
142
142
  function resolveLimit(name: keyof ResolvedEditorResourceLimits, value?: number): number {
143
143
  const resolved = value ?? DEFAULT_EDITOR_RESOURCE_LIMITS[name];
144
144
  validateLimit(name, resolved, HARD_EDITOR_RESOURCE_LIMITS[name]);
145
+
145
146
  return resolved;
146
147
  }
147
148
 
@@ -149,9 +150,13 @@ function validateOverrides<T extends object>(
149
150
  limits: T | undefined,
150
151
  ceilings: Readonly<Required<T>>
151
152
  ): void {
152
- if (limits === undefined) return;
153
+ if (limits === undefined) {
154
+ return;
155
+ }
156
+
153
157
  for (const name of Object.keys(ceilings) as Array<keyof T>) {
154
158
  const value = limits[name];
159
+
155
160
  if (value !== undefined) {
156
161
  validateLimit(String(name), value as number, ceilings[name] as number);
157
162
  }
@@ -179,9 +184,11 @@ export function validateEditorCreateLimits(limits?: {
179
184
  export function resolveEditorResourceLimits(
180
185
  limits: EditorResourceLimits = {}
181
186
  ): ResolvedEditorResourceLimits {
182
- return Object.fromEntries(
183
- (Object.keys(DEFAULT_EDITOR_RESOURCE_LIMITS) as Array<
184
- keyof ResolvedEditorResourceLimits
185
- >).map((name) => [name, resolveLimit(name, limits[name])])
186
- ) as unknown as ResolvedEditorResourceLimits;
187
+ const resolved = { ...DEFAULT_EDITOR_RESOURCE_LIMITS };
188
+
189
+ for (const name of Object.keys(resolved) as Array<keyof ResolvedEditorResourceLimits>) {
190
+ resolved[name] = resolveLimit(name, limits[name]);
191
+ }
192
+
193
+ return resolved;
187
194
  }
@@ -8,17 +8,19 @@ import { useRichTextEditorMentions } from './useRichTextEditorMentions';
8
8
  import { useRichTextEditorPresentation } from './useRichTextEditorPresentation';
9
9
 
10
10
  export const RichTextEditor = forwardRef<RichTextEditorRef, RichTextEditorProps>(
11
- function RichTextEditor(props, ref) {
11
+ (props, ref) => {
12
12
  const state = useRichTextEditorState(props, ref);
13
13
  const updates = useRichTextEditorUpdates(state);
14
14
  const commands = useRichTextEditorCommands({ ...state, ...updates });
15
15
  const events = useRichTextEditorEvents({ ...state, ...updates, ...commands });
16
+
16
17
  const mentions = useRichTextEditorMentions({
17
18
  ...state,
18
19
  ...commands,
19
20
  ...updates,
20
21
  ...events,
21
22
  });
23
+
22
24
  return useRichTextEditorPresentation({ ...state, ...mentions, ...commands, ...events });
23
25
  }
24
26
  );
@@ -1,5 +1,5 @@
1
1
  import {
2
- ExternalTextCompositionManager,
2
+ type ExternalTextCompositionManager,
3
3
  type NativeExternalTextCompositionHandle,
4
4
  } from './ExternalTextComposition';
5
5
  import { type ReactNode } from 'react';
@@ -1,14 +1,8 @@
1
1
  import { requireNativeViewManager } from 'expo-modules-core';
2
- import React from 'react';
2
+
3
3
  import { StyleSheet } from 'react-native';
4
- import {
5
- type NativeEditorViewProps,
6
- type NativeEditorViewHandle,
7
- } from './RichTextEditorNativeTypes';
8
4
 
9
- export const NativeEditorView = requireNativeViewManager('NativeEditor') as React.ComponentType<
10
- NativeEditorViewProps & React.RefAttributes<NativeEditorViewHandle>
11
- >;
5
+ export const NativeEditorView = requireNativeViewManager('NativeEditor');
12
6
 
13
7
  export const styles = StyleSheet.create({
14
8
  container: {
@@ -10,12 +10,7 @@ import {
10
10
  type Selection,
11
11
  } from './NativeEditorBridge';
12
12
  import { atomSelected, type AtomInstance } from './atomInstances';
13
- import {
14
- type EditorToolbarFrame,
15
- type EditorToolbarGroupChildItem,
16
- type EditorToolbarIcon,
17
- type EditorToolbarItem,
18
- } from './EditorToolbar';
13
+ import { type EditorToolbarFrame, type EditorToolbarGroupChildItem, type EditorToolbarItem } from './EditorToolbar';
19
14
  import { IMAGE_NODE_NAME } from './schemas';
20
15
  import { useRef } from 'react';
21
16
  import {
@@ -38,8 +33,13 @@ export function mergeMentionSuggestionTheme(
38
33
  baseTheme: EditorMentionTheme | undefined,
39
34
  resolvedTheme: EditorMentionTheme | undefined
40
35
  ): EditorMentionTheme | undefined {
41
- if (baseTheme == null) return resolvedTheme;
42
- if (resolvedTheme == null) return baseTheme;
36
+ if (baseTheme == null) {
37
+ return resolvedTheme;
38
+ }
39
+
40
+ if (resolvedTheme == null) {
41
+ return baseTheme;
42
+ }
43
43
 
44
44
  return {
45
45
  node: { ...baseTheme.node, ...resolvedTheme.node },
@@ -54,6 +54,7 @@ export function mergeMentionSuggestionTheme(
54
54
  export function allocateToolbarFrameOwnerId(): number {
55
55
  const ownerId = nextNativeEditorToolbarFrameOwnerId;
56
56
  nextNativeEditorToolbarFrameOwnerId += 1;
57
+
57
58
  return ownerId;
58
59
  }
59
60
 
@@ -82,13 +83,13 @@ export function selectedAtomKeys(
82
83
  ): Set<string> {
83
84
  return new Set(
84
85
  instances
85
- .filter((instance) => atomSelected(selection, instance.docPos))
86
+ .filter(instance => atomSelected(selection, instance.docPos))
86
87
  .map(({ key }) => key)
87
88
  );
88
89
  }
89
90
 
90
91
  export function equalStringSets(left: ReadonlySet<string>, right: ReadonlySet<string>): boolean {
91
- return left.size === right.size && [...left].every((value) => right.has(value));
92
+ return left.size === right.size && [ ...left ].every(value => right.has(value));
92
93
  }
93
94
 
94
95
  export function equalAtomInstances(
@@ -112,11 +113,18 @@ export function isRecord(value: unknown): value is Record<string, unknown> {
112
113
  }
113
114
 
114
115
  export function parseSelectionFromUpdate(value: unknown): Selection | null {
115
- if (!isRecord(value)) return null;
116
- if (value.type === 'all') return { type: 'all' };
116
+ if (!isRecord(value)) {
117
+ return null;
118
+ }
119
+
120
+ if (value.type === 'all') {
121
+ return { type: 'all' };
122
+ }
123
+
117
124
  if (value.type === 'node' && typeof value.pos === 'number') {
118
125
  return { type: 'node', pos: value.pos };
119
126
  }
127
+
120
128
  if (
121
129
  value.type === 'text' &&
122
130
  typeof value.anchor === 'number' &&
@@ -124,6 +132,7 @@ export function parseSelectionFromUpdate(value: unknown): Selection | null {
124
132
  ) {
125
133
  return { type: 'text', anchor: value.anchor, head: value.head };
126
134
  }
135
+
127
136
  return null;
128
137
  }
129
138
 
@@ -134,16 +143,26 @@ export function stringArray(value: unknown): string[] {
134
143
  }
135
144
 
136
145
  export function booleanMap(value: unknown): Record<string, boolean> {
137
- if (!isRecord(value)) return {};
146
+ if (!isRecord(value)) {
147
+ return {};
148
+ }
149
+
138
150
  const result: Record<string, boolean> = {};
151
+
139
152
  for (const key of Object.keys(value)) {
140
- if (typeof value[key] === 'boolean') result[key] = value[key] as boolean;
153
+ if (typeof value[key] === 'boolean') {
154
+ result[key] = value[key];
155
+ }
141
156
  }
157
+
142
158
  return result;
143
159
  }
144
160
 
145
161
  export function parseActiveStateFromUpdate(value: unknown): ActiveState | null {
146
- if (!isRecord(value)) return null;
162
+ if (!isRecord(value)) {
163
+ return null;
164
+ }
165
+
147
166
  return {
148
167
  marks: booleanMap(value.marks),
149
168
  markAttrs: isRecord(value.markAttrs)
@@ -188,6 +207,7 @@ export function acceptNativeCommitPayload(
188
207
  const canonicalBoundEditorId = normalizeNativeEditorV2DecimalId(boundEditorId);
189
208
  const canonicalEditorId = normalizeNativeEditorV2DecimalId(payload.editorId);
190
209
  const canonicalRevision = normalizeNativeEditorV2DecimalId(payload.documentRevision);
210
+
191
211
  if (
192
212
  canonicalBoundEditorId == null ||
193
213
  canonicalBoundEditorId !== boundEditorId ||
@@ -199,11 +219,17 @@ export function acceptNativeCommitPayload(
199
219
  ) {
200
220
  return null;
201
221
  }
222
+
202
223
  const snapshot = normalizeNativeEditorV2RenderUpdateValue(payload.updateJson);
203
- if (snapshot == null || snapshot.documentVersion !== canonicalRevision) return null;
224
+
225
+ if (snapshot == null || snapshot.documentVersion !== canonicalRevision) {
226
+ return null;
227
+ }
228
+
204
229
  if (lastAcceptedRevision != null && BigInt(canonicalRevision) <= BigInt(lastAcceptedRevision)) {
205
230
  return null;
206
231
  }
232
+
207
233
  return { documentRevision: canonicalRevision, snapshot };
208
234
  }
209
235
 
@@ -219,19 +245,20 @@ export function mapToolbarChildForNative(
219
245
  type: 'action',
220
246
  key: LINK_TOOLBAR_ACTION_KEY,
221
247
  label: item.label,
222
- icon: item.icon as EditorToolbarIcon,
248
+ icon: item.icon,
223
249
  buttonStyle: item.buttonStyle,
224
250
  placement: item.placement,
225
251
  isActive: activeState.marks.link === true,
226
252
  isDisabled: !editable || !onRequestLink || !activeState.allowedMarks.includes('link'),
227
253
  };
228
254
  }
255
+
229
256
  if (item.type === 'image') {
230
257
  return {
231
258
  type: 'action',
232
259
  key: IMAGE_TOOLBAR_ACTION_KEY,
233
260
  label: item.label,
234
- icon: item.icon as EditorToolbarIcon,
261
+ icon: item.icon,
235
262
  buttonStyle: item.buttonStyle,
236
263
  placement: item.placement,
237
264
  isActive: false,
@@ -241,6 +268,7 @@ export function mapToolbarChildForNative(
241
268
  !activeState.insertableNodes.includes(IMAGE_NODE_NAME),
242
269
  };
243
270
  }
271
+
244
272
  return item;
245
273
  }
246
274
 
@@ -251,24 +279,25 @@ export function mapToolbarItemsForNative(
251
279
  onRequestLink?: RichTextEditorProps['onRequestLink'],
252
280
  onRequestImage?: RichTextEditorProps['onRequestImage']
253
281
  ): EditorToolbarItem[] {
254
- return items.map((item) => {
282
+ return items.map(item => {
255
283
  if (item.type === 'group') {
256
284
  return {
257
285
  ...item,
258
- items: item.items.map((child) =>
286
+ items: item.items.map(child =>
259
287
  mapToolbarChildForNative(
260
288
  child,
261
289
  activeState,
262
290
  editable,
263
291
  onRequestLink,
264
292
  onRequestImage
265
- )
266
- ),
293
+ )),
267
294
  };
268
295
  }
296
+
269
297
  if (item.type === 'separator') {
270
298
  return item;
271
299
  }
300
+
272
301
  return mapToolbarChildForNative(item, activeState, editable, onRequestLink, onRequestImage);
273
302
  });
274
303
  }
@@ -279,11 +308,14 @@ export function serializeRemoteSelections(
279
308
  if (!remoteSelections || remoteSelections.length === 0) {
280
309
  return undefined;
281
310
  }
282
- const normalized = remoteSelections.map((selection) => {
311
+
312
+ const normalized = remoteSelections.map(selection => {
283
313
  const clientId = normalizeNativeEditorV2DecimalId(selection.clientId);
314
+
284
315
  if (clientId == null) {
285
316
  throw new Error('NativeRichTextEditor: remote clientId must be canonical decimal u64');
286
317
  }
318
+
287
319
  return {
288
320
  ...selection,
289
321
  clientId,
@@ -291,6 +323,7 @@ export function serializeRemoteSelections(
291
323
  head: requireNativeEditorV2U32(selection.head, 'remote selection head'),
292
324
  };
293
325
  });
326
+
294
327
  return stringifyCachedJson(normalized);
295
328
  }
296
329
 
@@ -300,6 +333,7 @@ export function serializeToolbarFrames(
300
333
  if (!frames || frames.length === 0) {
301
334
  return undefined;
302
335
  }
336
+
303
337
  return JSON.stringify(frames.length === 1 ? frames[0] : { frames });
304
338
  }
305
339
 
@@ -316,6 +350,7 @@ export function parseCaretRectJson(raw: string | null | undefined): RichTextEdit
316
350
  const height = typeof parsed.height === 'number' ? parsed.height : null;
317
351
  const editorWidth = typeof parsed.editorWidth === 'number' ? parsed.editorWidth : null;
318
352
  const editorHeight = typeof parsed.editorHeight === 'number' ? parsed.editorHeight : null;
353
+
319
354
  if (
320
355
  x == null ||
321
356
  y == null ||
@@ -326,7 +361,10 @@ export function parseCaretRectJson(raw: string | null | undefined): RichTextEdit
326
361
  ) {
327
362
  return null;
328
363
  }
329
- return { x, y, width, height, editorWidth, editorHeight };
364
+
365
+ return {
366
+ x, y, width, height, editorWidth, editorHeight,
367
+ };
330
368
  } catch {
331
369
  return null;
332
370
  }
@@ -337,13 +375,17 @@ export const serializedJsonCache = new WeakMap<object, string>();
337
375
  export function stringifyCachedJson(value: unknown): string {
338
376
  if (value != null && typeof value === 'object') {
339
377
  const cached = serializedJsonCache.get(value);
378
+
340
379
  if (cached != null) {
341
380
  return cached;
342
381
  }
382
+
343
383
  const serialized = JSON.stringify(value);
344
384
  serializedJsonCache.set(value, serialized);
385
+
345
386
  return serialized;
346
387
  }
388
+
347
389
  return JSON.stringify(value);
348
390
  }
349
391
 
@@ -358,6 +400,7 @@ export function useSerializedValue<T>(
358
400
  hasRevision: boolean;
359
401
  serialized: string | undefined;
360
402
  } | null>(null);
403
+
361
404
  const hasRevision = revision !== undefined;
362
405
  const cached = cacheRef.current;
363
406
 
@@ -365,17 +408,20 @@ export function useSerializedValue<T>(
365
408
  if (hasRevision && cached.hasRevision && Object.is(cached.revision, revision)) {
366
409
  return cached.serialized;
367
410
  }
411
+
368
412
  if (Object.is(cached.value, value) && cached.hasRevision === hasRevision) {
369
413
  return cached.serialized;
370
414
  }
371
415
  }
372
416
 
373
417
  const serialized = value == null ? undefined : serialize(value);
418
+
374
419
  cacheRef.current = {
375
420
  value,
376
421
  revision,
377
422
  hasRevision,
378
423
  serialized,
379
424
  };
425
+
380
426
  return serialized;
381
427
  }
@@ -200,7 +200,7 @@ export interface RichTextEditorProps {
200
200
  /** Remote awareness selections rendered as native overlays. */
201
201
  remoteSelections?: readonly RemoteSelectionDecoration[];
202
202
  /**
203
- * Shared v2 document session the only construction path. The native
203
+ * Shared v2 document session : the only construction path. The native
204
204
  * view binds to the same session (its editorId is passed straight to the
205
205
  * view), so typing, IME, selection, and toolbar commands flow through
206
206
  * the native v2 adapters into the shared engine while this component