@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
@@ -34,10 +34,12 @@ exports.LINK_TOOLBAR_ACTION_KEY = '__native-editor-link__';
34
34
  exports.IMAGE_TOOLBAR_ACTION_KEY = '__native-editor-image__';
35
35
  exports.nextNativeEditorToolbarFrameOwnerId = 1;
36
36
  function mergeMentionSuggestionTheme(baseTheme, resolvedTheme) {
37
- if (baseTheme == null)
37
+ if (baseTheme == null) {
38
38
  return resolvedTheme;
39
- if (resolvedTheme == null)
39
+ }
40
+ if (resolvedTheme == null) {
40
41
  return baseTheme;
42
+ }
41
43
  return {
42
44
  node: { ...baseTheme.node, ...resolvedTheme.node },
43
45
  suggestions: {
@@ -62,11 +64,11 @@ exports.EMPTY_ACTIVE_STATE = {
62
64
  };
63
65
  function selectedAtomKeys(selection, instances) {
64
66
  return new Set(instances
65
- .filter((instance) => (0, atomInstances_1.atomSelected)(selection, instance.docPos))
67
+ .filter(instance => (0, atomInstances_1.atomSelected)(selection, instance.docPos))
66
68
  .map(({ key }) => key));
67
69
  }
68
70
  function equalStringSets(left, right) {
69
- return left.size === right.size && [...left].every((value) => right.has(value));
71
+ return left.size === right.size && [...left].every(value => right.has(value));
70
72
  }
71
73
  function equalAtomInstances(left, right) {
72
74
  return (left.length === right.length &&
@@ -79,10 +81,12 @@ function isRecord(value) {
79
81
  return value != null && typeof value === 'object' && !Array.isArray(value);
80
82
  }
81
83
  function parseSelectionFromUpdate(value) {
82
- if (!isRecord(value))
84
+ if (!isRecord(value)) {
83
85
  return null;
84
- if (value.type === 'all')
86
+ }
87
+ if (value.type === 'all') {
85
88
  return { type: 'all' };
89
+ }
86
90
  if (value.type === 'node' && typeof value.pos === 'number') {
87
91
  return { type: 'node', pos: value.pos };
88
92
  }
@@ -99,18 +103,21 @@ function stringArray(value) {
99
103
  : [];
100
104
  }
101
105
  function booleanMap(value) {
102
- if (!isRecord(value))
106
+ if (!isRecord(value)) {
103
107
  return {};
108
+ }
104
109
  const result = {};
105
110
  for (const key of Object.keys(value)) {
106
- if (typeof value[key] === 'boolean')
111
+ if (typeof value[key] === 'boolean') {
107
112
  result[key] = value[key];
113
+ }
108
114
  }
109
115
  return result;
110
116
  }
111
117
  function parseActiveStateFromUpdate(value) {
112
- if (!isRecord(value))
118
+ if (!isRecord(value)) {
113
119
  return null;
120
+ }
114
121
  return {
115
122
  marks: booleanMap(value.marks),
116
123
  markAttrs: isRecord(value.markAttrs)
@@ -147,8 +154,9 @@ function acceptNativeCommitPayload(payload, boundEditorId, lastAcceptedRevision)
147
154
  return null;
148
155
  }
149
156
  const snapshot = (0, NativeEditorBridge_1.normalizeNativeEditorV2RenderUpdateValue)(payload.updateJson);
150
- if (snapshot == null || snapshot.documentVersion !== canonicalRevision)
157
+ if (snapshot == null || snapshot.documentVersion !== canonicalRevision) {
151
158
  return null;
159
+ }
152
160
  if (lastAcceptedRevision != null && BigInt(canonicalRevision) <= BigInt(lastAcceptedRevision)) {
153
161
  return null;
154
162
  }
@@ -184,11 +192,11 @@ function mapToolbarChildForNative(item, activeState, editable, onRequestLink, on
184
192
  return item;
185
193
  }
186
194
  function mapToolbarItemsForNative(items, activeState, editable, onRequestLink, onRequestImage) {
187
- return items.map((item) => {
195
+ return items.map(item => {
188
196
  if (item.type === 'group') {
189
197
  return {
190
198
  ...item,
191
- items: item.items.map((child) => mapToolbarChildForNative(child, activeState, editable, onRequestLink, onRequestImage)),
199
+ items: item.items.map(child => mapToolbarChildForNative(child, activeState, editable, onRequestLink, onRequestImage)),
192
200
  };
193
201
  }
194
202
  if (item.type === 'separator') {
@@ -201,7 +209,7 @@ function serializeRemoteSelections(remoteSelections) {
201
209
  if (!remoteSelections || remoteSelections.length === 0) {
202
210
  return undefined;
203
211
  }
204
- const normalized = remoteSelections.map((selection) => {
212
+ const normalized = remoteSelections.map(selection => {
205
213
  const clientId = (0, NativeEditorBridge_1.normalizeNativeEditorV2DecimalId)(selection.clientId);
206
214
  if (clientId == null) {
207
215
  throw new Error('NativeRichTextEditor: remote clientId must be canonical decimal u64');
@@ -241,7 +249,9 @@ function parseCaretRectJson(raw) {
241
249
  editorHeight == null) {
242
250
  return null;
243
251
  }
244
- return { x, y, width, height, editorWidth, editorHeight };
252
+ return {
253
+ x, y, width, height, editorWidth, editorHeight,
254
+ };
245
255
  }
246
256
  catch {
247
257
  return null;
@@ -167,7 +167,7 @@ export interface RichTextEditorProps {
167
167
  /** Remote awareness selections rendered as native overlays. */
168
168
  remoteSelections?: readonly RemoteSelectionDecoration[];
169
169
  /**
170
- * Shared v2 document session the only construction path. The native
170
+ * Shared v2 document session : the only construction path. The native
171
171
  * view binds to the same session (its editorId is passed straight to the
172
172
  * view), so typing, IME, selection, and toolbar commands flow through
173
173
  * the native v2 adapters into the shared engine while this component
@@ -3,13 +3,13 @@ import type { RemoteSelectionDecoration } from './NativeRichTextEditor';
3
3
  /**
4
4
  * Transport lifecycle, projected from the Rust transport state.
5
5
  *
6
- * - `idle` no transport configured; the handle is detached.
7
- * - `disconnected` configured but not currently connected.
8
- * - `connecting` opening the physical socket.
9
- * - `handshaking` socket open, Yjs sync in progress.
10
- * - `synchronized` sync complete; edits flow in both directions.
11
- * - `incompatible` the server's document cannot be reconciled with this one.
12
- * - `destroyed` the handle was destroyed.
6
+ * - `idle` : no transport configured; the handle is detached.
7
+ * - `disconnected` : configured but not currently connected.
8
+ * - `connecting` : opening the physical socket.
9
+ * - `handshaking` : socket open, Yjs sync in progress.
10
+ * - `synchronized` : sync complete; edits flow in both directions.
11
+ * - `incompatible` : the server's document cannot be reconciled with this one.
12
+ * - `destroyed` : the handle was destroyed.
13
13
  */
14
14
  export type YjsTransportStatus = 'idle' | 'disconnected' | 'connecting' | 'handshaking' | 'synchronized' | 'incompatible' | 'destroyed';
15
15
  /** Identity this client publishes to other peers through awareness. */
@@ -27,16 +27,19 @@ function asError(value, fallbackMessage) {
27
27
  return value instanceof Error ? value : new Error(fallbackMessage);
28
28
  }
29
29
  function isStrictlyNewerSequence(candidate, current) {
30
- if (current === null)
30
+ if (current === null) {
31
31
  return true;
32
- if (candidate.length !== current.length)
32
+ }
33
+ if (candidate.length !== current.length) {
33
34
  return candidate.length > current.length;
35
+ }
34
36
  return candidate > current;
35
37
  }
36
38
  function peersToRemoteSelections(peers) {
37
- return peers.flatMap((peer) => {
38
- if (peer.isLocal || peer.cursor == null)
39
+ return peers.flatMap(peer => {
40
+ if (peer.isLocal || peer.cursor == null) {
39
41
  return [];
42
+ }
40
43
  const applicationState = peer.state && typeof peer.state.state === 'object' && peer.state.state !== null
41
44
  ? peer.state.state
42
45
  : null;
@@ -64,14 +67,16 @@ function peersToRemoteSelections(peers) {
64
67
  }
65
68
  /**
66
69
  * Narrow a caller selection to the text-only cursor awareness carries.
67
- * Anything else a node or all-document selection, or an absent one is
70
+ * Anything else : a node or all-document selection, or an absent one : is
68
71
  * an explicit "no cursor", never a silently retained stale position.
69
72
  */
70
73
  function normalizeAwarenessSelection(selection) {
71
- if (selection === undefined || selection.type !== 'text')
74
+ if (selection === undefined || selection.type !== 'text') {
72
75
  return undefined;
73
- if (selection.anchor === undefined || selection.head === undefined)
76
+ }
77
+ if (selection.anchor === undefined || selection.head === undefined) {
74
78
  return undefined;
79
+ }
75
80
  return (0, NativeEditorBridge_1.createNativeEditorLocalAwarenessSelection)(selection.anchor, selection.head);
76
81
  }
77
82
  /**
@@ -80,8 +85,9 @@ function normalizeAwarenessSelection(selection) {
80
85
  * as the transport-less reads elsewhere in this module assume.
81
86
  */
82
87
  function copyTransportConfig(config) {
83
- if (config == null)
88
+ if (config == null) {
84
89
  return null;
90
+ }
85
91
  return {
86
92
  url: config.url,
87
93
  connect: config.connect,
@@ -126,7 +132,7 @@ function mergeAwarenessPartial(base, partial) {
126
132
  };
127
133
  // Selection is stated only when the caller states it. Rust holds the
128
134
  // local cursor as a sticky index that already tracks every document
129
- // change, so an omitted key means "retain it" never "resend the last
135
+ // change, so an omitted key means "retain it" : never "resend the last
130
136
  // position I happened to see", which the document may have invalidated.
131
137
  if ('selection' in partial) {
132
138
  next.selection = normalizeAwarenessSelection(partial.selection) ?? null;
@@ -148,7 +154,7 @@ class YjsCollaborationControllerImpl {
148
154
  this.callbacks = callbacks;
149
155
  this.transport = copyTransportConfig(options.transport);
150
156
  this._state = this.readEngineState(this.handle.bridge.getState());
151
- this.removeTransportListener = this.handle.addCollaborationTransportListener((event) => {
157
+ this.removeTransportListener = this.handle.addCollaborationTransportListener(event => {
152
158
  this.handleTransportEvent(event);
153
159
  });
154
160
  try {
@@ -177,15 +183,17 @@ class YjsCollaborationControllerImpl {
177
183
  this.setConnectionEnabled(false);
178
184
  }
179
185
  reconnect() {
180
- if (this.destroyed || this.transport === null)
186
+ if (this.destroyed || this.transport === null) {
181
187
  return;
188
+ }
182
189
  this.handle.configureCollaborationTransport({ ...this.transport, connect: false });
183
190
  this.transport = { ...this.transport, connect: true };
184
191
  this.handle.configureCollaborationTransport(this.transport);
185
192
  }
186
193
  destroy() {
187
- if (this.destroyed)
194
+ if (this.destroyed) {
188
195
  return;
196
+ }
189
197
  this.destroyed = true;
190
198
  this.removeTransportListener?.();
191
199
  this.removeTransportListener = null;
@@ -194,13 +202,15 @@ class YjsCollaborationControllerImpl {
194
202
  }
195
203
  }
196
204
  updateLocalAwareness(partial) {
197
- if (this.destroyed)
205
+ if (this.destroyed) {
198
206
  return;
207
+ }
199
208
  // Presence exists only while there is a local user. Once awareness
200
209
  // is withdrawn, focus and selection updates must not resurrect it
201
210
  // as an anonymous entry; only a fresh user re-establishes it.
202
- if (this.desiredAwareness === null && partial.user == null)
211
+ if (this.desiredAwareness === null && partial.user == null) {
203
212
  return;
213
+ }
204
214
  const base = this.desiredAwareness ?? { state: {}, focused: false };
205
215
  this.publishAwareness(mergeAwarenessPartial(base, partial));
206
216
  }
@@ -211,8 +221,9 @@ class YjsCollaborationControllerImpl {
211
221
  this.updateLocalAwareness({ focused });
212
222
  }
213
223
  applyLocalAwarenessOption(user) {
214
- if (this.destroyed)
224
+ if (this.destroyed) {
215
225
  return;
226
+ }
216
227
  if (user == null) {
217
228
  // Always withdraw: a fresh controller inherits whatever presence
218
229
  // a previous one left retained natively on this shared handle.
@@ -239,8 +250,9 @@ class YjsCollaborationControllerImpl {
239
250
  });
240
251
  }
241
252
  setConnectionEnabled(connect) {
242
- if (this.destroyed || this.transport === null)
253
+ if (this.destroyed || this.transport === null) {
243
254
  return;
255
+ }
244
256
  this.transport = { ...this.transport, connect };
245
257
  this.handle.configureCollaborationTransport(this.transport);
246
258
  }
@@ -251,7 +263,7 @@ class YjsCollaborationControllerImpl {
251
263
  * `desiredAwareness` advances only after native acceptance.
252
264
  *
253
265
  * Presence is ambient UI state, not user data. A refusal is reported
254
- * through `onError` and retried on the next change it never escapes
266
+ * through `onError` and retried on the next change : it never escapes
255
267
  * into a host focus, blur, or selection handler, and never fails an
256
268
  * edit. The candidate is discarded so state stays consistent with Rust.
257
269
  */
@@ -261,8 +273,9 @@ class YjsCollaborationControllerImpl {
261
273
  // Serializing caller-owned application state can itself fail on
262
274
  // a cyclic or non-encodable value, so it stays inside the guard.
263
275
  intentJson = JSON.stringify(intent);
264
- if (intentJson === this.publishedAwarenessJson)
276
+ if (intentJson === this.publishedAwarenessJson) {
265
277
  return;
278
+ }
266
279
  this.handle.setLocalAwareness(intent);
267
280
  }
268
281
  catch (error) {
@@ -288,8 +301,9 @@ class YjsCollaborationControllerImpl {
288
301
  this.callbacks.onError?.(error);
289
302
  return;
290
303
  }
291
- if (event.kind !== 'state')
304
+ if (event.kind !== 'state') {
292
305
  return;
306
+ }
293
307
  this._peers = [...event.peers];
294
308
  this.callbacks.onPeersChange?.(this._peers);
295
309
  try {
@@ -383,8 +397,9 @@ function useYjsCollaboration(options) {
383
397
  });
384
398
  const stableTransportProtocolAdapter = (0, react_1.useMemo)(() => {
385
399
  const current = transportProtocolAdapterRef.current;
386
- if (current === null)
400
+ if (current === null) {
387
401
  return null;
402
+ }
388
403
  return {
389
404
  protocols: [...current.protocols],
390
405
  ...(current.timeoutMillis === undefined
@@ -393,7 +408,7 @@ function useYjsCollaboration(options) {
393
408
  ...(current.terminalCloseCodes === undefined
394
409
  ? {}
395
410
  : { terminalCloseCodes: [...current.terminalCloseCodes] }),
396
- onOpen: (context) => transportProtocolAdapterRef.current?.onOpen(context) ?? {
411
+ onOpen: context => transportProtocolAdapterRef.current?.onOpen(context) ?? {
397
412
  action: 'reject',
398
413
  },
399
414
  onMessage: (context, frame) => transportProtocolAdapterRef.current?.onMessage(context, frame) ?? {
@@ -427,15 +442,15 @@ function useYjsCollaboration(options) {
427
442
  : { protocolAdapter: stableTransportProtocolAdapter }),
428
443
  },
429
444
  }, {
430
- onStateChange: (nextState) => {
445
+ onStateChange: nextState => {
431
446
  setState({ ...nextState });
432
447
  callbacksRef.current.onStateChange?.(nextState);
433
448
  },
434
- onPeersChange: (nextPeers) => {
449
+ onPeersChange: nextPeers => {
435
450
  setPeers([...nextPeers]);
436
451
  callbacksRef.current.onPeersChange?.(nextPeers);
437
452
  },
438
- onError: (error) => callbacksRef.current.onError?.(error),
453
+ onError: error => callbacksRef.current.onError?.(error),
439
454
  });
440
455
  controllerRef.current = controller;
441
456
  setState({ ...controller.state });
@@ -468,8 +483,9 @@ function useYjsCollaboration(options) {
468
483
  // eslint-disable-next-line react-hooks/exhaustive-deps
469
484
  }, [localAwarenessKey]);
470
485
  (0, react_1.useEffect)(() => {
471
- if (transportUrl === null)
486
+ if (transportUrl === null) {
472
487
  return;
488
+ }
473
489
  if (transportConnect) {
474
490
  controllerRef.current?.connect();
475
491
  }
@@ -484,7 +500,7 @@ function useYjsCollaboration(options) {
484
500
  connect: () => controllerRef.current?.connect(),
485
501
  disconnect: () => controllerRef.current?.disconnect(),
486
502
  reconnect: () => controllerRef.current?.reconnect(),
487
- updateLocalAwareness: (partial) => controllerRef.current?.updateLocalAwareness(partial),
503
+ updateLocalAwareness: partial => controllerRef.current?.updateLocalAwareness(partial),
488
504
  editorBindings: {
489
505
  documentHandle: options.handle,
490
506
  documentRevision: state.documentRevision,
package/dist/addons.d.ts CHANGED
@@ -30,7 +30,7 @@ export interface MentionQueryChangeEvent {
30
30
  anchor: number;
31
31
  head: number;
32
32
  };
33
- /** False once the query closed supply an empty suggestion list. */
33
+ /** False once the query closed : supply an empty suggestion list. */
34
34
  isActive: boolean;
35
35
  /** Engine document revision the query was computed against. */
36
36
  documentVersion?: string;
@@ -52,7 +52,7 @@ export interface MentionSelectEvent {
52
52
  export interface MentionSelectionAttrsEvent {
53
53
  trigger: string;
54
54
  suggestion: MentionSuggestion;
55
- /** Attributes resolved so far the suggestion's own, plus `label` and `mentionSuggestionChar`. */
55
+ /** Attributes resolved so far : the suggestion's own, plus `label` and `mentionSuggestionChar`. */
56
56
  attrs: Record<string, unknown>;
57
57
  /** Mark attributes active at the insertion point. */
58
58
  markAttrs: ReadonlyActiveState['markAttrs'];
@@ -69,7 +69,7 @@ export type MentionThemeResolveEvent = MentionSelectionAttrsEvent;
69
69
  /**
70
70
  * Mentions for `RichTextEditor`. The schema belongs to the document
71
71
  * handle, so create the handle with {@link withMentionsSchema} applied to
72
- * your schema this config alone does not add the `mention` node.
72
+ * your schema : this config alone does not add the `mention` node.
73
73
  * (`RichTextViewer` adds it for you.)
74
74
  *
75
75
  * The host owns the suggestion list: react to `onQueryChange` by filtering
@@ -185,7 +185,7 @@ export interface MentionFragmentOptions {
185
185
  /**
186
186
  * Build a document fragment holding one mention node, ready for
187
187
  * `insertContentJson`. Use it to insert a mention outside the suggestion
188
- * flow from a picker, say.
188
+ * flow : from a picker, say.
189
189
  *
190
190
  * @param attrs Attributes for the mention node, e.g. `{ label, id }`.
191
191
  * @param descriptor Document node name to wrap the fragment in. Defaults to `doc`.
package/dist/addons.js CHANGED
@@ -54,7 +54,7 @@ function mentionNodeSpec() {
54
54
  * ```
55
55
  */
56
56
  function withMentionsSchema(schema) {
57
- const hasMentionNode = schema.nodes.some((node) => node.name === exports.MENTION_NODE_NAME);
57
+ const hasMentionNode = schema.nodes.some(node => node.name === exports.MENTION_NODE_NAME);
58
58
  if (hasMentionNode) {
59
59
  return schema;
60
60
  }
@@ -68,7 +68,7 @@ function normalizeNativeEditorAddons(addons) {
68
68
  return addons?.codeHighlighting ? { codeHighlighting: addons.codeHighlighting } : undefined;
69
69
  }
70
70
  const trigger = addons.mentions.trigger?.trim() || DEFAULT_MENTION_TRIGGER;
71
- const suggestions = (addons.mentions.suggestions ?? []).map((suggestion) => {
71
+ const suggestions = (addons.mentions.suggestions ?? []).map(suggestion => {
72
72
  const label = suggestion.label?.trim() || suggestion.title;
73
73
  const attrs = {
74
74
  label,
@@ -106,7 +106,7 @@ function serializeNormalizedEditorAddons(addons) {
106
106
  /**
107
107
  * Build a document fragment holding one mention node, ready for
108
108
  * `insertContentJson`. Use it to insert a mention outside the suggestion
109
- * flow from a picker, say.
109
+ * flow : from a picker, say.
110
110
  *
111
111
  * @param attrs Attributes for the mention node, e.g. `{ label, id }`.
112
112
  * @param descriptor Document node name to wrap the fragment in. Defaults to `doc`.
@@ -67,13 +67,16 @@ function applyRenderPatch(previousBlocks, patch) {
67
67
  ];
68
68
  }
69
69
  function atomSelected(selection, docPos) {
70
- if (selection.type === 'all')
70
+ if (selection.type === 'all') {
71
71
  return true;
72
- if (selection.type === 'node')
72
+ }
73
+ if (selection.type === 'node') {
73
74
  return selection.pos === docPos;
75
+ }
74
76
  const { anchor, head } = selection;
75
- if (anchor == null || head == null)
77
+ if (anchor == null || head == null) {
76
78
  return false;
79
+ }
77
80
  const [from, to] = anchor <= head ? [anchor, head] : [head, anchor];
78
81
  return from <= docPos && docPos + 1 <= to;
79
82
  }
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveAtomAttrsUpdate = resolveAtomAttrsUpdate;
4
4
  const atomInstances_1 = require("./atomInstances");
5
5
  function copyJson(value, ancestors = new Set()) {
6
- if (value === null || typeof value === 'string' || typeof value === 'boolean')
6
+ if (value === null || typeof value === 'string' || typeof value === 'boolean') {
7
7
  return value;
8
- if (typeof value === 'number' && Number.isFinite(value))
8
+ }
9
+ if (typeof value === 'number' && Number.isFinite(value)) {
9
10
  return value;
11
+ }
10
12
  if (typeof value !== 'object' || ancestors.has(value) || ancestors.size > 128) {
11
13
  throw new atomInstances_1.AtomUpdateAttrsError('not-applicable', 'Atom attributes must contain finite JSON values.');
12
14
  }
@@ -17,7 +19,7 @@ function copyJson(value, ancestors = new Set()) {
17
19
  }
18
20
  ancestors.add(value);
19
21
  const result = Array.isArray(value)
20
- ? Array.from(value, (entry) => copyJson(entry, ancestors))
22
+ ? Array.from(value, entry => copyJson(entry, ancestors))
21
23
  : Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, copyJson(entry, ancestors)]));
22
24
  ancestors.delete(value);
23
25
  return Object.freeze(result);
@@ -25,7 +27,8 @@ function copyJson(value, ancestors = new Set()) {
25
27
  function resolveAtomAttrsUpdate(attrs, update) {
26
28
  let current = copyJson(attrs);
27
29
  let patch = {};
28
- for (const entry of Array.isArray(update) ? update : [update]) {
30
+ const updates = Array.isArray(update) ? update : [update];
31
+ for (const entry of updates) {
29
32
  const value = typeof entry === 'function' ? entry(current) : entry;
30
33
  if (value == null || typeof value !== 'object' || Array.isArray(value)) {
31
34
  throw new atomInstances_1.AtomUpdateAttrsError('not-applicable', 'Atom updates must return an attribute object.');
package/dist/atoms.js CHANGED
@@ -7,10 +7,12 @@ const attributeValidation_1 = require("./attributeValidation");
7
7
  const atomConstants_1 = require("./atomConstants");
8
8
  const atomPolicy_1 = require("./atomPolicy");
9
9
  function isAtomComponent(value) {
10
- if (typeof value === 'function')
10
+ if (typeof value === 'function') {
11
11
  return true;
12
- if (value == null || typeof value !== 'object' || !('$$typeof' in value))
12
+ }
13
+ if (value == null || typeof value !== 'object' || !('$$typeof' in value)) {
13
14
  return false;
15
+ }
14
16
  return (value.$$typeof === Symbol.for('react.memo') ||
15
17
  value.$$typeof === Symbol.for('react.forward_ref') ||
16
18
  value.$$typeof === Symbol.for('react.lazy'));
@@ -48,7 +50,7 @@ function normalizedHtmlRules(config) {
48
50
  throw new Error(`atom '${config.name}' requires HTML rules`);
49
51
  }
50
52
  const raw = config.html;
51
- if (Object.keys(raw).some((key) => !['tag', 'staticAttrs', 'attrMap'].includes(key))) {
53
+ if (Object.keys(raw).some(key => !['tag', 'staticAttrs', 'attrMap'].includes(key))) {
52
54
  throw new Error(`atom '${config.name}' has an unknown HTML rule field`);
53
55
  }
54
56
  if (typeof raw.tag !== 'string' || !isSafeTag(raw.tag)) {
@@ -65,7 +67,7 @@ function normalizedHtmlRules(config) {
65
67
  }
66
68
  const attrs = config.attrs ?? {};
67
69
  const attrMap = raw.attrMap == null
68
- ? Object.fromEntries(Object.keys(attrs).map((name) => [name, `data-${kebabCase(name)}`]))
70
+ ? Object.fromEntries(Object.keys(attrs).map(name => [name, `data-${kebabCase(name)}`]))
69
71
  : stringRecord(raw.attrMap, `atom '${config.name}' attrMap`);
70
72
  for (const name of Object.keys(attrMap)) {
71
73
  if (!Object.prototype.hasOwnProperty.call(attrs, name)) {
@@ -115,10 +117,12 @@ function defineAtomNode(config) {
115
117
  if (config.attrs != null && (typeof config.attrs !== 'object' || Array.isArray(config.attrs))) {
116
118
  throw new Error(`atom '${config.name}' attrs must be an object`);
117
119
  }
118
- for (const [name, spec] of Object.entries(config.attrs ?? {}))
120
+ for (const [name, spec] of Object.entries(config.attrs ?? {})) {
119
121
  (0, attributeValidation_1.validateAttributeSpec)(spec, name);
120
- if (config.idAttribute !== undefined && config.attrs?.[config.idAttribute]?.type !== 'string')
122
+ }
123
+ if (config.idAttribute !== undefined && config.attrs?.[config.idAttribute]?.type !== 'string') {
121
124
  throw new Error(`atom '${config.name}' identifier attribute must declare type string`);
125
+ }
122
126
  const html = normalizedHtmlRules(config);
123
127
  const nodeSpec = {
124
128
  name: config.name,
@@ -152,8 +156,9 @@ function defineAtomNode(config) {
152
156
  };
153
157
  }
154
158
  function schemaValuesEqual(left, right) {
155
- if (Object.is(left, right))
159
+ if (Object.is(left, right)) {
156
160
  return true;
161
+ }
157
162
  if (left == null || right == null || typeof left !== 'object' || typeof right !== 'object') {
158
163
  return false;
159
164
  }
@@ -171,13 +176,14 @@ function schemaValuesEqual(left, right) {
171
176
  leftKeys.every((key, index) => key === rightKeys[index] && schemaValuesEqual(leftRecord[key], rightRecord[key])));
172
177
  }
173
178
  function assertUnambiguousHtmlRules(nodes) {
174
- const ruled = nodes.filter((node) => node.html != null);
179
+ const ruled = nodes.filter(node => node.html != null);
175
180
  for (let rightIndex = 1; rightIndex < ruled.length; rightIndex += 1) {
176
181
  const right = ruled[rightIndex];
177
182
  for (let leftIndex = 0; leftIndex < rightIndex; leftIndex += 1) {
178
183
  const left = ruled[leftIndex];
179
- if (left.html?.tag !== right.html?.tag)
184
+ if (left.html?.tag !== right.html?.tag) {
180
185
  continue;
186
+ }
181
187
  const leftStatic = left.html?.staticAttrs ?? {};
182
188
  const rightStatic = right.html?.staticAttrs ?? {};
183
189
  const conflicts = Object.entries(leftStatic).some(([name, value]) => Object.prototype.hasOwnProperty.call(rightStatic, name) &&
@@ -192,7 +198,7 @@ function withAtomsSchema(schema, atoms) {
192
198
  const nodes = [...schema.nodes];
193
199
  let changed = false;
194
200
  for (const atom of atoms) {
195
- const existing = nodes.find((node) => node.name === atom.name);
201
+ const existing = nodes.find(node => node.name === atom.name);
196
202
  if (existing != null) {
197
203
  if (!schemaValuesEqual(existing, atom.nodeSpec)) {
198
204
  throw new Error(`schema already declares conflicting node '${atom.name}'`);
@@ -206,15 +212,17 @@ function withAtomsSchema(schema, atoms) {
206
212
  return changed ? { ...schema, nodes } : schema;
207
213
  }
208
214
  function serializeEditorAtoms(atoms) {
209
- if (atoms == null || atoms.length === 0)
215
+ if (atoms == null || atoms.length === 0) {
210
216
  return undefined;
217
+ }
211
218
  const serialized = {
212
219
  nodeTypes: [],
213
220
  estimatedHeights: {},
214
221
  };
215
222
  for (const atom of atoms) {
216
- if (Object.prototype.hasOwnProperty.call(serialized.estimatedHeights, atom.name))
223
+ if (Object.prototype.hasOwnProperty.call(serialized.estimatedHeights, atom.name)) {
217
224
  continue;
225
+ }
218
226
  serialized.nodeTypes.push(atom.name);
219
227
  serialized.estimatedHeights[atom.name] = atom.estimatedHeight ?? atomConstants_1.DEFAULT_ATOM_CHIP_HEIGHT;
220
228
  }