@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.
- package/README.md +8 -116
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/android/build.gradle +3 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +25 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +1 -0
- package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +101 -33
- package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +15 -3
- package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +14 -0
- package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1 -1
- 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 +85 -38
- package/dist/EditorStyleSheetTypes.d.ts +1 -1
- 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/ios-arm64/libeditor_core.a +0 -0
- package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
- package/ios/EditorInteractionOverlays.swift +114 -122
- package/ios/EditorLayoutManager.swift +13 -3
- package/ios/EditorStyleSheet.swift +12 -1
- package/ios/EditorTextView+Images.swift +32 -10
- package/ios/EditorTextView.swift +1 -1
- package/ios/EditorV2Adapter+RenderValidation.swift +2 -2
- package/ios/NativeToolbar+ButtonStyle.swift +17 -5
- package/ios/NativeToolbar+Diagnostics.swift +15 -0
- package/ios/RenderBridge+Atoms.swift +0 -1
- package/ios/RenderBridge+Attachments.swift +0 -29
- package/ios/RichTextEditorView.swift +4 -12
- package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +3 -2
- 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/EditorStyleSheetTypes.ts +1 -1
- 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/schemaResolution.ts
CHANGED
|
@@ -39,13 +39,18 @@ export function admitSchemaCollections(
|
|
|
39
39
|
|
|
40
40
|
for (let nodeIndex = 0; nodeIndex < schema.nodes.length; nodeIndex += 1) {
|
|
41
41
|
const node = schema.nodes[nodeIndex];
|
|
42
|
-
|
|
42
|
+
|
|
43
|
+
if (node == null || typeof node !== 'object') {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
43
47
|
const groups: string[] = [];
|
|
48
|
+
|
|
44
49
|
if (typeof node.group === 'string') {
|
|
45
50
|
if (
|
|
46
51
|
!forEachGroupToken(
|
|
47
52
|
node.group,
|
|
48
|
-
|
|
53
|
+
group => groups.push(group),
|
|
49
54
|
() => consumeSchemaWork(budget),
|
|
50
55
|
() => consumeSchemaWork(budget)
|
|
51
56
|
)
|
|
@@ -53,16 +58,26 @@ export function admitSchemaCollections(
|
|
|
53
58
|
throw schemaBoundaryError(budget.limit, budget.limit + 1);
|
|
54
59
|
}
|
|
55
60
|
}
|
|
61
|
+
|
|
56
62
|
const attrs = collectOwnAttrs(node.attrs, budget);
|
|
57
|
-
|
|
63
|
+
|
|
64
|
+
if (attrs == null) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
58
68
|
const projectionAttrs = collectOwnAttrs(node.json?.attrs, budget);
|
|
59
|
-
|
|
69
|
+
|
|
70
|
+
if (projectionAttrs == null) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
60
74
|
if (
|
|
61
75
|
node.json != null &&
|
|
62
76
|
((typeof node.json.type === 'string' &&
|
|
63
77
|
!consumeSchemaStringWork(budget, node.json.type)) ||
|
|
64
|
-
projectionAttrs.some(([name, rawValue]) => {
|
|
78
|
+
projectionAttrs.some(([ name, rawValue ]) => {
|
|
65
79
|
const value: unknown = rawValue;
|
|
80
|
+
|
|
66
81
|
return (
|
|
67
82
|
!consumeSchemaStringWork(budget, name) ||
|
|
68
83
|
(typeof value === 'string'
|
|
@@ -73,21 +88,32 @@ export function admitSchemaCollections(
|
|
|
73
88
|
) {
|
|
74
89
|
throw schemaBoundaryError(budget.limit, budget.limit + 1);
|
|
75
90
|
}
|
|
91
|
+
|
|
76
92
|
if (budget.exhausted) {
|
|
77
93
|
throw schemaBoundaryError(budget.limit, budget.limit + 1);
|
|
78
94
|
}
|
|
95
|
+
|
|
79
96
|
groupsByNode.set(node, groups);
|
|
80
97
|
attrsByNode.set(node, attrs);
|
|
81
98
|
}
|
|
82
99
|
|
|
83
100
|
for (let markIndex = 0; markIndex < schema.marks.length; markIndex += 1) {
|
|
84
101
|
const mark = schema.marks[markIndex];
|
|
102
|
+
|
|
85
103
|
if (!consumeSchemaWork(budget)) {
|
|
86
104
|
throw schemaBoundaryError(budget.limit, budget.limit + 1);
|
|
87
105
|
}
|
|
88
|
-
|
|
106
|
+
|
|
107
|
+
if (mark == null || typeof mark !== 'object') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
89
111
|
const attrs = collectOwnAttrs(mark.attrs, budget);
|
|
90
|
-
|
|
112
|
+
|
|
113
|
+
if (attrs == null) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
91
117
|
if (budget.exhausted) {
|
|
92
118
|
throw schemaBoundaryError(budget.limit, budget.limit + 1);
|
|
93
119
|
}
|
|
@@ -101,45 +127,70 @@ export function resolveDocumentSchema(
|
|
|
101
127
|
schema?: SchemaDefinition,
|
|
102
128
|
limits?: DocumentDescriptorLimits
|
|
103
129
|
): SchemaDefinition {
|
|
104
|
-
if (schema == null)
|
|
105
|
-
|
|
130
|
+
if (schema == null) {
|
|
131
|
+
return defaultSchema;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!Array.isArray(schema.nodes)) {
|
|
135
|
+
return defaultSchema;
|
|
136
|
+
}
|
|
137
|
+
|
|
106
138
|
if (!Array.isArray(schema.marks)) {
|
|
107
139
|
schema = { ...schema, marks: [] };
|
|
108
140
|
}
|
|
109
141
|
|
|
110
142
|
const resolvedLimits = resolveDescriptorLimits(limits);
|
|
143
|
+
|
|
111
144
|
if (schema.nodes.length > resolvedLimits.maxSchemaNodes) {
|
|
112
145
|
throw schemaBoundaryError(resolvedLimits.maxSchemaNodes, schema.nodes.length);
|
|
113
146
|
}
|
|
147
|
+
|
|
114
148
|
let expressionBytes = 0;
|
|
149
|
+
|
|
115
150
|
for (let nodeIndex = 0; nodeIndex < schema.nodes.length; nodeIndex += 1) {
|
|
116
151
|
const node = schema.nodes[nodeIndex];
|
|
152
|
+
|
|
117
153
|
if (node != null && typeof node.content === 'string') {
|
|
118
154
|
expressionBytes += utf8ByteLengthUpTo(
|
|
119
155
|
node.content,
|
|
120
156
|
resolvedLimits.maxSchemaExpressionBytes - expressionBytes
|
|
121
157
|
);
|
|
158
|
+
|
|
122
159
|
if (expressionBytes > resolvedLimits.maxSchemaExpressionBytes) {
|
|
123
160
|
throw schemaBoundaryError(resolvedLimits.maxSchemaExpressionBytes, expressionBytes);
|
|
124
161
|
}
|
|
125
162
|
}
|
|
126
163
|
}
|
|
164
|
+
|
|
127
165
|
const schemaBudget = createSchemaWorkBudget(resolvedLimits);
|
|
128
|
-
|
|
166
|
+
|
|
167
|
+
if (admitSchemaCollections(schema, schemaBudget) == null) {
|
|
168
|
+
return defaultSchema;
|
|
169
|
+
}
|
|
170
|
+
|
|
129
171
|
const normalizedSchema = normalizeSchemaDefinition(schema, schemaBudget);
|
|
130
|
-
|
|
172
|
+
|
|
173
|
+
if (normalizedSchema == null) {
|
|
174
|
+
return defaultSchema;
|
|
175
|
+
}
|
|
176
|
+
|
|
131
177
|
schema = normalizedSchema;
|
|
178
|
+
|
|
132
179
|
const admittedCollections = admitSchemaCollections(schema, {
|
|
133
180
|
limit: Number.MAX_SAFE_INTEGER,
|
|
134
181
|
work: 0,
|
|
135
182
|
exhausted: false,
|
|
136
183
|
});
|
|
137
|
-
|
|
184
|
+
|
|
185
|
+
if (admittedCollections == null) {
|
|
186
|
+
return defaultSchema;
|
|
187
|
+
}
|
|
138
188
|
|
|
139
189
|
const nodeNames = new Set<string>();
|
|
140
190
|
const markNames = new Set<string>();
|
|
141
191
|
let docRoles = 0;
|
|
142
192
|
let textRoles = 0;
|
|
193
|
+
|
|
143
194
|
for (const node of schema.nodes) {
|
|
144
195
|
if (
|
|
145
196
|
node == null ||
|
|
@@ -151,10 +202,18 @@ export function resolveDocumentSchema(
|
|
|
151
202
|
) {
|
|
152
203
|
return defaultSchema;
|
|
153
204
|
}
|
|
205
|
+
|
|
154
206
|
nodeNames.add(node.name);
|
|
155
|
-
|
|
156
|
-
if (node.role === '
|
|
207
|
+
|
|
208
|
+
if (node.role === 'doc') {
|
|
209
|
+
docRoles += 1;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (node.role === 'text') {
|
|
213
|
+
textRoles += 1;
|
|
214
|
+
}
|
|
157
215
|
}
|
|
216
|
+
|
|
158
217
|
for (const mark of schema.marks) {
|
|
159
218
|
if (
|
|
160
219
|
mark == null ||
|
|
@@ -164,29 +223,42 @@ export function resolveDocumentSchema(
|
|
|
164
223
|
) {
|
|
165
224
|
return defaultSchema;
|
|
166
225
|
}
|
|
226
|
+
|
|
167
227
|
markNames.add(mark.name);
|
|
168
228
|
}
|
|
169
|
-
|
|
229
|
+
|
|
230
|
+
if (docRoles !== 1 || textRoles !== 1) {
|
|
231
|
+
return defaultSchema;
|
|
232
|
+
}
|
|
170
233
|
|
|
171
234
|
const groups = new Set<string>();
|
|
172
235
|
const nodesBySymbol = new Map<string, NodeSpec[]>();
|
|
236
|
+
|
|
173
237
|
const addCandidate = (symbol: string, node: NodeSpec): void => {
|
|
174
238
|
const candidates = nodesBySymbol.get(symbol);
|
|
175
|
-
|
|
176
|
-
|
|
239
|
+
|
|
240
|
+
if (candidates) {
|
|
241
|
+
candidates.push(node);
|
|
242
|
+
} else {
|
|
243
|
+
nodesBySymbol.set(symbol, [ node ]);
|
|
244
|
+
}
|
|
177
245
|
};
|
|
246
|
+
|
|
178
247
|
for (const node of schema.nodes) {
|
|
179
248
|
addCandidate(node.name, node);
|
|
249
|
+
|
|
180
250
|
for (const group of admittedCollections.groupsByNode.get(node) ?? []) {
|
|
181
251
|
groups.add(group);
|
|
182
252
|
addCandidate(group, node);
|
|
183
253
|
}
|
|
184
254
|
}
|
|
255
|
+
|
|
185
256
|
for (const node of schema.nodes) {
|
|
186
257
|
const symbols = contentExpressionSymbols(node.content);
|
|
258
|
+
|
|
187
259
|
if (
|
|
188
260
|
symbols == null ||
|
|
189
|
-
symbols.some(
|
|
261
|
+
symbols.some(symbol => !nodeNames.has(symbol) && !groups.has(symbol))
|
|
190
262
|
) {
|
|
191
263
|
return defaultSchema;
|
|
192
264
|
}
|
|
@@ -194,49 +266,76 @@ export function resolveDocumentSchema(
|
|
|
194
266
|
|
|
195
267
|
const generatable = new Set<string>();
|
|
196
268
|
const consumeWork = (): boolean => consumeSchemaWork(schemaBudget);
|
|
269
|
+
|
|
197
270
|
const contentIsConstructible = (node: NodeSpec): boolean => {
|
|
198
|
-
if (!consumeWork())
|
|
271
|
+
if (!consumeWork()) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
199
275
|
return (
|
|
200
276
|
minimalContentMatch(
|
|
201
277
|
node.content,
|
|
202
|
-
|
|
278
|
+
symbol => {
|
|
203
279
|
const candidates = nodesBySymbol.get(symbol) ?? [];
|
|
280
|
+
|
|
204
281
|
for (const candidate of candidates) {
|
|
205
|
-
if (!consumeWork())
|
|
206
|
-
|
|
282
|
+
if (!consumeWork()) {
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (generatable.has(candidate.name)) {
|
|
287
|
+
return { type: candidate.name };
|
|
288
|
+
}
|
|
207
289
|
}
|
|
290
|
+
|
|
208
291
|
return undefined;
|
|
209
292
|
},
|
|
210
293
|
consumeWork
|
|
211
294
|
) != null
|
|
212
295
|
);
|
|
213
296
|
};
|
|
297
|
+
|
|
214
298
|
while (true) {
|
|
215
299
|
const before = generatable.size;
|
|
300
|
+
|
|
216
301
|
for (const node of schema.nodes) {
|
|
217
302
|
const hasRequiredAttrs = (admittedCollections.attrsByNode.get(node) ?? []).some(
|
|
218
|
-
([, attr]) => attr.default === undefined
|
|
303
|
+
([ , attr ]) => attr.default === undefined
|
|
219
304
|
);
|
|
305
|
+
|
|
220
306
|
if (node.role !== 'text' && !hasRequiredAttrs && contentIsConstructible(node)) {
|
|
221
307
|
generatable.add(node.name);
|
|
222
308
|
}
|
|
223
309
|
}
|
|
224
|
-
|
|
310
|
+
|
|
311
|
+
if (generatable.size === before) {
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
225
314
|
}
|
|
315
|
+
|
|
226
316
|
if (schemaBudget.exhausted) {
|
|
227
317
|
throw schemaBoundaryError(schemaBudget.limit, schemaBudget.limit + 1);
|
|
228
318
|
}
|
|
229
|
-
|
|
319
|
+
|
|
320
|
+
const hasUnconstructibleNode = schema.nodes.some(node => !contentIsConstructible(node));
|
|
321
|
+
|
|
230
322
|
if (schemaBudget.exhausted) {
|
|
231
323
|
throw schemaBoundaryError(schemaBudget.limit, schemaBudget.limit + 1);
|
|
232
324
|
}
|
|
233
|
-
|
|
325
|
+
|
|
326
|
+
if (hasUnconstructibleNode) {
|
|
327
|
+
return defaultSchema;
|
|
328
|
+
}
|
|
234
329
|
|
|
235
330
|
try {
|
|
236
331
|
constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollections);
|
|
332
|
+
|
|
237
333
|
return schema;
|
|
238
334
|
} catch (error) {
|
|
239
|
-
if (error instanceof NativeEditorBoundaryError)
|
|
335
|
+
if (error instanceof NativeEditorBoundaryError) {
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
|
|
240
339
|
return defaultSchema;
|
|
241
340
|
}
|
|
242
341
|
}
|
|
@@ -18,8 +18,10 @@ export interface NativeProps extends ViewProps {
|
|
|
18
18
|
mentionInteractionsEnabled?: WithDefault<boolean, false>;
|
|
19
19
|
fontEnvironmentRevision: Int32;
|
|
20
20
|
onPressLink?: DirectEventHandler<{ href: string; text: string }>;
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* React Native numbers are IEEE-754 doubles, which exactly represent every
|
|
23
|
+
* UInt32 document position. Int32 would corrupt positions above 2^31 - 1.
|
|
24
|
+
*/
|
|
23
25
|
onPressMention?: DirectEventHandler<{ docPos: Double; label: string; attrsJson: string }>;
|
|
24
26
|
onAtomLayout?: DirectEventHandler<{
|
|
25
27
|
generation: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect } from 'react';
|
|
2
2
|
import { Keyboard } from 'react-native';
|
|
3
|
-
import { useEditorToolbarState } from './useEditorToolbarState';
|
|
4
|
-
import { useEditorToolbarItems } from './useEditorToolbarItems';
|
|
3
|
+
import { type useEditorToolbarState } from './useEditorToolbarState';
|
|
4
|
+
import { type useEditorToolbarItems } from './useEditorToolbarItems';
|
|
5
5
|
import {
|
|
6
6
|
unregisterEditorToolbarFrame,
|
|
7
7
|
registerEditorToolbarFrame,
|
|
@@ -80,10 +80,12 @@ export function useEditorToolbarInteractions(
|
|
|
80
80
|
const publishToolbarFrame = useCallback(() => {
|
|
81
81
|
const registrationId = registrationIdRef.current;
|
|
82
82
|
const toolbar = rootRef.current;
|
|
83
|
+
|
|
83
84
|
if (!publishesFocusFrames || registrationId == null || !toolbar) {
|
|
84
85
|
if (registrationId != null) {
|
|
85
86
|
unregisterEditorToolbarFrame(registrationId);
|
|
86
87
|
}
|
|
88
|
+
|
|
87
89
|
return;
|
|
88
90
|
}
|
|
89
91
|
|
|
@@ -92,6 +94,7 @@ export function useEditorToolbarInteractions(
|
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
const measuredFrameOwnerId = frameOwnerId;
|
|
97
|
+
|
|
95
98
|
toolbar.measureInWindow((x, y, width, height) => {
|
|
96
99
|
if (
|
|
97
100
|
!framePublisherMountedRef.current ||
|
|
@@ -100,21 +103,30 @@ export function useEditorToolbarInteractions(
|
|
|
100
103
|
) {
|
|
101
104
|
return;
|
|
102
105
|
}
|
|
106
|
+
|
|
103
107
|
registerEditorToolbarFrame(
|
|
104
108
|
registrationId,
|
|
105
109
|
{ x, y, width, height },
|
|
106
110
|
measuredFrameOwnerId
|
|
107
111
|
);
|
|
108
112
|
});
|
|
109
|
-
}, [frameOwnerId,
|
|
113
|
+
}, [ frameOwnerId,
|
|
114
|
+
frameOwnerIdRef,
|
|
115
|
+
framePublisherMountedRef,
|
|
116
|
+
publishesFocusFrames,
|
|
117
|
+
publishesFocusFramesRef,
|
|
118
|
+
registrationIdRef,
|
|
119
|
+
rootRef ]);
|
|
110
120
|
|
|
111
121
|
const publishMenuFrame = useCallback(() => {
|
|
112
122
|
const registrationId = menuRegistrationIdRef.current;
|
|
113
123
|
const menuCard = menuCardRef.current;
|
|
124
|
+
|
|
114
125
|
if (!publishesFocusFrames || menuState == null || registrationId == null || !menuCard) {
|
|
115
126
|
if (registrationId != null) {
|
|
116
127
|
unregisterEditorToolbarFrame(registrationId);
|
|
117
128
|
}
|
|
129
|
+
|
|
118
130
|
return;
|
|
119
131
|
}
|
|
120
132
|
|
|
@@ -124,6 +136,7 @@ export function useEditorToolbarInteractions(
|
|
|
124
136
|
|
|
125
137
|
const measuredFrameOwnerId = frameOwnerId;
|
|
126
138
|
const measuredMenuState = menuState;
|
|
139
|
+
|
|
127
140
|
menuCard.measureInWindow((x, y, width, height) => {
|
|
128
141
|
if (
|
|
129
142
|
!framePublisherMountedRef.current ||
|
|
@@ -133,25 +146,34 @@ export function useEditorToolbarInteractions(
|
|
|
133
146
|
) {
|
|
134
147
|
return;
|
|
135
148
|
}
|
|
149
|
+
|
|
136
150
|
registerEditorToolbarFrame(
|
|
137
151
|
registrationId,
|
|
138
152
|
{ x, y, width, height },
|
|
139
153
|
measuredFrameOwnerId
|
|
140
154
|
);
|
|
141
155
|
});
|
|
142
|
-
}, [frameOwnerId,
|
|
156
|
+
}, [ frameOwnerId,
|
|
157
|
+
frameOwnerIdRef,
|
|
158
|
+
framePublisherMountedRef,
|
|
159
|
+
menuCardRef,
|
|
160
|
+
menuRegistrationIdRef,
|
|
161
|
+
menuState,
|
|
162
|
+
menuStateRef,
|
|
163
|
+
publishesFocusFrames,
|
|
164
|
+
publishesFocusFramesRef ]);
|
|
143
165
|
|
|
144
166
|
const publishToolbarFrames = useCallback(() => {
|
|
145
167
|
publishToolbarFrame();
|
|
146
168
|
publishMenuFrame();
|
|
147
|
-
}, [publishMenuFrame, publishToolbarFrame]);
|
|
169
|
+
}, [ publishMenuFrame, publishToolbarFrame ]);
|
|
148
170
|
|
|
149
171
|
const cancelScheduledFramePublishes = useCallback(() => {
|
|
150
|
-
framePublishAnimationFramesRef.current.forEach(
|
|
172
|
+
framePublishAnimationFramesRef.current.forEach(frame => cancelAnimationFrame(frame));
|
|
151
173
|
framePublishAnimationFramesRef.current = [];
|
|
152
|
-
framePublishTimeoutsRef.current.forEach(
|
|
174
|
+
framePublishTimeoutsRef.current.forEach(timeout => clearTimeout(timeout));
|
|
153
175
|
framePublishTimeoutsRef.current = [];
|
|
154
|
-
}, []);
|
|
176
|
+
}, [ framePublishAnimationFramesRef, framePublishTimeoutsRef ]);
|
|
155
177
|
|
|
156
178
|
const scheduleToolbarFramePublish = useCallback(() => {
|
|
157
179
|
if (!publishesFocusFrames) {
|
|
@@ -162,32 +184,39 @@ export function useEditorToolbarInteractions(
|
|
|
162
184
|
publishToolbarFrames();
|
|
163
185
|
|
|
164
186
|
framePublishAnimationFramesRef.current.push(requestAnimationFrame(publishToolbarFrames));
|
|
165
|
-
|
|
187
|
+
|
|
188
|
+
KEYBOARD_FRAME_REMEASURE_DELAYS_MS.forEach(delay => {
|
|
166
189
|
framePublishTimeoutsRef.current.push(setTimeout(publishToolbarFrames, delay));
|
|
167
190
|
});
|
|
168
|
-
}, [
|
|
191
|
+
}, [ publishesFocusFrames,
|
|
192
|
+
cancelScheduledFramePublishes,
|
|
193
|
+
publishToolbarFrames,
|
|
194
|
+
framePublishAnimationFramesRef,
|
|
195
|
+
framePublishTimeoutsRef ]);
|
|
169
196
|
|
|
170
197
|
const handleToolbarLayout = useCallback(() => {
|
|
171
198
|
requestAnimationFrame(publishToolbarFrame);
|
|
172
|
-
}, [publishToolbarFrame]);
|
|
199
|
+
}, [ publishToolbarFrame ]);
|
|
173
200
|
|
|
174
201
|
const handleMenuLayout = useCallback(() => {
|
|
175
202
|
requestAnimationFrame(publishMenuFrame);
|
|
176
|
-
}, [publishMenuFrame]);
|
|
203
|
+
}, [ publishMenuFrame ]);
|
|
177
204
|
|
|
178
205
|
useEffect(() => {
|
|
179
206
|
if (!publishesFocusFrames) {
|
|
180
207
|
const registrationId = registrationIdRef.current;
|
|
208
|
+
|
|
181
209
|
if (registrationId != null) {
|
|
182
210
|
unregisterEditorToolbarFrame(registrationId);
|
|
183
211
|
}
|
|
212
|
+
|
|
184
213
|
return;
|
|
185
214
|
}
|
|
186
215
|
|
|
187
216
|
const frame = requestAnimationFrame(publishToolbarFrame);
|
|
217
|
+
|
|
188
218
|
return () => cancelAnimationFrame(frame);
|
|
189
|
-
}, [
|
|
190
|
-
expandedGroupKey,
|
|
219
|
+
}, [ expandedGroupKey,
|
|
191
220
|
menuState?.groupKey,
|
|
192
221
|
publishesFocusFrames,
|
|
193
222
|
publishToolbarFrame,
|
|
@@ -196,42 +225,55 @@ export function useEditorToolbarInteractions(
|
|
|
196
225
|
endItems.length,
|
|
197
226
|
windowHeight,
|
|
198
227
|
windowWidth,
|
|
199
|
-
|
|
228
|
+
registrationIdRef ]);
|
|
200
229
|
|
|
201
230
|
useEffect(() => {
|
|
202
231
|
if (!publishesFocusFrames || menuState == null) {
|
|
203
232
|
const registrationId = menuRegistrationIdRef.current;
|
|
233
|
+
|
|
204
234
|
if (registrationId != null) {
|
|
205
235
|
unregisterEditorToolbarFrame(registrationId);
|
|
206
236
|
}
|
|
237
|
+
|
|
207
238
|
return;
|
|
208
239
|
}
|
|
209
240
|
|
|
210
241
|
const frame = requestAnimationFrame(publishMenuFrame);
|
|
242
|
+
|
|
211
243
|
return () => cancelAnimationFrame(frame);
|
|
212
|
-
}, [menuState,
|
|
244
|
+
}, [ menuState,
|
|
245
|
+
publishesFocusFrames,
|
|
246
|
+
publishMenuFrame,
|
|
247
|
+
windowHeight,
|
|
248
|
+
windowWidth,
|
|
249
|
+
menuRegistrationIdRef ]);
|
|
213
250
|
|
|
214
251
|
useEffect(() => {
|
|
215
252
|
const registrationId = registrationIdRef.current;
|
|
216
253
|
const menuRegistrationId = menuRegistrationIdRef.current;
|
|
254
|
+
|
|
217
255
|
return () => {
|
|
218
256
|
cancelScheduledFramePublishes();
|
|
257
|
+
|
|
219
258
|
if (toolbarInteractionActiveRef.current) {
|
|
220
259
|
toolbarInteractionActiveRef.current = false;
|
|
221
260
|
endEditorToolbarInteraction();
|
|
222
261
|
}
|
|
262
|
+
|
|
223
263
|
if (registrationId != null) {
|
|
224
264
|
unregisterEditorToolbarFrame(registrationId);
|
|
225
265
|
}
|
|
266
|
+
|
|
226
267
|
if (menuRegistrationId != null) {
|
|
227
268
|
unregisterEditorToolbarFrame(menuRegistrationId);
|
|
228
269
|
}
|
|
229
270
|
};
|
|
230
|
-
}, [cancelScheduledFramePublishes]);
|
|
271
|
+
}, [ cancelScheduledFramePublishes, menuRegistrationIdRef, registrationIdRef, toolbarInteractionActiveRef ]);
|
|
231
272
|
|
|
232
273
|
useEffect(() => {
|
|
233
274
|
if (!publishesFocusFrames) {
|
|
234
275
|
cancelScheduledFramePublishes();
|
|
276
|
+
|
|
235
277
|
return;
|
|
236
278
|
}
|
|
237
279
|
|
|
@@ -242,81 +284,88 @@ export function useEditorToolbarInteractions(
|
|
|
242
284
|
];
|
|
243
285
|
|
|
244
286
|
return () => {
|
|
245
|
-
subscriptions.forEach(
|
|
287
|
+
subscriptions.forEach(subscription => subscription.remove());
|
|
246
288
|
cancelScheduledFramePublishes();
|
|
247
289
|
};
|
|
248
|
-
}, [cancelScheduledFramePublishes, publishesFocusFrames, scheduleToolbarFramePublish]);
|
|
290
|
+
}, [ cancelScheduledFramePublishes, publishesFocusFrames, scheduleToolbarFramePublish ]);
|
|
249
291
|
|
|
250
292
|
useEffect(() => {
|
|
251
293
|
if (expandedGroupKey != null && !groupsByKey.has(expandedGroupKey)) {
|
|
252
294
|
setExpandedGroupKey(null);
|
|
253
295
|
}
|
|
254
|
-
}, [expandedGroupKey, groupsByKey]);
|
|
296
|
+
}, [ expandedGroupKey, groupsByKey, setExpandedGroupKey ]);
|
|
255
297
|
|
|
256
298
|
useEffect(() => {
|
|
257
299
|
if (menuState != null && !groupsByKey.has(menuState.groupKey)) {
|
|
258
300
|
setMenuState(null);
|
|
259
301
|
}
|
|
260
|
-
}, [groupsByKey, menuState]);
|
|
302
|
+
}, [ groupsByKey, menuState, setMenuState ]);
|
|
261
303
|
|
|
262
304
|
useEffect(() => {
|
|
263
305
|
if (shouldRenderMentionSuggestions) {
|
|
264
306
|
setExpandedGroupKey(null);
|
|
265
307
|
setMenuState(null);
|
|
266
308
|
}
|
|
267
|
-
}, [shouldRenderMentionSuggestions]);
|
|
309
|
+
}, [ setExpandedGroupKey, setMenuState, shouldRenderMentionSuggestions ]);
|
|
268
310
|
|
|
269
311
|
const handleButtonPress = useCallback((button: ToolbarButton) => {
|
|
270
312
|
button.action();
|
|
313
|
+
|
|
271
314
|
if (button.groupKey) {
|
|
272
|
-
setExpandedGroupKey(
|
|
315
|
+
setExpandedGroupKey(current => (current === button.groupKey ? null : current));
|
|
273
316
|
}
|
|
317
|
+
|
|
274
318
|
setMenuState(null);
|
|
275
|
-
}, []);
|
|
319
|
+
}, [ setExpandedGroupKey, setMenuState ]);
|
|
276
320
|
|
|
277
321
|
const handleToolbarPressIn = useCallback(() => {
|
|
278
322
|
if (preserveEditorFocus && !toolbarInteractionActiveRef.current) {
|
|
279
323
|
toolbarInteractionActiveRef.current = true;
|
|
280
324
|
beginEditorToolbarInteraction();
|
|
281
325
|
}
|
|
282
|
-
}, [preserveEditorFocus]);
|
|
326
|
+
}, [ preserveEditorFocus, toolbarInteractionActiveRef ]);
|
|
283
327
|
|
|
284
328
|
const handleToolbarPressOut = useCallback(() => {
|
|
285
329
|
if (preserveEditorFocus && toolbarInteractionActiveRef.current) {
|
|
286
330
|
toolbarInteractionActiveRef.current = false;
|
|
287
331
|
endEditorToolbarInteraction();
|
|
288
332
|
}
|
|
289
|
-
}, [preserveEditorFocus]);
|
|
333
|
+
}, [ preserveEditorFocus, toolbarInteractionActiveRef ]);
|
|
290
334
|
|
|
291
335
|
const handleGroupPress = useCallback((group: ToolbarGroupButton) => {
|
|
292
336
|
if (group.isDisabled) {
|
|
293
337
|
return;
|
|
294
338
|
}
|
|
339
|
+
|
|
295
340
|
if (group.presentation === 'expand') {
|
|
296
341
|
setMenuState(null);
|
|
297
|
-
setExpandedGroupKey(
|
|
342
|
+
setExpandedGroupKey(current => (current === group.key ? null : group.key));
|
|
343
|
+
|
|
298
344
|
return;
|
|
299
345
|
}
|
|
300
346
|
|
|
301
347
|
const anchor = groupButtonRefs.current.get(group.key);
|
|
348
|
+
|
|
302
349
|
if (!anchor) {
|
|
303
350
|
return;
|
|
304
351
|
}
|
|
352
|
+
|
|
305
353
|
anchor.measureInWindow((x, y, width, height) => {
|
|
306
354
|
setExpandedGroupKey(null);
|
|
307
|
-
|
|
355
|
+
|
|
356
|
+
setMenuState(current =>
|
|
308
357
|
current?.groupKey === group.key
|
|
309
358
|
? null
|
|
310
359
|
: {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
);
|
|
360
|
+
groupKey: group.key,
|
|
361
|
+
x,
|
|
362
|
+
y,
|
|
363
|
+
width,
|
|
364
|
+
height,
|
|
365
|
+
});
|
|
318
366
|
});
|
|
319
|
-
}, []);
|
|
367
|
+
}, [ groupButtonRefs, setExpandedGroupKey, setMenuState ]);
|
|
368
|
+
|
|
320
369
|
return {
|
|
321
370
|
handleToolbarPressIn,
|
|
322
371
|
handleToolbarPressOut,
|