Lexical Text Editor: I am using Lexical Text Editor for my text editing needs.
Objective: I want to allow users to select a portion of the text within the editor and then click a button to wrap the selected text with an node, essentially creating an abbreviation with a title.
I created react component and added it to lexical toolbar as external component its worked, but with lexical editor doesn't work
import React, { useState } from "react";
const AbbreviationCreator = () => {
const [selectedText, setSelectedText] = useState("");
const [showInput, setShowInput] = useState(false);
const [abbrTitle, setAbbrTitle] = useState("");
const [hasTitle, setHasTitle] = useState(false);
const handleSelection = () => {
const selected = window.getSelection().toString();
const range = window.getSelection().getRangeAt(0);
setSelectedText({ selected: selected, range: range });
};
const createAbbreviation = () => {
if (selectedText.selected.trim() !== "") {
const abbrElement = document.createElement("abbr");
abbrElement.title = abbrTitle;
abbrElement.innerText = selectedText.selected;
selectedText.range.deleteContents();
selectedText.range.insertNode(abbrElement);
}
setShowInput(false);
console.log({ selectedtext: selectedText, title: abbrTitle });
};
const CheckAbbr = () => {
const selectionRange = window.getSelection();
const startNode = selectionRange.anchorNode;
const parentElement = startNode ? startNode.parentNode : null;
if (parentElement.nodeName === "ABBR") {
setAbbrTitle(parentElement.attributes.title.value);
setHasTitle(true);
} else {
setAbbrTitle("");
setHasTitle(false);
console.log("No parent element found");
}
setShowInput(true);
};
const removeTitle = () => {
const selectionRange = selectedText.range;
const abbrElement = selectionRange.commonAncestorContainer.parentElement;
if (abbrElement.nodeName === "ABBR") {
const textNode = document.createTextNode(abbrElement.innerText);
abbrElement.parentNode.replaceChild(textNode, abbrElement);
}
setShowInput(false);
};
return (
<div className="flex gap-3 mt-7">
<div onMouseUp={handleSelection} className="border p-5 w-[500px]">
<p>
Select text to create abbreviation with title Select text to create
abbreviation with title Select text to create abbreviation with title
Select text to create abbreviation with title .
</p>
<hr />
<p>
Select text to create abbreviation with title Select text to create
abbreviation with title Select text to create abbreviation with title
Select text to create abbreviation with title .
</p>
<hr />
<p>
Select text to create abbreviation with title Select text to create
abbreviation with title Select text to create abbreviation with title
Select text to create abbreviation with title .
</p>
</div>
{showInput ? (
<div className="flex flex-col">
<input
type="text"
className="border h-[20px] p-3"
name=""
value={abbrTitle}
autoFocus
placeholder=""
onChange={(e) => {
setAbbrTitle(e.target.value);
}}
/>
<div className="flex gap-2 mt-3">
<button
className="bg-black text-white p-2"
onClick={createAbbreviation}
>
Add Title
</button>
{hasTitle ? (
<button className="bg-black text-white p-2" onClick={removeTitle}>
remove Title
</button>
) : null}
</div>
</div>
) : null}
<div>
<p>
<button
disabled={!selectedText && true}
className="bg-orange p-2"
onClick={CheckAbbr}
>
Create Abbr
</button>
</p>
</div>
</div>
);
};
export default AbbreviationCreator;