Creating Abbreviation Node for Selected Text in lexical text editor (Produced by Facebook)

103 views Asked by At

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;
0

There are 0 answers