v3/frontend/src/editor/plugins/selection_plugin.tsx

49 lines
1.4 KiB
TypeScript

import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { mergeRegister } from "@lexical/utils";
import { $getNodeByKey, $getSelection, COMMAND_PRIORITY_EDITOR, type LexicalNode, SELECTION_CHANGE_COMMAND } from "lexical";
import { useEffect, useState } from "react";
import { $isFocusableNode } from "../nodes/focusable_node";
export function SelectionPlugin() {
const [editor] = useLexicalComposerContext();
const [previousSelectedNodes, setPreviousSelectedNodes] = useState<string[]>([]);
useEffect(() => mergeRegister(
editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
const selection = $getSelection();
const nodes = selection?.getNodes() || [];
previousSelectedNodes
.map((key) => $getNodeByKey(key))
.forEach(markTreeAsUnfocused);
nodes.forEach(markTreeAsFocused);
setPreviousSelectedNodes(nodes.map(n => n.getKey()));
return false;
}, COMMAND_PRIORITY_EDITOR),
));
return null;
}
function markTreeAsFocused(node: LexicalNode | null) {
if (!node) return;
if ($isFocusableNode(node)) {
node.setFocus(true);
}
markTreeAsFocused(node.getParent());
}
function markTreeAsUnfocused(node: LexicalNode | null) {
if (!node) return;
if ($isFocusableNode(node)) {
node.setFocus(false);
}
markTreeAsUnfocused(node.getParent());
}