@apollohg/react-native-rich-text-editor 2.0.0 → 2.0.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 (161) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/android/build.gradle +3 -0
  4. package/app.plugin.js +42 -39
  5. package/dist/AtomHost.js +18 -11
  6. package/dist/EditorAddon.js +4 -2
  7. package/dist/EditorAddonNormalization.js +17 -9
  8. package/dist/EditorMentionThemeNormalization.js +6 -3
  9. package/dist/EditorMentionThemeValidation.js +28 -11
  10. package/dist/EditorStyleSheetNormalization.js +84 -37
  11. package/dist/EditorTheme.d.ts +4 -0
  12. package/dist/EditorTheme.js +5 -3
  13. package/dist/EditorToolbarComponent.d.ts +1 -1
  14. package/dist/EditorToolbarComponent.js +1 -1
  15. package/dist/EditorToolbarRegistry.js +5 -5
  16. package/dist/EditorToolbarTypes.d.ts +12 -12
  17. package/dist/EditorToolbarVisuals.js +1 -1
  18. package/dist/ExternalTextComposition.js +89 -43
  19. package/dist/ImageLoadingPolicy.d.ts +1 -1
  20. package/dist/NativeEditorBoundaryError.d.ts +7 -7
  21. package/dist/NativeEditorBoundaryError.js +9 -5
  22. package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
  23. package/dist/NativeEditorCollaborationTransport.js +28 -15
  24. package/dist/NativeEditorCreateConfig.js +11 -6
  25. package/dist/NativeEditorCreateJson.js +51 -25
  26. package/dist/NativeEditorCreateValidation.js +11 -6
  27. package/dist/NativeEditorDocumentBridge.d.ts +1 -1
  28. package/dist/NativeEditorDocumentBridge.js +32 -18
  29. package/dist/NativeEditorDocumentHandle.d.ts +4 -4
  30. package/dist/NativeEditorDocumentHandle.js +1 -1
  31. package/dist/NativeEditorLocalAwareness.js +25 -13
  32. package/dist/NativeEditorNativeModule.d.ts +8 -1
  33. package/dist/NativeEditorNativeModule.js +7 -5
  34. package/dist/NativeEditorRenderNormalization.js +66 -25
  35. package/dist/NativeEditorResultNormalization.js +53 -29
  36. package/dist/NativeEditorTypes.d.ts +10 -10
  37. package/dist/NativeEditorV2Decimal.js +6 -3
  38. package/dist/NativeProseViewer.js +11 -3
  39. package/dist/ResourceLimits.d.ts +2 -2
  40. package/dist/ResourceLimits.js +7 -2
  41. package/dist/RichTextEditor.js +1 -1
  42. package/dist/RichTextEditorNativeTypes.d.ts +1 -1
  43. package/dist/RichTextEditorNativeView.d.ts +1 -3
  44. package/dist/RichTextEditorSerialization.js +24 -14
  45. package/dist/RichTextEditorTypes.d.ts +1 -1
  46. package/dist/YjsCollaboration.d.ts +7 -7
  47. package/dist/YjsCollaboration.js +42 -26
  48. package/dist/addons.d.ts +4 -4
  49. package/dist/addons.js +3 -3
  50. package/dist/atomInstances.js +6 -3
  51. package/dist/atomUpdates.js +7 -4
  52. package/dist/atoms.js +20 -12
  53. package/dist/attributeValidation.js +55 -24
  54. package/dist/contentExpression.js +80 -42
  55. package/dist/listMarkers.d.ts +1 -1
  56. package/dist/listMarkers.js +1 -1
  57. package/dist/schemaDefinition.d.ts +1 -1
  58. package/dist/schemaDefinition.js +23 -14
  59. package/dist/schemaDocument.js +1 -1
  60. package/dist/schemaDocumentConstruction.js +25 -14
  61. package/dist/schemaNormalization.js +51 -29
  62. package/dist/schemaPresets.d.ts +1 -1
  63. package/dist/schemaPresets.js +9 -4
  64. package/dist/schemaResolution.js +46 -25
  65. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
  66. package/dist/useEditorToolbarInteractions.d.ts +2 -2
  67. package/dist/useEditorToolbarInteractions.js +45 -23
  68. package/dist/useEditorToolbarItems.d.ts +1 -1
  69. package/dist/useEditorToolbarItems.js +4 -3
  70. package/dist/useEditorToolbarPresentation.d.ts +3 -3
  71. package/dist/useEditorToolbarPresentation.js +4 -4
  72. package/dist/useEditorToolbarState.d.ts +1 -1
  73. package/dist/useEditorToolbarState.js +1 -1
  74. package/dist/useFocusPreservingFrames.js +11 -8
  75. package/dist/useNativeEditor.d.ts +1 -1
  76. package/dist/useNativeEditor.js +21 -11
  77. package/dist/useRichTextEditorCommands.d.ts +2 -2
  78. package/dist/useRichTextEditorCommands.js +59 -29
  79. package/dist/useRichTextEditorEvents.d.ts +3 -3
  80. package/dist/useRichTextEditorEvents.js +75 -32
  81. package/dist/useRichTextEditorMentions.d.ts +4 -4
  82. package/dist/useRichTextEditorMentions.js +48 -29
  83. package/dist/useRichTextEditorPresentation.d.ts +4 -4
  84. package/dist/useRichTextEditorPresentation.js +25 -23
  85. package/dist/useRichTextEditorState.d.ts +3 -3
  86. package/dist/useRichTextEditorState.js +20 -15
  87. package/dist/useRichTextEditorUpdates.d.ts +1 -1
  88. package/dist/useRichTextEditorUpdates.js +99 -41
  89. package/dist/useViewerAtoms.js +63 -36
  90. package/ios/EditorCore.xcframework/Info.plist +5 -5
  91. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  92. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  93. package/package.json +11 -3
  94. package/react-native.config.js +1 -1
  95. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  96. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  97. package/rust/android/x86/libeditor_core.so +0 -0
  98. package/rust/android/x86_64/libeditor_core.so +0 -0
  99. package/src/AtomHost.tsx +58 -28
  100. package/src/EditorAddon.ts +18 -8
  101. package/src/EditorAddonNormalization.ts +40 -11
  102. package/src/EditorMentionThemeNormalization.ts +15 -4
  103. package/src/EditorMentionThemeValidation.ts +51 -14
  104. package/src/EditorStyleSheet.ts +1 -0
  105. package/src/EditorStyleSheetNormalization.ts +195 -64
  106. package/src/EditorTheme.ts +13 -5
  107. package/src/EditorToolbarComponent.tsx +2 -1
  108. package/src/EditorToolbarRegistry.tsx +23 -13
  109. package/src/EditorToolbarTypes.tsx +12 -12
  110. package/src/EditorToolbarVisuals.tsx +6 -3
  111. package/src/EditorUpdateRevision.ts +1 -0
  112. package/src/ExternalTextComposition.ts +259 -49
  113. package/src/ImageLoadingPolicy.ts +3 -1
  114. package/src/NativeEditorBoundaryError.ts +38 -11
  115. package/src/NativeEditorCollaborationTransport.ts +108 -27
  116. package/src/NativeEditorCreateConfig.ts +92 -19
  117. package/src/NativeEditorCreateJson.ts +163 -26
  118. package/src/NativeEditorCreateValidation.ts +33 -12
  119. package/src/NativeEditorDocumentBridge.ts +111 -19
  120. package/src/NativeEditorDocumentHandle.ts +9 -4
  121. package/src/NativeEditorLocalAwareness.ts +70 -15
  122. package/src/NativeEditorNativeModule.ts +13 -9
  123. package/src/NativeEditorRenderNormalization.ts +128 -29
  124. package/src/NativeEditorResultNormalization.ts +143 -32
  125. package/src/NativeEditorTypes.ts +12 -11
  126. package/src/NativeEditorV2Decimal.ts +12 -3
  127. package/src/NativeProseViewer.tsx +46 -16
  128. package/src/ResourceLimits.ts +15 -8
  129. package/src/RichTextEditor.tsx +3 -1
  130. package/src/RichTextEditorNativeTypes.tsx +1 -1
  131. package/src/RichTextEditorNativeView.tsx +2 -8
  132. package/src/RichTextEditorSerialization.tsx +70 -24
  133. package/src/RichTextEditorTypes.tsx +1 -1
  134. package/src/YjsCollaboration.ts +143 -47
  135. package/src/addons.ts +12 -8
  136. package/src/atomInstances.ts +25 -5
  137. package/src/atomUpdates.ts +23 -6
  138. package/src/atoms.ts +85 -18
  139. package/src/attributeValidation.ts +97 -33
  140. package/src/contentExpression.ts +218 -63
  141. package/src/listMarkers.ts +1 -1
  142. package/src/schemaDefinition.ts +82 -20
  143. package/src/schemaDocument.ts +15 -1
  144. package/src/schemaDocumentConstruction.ts +80 -16
  145. package/src/schemaNormalization.ts +155 -41
  146. package/src/schemaPresets.ts +37 -31
  147. package/src/schemaResolution.ts +126 -27
  148. package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
  149. package/src/useEditorToolbarInteractions.tsx +85 -36
  150. package/src/useEditorToolbarItems.tsx +50 -22
  151. package/src/useEditorToolbarPresentation.tsx +81 -58
  152. package/src/useEditorToolbarState.tsx +8 -6
  153. package/src/useFocusPreservingFrames.ts +43 -15
  154. package/src/useNativeEditor.ts +111 -51
  155. package/src/useRichTextEditorCommands.tsx +127 -54
  156. package/src/useRichTextEditorEvents.tsx +144 -42
  157. package/src/useRichTextEditorMentions.tsx +118 -37
  158. package/src/useRichTextEditorPresentation.tsx +128 -114
  159. package/src/useRichTextEditorState.tsx +76 -40
  160. package/src/useRichTextEditorUpdates.tsx +207 -56
  161. package/src/useViewerAtoms.tsx +162 -66
