flyeditor
1.1.2
ko
en
code
youtube
npm i flyeditor

FlyEditor

FlyEditor is a lightweight WYSIWYG web editor component designed for React environments.
It seamlessly supports switching between editing and viewer modes, file uploads, customizable toolbars, and more.



Live Preview

You can test the features and functionality of FlyEditor via the link below:

FlyEditor Live Preview



Key Features

  • Flexible Mode Switching: Easily toggle between Edit mode and Read-only (Viewer) mode using the editable prop.
  • Multiple Image Upload Methods:
    • Supports callbacks for single and multiple file uploads (onUploadImage, onUploadImages).
    • Supports direct Drag & Drop image uploads within the editor.
    • Dynamic image URL insertion via external state (insertImageSource).
  • Customizable Toolbar: Freely configure and restrict items on horizontal (toolsH) and vertical (toolsV) toolbars.
  • Custom Font & Size Settings: Define default typography or set custom lists for font families (userFontFamilyList) and font sizes (userFontSizeList).
  • Note Line Background Mode: Enable useNoteLine to apply a ruled notebook background line style.
  • Multilingual & UX Features: Supports Korean/English UI languages (lang), toolbar tooltips, auto-focus, and keyboard shortcut (Ctrl+S / Cmd+S) save callbacks.


Installation

npm i flyeditor


Quick Start

Below is a basic example of using FlyEditor in a React component.

import React, { useState } from 'react';
import FlyEditor from 'flyeditor';
import 'flyeditor/dist/flyeditor.css';

const MyEditor = () => {
    const [initContent, setInitContent] = useState('<p>Hello World!</p>');
    const [content, setContent] = useState('');
    const [isEditable, setIsEditable] = useState(true);

    return (
        <FlyEditor
            value={initContent}
            editable={isEditable}
            onChange={setContent}
        />
    );
};

export default MyEditor;


Usage Examples

1. Saving Content

A simple way to save content entered into the editor.

import React, { useState } from 'react';
import FlyEditor from 'flyeditor';
import 'flyeditor/dist/flyeditor.css';

const MyEditor = () => {
    const [initContent, setInitContent] = useState('<p>Hello World!</p>');
    const [content, setContent] = useState('');
    const [isEditable, setIsEditable] = useState(true);

    // 1. Save manually via user button
    const saveContent = async () => {
        // Example: Call server API to save content
        const formData = new FormData();
        formData.append('content', content);
        const res = await api.saveContent(formData);
        console.log('Saved successfully.');
    };

    // 2. Triggered internally from the editor
    const onSaveContent = async (htmlContent: string) => {
        // Example: Call server API to save content
        const formData = new FormData();
        formData.append('content', htmlContent);
        const res = await api.saveContent(formData);
        console.log('Saved successfully.');
    };

    return (
        <div>
            <button onClick={saveContent}>Save</button>
            <FlyEditor
                value={initContent}
                editable={isEditable}
                onChange={setContent}
                onSave={onSaveContent}
            />
        </div>
    );
};

export default MyEditor;


2. Handling Image Uploads (Single)

Integrate server upload logic using the onUploadImage prop.

import FlyEditor, { IImageAttr } from 'flyeditor';

...

const MyEditor = () => {

    const [initContent, setInitContent] = useState('<p>Hello World!</p>');
    const [content, setContent] = useState('');

    // Single image upload handler
    const handleUploadImage = async (file: File): Promise<IImageAttr> => {
        // Example: Call server API for file upload
        // const formData = new FormData();
        // formData.append('file', file);
        // const res = await api.upload(formData);

        return {
            url: 'https://example.com/images/sample.png',
            name: file.name,
            alt: 'Uploaded image',
        };
    };

    // Apply component
    return (
        <FlyEditor
            value={initContent}
            editable={true}
            onChange={setContent}
            onUploadImage={handleUploadImage} // Single upload
            // multiUploadImage={true}        // Set to true for multiple uploads
            // onUploadImages={handleUploadImages}
        />
    );
    ...

}

3. Inserting Image URLs via External Buttons

Dynamically insert images into the editor using external state (insertImageSource). Reset state in the onImageInserted callback after completion.

...

const [imageSource, setImageSource] = useState<string | IImageAttr | null>(
    null,
);

const insertImage = () => {
    setImageSource({
        url: 'https://example.com/flower.png',
        name: 'flower',
        alt: 'Flower image',
    });
};

return (
    <>
        <button onClick={insertImage}>Insert Image</button>
        <FlyEditor
            value={initContent}
            editable={true}
            onChange={setContent}
            insertImageSource={imageSource}
            onImageInserted={() => setImageSource(null)} // Reset to null after processing (Required)
        />
    </>
);

...

4. Enabling Note Line Mode

<FlyEditor
    value={initContent}
    editable={true}
    useNoteLine={true} // Enable notebook line background mode
    onChange={setContent}
    onSave={html => console.log('Saved HTML:', html)}
/>


5. Viewer Configuration

To display saved HTML content created with the editor, import flyeditor.css and use FlyView

import { FlyView } from 'flyeditor';
import 'flyeditor/dist/flyeditor.css';
...

