Giter Site home page Giter Site logo

react-tinymce-mention's Introduction

React TinyMCE @Mention

Build Status npm version

Provides a simple yet flexible interface for adding @mention functionality into the TinyMCE rich text editor, built with React.js and Redux. Supports data sources that are simple Arrays as well as Promises, allows for data transformations, and exposes an interface for defining your own custom dropdown select menu.

Out of the box support for all major browsers and IE 9-11, and will work with IE8 assuming your app implements a polyfill before the plugin is loaded (see https://babeljs.io/docs/usage/polyfill for instructions).

Works best with react-tinymce, but will work in any environment where window.tinymce is available.

mentions

(NOTE: While this plugin is currently coupled with TinyMCE, extracting it from the current implementation should be fairly simple and we plan on releasing adaptors for other editors in the future.)

Installation

npm install --save react-tinymce-mention

Compatibility

The 0.2.x line uses React 13.x; if you're using React 15.x, pull 0.3.x.

Simple Use Case

import React from 'react';
import ReactDOM from 'react-dom';
import Mention from 'react-tinymce-mention';
import Editor from './components/Editor';

ReactDOM.render(
  <div>
    <Editor />
    <Mention dataSource={[
      'hello',
      'how',
      'are',
      'you'
    ]}
    />
  </div>
, document.getElementById('root')
);

In the simplest case, only dataSource is required; the list containing @mention matches is rendered with a default set of components that you can hijack via stylesheet classes. See src/mention/test-pages/simple.js for a working example.

Advanced (Complete API, minus asyncDataSource)

import React from 'react';
import ReactDOM from 'react-dom';
import Mention from 'react-tinymce-mention';
import Editor from './components/Editor';
import CustomList from './components/CustomList';
import CustomRTEMention from './components/CustomRTEMention';
import complexDataSource from './api/complexDataSource';

ReactDOM.render(
  <div>
    <Editor />
    <Mention
      delimiter={'@'}
      dataSource={complexDataSource}
      transformFn={dataSource => {
        return dataSource.map(result => {
          const { fullName } = result;

          // When transforming your dataSource, a `displayLabel` and
          // `searchKey` is required
          return {
            displayLabel: fullName,
            searchKey: fullName
          };
        });
      }}
      customListRenderer={({ clickFn, fetching, highlightIndex, matchedSources }) => {
        return (
          <CustomList
            fetching={fetching}
            highlightIndex={highlightIndex}
            matchedSources={matchedSources}
            onClick={clickFn}
          />
        );
      }}
      customRTEMention={({ delimiter, displayLabel, id, tinymceId }) => {
        return (
          <CustomRTEMention
            delimiter={delimiter}
            displayLabel={displayLabel}
            id={id}
            tinymceId={tinymceId}
          />
        );
      }}
      onAdd={({ changed, mentions }) => {
        console.log('Added', changed, mentions)
      }}
      onRemove={({ changed, mentions }) => {
        console.log('Removed', changed, mentions);
      }}
      showDebugger={true}
    />
  </div>
, document.getElementById('root')
);

In the advanced use-case you can define a

  • dataSource - Array or Promise
  • delimiter - Either '@' (default) or '#'.
  • transformFn - a function that processes your dataSource before it is injected into the plugin.
  • customListRenderer - A function that returns a component, allowing you to define your own dropdown list.
  • customRTEMention - A component that represents what is inserted into the TinyMCE input window. (Note: TinyMCE is aggressive about cleaning up markup as well as the format, so follow something similar to the example)
  • onAdd - A function that is called whenever you select a mention and it is inserted into the editor.
  • onRemove - Similar to the above, this function is called whenever a mention is removed.
  • showDebugger - Useful when developing a custom dropdown list, enabling this switch allows you to see all of the items available for selection as well as the mentions that have been currently selected.

See src/mention/test-pages/advanced.js for a working example.

Promise Example

import React from 'react';
import ReactDOM from 'react-dom';
import Mention from 'react-tinymce-mention';
import axios from 'axios';
import Editor from './components/Editor';

ReactDOM.render(
  <div>
    <Editor />
    <Mention
      showDebugger={true}
      delimiter={'#'}
      dataSource={axios.get('/public/api/complex.json')}
      transformFn={dataSource => {
        return dataSource.data.map(result => {
          const { fullName } = result;
          return {
            searchKey: fullName,
            displayLabel: fullName
          };
        });
      }}
    />
  </div>
, document.getElementById('root'));

In this example, if you pass in a Promise one of the hard requirements is that the array you return from your transformFn conforms to the above -- a searchKey and displayLabel is required. If you forget these properties an error will be thrown.

See src/mention/test-pages/promise.js for a working example.

Async Example

import React from 'react';
import ReactDOM from 'react-dom';
import Mention from 'react-tinymce-mention';
import axios from 'axios';
import Editor from './components/Editor';
import CustomList from './components/CustomList';

ReactDOM.render(
  <div>
    <Editor />
    <Mention
      showDebugger={true}
      delimiter={'@'}
      asyncDataSource={query => {
        return new Promise(resolve => {
          axios.get(`/public/api/complex.json?q=${query}`)
            .then(response => {
              resolve(transformDataSource(response.data));
            });
        });
      }}
      customListRenderer={({ clickFn, fetching, highlightIndex, matchedSources }) => {
        return (
          <CustomList
            fetching={fetching}
            highlightIndex={highlightIndex}
            matchedSources={matchedSources}
            onClick={clickFn}
          />
        );
      }}
    />
  </div>
, document.getElementById('root'));

function transformDataSource(dataSource) {
  return dataSource.map(result => {
    const { fullName } = result;
    return {
      searchKey: fullName,
      displayLabel: fullName
    };
  });
}

Lastly, if you would like to implement a Mention component that queries a an API when the user types, define an asynDataSource. As with the Promise example above, your final dataSource will need to conform to the searchKey and displayLabel requirement.

See src/mention/test-pages/async.js for a working example.

Troubleshooting

If you are not using react-tinymce and find that editor errors out stating that it can't find the Mention plugin to load, try initializing the plugin before your instance of TinyMCE.

Development

Example implementations have been given in src/mention/test-pages. To enable, uncomment the relevant line in src/index.js and save.

npm install
npm test (or) npm run test-watch
npm start
open http://localhost:3333

TODO

  • More tests

react-tinymce-mention's People

Contributors

damassi avatar deltamualpha avatar valoricde avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

react-tinymce-mention's Issues

Multi editor setup

Hi, do you know which parts I have to adapt in order to get the component working with multiple editors?

no styles

It's returning the suggestions, but they're not working as the gif from the readme file. Is that the expected behavior?

image

Update to react 16.2

Can we update the package to be compatible with react 16.2 ASAP. Need this very urgently

Components of this library must extend React.Component

It seems like that the Mention component which is exported does not inherit from React.Component, and neither is a React old-style class.

Is there any reason for this? Same goes for SuggestionRenderer and DefaultList.

Furthermore, in React 0.14, you don't need to wrap <Provider> child into a function.

Using Mention Causes TinyMCE to not fire Change events

If I have "mention" in the list of plugins (as shown in the code below) I stop getting onChange and onKeyUp events from TinyMCE.

Using cdn.tinymce.com/4/tinymce.min.js

Any idea why this would be? Are there any full working code examples somewhere using this plugin?

             <Mention
                    dataSource={[
                        'hello',
                        'helloooo',
                        'hello0',
                        'howdy']}
                    delimiter={'@'}
                />
                
                <TinyMCE
                    content={this.props.document.editorState}
                    config={{
                        plugins: 'autolink link image lists print preview mention',
                        toolbar: 'undo redo | bold italic | alignleft aligncenter alignright'
                    }}
                    onChange={this.handleEditorChange}
                    onKeyup={this.handleEditorChange} // ... because onChange isn't enough :-/
                />

Adding mention at start of new paragraph does not work when previous paragraph ends with mention

When you add a mention on a line, press Enter to move to a new line, and then immediately add another mention on the next line, the first mention is replaced by the new mention you just added.

For example, if I try to add:

@JoeBlow
@Henry

It will be converted to:

@Henry

In _renderMentionIntoEditor, after the placeholder text is inserted into the editor, editor.getContent() will return something like <p>@joeblow</p><p>@h__PLACEHOLDER__</p>. Notice there is no whitespace between the paragraph tags, so the regex ends up replacing the wrong thing.

Thx.

Module not found: Can't resolve './components/CustomList'

Hello Guys,

I need some help. I do not know why but the module CustomList cannot be found.
Also, I am importing the Editor as described in the TyniMce guide for React:
import {Editor} from '@tinymce/tinymce-react';

Can anyone help here? :/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.