flyeditor
1.0.2
npm i flyeditor

FlyEditor

FlyEditor는 React 환경에서 간편하게 사용할 수 있는 위지윅(WYSIWYG) 웹에디터 컴포넌트입니다.
손쉽게 편집 및 뷰어 모드 전환, 파일 업로드, 커스텀 도구모음 등을 지원합니다.



미리보기

아래 링크에서 FlyEditor 의 동작 및 기능을 테스트해 보실 수 있습니다.

FlyEditor 미리보기



주요 기능 (Features)

  • 자유로운 모드 전환: editable 속성을 통해 편집 모드와 읽기 전용(Viewer) 모드를 손쉽게 전환할 수 있습니다.
  • 다양한 이미지 업로드 방식 지원:
    • 단일 및 다중 파일 업로드 콜백 지원 (onUploadImage, onUploadImages)
    • 에디터 내 직접 드래그 앤 드롭(Drag & Drop) 업로드 지원
    • 외부 상태(insertImageSource)를 통한 동적 이미지 URL 직접 삽입 기능
  • 자유로운 커스텀 툴바 (Toolbar): 가로(toolsH) 및 세로(toolsV) 툴바 항목을 원하는 구성으로 자유롭게 배치 및 제한할 수 있습니다.
  • 커스텀 폰트 & 크기 설정: 기본 글꼴 및 크기 지정은 물론, 사용자가 사용할 폰트 목록(userFontFamilyList)과 크기 목록(userFontSizeList)을 커스텀 정의할 수 있습니다.
  • 노트 줄 배경 모드: useNoteLine 옵션을 활성화하여 공책/노트 형태의 배경 라인 스타일을 적용할 수 있습니다.
  • 다국어 및 UX 편의기능: 한국어/영어 UI 언어 셋(lang), 툴바 툴팁, 자동 포커스, 단축키(Ctrl+S / Cmd+S) 저장 콜백을 지원합니다.


설치 (Installation)

npm i flyeditor


빠른 시작 (Quick Start)

가장 기본적인 형태로 FlyEditor를 사용하는 방법입니다.

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

