npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

prosemirror-suggest

v3.0.0

Published

Primitives for building your prosemirror suggestion and autocomplete functionality

Downloads

156,129

Readme

prosemirror-suggest

Primitives for building your prosemirror suggestion and autocomplete functionality.

Version Weekly Downloads Bundled size Typed Codebase MIT License

The problem

You want to create a plugin for your prosemirror editor that responds to an activation character to create suggesters or options or actions for the user. Doing this from scratch can be difficult.

This solution

prosemirror-suggest provides the suggestion primitives needed for building this functionality into your editor. You might be building user mentions, emoji search, an actions dropdown or anything that extracts a query from the editor after the activation character(s).

This implementation doesn't attempt to be magical. There's still a lot of work that goes into setting up your configuration. However, with this toolkit, you you will be building on a well-tested foundation with a structured API.

Installation

# yarn
yarn add prosemirror-suggest prosemirror-view prosemirror-state prosemirror-keymap

# pnpm
pnpm add prosemirror-suggest prosemirror-view prosemirror-state prosemirror-keymap

# npm
npm install prosemirror-suggest prosemirror-view prosemirror-state prosemirror-keymap

The installation requires the installation of the peer dependencies prosemirror-view, prosemirror-state and prosemirror-model to avoid version clashes.

Getting Started

This documentation will be updated soon.

prosemirror-suggest uses configuration objects called Suggester's to define the behaviour of the suggesters you create. By calling the exported suggest method with all required Suggester's the functionality is added to the editor in one plugin.

In the following example we're creating an emoji suggestion plugin that responds to the colon character with a query and presents a list of matching emojis based on the query typed so far.

import { schema } from 'prosemirror-schema-basic';
import { suggest, Suggester } from 'prosemirror-suggest';

const maxResults = 10;
let selectedIndex = 0;
let emojiList: string[] = [];
let showSuggestions = false;

const suggestEmojis: Suggester = {
  // By default decorations are used to highlight the currently matched
  // suggestion in the dom.
  // In this example we don't need decorations (in fact they cause problems when the
  // emoji string replaces the query text in the dom).
  noDecorations: true,
  char: ':', // The character to match against
  name: 'emoji-suggestion', // a unique name
  appendText: '', // Text to append to the created match

  // Keybindings are similar to prosemirror keymaps with a few extra niceties.
  // The key identifier can also include modifiers (e.g.) `Cmd-Space: () => false`
  // Return true to prevent any further keyboard handlers from running.
  keyBindings: {
    ArrowUp: () => {
      selectedIndex = rotateSelectionBackwards(selectedIndex, emojiList.length);
    },
    ArrowDown: () => {
      selectedIndex = rotateSelectionForwards(selectedIndex, emojiList.length);
    },
    Enter: ({ command }) => {
      if (showSuggestions) {
        command(emojiList[selectedIndex]);
      }
    },
    Esc: () => {
      showSuggestions = false;
    },
  },

  onChange: (params) => {
    const query = params.query.full;
    emojiList = sortEmojiMatches({ query, maxResults });
    selectedIndex = 0;
    showSuggestions = true;
  },

  onExit: () => {
    showSuggestions = false;
    emojiList = [];
    selectedIndex = 0;
  },

  // Create a  function that is passed into the change, exit and keybinding handlers.
  // This is useful when these handlers are called in a different part of the app.
  createCommand: ({ match, view }) => {
    return (emoji, skinVariation) => {
      if (!emoji) {
        throw new Error('An emoji is required when calling the emoji suggesters command');
      }

      const tr = view.state.tr;
      const { from, end: to } = match.range;
      tr.insertText(emoji, from, to);
      view.dispatch(tr);
    };
  },
};

// Create the plugin with the above configuration. It also supports multiple plugins being added.
const suggestionPlugin = suggest(suggestEmojis);

// Include the plugin in the created editor state.
const state = EditorState.create({ schema, plugins: [suggestionPlugin] });

You can see this example brought to life in the remirror codebase under the @remirror/extension-emoji and the @remirror/extension-mention packages.

The following examples are available for you to try out on the docs site

Search emoji on : key

The emojis are inserted as plain text. It’s up to you whether you insert the emoji as a node, mark or plaintext.

A gif showing emoji being inserted after typing the colon (:) key. First a laughing emoji then a heart and finally the poop emoji

Editable mention on @ key

Each mention is a mark that wraps the mentioned text with a spec property of inclusive: false

A gif showing mentions being suggested as the user types with editing supported

Core API

suggest

This creates a suggestion plugin with all the suggesters provided.

Signature:

// eslint-disable-next-line @typescript-eslint/no-unused-expressions
(...suggesters: Suggester[]) => Plugin;

The priority of the suggesters is the order in which they are passed into this function.

const plugin = suggest(two, one, three);

In the above example two will be checked first, then one and then three.

Only one suggester can match at any given time. The order and specificity of the regex parameters help determines which suggester will be active.

Suggester

This Suggester interface defines all the options required to create a suggester within your editor.

Signature:

export interface Suggester<GCommand extends AnyFunction<void> = AnyFunction<void>>

Properties

