@mx-space/cli 0.14.1 → 0.14.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/dist/{Lexical.dev-DTxuYHmG.mjs → Lexical.dev-CtGmYDoh.mjs} +770 -271
- package/dist/{Lexical.node-BlCLnfA6.mjs → Lexical.node-8sRFmq2X.mjs} +15 -5
- package/dist/Lexical.prod-D-VfeKDz.mjs +7200 -0
- package/dist/{LexicalClipboard.dev-CdFkLR_D.mjs → LexicalClipboard.dev-CzQ15z6E.mjs} +6 -6
- package/dist/{LexicalClipboard.node-ktUajxsv.mjs → LexicalClipboard.node-D4gMGws6.mjs} +2 -2
- package/dist/{LexicalClipboard.prod-DliyLofW.mjs → LexicalClipboard.prod-CltkQpzS.mjs} +10 -8
- package/dist/{LexicalCodeCore.dev-CL9tHWJX.mjs → LexicalCodeCore.dev-DkYBZRGB.mjs} +11 -9
- package/dist/{LexicalCodeCore.prod-BoMSJc29.mjs → LexicalCodeCore.prod-COc3_QL8.mjs} +178 -167
- package/dist/{LexicalDragon.dev-CqW7Aq5H.mjs → LexicalDragon.dev-Dv5_WUae.mjs} +3 -3
- package/dist/{LexicalDragon.node-DLXctJyy.mjs → LexicalDragon.node-DgjrmWkd.mjs} +2 -2
- package/dist/{LexicalDragon.prod-DHI3T6n5.mjs → LexicalDragon.prod-DnpbDe-_.mjs} +5 -4
- package/dist/{LexicalExtension.dev-BP-18zns.mjs → LexicalExtension.dev-JMH_6-OZ.mjs} +73 -52
- package/dist/{LexicalExtension.node-BWH6xbzG.mjs → LexicalExtension.node-BUozzx4t.mjs} +4 -2
- package/dist/{LexicalExtension.prod-Cs6OgrDn.mjs → LexicalExtension.prod-UiyDgmou.mjs} +370 -347
- package/dist/{LexicalHeadless.dev-DJp__UcP.mjs → LexicalHeadless.dev-BfLGciiX.mjs} +2 -2
- package/dist/{LexicalHeadless.prod-o0v9cIu5.mjs → LexicalHeadless.prod-CWF7edmQ.mjs} +2 -2
- package/dist/{LexicalHtml.dev-DoymwFpG.mjs → LexicalHtml.dev-D5EF5PGW.mjs} +13 -11
- package/dist/{LexicalHtml.node-CVkbWtUA.mjs → LexicalHtml.node-BYbzHNVe.mjs} +4 -4
- package/dist/{LexicalHtml.prod-C2b3z99k.mjs → LexicalHtml.prod-D_FfkvVD.mjs} +330 -299
- package/dist/{LexicalLink.dev-7cgLOLIe.mjs → LexicalLink.dev-D3Pgh6ik.mjs} +53 -23
- package/dist/{LexicalLink.prod-DWFgoXHR.mjs → LexicalLink.prod-XZoAYVYD.mjs} +217 -198
- package/dist/{LexicalList.dev-Ci2iOxFx.mjs → LexicalList.dev-B5d3ObhB.mjs} +49 -44
- package/dist/LexicalList.prod-OQDpVAEb.mjs +967 -0
- package/dist/{LexicalMarkdown.dev-C0ZYCyuR.mjs → LexicalMarkdown.dev-BkM8G3DG.mjs} +61 -42
- package/dist/{LexicalMarkdown.prod-0M-Nc-rh.mjs → LexicalMarkdown.prod-DcVXCex6.mjs} +254 -202
- package/dist/{LexicalRichText.dev-Cnr1kDym.mjs → LexicalRichText.dev-DppD7IrA.mjs} +337 -52
- package/dist/{LexicalRichText.node-BUJZAiap.mjs → LexicalRichText.node-CPSn7dkg.mjs} +12 -8
- package/dist/LexicalRichText.prod-h7JPxFNp.mjs +718 -0
- package/dist/{LexicalSelection.dev-C4L7l8OB.mjs → LexicalSelection.dev-CD0SLbxP.mjs} +48 -17
- package/dist/{LexicalSelection.node-CLKroUMQ.mjs → LexicalSelection.node-CGlJgUlZ.mjs} +5 -4
- package/dist/{LexicalSelection.prod-DzFqpTlw.mjs → LexicalSelection.prod-DbVZN5AV.mjs} +101 -92
- package/dist/{LexicalTable.dev-Cc9-zqKa.mjs → LexicalTable.dev-D0HU14UV.mjs} +340 -138
- package/dist/LexicalTable.prod-BcPNSrxP.mjs +2468 -0
- package/dist/{LexicalUtils.dev-BRgK0L6G.mjs → LexicalUtils.dev-iKy_TrRT.mjs} +15 -19
- package/dist/{LexicalUtils.node-BVAwOkL4.mjs → LexicalUtils.node-CIgMS8cG.mjs} +6 -6
- package/dist/{LexicalUtils.prod-C1gtvVDP.mjs → LexicalUtils.prod-DIAsKJzu.mjs} +155 -159
- package/dist/bin/mxs.mjs +1 -1
- package/dist/esm-CH7CrOvh.mjs +2 -0
- package/dist/{esm-BNu4sUWV.mjs → esm-CwXl1N0a.mjs} +1801 -6013
- package/dist/index.d.mts +57 -62
- package/dist/index.mjs +1 -1
- package/dist/{mxs-CMX2yklg.mjs → mxs-iW9DgqSZ.mjs} +14930 -9234
- package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
- package/dist/vendor/litexml/cli.mjs +6693 -5762
- package/dist/vendor/litexml/litexml-html-preview-client.js +11912 -8698
- package/package.json +31 -30
- package/LICENSE +0 -33
- package/dist/Lexical.prod-CeB9UQuo.mjs +0 -6816
- package/dist/LexicalList.prod-D0xX5d3G.mjs +0 -944
- package/dist/LexicalRichText.prod-BfbMQ9uM.mjs +0 -538
- package/dist/LexicalTable.prod-BgO4nCxy.mjs +0 -2336
- package/dist/esm-jbwcVZth.mjs +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../../node_modules/.pnpm/lexical@0.
|
|
1
|
+
//#region ../../node_modules/.pnpm/lexical@0.48.0_typescript@6.0.3/node_modules/lexical/dist/Lexical.dev.mjs
|
|
2
2
|
/**
|
|
3
3
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
4
|
*
|
|
@@ -368,11 +368,11 @@ var ElementDOMSlot = class ElementDOMSlot extends DOMSlot {
|
|
|
368
368
|
}
|
|
369
369
|
const element = this.element;
|
|
370
370
|
const before = this.before;
|
|
371
|
-
const br =
|
|
371
|
+
const br = $getDocument().createElement("br");
|
|
372
372
|
br.setAttribute("data-lexical-managed-linebreak", "true");
|
|
373
373
|
element.insertBefore(br, before);
|
|
374
374
|
if (webkitHack) {
|
|
375
|
-
const img =
|
|
375
|
+
const img = $getDocument().createElement("img");
|
|
376
376
|
img.setAttribute("data-lexical-managed-linebreak", "true");
|
|
377
377
|
img.style.setProperty("display", "inline", "important");
|
|
378
378
|
img.style.setProperty("border", "0px", "important");
|
|
@@ -448,7 +448,7 @@ function indexPath(root, child) {
|
|
|
448
448
|
*/
|
|
449
449
|
let envLexicalVersion;
|
|
450
450
|
try {
|
|
451
|
-
envLexicalVersion = "0.
|
|
451
|
+
envLexicalVersion = "0.48.0+dev.esm";
|
|
452
452
|
} catch (_unused) {}
|
|
453
453
|
const LEXICAL_VERSION = envLexicalVersion ?? "\"<unknown>+source\"";
|
|
454
454
|
/**
|
|
@@ -1784,8 +1784,8 @@ function $setElementDirection(dom, node) {
|
|
|
1784
1784
|
if (direction !== null) dom.dir = direction;
|
|
1785
1785
|
else dom.removeAttribute("dir");
|
|
1786
1786
|
}
|
|
1787
|
-
function createSlotDOM(name) {
|
|
1788
|
-
const container =
|
|
1787
|
+
function $createSlotDOM(name) {
|
|
1788
|
+
const container = $getDocument().createElement("div");
|
|
1789
1789
|
container.setAttribute("data-lexical-slot", name);
|
|
1790
1790
|
container.style.display = "none";
|
|
1791
1791
|
return container;
|
|
@@ -1801,7 +1801,7 @@ function $mountSlotChildren(node, hostDom, slots) {
|
|
|
1801
1801
|
let totalText = "";
|
|
1802
1802
|
const decoratorHost = $isDecoratorNode(node);
|
|
1803
1803
|
for (const [name, slotKey] of slots) {
|
|
1804
|
-
const container = createSlotDOM(name);
|
|
1804
|
+
const container = $createSlotDOM(name);
|
|
1805
1805
|
$applySlotEditable(hostDom, decoratorHost, container);
|
|
1806
1806
|
hostDom.appendChild(container);
|
|
1807
1807
|
subTreeTextContent = "";
|
|
@@ -1848,7 +1848,7 @@ function $reconcileSlotChildren(prevNode, nextNode, hostDom) {
|
|
|
1848
1848
|
subTreeTextContent = "";
|
|
1849
1849
|
const saved = $beginCaptureGuard();
|
|
1850
1850
|
if (container === null) {
|
|
1851
|
-
container = createSlotDOM(name);
|
|
1851
|
+
container = $createSlotDOM(name);
|
|
1852
1852
|
let firstNonSlot = null;
|
|
1853
1853
|
for (const child of hostDom.children) if (!child.hasAttribute("data-lexical-slot")) {
|
|
1854
1854
|
firstNonSlot = child;
|
|
@@ -2636,6 +2636,12 @@ const DELETE_LINE_COMMAND = /* @__PURE__ */ createCommand("DELETE_LINE_COMMAND")
|
|
|
2636
2636
|
*/
|
|
2637
2637
|
const FORMAT_TEXT_COMMAND = /* @__PURE__ */ createCommand("FORMAT_TEXT_COMMAND");
|
|
2638
2638
|
/**
|
|
2639
|
+
* Dispatched to explicitly set or unset text formats on the selection.
|
|
2640
|
+
* Unlike FORMAT_TEXT_COMMAND which toggles, this command sets each specified
|
|
2641
|
+
* format to the exact boolean value provided.
|
|
2642
|
+
*/
|
|
2643
|
+
const SET_TEXT_FORMAT_COMMAND = /* @__PURE__ */ createCommand("SET_TEXT_FORMAT_COMMAND");
|
|
2644
|
+
/**
|
|
2639
2645
|
* Dispatched on undo (Cmd+Z on macOS, Ctrl+Z elsewhere).
|
|
2640
2646
|
*/
|
|
2641
2647
|
const UNDO_COMMAND = /* @__PURE__ */ createCommand("UNDO_COMMAND");
|
|
@@ -2743,6 +2749,114 @@ const BLUR_COMMAND = /* @__PURE__ */ createCommand("BLUR_COMMAND");
|
|
|
2743
2749
|
* Dispatched after any KeyboardEvent when modifiers are pressed
|
|
2744
2750
|
*/
|
|
2745
2751
|
const KEY_MODIFIER_COMMAND = /* @__PURE__ */ createCommand("KEY_MODIFIER_COMMAND");
|
|
2752
|
+
/**
|
|
2753
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2754
|
+
*
|
|
2755
|
+
* This source code is licensed under the MIT license found in the
|
|
2756
|
+
* LICENSE file in the root directory of this source tree.
|
|
2757
|
+
*
|
|
2758
|
+
*/
|
|
2759
|
+
/**
|
|
2760
|
+
* A registry mapping keys to a per-key activation, reference counted so the
|
|
2761
|
+
* activation is created on the first registration for a key and torn down
|
|
2762
|
+
* only when the last outstanding registration for that key is released. This
|
|
2763
|
+
* lets the same key be driven by more than one caller (or survive a
|
|
2764
|
+
* re-entrant / double registration) without double-wiring or premature
|
|
2765
|
+
* teardown.
|
|
2766
|
+
*
|
|
2767
|
+
* Keys are compared by identity (Map semantics), so any object works — a DOM
|
|
2768
|
+
* element, a `Document`, a `Window`, or an opaque handle.
|
|
2769
|
+
*/
|
|
2770
|
+
/**
|
|
2771
|
+
* Creates a {@link RefCountedRegistry}.
|
|
2772
|
+
*
|
|
2773
|
+
* @param activate - Wires `key` and returns its teardown. Called on the first
|
|
2774
|
+
* registration of each key.
|
|
2775
|
+
*/
|
|
2776
|
+
function createRefCountedRegistry(activate) {
|
|
2777
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2778
|
+
return {
|
|
2779
|
+
dispose() {
|
|
2780
|
+
for (const entry of entries.values()) entry.dispose();
|
|
2781
|
+
entries.clear();
|
|
2782
|
+
},
|
|
2783
|
+
register(key, options) {
|
|
2784
|
+
let entry = entries.get(key);
|
|
2785
|
+
if (entry === void 0) {
|
|
2786
|
+
entry = {
|
|
2787
|
+
dispose: activate(key, options),
|
|
2788
|
+
holders: /* @__PURE__ */ new Set()
|
|
2789
|
+
};
|
|
2790
|
+
entries.set(key, entry);
|
|
2791
|
+
}
|
|
2792
|
+
const release = () => {
|
|
2793
|
+
const current = entries.get(key);
|
|
2794
|
+
if (current && current.holders.delete(release) && current.holders.size === 0) {
|
|
2795
|
+
entries.delete(key);
|
|
2796
|
+
current.dispose();
|
|
2797
|
+
}
|
|
2798
|
+
};
|
|
2799
|
+
entry.holders.add(release);
|
|
2800
|
+
return release;
|
|
2801
|
+
}
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
/**
|
|
2805
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2806
|
+
*
|
|
2807
|
+
* This source code is licensed under the MIT license found in the
|
|
2808
|
+
* LICENSE file in the root directory of this source tree.
|
|
2809
|
+
*
|
|
2810
|
+
*/
|
|
2811
|
+
/**
|
|
2812
|
+
* The typed event map for a given {@link EventTarget}. Falls back to the global
|
|
2813
|
+
* handlers map (rather than a permissive `Record<string, Event>`) so unknown
|
|
2814
|
+
* event names are rejected as typos. Shared by {@link registerEventListener}
|
|
2815
|
+
* and `registerEventListeners`; the former additionally has a `string` overload
|
|
2816
|
+
* as an escape hatch for non-standard names (e.g. the legacy `textInput`),
|
|
2817
|
+
* which the object form intentionally does not.
|
|
2818
|
+
*/
|
|
2819
|
+
/**
|
|
2820
|
+
* Add an event listener to `target` and return a function that removes it.
|
|
2821
|
+
*
|
|
2822
|
+
* This is a thin, strongly typed wrapper around
|
|
2823
|
+
* {@link EventTarget.addEventListener} that mirrors its overloads but returns a
|
|
2824
|
+
* dispose function instead of `void`. It removes the
|
|
2825
|
+
* `addEventListener`/`removeEventListener` boilerplate that every DOM
|
|
2826
|
+
* subscription would otherwise duplicate, and composes cleanly with
|
|
2827
|
+
* {@link mergeRegister} or as the return value of an effect.
|
|
2828
|
+
*
|
|
2829
|
+
* The same `options` value is forwarded to both `addEventListener` and
|
|
2830
|
+
* `removeEventListener` so that the `capture` flag always matches, which is
|
|
2831
|
+
* required for the listener to be removed correctly.
|
|
2832
|
+
*
|
|
2833
|
+
* @example
|
|
2834
|
+
* ```ts
|
|
2835
|
+
* // Returned directly from a React effect
|
|
2836
|
+
* useEffect(
|
|
2837
|
+
* () => registerEventListener(container, 'keydown', handler),
|
|
2838
|
+
* [container],
|
|
2839
|
+
* );
|
|
2840
|
+
* ```
|
|
2841
|
+
* @example
|
|
2842
|
+
* ```ts
|
|
2843
|
+
* // Composed with other teardown via mergeRegister
|
|
2844
|
+
* return mergeRegister(
|
|
2845
|
+
* registerEventListener(window, 'resize', onResize),
|
|
2846
|
+
* registerEventListener(document, 'selectionchange', onSelectionChange),
|
|
2847
|
+
* );
|
|
2848
|
+
* ```
|
|
2849
|
+
*
|
|
2850
|
+
* @param target - The {@link EventTarget} to subscribe to
|
|
2851
|
+
* @param type - The event type to listen for (e.g. `'keydown'`)
|
|
2852
|
+
* @param listener - The listener invoked when a matching event is dispatched
|
|
2853
|
+
* @param options - Options forwarded to `add`/`removeEventListener`
|
|
2854
|
+
* @returns A function that removes the listener when called
|
|
2855
|
+
*/
|
|
2856
|
+
function registerEventListener(target, type, listener, options) {
|
|
2857
|
+
target.addEventListener(type, listener, options);
|
|
2858
|
+
return target.removeEventListener.bind(target, type, listener, options);
|
|
2859
|
+
}
|
|
2746
2860
|
const PASS_THROUGH_COMMAND = Object.freeze({});
|
|
2747
2861
|
const ANDROID_COMPOSITION_LATENCY = 30;
|
|
2748
2862
|
const rootElementEvents = [
|
|
@@ -2763,28 +2877,12 @@ const rootElementEvents = [
|
|
|
2763
2877
|
["drop", PASS_THROUGH_COMMAND]
|
|
2764
2878
|
];
|
|
2765
2879
|
if (CAN_USE_BEFORE_INPUT) rootElementEvents.push(["beforeinput", (event, editor) => onBeforeInput(event, editor)]);
|
|
2766
|
-
let lastKeyDownTimeStamp = 0;
|
|
2767
|
-
let lastKeyCode = null;
|
|
2768
|
-
let lastBeforeInputInsertTextTimeStamp = 0;
|
|
2769
|
-
let unprocessedBeforeInputData = null;
|
|
2770
|
-
let isInsertTextAfterHandledSelectionCommand = false;
|
|
2771
|
-
let handledSelectionCommandTimeoutId = null;
|
|
2772
2880
|
const rootElementToDocument = /* @__PURE__ */ new WeakMap();
|
|
2773
2881
|
const documentRegistrations = /* @__PURE__ */ new WeakMap();
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
let isSafariEndingComposition = false;
|
|
2779
|
-
let safariEndCompositionEventData = "";
|
|
2780
|
-
let postDeleteSelectionToRestore = null;
|
|
2781
|
-
let collapsedSelectionFormat = [
|
|
2782
|
-
0,
|
|
2783
|
-
"",
|
|
2784
|
-
0,
|
|
2785
|
-
"root",
|
|
2786
|
-
0
|
|
2787
|
-
];
|
|
2882
|
+
const documentSelectionChange = createRefCountedRegistry((doc) => {
|
|
2883
|
+
doc.addEventListener("selectionchange", onDocumentSelectionChange);
|
|
2884
|
+
return () => doc.removeEventListener("selectionchange", onDocumentSelectionChange);
|
|
2885
|
+
});
|
|
2788
2886
|
function $shouldPreventDefaultAndInsertText(selection, domTargetRange, text, timeStamp, isBeforeInput, cachedDOMSelectionPoints) {
|
|
2789
2887
|
const anchor = selection.anchor;
|
|
2790
2888
|
const focus = selection.focus;
|
|
@@ -2800,16 +2898,17 @@ function $shouldPreventDefaultAndInsertText(selection, domTargetRange, text, tim
|
|
|
2800
2898
|
const anchorKey = anchor.key;
|
|
2801
2899
|
const backingAnchorElement = editor.getElementByKey(anchorKey);
|
|
2802
2900
|
const textLength = text.length;
|
|
2803
|
-
return anchorKey !== focus.key || !$isTextNode(anchorNode) || (!isBeforeInput && (!CAN_USE_BEFORE_INPUT || lastBeforeInputInsertTextTimeStamp < timeStamp + 50) || anchorNode.isDirty() && textLength < 2 || doesContainSurrogatePair(text)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || $isTokenOrSegmented(anchorNode) || anchorNode.isDirty() && textLength > 1 || (isBeforeInput || !CAN_USE_BEFORE_INPUT) && backingAnchorElement !== null && !anchorNode.isComposing() && domAnchorNode !== $getDOMTextNode(anchorNode, backingAnchorElement, editor) || domSelectionPoints !== null && domTargetRange !== null && (!domTargetRange.collapsed || domTargetRange.startContainer !== domSelectionPoints.anchorNode || domTargetRange.startOffset !== domSelectionPoints.anchorOffset) || !anchorNode.isComposing() && (anchorNode.getFormat() !== selection.format || anchorNode.getStyle() !== selection.style) || $shouldInsertTextAfterOrBeforeTextNode(selection, anchorNode);
|
|
2901
|
+
return anchorKey !== focus.key || !$isTextNode(anchorNode) || (!isBeforeInput && (!CAN_USE_BEFORE_INPUT || editor._inputState.lastBeforeInputInsertTextTimeStamp < timeStamp + 50) || anchorNode.isDirty() && textLength < 2 || doesContainSurrogatePair(text)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || $isTokenOrSegmented(anchorNode) || anchorNode.isDirty() && textLength > 1 || (isBeforeInput || !CAN_USE_BEFORE_INPUT) && backingAnchorElement !== null && !anchorNode.isComposing() && domAnchorNode !== $getDOMTextNode(anchorNode, backingAnchorElement, editor) || domSelectionPoints !== null && domTargetRange !== null && (!domTargetRange.collapsed || domTargetRange.startContainer !== domSelectionPoints.anchorNode || domTargetRange.startOffset !== domSelectionPoints.anchorOffset) || !anchorNode.isComposing() && (anchorNode.getFormat() !== selection.format || anchorNode.getStyle() !== selection.style) || $shouldInsertTextAfterOrBeforeTextNode(selection, anchorNode);
|
|
2804
2902
|
}
|
|
2805
2903
|
function shouldSkipSelectionChange(domNode, offset) {
|
|
2806
2904
|
return isDOMTextNode(domNode) && domNode.nodeValue !== null && offset !== 0 && offset !== domNode.nodeValue.length;
|
|
2807
2905
|
}
|
|
2808
2906
|
function onSelectionChange(domSelection, editor, isActive) {
|
|
2809
2907
|
const { anchorNode: anchorDOM, anchorOffset, focusNode: focusDOM, focusOffset } = getDOMSelectionPoints(domSelection, editor._rootElement);
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2908
|
+
const inputState = editor._inputState;
|
|
2909
|
+
if (inputState.isSelectionChangeFromDOMUpdate) {
|
|
2910
|
+
inputState.isSelectionChangeFromDOMUpdate = false;
|
|
2911
|
+
if (shouldSkipSelectionChange(anchorDOM, anchorOffset) && shouldSkipSelectionChange(focusDOM, focusOffset) && !inputState.postDeleteSelectionToRestore) return;
|
|
2813
2912
|
}
|
|
2814
2913
|
updateEditorSync(editor, () => {
|
|
2815
2914
|
if (!isActive) {
|
|
@@ -2818,15 +2917,15 @@ function onSelectionChange(domSelection, editor, isActive) {
|
|
|
2818
2917
|
}
|
|
2819
2918
|
if (!isSelectionWithinEditor(editor, anchorDOM, focusDOM)) return;
|
|
2820
2919
|
let selection = $getSelection();
|
|
2821
|
-
if (postDeleteSelectionToRestore && $isRangeSelection(selection) && selection.isCollapsed()) {
|
|
2920
|
+
if (inputState.postDeleteSelectionToRestore && $isRangeSelection(selection) && selection.isCollapsed()) {
|
|
2822
2921
|
const curAnchor = selection.anchor;
|
|
2823
|
-
const prevAnchor = postDeleteSelectionToRestore.anchor;
|
|
2922
|
+
const prevAnchor = inputState.postDeleteSelectionToRestore.anchor;
|
|
2824
2923
|
if (curAnchor.key === prevAnchor.key && curAnchor.offset === prevAnchor.offset + 1 || curAnchor.offset === 1 && prevAnchor.getNode().is(curAnchor.getNode().getPreviousSibling())) {
|
|
2825
|
-
selection = postDeleteSelectionToRestore.clone();
|
|
2924
|
+
selection = inputState.postDeleteSelectionToRestore.clone();
|
|
2826
2925
|
$setSelection(selection);
|
|
2827
2926
|
}
|
|
2828
2927
|
}
|
|
2829
|
-
postDeleteSelectionToRestore = null;
|
|
2928
|
+
inputState.postDeleteSelectionToRestore = null;
|
|
2830
2929
|
if ($isRangeSelection(selection)) {
|
|
2831
2930
|
const anchor = selection.anchor;
|
|
2832
2931
|
const anchorNode = anchor.getNode();
|
|
@@ -2834,7 +2933,7 @@ function onSelectionChange(domSelection, editor, isActive) {
|
|
|
2834
2933
|
if (domSelection.type === "Range" && anchorDOM === focusDOM) selection.dirty = true;
|
|
2835
2934
|
const windowEvent = getWindow(editor).event;
|
|
2836
2935
|
const currentTimeStamp = windowEvent ? windowEvent.timeStamp : performance.now();
|
|
2837
|
-
const
|
|
2936
|
+
const { format: lastFormat, style: lastStyle, offset: lastOffset, key: lastKey, timeStamp } = inputState.collapsedSelectionFormat;
|
|
2838
2937
|
const root = $getRoot();
|
|
2839
2938
|
const isRootTextContentEmpty = editor.isComposing() === false && root.getTextContent() === "";
|
|
2840
2939
|
if (currentTimeStamp < timeStamp + 200 && anchor.offset === lastOffset && anchor.key === lastKey) $updateSelectionFormatStyle(selection, lastFormat, lastStyle);
|
|
@@ -2912,7 +3011,7 @@ function onPointerDown(event, editor) {
|
|
|
2912
3011
|
const target = getComposedEventTarget(event);
|
|
2913
3012
|
const pointerType = event.pointerType;
|
|
2914
3013
|
if (isDOMNode(target) && pointerType !== "touch" && pointerType !== "pen" && event.button === 0) updateEditorSync(editor, () => {
|
|
2915
|
-
if (!isDOMCapturingSelection(target, editor)) isSelectionChangeFromMouseDown = true;
|
|
3014
|
+
if (!isDOMCapturingSelection(target, editor)) editor._inputState.isSelectionChangeFromMouseDown = true;
|
|
2916
3015
|
});
|
|
2917
3016
|
}
|
|
2918
3017
|
function getTargetRange(event) {
|
|
@@ -2922,6 +3021,7 @@ function getTargetRange(event) {
|
|
|
2922
3021
|
return targetRanges[0];
|
|
2923
3022
|
}
|
|
2924
3023
|
function $maybeMoveSelectionPastTrailingAcceptanceBoundary(insertedText) {
|
|
3024
|
+
const { lastKeyCode } = getActiveEditor()._inputState;
|
|
2925
3025
|
if (insertedText == null || insertedText.length <= 1 || lastKeyCode == null) return;
|
|
2926
3026
|
const characterToSearchFor = lastKeyCode.length === 1 ? lastKeyCode : lastKeyCode === "Enter" ? "\n" : lastKeyCode === "Tab" ? " " : null;
|
|
2927
3027
|
if (!characterToSearchFor) return;
|
|
@@ -2947,20 +3047,20 @@ function $maybeMoveSelectionPastTrailingAcceptanceBoundary(insertedText) {
|
|
|
2947
3047
|
function $canRemoveText(anchorNode, focusNode) {
|
|
2948
3048
|
return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !$isTokenOrTab(anchorNode) || !$isTokenOrTab(focusNode);
|
|
2949
3049
|
}
|
|
2950
|
-
function isPossiblyAndroidKeyPress(timeStamp) {
|
|
2951
|
-
return lastKeyCode === "MediaLast" && timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY;
|
|
3050
|
+
function isPossiblyAndroidKeyPress(inputState, timeStamp) {
|
|
3051
|
+
return inputState.lastKeyCode === "MediaLast" && timeStamp < inputState.lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY;
|
|
2952
3052
|
}
|
|
2953
|
-
function clearHandledSelectionCommandInsertText() {
|
|
2954
|
-
isInsertTextAfterHandledSelectionCommand = false;
|
|
2955
|
-
if (handledSelectionCommandTimeoutId !== null) {
|
|
2956
|
-
clearTimeout(handledSelectionCommandTimeoutId);
|
|
2957
|
-
handledSelectionCommandTimeoutId = null;
|
|
3053
|
+
function clearHandledSelectionCommandInsertText(inputState) {
|
|
3054
|
+
inputState.isInsertTextAfterHandledSelectionCommand = false;
|
|
3055
|
+
if (inputState.handledSelectionCommandTimeoutId !== null) {
|
|
3056
|
+
clearTimeout(inputState.handledSelectionCommandTimeoutId);
|
|
3057
|
+
inputState.handledSelectionCommandTimeoutId = null;
|
|
2958
3058
|
}
|
|
2959
3059
|
}
|
|
2960
|
-
function markHandledSelectionCommandInsertText() {
|
|
2961
|
-
clearHandledSelectionCommandInsertText();
|
|
2962
|
-
isInsertTextAfterHandledSelectionCommand = true;
|
|
2963
|
-
handledSelectionCommandTimeoutId = setTimeout(clearHandledSelectionCommandInsertText, 0);
|
|
3060
|
+
function markHandledSelectionCommandInsertText(inputState) {
|
|
3061
|
+
clearHandledSelectionCommandInsertText(inputState);
|
|
3062
|
+
inputState.isInsertTextAfterHandledSelectionCommand = true;
|
|
3063
|
+
inputState.handledSelectionCommandTimeoutId = setTimeout(() => clearHandledSelectionCommandInsertText(inputState), 0);
|
|
2964
3064
|
}
|
|
2965
3065
|
function registerDefaultCommandHandlers(editor) {
|
|
2966
3066
|
editor.registerCommand(BEFORE_INPUT_COMMAND, $handleBeforeInput, 0);
|
|
@@ -3002,9 +3102,10 @@ function $handleBeforeInput(event) {
|
|
|
3002
3102
|
const inputType = event.inputType;
|
|
3003
3103
|
const targetRange = getTargetRange(event);
|
|
3004
3104
|
const editor = getActiveEditor();
|
|
3105
|
+
const inputState = editor._inputState;
|
|
3005
3106
|
const selection = $getSelection();
|
|
3006
|
-
if (inputType === "insertText" && event.data && isInsertTextAfterHandledSelectionCommand) {
|
|
3007
|
-
clearHandledSelectionCommandInsertText();
|
|
3107
|
+
if (inputType === "insertText" && event.data && inputState.isInsertTextAfterHandledSelectionCommand) {
|
|
3108
|
+
clearHandledSelectionCommandInsertText(inputState);
|
|
3008
3109
|
event.preventDefault();
|
|
3009
3110
|
if ($isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
3010
3111
|
const point = selection.isBackward() ? selection.anchor : selection.focus;
|
|
@@ -3021,9 +3122,9 @@ function $handleBeforeInput(event) {
|
|
|
3021
3122
|
}
|
|
3022
3123
|
if ($isRangeSelection(selection)) {
|
|
3023
3124
|
const isSelectionAnchorSameAsFocus = selection.anchor.key === selection.focus.key;
|
|
3024
|
-
if (isPossiblyAndroidKeyPress(event.timeStamp) && editor.isComposing() && isSelectionAnchorSameAsFocus) {
|
|
3125
|
+
if (isPossiblyAndroidKeyPress(inputState, event.timeStamp) && editor.isComposing() && isSelectionAnchorSameAsFocus) {
|
|
3025
3126
|
$setCompositionKey(null);
|
|
3026
|
-
lastKeyDownTimeStamp = 0;
|
|
3127
|
+
inputState.lastKeyDownTimeStamp = 0;
|
|
3027
3128
|
setTimeout(() => {
|
|
3028
3129
|
updateEditorSync(editor, () => {
|
|
3029
3130
|
$setCompositionKey(null);
|
|
@@ -3056,8 +3157,8 @@ function $handleBeforeInput(event) {
|
|
|
3056
3157
|
dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true);
|
|
3057
3158
|
const selectionAfterDelete = $getSelection();
|
|
3058
3159
|
if (IS_ANDROID_CHROME && $isRangeSelection(selectionAfterDelete) && selectionAfterDelete.isCollapsed()) {
|
|
3059
|
-
postDeleteSelectionToRestore = selectionAfterDelete;
|
|
3060
|
-
setTimeout(() => postDeleteSelectionToRestore = null);
|
|
3160
|
+
inputState.postDeleteSelectionToRestore = selectionAfterDelete;
|
|
3161
|
+
setTimeout(() => inputState.postDeleteSelectionToRestore = null);
|
|
3061
3162
|
}
|
|
3062
3163
|
}
|
|
3063
3164
|
}
|
|
@@ -3066,9 +3167,9 @@ function $handleBeforeInput(event) {
|
|
|
3066
3167
|
}
|
|
3067
3168
|
if (!$isRangeSelection(selection)) return true;
|
|
3068
3169
|
const data = event.data;
|
|
3069
|
-
if (unprocessedBeforeInputData !== null) $updateSelectedTextFromDOM(false, editor, unprocessedBeforeInputData);
|
|
3070
|
-
if ((!selection.dirty || unprocessedBeforeInputData !== null) && selection.isCollapsed() && !$isRootNode(selection.anchor.getNode()) && targetRange !== null) selection.applyDOMRange(targetRange);
|
|
3071
|
-
unprocessedBeforeInputData = null;
|
|
3170
|
+
if (inputState.unprocessedBeforeInputData !== null) $updateSelectedTextFromDOM(false, editor, inputState.unprocessedBeforeInputData);
|
|
3171
|
+
if ((!selection.dirty || inputState.unprocessedBeforeInputData !== null) && selection.isCollapsed() && !$isRootNode(selection.anchor.getNode()) && targetRange !== null) selection.applyDOMRange(targetRange);
|
|
3172
|
+
inputState.unprocessedBeforeInputData = null;
|
|
3072
3173
|
const anchor = selection.anchor;
|
|
3073
3174
|
const focus = selection.focus;
|
|
3074
3175
|
const anchorNode = anchor.getNode();
|
|
@@ -3088,8 +3189,8 @@ function $handleBeforeInput(event) {
|
|
|
3088
3189
|
event.preventDefault();
|
|
3089
3190
|
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data);
|
|
3090
3191
|
$maybeMoveSelectionPastTrailingAcceptanceBoundary(data);
|
|
3091
|
-
} else unprocessedBeforeInputData = data;
|
|
3092
|
-
lastBeforeInputInsertTextTimeStamp = event.timeStamp;
|
|
3192
|
+
} else inputState.unprocessedBeforeInputData = data;
|
|
3193
|
+
inputState.lastBeforeInputInsertTextTimeStamp = event.timeStamp;
|
|
3093
3194
|
return true;
|
|
3094
3195
|
}
|
|
3095
3196
|
event.preventDefault();
|
|
@@ -3100,18 +3201,23 @@ function $handleBeforeInput(event) {
|
|
|
3100
3201
|
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
|
|
3101
3202
|
$maybeMoveSelectionPastTrailingAcceptanceBoundary((event.dataTransfer ? event.dataTransfer.getData("text/plain") : null) ?? event.data);
|
|
3102
3203
|
break;
|
|
3103
|
-
case "insertFromComposition":
|
|
3204
|
+
case "insertFromComposition": {
|
|
3205
|
+
const skipRedundantInsert = inputState.hadOrphanedCompositionEvents;
|
|
3206
|
+
inputState.hadOrphanedCompositionEvents = false;
|
|
3207
|
+
const prevCompositionKey = editor._compositionKey;
|
|
3104
3208
|
$setCompositionKey(null);
|
|
3105
|
-
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
|
|
3209
|
+
if (!skipRedundantInsert) dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
|
|
3210
|
+
$cleanupComposedSubclass(prevCompositionKey);
|
|
3106
3211
|
break;
|
|
3212
|
+
}
|
|
3107
3213
|
case "insertLineBreak":
|
|
3108
3214
|
$setCompositionKey(null);
|
|
3109
3215
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
|
|
3110
3216
|
break;
|
|
3111
3217
|
case "insertParagraph":
|
|
3112
3218
|
$setCompositionKey(null);
|
|
3113
|
-
if (isInsertLineBreak && !IS_IOS) {
|
|
3114
|
-
isInsertLineBreak = false;
|
|
3219
|
+
if (inputState.isInsertLineBreak && !IS_IOS) {
|
|
3220
|
+
inputState.isInsertLineBreak = false;
|
|
3115
3221
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
|
|
3116
3222
|
} else dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND, void 0);
|
|
3117
3223
|
break;
|
|
@@ -3170,14 +3276,16 @@ function $handleBeforeInput(event) {
|
|
|
3170
3276
|
}
|
|
3171
3277
|
function onInput(event, editor) {
|
|
3172
3278
|
event.stopPropagation();
|
|
3173
|
-
|
|
3279
|
+
const inputState = editor._inputState;
|
|
3280
|
+
clearHandledSelectionCommandInsertText(inputState);
|
|
3174
3281
|
updateEditorSync(editor, () => {
|
|
3175
3282
|
if (!isInputEventTargetingCapturedSelection(event, editor)) editor.dispatchCommand(INPUT_COMMAND, event);
|
|
3176
3283
|
}, { event });
|
|
3177
|
-
unprocessedBeforeInputData = null;
|
|
3284
|
+
inputState.unprocessedBeforeInputData = null;
|
|
3178
3285
|
}
|
|
3179
3286
|
function $handleInput(event) {
|
|
3180
3287
|
const editor = getActiveEditor();
|
|
3288
|
+
const inputState = editor._inputState;
|
|
3181
3289
|
const selection = $getSelection();
|
|
3182
3290
|
const data = event.data;
|
|
3183
3291
|
const targetRange = getTargetRange(event);
|
|
@@ -3185,11 +3293,20 @@ function $handleInput(event) {
|
|
|
3185
3293
|
if (data != null && $isRangeSelection(selection)) {
|
|
3186
3294
|
const domSelection = getDOMSelection(getWindow(editor));
|
|
3187
3295
|
const domSelectionPoints = domSelection !== null ? getDOMSelectionPoints(domSelection, editor._rootElement) : null;
|
|
3188
|
-
|
|
3296
|
+
const isOrphanedCompositionEnd = event.inputType === "insertCompositionText" && inputState.compositionPhase !== "ending-firefox" && !editor.isComposing();
|
|
3297
|
+
if (isOrphanedCompositionEnd) inputState.hadOrphanedCompositionEvents = true;
|
|
3298
|
+
const inputAnchorNode = selection.anchor.getNode();
|
|
3299
|
+
const isCompositionOnToken = event.inputType === "insertCompositionText" && inputState.compositionPhase !== "ending-firefox" && editor.isComposing() && $isTextNode(inputAnchorNode) && $isTokenOrSegmented(inputAnchorNode);
|
|
3300
|
+
if (!isOrphanedCompositionEnd && !isCompositionOnToken && $shouldPreventDefaultAndInsertText(selection, targetRange, data, event.timeStamp, false, domSelectionPoints)) {
|
|
3189
3301
|
handled = true;
|
|
3190
|
-
if (
|
|
3191
|
-
$onCompositionEndImpl(editor, data);
|
|
3192
|
-
|
|
3302
|
+
if (inputState.compositionPhase === "ending-firefox") {
|
|
3303
|
+
const tokenRedirected = $onCompositionEndImpl(editor, data);
|
|
3304
|
+
inputState.compositionPhase = "idle";
|
|
3305
|
+
if (tokenRedirected) {
|
|
3306
|
+
$addUpdateTag(COMPOSITION_END_TAG);
|
|
3307
|
+
$flushMutations();
|
|
3308
|
+
return true;
|
|
3309
|
+
}
|
|
3193
3310
|
}
|
|
3194
3311
|
const anchorNode = selection.anchor.getNode();
|
|
3195
3312
|
if (domSelection === null || domSelectionPoints === null) return true;
|
|
@@ -3204,17 +3321,17 @@ function $handleInput(event) {
|
|
|
3204
3321
|
selection._cachedIsBackward = null;
|
|
3205
3322
|
}
|
|
3206
3323
|
if (IS_ANDROID_CHROME && editor.isComposing()) {
|
|
3207
|
-
lastKeyDownTimeStamp = 0;
|
|
3324
|
+
inputState.lastKeyDownTimeStamp = 0;
|
|
3208
3325
|
$setCompositionKey(null);
|
|
3209
3326
|
}
|
|
3210
3327
|
}
|
|
3211
3328
|
}
|
|
3212
3329
|
if (!handled) {
|
|
3213
3330
|
$updateSelectedTextFromDOM(false, editor, data !== null ? data : void 0);
|
|
3214
|
-
if (
|
|
3331
|
+
if (inputState.compositionPhase === "ending-firefox") {
|
|
3215
3332
|
$onCompositionEndImpl(editor, data || void 0);
|
|
3216
3333
|
$addUpdateTag(COMPOSITION_END_TAG);
|
|
3217
|
-
|
|
3334
|
+
inputState.compositionPhase = "idle";
|
|
3218
3335
|
}
|
|
3219
3336
|
}
|
|
3220
3337
|
$flushMutations();
|
|
@@ -3225,21 +3342,45 @@ function onCompositionStart(event, editor) {
|
|
|
3225
3342
|
}
|
|
3226
3343
|
function $handleCompositionStart(event) {
|
|
3227
3344
|
const editor = getActiveEditor();
|
|
3345
|
+
const inputState = editor._inputState;
|
|
3228
3346
|
const selection = $getSelection();
|
|
3229
3347
|
if ($isRangeSelection(selection) && !editor.isComposing()) {
|
|
3348
|
+
inputState.compositionPhase = "composing";
|
|
3349
|
+
inputState.hadOrphanedCompositionEvents = false;
|
|
3230
3350
|
const anchor = selection.anchor;
|
|
3231
3351
|
const node = selection.anchor.getNode();
|
|
3232
3352
|
$setCompositionKey(anchor.key);
|
|
3233
3353
|
$addUpdateTag(COMPOSITION_START_TAG);
|
|
3234
|
-
if (event.timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY || anchor.type === "element" || !selection.isCollapsed() || node.getFormat() !== selection.format || $isTextNode(node) && node.getStyle() !== selection.style)
|
|
3354
|
+
if (event.timeStamp < inputState.lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY || anchor.type === "element" || !selection.isCollapsed() || !IS_ANDROID_CHROME && (node.getFormat() !== selection.format || $isTextNode(node) && node.getStyle() !== selection.style) || $isTextNode(node) && ($isTokenOrSegmented(node) || anchor.offset === 0 && !node.canInsertTextBefore() || anchor.offset === node.getTextContentSize() && !node.canInsertTextAfter())) {
|
|
3355
|
+
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, COMPOSITION_START_CHAR);
|
|
3356
|
+
const updatedSelection = $getSelection();
|
|
3357
|
+
if ($isRangeSelection(updatedSelection)) $setCompositionKey(updatedSelection.anchor.key);
|
|
3358
|
+
}
|
|
3235
3359
|
}
|
|
3236
3360
|
return true;
|
|
3237
3361
|
}
|
|
3238
3362
|
function $handleCompositionEnd(event) {
|
|
3239
|
-
|
|
3363
|
+
const editor = getActiveEditor();
|
|
3364
|
+
editor._inputState.compositionPhase = "idle";
|
|
3365
|
+
$onCompositionEndImpl(editor, event.data);
|
|
3240
3366
|
$addUpdateTag(COMPOSITION_END_TAG);
|
|
3241
3367
|
return true;
|
|
3242
3368
|
}
|
|
3369
|
+
function $cleanupComposedSubclass(compositionKey) {
|
|
3370
|
+
if (compositionKey === null) return;
|
|
3371
|
+
const composedNode = $getNodeByKey(compositionKey);
|
|
3372
|
+
if (!$isTextNode(composedNode) || composedNode.getType() === "text" || $isTokenOrSegmented(composedNode) || !composedNode.isAttached()) return;
|
|
3373
|
+
const sel = $getSelection();
|
|
3374
|
+
const offset = $isRangeSelection(sel) && sel.anchor.key === compositionKey ? sel.anchor.offset : null;
|
|
3375
|
+
const replacement = $createTextNode(composedNode.getTextContent());
|
|
3376
|
+
replacement.setFormat(composedNode.getFormat());
|
|
3377
|
+
replacement.setStyle(composedNode.getStyle());
|
|
3378
|
+
composedNode.replace(replacement);
|
|
3379
|
+
if (offset !== null) {
|
|
3380
|
+
const safeOffset = Math.min(offset, replacement.getTextContentSize());
|
|
3381
|
+
replacement.select(safeOffset, safeOffset);
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3243
3384
|
function $onCompositionEndImpl(editor, data) {
|
|
3244
3385
|
const compositionKey = editor._compositionKey;
|
|
3245
3386
|
$setCompositionKey(null);
|
|
@@ -3259,7 +3400,8 @@ function $onCompositionEndImpl(editor, data) {
|
|
|
3259
3400
|
}
|
|
3260
3401
|
$updateTextNodeFromDOMContent(node, textNode.nodeValue, anchorOffset, focusOffset, true);
|
|
3261
3402
|
}
|
|
3262
|
-
|
|
3403
|
+
$cleanupComposedSubclass(compositionKey);
|
|
3404
|
+
return false;
|
|
3263
3405
|
} else if (data[data.length - 1] === "\n") {
|
|
3264
3406
|
const selection = $getSelection();
|
|
3265
3407
|
if ($isRangeSelection(selection) || $isNodeSelection(selection)) {
|
|
@@ -3268,40 +3410,52 @@ function $onCompositionEndImpl(editor, data) {
|
|
|
3268
3410
|
selection.anchor.set(focus.key, focus.offset, focus.type);
|
|
3269
3411
|
}
|
|
3270
3412
|
dispatchCommand(editor, KEY_ENTER_COMMAND, null);
|
|
3271
|
-
|
|
3413
|
+
$cleanupComposedSubclass(compositionKey);
|
|
3414
|
+
return false;
|
|
3272
3415
|
}
|
|
3273
3416
|
}
|
|
3417
|
+
const node = $getNodeByKey(compositionKey);
|
|
3418
|
+
if (node !== null && $isTextNode(node) && $isTokenOrSegmented(node)) {
|
|
3419
|
+
node.markDirty();
|
|
3420
|
+
const selection = $getSelection();
|
|
3421
|
+
const textLen = node.getTextContentSize();
|
|
3422
|
+
const offset = $isRangeSelection(selection) && selection.anchor.key === compositionKey ? selection.anchor.offset : textLen;
|
|
3423
|
+
node.select(offset, offset).insertText(data);
|
|
3424
|
+
return true;
|
|
3425
|
+
}
|
|
3274
3426
|
}
|
|
3275
3427
|
$updateSelectedTextFromDOM(true, editor, data);
|
|
3428
|
+
$cleanupComposedSubclass(compositionKey);
|
|
3429
|
+
return false;
|
|
3276
3430
|
}
|
|
3277
3431
|
function onCompositionEnd(event, editor) {
|
|
3278
|
-
|
|
3432
|
+
const inputState = editor._inputState;
|
|
3433
|
+
if (IS_FIREFOX) inputState.compositionPhase = "ending-firefox";
|
|
3279
3434
|
else if (!IS_IOS && (IS_SAFARI || IS_APPLE_WEBKIT)) {
|
|
3280
|
-
|
|
3281
|
-
|
|
3435
|
+
inputState.compositionPhase = "ending-safari";
|
|
3436
|
+
inputState.compositionEndData = event.data;
|
|
3282
3437
|
} else dispatchCommand(editor, COMPOSITION_END_COMMAND, event);
|
|
3283
3438
|
}
|
|
3284
3439
|
function onKeyDown(event, editor) {
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3440
|
+
const inputState = editor._inputState;
|
|
3441
|
+
inputState.lastKeyDownTimeStamp = event.timeStamp;
|
|
3442
|
+
inputState.lastKeyCode = event.key;
|
|
3443
|
+
if (event.key !== "Backspace") clearHandledSelectionCommandInsertText(inputState);
|
|
3288
3444
|
if (editor.isComposing()) return;
|
|
3289
3445
|
dispatchCommand(editor, KEY_DOWN_COMMAND, event);
|
|
3290
3446
|
}
|
|
3291
3447
|
function $handleKeyDown(event) {
|
|
3292
3448
|
const editor = getActiveEditor();
|
|
3449
|
+
const inputState = editor._inputState;
|
|
3293
3450
|
if (event.key == null) return true;
|
|
3294
|
-
if (
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
}
|
|
3303
|
-
isSafariEndingComposition = false;
|
|
3304
|
-
safariEndCompositionEventData = "";
|
|
3451
|
+
if (inputState.compositionPhase === "ending-safari") {
|
|
3452
|
+
const isBack = isBackspace(event);
|
|
3453
|
+
if (isBack) updateEditorSync(editor, () => {
|
|
3454
|
+
$onCompositionEndImpl(editor, inputState.compositionEndData);
|
|
3455
|
+
});
|
|
3456
|
+
inputState.compositionPhase = "idle";
|
|
3457
|
+
inputState.compositionEndData = "";
|
|
3458
|
+
if (isBack) return true;
|
|
3305
3459
|
}
|
|
3306
3460
|
if (isMoveForward(event)) dispatchCommand(editor, KEY_ARROW_RIGHT_COMMAND, event);
|
|
3307
3461
|
else if (isMoveToEnd(event)) dispatchCommand(editor, MOVE_TO_END, event);
|
|
@@ -3310,18 +3464,18 @@ function $handleKeyDown(event) {
|
|
|
3310
3464
|
else if (isMoveUp(event)) dispatchCommand(editor, KEY_ARROW_UP_COMMAND, event);
|
|
3311
3465
|
else if (isMoveDown(event)) dispatchCommand(editor, KEY_ARROW_DOWN_COMMAND, event);
|
|
3312
3466
|
else if (isLineBreak(event)) {
|
|
3313
|
-
isInsertLineBreak = true;
|
|
3467
|
+
inputState.isInsertLineBreak = true;
|
|
3314
3468
|
dispatchCommand(editor, KEY_ENTER_COMMAND, event);
|
|
3315
3469
|
} else if (isSpace(event)) dispatchCommand(editor, KEY_SPACE_COMMAND, event);
|
|
3316
3470
|
else if (isOpenLineBreak(event)) {
|
|
3317
3471
|
event.preventDefault();
|
|
3318
|
-
isInsertLineBreak = true;
|
|
3472
|
+
inputState.isInsertLineBreak = true;
|
|
3319
3473
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, true);
|
|
3320
3474
|
} else if (isParagraph(event)) {
|
|
3321
|
-
isInsertLineBreak = false;
|
|
3475
|
+
inputState.isInsertLineBreak = false;
|
|
3322
3476
|
dispatchCommand(editor, KEY_ENTER_COMMAND, event);
|
|
3323
3477
|
} else if (isDeleteBackward(event)) if (isBackspace(event)) {
|
|
3324
|
-
if (dispatchCommand(editor, KEY_BACKSPACE_COMMAND, event)) markHandledSelectionCommandInsertText();
|
|
3478
|
+
if (dispatchCommand(editor, KEY_BACKSPACE_COMMAND, event)) markHandledSelectionCommandInsertText(inputState);
|
|
3325
3479
|
} else {
|
|
3326
3480
|
event.preventDefault();
|
|
3327
3481
|
dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true);
|
|
@@ -3364,7 +3518,7 @@ function $handleKeyDown(event) {
|
|
|
3364
3518
|
const prevSelection = editor._editorState._selection;
|
|
3365
3519
|
if (isSelectAll(event)) {
|
|
3366
3520
|
event.preventDefault();
|
|
3367
|
-
if (dispatchCommand(editor, SELECT_ALL_COMMAND, event)) markHandledSelectionCommandInsertText();
|
|
3521
|
+
if (dispatchCommand(editor, SELECT_ALL_COMMAND, event)) markHandledSelectionCommandInsertText(inputState);
|
|
3368
3522
|
} else if (prevSelection !== null && !$isRangeSelection(prevSelection)) {
|
|
3369
3523
|
if (isCopy(event)) {
|
|
3370
3524
|
event.preventDefault();
|
|
@@ -3393,8 +3547,8 @@ function onDocumentSelectionChange(event) {
|
|
|
3393
3547
|
const ownerDocument = getDOMOwnerDocument(event.target);
|
|
3394
3548
|
let nextActiveEditor = null;
|
|
3395
3549
|
let resolvedAnchorNode = null;
|
|
3550
|
+
const registration = ownerDocument !== null ? documentRegistrations.get(ownerDocument) : void 0;
|
|
3396
3551
|
if (ownerDocument !== null) {
|
|
3397
|
-
const registration = documentRegistrations.get(ownerDocument);
|
|
3398
3552
|
if (registration !== void 0) {
|
|
3399
3553
|
const editorsForDoc = registration.editors;
|
|
3400
3554
|
let hasShadow = registration.hasShadowEditor;
|
|
@@ -3443,8 +3597,8 @@ function onDocumentSelectionChange(event) {
|
|
|
3443
3597
|
}
|
|
3444
3598
|
}
|
|
3445
3599
|
if (nextActiveEditor === null) return;
|
|
3446
|
-
if (isSelectionChangeFromMouseDown) {
|
|
3447
|
-
isSelectionChangeFromMouseDown = false;
|
|
3600
|
+
if (nextActiveEditor._inputState.isSelectionChangeFromMouseDown) {
|
|
3601
|
+
if (registration !== void 0) for (const ed of registration.editors) ed._inputState.isSelectionChangeFromMouseDown = false;
|
|
3448
3602
|
updateEditorSync(nextActiveEditor, () => {
|
|
3449
3603
|
const lastSelection = $getPreviousSelection();
|
|
3450
3604
|
const domAnchorNode = resolvedAnchorNode ?? getDOMSelectionPoints(domSelection, nextActiveEditor._rootElement).anchorNode;
|
|
@@ -3475,17 +3629,15 @@ function addRootElementEvents(rootElement, editor) {
|
|
|
3475
3629
|
if (registration === void 0) {
|
|
3476
3630
|
registration = {
|
|
3477
3631
|
editors: /* @__PURE__ */ new Set(),
|
|
3478
|
-
hasShadowEditor: void 0
|
|
3479
|
-
rootElementCount: 0
|
|
3632
|
+
hasShadowEditor: void 0
|
|
3480
3633
|
};
|
|
3481
3634
|
documentRegistrations.set(doc, registration);
|
|
3482
3635
|
}
|
|
3483
|
-
if (registration.rootElementCount < 1) doc.addEventListener("selectionchange", onDocumentSelectionChange);
|
|
3484
|
-
registration.rootElementCount += 1;
|
|
3485
3636
|
registration.editors.add(editor);
|
|
3486
3637
|
registration.hasShadowEditor = void 0;
|
|
3487
3638
|
rootElement.__lexicalEditor = editor;
|
|
3488
3639
|
const removeHandles = getRootElementRemoveHandles(rootElement);
|
|
3640
|
+
removeHandles.push(documentSelectionChange.register(doc));
|
|
3489
3641
|
for (let i = 0; i < rootElementEvents.length; i++) {
|
|
3490
3642
|
const [eventName, onEvent] = rootElementEvents[i];
|
|
3491
3643
|
const eventHandler = typeof onEvent === "function" ? (event) => {
|
|
@@ -3508,10 +3660,7 @@ function addRootElementEvents(rootElement, editor) {
|
|
|
3508
3660
|
case "drop": return isEditable && dispatchCommand(editor, DROP_COMMAND, event);
|
|
3509
3661
|
}
|
|
3510
3662
|
};
|
|
3511
|
-
|
|
3512
|
-
removeHandles.push(() => {
|
|
3513
|
-
rootElement.removeEventListener(eventName, eventHandler);
|
|
3514
|
-
});
|
|
3663
|
+
removeHandles.push(registerEventListener(rootElement, eventName, eventHandler));
|
|
3515
3664
|
}
|
|
3516
3665
|
}
|
|
3517
3666
|
const rootElementNotRegisteredWarning = warnOnlyOnce("Root element not registered");
|
|
@@ -3526,11 +3675,7 @@ function removeRootElementEvents(rootElement) {
|
|
|
3526
3675
|
rootElementNotRegisteredWarning();
|
|
3527
3676
|
return;
|
|
3528
3677
|
}
|
|
3529
|
-
const newCount = registration.rootElementCount - 1;
|
|
3530
|
-
if (!(newCount >= 0)) formatDevErrorMessage(`Root element count less than 0`);
|
|
3531
3678
|
rootElementToDocument.delete(rootElement);
|
|
3532
|
-
registration.rootElementCount = newCount;
|
|
3533
|
-
if (newCount === 0) doc.removeEventListener("selectionchange", onDocumentSelectionChange);
|
|
3534
3679
|
const editor = getEditorPropertyFromDOMNode(rootElement);
|
|
3535
3680
|
if (isLexicalEditor(editor)) {
|
|
3536
3681
|
cleanActiveNestedEditorsMap(editor);
|
|
@@ -3549,17 +3694,19 @@ function cleanActiveNestedEditorsMap(editor) {
|
|
|
3549
3694
|
if (activeNestedEditorsMap.get(rootEditorKey) === editor) activeNestedEditorsMap.delete(rootEditorKey);
|
|
3550
3695
|
} else activeNestedEditorsMap.delete(editor._key);
|
|
3551
3696
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3697
|
+
/** @internal */
|
|
3698
|
+
function markSelectionChangeFromDOMUpdate(editor) {
|
|
3699
|
+
editor._inputState.isSelectionChangeFromDOMUpdate = true;
|
|
3554
3700
|
}
|
|
3555
|
-
|
|
3556
|
-
|
|
3701
|
+
/** @internal */
|
|
3702
|
+
function markCollapsedSelectionFormat(editor, format, style, offset, key, timeStamp) {
|
|
3703
|
+
editor._inputState.collapsedSelectionFormat = {
|
|
3557
3704
|
format,
|
|
3558
|
-
style,
|
|
3559
|
-
offset,
|
|
3560
3705
|
key,
|
|
3706
|
+
offset,
|
|
3707
|
+
style,
|
|
3561
3708
|
timeStamp
|
|
3562
|
-
|
|
3709
|
+
};
|
|
3563
3710
|
}
|
|
3564
3711
|
/**
|
|
3565
3712
|
* The base type for all serialized nodes
|
|
@@ -4215,8 +4362,7 @@ var LexicalNode = class {
|
|
|
4215
4362
|
* @param targetNode - the would-be child node.
|
|
4216
4363
|
*/
|
|
4217
4364
|
isParentOf(targetNode) {
|
|
4218
|
-
|
|
4219
|
-
return result !== null && result.type === "ancestor";
|
|
4365
|
+
return $hasAncestor(targetNode, this);
|
|
4220
4366
|
}
|
|
4221
4367
|
/**
|
|
4222
4368
|
* Returns a list of nodes that are between this node and
|
|
@@ -5001,7 +5147,7 @@ function $setTextContent(nextText, dom, node) {
|
|
|
5001
5147
|
const slot = $getEditorDOMRenderConfig(editor).$getDOMSlot(node, dom, editor);
|
|
5002
5148
|
const firstChild = slot.getFirstChild();
|
|
5003
5149
|
if (firstChild === null || firstChild.nodeType !== Node.TEXT_NODE) {
|
|
5004
|
-
slot.insertChild(
|
|
5150
|
+
slot.insertChild($getDocument().createTextNode(text));
|
|
5005
5151
|
return;
|
|
5006
5152
|
}
|
|
5007
5153
|
const textChild = firstChild;
|
|
@@ -5018,11 +5164,14 @@ function $createTextInnerDOM(innerDOM, node, innerTag, format, text, config) {
|
|
|
5018
5164
|
const textClassNames = config.theme.text;
|
|
5019
5165
|
if (textClassNames !== void 0) setTextThemeClassNames(innerTag, 0, format, innerDOM, textClassNames);
|
|
5020
5166
|
}
|
|
5021
|
-
function wrapElementWith(element, tag) {
|
|
5022
|
-
const el =
|
|
5167
|
+
function $wrapElementWith(element, tag) {
|
|
5168
|
+
const el = $getDocument().createElement(tag);
|
|
5023
5169
|
el.appendChild(element);
|
|
5024
5170
|
return el;
|
|
5025
5171
|
}
|
|
5172
|
+
function $isInlineFormattable(node) {
|
|
5173
|
+
return node != null && node.__isInlineFormattable === true;
|
|
5174
|
+
}
|
|
5026
5175
|
/** @noInheritDoc */
|
|
5027
5176
|
var TextNode = class TextNode extends LexicalNode {
|
|
5028
5177
|
/** @internal */
|
|
@@ -5035,6 +5184,10 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5035
5184
|
__mode;
|
|
5036
5185
|
/** @internal */
|
|
5037
5186
|
__detail;
|
|
5187
|
+
/** @internal */
|
|
5188
|
+
get __isInlineFormattable() {
|
|
5189
|
+
return true;
|
|
5190
|
+
}
|
|
5038
5191
|
static getType() {
|
|
5039
5192
|
return "text";
|
|
5040
5193
|
}
|
|
@@ -5082,7 +5235,8 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5082
5235
|
* @returns TextModeType.
|
|
5083
5236
|
*/
|
|
5084
5237
|
getMode() {
|
|
5085
|
-
|
|
5238
|
+
const self = this.getLatest();
|
|
5239
|
+
return TEXT_TYPE_TO_MODE[self.__mode];
|
|
5086
5240
|
}
|
|
5087
5241
|
/**
|
|
5088
5242
|
* Returns the styles currently applied to the node. This is analogous to CSSText in the DOM.
|
|
@@ -5191,11 +5345,11 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5191
5345
|
const outerTag = getElementOuterTag(this, format);
|
|
5192
5346
|
const innerTag = getElementInnerTag(this, format);
|
|
5193
5347
|
const tag = outerTag === null ? innerTag : outerTag;
|
|
5194
|
-
const dom =
|
|
5348
|
+
const dom = $getDocument().createElement(tag);
|
|
5195
5349
|
let innerDOM = dom;
|
|
5196
5350
|
if (this.hasFormat("code")) dom.setAttribute("spellcheck", "false");
|
|
5197
5351
|
if (outerTag !== null) {
|
|
5198
|
-
innerDOM =
|
|
5352
|
+
innerDOM = $getDocument().createElement(innerTag);
|
|
5199
5353
|
dom.appendChild(innerDOM);
|
|
5200
5354
|
}
|
|
5201
5355
|
const text = this.__text;
|
|
@@ -5216,7 +5370,7 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5216
5370
|
if (prevOuterTag === nextOuterTag && prevInnerTag !== nextInnerTag) {
|
|
5217
5371
|
const prevInnerDOM = dom.firstChild;
|
|
5218
5372
|
if (prevInnerDOM == null) formatDevErrorMessage(`updateDOM: prevInnerDOM is null or undefined`);
|
|
5219
|
-
const nextInnerDOM =
|
|
5373
|
+
const nextInnerDOM = $getDocument().createElement(nextInnerTag);
|
|
5220
5374
|
$createTextInnerDOM(nextInnerDOM, this, nextInnerTag, nextFormat, nextText, config);
|
|
5221
5375
|
dom.replaceChild(nextInnerDOM, prevInnerDOM);
|
|
5222
5376
|
return false;
|
|
@@ -5301,10 +5455,10 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5301
5455
|
if (this.hasFormat("lowercase")) element.style.textTransform = "lowercase";
|
|
5302
5456
|
else if (this.hasFormat("uppercase")) element.style.textTransform = "uppercase";
|
|
5303
5457
|
else if (this.hasFormat("capitalize")) element.style.textTransform = "capitalize";
|
|
5304
|
-
if (this.hasFormat("bold")) element = wrapElementWith(element, "b");
|
|
5305
|
-
if (this.hasFormat("italic")) element = wrapElementWith(element, "i");
|
|
5306
|
-
if (this.hasFormat("strikethrough")) element = wrapElementWith(element, "s");
|
|
5307
|
-
if (this.hasFormat("underline")) element = wrapElementWith(element, "u");
|
|
5458
|
+
if (this.hasFormat("bold")) element = $wrapElementWith(element, "b");
|
|
5459
|
+
if (this.hasFormat("italic")) element = $wrapElementWith(element, "i");
|
|
5460
|
+
if (this.hasFormat("strikethrough")) element = $wrapElementWith(element, "s");
|
|
5461
|
+
if (this.hasFormat("underline")) element = $wrapElementWith(element, "u");
|
|
5308
5462
|
return { element };
|
|
5309
5463
|
}
|
|
5310
5464
|
exportJSON() {
|
|
@@ -5398,6 +5552,12 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5398
5552
|
/**
|
|
5399
5553
|
* Sets the mode of the node.
|
|
5400
5554
|
*
|
|
5555
|
+
* Note: during IME composition, a segmented TextNode may be temporarily
|
|
5556
|
+
* switched to normal mode to preserve the DOM element that the browser's
|
|
5557
|
+
* composition tracker is bound to. Subclass transforms or method overrides
|
|
5558
|
+
* that assume the node is always in segmented mode should account for this
|
|
5559
|
+
* transient state.
|
|
5560
|
+
*
|
|
5401
5561
|
* @returns this TextNode.
|
|
5402
5562
|
*/
|
|
5403
5563
|
setMode(type) {
|
|
@@ -5758,7 +5918,7 @@ function applyTextFormatFromStyle(style, shouldApply) {
|
|
|
5758
5918
|
const hasUnderlineTextDecoration = textDecoration.includes("underline");
|
|
5759
5919
|
const verticalAlign = style.verticalAlign;
|
|
5760
5920
|
return (lexicalNode) => {
|
|
5761
|
-
if (!$isTextNode(lexicalNode)) return lexicalNode;
|
|
5921
|
+
if (!$isTextNode(lexicalNode) && !$isInlineFormattable(lexicalNode)) return lexicalNode;
|
|
5762
5922
|
if (hasBoldFontWeight && !lexicalNode.hasFormat("bold")) lexicalNode.toggleFormat("bold");
|
|
5763
5923
|
if (hasLinethroughTextDecoration && !lexicalNode.hasFormat("strikethrough")) lexicalNode.toggleFormat("strikethrough");
|
|
5764
5924
|
if (hasItalicFontStyle && !lexicalNode.hasFormat("italic")) lexicalNode.toggleFormat("italic");
|
|
@@ -6026,8 +6186,17 @@ var NodeSelection = class NodeSelection {
|
|
|
6026
6186
|
$setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
|
|
6027
6187
|
}
|
|
6028
6188
|
for (const node of nodes) node.remove();
|
|
6189
|
+
$ensureRootHasParagraph();
|
|
6029
6190
|
}
|
|
6030
6191
|
};
|
|
6192
|
+
function $ensureRootHasParagraph() {
|
|
6193
|
+
const root = $getRoot();
|
|
6194
|
+
if (root.isEmpty()) {
|
|
6195
|
+
const paragraph = $createParagraphNode();
|
|
6196
|
+
root.append(paragraph);
|
|
6197
|
+
paragraph.select();
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6031
6200
|
function $isRangeSelection(x) {
|
|
6032
6201
|
return x instanceof RangeSelection;
|
|
6033
6202
|
}
|
|
@@ -6207,11 +6376,11 @@ var RangeSelection = class RangeSelection {
|
|
|
6207
6376
|
this.dirty = true;
|
|
6208
6377
|
}
|
|
6209
6378
|
/**
|
|
6210
|
-
* Returns whether the provided TextFormatType is present on the Selection. This will be true if
|
|
6211
|
-
*
|
|
6379
|
+
* Returns whether the provided TextFormatType is present on the Selection. This will be true if all text nodes in the Selection
|
|
6380
|
+
* have the specified format.
|
|
6212
6381
|
*
|
|
6213
6382
|
* @param type the TextFormatType to check for.
|
|
6214
|
-
* @returns true if the provided format is currently toggled on
|
|
6383
|
+
* @returns true if the provided format is currently toggled on the Selection, false otherwise.
|
|
6215
6384
|
*/
|
|
6216
6385
|
hasFormat(type) {
|
|
6217
6386
|
const formatFlag = TEXT_TYPE_TO_FORMAT[type];
|
|
@@ -6288,12 +6457,14 @@ var RangeSelection = class RangeSelection {
|
|
|
6288
6457
|
this.insertText(text);
|
|
6289
6458
|
return;
|
|
6290
6459
|
}
|
|
6291
|
-
} else if (firstNode.isSegmented() && startOffset !== firstNodeTextLength)
|
|
6460
|
+
} else if (firstNode.isSegmented() && startOffset !== firstNodeTextLength) if ($getCompositionKey() !== null) firstNode = firstNode.setMode("normal").setFormat(format).setStyle(style);
|
|
6461
|
+
else {
|
|
6292
6462
|
const textNode = $createTextNode(firstNode.getTextContent());
|
|
6293
6463
|
textNode.setFormat(format);
|
|
6294
6464
|
firstNode.replace(textNode);
|
|
6295
6465
|
firstNode = textNode;
|
|
6296
|
-
}
|
|
6466
|
+
}
|
|
6467
|
+
else if (!this.isCollapsed() && text !== "") {
|
|
6297
6468
|
const lastNodeParent = lastNode.getParent();
|
|
6298
6469
|
if (!firstNodeParent.canInsertTextBefore() || !firstNodeParent.canInsertTextAfter() || $isElementNode(lastNodeParent) && (!lastNodeParent.canInsertTextBefore() || !lastNodeParent.canInsertTextAfter())) {
|
|
6299
6470
|
this.insertText("");
|
|
@@ -6366,7 +6537,10 @@ var RangeSelection = class RangeSelection {
|
|
|
6366
6537
|
lastNode.replace(textNode);
|
|
6367
6538
|
lastNode = textNode;
|
|
6368
6539
|
}
|
|
6369
|
-
if (!$isRootNode(endPoint.getNode()) && endPoint.type === "text")
|
|
6540
|
+
if (!$isRootNode(endPoint.getNode()) && endPoint.type === "text") {
|
|
6541
|
+
if (!$isTextNode(lastNode)) formatDevErrorMessage(`insertText: lastNode is not a TextNode`);
|
|
6542
|
+
lastNode = lastNode.spliceText(0, endOffset, "");
|
|
6543
|
+
}
|
|
6370
6544
|
markedNodeKeysForKeep.add(lastNode.__key);
|
|
6371
6545
|
} else {
|
|
6372
6546
|
const lastNodeParent = lastNode.getParentOrThrow();
|
|
@@ -6440,79 +6614,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6440
6614
|
* @param alignWithFormat a 32-bit integer representing formatting flags to align with.
|
|
6441
6615
|
*/
|
|
6442
6616
|
formatText(formatType, alignWithFormat = null) {
|
|
6443
|
-
|
|
6444
|
-
this.toggleFormat(formatType);
|
|
6445
|
-
$setCompositionKey(null);
|
|
6446
|
-
return;
|
|
6447
|
-
}
|
|
6448
|
-
const selectedNodes = this.getNodes();
|
|
6449
|
-
const selectedTextNodes = [];
|
|
6450
|
-
for (const selectedNode of selectedNodes) if ($isTextNode(selectedNode)) selectedTextNodes.push(selectedNode);
|
|
6451
|
-
const applyFormatToElements = (alignWith) => {
|
|
6452
|
-
selectedNodes.forEach((node) => {
|
|
6453
|
-
if ($isElementNode(node)) {
|
|
6454
|
-
const newFormat = node.getFormatFlags(formatType, alignWith);
|
|
6455
|
-
node.setTextFormat(newFormat);
|
|
6456
|
-
}
|
|
6457
|
-
});
|
|
6458
|
-
};
|
|
6459
|
-
const selectedTextNodesLength = selectedTextNodes.length;
|
|
6460
|
-
if (selectedTextNodesLength === 0) {
|
|
6461
|
-
this.toggleFormat(formatType);
|
|
6462
|
-
$setCompositionKey(null);
|
|
6463
|
-
applyFormatToElements(alignWithFormat);
|
|
6464
|
-
return;
|
|
6465
|
-
}
|
|
6466
|
-
const anchor = this.anchor;
|
|
6467
|
-
const focus = this.focus;
|
|
6468
|
-
const isBackward = this.isBackward();
|
|
6469
|
-
const startPoint = isBackward ? focus : anchor;
|
|
6470
|
-
const endPoint = isBackward ? anchor : focus;
|
|
6471
|
-
let firstIndex = 0;
|
|
6472
|
-
let firstNode = selectedTextNodes[0];
|
|
6473
|
-
let startOffset = startPoint.type === "element" ? 0 : startPoint.offset;
|
|
6474
|
-
if (startPoint.type === "text" && startOffset === firstNode.getTextContentSize()) {
|
|
6475
|
-
firstIndex = 1;
|
|
6476
|
-
firstNode = selectedTextNodes[1];
|
|
6477
|
-
startOffset = 0;
|
|
6478
|
-
}
|
|
6479
|
-
if (firstNode == null) return;
|
|
6480
|
-
const firstNextFormat = firstNode.getFormatFlags(formatType, alignWithFormat);
|
|
6481
|
-
applyFormatToElements(firstNextFormat);
|
|
6482
|
-
const lastIndex = selectedTextNodesLength - 1;
|
|
6483
|
-
let lastNode = selectedTextNodes[lastIndex];
|
|
6484
|
-
const endOffset = endPoint.type === "text" ? endPoint.offset : lastNode.getTextContentSize();
|
|
6485
|
-
if (firstNode.is(lastNode)) {
|
|
6486
|
-
if (startOffset === endOffset) return;
|
|
6487
|
-
if ($isTokenOrSegmented(firstNode) || startOffset === 0 && endOffset === firstNode.getTextContentSize()) firstNode.setFormat(firstNextFormat);
|
|
6488
|
-
else {
|
|
6489
|
-
const splitNodes = firstNode.splitText(startOffset, endOffset);
|
|
6490
|
-
const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
|
|
6491
|
-
replacement.setFormat(firstNextFormat);
|
|
6492
|
-
if (startPoint.type === "text") startPoint.set(replacement.__key, 0, "text");
|
|
6493
|
-
if (endPoint.type === "text") endPoint.set(replacement.__key, endOffset - startOffset, "text");
|
|
6494
|
-
}
|
|
6495
|
-
this.format = firstNextFormat;
|
|
6496
|
-
return;
|
|
6497
|
-
}
|
|
6498
|
-
if (startOffset !== 0 && !$isTokenOrSegmented(firstNode)) {
|
|
6499
|
-
[, firstNode] = firstNode.splitText(startOffset);
|
|
6500
|
-
startOffset = 0;
|
|
6501
|
-
}
|
|
6502
|
-
firstNode.setFormat(firstNextFormat);
|
|
6503
|
-
const lastNextFormat = lastNode.getFormatFlags(formatType, firstNextFormat);
|
|
6504
|
-
if (endOffset > 0) {
|
|
6505
|
-
if (endOffset !== lastNode.getTextContentSize() && !$isTokenOrSegmented(lastNode)) [lastNode] = lastNode.splitText(endOffset);
|
|
6506
|
-
lastNode.setFormat(lastNextFormat);
|
|
6507
|
-
}
|
|
6508
|
-
for (let i = firstIndex + 1; i < lastIndex; i++) {
|
|
6509
|
-
const textNode = selectedTextNodes[i];
|
|
6510
|
-
const nextFormat = textNode.getFormatFlags(formatType, lastNextFormat);
|
|
6511
|
-
textNode.setFormat(nextFormat);
|
|
6512
|
-
}
|
|
6513
|
-
if (startPoint.type === "text") startPoint.set(firstNode.__key, startOffset, "text");
|
|
6514
|
-
if (endPoint.type === "text") endPoint.set(lastNode.__key, endOffset, "text");
|
|
6515
|
-
this.format = firstNextFormat | lastNextFormat;
|
|
6617
|
+
$formatText(this, formatType, alignWithFormat);
|
|
6516
6618
|
}
|
|
6517
6619
|
/**
|
|
6518
6620
|
* Attempts to "intelligently" insert an arbitrary list of Lexical nodes into the EditorState at the
|
|
@@ -6546,8 +6648,8 @@ var RangeSelection = class RangeSelection {
|
|
|
6546
6648
|
if (nodeToSelect !== null) nodeToSelect.selectEnd();
|
|
6547
6649
|
return;
|
|
6548
6650
|
}
|
|
6549
|
-
|
|
6550
|
-
|
|
6651
|
+
let firstNode = (this.isBackward() ? this.focus : this.anchor).getNode();
|
|
6652
|
+
let firstBlock = $findMatchingParent(firstNode, INTERNAL_$isBlock);
|
|
6551
6653
|
const last = nodes[nodes.length - 1];
|
|
6552
6654
|
if ($isElementNode(firstBlock) && "__language" in firstBlock) {
|
|
6553
6655
|
if ("__language" in nodes[0]) this.insertText(nodes[0].getTextContent());
|
|
@@ -6597,6 +6699,10 @@ var RangeSelection = class RangeSelection {
|
|
|
6597
6699
|
const blocks = blocksParent.getChildren();
|
|
6598
6700
|
const isMergeable = (node) => $isElementNode(node) && INTERNAL_$isBlock(node) && !node.isEmpty() && $isElementNode(firstBlock) && (!firstBlock.isEmpty() || firstBlock.canMergeWhenEmpty());
|
|
6599
6701
|
const insertedParagraph = !$isElementNode(firstBlock) || !firstBlock.isEmpty() ? this.insertParagraph() : null;
|
|
6702
|
+
if (insertedParagraph && !firstBlock.isAttached()) {
|
|
6703
|
+
firstNode = this.anchor.getNode();
|
|
6704
|
+
firstBlock = $findMatchingParent(firstNode, INTERNAL_$isBlock);
|
|
6705
|
+
}
|
|
6600
6706
|
const lastToInsert = blocks[blocks.length - 1];
|
|
6601
6707
|
let firstToInsert = blocks[0];
|
|
6602
6708
|
if (isMergeable(firstToInsert)) {
|
|
@@ -6725,21 +6831,37 @@ var RangeSelection = class RangeSelection {
|
|
|
6725
6831
|
const rootElement = editor._rootElement;
|
|
6726
6832
|
const focusNode = this.focus.getNode();
|
|
6727
6833
|
if (rootElement !== null && blockCursorElement !== null && $isElementNode(focusNode) && !focusNode.isInline() && !focusNode.canBeEmpty()) removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
|
|
6834
|
+
const focusKeyedDOM = getElementByKeyOrThrow(editor, this.focus.key);
|
|
6835
|
+
let nextFocusDOM = focusKeyedDOM;
|
|
6836
|
+
if (this.focus.type === "text") nextFocusDOM = $isTextNode(focusNode) ? $getDOMTextNode(focusNode, focusKeyedDOM, editor) : null;
|
|
6728
6837
|
if (this.dirty) {
|
|
6729
6838
|
const anchorKeyedDOM = getElementByKeyOrThrow(editor, this.anchor.key);
|
|
6730
|
-
const focusKeyedDOM = getElementByKeyOrThrow(editor, this.focus.key);
|
|
6731
6839
|
let nextAnchorDOM = anchorKeyedDOM;
|
|
6732
|
-
let nextFocusDOM = focusKeyedDOM;
|
|
6733
6840
|
if (this.anchor.type === "text") {
|
|
6734
6841
|
const node = this.anchor.getNode();
|
|
6735
6842
|
nextAnchorDOM = $isTextNode(node) ? $getDOMTextNode(node, anchorKeyedDOM, editor) : null;
|
|
6736
6843
|
}
|
|
6737
|
-
if (this.focus.type === "text") {
|
|
6738
|
-
const node = this.focus.getNode();
|
|
6739
|
-
nextFocusDOM = $isTextNode(node) ? $getDOMTextNode(node, focusKeyedDOM, editor) : null;
|
|
6740
|
-
}
|
|
6741
6844
|
if (nextAnchorDOM && nextFocusDOM) setDOMSelectionBaseAndExtent(domSelection, nextAnchorDOM, this.anchor.offset, nextFocusDOM, this.focus.offset);
|
|
6742
6845
|
}
|
|
6846
|
+
if (granularity === "character" && $isTextNode(focusNode) && focusNode.isUnmergeable()) {
|
|
6847
|
+
if (isBackward ? this.focus.offset === 0 : this.focus.offset === focusNode.getTextContentSize()) {
|
|
6848
|
+
const sibling = $getSiblingCaret(focusNode, isBackward ? "previous" : "next").getNodeAtCaret();
|
|
6849
|
+
if ($isTextNode(sibling)) if (collapse) {
|
|
6850
|
+
const sibKeyedDOM = editor.getElementByKey(sibling.getKey());
|
|
6851
|
+
const sibDOM = sibKeyedDOM ? $getDOMTextNode(sibling, sibKeyedDOM, editor) : null;
|
|
6852
|
+
if (sibDOM) {
|
|
6853
|
+
const sibOffset = isBackward ? sibDOM.length : 0;
|
|
6854
|
+
setDOMSelectionBaseAndExtent(domSelection, sibDOM, sibOffset, sibDOM, sibOffset);
|
|
6855
|
+
}
|
|
6856
|
+
} else {
|
|
6857
|
+
const sibLen = sibling.getTextContentSize();
|
|
6858
|
+
if (isBackward) this.focus.set(sibling.__key, sibLen - 1, "text");
|
|
6859
|
+
else this.focus.set(sibling.__key, 1, "text");
|
|
6860
|
+
this.dirty = true;
|
|
6861
|
+
return;
|
|
6862
|
+
}
|
|
6863
|
+
}
|
|
6864
|
+
}
|
|
6743
6865
|
moveNativeSelection(domSelection, alter, isBackward ? "backward" : "forward", granularity);
|
|
6744
6866
|
if (domSelection.rangeCount > 0) {
|
|
6745
6867
|
const composedRange = getComposedStaticRange(domSelection, editor._rootElement);
|
|
@@ -6749,23 +6871,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6749
6871
|
this.applyDOMRange(range);
|
|
6750
6872
|
this.dirty = true;
|
|
6751
6873
|
if (!collapse) {
|
|
6752
|
-
|
|
6753
|
-
const validNodes = [];
|
|
6754
|
-
let shrinkSelection = false;
|
|
6755
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
6756
|
-
const nextNode = nodes[i];
|
|
6757
|
-
if ($hasAncestor(nextNode, root)) validNodes.push(nextNode);
|
|
6758
|
-
else shrinkSelection = true;
|
|
6759
|
-
}
|
|
6760
|
-
if (shrinkSelection && validNodes.length > 0) if (isBackward) {
|
|
6761
|
-
const firstValidNode = validNodes[0];
|
|
6762
|
-
if ($isElementNode(firstValidNode)) firstValidNode.selectStart();
|
|
6763
|
-
else firstValidNode.getParentOrThrow().selectStart();
|
|
6764
|
-
} else {
|
|
6765
|
-
const lastValidNode = validNodes[validNodes.length - 1];
|
|
6766
|
-
if ($isElementNode(lastValidNode)) lastValidNode.selectEnd();
|
|
6767
|
-
else lastValidNode.getParentOrThrow().selectEnd();
|
|
6768
|
-
}
|
|
6874
|
+
$shrinkSelectionToRoot(this, isBackward, root);
|
|
6769
6875
|
if (!(composedRange ? domSelection.direction !== "backward" : domSelection.anchorNode === range.startContainer && domSelection.anchorOffset === range.startOffset)) $swapPoints(this);
|
|
6770
6876
|
}
|
|
6771
6877
|
}
|
|
@@ -6862,7 +6968,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6862
6968
|
}
|
|
6863
6969
|
}
|
|
6864
6970
|
const focus = this.focus;
|
|
6865
|
-
this
|
|
6971
|
+
$extendSelectionForDeletion(this, isBackward, "character");
|
|
6866
6972
|
if (!this.isCollapsed()) {
|
|
6867
6973
|
const focusNode = focus.type === "text" ? focus.getNode() : null;
|
|
6868
6974
|
anchorNode = anchor.type === "text" ? anchor.getNode() : null;
|
|
@@ -6890,6 +6996,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6890
6996
|
if (isBackward && !wasCollapsed && this.isCollapsed() && this.anchor.type === "element" && this.anchor.offset === 0) {
|
|
6891
6997
|
const anchorNode = this.anchor.getNode();
|
|
6892
6998
|
if (anchorNode.isEmpty() && $isRootNode(anchorNode.getParent()) && anchorNode.getPreviousSibling() === null) $collapseAtStart(this, anchorNode);
|
|
6999
|
+
$ensureRootHasParagraph();
|
|
6893
7000
|
}
|
|
6894
7001
|
}
|
|
6895
7002
|
/**
|
|
@@ -6905,9 +7012,12 @@ var RangeSelection = class RangeSelection {
|
|
|
6905
7012
|
this.deleteCharacter(isBackward);
|
|
6906
7013
|
return;
|
|
6907
7014
|
}
|
|
6908
|
-
if (this.isCollapsed()) this
|
|
7015
|
+
if (this.isCollapsed()) $extendSelectionForDeletion(this, isBackward, "lineboundary");
|
|
6909
7016
|
if (this.isCollapsed()) this.deleteCharacter(isBackward);
|
|
6910
|
-
else this.
|
|
7017
|
+
else if ($findMatchingParent(this.anchor.getNode(), INTERNAL_$isBlock) !== $findMatchingParent(this.focus.getNode(), INTERNAL_$isBlock)) {
|
|
7018
|
+
this.focus.set(this.anchor.key, this.anchor.offset, this.anchor.type);
|
|
7019
|
+
this.deleteCharacter(isBackward);
|
|
7020
|
+
} else this.removeText();
|
|
6911
7021
|
}
|
|
6912
7022
|
/**
|
|
6913
7023
|
* Performs one logical word deletion operation on the EditorState based on the current Selection.
|
|
@@ -6920,7 +7030,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6920
7030
|
const anchor = this.anchor;
|
|
6921
7031
|
const anchorNode = anchor.getNode();
|
|
6922
7032
|
if (this.forwardDeletion(anchor, anchorNode, isBackward)) return;
|
|
6923
|
-
this
|
|
7033
|
+
$extendSelectionForDeletion(this, isBackward, "word");
|
|
6924
7034
|
}
|
|
6925
7035
|
if (this.isCollapsed()) this.deleteCharacter(isBackward);
|
|
6926
7036
|
else this.removeText();
|
|
@@ -6944,6 +7054,124 @@ var RangeSelection = class RangeSelection {
|
|
|
6944
7054
|
function $isNodeSelection(x) {
|
|
6945
7055
|
return x instanceof NodeSelection;
|
|
6946
7056
|
}
|
|
7057
|
+
/**
|
|
7058
|
+
* Applies a pure bitmask transform to every formattable node in the selection
|
|
7059
|
+
* in a single traversal, splitting the first and last TextNodes as necessary
|
|
7060
|
+
* so that only the selected text is affected. Each node receives exactly one
|
|
7061
|
+
* `setFormat(applyFormat(getFormat()))` (ElementNodes use their textFormat).
|
|
7062
|
+
*
|
|
7063
|
+
* @param selection - the selection whose nodes should be formatted.
|
|
7064
|
+
* @param applyFormat - maps a node's current 32-bit format to its new format.
|
|
7065
|
+
*/
|
|
7066
|
+
function $updateTextFormat(selection, applyFormat) {
|
|
7067
|
+
if ($isNodeSelection(selection)) {
|
|
7068
|
+
for (const node of selection.getNodes()) if ($isInlineFormattable(node)) node.setFormat(applyFormat(node.getFormat()));
|
|
7069
|
+
return;
|
|
7070
|
+
}
|
|
7071
|
+
if (selection.isCollapsed()) {
|
|
7072
|
+
selection.setFormat(applyFormat(selection.format));
|
|
7073
|
+
$setCompositionKey(null);
|
|
7074
|
+
return;
|
|
7075
|
+
}
|
|
7076
|
+
const selectedTextNodes = [];
|
|
7077
|
+
for (const node of selection.getNodes()) if ($isTextNode(node)) selectedTextNodes.push(node);
|
|
7078
|
+
else if ($isElementNode(node)) node.setTextFormat(applyFormat(node.getTextFormat()));
|
|
7079
|
+
else if ($isInlineFormattable(node)) node.setFormat(applyFormat(node.getFormat()));
|
|
7080
|
+
const selectedTextNodesLength = selectedTextNodes.length;
|
|
7081
|
+
if (selectedTextNodesLength === 0) {
|
|
7082
|
+
selection.setFormat(applyFormat(selection.format));
|
|
7083
|
+
$setCompositionKey(null);
|
|
7084
|
+
return;
|
|
7085
|
+
}
|
|
7086
|
+
const anchor = selection.anchor;
|
|
7087
|
+
const focus = selection.focus;
|
|
7088
|
+
const isBackward = selection.isBackward();
|
|
7089
|
+
const startPoint = isBackward ? focus : anchor;
|
|
7090
|
+
const endPoint = isBackward ? anchor : focus;
|
|
7091
|
+
let firstIndex = 0;
|
|
7092
|
+
let firstNode = selectedTextNodes[0];
|
|
7093
|
+
let startOffset = startPoint.type === "element" ? 0 : startPoint.offset;
|
|
7094
|
+
if (startPoint.type === "text" && startOffset === firstNode.getTextContentSize()) {
|
|
7095
|
+
firstIndex = 1;
|
|
7096
|
+
firstNode = selectedTextNodes[1];
|
|
7097
|
+
startOffset = 0;
|
|
7098
|
+
}
|
|
7099
|
+
if (firstNode == null) return;
|
|
7100
|
+
const lastIndex = selectedTextNodesLength - 1;
|
|
7101
|
+
let lastNode = selectedTextNodes[lastIndex];
|
|
7102
|
+
const endOffset = endPoint.type === "text" ? endPoint.offset : lastNode.getTextContentSize();
|
|
7103
|
+
if (firstNode.is(lastNode)) {
|
|
7104
|
+
if (startOffset === endOffset) return;
|
|
7105
|
+
const newFormat = applyFormat(firstNode.getFormat());
|
|
7106
|
+
if ($isTokenOrSegmented(firstNode) || startOffset === 0 && endOffset === firstNode.getTextContentSize()) firstNode.setFormat(newFormat);
|
|
7107
|
+
else {
|
|
7108
|
+
const splitNodes = firstNode.splitText(startOffset, endOffset);
|
|
7109
|
+
const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
|
|
7110
|
+
replacement.setFormat(newFormat);
|
|
7111
|
+
if (startPoint.type === "text") startPoint.set(replacement.__key, 0, "text");
|
|
7112
|
+
if (endPoint.type === "text") endPoint.set(replacement.__key, endOffset - startOffset, "text");
|
|
7113
|
+
}
|
|
7114
|
+
selection.format = newFormat;
|
|
7115
|
+
return;
|
|
7116
|
+
}
|
|
7117
|
+
if (startOffset !== 0 && !$isTokenOrSegmented(firstNode)) {
|
|
7118
|
+
[, firstNode] = firstNode.splitText(startOffset);
|
|
7119
|
+
startOffset = 0;
|
|
7120
|
+
}
|
|
7121
|
+
const firstNextFormat = applyFormat(firstNode.getFormat());
|
|
7122
|
+
firstNode.setFormat(firstNextFormat);
|
|
7123
|
+
const lastNextFormat = applyFormat(lastNode.getFormat());
|
|
7124
|
+
if (endOffset > 0) {
|
|
7125
|
+
if (endOffset !== lastNode.getTextContentSize() && !$isTokenOrSegmented(lastNode)) [lastNode] = lastNode.splitText(endOffset);
|
|
7126
|
+
lastNode.setFormat(lastNextFormat);
|
|
7127
|
+
}
|
|
7128
|
+
for (let i = firstIndex + 1; i < lastIndex; i++) {
|
|
7129
|
+
const textNode = selectedTextNodes[i];
|
|
7130
|
+
textNode.setFormat(applyFormat(textNode.getFormat()));
|
|
7131
|
+
}
|
|
7132
|
+
if (startPoint.type === "text") startPoint.set(firstNode.__key, startOffset, "text");
|
|
7133
|
+
if (endPoint.type === "text") endPoint.set(lastNode.__key, endOffset, "text");
|
|
7134
|
+
selection.format = firstNextFormat | lastNextFormat;
|
|
7135
|
+
}
|
|
7136
|
+
/**
|
|
7137
|
+
* Explicitly sets or unsets text formats on the selection. Unlike $formatText
|
|
7138
|
+
* which toggles based on the current selection state, this function sets each
|
|
7139
|
+
* specified format to the exact boolean value provided. Mutually exclusive
|
|
7140
|
+
* formats (subscript/superscript, lowercase/uppercase/capitalize) are
|
|
7141
|
+
* reconciled by {@link toggleTextFormatType}, with later entries winning when
|
|
7142
|
+
* the requested formats conflict.
|
|
7143
|
+
*
|
|
7144
|
+
* @param selection - the selection whose nodes should be formatted.
|
|
7145
|
+
* @param formats - a partial record mapping TextFormatType to boolean.
|
|
7146
|
+
*/
|
|
7147
|
+
function $setTextFormat(selection, formats) {
|
|
7148
|
+
const entries = [];
|
|
7149
|
+
for (const [type, value] of Object.entries(formats)) if (typeof value === "boolean") entries.push([type, value]);
|
|
7150
|
+
if (entries.length === 0) return;
|
|
7151
|
+
$updateTextFormat(selection, (format) => {
|
|
7152
|
+
for (const [type, value] of entries) format = toggleTextFormatType(format, type, value ? TEXT_TYPE_TO_FORMAT[type] : 0);
|
|
7153
|
+
return format;
|
|
7154
|
+
});
|
|
7155
|
+
}
|
|
7156
|
+
/**
|
|
7157
|
+
* Applies the provided format to TextNodes and inline formattable nodes
|
|
7158
|
+
* (e.g. DecoratorTextNode) in the selection, splitting or merging TextNodes
|
|
7159
|
+
* as necessary and aligning all formattable nodes to the same target format.
|
|
7160
|
+
*
|
|
7161
|
+
* For RangeSelection the toggle direction is determined by the selection's
|
|
7162
|
+
* computed format (intersection of all text nodes) when no explicit alignment
|
|
7163
|
+
* is given. For NodeSelection each node is toggled independently when no
|
|
7164
|
+
* explicit alignment is given, since there is no TextNode to use as an
|
|
7165
|
+
* alignment reference.
|
|
7166
|
+
*
|
|
7167
|
+
* @param selection - the selection whose nodes should be formatted.
|
|
7168
|
+
* @param formatType - the format type to apply.
|
|
7169
|
+
* @param alignWithFormat - optional 32-bit bitmask to align with.
|
|
7170
|
+
*/
|
|
7171
|
+
function $formatText(selection, formatType, alignWithFormat = null) {
|
|
7172
|
+
const effectiveAlign = alignWithFormat === null && $isRangeSelection(selection) ? toggleTextFormatType(selection.format, formatType, null) : alignWithFormat;
|
|
7173
|
+
$updateTextFormat(selection, (format) => toggleTextFormatType(format, formatType, effectiveAlign));
|
|
7174
|
+
}
|
|
6947
7175
|
function getCharacterOffset(point) {
|
|
6948
7176
|
const offset = point.offset;
|
|
6949
7177
|
if (point.type === "text") return offset;
|
|
@@ -6980,9 +7208,126 @@ function moveNativeSelection(domSelection, alter, direction, granularity) {
|
|
|
6980
7208
|
domSelection.modify(alter, direction, granularity);
|
|
6981
7209
|
}
|
|
6982
7210
|
/**
|
|
7211
|
+
* Validate that the selection respects `root` (the nearest root or shadow
|
|
7212
|
+
* root): if any selected node lies outside of it, shrink the selection to the
|
|
7213
|
+
* valid edge in the given direction. The valid node check is a safeguard
|
|
7214
|
+
* against an invalid selection, for which getNodes() returns an empty array.
|
|
7215
|
+
*
|
|
7216
|
+
* @returns true if the selection was shrunk
|
|
7217
|
+
*/
|
|
7218
|
+
function $shrinkSelectionToRoot(selection, isBackward, root) {
|
|
7219
|
+
const nodes = selection.getNodes();
|
|
7220
|
+
const validNodes = nodes.filter((node) => $hasAncestor(node, root));
|
|
7221
|
+
if (validNodes.length === 0 || validNodes.length === nodes.length) return false;
|
|
7222
|
+
const edgeNode = isBackward ? validNodes[0] : validNodes[validNodes.length - 1];
|
|
7223
|
+
const edgeElement = $isElementNode(edgeNode) ? edgeNode : edgeNode.getParentOrThrow();
|
|
7224
|
+
if (isBackward) edgeElement.selectStart();
|
|
7225
|
+
else edgeElement.selectEnd();
|
|
7226
|
+
return true;
|
|
7227
|
+
}
|
|
7228
|
+
/**
|
|
7229
|
+
* Extend a collapsed selection by one unit (`character`, `word` or
|
|
7230
|
+
* `lineboundary`) in the deletion direction without ever creating a
|
|
7231
|
+
* non-collapsed DOM selection.
|
|
7232
|
+
*
|
|
7233
|
+
* On Linux/X11, browsers propagate any non-collapsed DOM selection made
|
|
7234
|
+
* during a user gesture to the PRIMARY selection (the middle-click paste
|
|
7235
|
+
* buffer), so a deletion must never pass through a transient non-collapsed
|
|
7236
|
+
* DOM selection or every Backspace/Delete overwrites the user's paste
|
|
7237
|
+
* buffer (https://github.com/facebook/lexical/issues/8766). A collapsed
|
|
7238
|
+
* caret never takes PRIMARY ownership, so the DOM caret is moved with the
|
|
7239
|
+
* native `modify('move')` to measure where the engine places the unit
|
|
7240
|
+
* boundary, and the `[original .. landed]` range is constructed in the
|
|
7241
|
+
* model only. `applyDOMRange` reads just the range's boundary points (it
|
|
7242
|
+
* never touches the DOM selection), giving the same point resolution,
|
|
7243
|
+
* decorator pre/post handling, shadow-root shrink validation and
|
|
7244
|
+
* anchor/focus orientation as a native selection extension would, while
|
|
7245
|
+
* the DOM selection is only ever collapsed.
|
|
7246
|
+
*
|
|
7247
|
+
* When the measurement is not possible — no DOM selection or no
|
|
7248
|
+
* `Selection.modify` (headless environments can polyfill it), or an
|
|
7249
|
+
* unresolvable anchor — the selection is left collapsed, so the deletion
|
|
7250
|
+
* becomes a no-op for that keystroke.
|
|
7251
|
+
*/
|
|
7252
|
+
function $extendSelectionForDeletion(selection, isBackward, granularity) {
|
|
7253
|
+
if ($modifySelectionAroundDecoratorsAndBlocks(selection, "extend", isBackward, granularity)) return;
|
|
7254
|
+
const editor = getActiveEditor();
|
|
7255
|
+
const domSelection = getDOMSelection(getWindow(editor));
|
|
7256
|
+
if (!domSelection || typeof domSelection.modify !== "function") return;
|
|
7257
|
+
const blockCursorElement = editor._blockCursorElement;
|
|
7258
|
+
const rootElement = editor._rootElement;
|
|
7259
|
+
const anchor = selection.anchor;
|
|
7260
|
+
const focusNode = selection.focus.getNode();
|
|
7261
|
+
if (rootElement !== null && blockCursorElement !== null && $isElementNode(focusNode) && !focusNode.isInline() && !focusNode.canBeEmpty()) removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
|
|
7262
|
+
const $resolvePointDOM = (point) => {
|
|
7263
|
+
const pointNode = point.getNode();
|
|
7264
|
+
const keyedDOM = editor.getElementByKey(point.key);
|
|
7265
|
+
return keyedDOM !== null && point.type === "text" && $isTextNode(pointNode) ? $getDOMTextNode(pointNode, keyedDOM, editor) : keyedDOM;
|
|
7266
|
+
};
|
|
7267
|
+
const anchorNode = anchor.getNode();
|
|
7268
|
+
const anchorDOM = $resolvePointDOM(anchor);
|
|
7269
|
+
if (anchorDOM === null) return;
|
|
7270
|
+
const anchorOffset = anchor.offset;
|
|
7271
|
+
const wasCollapsed = selection.isCollapsed();
|
|
7272
|
+
const focus = selection.focus;
|
|
7273
|
+
const focusDOM = wasCollapsed ? anchorDOM : $resolvePointDOM(focus);
|
|
7274
|
+
if (focusDOM === null) return;
|
|
7275
|
+
const focusOffset = focus.offset;
|
|
7276
|
+
setDOMSelectionBaseAndExtent(domSelection, focusDOM, focusOffset, focusDOM, focusOffset);
|
|
7277
|
+
moveNativeSelection(domSelection, "move", isBackward ? "backward" : "forward", granularity);
|
|
7278
|
+
if (domSelection.rangeCount === 0) return;
|
|
7279
|
+
const landedRange = getComposedStaticRange(domSelection, rootElement) || domSelection.getRangeAt(0);
|
|
7280
|
+
const landedContainer = landedRange.startContainer;
|
|
7281
|
+
const landedOffset = landedRange.startOffset;
|
|
7282
|
+
if (wasCollapsed && granularity === "character" && anchor.type === "text" && $isTextNode(anchorNode) && anchorNode.isUnmergeable()) {
|
|
7283
|
+
if (anchorOffset === (isBackward ? 0 : anchorNode.getTextContentSize())) {
|
|
7284
|
+
const sibling = $getSiblingCaret(anchorNode, isBackward ? "previous" : "next").getNodeAtCaret();
|
|
7285
|
+
if ($isTextNode(sibling)) {
|
|
7286
|
+
const sibOffset = isBackward ? sibling.getTextContentSize() - 1 : 1;
|
|
7287
|
+
selection.focus.set(sibling.__key, sibOffset, "text");
|
|
7288
|
+
selection.dirty = true;
|
|
7289
|
+
return;
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
}
|
|
7293
|
+
if (wasCollapsed && granularity === "character" && anchor.type === "text") {
|
|
7294
|
+
const edgeOffset = isBackward ? 0 : anchorNode.getTextContentSize();
|
|
7295
|
+
const clampedOffset = landedContainer === anchorDOM ? landedOffset : anchorOffset !== edgeOffset ? edgeOffset : -1;
|
|
7296
|
+
if (clampedOffset >= 0) {
|
|
7297
|
+
if (clampedOffset !== anchorOffset) {
|
|
7298
|
+
selection.focus.set(anchor.key, clampedOffset, "text");
|
|
7299
|
+
selection.dirty = true;
|
|
7300
|
+
}
|
|
7301
|
+
return;
|
|
7302
|
+
}
|
|
7303
|
+
}
|
|
7304
|
+
const [startContainer, startOffset, endContainer, endOffset] = isBackward ? [
|
|
7305
|
+
landedContainer,
|
|
7306
|
+
landedOffset,
|
|
7307
|
+
anchorDOM,
|
|
7308
|
+
anchorOffset
|
|
7309
|
+
] : [
|
|
7310
|
+
anchorDOM,
|
|
7311
|
+
anchorOffset,
|
|
7312
|
+
landedContainer,
|
|
7313
|
+
landedOffset
|
|
7314
|
+
];
|
|
7315
|
+
const root = $isRootNode(anchorNode) ? anchorNode : $getNearestRootOrShadowRoot(anchorNode);
|
|
7316
|
+
selection.applyDOMRange({
|
|
7317
|
+
collapsed: false,
|
|
7318
|
+
endContainer,
|
|
7319
|
+
endOffset,
|
|
7320
|
+
startContainer,
|
|
7321
|
+
startOffset
|
|
7322
|
+
});
|
|
7323
|
+
selection.dirty = true;
|
|
7324
|
+
if (!$shrinkSelectionToRoot(selection, isBackward, root) && isBackward) $swapPoints(selection);
|
|
7325
|
+
if (granularity === "lineboundary") $modifySelectionAroundDecoratorsAndBlocks(selection, "extend", isBackward, granularity, "decorators");
|
|
7326
|
+
}
|
|
7327
|
+
/**
|
|
6983
7328
|
* Called by `RangeSelection.deleteCharacter` to determine if
|
|
6984
|
-
* `
|
|
6985
|
-
*
|
|
7329
|
+
* `$extendSelectionForDeletion` extended the selection further
|
|
7330
|
+
* than a user would expect for that operation.
|
|
6986
7331
|
*
|
|
6987
7332
|
* A short(?) JavaScript string vs. Unicode primer:
|
|
6988
7333
|
*
|
|
@@ -7016,7 +7361,7 @@ function moveNativeSelection(domSelection, alter, direction, granularity) {
|
|
|
7016
7361
|
* essentially be arbitrarily long, as there are many ways to combine
|
|
7017
7362
|
* them.
|
|
7018
7363
|
*
|
|
7019
|
-
* The
|
|
7364
|
+
* The native caret measurement has already extended our selection by one
|
|
7020
7365
|
* *grapheme* in the direction we want to delete. Sounds great, it's done
|
|
7021
7366
|
* a lot of awfully tricky work for us because this functionality has only
|
|
7022
7367
|
* recently become available in JavaScript via `Intl.Segmenter`. The
|
|
@@ -7197,7 +7542,7 @@ function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
|
|
|
7197
7542
|
const parent = node.getParent();
|
|
7198
7543
|
if (!isBackward) {
|
|
7199
7544
|
if ($isElementNode(prevSibling) && !isCollapsed && prevSibling.isInline()) point.set(prevSibling.__key, prevSibling.getChildrenSize(), "element");
|
|
7200
|
-
else if ($isTextNode(prevSibling)) point.set(prevSibling.__key, prevSibling.getTextContent().length, "text");
|
|
7545
|
+
else if ($isTextNode(prevSibling) && !node.isUnmergeable()) point.set(prevSibling.__key, prevSibling.getTextContent().length, "text");
|
|
7201
7546
|
} else if ((isCollapsed || !isBackward) && prevSibling === null && $isElementNode(parent) && parent.isInline()) {
|
|
7202
7547
|
const parentSibling = parent.getPreviousSibling();
|
|
7203
7548
|
if ($isTextNode(parentSibling)) point.set(parentSibling.__key, parentSibling.getTextContent().length, "text");
|
|
@@ -7206,7 +7551,7 @@ function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
|
|
|
7206
7551
|
const nextSibling = node.getNextSibling();
|
|
7207
7552
|
const parent = node.getParent();
|
|
7208
7553
|
if (isBackward && $isElementNode(nextSibling) && nextSibling.isInline()) point.set(nextSibling.__key, 0, "element");
|
|
7209
|
-
else if ((isCollapsed || isBackward) && nextSibling === null && $isElementNode(parent) && parent.isInline() && !parent.canInsertTextAfter()) {
|
|
7554
|
+
else if ((isCollapsed || isBackward) && nextSibling === null && $isElementNode(parent) && parent.isInline() && !parent.canInsertTextAfter() && parent.getTextContentSize() > 1) {
|
|
7210
7555
|
const parentSibling = parent.getNextSibling();
|
|
7211
7556
|
if ($isTextNode(parentSibling)) point.set(parentSibling.__key, 0, "text");
|
|
7212
7557
|
}
|
|
@@ -7565,7 +7910,7 @@ function $updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
|
|
|
7565
7910
|
} else if ($isRangeSelection(prevSelection) && prevSelection.anchor.type === "text") anchorFormatOrStyleChanged = true;
|
|
7566
7911
|
if (focus.type === "text") nextFocusNode = $isTextNode(focusNode) ? $getDOMTextNode(focusNode, focusDOM, editor) : null;
|
|
7567
7912
|
if (nextAnchorNode === null || nextFocusNode === null) return;
|
|
7568
|
-
if (isCollapsed && (prevSelection === null || anchorFormatOrStyleChanged || $isRangeSelection(prevSelection) && (prevSelection.format !== nextFormat || prevSelection.style !== nextStyle))) markCollapsedSelectionFormat(nextFormat, nextStyle, nextAnchorOffset, anchor.key, performance.now());
|
|
7913
|
+
if (isCollapsed && (prevSelection === null || anchorFormatOrStyleChanged || $isRangeSelection(prevSelection) && (prevSelection.format !== nextFormat || prevSelection.style !== nextStyle))) markCollapsedSelectionFormat(editor, nextFormat, nextStyle, nextAnchorOffset, anchor.key, performance.now());
|
|
7569
7914
|
if (!(domSelection.type === "Range" && isCollapsed) && currentPoints.anchorOffset === nextAnchorOffset && currentPoints.focusOffset === nextFocusOffset && currentPoints.anchorNode === nextAnchorNode && currentPoints.focusNode === nextFocusNode) {
|
|
7570
7915
|
if (activeElement === null || !rootElement.contains(activeElement)) {
|
|
7571
7916
|
const focusEditor = activeElement !== null ? getNearestEditorFromDOMNode(activeElement) : null;
|
|
@@ -7594,7 +7939,7 @@ function $updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
|
|
|
7594
7939
|
scrollIntoViewIfNeeded(editor, selectionRect, rootElement);
|
|
7595
7940
|
}
|
|
7596
7941
|
}
|
|
7597
|
-
markSelectionChangeFromDOMUpdate();
|
|
7942
|
+
markSelectionChangeFromDOMUpdate(editor);
|
|
7598
7943
|
}
|
|
7599
7944
|
function $insertNodes(nodes) {
|
|
7600
7945
|
let selection = $getSelection() || $getPreviousSelection();
|
|
@@ -8072,7 +8417,7 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8072
8417
|
const rootElement = editor._rootElement;
|
|
8073
8418
|
const shouldSkipDOM = editor._headless || rootElement === null;
|
|
8074
8419
|
if (pendingEditorState === null) {
|
|
8075
|
-
if (editor._deferred.length > 0) triggerDeferredUpdateCallbacks(editor, editor._deferred);
|
|
8420
|
+
if (!editor._updating && editor._deferred.length > 0) triggerDeferredUpdateCallbacks(editor, editor._deferred);
|
|
8076
8421
|
return;
|
|
8077
8422
|
}
|
|
8078
8423
|
const currentEditorState = editor._editorState;
|
|
@@ -8130,7 +8475,6 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8130
8475
|
const dirtyElements = editor._dirtyElements;
|
|
8131
8476
|
const normalizedNodes = editor._normalizedNodes;
|
|
8132
8477
|
const tags = editor._updateTags;
|
|
8133
|
-
const deferred = editor._deferred;
|
|
8134
8478
|
if (needsUpdate) {
|
|
8135
8479
|
editor._dirtyType = NO_DIRTY_NODES;
|
|
8136
8480
|
editor._cloneNotNeeded.clear();
|
|
@@ -8179,7 +8523,10 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8179
8523
|
prevEditorState: recoveryEditorState || currentEditorState,
|
|
8180
8524
|
tags
|
|
8181
8525
|
});
|
|
8182
|
-
|
|
8526
|
+
if (!previouslyUpdating) {
|
|
8527
|
+
const deferred = editor._deferred;
|
|
8528
|
+
triggerDeferredUpdateCallbacks(editor, deferred);
|
|
8529
|
+
}
|
|
8183
8530
|
$triggerEnqueuedUpdates(editor);
|
|
8184
8531
|
}
|
|
8185
8532
|
function triggerTextContentListeners(editor, currentEditorState, pendingEditorState) {
|
|
@@ -8500,7 +8847,8 @@ var ElementNode = class extends LexicalNode {
|
|
|
8500
8847
|
return this.getLatest().__format;
|
|
8501
8848
|
}
|
|
8502
8849
|
getFormatType() {
|
|
8503
|
-
|
|
8850
|
+
const format = this.getFormat();
|
|
8851
|
+
return ELEMENT_FORMAT_TO_TYPE[format] || "";
|
|
8504
8852
|
}
|
|
8505
8853
|
getStyle() {
|
|
8506
8854
|
return this.getLatest().__style;
|
|
@@ -9234,7 +9582,7 @@ var ArtificialNode__DO_NOT_USE = class extends ElementNode {
|
|
|
9234
9582
|
return "artificial";
|
|
9235
9583
|
}
|
|
9236
9584
|
createDOM(config) {
|
|
9237
|
-
return
|
|
9585
|
+
return $getDocument().createElement("div");
|
|
9238
9586
|
}
|
|
9239
9587
|
};
|
|
9240
9588
|
/**
|
|
@@ -9260,7 +9608,7 @@ var LineBreakNode = class LineBreakNode extends LexicalNode {
|
|
|
9260
9608
|
return "\n";
|
|
9261
9609
|
}
|
|
9262
9610
|
createDOM() {
|
|
9263
|
-
return
|
|
9611
|
+
return $getDocument().createElement("br");
|
|
9264
9612
|
}
|
|
9265
9613
|
updateDOM() {
|
|
9266
9614
|
return false;
|
|
@@ -9347,7 +9695,7 @@ var ParagraphNode = class ParagraphNode extends ElementNode {
|
|
|
9347
9695
|
return new ParagraphNode(node.__key);
|
|
9348
9696
|
}
|
|
9349
9697
|
createDOM(config) {
|
|
9350
|
-
const dom =
|
|
9698
|
+
const dom = $getDocument().createElement("p");
|
|
9351
9699
|
const classNames = getCachedClassNameArray(config.theme, "paragraph");
|
|
9352
9700
|
if (classNames !== void 0) dom.classList.add(...classNames);
|
|
9353
9701
|
return dom;
|
|
@@ -9364,7 +9712,7 @@ var ParagraphNode = class ParagraphNode extends ElementNode {
|
|
|
9364
9712
|
exportDOM(editor) {
|
|
9365
9713
|
const { element } = super.exportDOM(editor);
|
|
9366
9714
|
if (isHTMLElement(element)) {
|
|
9367
|
-
if (this.isEmpty()) element.append(
|
|
9715
|
+
if (this.isEmpty()) element.append($getDocument().createElement("br"));
|
|
9368
9716
|
const formatType = this.getFormatType();
|
|
9369
9717
|
if (formatType) element.style.textAlign = formatType;
|
|
9370
9718
|
}
|
|
@@ -9448,6 +9796,33 @@ function $isParagraphNode(node) {
|
|
|
9448
9796
|
* - `'latest'` reads the latest committed state without flushing pending
|
|
9449
9797
|
* updates, equivalent to `editor.getEditorState().read(callbackFn, {editor})`.
|
|
9450
9798
|
*/
|
|
9799
|
+
/** @internal */
|
|
9800
|
+
/** @internal */
|
|
9801
|
+
/** @internal */
|
|
9802
|
+
function createInputState() {
|
|
9803
|
+
return {
|
|
9804
|
+
collapsedSelectionFormat: {
|
|
9805
|
+
format: 0,
|
|
9806
|
+
key: "root",
|
|
9807
|
+
offset: 0,
|
|
9808
|
+
style: "",
|
|
9809
|
+
timeStamp: 0
|
|
9810
|
+
},
|
|
9811
|
+
compositionEndData: "",
|
|
9812
|
+
compositionPhase: "idle",
|
|
9813
|
+
hadOrphanedCompositionEvents: false,
|
|
9814
|
+
handledSelectionCommandTimeoutId: null,
|
|
9815
|
+
isInsertLineBreak: false,
|
|
9816
|
+
isInsertTextAfterHandledSelectionCommand: false,
|
|
9817
|
+
isSelectionChangeFromDOMUpdate: false,
|
|
9818
|
+
isSelectionChangeFromMouseDown: false,
|
|
9819
|
+
lastBeforeInputInsertTextTimeStamp: 0,
|
|
9820
|
+
lastKeyCode: null,
|
|
9821
|
+
lastKeyDownTimeStamp: 0,
|
|
9822
|
+
postDeleteSelectionToRestore: null,
|
|
9823
|
+
unprocessedBeforeInputData: null
|
|
9824
|
+
};
|
|
9825
|
+
}
|
|
9451
9826
|
/**
|
|
9452
9827
|
* Configuration entry passed in {@link CreateEditorArgs.nodes} to substitute
|
|
9453
9828
|
* a core node class with a custom subclass. The replacement class itself
|
|
@@ -9585,6 +9960,8 @@ function resetEditor(editor, prevRootElement, nextRootElement, pendingEditorStat
|
|
|
9585
9960
|
editor._cascadeCount = 0;
|
|
9586
9961
|
}
|
|
9587
9962
|
editor._blockCursorElement = null;
|
|
9963
|
+
if (editor._inputState.handledSelectionCommandTimeoutId !== null) clearTimeout(editor._inputState.handledSelectionCommandTimeoutId);
|
|
9964
|
+
editor._inputState = createInputState();
|
|
9588
9965
|
const observer = editor._observer;
|
|
9589
9966
|
if (observer !== null) {
|
|
9590
9967
|
observer.disconnect();
|
|
@@ -9838,6 +10215,8 @@ var LexicalEditor = class {
|
|
|
9838
10215
|
*/
|
|
9839
10216
|
_slotsUsed;
|
|
9840
10217
|
/** @internal */
|
|
10218
|
+
_inputState;
|
|
10219
|
+
/** @internal */
|
|
9841
10220
|
_createEditorArgs;
|
|
9842
10221
|
/** @internal */
|
|
9843
10222
|
constructor(editorState, parentEditor, nodes, config, onError, onWarn, htmlConversions, editable, createEditorArgs) {
|
|
@@ -9881,6 +10260,7 @@ var LexicalEditor = class {
|
|
|
9881
10260
|
this._window = null;
|
|
9882
10261
|
this._blockCursorElement = null;
|
|
9883
10262
|
this._slotsUsed = false;
|
|
10263
|
+
this._inputState = createInputState();
|
|
9884
10264
|
}
|
|
9885
10265
|
/**
|
|
9886
10266
|
*
|
|
@@ -9901,7 +10281,7 @@ var LexicalEditor = class {
|
|
|
9901
10281
|
return registerListener(this._listeners.update, listener);
|
|
9902
10282
|
}
|
|
9903
10283
|
/**
|
|
9904
|
-
* Registers a listener for
|
|
10284
|
+
* Registers a listener for when the editor changes between editable and non-editable states.
|
|
9905
10285
|
* Will trigger the provided callback each time the editor transitions between these states until the
|
|
9906
10286
|
* teardown function is called.
|
|
9907
10287
|
*
|
|
@@ -10736,6 +11116,7 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
|
|
|
10736
11116
|
let node = textNode;
|
|
10737
11117
|
if (node.isAttached() && (compositionEnd || !node.isDirty())) {
|
|
10738
11118
|
const isComposing = node.isComposing();
|
|
11119
|
+
if (node.isToken() && isComposing) return;
|
|
10739
11120
|
let normalizedTextContent = textContent;
|
|
10740
11121
|
if (isComposing || compositionEnd) {
|
|
10741
11122
|
if (textContent.endsWith(COMPOSITION_SUFFIX)) normalizedTextContent = textContent.slice(0, -COMPOSITION_SUFFIX.length);
|
|
@@ -10770,7 +11151,7 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
|
|
|
10770
11151
|
const prevTextContentSize = node.getTextContentSize();
|
|
10771
11152
|
const compositionKey = $getCompositionKey();
|
|
10772
11153
|
const nodeKey = node.getKey();
|
|
10773
|
-
if (node.isToken() || compositionKey !== null && nodeKey === compositionKey && !isComposing || $isRangeSelection(prevSelection) && (parent !== null && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0 || prevSelection.anchor.key === textNode.__key && prevSelection.anchor.offset === 0 && !node.canInsertTextBefore() && !isComposing || prevSelection.focus.key === textNode.__key && prevSelection.focus.offset === prevTextContentSize && !node.canInsertTextAfter() && !isComposing)) {
|
|
11154
|
+
if (node.isToken() && !isComposing || compositionKey !== null && nodeKey === compositionKey && !isComposing || $isRangeSelection(prevSelection) && (parent !== null && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0 || prevSelection.anchor.key === textNode.__key && prevSelection.anchor.offset === 0 && !node.canInsertTextBefore() && !isComposing || prevSelection.focus.key === textNode.__key && prevSelection.focus.offset === prevTextContentSize && !node.canInsertTextAfter() && !isComposing)) {
|
|
10774
11155
|
node.markDirty();
|
|
10775
11156
|
return;
|
|
10776
11157
|
}
|
|
@@ -11120,6 +11501,8 @@ function scrollIntoViewIfNeeded(editor, selectionRect, rootElement) {
|
|
|
11120
11501
|
const doc = getDOMOwnerDocument(rootElement);
|
|
11121
11502
|
const defaultView = getDefaultView(doc);
|
|
11122
11503
|
if (doc === null || defaultView === null) return;
|
|
11504
|
+
const rootRect = rootElement.getBoundingClientRect();
|
|
11505
|
+
if (selectionRect.bottom < rootRect.top) return;
|
|
11123
11506
|
let { top: currentTop, bottom: currentBottom } = selectionRect;
|
|
11124
11507
|
let targetTop = 0;
|
|
11125
11508
|
let targetBottom = 0;
|
|
@@ -11142,7 +11525,7 @@ function scrollIntoViewIfNeeded(editor, selectionRect, rootElement) {
|
|
|
11142
11525
|
if (isFinite(scrollPaddingTop)) targetTop += scrollPaddingTop;
|
|
11143
11526
|
if (isFinite(scrollPaddingBottom)) targetBottom -= scrollPaddingBottom;
|
|
11144
11527
|
} else {
|
|
11145
|
-
const targetRect = element.getBoundingClientRect();
|
|
11528
|
+
const targetRect = element === rootElement ? rootRect : element.getBoundingClientRect();
|
|
11146
11529
|
targetTop = targetRect.top;
|
|
11147
11530
|
targetBottom = targetRect.bottom;
|
|
11148
11531
|
}
|
|
@@ -11219,8 +11602,11 @@ function $getNearestRootOrShadowRoot(node) {
|
|
|
11219
11602
|
}
|
|
11220
11603
|
return current;
|
|
11221
11604
|
}
|
|
11605
|
+
function $isShadowRootNode(node) {
|
|
11606
|
+
return $isElementNode(node) && node.isShadowRoot();
|
|
11607
|
+
}
|
|
11222
11608
|
function $isRootOrShadowRoot(node) {
|
|
11223
|
-
return $isRootNode(node) || $
|
|
11609
|
+
return $isRootNode(node) || $isShadowRootNode(node);
|
|
11224
11610
|
}
|
|
11225
11611
|
/**
|
|
11226
11612
|
* Returns a shallow clone of node with a new key. All properties of the node
|
|
@@ -11275,9 +11661,9 @@ function $getNodeByKeyOrThrow(key) {
|
|
|
11275
11661
|
if (node === null) formatDevErrorMessage(`Expected node with key ${key} to exist but it's not in the nodeMap.`);
|
|
11276
11662
|
return node;
|
|
11277
11663
|
}
|
|
11278
|
-
function createBlockCursorElement(editorConfig) {
|
|
11664
|
+
function $createBlockCursorElement(editorConfig) {
|
|
11279
11665
|
const theme = editorConfig.theme;
|
|
11280
|
-
const element =
|
|
11666
|
+
const element = $getDocument().createElement("div");
|
|
11281
11667
|
element.contentEditable = "false";
|
|
11282
11668
|
element.setAttribute("data-lexical-cursor", "true");
|
|
11283
11669
|
let blockCursorTheme = theme.blockCursor;
|
|
@@ -11287,8 +11673,24 @@ function createBlockCursorElement(editorConfig) {
|
|
|
11287
11673
|
}
|
|
11288
11674
|
return element;
|
|
11289
11675
|
}
|
|
11290
|
-
|
|
11291
|
-
|
|
11676
|
+
/**
|
|
11677
|
+
* Returns true if the given node needs a block cursor given an adjacent selection,
|
|
11678
|
+
* the node must be non-inline and one of:
|
|
11679
|
+
* - DecoratorNode
|
|
11680
|
+
* - ShadowRootNode with a parent that is not also a ShadowRootNode
|
|
11681
|
+
* - An ElementNode that can't be empty
|
|
11682
|
+
*/
|
|
11683
|
+
function $needsBlockCursorBeside(node) {
|
|
11684
|
+
if (!node || node.isInline()) return false;
|
|
11685
|
+
if ($isDecoratorNode(node)) return true;
|
|
11686
|
+
if ($isElementNode(node)) {
|
|
11687
|
+
if (node.isShadowRoot()) {
|
|
11688
|
+
const parent = node.getParent();
|
|
11689
|
+
return !($isElementNode(parent) && parent.isShadowRoot());
|
|
11690
|
+
}
|
|
11691
|
+
return !node.canBeEmpty();
|
|
11692
|
+
}
|
|
11693
|
+
return false;
|
|
11292
11694
|
}
|
|
11293
11695
|
function removeDOMBlockCursorElement(blockCursorElement, editor, rootElement) {
|
|
11294
11696
|
rootElement.style.removeProperty("caret-color");
|
|
@@ -11306,12 +11708,12 @@ function $updateDOMBlockCursorElement(editor, rootElement, nextSelection) {
|
|
|
11306
11708
|
let isBlockCursor = false;
|
|
11307
11709
|
let insertBeforeElement = null;
|
|
11308
11710
|
if (offset === elementNodeSize) {
|
|
11309
|
-
if (
|
|
11711
|
+
if ($needsBlockCursorBeside(elementNode.getChildAtIndex(offset - 1))) isBlockCursor = true;
|
|
11310
11712
|
} else {
|
|
11311
11713
|
const child = elementNode.getChildAtIndex(offset);
|
|
11312
|
-
if (child !== null &&
|
|
11714
|
+
if (child !== null && $needsBlockCursorBeside(child)) {
|
|
11313
11715
|
const sibling = child.getPreviousSibling();
|
|
11314
|
-
if (sibling === null ||
|
|
11716
|
+
if (sibling === null || $needsBlockCursorBeside(sibling)) {
|
|
11315
11717
|
isBlockCursor = true;
|
|
11316
11718
|
insertBeforeElement = editor.getElementByKey(child.__key);
|
|
11317
11719
|
}
|
|
@@ -11319,7 +11721,7 @@ function $updateDOMBlockCursorElement(editor, rootElement, nextSelection) {
|
|
|
11319
11721
|
}
|
|
11320
11722
|
if (isBlockCursor) {
|
|
11321
11723
|
const elementDOM = $getDOMSlot(elementNode, editor.getElementByKey(elementNode.__key), editor).element;
|
|
11322
|
-
if (blockCursorElement === null) editor._blockCursorElement = blockCursorElement = createBlockCursorElement(editor._config);
|
|
11724
|
+
if (blockCursorElement === null) editor._blockCursorElement = blockCursorElement = $createBlockCursorElement(editor._config);
|
|
11323
11725
|
rootElement.style.caretColor = "transparent";
|
|
11324
11726
|
if (insertBeforeElement === null) elementDOM.appendChild(blockCursorElement);
|
|
11325
11727
|
else elementDOM.insertBefore(blockCursorElement, insertBeforeElement);
|
|
@@ -11414,6 +11816,28 @@ function getRootOwnerDocument(rootElement) {
|
|
|
11414
11816
|
return rootElement !== null ? rootElement.ownerDocument : document;
|
|
11415
11817
|
}
|
|
11416
11818
|
/**
|
|
11819
|
+
* Returns the {@link Document} that owns the active editor's root element.
|
|
11820
|
+
* Falls back to `globalThis.document` when there is no active editor (e.g.
|
|
11821
|
+
* a node method such as `createDOM` / `exportDOM` is invoked headlessly,
|
|
11822
|
+
* outside of `editor.update()` / `editor.read()`), or when the active
|
|
11823
|
+
* editor has no root element (e.g. headless mode with
|
|
11824
|
+
* {@link @lexical/headless!withDOM | withDOM}).
|
|
11825
|
+
*
|
|
11826
|
+
* Use this inside `createDOM`, `updateDOM`, and `exportDOM` instead of the
|
|
11827
|
+
* bare `document` global so the node works correctly when the editor lives
|
|
11828
|
+
* inside a Shadow DOM or a cross-origin `<iframe>`.
|
|
11829
|
+
*
|
|
11830
|
+
* Unlike most `$`-prefixed helpers, this does NOT require an ambient active
|
|
11831
|
+
* editor: it must remain callable from `createDOM` / `exportDOM`, which are
|
|
11832
|
+
* public methods that consumers may legitimately call while serializing
|
|
11833
|
+
* nodes headlessly. Throwing here would silently break every node whose DOM
|
|
11834
|
+
* methods were migrated off the bare `document` global.
|
|
11835
|
+
*/
|
|
11836
|
+
function $getDocument() {
|
|
11837
|
+
const editor = internalGetActiveEditor();
|
|
11838
|
+
return getRootOwnerDocument(editor !== null ? editor._rootElement : null);
|
|
11839
|
+
}
|
|
11840
|
+
/**
|
|
11417
11841
|
* A subset of `Selection` covering the four boundary-point fields Lexical
|
|
11418
11842
|
* reads plus `direction`. Designed so a `Selection` instance can be returned
|
|
11419
11843
|
* where a `DOMSelectionBoundaryPoints` is expected (see {@link getDOMSelectionPoints}).
|
|
@@ -13495,6 +13919,21 @@ function $removeTextFromCaretRange(initialRange, sliceMode = "removeEmptySlices"
|
|
|
13495
13919
|
parent = parent.getParent();
|
|
13496
13920
|
element.remove(true);
|
|
13497
13921
|
}
|
|
13922
|
+
} else if (focusCandidate) {
|
|
13923
|
+
const focusBlock = $getBlockFromCaret(focusCandidate);
|
|
13924
|
+
const focusBlockParent = focusBlock && focusBlock.getParent();
|
|
13925
|
+
const topmostShadowRoot = focusBlock && focusBlock.getParents().findLast($isShadowRootNode);
|
|
13926
|
+
if (focusBlock && focusBlockParent && !$isRootNode(focusBlockParent) && focusBlock.isEmpty() && seenStart.has(focusBlock.getKey()) && $getSlotNames(focusBlock).length === 0 && (!topmostShadowRoot || seenStart.has(topmostShadowRoot.getKey()))) {
|
|
13927
|
+
focusBlock.remove(true);
|
|
13928
|
+
let parent = focusBlockParent;
|
|
13929
|
+
while (parent && !$isRootNode(parent) && parent.isEmpty()) {
|
|
13930
|
+
const grandparent = parent.getParent();
|
|
13931
|
+
if (grandparent && $isRootNode(grandparent) && grandparent.getChildrenSize() <= 1) break;
|
|
13932
|
+
const element = parent;
|
|
13933
|
+
parent = grandparent;
|
|
13934
|
+
element.remove(true);
|
|
13935
|
+
}
|
|
13936
|
+
}
|
|
13498
13937
|
}
|
|
13499
13938
|
const bestCandidate = [
|
|
13500
13939
|
anchorCandidate,
|
|
@@ -13505,6 +13944,16 @@ function $removeTextFromCaretRange(initialRange, sliceMode = "removeEmptySlices"
|
|
|
13505
13944
|
if (bestCandidate) return $getCollapsedCaretRange($getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction));
|
|
13506
13945
|
formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map((n) => n.origin.__key))}`);
|
|
13507
13946
|
}
|
|
13947
|
+
function $getBlockFromCaret(caret) {
|
|
13948
|
+
if ($isChildCaret(caret)) {
|
|
13949
|
+
const origin = caret.origin;
|
|
13950
|
+
if (INTERNAL_$isBlock(origin)) return origin;
|
|
13951
|
+
} else {
|
|
13952
|
+
const parent = caret.getParentAtCaret();
|
|
13953
|
+
if (parent && INTERNAL_$isBlock(parent)) return parent;
|
|
13954
|
+
}
|
|
13955
|
+
return null;
|
|
13956
|
+
}
|
|
13508
13957
|
/**
|
|
13509
13958
|
* Determine if the two caret origins are in distinct blocks that
|
|
13510
13959
|
* should be merged.
|
|
@@ -13952,5 +14401,55 @@ function mergeRegister(...func) {
|
|
|
13952
14401
|
func.length = 0;
|
|
13953
14402
|
};
|
|
13954
14403
|
}
|
|
14404
|
+
/**
|
|
14405
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14406
|
+
*
|
|
14407
|
+
* This source code is licensed under the MIT license found in the
|
|
14408
|
+
* LICENSE file in the root directory of this source tree.
|
|
14409
|
+
*
|
|
14410
|
+
*/
|
|
14411
|
+
/**
|
|
14412
|
+
* A map of event type to listener for a given {@link EventTarget}. Each
|
|
14413
|
+
* listener's event argument is inferred from the event type, e.g. for an
|
|
14414
|
+
* `HTMLElement` the `'keydown'` listener receives a `KeyboardEvent`.
|
|
14415
|
+
*/
|
|
14416
|
+
/**
|
|
14417
|
+
* Add several event listeners to a single `target` and return one function
|
|
14418
|
+
* that removes all of them.
|
|
14419
|
+
*
|
|
14420
|
+
* This is the batch form of {@link registerEventListener}: it takes a
|
|
14421
|
+
* `{type: listener}` object (strongly typed per event type) and shares one
|
|
14422
|
+
* `options` value across every listener. The returned dispose function removes
|
|
14423
|
+
* the listeners in reverse registration order (via {@link mergeRegister}).
|
|
14424
|
+
*
|
|
14425
|
+
* Because `options` is shared, register listeners that need a different
|
|
14426
|
+
* `options` value (e.g. a different `capture` flag) with a separate call and
|
|
14427
|
+
* combine the results with `mergeRegister`.
|
|
14428
|
+
*
|
|
14429
|
+
* @example
|
|
14430
|
+
* ```ts
|
|
14431
|
+
* // All five listeners share {capture: true}
|
|
14432
|
+
* return registerEventListeners(
|
|
14433
|
+
* window,
|
|
14434
|
+
* {
|
|
14435
|
+
* beforeinput: report,
|
|
14436
|
+
* cut: report,
|
|
14437
|
+
* keydown: report,
|
|
14438
|
+
* paste: report,
|
|
14439
|
+
* selectionchange: report,
|
|
14440
|
+
* },
|
|
14441
|
+
* {capture: true},
|
|
14442
|
+
* );
|
|
14443
|
+
* ```
|
|
14444
|
+
*
|
|
14445
|
+
* @param target - The {@link EventTarget} to subscribe to
|
|
14446
|
+
* @param listeners - A map of event type to listener
|
|
14447
|
+
* @param options - Options forwarded to `add`/`removeEventListener` for every
|
|
14448
|
+
* listener
|
|
14449
|
+
* @returns A function that removes every listener when called
|
|
14450
|
+
*/
|
|
14451
|
+
function registerEventListeners(target, listeners, options) {
|
|
14452
|
+
return mergeRegister(...Object.entries(listeners).map(([type, listener]) => registerEventListener(target, type, listener, options)));
|
|
14453
|
+
}
|
|
13955
14454
|
//#endregion
|
|
13956
|
-
export { $addUpdateTag, $applyNodeReplacement, $assumeActiveEditor, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $cloneWithPropertiesEphemeral, $comparePointCaretNext, $copyNode, $create, $createChildrenArray, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $findMatchingParent, $fullReconcile, $generateNodesFromRawText, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getDOMSlot, $getDOMTextNode, $getEditor, $getEditorDOMRenderConfig, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getNodeFromDOMNode, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getSlot, $getSlotFrame, $getSlotHost, $getSlotNameWithinHost, $getSlotNames, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodeToNearestRootAtCaret, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isEditorState, $isElementDOMSlot, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isLeafNode, $isLexicalNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSelectionCapturedInDecoratorInput, $isSiblingCaret, $isSlotChild, $isSlotHost, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $isTokenOrTab, $markSlotEditable, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeFromParent, $removeSlot, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setDirectionFromDOM, $setFormatFromDOM, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setSlot, $setState, $splitAtPointCaretNext, $splitNode, $updateDOMSelection, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BEFORE_INPUT_COMMAND, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CAN_USE_BEFORE_INPUT, CAN_USE_DOM, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COLLABORATION_TAG, COMMAND_PRIORITY_BEFORE_CRITICAL, COMMAND_PRIORITY_BEFORE_EDITOR, COMMAND_PRIORITY_BEFORE_HIGH, COMMAND_PRIORITY_BEFORE_LOW, COMMAND_PRIORITY_BEFORE_NORMAL, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, COMPOSITION_END_COMMAND, COMPOSITION_END_TAG, COMPOSITION_START_COMMAND, COMPOSITION_START_TAG, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, CUT_TAG, DEFAULT_EDITOR_DOM_CONFIG, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, HISTORIC_TAG, HISTORY_MERGE_TAG, HISTORY_PUSH_TAG, INDENT_CONTENT_COMMAND, INPUT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_ANDROID, IS_ANDROID_CHROME, IS_APPLE, IS_APPLE_WEBKIT, IS_BOLD, IS_CHROME, IS_CODE, IS_FIREFOX, IS_HIGHLIGHT, IS_IOS, IS_ITALIC, IS_SAFARI, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_DIRECT, NODE_STATE_KEY, NODE_STATE_LATEST, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, PASTE_TAG, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, SKIP_COLLAB_TAG, SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG, SKIP_SELECTION_FOCUS_TAG, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, addClassNamesToElement, buildImportMap, configExtension, createCommand, createEditor, createSharedNodeState, createState, declarePeerDependency, defineExtension, findAllLexicalElementsDeep, flipDirection, getActiveElement, getActiveElementDeep, getComposedEventTarget, getComposedStaticRange, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMSelectionPoints, getDOMSelectionRange, getDOMSelectionRangeAndPoints, getDOMShadowRoots, getDOMTextNode, getDeclaredSlots, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, getParentElement, getRegisteredNode, getRegisteredNodeOrThrow, getRegisteredSubtypeMap, getRootOwnerDocument, getStaticNodeConfig, getStyleObjectFromCSS, getTextDirection, getTransformSetFromKlass, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMCapturingSelection, isDOMDocumentNode, isDOMNode, isDOMShadowRoot, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isExactShortcutMatch, isHTMLAnchorElement, isHTMLElement, isHTMLTableCellElement, isHTMLTableRowElement, isInlineDomNode, isLastChildInBlockNode, isLexicalEditor, isModifierMatch, isOnlyChildInBlockNode, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, iterStaticNodeConfigChain, makeStepwiseIterator, mergeRegister, mountSlotContainer, normalizeClassNames, removeClassNamesFromElement, removeFromParent, resetRandomKey, safeCast, setDOMStyleFromCSS, setDOMStyleObject, setDOMUnmanaged, setNodeIndentFromDOM, shallowMergeConfig, stopLexicalPropagation, toggleTextFormatType, tokenizeRawText, unmountSlotContainer };
|
|
14455
|
+
export { $addUpdateTag, $applyNodeReplacement, $assumeActiveEditor, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $cloneWithPropertiesEphemeral, $comparePointCaretNext, $copyNode, $create, $createChildrenArray, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $findMatchingParent, $formatText, $fullReconcile, $generateNodesFromRawText, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getDOMSlot, $getDOMTextNode, $getDocument, $getEditor, $getEditorDOMRenderConfig, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getNodeFromDOMNode, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getSlot, $getSlotFrame, $getSlotHost, $getSlotNameWithinHost, $getSlotNames, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodeToNearestRootAtCaret, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isEditorState, $isElementDOMSlot, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isInlineFormattable, $isLeafNode, $isLexicalNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSelectionCapturedInDecoratorInput, $isShadowRootNode, $isSiblingCaret, $isSlotChild, $isSlotHost, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $isTokenOrTab, $markSlotEditable, $needsBlockCursorBeside, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeFromParent, $removeSlot, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setDirectionFromDOM, $setFormatFromDOM, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setSlot, $setState, $setTextFormat, $splitAtPointCaretNext, $splitNode, $updateDOMSelection, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BEFORE_INPUT_COMMAND, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CAN_USE_BEFORE_INPUT, CAN_USE_DOM, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COLLABORATION_TAG, COMMAND_PRIORITY_BEFORE_CRITICAL, COMMAND_PRIORITY_BEFORE_EDITOR, COMMAND_PRIORITY_BEFORE_HIGH, COMMAND_PRIORITY_BEFORE_LOW, COMMAND_PRIORITY_BEFORE_NORMAL, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, COMPOSITION_END_COMMAND, COMPOSITION_END_TAG, COMPOSITION_START_COMMAND, COMPOSITION_START_TAG, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, CUT_TAG, DEFAULT_EDITOR_DOM_CONFIG, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, HISTORIC_TAG, HISTORY_MERGE_TAG, HISTORY_PUSH_TAG, INDENT_CONTENT_COMMAND, INPUT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_ANDROID, IS_ANDROID_CHROME, IS_APPLE, IS_APPLE_WEBKIT, IS_BOLD, IS_CHROME, IS_CODE, IS_FIREFOX, IS_HIGHLIGHT, IS_IOS, IS_ITALIC, IS_SAFARI, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_DIRECT, NODE_STATE_KEY, NODE_STATE_LATEST, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, PASTE_TAG, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, SET_TEXT_FORMAT_COMMAND, SKIP_COLLAB_TAG, SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG, SKIP_SELECTION_FOCUS_TAG, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, addClassNamesToElement, buildImportMap, configExtension, createCommand, createEditor, createRefCountedRegistry, createSharedNodeState, createState, declarePeerDependency, defineExtension, findAllLexicalElementsDeep, flipDirection, getActiveElement, getActiveElementDeep, getComposedEventTarget, getComposedStaticRange, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMSelectionPoints, getDOMSelectionRange, getDOMSelectionRangeAndPoints, getDOMShadowRoots, getDOMTextNode, getDeclaredSlots, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, getParentElement, getRegisteredNode, getRegisteredNodeOrThrow, getRegisteredSubtypeMap, getRootOwnerDocument, getStaticNodeConfig, getStyleObjectFromCSS, getTextDirection, getTransformSetFromKlass, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMCapturingSelection, isDOMDocumentNode, isDOMNode, isDOMShadowRoot, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isExactShortcutMatch, isHTMLAnchorElement, isHTMLElement, isHTMLTableCellElement, isHTMLTableRowElement, isInlineDomNode, isLastChildInBlockNode, isLexicalEditor, isModifierMatch, isOnlyChildInBlockNode, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, iterStaticNodeConfigChain, makeStepwiseIterator, mergeRegister, mountSlotContainer, normalizeClassNames, registerEventListener, registerEventListeners, removeClassNamesFromElement, removeFromParent, resetRandomKey, safeCast, setDOMStyleFromCSS, setDOMStyleObject, setDOMUnmanaged, setNodeIndentFromDOM, shallowMergeConfig, stopLexicalPropagation, toggleTextFormatType, tokenizeRawText, unmountSlotContainer };
|