This package has been deprecated

    Author message:

    Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

    react-smde

    1.1.0 • Public • Published

    react-smde

    A lightweight Simple Markdown Editor for React.

    NPM

    codecov Open Issues Dependencies License

    Installation

    Demo

    Basic Usage

    Props

    Markdown Previewing

    Package Exports

    Hot Keys

    Custom Commands

    Custom Styling

    Suggestions

    Tooltips

    Builds

    Report Bugs

    Feature Requests

    License

    Third Party Resources

    Installation

    npm i react-smde
    

    or

    yarn add react-smde
    

    react-smde is unopinionated about how to preview Markdown, therefore you'll need to supply your own Markdown previewer (see Basic Usage for an example).

    Demo

    Basic Usage

    import MDEditor from "react-smde";
    import ReactMarkdown from "react-markdown";
     
    class App extends Component {
      constructor() {
        super();
        this.state = { value: "" };
        this.handleValueChange = this.handleValueChange.bind(this);
      }
     
      handleValueChange(value) {
        this.setState({ value });
      }
     
      render() {
        return (
          <MDEditor onChange={this.handleValueChange} value={this.state.value}>
            <ReactMarkdown>{this.state.value || "(empty)"}</ReactMarkdown>
          </MDEditor>
        );
      }
    }

    Props

    The following props are accepted by MDEditor:

    prop Description
    autoGrow(bool) A boolean to autogrow the textarea until the maxEditorHeight has been reached. (default: false)
    classes(obj) An optional object of string classNames that will be appended to the specified className. (see Custom Styling for more info)
    commands(arr) A single array with an array of grouped object commands. (see Custom Commands for more info)
    debounceSuggestions(num) A number set in ms to debounce calling the loadSuggestions function. (default: 300)†
    disableGrip(bool) A boolean to hide and disable the bottom textarea resizing button. (default: false)
    disableHotKeys(bool) A boolean to disable the textarea hot keys. (default: true)
    disablePreview(bool) A boolean to disable the preview button -- also disables the preview/write hot key. (default: false)
    disableToolbar(bool) A boolean to disable the toolbar. (default: false)
    hideGrip(bool) A boolean to hide the bottom textarea toolbar. (default: false)
    editorRef(func) An optional callback function to hoist the MDEditor's ref.
    grip(str/node) An optional custom grip node or string
    loadSuggestions(func) A function that returns an array of suggestions triggered by the suggestionTriggerCharacter. (see Suggestions for more info)
    maxCharacterLength(num/str) A maximum MDEditor character length as a number or string. (default: null)
    maxEditorHeight(num/str) A maximum MDEditor height number that is set in px or string. (default: 500)
    maxEditorWidth (num/str) A maximum MDEditor width number or string. (default: 600px)
    minEditorHeight(num/str) A minimum MDEditor height number that is set in px or string. (default: 250)
    onChange(func) A required callback function to handle value changes.
    readOnly(bool) A boolean to disable editing the text within the textarea. (default: false)
    selectedTab(str) A string (write/preview) to initialize the MDEditor's view in. (default: write)
    showCharacterLength(bool) A boolean to display the MDEditor's character length. †† (default: false)
    suggestionTriggerCharacter(str) A string character to trigger suggestions. (default: @)
    textAreaProps(obj) An optional object of properties to apply to the textarea.
    tooltipPlacement(str) The tooltip position relative to the target. (default: top -- see Tooltips for more info)
    value(str) A required string value.

    † Setting debounceSuggestions lower than 300ms, will disable the suggestions loading indicator. In testing, a number lower than 300ms caused unavoidable UI flashes when the returned data is static. As such, this allows you to utilize an array of static data and avoid seeing a loading indicator for each key input.

    †† Setting showCharacterLength as true will only be visible if hideGrip is false. In order words, if you hide the bottom bar, it won't display the character length.

    Markdown Previewing

    The MDEditor is unopinionated when it comes to previewing markdown content. Therefore, you must supply your own Markdown previewer as children to the MDEditor. The demo provided in the source and the example below utilizes react-markdown.

    import React, { Component } from "react";
    import MDEditor from "react-smde";
    import ReactMarkdown from "react-markdown";
     
    class App extends Component {
      constructor() {
        super();
        this.state = { value: "" };
        this.handleValueChange = this.handleValueChange.bind(this);
      }
     
      handleValueChange(value) {
        this.setState({ value });
      }
     
      render() {
        return (
          <MDEditor onChange={this.handleValueChange} value={this.state.value}>
            <ReactMarkdown>{this.state.value || "(empty)"}</ReactMarkdown>
          </MDEditor>
        );
      }
    }

    Package Exports

    Aside from the default exported MDEditor, this package also exports a few other named internals:

    commands (an object of all predefined commands)
    defaultCommandLayout (a chunked array of predefined commands)
    replaceSelection (function to replace/insert text -- it requires two arguments: the editor ref and a string)
    SvgIcon (component used for default command icons)
    

    You can see use cases for these internals by visiting the Live Demo.

    Hot Keys

    The MDEditor comes pre-configured with disabled hot keys:

    • Bold (ctrl+b)
    • Italic (ctrl+i)
    • Link (ctrl+k)
    • Edit/Preview toggle (ctrl+0)

    If you want to include these keys, then they can be enabled by passing the disableHotKeys=false prop to the MDEditor. By default, they're disabled because they can interfere with other key press triggered event listeners.

    Custom Styling

    The MDEditor was designed to be as flexible as possible when it comes to customizing the appearance of the editor.

    In order to change the style, pass a classes object property to the MDEditor with a custom class name targeting the specified property.

    Click to view a summary of available "mde" property overrides...
    
    mde (applied to root)
    mdedropdown (applied to header dropdown)
    mdetoolbar (applied to toolbar)
    mdetoolbargroup (applied to toolbar groups)
    mdetoolbaritem (applied to toolbar items)
    mdetoolbarseparator (applied to toolbar separators)
    mdepreview (applied to preview wrapper)
    mdepreviewcontent (applied to previewed content)
    mdenosuggestions (applied to no suggestions result item)
    mdesuggestions (applied to suggestions overlay)
    mdetextarea (applied to textarea input)
    mdetextareawrapper (applied to textarea wrapper)
    mdetextareacharacterlength (applied to textarea character length)
    mdegripcontainer (applied to editor bottom grip container)
    mdegripicon (applied to editor bottom grip icon)
    mdetooltiparrow (tooltip arrow) 
    mdetooltippopper (tooltip container) 
    mdetooltippopperarrow (tooltip arrow container) 
    mdetooltip (tooltip) 
    mdetooltipplacementbottom (tooltips with placement bottom) 
    mdetooltipplacementleft (tooltips with placement left) 
    mdetooltipplacementright (tooltips with placement right) 
    mdetooltipplacementtop (tooltips with placement top) 
    mdetooltiptouch (tooltip that has been activated by touch)
    

    For example:

    classes={{ mde: "custom-mde", mdetoolbar: "custom-toolbar" }}
    

    Note: This package uses styled-components under the hood and your CSS classnames will need to have higher specificity when overriding styles. See issues with specificity for more information.


    Custom Commands

    You can rearrange, remove, and adjust properties and/or add your own commands! The commands property of the MDEditor expects a single array of one or many arrays of grouped object commands.

    Commands are simple objects where name must either match a name from this predefined list or must be a unique string:

    {
      name: "bold",
      tooltip: "Add bold text (ctrl+b)",
      buttonProps: { "aria-label": "Add bold text" },
      icon: <SvgIcon icon="bold" />
    }
    

    The icon property must be a React node or a string. You can either pass your own node or you can import the SvgIcon from this package and pass it an icon string property as shown above. For predefined icons, please see this function, which returns a predefined React SVG node based upon a string.

    You can override button commands by passing in a callback function to the the buttonProps. This assumes that your button is not a menu. If it is a menu, then you can pass an onClick callback function as a property and it will override the children's button commands. For a working example, see the Custom Commands Demo.

    If you wish to append to the predefined commands, then you can import the defaultCommandLayout from the package and spread it out in the commands property (see example below).

    For example:

    import MDEditor, { commands, defaultCommandLayout, SvgIcon } from "react-smde";
     
    const { checkedList, orderedList, unorderedList } = commands;
     
    // manual command layout
    <MDEditor
        commands={[
          [orderedList, unorderedList, checkedList],
            [
              {
                name: "bold",
                tooltip: "Add bold text (ctrl+b)",
                buttonProps: { "aria-label": "Add bold text" },
                icon: <SvgIcon icon="bold" />
              }
            ]
          ]
        }
        ...otherProps
    >
      ...etc
    </MDEditor>
     
    // appending custom commands to the default layout
    <MDEditor
        commands={[
            ...defaultCommandLayout,
            [
              {
                name: "bold",
                tooltip: "Add bold text (ctrl+b)",
                buttonProps: { "aria-label": "Add bold text" },
                icon: <SvgIcon icon="bold" />
              }
            ]
          ]
        }
        ...otherProps
    >
      ...etc
    </MDEditor>
     

    Suggestions

    In order to use suggestions, you must supply a callback function to the MDEditor as loadSuggestions. The loadSuggestions callback function must return data in the following structure:

    [
      { value: "example1" },
      { value: "example2" },
      { value: "example3" },
      ...etc
    ]
    

    By default, the MDEditor expects the data to be filtered server-side or by the loadSuggestions callback function.

    The suggestions overlay will only be triggered by the suggestionTriggerCharacter and will only execute the loadSuggestions function as determined by the debounceSuggestions property.

    Please note that setting a debounceSuggestions lower than 300ms will disable the loading indicator -- this is useful if the returned data remains static.

    For a dynamic data set example, see the Demo example above, otherwise here's a static data example:

    import React, { Component } from "react";
    import MDEditor from "react-smde";
     
    class App extends Component {
      constructor() {
        super();
        this.state = {
          value: ""
          suggestions: [
            { value: "andre" },
            { value: "angela" },
            { value: "david" },
            { value: "louise" }
          ]
        };
        this.handleValueChange = this.handleValueChange.bind(this);
        this.loadSuggestions = this.loadSuggestions.bind(this);
      }
     
      handleValueChange(value) {
        this.setState({ value });
      }
     
      loadSuggestions(searchText) {
        return this.state.suggestions.filter(({ value }) =>
          value.toLowerCase().includes(searchText.toLowerCase())
        );
      }
     
      render() {
        return(
          <div className="container">
            <MDEditor
              onChange={this.handleValueChange}
              value={this.state.value}
              debounceSuggestions={0}
              loadSuggestions={this.loadSuggestions}
            >
              <ReactMarkdown>{this.state.value}</ReactMarkdown>
            </MDEditor>
          </div>
        );
      }
    }

    Tooltips

    You can specify the position of the tooltip in relation to its target. For example, one of the following strings can be passed to the tooltipPlacement property:

    'bottom-end'
    'bottom-start'
    'bottom'
    'left-end'
    'left-start'
    'left'
    'right-end'
    'right-start'
    'right'
    'top-end'
    'top-start'
    'top'
    

    Please note that there must be sufficient surrounding window space for the tooltip to occupy the specified placement area; otherwise, the tooltip location may be incorrectly calculated and cause an undesirable UX.

    Builds

    By default, this package is compiled to a common-js (CJS - main) file with supplemental Universal Module Definition (UMD - fallback) and a ECMAScript Module (ESM - module) files. If you wish to use one of the supplemental verisons, then you can do so by either:

    Option 1: Import from react-smde/dist/(esm|umd)/index.(esm.umd).js.

    Option 2: If you're using webpack, then you can utilize the resolve.mainFields property and point to one of the fields listed above: main, module, or fallback. See the resolve.mainFields webpack documentation for more info.

    Report bugs

    If you run into any issues, please fill out a bug report.

    ⚠️ NOTE: Please provide a reproducible codesandbox example of the bug(s) you're experiencing. Issues that don't provide a reproducible example may be ignored.

    Feature Requests

    Have a feature you want included or believe the editor is missing a standard feature? You can either fork the repo, commit changes, and submit a new PR (please include relevant .tests.js files and run npm run test:cov or yarn test:cov to make sure the code is covered) or you can submit a feature request.

    License

    react-smde is MIT licensed.

    Third Party Resources

    In order to make react-smde, the following packages are referenced and used within this package:

    Install

    npm i react-smde

    DownloadsWeekly Downloads

    27

    Version

    1.1.0

    License

    MIT

    Unpacked Size

    261 kB

    Total Files

    6

    Last publish

    Collaborators

    • mattcarlotta