Toolbar에 연동하기
외부 버튼 활용하기 가이드 절차에 따라 react-quill-new 패키지 3.3.3 버전을 설치해 주세요.
예제 코드 소스
React Quill 패키지의 테마 스타일 파일과 컴포넌트 파일을 함께 import하는 것, 잊지 마세요!
가이드 - 더 나아가기 - 커스텀 훅 만들기를 참고하여
useEditorHandlers()훅을 생성합니다.EditorToolbar.tsx파일을 생성하고, 원하는 대로 ToolBar를 구성합니다. 단, 사전에 설정되지 않은 ToolBar 항목은 반드시 toolbar 속성에 추가해야 합니다.
tsx
<span className="ql-formats">
<button className="ql-video-thumbnail !flex !w-auto items-center">
<AiOutlineVideoCameraAdd />
<span className="ml-1 text-xs font-bold text-primaryDark underline underline-offset-2 hover:text-indigo-800">
동영상에서 썸네일 가져오기
</span>
</button>
</span><ReactQuill />컴포넌트와 2번에서 만든<EditorToolbar />컴포넌트를 삽입합니다. formats, modules를 지정하여 React Video Thumbnail Extractor와 연동합니다.useEditorHandlers()훅의openModal메서드는 2번에서 만든 Toolbar 버튼을 클릭했을 때, 실행됩니다.modules를
useMemo()훅으로 감싸서openModal헨들러로 인해 발생하는 에디터의 불필요한 리렌더링을 방지합니다.
tsx
import { EditorToolbar, formats } from 'EditorToolbar';
// ...중략
const modules = useMemo(
() => ({
toolbar: {
// EditorToolbar.tsx 파일의 root Div id를 삽입
container: '#quill-toolbar',
// handler 이름은 EditorToolbar.tsx 파일의 button className에서 ql-을 제외한 값 삽입
handlers: {
'video-thumbnail': openModal
}
}
}),
[]
);
// ...중략
<EditorToolbar />
<ReactQuill
theme="snow"
value={editorContent}
formats={formats}
modules={modules}
onChange={setEditorContent}
placeholder="에디터 툴바에서 동영상에서 썸네일 가져오기를 선택해서 이미지를 삽입해 보세요."
/>/react-quill/EditorToolbar.tsx
tsx
import { AiOutlineVideoCameraAdd } from 'react-icons/ai';
export const formats = [
'header',
'font',
'size',
'bold',
'italic',
'underline',
'align',
'strike',
'script',
'blockquote',
'background',
'list',
'indent',
'link',
'image',
'color',
'code-block'
];
export const EditorToolbar = () => (
<div id="quill-toolbar">
<span className="ql-formats">
<select className="ql-size" defaultValue="medium">
<option value="extra-small">Size 1</option>
<option value="small">Size 2</option>
<option value="medium">Size 3</option>
<option value="large">Size 4</option>
</select>
<select className="ql-header" defaultValue="3">
<option value="1">Heading</option>
<option value="2">Subheading</option>
<option value="3">Normal</option>
</select>
</span>
<span className="ql-formats">
<button className="ql-bold" />
<button className="ql-italic" />
<button className="ql-underline" />
<button className="ql-strike" />
<button className="ql-list" value="ordered" />
</span>
<span className="ql-formats">
<select className="ql-align" />
<select className="ql-color" />
<select className="ql-background" />
</span>
{/* Custom Button 추가 */}
<span className="ql-formats">
<button className="ql-video-thumbnail !flex !w-auto items-center">
<AiOutlineVideoCameraAdd />
<span className="ml-1 text-xs font-bold text-primaryDark underline underline-offset-2 hover:text-indigo-800">
동영상에서 썸네일 가져오기
</span>
</button>
</span>
</div>
);/react-quill/DemoAdvanced.tsx
tsx
import 'react-quill-new/dist/quill.snow.css';
import './style.css';
import '@devskyui/react-video-thumbnail-extractor/style.css';
import type { Thumbnail } from '@devskyui/react-video-thumbnail-extractor';
import { VideoThumbnailExtractorModal } from '@devskyui/react-video-thumbnail-extractor';
import { useMemo } from 'react';
import ReactQuill from 'react-quill-new';
import { useEditorHandlers } from '@/hooks';
import { EditorToolbar, formats } from './';
export const DemoAdvanced = () => {
const {
editorContent,
setEditorContent,
isOpen,
openModal,
closeModal,
handleAddedThumbnail,
handleRemovedThumbnail,
handleError
} = useEditorHandlers();
const modules = useMemo(
() => ({
toolbar: {
// EditorToolbar.tsx 파일의 root Div id를 삽입
container: '#quill-toolbar',
// handler 이름은 EditorToolbar.tsx 파일의 button className에서 ql-을 제외한 값 삽입
handlers: {
'video-thumbnail': openModal
}
}
}),
[]
);
const handleInsertThumbnails = (thumbnails: Thumbnail[]) => {
const thumbnailUrls = thumbnails.map((thumbnail) => thumbnail.base64Url);
if (thumbnails.length < 1) return;
const imageTags = thumbnailUrls.map((url) => `<p><img src="${url}" /></p><p></p>`).join('');
setEditorContent((prevContent) => prevContent + imageTags);
};
return (
<>
<EditorToolbar />
<ReactQuill
theme="snow"
value={editorContent}
formats={formats}
modules={modules}
onChange={setEditorContent}
placeholder="에디터 툴바에서 동영상에서 썸네일 가져오기를 선택해서 이미지를 삽입해 보세요."
/>
<VideoThumbnailExtractorModal
isOpen={isOpen}
maxFileSize={300}
maxThumbnailLength={4}
confirmButtonLabel="에디터에 썸네일 삽입하기"
cancelButtonLabel="취소"
onThumbnailAdded={handleAddedThumbnail}
onThumbnailRemoved={handleRemovedThumbnail}
onError={handleError}
onSuccess={(thumbnails: Thumbnail[]) => {
handleInsertThumbnails(thumbnails);
closeModal();
}}
onCancel={() => closeModal()}
/>
</>
);
};