@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.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/android/build.gradle +3 -0
- package/app.plugin.js +42 -39
- package/dist/AtomHost.js +18 -11
- package/dist/EditorAddon.js +4 -2
- package/dist/EditorAddonNormalization.js +17 -9
- package/dist/EditorMentionThemeNormalization.js +6 -3
- package/dist/EditorMentionThemeValidation.js +28 -11
- package/dist/EditorStyleSheetNormalization.js +84 -37
- package/dist/EditorTheme.d.ts +4 -0
- package/dist/EditorTheme.js +5 -3
- package/dist/EditorToolbarComponent.d.ts +1 -1
- package/dist/EditorToolbarComponent.js +1 -1
- package/dist/EditorToolbarRegistry.js +5 -5
- package/dist/EditorToolbarTypes.d.ts +12 -12
- package/dist/EditorToolbarVisuals.js +1 -1
- package/dist/ExternalTextComposition.js +89 -43
- package/dist/ImageLoadingPolicy.d.ts +1 -1
- package/dist/NativeEditorBoundaryError.d.ts +7 -7
- package/dist/NativeEditorBoundaryError.js +9 -5
- package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
- package/dist/NativeEditorCollaborationTransport.js +28 -15
- package/dist/NativeEditorCreateConfig.js +11 -6
- package/dist/NativeEditorCreateJson.js +51 -25
- package/dist/NativeEditorCreateValidation.js +11 -6
- package/dist/NativeEditorDocumentBridge.d.ts +1 -1
- package/dist/NativeEditorDocumentBridge.js +32 -18
- package/dist/NativeEditorDocumentHandle.d.ts +4 -4
- package/dist/NativeEditorDocumentHandle.js +1 -1
- package/dist/NativeEditorLocalAwareness.js +25 -13
- package/dist/NativeEditorNativeModule.d.ts +8 -1
- package/dist/NativeEditorNativeModule.js +7 -5
- package/dist/NativeEditorRenderNormalization.js +66 -25
- package/dist/NativeEditorResultNormalization.js +53 -29
- package/dist/NativeEditorTypes.d.ts +10 -10
- package/dist/NativeEditorV2Decimal.js +6 -3
- package/dist/NativeProseViewer.js +11 -3
- package/dist/ResourceLimits.d.ts +2 -2
- package/dist/ResourceLimits.js +7 -2
- package/dist/RichTextEditor.js +1 -1
- package/dist/RichTextEditorNativeTypes.d.ts +1 -1
- package/dist/RichTextEditorNativeView.d.ts +1 -3
- package/dist/RichTextEditorSerialization.js +24 -14
- package/dist/RichTextEditorTypes.d.ts +1 -1
- package/dist/YjsCollaboration.d.ts +7 -7
- package/dist/YjsCollaboration.js +42 -26
- package/dist/addons.d.ts +4 -4
- package/dist/addons.js +3 -3
- package/dist/atomInstances.js +6 -3
- package/dist/atomUpdates.js +7 -4
- package/dist/atoms.js +20 -12
- package/dist/attributeValidation.js +55 -24
- package/dist/contentExpression.js +80 -42
- package/dist/listMarkers.d.ts +1 -1
- package/dist/listMarkers.js +1 -1
- package/dist/schemaDefinition.d.ts +1 -1
- package/dist/schemaDefinition.js +23 -14
- package/dist/schemaDocument.js +1 -1
- package/dist/schemaDocumentConstruction.js +25 -14
- package/dist/schemaNormalization.js +51 -29
- package/dist/schemaPresets.d.ts +1 -1
- package/dist/schemaPresets.js +9 -4
- package/dist/schemaResolution.js +46 -25
- package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
- package/dist/useEditorToolbarInteractions.d.ts +2 -2
- package/dist/useEditorToolbarInteractions.js +45 -23
- package/dist/useEditorToolbarItems.d.ts +1 -1
- package/dist/useEditorToolbarItems.js +4 -3
- package/dist/useEditorToolbarPresentation.d.ts +3 -3
- package/dist/useEditorToolbarPresentation.js +4 -4
- package/dist/useEditorToolbarState.d.ts +1 -1
- package/dist/useEditorToolbarState.js +1 -1
- package/dist/useFocusPreservingFrames.js +11 -8
- package/dist/useNativeEditor.d.ts +1 -1
- package/dist/useNativeEditor.js +21 -11
- package/dist/useRichTextEditorCommands.d.ts +2 -2
- package/dist/useRichTextEditorCommands.js +59 -29
- package/dist/useRichTextEditorEvents.d.ts +3 -3
- package/dist/useRichTextEditorEvents.js +75 -32
- package/dist/useRichTextEditorMentions.d.ts +4 -4
- package/dist/useRichTextEditorMentions.js +48 -29
- package/dist/useRichTextEditorPresentation.d.ts +4 -4
- package/dist/useRichTextEditorPresentation.js +25 -23
- package/dist/useRichTextEditorState.d.ts +3 -3
- package/dist/useRichTextEditorState.js +20 -15
- package/dist/useRichTextEditorUpdates.d.ts +1 -1
- package/dist/useRichTextEditorUpdates.js +99 -41
- package/dist/useViewerAtoms.js +63 -36
- package/ios/EditorCore.xcframework/Info.plist +5 -5
- package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
- package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
- package/package.json +11 -3
- package/react-native.config.js +1 -1
- package/rust/android/arm64-v8a/libeditor_core.so +0 -0
- package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
- package/rust/android/x86/libeditor_core.so +0 -0
- package/rust/android/x86_64/libeditor_core.so +0 -0
- package/src/AtomHost.tsx +58 -28
- package/src/EditorAddon.ts +18 -8
- package/src/EditorAddonNormalization.ts +40 -11
- package/src/EditorMentionThemeNormalization.ts +15 -4
- package/src/EditorMentionThemeValidation.ts +51 -14
- package/src/EditorStyleSheet.ts +1 -0
- package/src/EditorStyleSheetNormalization.ts +195 -64
- package/src/EditorTheme.ts +13 -5
- package/src/EditorToolbarComponent.tsx +2 -1
- package/src/EditorToolbarRegistry.tsx +23 -13
- package/src/EditorToolbarTypes.tsx +12 -12
- package/src/EditorToolbarVisuals.tsx +6 -3
- package/src/EditorUpdateRevision.ts +1 -0
- package/src/ExternalTextComposition.ts +259 -49
- package/src/ImageLoadingPolicy.ts +3 -1
- package/src/NativeEditorBoundaryError.ts +38 -11
- package/src/NativeEditorCollaborationTransport.ts +108 -27
- package/src/NativeEditorCreateConfig.ts +92 -19
- package/src/NativeEditorCreateJson.ts +163 -26
- package/src/NativeEditorCreateValidation.ts +33 -12
- package/src/NativeEditorDocumentBridge.ts +111 -19
- package/src/NativeEditorDocumentHandle.ts +9 -4
- package/src/NativeEditorLocalAwareness.ts +70 -15
- package/src/NativeEditorNativeModule.ts +13 -9
- package/src/NativeEditorRenderNormalization.ts +128 -29
- package/src/NativeEditorResultNormalization.ts +143 -32
- package/src/NativeEditorTypes.ts +12 -11
- package/src/NativeEditorV2Decimal.ts +12 -3
- package/src/NativeProseViewer.tsx +46 -16
- package/src/ResourceLimits.ts +15 -8
- package/src/RichTextEditor.tsx +3 -1
- package/src/RichTextEditorNativeTypes.tsx +1 -1
- package/src/RichTextEditorNativeView.tsx +2 -8
- package/src/RichTextEditorSerialization.tsx +70 -24
- package/src/RichTextEditorTypes.tsx +1 -1
- package/src/YjsCollaboration.ts +143 -47
- package/src/addons.ts +12 -8
- package/src/atomInstances.ts +25 -5
- package/src/atomUpdates.ts +23 -6
- package/src/atoms.ts +85 -18
- package/src/attributeValidation.ts +97 -33
- package/src/contentExpression.ts +218 -63
- package/src/listMarkers.ts +1 -1
- package/src/schemaDefinition.ts +82 -20
- package/src/schemaDocument.ts +15 -1
- package/src/schemaDocumentConstruction.ts +80 -16
- package/src/schemaNormalization.ts +155 -41
- package/src/schemaPresets.ts +37 -31
- package/src/schemaResolution.ts +126 -27
- package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
- package/src/useEditorToolbarInteractions.tsx +85 -36
- package/src/useEditorToolbarItems.tsx +50 -22
- package/src/useEditorToolbarPresentation.tsx +81 -58
- package/src/useEditorToolbarState.tsx +8 -6
- package/src/useFocusPreservingFrames.ts +43 -15
- package/src/useNativeEditor.ts +111 -51
- package/src/useRichTextEditorCommands.tsx +127 -54
- package/src/useRichTextEditorEvents.tsx +144 -42
- package/src/useRichTextEditorMentions.tsx +118 -37
- package/src/useRichTextEditorPresentation.tsx +128 -114
- package/src/useRichTextEditorState.tsx +76 -40
- package/src/useRichTextEditorUpdates.tsx +207 -56
- package/src/useViewerAtoms.tsx +162 -66
package/src/ResourceLimits.ts
CHANGED
|
@@ -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
|
|
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
|
|
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)
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
}
|
package/src/RichTextEditor.tsx
CHANGED
|
@@ -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
|
-
|
|
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,14 +1,8 @@
|
|
|
1
1
|
import { requireNativeViewManager } from 'expo-modules-core';
|
|
2
|
-
|
|
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')
|
|
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)
|
|
42
|
-
|
|
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(
|
|
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(
|
|
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))
|
|
116
|
-
|
|
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))
|
|
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')
|
|
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))
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
282
|
+
return items.map(item => {
|
|
255
283
|
if (item.type === 'group') {
|
|
256
284
|
return {
|
|
257
285
|
...item,
|
|
258
|
-
items: item.items.map(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|