JSPM

  • Created
  • Published
  • Downloads 28553
  • Score
    100M100P100Q161224F
  • License MIT

A mentions plugin for the lexical text editor.

Package Exports

  • lexical-beautiful-mentions
  • lexical-beautiful-mentions/cjs/index.js
  • lexical-beautiful-mentions/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (lexical-beautiful-mentions) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

lexical-beautiful-mentions

CI status CodeQL status

A mentions plugin for the lexical editor. lexical is an extendable text editor for the web build by Meta. While the lexical playground offers a basic mentions plugin for demo purposes, this plugin is more advanced and offers the following features:

  • Customizable triggers: You can set up different characters or words that interact as triggers. For example, you could set "@" as the trigger for mentioning users, "#" for mentioning topics, or "due:" for mentioning due dates.
  • Editing mentions outside of the editor: You can programmatically insert, delete, or rename mentions from outside of the editor textbox using a React hook.
  • Customizable mention style: You can change the look of the mentions via the editor theme to match the style of your application.
  • Automatic spacing: The plugin automatically adds spaces around the mentions, which makes it easier for the user to continue typing.
  • Adding new mentions: You can allow users to create new mentions that are not in the suggestion list.
  • Flexible way to provide mentions: You can use an async query function or a predefined list to provide mentions for the suggestion list.
  • Custom menu and menu item: You can customize the look and behavior of the menu that displays the mention suggestions.

Installation

To install the plugin, run the following command:

// with npm
npm install lexical-beautiful-mentions

// with yarn
yarn add lexical-beautiful-mentions

You also need to install the lexical and @lexical/react, which is a peer dependency of this plugin.

Usage

Import the BeautifulMentionsPlugin plugin:

import { BeautifulMentionsPlugin } from "lexical-beautiful-mentions";

Add the plugin to the lexical editor:

const mentionItems = {
  "@": ["Anton", "Boris", "Catherine", "Dmitri", "Elena", "Felix", "Gina"],
  "#": ["Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape"],
  "due:": ["Today", "Tomorrow", "01-01-2023"],
};

// ...

return (
  <LexicalComposer>
    {/** ... */}
    <BeautifulMentionsPlugin
      items={mentionItems}
    />
    {/** ... */}
  </LexicalComposer>
);

Customizable mention style


const editorConfig = {
  // ...
  theme: {
    // ...
    beautifulMentions: {
      "@": `px-1 mx-px ...`, // use the trigger name as the key
      "@Focused": "outline-none shadow-md ...", // add the "Focused" suffix to style the focused mention
    },
  },
};

// ...

return (
  <LexicalComposer initialConfig={editorConfig}>
    {/** ... */}
  </LexicalComposer>
);

Add custom menu and menu item component


const Menu = forwardRef<
  HTMLElement, 
  BeautifulMentionsMenuProps
>(({ open, loading, ...props }, ref) => (
  <ul
    className="m-0 mt-6 ..."
    {...props}
    ref={ref}
  />
));

const MenuItem = forwardRef<
  HTMLLIElement,
  BeautifulMentionsMenuItemProps
>(({ selected, ...props }, ref) => (
  <li
    className={`m-0 flex ... ${selected ? "bg-gray-100 ..." : "bg-white ..."}`}
    {...props}
    ref={ref}
  />
));

// ...

<BeautifulMentionsPlugin
  items={mentionItems}
  menuComponent={CustomMenu}
  menuItemComponent={CustomMenuItem}
/>

Programmatically insert, delete, or rename mentions

import {
  BeautifulMentionsPlugin,
  useBeautifulMentions,
} from "lexical-beautiful-mentions";

// ...

function MentionsToolbar() {
  const { removeMentions, insertMention } = useBeautifulMentions();
  return (
    <div className="grid gap-2 grid-cols-2">
      <Button onClick={() => removeMentions({ trigger: "#", value: "urgent" })}>
        Remove Mention
      </Button>
      <Button onClick={() => insertMention({ trigger: "#", value: "work" })}>
        Insert Mention
      </Button>
    </div>
  );
}

// ...

return (
  <LexicalComposer>
    {/** ... */}
    <BeautifulMentionsPlugin
      items={mentionItems}
    />
    <MentionsToolbar />
    {/** ... */}
  </LexicalComposer>
);

Async query function

const queryMentions = async (trigger: string, query: string) => {
  const response = await fetch(
    `https://example.com/api/mentions?trigger=${trigger}&query=${query}`
  );
  const data = await response.json();
  return data as string[];
};

// ...

return (
  <LexicalComposer>
    {/** ... */}
    <BeautifulMentionsPlugin
      triggers={["@", "#"]} // needed to tell the plugin when to call the query function
      onSearch={queryMentions}
    />
    {/** ... */}
  </LexicalComposer>
);