| Property | Type | Description | | --- | --- | --- | | appendText | string | Text to append after the mention has been added. | | char | string | The activation character(s) to match against. | | ignoredClassName | string | Set a class for the ignored suggester decoration. | | ignoredTag | string | Set a tag for the ignored suggester decoration. | | invalidPrefixCharacters | RegExp | string | A regex expression used to invalidate the text directly before the match. | | keyBindings | SuggestKeyBindingMap<GCommand> | An object that describes how certain key bindings should be handled. | | matchOffset | number | Sets the characters that need to be present after the initial character match before a match is triggered. | | name | string | A unique identifier for the suggester. | | noDecorations | boolean | When true, decorations are not created when this mention is being edited.. | | startOfLine | boolean | Whether to only match from the start of the line | | suggestClassName | string | Class name to use for the decoration (while the suggester is still being written) | | suggestTag | string | Tag for the prosemirror decoration which wraps an active match. | | supportedCharacters | RegExp | string | A regex containing all supported characters when within a suggester. | | validPrefixCharacters | RegExp | string | A regex expression used to validate the text directly before the match. |

Methods

| Method | Description | | --- | --- | | createCommand(params) | Create the suggested actions which are made available to the onExit and ononChange handlers. | | onChange(params) | Called whenever a suggester becomes active or changes in anyway. | | onCharacterEntry(params) | Called for each character entry and can be used to disable certain characters. | | onExit(params) | Called when a suggester is exited with the pre-exit match value. |

The options are passed to the suggest method which uses them.

Package API

Enumerations

| Enumeration | Description | | -------------- | ----------------------------------------------- | | ChangeReason | The potential reason for changes | | ExitReason | The potential reasons for an exit of a mention. |

Interfaces

| Interface | Description | | --- | --- | | AddIgnoredParameter | The parameters needed for the SuggestIgnoreParameter.addIgnored() action method available to the suggest plugin handlers. | | CompareMatchParameter | A parameter builder interface which compares the previous and next match. | | CreateSuggestCommandParameter | The parameters passed into the createSuggest suggester property. | | FromToEndParameter | A parameter builder interface describing a from/to/end range. | | KeyboardEventParameter | A parameter builder interface describing the event which triggers the keyboard event handler. | | MatchValue | The match value with the full and partial text. | | OnKeyDownParameter | The parameters required by the . | | ReasonMatchParameter | A parameter builder interface which adds the match property. | | ReasonParameter | A parameter builder interface indicating the reason the handler was called. | | RemoveIgnoredParameter | The parameters needed for the action method available to the suggest plugin handlers. | | SuggestCallbackParameter | | | SuggestChangeHandlerParameter | The parameters passed to the Suggester.onChange() method. | | SuggestCharacterEntryParameter | The parameters passed to the Suggester.onCharacterEntry() method. | | SuggestCommandParameter | A parameter builder interface which adds the command property. | | Suggester | This Suggester interface defines all the options required to create a suggestion within your editor. | | SuggesterParameter | | | SuggestExitHandlerParameter | The parameters passed to the Suggester.onExit() method. | | SuggestIgnoreParameter | A parameter builder interface describing the ignore methods available to the Suggester handlers. | | SuggestKeyBindingParameter | The parameters required by the SuggestKeyBinding method. | | SuggestMarkParameter | A special parameter needed when creating editable suggester using prosemirror Marks. The method should be called when removing a suggester that was identified by a prosemirror Mark. | | SuggestReasonMap | A mapping of the handler matches with their reasons for occurring within the suggest state. | | SuggestStateMatch | Describes the properties of a match which includes range and the text as well as information of the suggester that created the match. | | SuggestStateMatchParameter | A parameter builder interface describing match found by the suggest plugin. | | SuggestStateMatchReason | |

Variables

| Variable | Description | | --- | --- | | createRegexFromSuggester | Create a regex expression to evaluate matches directly from the suggester properties. | | DEFAULT_SUGGEST_ACTIONS | | | DEFAULT_SUGGESTER | | | escapeChar | | | getRegexPrefix | Find regex prefix when depending on whether the mention only supports the start of a line or not | | getSuggestPluginState | Get the state of the suggest plugin. | | isChange | Is this a change in the current suggestion (added or deleted characters)? | | isChangeReason | | | isEntry | Are we entering a new suggestion? | | isExit | Are we exiting a suggestion? | | isExitReason | Check that the passed in value is an ExitReason | | isInvalidSplitReason | Checks that the reason was caused by a split at a point where there is no query. | | isJump | Is this a jump from one suggestion to another? | | isJumpReason | Checks to see if this is a jump reason. | | isMove | Has the cursor moved within the current suggestion (added or deleted characters)? | | isRemovedReason | Checks that the reason was caused by a deletion. | | isSplitReason | Checks that the reason passed is a split reason. This typically means that we should default to a partial update / creation of the mention. | | isValidMatch | True when the match is currently active (i.e. it's query has a value) | | regexToString | Convert a RegExp into a string | | selectionOutsideMatch | True when the current selection is outside the match. | | suggest | This creates a suggestion plugin with all the suggesters provided. |

Type Aliases

| Type Alias | Description | | --- | --- | | SuggestKeyBinding | A method for performing actions when a certain key / pattern is pressed. | | SuggestKeyBindingMap | The keybindings shape for the Suggester.keyBindings property. | | SuggestReplacementType | Determines whether to replace the full match or the partial match (up to the cursor position). |