@etrepum/lexical-builder 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/AutoFocusPlan.d.ts +12 -0
- package/dist/AutoFocusPlan.d.ts.map +1 -0
- package/dist/DragonPlan.d.ts +9 -0
- package/dist/DragonPlan.d.ts.map +1 -0
- package/dist/HistoryPlan.d.ts +8 -0
- package/dist/HistoryPlan.d.ts.map +1 -0
- package/dist/LexicalBuilder.d.ts +20 -0
- package/dist/LexicalBuilder.d.ts.map +1 -0
- package/dist/PlainTextPlan.d.ts +2 -0
- package/dist/PlainTextPlan.d.ts.map +1 -0
- package/dist/PlanRep.d.ts +15 -0
- package/dist/PlanRep.d.ts.map +1 -0
- package/dist/ReactPlan.d.ts +40 -0
- package/dist/ReactPlan.d.ts.map +1 -0
- package/dist/ReactPluginHostPlan.d.ts +23 -0
- package/dist/ReactPluginHostPlan.d.ts.map +1 -0
- package/dist/RichTextPlan.d.ts +9 -0
- package/dist/RichTextPlan.d.ts.map +1 -0
- package/dist/__tests__/unit/LexicalBuilder.test.d.ts +9 -0
- package/dist/__tests__/unit/LexicalBuilder.test.d.ts.map +1 -0
- package/dist/deepThemeMergeInPlace.d.ts +9 -0
- package/dist/deepThemeMergeInPlace.d.ts.map +1 -0
- package/dist/definePlan.d.ts +6 -0
- package/dist/definePlan.d.ts.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +696 -0
- package/dist/index.js.map +1 -0
- package/dist/initializeEditor.d.ts +5 -0
- package/dist/initializeEditor.d.ts.map +1 -0
- package/dist/registerShowPlaceholder.d.ts +6 -0
- package/dist/registerShowPlaceholder.d.ts.map +1 -0
- package/dist/registerSubscription.d.ts +11 -0
- package/dist/registerSubscription.d.ts.map +1 -0
- package/dist/safeCast.d.ts +9 -0
- package/dist/safeCast.d.ts.map +1 -0
- package/dist/shallowMergeConfig.d.ts +4 -0
- package/dist/shallowMergeConfig.d.ts.map +1 -0
- package/dist/shared/invariant.d.ts +9 -0
- package/dist/shared/invariant.d.ts.map +1 -0
- package/dist/shared/useLayoutEffect.d.ts +5 -0
- package/dist/shared/useLayoutEffect.d.ts.map +1 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/useReactDecorators.d.ts +10 -0
- package/dist/useReactDecorators.d.ts.map +1 -0
- package/dist/useRegisterSubscription.d.ts +4 -0
- package/dist/useRegisterSubscription.d.ts.map +1 -0
- package/package.json +7 -10
- package/dist/index.d.mts +0 -248
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -31656
package/dist/index.js
ADDED
@@ -0,0 +1,696 @@
|
|
1
|
+
var __defProp = Object.defineProperty;
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
3
|
+
var __publicField = (obj, key, value) => {
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
5
|
+
return value;
|
6
|
+
};
|
7
|
+
import { registerDragonSupport } from "@lexical/dragon";
|
8
|
+
import { createEmptyHistoryState, registerHistory } from "@lexical/history";
|
9
|
+
import { $getRoot, $createParagraphNode, createEditor, createCommand, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR } from "lexical";
|
10
|
+
import { mergeRegister, CAN_USE_DOM } from "@lexical/utils";
|
11
|
+
import { registerPlainText } from "@lexical/plain-text";
|
12
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
13
|
+
import { LexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
14
|
+
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
15
|
+
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
|
16
|
+
import useLexicalEditable from "@lexical/react/useLexicalEditable";
|
17
|
+
import { useLayoutEffect, useEffect, useState, useMemo, Suspense, useCallback, useRef } from "react";
|
18
|
+
import { $canShowPlaceholderCurry } from "@lexical/text";
|
19
|
+
import { flushSync, createPortal } from "react-dom";
|
20
|
+
import useLexicalSubscription from "@lexical/react/useLexicalSubscription";
|
21
|
+
import { createRoot } from "react-dom/client";
|
22
|
+
import { HeadingNode, QuoteNode, registerRichText } from "@lexical/rich-text";
|
23
|
+
function definePlan(plan) {
|
24
|
+
return plan;
|
25
|
+
}
|
26
|
+
function defineRootPlan(plan) {
|
27
|
+
return { ...plan, name: "[root]", config: {} };
|
28
|
+
}
|
29
|
+
function configPlan(plan, config) {
|
30
|
+
return [plan, config];
|
31
|
+
}
|
32
|
+
function safeCast(value) {
|
33
|
+
return value;
|
34
|
+
}
|
35
|
+
const AutoFocusPlan = definePlan({
|
36
|
+
config: safeCast({}),
|
37
|
+
name: "@etrepum/lexical-builder/AutoFocusPlan",
|
38
|
+
register(editor, { defaultSelection }) {
|
39
|
+
return editor.registerRootListener((rootElement) => {
|
40
|
+
editor.focus(
|
41
|
+
() => {
|
42
|
+
const activeElement = document.activeElement;
|
43
|
+
if (rootElement !== null && (activeElement === null || !rootElement.contains(activeElement))) {
|
44
|
+
rootElement.focus({ preventScroll: true });
|
45
|
+
}
|
46
|
+
},
|
47
|
+
{ defaultSelection }
|
48
|
+
);
|
49
|
+
});
|
50
|
+
}
|
51
|
+
});
|
52
|
+
const DragonPlan = definePlan({
|
53
|
+
config: {},
|
54
|
+
name: "@lexical/dragon",
|
55
|
+
register: registerDragonSupport
|
56
|
+
});
|
57
|
+
const HistoryPlan = definePlan({
|
58
|
+
config: safeCast({
|
59
|
+
createInitialHistoryState: createEmptyHistoryState,
|
60
|
+
delay: 300
|
61
|
+
}),
|
62
|
+
name: "@etrepum/lexical-builder/HistoryPlan",
|
63
|
+
register(editor, { delay, createInitialHistoryState }) {
|
64
|
+
return registerHistory(editor, createInitialHistoryState(), delay);
|
65
|
+
}
|
66
|
+
});
|
67
|
+
function invariant(cond, message, ...args) {
|
68
|
+
if (cond) {
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
throw new Error(
|
72
|
+
args.reduce((msg, arg) => msg.replace("%s", String(arg)), message || "")
|
73
|
+
);
|
74
|
+
}
|
75
|
+
function deepThemeMergeInPlace(a, b) {
|
76
|
+
if (a && b && !Array.isArray(b) && typeof a === "object" && typeof b === "object") {
|
77
|
+
const aObj = a;
|
78
|
+
const bObj = b;
|
79
|
+
for (const k in bObj) {
|
80
|
+
aObj[k] = deepThemeMergeInPlace(aObj[k], bObj[k]);
|
81
|
+
}
|
82
|
+
return a;
|
83
|
+
}
|
84
|
+
return b;
|
85
|
+
}
|
86
|
+
const HISTORY_MERGE_OPTIONS = { tag: "history-merge" };
|
87
|
+
function $defaultInitializer() {
|
88
|
+
const root = $getRoot();
|
89
|
+
if (root.isEmpty()) {
|
90
|
+
root.append($createParagraphNode());
|
91
|
+
}
|
92
|
+
}
|
93
|
+
function initializeEditor(editor, $initialEditorState = $defaultInitializer) {
|
94
|
+
switch (typeof $initialEditorState) {
|
95
|
+
case "function": {
|
96
|
+
editor.update(() => $initialEditorState(editor), HISTORY_MERGE_OPTIONS);
|
97
|
+
break;
|
98
|
+
}
|
99
|
+
case "string": {
|
100
|
+
const parsedEditorState = editor.parseEditorState($initialEditorState);
|
101
|
+
editor.setEditorState(parsedEditorState, HISTORY_MERGE_OPTIONS);
|
102
|
+
break;
|
103
|
+
}
|
104
|
+
case "object": {
|
105
|
+
if ($initialEditorState) {
|
106
|
+
editor.setEditorState($initialEditorState, HISTORY_MERGE_OPTIONS);
|
107
|
+
}
|
108
|
+
break;
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
function shallowMergeConfig(a, b) {
|
113
|
+
if (!b || a === b) {
|
114
|
+
return a;
|
115
|
+
}
|
116
|
+
for (const k in b) {
|
117
|
+
if (b[k] !== a[k]) {
|
118
|
+
return { ...a, ...b };
|
119
|
+
}
|
120
|
+
}
|
121
|
+
return a;
|
122
|
+
}
|
123
|
+
class PlanRep {
|
124
|
+
constructor(builder, plan) {
|
125
|
+
__publicField(this, "builder");
|
126
|
+
__publicField(this, "configs");
|
127
|
+
__publicField(this, "_config");
|
128
|
+
__publicField(this, "plan");
|
129
|
+
this.builder = builder;
|
130
|
+
this.plan = plan;
|
131
|
+
this.configs = /* @__PURE__ */ new Set();
|
132
|
+
}
|
133
|
+
getPeerConfig(name) {
|
134
|
+
const rep = this.builder.planNameMap.get(name);
|
135
|
+
return rep && rep.getConfig();
|
136
|
+
}
|
137
|
+
getDependencyConfig(dep) {
|
138
|
+
const pair = this.builder.planMap.get(dep);
|
139
|
+
invariant(
|
140
|
+
pair !== void 0,
|
141
|
+
"LexicalPlanBuilder: Plan %s missing dependency plan %s to be in registry",
|
142
|
+
this.plan.name,
|
143
|
+
dep.name
|
144
|
+
);
|
145
|
+
return pair[1].getConfig();
|
146
|
+
}
|
147
|
+
getConfig() {
|
148
|
+
if (this._config) {
|
149
|
+
return this._config;
|
150
|
+
}
|
151
|
+
let config = this.plan.config;
|
152
|
+
const mergeConfig = this.plan.mergeConfig ? this.plan.mergeConfig.bind(this.plan) : shallowMergeConfig;
|
153
|
+
for (const cfg of this.configs) {
|
154
|
+
config = mergeConfig(config, cfg);
|
155
|
+
}
|
156
|
+
this._config = config;
|
157
|
+
return config;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
const buildersForEditors = /* @__PURE__ */ new WeakMap();
|
161
|
+
function buildEditorFromPlans(plan, ...plans) {
|
162
|
+
const builder = new LexicalBuilder();
|
163
|
+
builder.addPlan(plan);
|
164
|
+
for (const otherPlan of plans) {
|
165
|
+
builder.addPlan(otherPlan);
|
166
|
+
}
|
167
|
+
return builder.buildEditor();
|
168
|
+
}
|
169
|
+
class LexicalBuilder {
|
170
|
+
constructor() {
|
171
|
+
__publicField(this, "phases");
|
172
|
+
__publicField(this, "planMap");
|
173
|
+
__publicField(this, "planNameMap");
|
174
|
+
__publicField(this, "conflicts");
|
175
|
+
this.phases = [/* @__PURE__ */ new Map()];
|
176
|
+
this.planMap = /* @__PURE__ */ new Map();
|
177
|
+
this.planNameMap = /* @__PURE__ */ new Map();
|
178
|
+
this.conflicts = /* @__PURE__ */ new Map();
|
179
|
+
}
|
180
|
+
static fromEditor(editor) {
|
181
|
+
const builder = buildersForEditors.get(editor);
|
182
|
+
invariant(
|
183
|
+
builder !== void 0,
|
184
|
+
"LexicalBuilder.fromEditor: editor was not created with this version of LexicalBuilder"
|
185
|
+
);
|
186
|
+
return builder;
|
187
|
+
}
|
188
|
+
buildEditor() {
|
189
|
+
const { $initialEditorState, onError, ...editorConfig } = this.buildCreateEditorArgs();
|
190
|
+
const editor = createEditor({
|
191
|
+
...editorConfig,
|
192
|
+
...onError ? { onError: (err) => onError(err, editor) } : {}
|
193
|
+
});
|
194
|
+
initializeEditor(editor, $initialEditorState);
|
195
|
+
buildersForEditors.set(editor, this);
|
196
|
+
const dispose = mergeRegister(
|
197
|
+
() => buildersForEditors.delete(editor),
|
198
|
+
this.registerEditor(editor)
|
199
|
+
);
|
200
|
+
return { dispose, editor };
|
201
|
+
}
|
202
|
+
addPlan(arg) {
|
203
|
+
let plan;
|
204
|
+
let configs;
|
205
|
+
if (Array.isArray(arg)) {
|
206
|
+
[plan, ...configs] = arg;
|
207
|
+
} else {
|
208
|
+
plan = arg;
|
209
|
+
configs = [];
|
210
|
+
}
|
211
|
+
let [phase, planRep] = this.planMap.get(plan) || [0, void 0];
|
212
|
+
if (!planRep) {
|
213
|
+
const hasConflict = this.conflicts.get(plan.name);
|
214
|
+
if (typeof hasConflict === "string") {
|
215
|
+
invariant(
|
216
|
+
false,
|
217
|
+
"LexicalBuilder: plan %s conflicts with %s",
|
218
|
+
plan.name,
|
219
|
+
hasConflict
|
220
|
+
);
|
221
|
+
}
|
222
|
+
for (const name of plan.conflictsWith || []) {
|
223
|
+
invariant(
|
224
|
+
!this.planNameMap.has(name),
|
225
|
+
"LexicalBuilder: plan %s conflicts with %s",
|
226
|
+
plan.name,
|
227
|
+
name
|
228
|
+
);
|
229
|
+
this.conflicts.set(name, plan.name);
|
230
|
+
}
|
231
|
+
for (const dep of plan.dependencies || []) {
|
232
|
+
phase = Math.max(phase, 1 + this.addPlan(dep));
|
233
|
+
}
|
234
|
+
for (const [depName, cfg] of Object.entries(
|
235
|
+
plan.peerDependencies || {}
|
236
|
+
)) {
|
237
|
+
const dep = this.planNameMap.get(depName);
|
238
|
+
if (dep) {
|
239
|
+
phase = Math.max(phase, 1 + this.addPlan([dep.plan, cfg]));
|
240
|
+
}
|
241
|
+
}
|
242
|
+
invariant(
|
243
|
+
this.phases.length >= phase,
|
244
|
+
"LexicalBuilder: Expected phase to be no greater than phases.length"
|
245
|
+
);
|
246
|
+
if (this.phases.length === phase) {
|
247
|
+
this.phases.push(/* @__PURE__ */ new Map());
|
248
|
+
}
|
249
|
+
planRep = new PlanRep(this, plan);
|
250
|
+
invariant(
|
251
|
+
!this.planNameMap.has(plan.name),
|
252
|
+
"LexicalBuilder: Multiple plans registered with name %s, names must be unique",
|
253
|
+
plan.name
|
254
|
+
);
|
255
|
+
this.planMap.set(plan, [phase, planRep]);
|
256
|
+
this.planNameMap.set(plan.name, planRep);
|
257
|
+
const currentPhaseMap = this.phases[phase];
|
258
|
+
invariant(
|
259
|
+
currentPhaseMap !== void 0,
|
260
|
+
"LexicalBuilder: Expecting phase map for phase %s",
|
261
|
+
String(phase)
|
262
|
+
);
|
263
|
+
currentPhaseMap.set(plan, planRep);
|
264
|
+
}
|
265
|
+
for (const config of configs) {
|
266
|
+
planRep.configs.add(config);
|
267
|
+
}
|
268
|
+
return phase;
|
269
|
+
}
|
270
|
+
*sortedPlanReps() {
|
271
|
+
for (const phase of this.phases) {
|
272
|
+
yield* phase.values();
|
273
|
+
}
|
274
|
+
}
|
275
|
+
registerEditor(editor) {
|
276
|
+
const cleanups = [];
|
277
|
+
const controller = new AbortController();
|
278
|
+
for (const planRep of this.sortedPlanReps()) {
|
279
|
+
if (planRep.plan.register) {
|
280
|
+
cleanups.push(
|
281
|
+
planRep.plan.register(editor, planRep.getConfig(), {
|
282
|
+
getDependencyConfig: planRep.getDependencyConfig.bind(planRep),
|
283
|
+
getPeerConfig: planRep.getPeerConfig.bind(planRep),
|
284
|
+
signal: controller.signal
|
285
|
+
})
|
286
|
+
);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
return () => {
|
290
|
+
for (let i = cleanups.length - 1; i >= 0; i--) {
|
291
|
+
const cleanupFun = cleanups[i];
|
292
|
+
invariant(
|
293
|
+
cleanupFun !== void 0,
|
294
|
+
"LexicalBuilder: Expecting cleanups[%s] to be defined",
|
295
|
+
String(i)
|
296
|
+
);
|
297
|
+
cleanupFun();
|
298
|
+
}
|
299
|
+
cleanups.length = 0;
|
300
|
+
controller.abort();
|
301
|
+
};
|
302
|
+
}
|
303
|
+
buildCreateEditorArgs() {
|
304
|
+
const config = {};
|
305
|
+
const nodes = /* @__PURE__ */ new Set();
|
306
|
+
const replacedNodes = /* @__PURE__ */ new Map();
|
307
|
+
const htmlExport = /* @__PURE__ */ new Map();
|
308
|
+
const htmlImport = {};
|
309
|
+
const theme = {};
|
310
|
+
for (const planRep of this.sortedPlanReps()) {
|
311
|
+
const { plan } = planRep;
|
312
|
+
if (plan.onError !== void 0) {
|
313
|
+
config.onError = plan.onError;
|
314
|
+
}
|
315
|
+
if (plan.disableEvents !== void 0) {
|
316
|
+
config.disableEvents = plan.disableEvents;
|
317
|
+
}
|
318
|
+
if (plan.editable !== void 0) {
|
319
|
+
config.editable = plan.editable;
|
320
|
+
}
|
321
|
+
if (plan.namespace !== void 0) {
|
322
|
+
config.namespace = plan.namespace;
|
323
|
+
}
|
324
|
+
if (plan.$initialEditorState !== void 0) {
|
325
|
+
config.$initialEditorState = plan.$initialEditorState;
|
326
|
+
}
|
327
|
+
if (plan.nodes) {
|
328
|
+
for (const node of plan.nodes) {
|
329
|
+
if (typeof node !== "function") {
|
330
|
+
const conflictPlan = replacedNodes.get(node.replace);
|
331
|
+
if (conflictPlan) {
|
332
|
+
invariant(
|
333
|
+
false,
|
334
|
+
"LexicalBuilder: Plan %s can not register replacement for node %s because %s already did",
|
335
|
+
plan.name,
|
336
|
+
node.replace.name,
|
337
|
+
conflictPlan.plan.name
|
338
|
+
);
|
339
|
+
}
|
340
|
+
replacedNodes.set(node.replace, planRep);
|
341
|
+
}
|
342
|
+
nodes.add(node);
|
343
|
+
}
|
344
|
+
}
|
345
|
+
if (plan.html) {
|
346
|
+
if (plan.html.export) {
|
347
|
+
for (const [k, v] of plan.html.export.entries()) {
|
348
|
+
htmlExport.set(k, v);
|
349
|
+
}
|
350
|
+
}
|
351
|
+
if (plan.html.import) {
|
352
|
+
Object.assign(htmlImport, plan.html.import);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
if (plan.theme) {
|
356
|
+
deepThemeMergeInPlace(theme, plan.theme);
|
357
|
+
}
|
358
|
+
}
|
359
|
+
if (Object.keys(theme).length > 0) {
|
360
|
+
config.theme = theme;
|
361
|
+
}
|
362
|
+
if (nodes.size) {
|
363
|
+
config.nodes = [...nodes];
|
364
|
+
}
|
365
|
+
const hasImport = Object.keys(htmlImport).length > 0;
|
366
|
+
const hasExport = htmlExport.size > 0;
|
367
|
+
if (hasImport || hasExport) {
|
368
|
+
config.html = {};
|
369
|
+
if (hasImport) {
|
370
|
+
config.html.import = htmlImport;
|
371
|
+
}
|
372
|
+
if (hasExport) {
|
373
|
+
config.html.export = htmlExport;
|
374
|
+
}
|
375
|
+
}
|
376
|
+
return config;
|
377
|
+
}
|
378
|
+
}
|
379
|
+
const PlainTextPlan = definePlan({
|
380
|
+
config: {},
|
381
|
+
conflictsWith: ["@lexical/rich-text"],
|
382
|
+
name: "@lexical/plain-text",
|
383
|
+
register: registerPlainText
|
384
|
+
});
|
385
|
+
function canShowPlaceholderFromCurrentEditorState(editor) {
|
386
|
+
const currentCanShowPlaceholder = editor.getEditorState().read($canShowPlaceholderCurry(editor.isComposing()));
|
387
|
+
return currentCanShowPlaceholder;
|
388
|
+
}
|
389
|
+
function subscribe(editor, onChange) {
|
390
|
+
const resetCanShowPlaceholder = () => onChange(canShowPlaceholderFromCurrentEditorState(editor));
|
391
|
+
return mergeRegister(
|
392
|
+
editor.registerUpdateListener(resetCanShowPlaceholder),
|
393
|
+
editor.registerEditableListener(resetCanShowPlaceholder)
|
394
|
+
);
|
395
|
+
}
|
396
|
+
const canShowPlaceholder = {
|
397
|
+
initialValueFn: canShowPlaceholderFromCurrentEditorState,
|
398
|
+
subscribe
|
399
|
+
};
|
400
|
+
const useLayoutEffectImpl = CAN_USE_DOM ? useLayoutEffect : useEffect;
|
401
|
+
function useReactDecorators(editor, ErrorBoundary) {
|
402
|
+
const [decorators, setDecorators] = useState(
|
403
|
+
() => editor.getDecorators()
|
404
|
+
);
|
405
|
+
useLayoutEffectImpl(() => {
|
406
|
+
return editor.registerDecoratorListener((nextDecorators) => {
|
407
|
+
flushSync(() => {
|
408
|
+
setDecorators(nextDecorators);
|
409
|
+
});
|
410
|
+
});
|
411
|
+
}, [editor]);
|
412
|
+
useEffect(() => {
|
413
|
+
setDecorators(editor.getDecorators());
|
414
|
+
}, [editor]);
|
415
|
+
return useMemo(() => {
|
416
|
+
const decoratedPortals = [];
|
417
|
+
const decoratorKeys = Object.keys(decorators);
|
418
|
+
for (let i = 0; i < decoratorKeys.length; i++) {
|
419
|
+
const nodeKey = decoratorKeys[i];
|
420
|
+
invariant(
|
421
|
+
nodeKey !== void 0,
|
422
|
+
"useReactDecorators: decoratorKeys[%s] must be defined",
|
423
|
+
String(i)
|
424
|
+
);
|
425
|
+
const element = editor.getElementByKey(nodeKey);
|
426
|
+
if (element !== null) {
|
427
|
+
const reactDecorator = /* @__PURE__ */ jsx(ErrorBoundary, { onError: (e) => editor._onError(e), children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: decorators[nodeKey] }) });
|
428
|
+
decoratedPortals.push(createPortal(reactDecorator, element, nodeKey));
|
429
|
+
}
|
430
|
+
}
|
431
|
+
return decoratedPortals;
|
432
|
+
}, [ErrorBoundary, decorators, editor]);
|
433
|
+
}
|
434
|
+
function useRegisterSubscription(subscription) {
|
435
|
+
const sub = useCallback(
|
436
|
+
(editor) => {
|
437
|
+
return {
|
438
|
+
initialValueFn: subscription.initialValueFn.bind(subscription, editor),
|
439
|
+
subscribe: subscription.subscribe.bind(subscription, editor)
|
440
|
+
};
|
441
|
+
},
|
442
|
+
[subscription]
|
443
|
+
);
|
444
|
+
return useLexicalSubscription(sub);
|
445
|
+
}
|
446
|
+
const scheduleMicrotask = "queueMicrotask" in globalThis ? queueMicrotask : (fn) => Promise.resolve().then(fn);
|
447
|
+
function LexicalPlanComposer({
|
448
|
+
plan,
|
449
|
+
children
|
450
|
+
}) {
|
451
|
+
const componentRef = useRef(void 0);
|
452
|
+
const handle = useMemo(() => {
|
453
|
+
return buildEditorFromPlans(
|
454
|
+
definePlan({
|
455
|
+
name: "@lexical/builder/LexicalPlanComposer",
|
456
|
+
config: {},
|
457
|
+
dependencies: [ReactPlan],
|
458
|
+
register(_editor, _config, state) {
|
459
|
+
componentRef.current = state.getDependencyConfig(ReactPlan).Component;
|
460
|
+
return () => {
|
461
|
+
componentRef.current = void 0;
|
462
|
+
};
|
463
|
+
}
|
464
|
+
}),
|
465
|
+
plan
|
466
|
+
);
|
467
|
+
}, [plan]);
|
468
|
+
useEffect(() => {
|
469
|
+
let didMount = false;
|
470
|
+
scheduleMicrotask(() => {
|
471
|
+
didMount = true;
|
472
|
+
});
|
473
|
+
return () => {
|
474
|
+
if (didMount) {
|
475
|
+
handle.dispose();
|
476
|
+
}
|
477
|
+
};
|
478
|
+
}, [handle]);
|
479
|
+
const EditorComponent = componentRef.current;
|
480
|
+
return EditorComponent ? /* @__PURE__ */ jsx(EditorComponent, { children }) : null;
|
481
|
+
}
|
482
|
+
function DefaultEditorChildrenComponent({
|
483
|
+
contentEditable,
|
484
|
+
placeholder,
|
485
|
+
children
|
486
|
+
}) {
|
487
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
488
|
+
contentEditable,
|
489
|
+
placeholder && /* @__PURE__ */ jsx(Placeholder, { content: placeholder }),
|
490
|
+
children
|
491
|
+
] });
|
492
|
+
}
|
493
|
+
function buildEditorComponent(config) {
|
494
|
+
const context = config.getContext();
|
495
|
+
const [editor] = context;
|
496
|
+
const rawConfigDecorators = config.decorators.map(
|
497
|
+
(El) => typeof El === "function" ? /* @__PURE__ */ jsx(El, { context }) : El
|
498
|
+
);
|
499
|
+
return function EditorComponent(props) {
|
500
|
+
const {
|
501
|
+
EditorChildrenComponent = config.EditorChildrenComponent,
|
502
|
+
ErrorBoundary = config.ErrorBoundary,
|
503
|
+
contentEditable = config.contentEditable,
|
504
|
+
placeholder = config.placeholder,
|
505
|
+
children
|
506
|
+
} = props;
|
507
|
+
const decorators = useReactDecorators(editor, ErrorBoundary);
|
508
|
+
const configDecorators = useMemo(
|
509
|
+
() => rawConfigDecorators.map((decorator, i) => /* @__PURE__ */ jsx(ErrorBoundary, { onError: (e) => editor._onError(e), children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: decorator }) }, i)),
|
510
|
+
[ErrorBoundary]
|
511
|
+
);
|
512
|
+
return /* @__PURE__ */ jsx(LexicalComposerContext.Provider, { value: context, children: /* @__PURE__ */ jsxs(
|
513
|
+
EditorChildrenComponent,
|
514
|
+
{
|
515
|
+
context,
|
516
|
+
contentEditable,
|
517
|
+
placeholder: placeholder && /* @__PURE__ */ jsx(Placeholder, { content: placeholder }),
|
518
|
+
children: [
|
519
|
+
children,
|
520
|
+
configDecorators,
|
521
|
+
decorators
|
522
|
+
]
|
523
|
+
}
|
524
|
+
) });
|
525
|
+
};
|
526
|
+
}
|
527
|
+
function WithEditable({
|
528
|
+
content
|
529
|
+
}) {
|
530
|
+
return content(useLexicalEditable());
|
531
|
+
}
|
532
|
+
function Placeholder({
|
533
|
+
content
|
534
|
+
}) {
|
535
|
+
const showPlaceholder = useRegisterSubscription(canShowPlaceholder);
|
536
|
+
if (!showPlaceholder) {
|
537
|
+
return null;
|
538
|
+
} else if (typeof content === "function") {
|
539
|
+
return /* @__PURE__ */ jsx(WithEditable, { content });
|
540
|
+
} else {
|
541
|
+
return content;
|
542
|
+
}
|
543
|
+
}
|
544
|
+
const initialConfig = {
|
545
|
+
EditorChildrenComponent: DefaultEditorChildrenComponent,
|
546
|
+
ErrorBoundary: LexicalErrorBoundary,
|
547
|
+
contentEditable: /* @__PURE__ */ jsx(ContentEditable, {}),
|
548
|
+
decorators: [],
|
549
|
+
placeholder: null,
|
550
|
+
// Initialized on registration
|
551
|
+
Component() {
|
552
|
+
invariant(false, "ReactPlan used before register");
|
553
|
+
},
|
554
|
+
// Initialized on registration
|
555
|
+
getContext() {
|
556
|
+
invariant(false, "ReactPlan used before register");
|
557
|
+
}
|
558
|
+
};
|
559
|
+
const ReactPlan = definePlan({
|
560
|
+
config: initialConfig,
|
561
|
+
mergeConfig(a, b) {
|
562
|
+
const config = shallowMergeConfig(a, b);
|
563
|
+
if (b && b.decorators && b.decorators.length > 0) {
|
564
|
+
config.decorators = [...a.decorators, ...b.decorators];
|
565
|
+
}
|
566
|
+
return config;
|
567
|
+
},
|
568
|
+
name: "@etrepum/lexical-builder/ReactPlan",
|
569
|
+
register(editor, config) {
|
570
|
+
const context = [
|
571
|
+
editor,
|
572
|
+
{ getTheme: () => editor._config.theme }
|
573
|
+
];
|
574
|
+
config.getContext = () => context;
|
575
|
+
config.Component = buildEditorComponent(config);
|
576
|
+
return () => {
|
577
|
+
config.getContext = initialConfig.getContext;
|
578
|
+
config.Component = initialConfig.Component;
|
579
|
+
};
|
580
|
+
}
|
581
|
+
});
|
582
|
+
function mountReactPluginComponent(editor, opts) {
|
583
|
+
const { Component, props, ...rest } = opts;
|
584
|
+
return mountReactPluginElement(editor, {
|
585
|
+
...rest,
|
586
|
+
element: Component && props ? /* @__PURE__ */ jsx(Component, { ...props }) : null
|
587
|
+
});
|
588
|
+
}
|
589
|
+
function mountReactPluginElement(editor, opts) {
|
590
|
+
editor.dispatchCommand(REACT_MOUNT_PLUGIN_COMMAND, opts);
|
591
|
+
}
|
592
|
+
function mountReactPluginHost(editor, container) {
|
593
|
+
editor.dispatchCommand(REACT_PLUGIN_HOST_MOUNT_COMMAND, {
|
594
|
+
root: createRoot(container)
|
595
|
+
});
|
596
|
+
}
|
597
|
+
const REACT_PLUGIN_HOST_MOUNT_COMMAND = createCommand("REACT_PLUGIN_HOST_MOUNT_COMMAND");
|
598
|
+
const REACT_MOUNT_PLUGIN_COMMAND = createCommand(
|
599
|
+
"REACT_MOUNT_PLUGIN_COMMAND"
|
600
|
+
);
|
601
|
+
const ReactPluginHostPlan = definePlan({
|
602
|
+
config: {},
|
603
|
+
dependencies: [
|
604
|
+
configPlan(ReactPlan, {
|
605
|
+
contentEditable: null
|
606
|
+
})
|
607
|
+
],
|
608
|
+
name: "@etrepum/lexical-builder/ReactPluginHostPlan",
|
609
|
+
register(editor, _config, state) {
|
610
|
+
let root;
|
611
|
+
const mountedPlugins = /* @__PURE__ */ new Map();
|
612
|
+
const { ErrorBoundary, Component } = state.getDependencyConfig(ReactPlan);
|
613
|
+
function renderMountedPlugins() {
|
614
|
+
const children = [];
|
615
|
+
for (const { key, element, domNode } of mountedPlugins.values()) {
|
616
|
+
if (!element) {
|
617
|
+
continue;
|
618
|
+
}
|
619
|
+
const wrapped = /* @__PURE__ */ jsx(ErrorBoundary, { onError: (e) => editor._onError(e), children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: element }) }, key);
|
620
|
+
children.push(domNode ? createPortal(wrapped, domNode, key) : wrapped);
|
621
|
+
}
|
622
|
+
return children.length > 0 ? /* @__PURE__ */ jsx(Fragment, { children }) : null;
|
623
|
+
}
|
624
|
+
function PluginHost() {
|
625
|
+
const [children, setChildren] = useState(renderMountedPlugins);
|
626
|
+
useEffect(() => {
|
627
|
+
return editor.registerCommand(
|
628
|
+
REACT_MOUNT_PLUGIN_COMMAND,
|
629
|
+
() => {
|
630
|
+
setChildren(renderMountedPlugins);
|
631
|
+
return true;
|
632
|
+
},
|
633
|
+
COMMAND_PRIORITY_EDITOR
|
634
|
+
);
|
635
|
+
}, []);
|
636
|
+
return children;
|
637
|
+
}
|
638
|
+
return mergeRegister(
|
639
|
+
() => {
|
640
|
+
if (root) {
|
641
|
+
root.unmount();
|
642
|
+
}
|
643
|
+
},
|
644
|
+
editor.registerCommand(
|
645
|
+
REACT_MOUNT_PLUGIN_COMMAND,
|
646
|
+
(arg) => {
|
647
|
+
mountedPlugins.set(arg.key, arg);
|
648
|
+
return false;
|
649
|
+
},
|
650
|
+
COMMAND_PRIORITY_CRITICAL
|
651
|
+
),
|
652
|
+
editor.registerCommand(
|
653
|
+
REACT_PLUGIN_HOST_MOUNT_COMMAND,
|
654
|
+
(arg) => {
|
655
|
+
root = arg.root;
|
656
|
+
root.render(
|
657
|
+
/* @__PURE__ */ jsx(Component, { children: /* @__PURE__ */ jsx(PluginHost, {}) })
|
658
|
+
);
|
659
|
+
return true;
|
660
|
+
},
|
661
|
+
COMMAND_PRIORITY_EDITOR
|
662
|
+
)
|
663
|
+
);
|
664
|
+
}
|
665
|
+
});
|
666
|
+
const RichTextPlan = definePlan({
|
667
|
+
config: {},
|
668
|
+
conflictsWith: ["@lexical/plain-text"],
|
669
|
+
name: "@lexical/rich-text",
|
670
|
+
nodes: [HeadingNode, QuoteNode],
|
671
|
+
register: registerRichText
|
672
|
+
});
|
673
|
+
const PACKAGE_VERSION = "0.0.5";
|
674
|
+
export {
|
675
|
+
AutoFocusPlan,
|
676
|
+
DragonPlan,
|
677
|
+
HistoryPlan,
|
678
|
+
LexicalBuilder,
|
679
|
+
LexicalPlanComposer,
|
680
|
+
PACKAGE_VERSION,
|
681
|
+
PlainTextPlan,
|
682
|
+
REACT_MOUNT_PLUGIN_COMMAND,
|
683
|
+
REACT_PLUGIN_HOST_MOUNT_COMMAND,
|
684
|
+
ReactPlan,
|
685
|
+
ReactPluginHostPlan,
|
686
|
+
RichTextPlan,
|
687
|
+
buildEditorFromPlans,
|
688
|
+
configPlan,
|
689
|
+
definePlan,
|
690
|
+
defineRootPlan,
|
691
|
+
mountReactPluginComponent,
|
692
|
+
mountReactPluginElement,
|
693
|
+
mountReactPluginHost,
|
694
|
+
safeCast
|
695
|
+
};
|
696
|
+
//# sourceMappingURL=index.js.map
|