@@ -65,7 +65,12 @@ function RichTextViewer(props) {
65
65
  const { contentJSON, contentHTML, schema, atoms, readOnly = true, atomsInteractive = true, atomViewport, onUpdateAtomAttrs, theme, allowBase64Images = false, imageLoadingPolicy, resourceLimits, collapseTrailingEmptyParagraphs = true, enableLinkTaps = true, renderImages = true, fontEnvironmentRevision = 0, addons, onPressLink, onError, ...viewProps } = props;
66
66
  const { mentions, codeHighlighting } = (0, react_1.useMemo)(() => (0, addons_1.normalizeEditorAddons)(addons), [addons]);
67
67
  const resolvedResourceLimits = (0, react_1.useMemo)(() => (resourceLimits ? (0, ResourceLimits_1.resolveEditorResourceLimits)(resourceLimits) : undefined), [resourceLimits]);
68
- const configJson = (0, react_1.useMemo)(() => (0, ViewerConfiguration_1.serializePreparedProseViewerConfiguration)(resolveViewerConfiguration(schema, allowBase64Images, resolvedResourceLimits, mentions, atoms, codeHighlighting)), [allowBase64Images, mentions, resolvedResourceLimits, schema, atoms, codeHighlighting]);
68
+ const configJson = (0, react_1.useMemo)(() => (0, ViewerConfiguration_1.serializePreparedProseViewerConfiguration)(resolveViewerConfiguration(schema, allowBase64Images, resolvedResourceLimits, mentions, atoms, codeHighlighting)), [allowBase64Images,
69
+ mentions,
70
+ resolvedResourceLimits,
71
+ schema,
72
+ atoms,
73
+ codeHighlighting]);
69
74
  const themeJson = (0, react_1.useMemo)(() => (0, EditorTheme_1.serializeEditorTheme)(theme, mentions?.theme), [mentions?.theme, theme]);
70
75
  const imagePolicyJson = (0, react_1.useMemo)(() => (0, ImageLoadingPolicy_1.serializeEditorImageLoadingPolicy)(imageLoadingPolicy), [imageLoadingPolicy]);
71
76
  const sourceKind = contentJSON === undefined ? 'html' : 'json';
@@ -75,7 +80,9 @@ function RichTextViewer(props) {
75
80
  }
76
81
  return typeof contentJSON === 'string' ? contentJSON : stringifyCachedJson(contentJSON);
77
82
  }, [contentHTML, contentJSON]);