const MyEditor = () => {
    const [content, setContent] = useState(
        '<p>안녕하세요! FlyEditor 입니다.</p>',
    );
    const [isEditable, setIsEditable] = useState(true);

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

export default MyEditor;


주요 예제 (Usage Examples)

1. 콘텐츠 저장

에디터에 입력된 내용을 저장하는 간단한 방법 입니다.

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

const MyEditor = () => {
    const [content, setContent] = useState(
        '<p>안녕하세요! FlyEditor 입니다.</p>',
    );
    const [isEditable, setIsEditable] = useState(true);

    // 1. 사용자 버튼으로 직접 저장
    const saveContent = async () => {
        // 예시: 서버에 저장 처리 API 호출
        const formData = new FormData();
        formData.append('content', content);
        const res = await api.saveContent(formData);
        console.log('저장되었습니다.');
    };

    // 2. 에디터 내부에서 저장 실행 시
    const onSaveContent = async (htmlContent: string) => {
        // 예시: 서버에 저장 처리 API 호출
        const formData = new FormData();
        formData.append('content', htmlContent);
        const res = await api.saveContent(formData);
        console.log('저장되었습니다.');
    };

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

export default MyEditor;


2. 이미지 업로드 처리 (단일)

onUploadImage 속성을 통해 서버 업로드 로직을 연동할 수 있습니다.

import FlyEditor, { IImageAttr } from 'flyeditor';

...

const MyEditor = () => {

    // 단일 이미지 업로드 핸들러
    const handleUploadImage = async (file: File): Promise<IImageAttr> => {
        // 예시: 서버 업로드 처리 API 호출
        // 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: '업로드 이미지',
        };
    };

    // 컴포넌트 적용
    return (
        <FlyEditor
            value={content}
            editable={true}
            onChange={setContent}
            onUploadImage={handleUploadImage} // 단일 업로드
            // multiUploadImage={true}        // 다중 업로드 사용 시 true
            // onUploadImages={handleUploadImages}
        />
    );
    ...

}

3. 외부 버튼을 통한 이미지 URL 직접 삽입

외부 상태(insertImageSource)를 통해 에디터 내부에 이미지를 동적으로 삽입할 수 있습니다. 삽입 완료 후 onImageInserted 콜백에서 상태를 초기화합니다.

...

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

const insertImage = () => {
    setImageSource({
        url: 'https://example.com/flower.png',
        name: 'flower',
        alt: '꽃 이미지',
    });
};

return (
    <>
        <button onClick={insertImage}>이미지 삽입</button>
        <FlyEditor
            value={content}
            editable={true}
            onChange={setContent}
            insertImageSource={imageSource}
            onImageInserted={() => setImageSource(null)} // 처리 후 null로 리셋 필수
        />
    </>
);

...

4. 노트 줄 모드 설정

<FlyEditor
    value={content}
    editable={true}
    useNoteLine={true} // 노트 줄 배경 모드 활성화
    onChange={setContent}
    onSave={html => console.log('저장된 HTML:', html)}
/>


Props API Reference

FlyEditor 컴포넌트에서 지원하는 주요 속성 목록입니다. (모든 항목은 선택 옵션이며 설정하지 않으면 기본값으로 동작 합니다.)

PropTypeDefault설명
valuestring''에디터에 삽입될 콘텐츠 (HTML)
editablebooleantrue편집 모드(true) 또는 뷰어 모드(false) 설정
onChange(html: string) => void-컨텐츠 변경 시 호출되는 콜백 함수
onSave(html: string) => void-저장 버튼을 클릭 하거나 키보드 ctrl + s (mac: cmd + s) 입력시 호출되는 콜백 함수
autoFocusbooleantrue에디터에 자동 포커스 여부
lang'ko' | 'en'브라우저 언어셋에디터 UI 언어 설정
useNoteLinebooleanfalse에디터 배경에 노트 줄 스타일 적용 여부
tooltipbooleantrue툴바 아이콘에 말풍선 툴팁 표시 여부
classNamestring-에디터 컨테이너 커스텀 클래스명
insertImageSourcestring | IImageAttr | nullnull에디터에 외부에서 주입할 이미지 정보
onImageInserted() => void-insertImageSource를 통한 이미지 삽입 완료 후 실행할 리셋 콜백
onUploadImage(file: File) => Promise<IImageAttr>-단일 이미지 파일 업로드 핸들러
onUploadImages(files: FileList) => Promise<IImageAttr[]>-다중 이미지 파일 업로드 핸들러 (multiUploadImagetrue 인경우 사용)
multiUploadImagebooleanfalse다중 파일 업로드 허용 여부
dropUploadImagebooleantrue드래그 앤 드롭을 통한 이미지 업로드 허용 여부
defaultFontSizenumber15기본 글자 크기 지정
defaultFontFamilystringPretendard기본 글자 모양 지정
userFontSizeListnumber[]기본셋툴바 드롭다운에 표시할 폰트 크기 목록
userFontFamilyListIFontFamilyInfo[]기본셋툴바 드롭다운에 표시할 커스텀 폰트 목록
toolsHstring[]기본셋가로 툴바 배치 항목 설정
toolsVstring[]기본셋세로 툴바 배치 항목 설정


인터페이스 (Interfaces)

IImageAttr

이미지 삽입 및 업로드 반환 시 사용되는 객체 타입입니다.

export interface IImageAttr {
    url: string; // 이미지 접근 가능한 URL (필수)
    name?: string; // 파일명 또는 식별용 이름
    alt?: string; // 대체 텍스트 (alt 속성)
}

IFontFamilyItem

폰트 선택 드롭다운 옵션 타입입니다.

export interface IFontFamilyInfo {
    label: string; // 사용자 화면에 표시될 이름
    value: string; // 실제 CSS font-family 값
}


Custom Toolbar Configuration

toolsHtoolsV 속성을 활용하면 필요한 버튼만 커스텀하여 툴바를 배치할 수 있습니다.

  • toolsH : 가로 배치형 툴바
  • toolsV : 세로 배치형 툴바 (fontsize, fontfamily, forecolor, backcolor 는 배치 불가)
<FlyEditor
    toolsH={[
        'save',
        'fontsize',
        'fontfamily',
        '',
        'forecolor',
        'backcolor',
        '',
        'bold',
        'italic',
        'underline',
        'strikethrough',
        '',
        'image',
    ]}
    toolsV={[
        'left',
        'center',
        'right',
        'justify',
        '',
        'moveup',
        'movedown',
        'insertbefore',
        'insertafter',
        'indent',
        'outdent',
    ]}
/>

Toolbar Items Reference

toolsHtoolsV 옵션 배열에 사용할 수 있는 전체 툴 아이콘 목록 및 설명입니다.

참고: 배열 내에 빈 문자열('')을 넣으면 툴바 아이콘 사이에 간격(separator)이 삽입됩니다.

1. 가로 툴바 (toolsH) - 글자 서식 및 스타일, 저장, 이미지 삽입

Tool Key아이콘/기능명설명
save저장onSave 콜백 함수를 실행하여 현재 에디터 컨텐츠(html)를 전달합니다.
fontsize글자 크기텍스트의 크기를 변경하는 드롭다운 메뉴를 제공합니다.
fontfamily글자 모양텍스트의 폰트종류를 변경하는 드롭다운 메뉴를 제공합니다.
forecolor글자 색상선택한 텍스트의 글자 색상(Color)을 변경합니다.
backcolor배경 색상선택한 텍스트의 배경/형광펜 색상(Background Color)을 변경합니다.
bold굵게선택한 텍스트를 굵은 글씨로 설정하거나 해제합니다.
italic기울임선택한 텍스트를 이탤릭체로 설정하거나 해제합니다.
underline밑줄선택한 텍스트에 밑줄을 적용하거나 해제합니다.
strikethrough취소선선택한 텍스트에 취소선을 적용하거나 해제합니다.
superscript위 첨자선택한 텍스트를 위 첨자로 변경하거나 해제합니다.
subscript아래 첨자선택한 텍스트를 아래 첨자로 변경하거나 해제합니다.
image이미지 삽입단일/다중 이미지 파일 업로드 창을 호출합니다.

2. 세로 툴바 (toolsV) - 문단 서식 및 이동

Tool Key아이콘/기능명설명
left왼쪽 정렬현재 문단 또는 선택한 블록을 왼쪽으로 정렬합니다.
center가운데 정렬현재 문단 또는 선택한 블록을 가운데로 정렬합니다.
right오른쪽 정렬현재 문단 또는 선택한 블록을 오른쪽으로 정렬합니다.
justify양쪽 정렬현재 문단 또는 선택한 블록을 양쪽 정렬(Justify)합니다.
moveup위로 이동현재 포커스된 문단을 바로 이전 문단 위로 이동시킵니다.
movedown아래로 이동현재 포커스된 문단을 바로 다음 문단 아래로 이동시킵니다.
insertbefore위에 줄 추가현재 블록 위쪽에 새로운 빈 문단을 삽입합니다.
insertafter아래에 줄 추가현재 블록 아래쪽에 새로운 빈 문단을 삽입합니다.
indent들여쓰기현재 선택한 블록의 들여쓰기를 증가시킵니다.
outdent내어쓰기현재 선택한 블록의 들여쓰기를 감소시킵니다.


License

MIT License