@etrepum/lexical-builder 0.0.4 → 0.0.5
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/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
|