const MyViewer = () => {

    const [dbContent, setDbContent] = useState('');

    useEffect(()=>{
         // ex) server api
        const res = await api.getContent();
        setDbContent(res);
    }, [])

    return (
        <div className="viewer-container">
            <FlyView value={dbContent} />
        </div>
    );
    ...

}


Props API Reference

List of main props supported by the FlyEditor component. (All props are optional and revert to default values if unspecified.)

PropTypeDefaultDescription
valuestring''HTML content to be inserted into the editor
editablebooleantrueSets Edit mode (true) or Viewer mode (false)
onChange(html: string) => void-Callback function called when content changes
onSave(html: string) => void-Callback called when clicking the Save button or pressing Ctrl+S (Cmd+S)
autoFocusbooleantrueWhether to auto-focus the editor upon mount
lang'ko' | 'en'Browser localeEditor UI language setting
useNoteLinebooleanfalseWhether to apply notebook line background style
tooltipbooleantrueWhether to show tooltips on toolbar icons
classNamestring-Custom class name for the editor container
insertImageSourcestring | IImageAttr | nullnullImage data/URL injected externally into the editor
onImageInserted() => void-Reset callback executed after insertImageSource insertion completes
onUploadImage(file: File) => Promise<IImageAttr>-Single image file upload handler
onUploadImages(files: FileList) => Promise<IImageAttr[]>-Multiple image files upload handler (Used when multiUploadImage is true)
multiUploadImagebooleanfalseAllows multiple file uploads
dropUploadImagebooleantrueAllows image uploads via Drag & Drop
defaultFontSizenumber15Default font size
defaultFontFamilystringPretendardDefault font family
userFontSizeListnumber[]Default setList of font sizes displayed in toolbar dropdown
userFontFamilyListIFontFamilyInfo[]Default setList of custom font families displayed in toolbar dropdown
toolsHstring[]Default setHorizontal toolbar item configuration
toolsVstring[]Default setVertical toolbar item configuration


Interfaces

IImageAttr

Object type used when inserting or returning uploaded images.

export interface IImageAttr {
    url: string; // Accessible image URL (Required)
    name?: string; // File name or identifier
    alt?: string; // Alternative text (alt attribute)
}

IFontFamilyItem

Option type for the font family selection dropdown.

export interface IFontFamilyInfo {
    label: string; // Display name shown to the user
    value: string; // Actual CSS font-family value
}


Custom Toolbar Configuration

By utilizing toolsH and toolsV props, you can customize and layout only the required toolbar buttons.

  • toolsH: Horizontal toolbar layout
  • toolsV: Vertical toolbar layout (fontsize, fontfamily, forecolor, backcolor cannot be placed here)
<FlyEditor
    toolsH={[
        'save',
        'history',
        'fontsize',
        'fontfamily',
        '',
        'forecolor',
        'backcolor',
        '',
        'bold',
        'italic',
        'underline',
        'strikethrough',
        '',
        'image',
        'code',
        'youtube',
    ]}
    toolsV={[
        'left',
        'center',
        'right',
        'justify',
        '',
        'moveup',
        'movedown',
        'insertbefore',
        'insertafter',
        'indent',
        'outdent',
        'empty',
    ]}
/>

Toolbar Items Reference

Complete list and descriptions of tool icons usable in toolsH and toolsV arrays.

Note: Inserting an empty string ('') in the array adds a separator space between toolbar icons. empty: If you put empty in the array, an empty space the size of the default toolbar icon is inserted.

1. Horizontal Toolbar (toolsH) - Text Formatting & Styles, Save, Image Insertion

Tool KeyIcon/FeatureDescription
saveSaveExecutes onSave callback and passes the current editor HTML content.
historyundo/redoundo, redo button
fontsizeFont SizeProvides a dropdown menu to change text size.
fontfamilyFont FamilyProvides a dropdown menu to change font family.
forecolorText ColorChanges the text color of selected text.
backcolorBackground ColorChanges the background / highlight color of selected text.
boldBoldToggles bold style on selected text.
italicItalicToggles italic style on selected text.
underlineUnderlineToggles underline style on selected text.
strikethroughStrikethroughToggles strikethrough style on selected text.
superscriptSuperscriptToggles superscript style on selected text.
subscriptSubscriptToggles subscript style on selected text.
imageInsert ImageOpens file upload window for single/multiple images.
codeInsert Source CodeOpens source code input modal.
youtubeInsert YouTubeOpens YouTube video input modal (Enter YouTube share URL).

2. Vertical Toolbar (toolsV) - Paragraph Formatting & Movement

Tool KeyIcon/FeatureDescription
leftAlign LeftAligns current paragraph or selected block to the left.
centerAlign CenterAligns current paragraph or selected block to the center.
rightAlign RightAligns current paragraph or selected block to the right.
justifyJustifyJustifies current paragraph or selected block.
moveupMove UpMoves the currently focused paragraph above the previous paragraph.
movedownMove DownMoves the currently focused paragraph below the next paragraph.
insertbeforeInsert Line AboveInserts a new empty paragraph above the current block.
insertafterInsert Line BelowInserts a new empty paragraph below the current block.
indentIndentIncreases indentation for the current block.
outdentOutdentDecreases indentation for the current block.


License

MIT License