78
- const atomIdentity = (0, react_1.useMemo)(() => ({}), [
83
+ const atomIdentity = (0, react_1.useMemo)(() => ({
84
+ sourceKind, source, configJson, themeJson, imagePolicyJson, renderImages, collapseTrailingEmptyParagraphs, fontEnvironmentRevision,
85
+ }), [
79
86
  sourceKind,
80
87
  source,
81
88
  configJson,
@@ -122,8 +129,9 @@ function RichTextViewer(props) {
122
129
  onError?.(event.nativeEvent);
123
130
  }, [onError]);
124
131
  const nativeViewer = ((0, jsx_runtime_1.jsx)(PreparedProseViewerNativeComponent_1.default, { ...(viewerAtoms.enabled ? { style: { alignSelf: 'stretch' } } : viewProps), sourceKind: sourceKind, source: source, configJson: configJson, themeJson: viewerAtoms.themeJson, onAtomLayout: viewerAtoms.enabled ? viewerAtoms.onAtomLayout : undefined, imagePolicyJson: imagePolicyJson, imagesEnabled: renderImages, collapsesWhenEmpty: collapseTrailingEmptyParagraphs, enableLinkTaps: enableLinkTaps && onPressLink != null, mentionInteractionsEnabled: mentions?.onPress != null, fontEnvironmentRevision: fontEnvironmentRevision, onPressLink: onPressLink ? handlePressLink : undefined, onPressMention: mentions?.onPress ? handlePressMention : undefined, onError: onError ? handleError : undefined }));
125
- if (!viewerAtoms.enabled)
132
+ if (!viewerAtoms.enabled) {
126
133
  return nativeViewer;
134
+ }
127
135
  return ((0, jsx_runtime_1.jsx)(react_native_1.View, { ...viewProps, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { alignSelf: 'stretch' }, onLayout: viewerAtoms.onContainerLayout, children: [nativeViewer, viewerAtoms.children] }) }));
128
136
  }
129
137
  /** @deprecated Use RichTextViewer instead. */
@@ -6,7 +6,7 @@
6
6
  * Every field is optional; an omitted one uses
7
7
  * {@link DEFAULT_EDITOR_RESOURCE_LIMITS}. Each value must be a positive
8
8
  * integer no greater than the matching {@link HARD_EDITOR_RESOURCE_LIMITS}
9
- * ceiling anything else throws `NativeEditorBoundaryError`
9
+ * ceiling : anything else throws `NativeEditorBoundaryError`
10
10
  * (`INVALID_RESOURCE_LIMIT`). Exceeding a limit at runtime raises
11
11
  * `INPUT_LIMIT_EXCEEDED`, `DOCUMENT_LIMIT_EXCEEDED`, or `SCHEMA_INVALID`.
12
12
  */
@@ -23,7 +23,7 @@ export interface EditorResourceLimits {
23
23
  maxSchemaExpressionBytes?: number;
24
24
  /** Byte ceiling for one inbound collaboration message. */
25
25
  maxCollaborationMessageBytes?: number;
26
- /** Byte ceiling for an encoded Yjs state imported room snapshots and exported ones. */
26
+ /** Byte ceiling for an encoded Yjs state : imported room snapshots and exported ones. */
27
27
  maxEncodedStateBytes?: number;
28
28
  }
29
29
  /**
@@ -53,8 +53,9 @@ function resolveLimit(name, value) {
53
53
  return resolved;
54
54
  }
55
55
  function validateOverrides(limits, ceilings) {
56
- if (limits === undefined)
56
+ if (limits === undefined) {
57
57
  return;
58
+ }
58
59
  for (const name of Object.keys(ceilings)) {
59
60
  const value = limits[name];
60
61
  if (value !== undefined) {
@@ -76,5 +77,9 @@ function validateEditorCreateLimits(limits) {
76
77
  * not a positive integer within its ceiling.
77
78
  */
78
79
  function resolveEditorResourceLimits(limits = {}) {
79
- return Object.fromEntries(Object.keys(exports.DEFAULT_EDITOR_RESOURCE_LIMITS).map((name) => [name, resolveLimit(name, limits[name])]));
80
+ const resolved = { ...exports.DEFAULT_EDITOR_RESOURCE_LIMITS };
81
+ for (const name of Object.keys(resolved)) {
82
+ resolved[name] = resolveLimit(name, limits[name]);
83
+ }
84
+ return resolved;
80
85
  }
@@ -8,7 +8,7 @@ const useRichTextEditorCommands_1 = require("./useRichTextEditorCommands");
8
8
  const useRichTextEditorEvents_1 = require("./useRichTextEditorEvents");
9
9
  const useRichTextEditorMentions_1 = require("./useRichTextEditorMentions");
10
10
  const useRichTextEditorPresentation_1 = require("./useRichTextEditorPresentation");
11
- exports.RichTextEditor = (0, react_1.forwardRef)(function RichTextEditor(props, ref) {
11
+ exports.RichTextEditor = (0, react_1.forwardRef)((props, ref) => {
12
12
  const state = (0, useRichTextEditorState_1.useRichTextEditorState)(props, ref);
13
13
  const updates = (0, useRichTextEditorUpdates_1.useRichTextEditorUpdates)(state);
14
14
  const commands = (0, useRichTextEditorCommands_1.useRichTextEditorCommands)({ ...state, ...updates });
@@ -1,4 +1,4 @@
1
- import { ExternalTextCompositionManager, type NativeExternalTextCompositionHandle } from './ExternalTextComposition';
1
+ import { type ExternalTextCompositionManager, type NativeExternalTextCompositionHandle } from './ExternalTextComposition';
2
2
  import { type ReactNode } from 'react';
3
3
  import { type NativeSyntheticEvent, type StyleProp, type ViewStyle } from 'react-native';
4
4
  import { type DocumentJSON, type NativeEditorDocumentHandle } from './NativeEditorBridge';
@@ -1,6 +1,4 @@
1
- import React from 'react';
2
- import { type NativeEditorViewProps, type NativeEditorViewHandle } from './RichTextEditorNativeTypes';
3
- export declare const NativeEditorView: React.ComponentType<NativeEditorViewProps & React.RefAttributes<NativeEditorViewHandle>>;
1
+ export declare const NativeEditorView: import("react").ComponentType<any>;
4
2
  export declare const styles: {
5
3
  container: {
6
4
  position: "relative";
@@ -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.');