@zm-editor/react 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ko.md +260 -0
- package/README.md +300 -0
- package/dist/index.js +88 -19
- package/dist/styles.css +8078 -0
- package/dist/variables.css +480 -0
- package/package.json +84 -77
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# @zm-editor/react
|
|
2
|
+
|
|
3
|
+
[Tiptap](https://tiptap.dev) 기반의 Notion 스타일 리치 텍스트 에디터 React 컴포넌트입니다.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@zm-editor/react)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
[English](./README.md) | **한국어**
|
|
9
|
+
|
|
10
|
+
## 주요 기능
|
|
11
|
+
|
|
12
|
+
- **Notion 스타일 UX** - 슬래시 명령어, 버블 메뉴, 드래그 앤 드롭 블록
|
|
13
|
+
- **35+ 슬래시 명령어** - 제목, 목록, 코드 블록, 테이블 등
|
|
14
|
+
- **28+ 커스텀 블록** - 이미지, 임베드, 콜아웃, 다이어그램, API 블록 등
|
|
15
|
+
- **구문 강조** - 26개 이상 언어 지원 (GitHub Dark 테마)
|
|
16
|
+
- **Mermaid 다이어그램** - 플로우차트, 시퀀스 다이어그램, 마인드맵
|
|
17
|
+
- **수학 수식** - KaTeX LaTeX 렌더링
|
|
18
|
+
- **다국어 지원** - 한국어 & 영어 내장
|
|
19
|
+
- **다크 모드** - 완전한 다크 모드 지원
|
|
20
|
+
- **TypeScript** - 완전한 타입 정의 포함
|
|
21
|
+
|
|
22
|
+
## 설치
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @zm-editor/core @zm-editor/react
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 필수 의존성
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install react react-dom
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 선택적 의존성
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Mermaid 다이어그램 (플로우차트, 시퀀스 다이어그램 등)
|
|
38
|
+
npm install mermaid
|
|
39
|
+
|
|
40
|
+
# 수학 수식 (LaTeX 렌더링)
|
|
41
|
+
npm install katex
|
|
42
|
+
|
|
43
|
+
# 파일 첨부의 PDF 미리보기
|
|
44
|
+
npm install pdfjs-dist
|
|
45
|
+
|
|
46
|
+
# HTML 새니타이징
|
|
47
|
+
npm install dompurify
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> **참고:** Mermaid와 KaTeX는 선택 사항입니다. 설치하지 않은 경우, 다이어그램이나 수식 블록 사용 시 설치 안내가 표시됩니다.
|
|
51
|
+
|
|
52
|
+
## 빠른 시작
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
'use client'; // Next.js App Router 필수
|
|
56
|
+
|
|
57
|
+
import { ZmEditor } from '@zm-editor/react';
|
|
58
|
+
|
|
59
|
+
export default function MyEditor() {
|
|
60
|
+
return (
|
|
61
|
+
<ZmEditor
|
|
62
|
+
initialContent="<p>안녕하세요!</p>"
|
|
63
|
+
onChange={(editor) => {
|
|
64
|
+
console.log(editor.getJSON());
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Next.js 사용법
|
|
72
|
+
|
|
73
|
+
Next.js App Router에서는 SSR 문제를 피하기 위해 동적 import를 사용하세요:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
'use client';
|
|
77
|
+
|
|
78
|
+
import dynamic from 'next/dynamic';
|
|
79
|
+
|
|
80
|
+
const ZmEditor = dynamic(
|
|
81
|
+
() => import('@zm-editor/react').then((mod) => mod.ZmEditor),
|
|
82
|
+
{ ssr: false }
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
export default function EditorWrapper() {
|
|
86
|
+
return <ZmEditor />;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Props
|
|
91
|
+
|
|
92
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
93
|
+
|------|------|--------|------|
|
|
94
|
+
| `initialContent` | `string \| JSONContent` | `''` | 초기 에디터 콘텐츠 (HTML 또는 JSON) |
|
|
95
|
+
| `onChange` | `(editor: Editor) => void` | - | 콘텐츠 변경 시 콜백 |
|
|
96
|
+
| `onImageUpload` | `(file: File) => Promise<string>` | - | 커스텀 이미지 업로드 핸들러 |
|
|
97
|
+
| `locale` | `ZmEditorLocale` | `enLocale` | 다국어 설정 |
|
|
98
|
+
| `editable` | `boolean` | `true` | 편집 가능/불가 설정 |
|
|
99
|
+
| `placeholder` | `string` | - | 플레이스홀더 텍스트 |
|
|
100
|
+
| `className` | `string` | - | 추가 CSS 클래스 |
|
|
101
|
+
|
|
102
|
+
## 슬래시 명령어
|
|
103
|
+
|
|
104
|
+
`/`를 입력하면 명령어 메뉴가 열립니다:
|
|
105
|
+
|
|
106
|
+
| 명령어 | 설명 |
|
|
107
|
+
|--------|------|
|
|
108
|
+
| `/text` | 일반 텍스트 |
|
|
109
|
+
| `/h1`, `/h2`, `/h3` | 제목 |
|
|
110
|
+
| `/bullet` | 글머리 기호 목록 |
|
|
111
|
+
| `/number` | 번호 목록 |
|
|
112
|
+
| `/task` | 할 일 목록 (체크리스트) |
|
|
113
|
+
| `/quote` | 인용문 |
|
|
114
|
+
| `/code` | 구문 강조 코드 블록 |
|
|
115
|
+
| `/table` | 테이블 (3x3) |
|
|
116
|
+
| `/image` | 이미지 업로드 |
|
|
117
|
+
| `/file` | 파일 첨부 |
|
|
118
|
+
| `/embed` | 임베드 (YouTube, CodeSandbox, StackBlitz, Replit) |
|
|
119
|
+
| `/callout` | 콜아웃 (info, warning, error, success, tip, note) |
|
|
120
|
+
| `/toggle` | 토글 (접기/펼치기) |
|
|
121
|
+
| `/mermaid` | Mermaid 다이어그램 |
|
|
122
|
+
| `/math` | 수학 수식 (LaTeX) |
|
|
123
|
+
| `/terminal` | 터미널 블록 |
|
|
124
|
+
| `/api` | API 요청/응답 블록 |
|
|
125
|
+
| `/divider` | 구분선 |
|
|
126
|
+
| `/toc` | 목차 |
|
|
127
|
+
| ... | 그 외 15개 이상 |
|
|
128
|
+
|
|
129
|
+
## 다국어 설정 (i18n)
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { ZmEditor, koLocale, enLocale } from '@zm-editor/react';
|
|
133
|
+
|
|
134
|
+
// 한국어
|
|
135
|
+
<ZmEditor locale={koLocale} />
|
|
136
|
+
|
|
137
|
+
// 영어 (기본값)
|
|
138
|
+
<ZmEditor locale={enLocale} />
|
|
139
|
+
|
|
140
|
+
// 커스텀
|
|
141
|
+
<ZmEditor
|
|
142
|
+
locale={{
|
|
143
|
+
...koLocale,
|
|
144
|
+
editor: {
|
|
145
|
+
placeholder: '내용을 입력하세요...',
|
|
146
|
+
},
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 커스텀 이미지 업로드
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
<ZmEditor
|
|
155
|
+
onImageUpload={async (file) => {
|
|
156
|
+
const formData = new FormData();
|
|
157
|
+
formData.append('file', file);
|
|
158
|
+
|
|
159
|
+
const response = await fetch('/api/upload', {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
body: formData,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const { url } = await response.json();
|
|
165
|
+
return url;
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 콘텐츠 내보내기
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
import { useRef } from 'react';
|
|
174
|
+
import { ZmEditor, type ZmEditorRef } from '@zm-editor/react';
|
|
175
|
+
|
|
176
|
+
function MyEditor() {
|
|
177
|
+
const editorRef = useRef<ZmEditorRef>(null);
|
|
178
|
+
|
|
179
|
+
const handleExport = () => {
|
|
180
|
+
const editor = editorRef.current?.editor;
|
|
181
|
+
if (!editor) return;
|
|
182
|
+
|
|
183
|
+
const json = editor.getJSON(); // JSON 형식
|
|
184
|
+
const html = editor.getHTML(); // HTML 형식
|
|
185
|
+
const text = editor.getText(); // 텍스트 형식
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<>
|
|
190
|
+
<ZmEditor ref={editorRef} />
|
|
191
|
+
<button onClick={handleExport}>내보내기</button>
|
|
192
|
+
</>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 테마 커스터마이징
|
|
198
|
+
|
|
199
|
+
### 스타일 가져오기
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import '@zm-editor/react/styles.css';
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### CSS 변수로 커스터마이징
|
|
206
|
+
|
|
207
|
+
```css
|
|
208
|
+
:root {
|
|
209
|
+
/* 기본 색상 */
|
|
210
|
+
--zm-colors-primary: #8b5cf6;
|
|
211
|
+
--zm-colors-primary-hover: #7c3aed;
|
|
212
|
+
|
|
213
|
+
/* 에디터 배경 & 텍스트 */
|
|
214
|
+
--zm-colors-editor-background: #ffffff;
|
|
215
|
+
--zm-colors-editor-text: #374151;
|
|
216
|
+
--zm-colors-editor-border: #e5e7eb;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* 다크 모드 */
|
|
220
|
+
.dark,
|
|
221
|
+
[data-theme='dark'] {
|
|
222
|
+
--zm-colors-primary: #a78bfa;
|
|
223
|
+
--zm-colors-editor-background: #1f2937;
|
|
224
|
+
--zm-colors-editor-text: #d1d5db;
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 다크 모드 지원
|
|
229
|
+
|
|
230
|
+
zm-editor는 다음 방식의 다크 모드를 자동 지원합니다:
|
|
231
|
+
- `.dark` 클래스 (Tailwind CSS / next-themes)
|
|
232
|
+
- `[data-theme="dark"]` 속성
|
|
233
|
+
- `@media (prefers-color-scheme: dark)` 시스템 설정
|
|
234
|
+
|
|
235
|
+
## 브라우저 지원
|
|
236
|
+
|
|
237
|
+
- Chrome (최신)
|
|
238
|
+
- Firefox (최신)
|
|
239
|
+
- Safari (최신)
|
|
240
|
+
- Edge (최신)
|
|
241
|
+
|
|
242
|
+
## 요구 사항
|
|
243
|
+
|
|
244
|
+
- React 18+
|
|
245
|
+
- Node.js 18+
|
|
246
|
+
|
|
247
|
+
## 관련 패키지
|
|
248
|
+
|
|
249
|
+
| 패키지 | 설명 |
|
|
250
|
+
|--------|------|
|
|
251
|
+
| [@zm-editor/core](https://www.npmjs.com/package/@zm-editor/core) | 코어 Tiptap 확장 및 유틸리티 |
|
|
252
|
+
|
|
253
|
+
## 링크
|
|
254
|
+
|
|
255
|
+
- [GitHub 저장소](https://github.com/hanumoka/zm-editor)
|
|
256
|
+
- [문서](https://github.com/hanumoka/zm-editor#readme)
|
|
257
|
+
|
|
258
|
+
## 라이선스
|
|
259
|
+
|
|
260
|
+
[MIT](https://github.com/hanumoka/zm-editor/blob/main/LICENSE)
|
package/README.md
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# @zm-editor/react
|
|
2
|
+
|
|
3
|
+
React components for zm-editor - a Notion-style rich text editor built on [Tiptap](https://tiptap.dev).
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@zm-editor/react)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
**English** | [한국어](./README.ko.md)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Notion-like UX** - Slash commands, bubble menu, drag & drop blocks
|
|
13
|
+
- **35+ Slash Commands** - Headings, lists, code blocks, tables, and more
|
|
14
|
+
- **28+ Custom Blocks** - Images, embeds, callouts, diagrams, API blocks, etc.
|
|
15
|
+
- **Syntax Highlighting** - 26+ languages with GitHub Dark theme
|
|
16
|
+
- **Mermaid Diagrams** - Flowcharts, sequence diagrams, mindmaps
|
|
17
|
+
- **Math Equations** - KaTeX LaTeX rendering
|
|
18
|
+
- **i18n Support** - English & Korean built-in
|
|
19
|
+
- **Dark Mode** - Full dark mode support
|
|
20
|
+
- **TypeScript** - Full type definitions included
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @zm-editor/core @zm-editor/react
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Peer Dependencies
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install react react-dom
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Optional Dependencies
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# For Mermaid diagrams (flowcharts, sequence diagrams, etc.)
|
|
38
|
+
npm install mermaid
|
|
39
|
+
|
|
40
|
+
# For Math equations (LaTeX rendering)
|
|
41
|
+
npm install katex
|
|
42
|
+
|
|
43
|
+
# For PDF preview in file attachments
|
|
44
|
+
npm install pdfjs-dist
|
|
45
|
+
|
|
46
|
+
# For HTML sanitization
|
|
47
|
+
npm install dompurify
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> **Note:** Mermaid and KaTeX are optional. If not installed, the editor will display a helpful installation prompt when you try to use diagram or math blocks.
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
'use client'; // Required for Next.js App Router
|
|
56
|
+
|
|
57
|
+
import { ZmEditor } from '@zm-editor/react';
|
|
58
|
+
|
|
59
|
+
export default function MyEditor() {
|
|
60
|
+
return (
|
|
61
|
+
<ZmEditor
|
|
62
|
+
initialContent="<p>Hello, world!</p>"
|
|
63
|
+
onChange={(editor) => {
|
|
64
|
+
console.log(editor.getJSON());
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Usage with Next.js
|
|
72
|
+
|
|
73
|
+
For Next.js App Router, use dynamic import to avoid SSR issues:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
'use client';
|
|
77
|
+
|
|
78
|
+
import dynamic from 'next/dynamic';
|
|
79
|
+
|
|
80
|
+
const ZmEditor = dynamic(
|
|
81
|
+
() => import('@zm-editor/react').then((mod) => mod.ZmEditor),
|
|
82
|
+
{ ssr: false }
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
export default function EditorWrapper() {
|
|
86
|
+
return <ZmEditor />;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Props
|
|
91
|
+
|
|
92
|
+
| Prop | Type | Default | Description |
|
|
93
|
+
|------|------|---------|-------------|
|
|
94
|
+
| `initialContent` | `string \| JSONContent` | `''` | Initial editor content (HTML or JSON) |
|
|
95
|
+
| `onChange` | `(editor: Editor) => void` | - | Callback when content changes |
|
|
96
|
+
| `onImageUpload` | `(file: File) => Promise<string>` | - | Custom image upload handler |
|
|
97
|
+
| `locale` | `ZmEditorLocale` | `enLocale` | Locale for i18n |
|
|
98
|
+
| `editable` | `boolean` | `true` | Enable/disable editing |
|
|
99
|
+
| `placeholder` | `string` | - | Placeholder text |
|
|
100
|
+
| `className` | `string` | - | Additional CSS class |
|
|
101
|
+
|
|
102
|
+
## Slash Commands
|
|
103
|
+
|
|
104
|
+
Type `/` to open the command menu:
|
|
105
|
+
|
|
106
|
+
| Command | Description |
|
|
107
|
+
|---------|-------------|
|
|
108
|
+
| `/text` | Plain text paragraph |
|
|
109
|
+
| `/h1`, `/h2`, `/h3` | Headings |
|
|
110
|
+
| `/bullet` | Bullet list |
|
|
111
|
+
| `/number` | Numbered list |
|
|
112
|
+
| `/task` | Task list (checklist) |
|
|
113
|
+
| `/quote` | Blockquote |
|
|
114
|
+
| `/code` | Code block with syntax highlighting |
|
|
115
|
+
| `/table` | Table (3x3) |
|
|
116
|
+
| `/image` | Image upload |
|
|
117
|
+
| `/file` | File attachment |
|
|
118
|
+
| `/embed` | Embed (YouTube, CodeSandbox, StackBlitz, Replit) |
|
|
119
|
+
| `/callout` | Callout box (info, warning, error, success, tip, note) |
|
|
120
|
+
| `/toggle` | Toggle (collapsible content) |
|
|
121
|
+
| `/mermaid` | Mermaid diagram |
|
|
122
|
+
| `/math` | Math equation (LaTeX) |
|
|
123
|
+
| `/terminal` | Terminal block |
|
|
124
|
+
| `/api` | API request/response block |
|
|
125
|
+
| `/divider` | Horizontal rule |
|
|
126
|
+
| `/toc` | Table of contents |
|
|
127
|
+
| `/error` | Error/warning/info message |
|
|
128
|
+
| `/os` | OS-specific commands (macOS/Linux/Windows) |
|
|
129
|
+
| `/changelog` | Version changelog |
|
|
130
|
+
| `/env` | Environment variables (with masking) |
|
|
131
|
+
| `/gist` | GitHub Gist embed |
|
|
132
|
+
| `/diff` | Code diff block |
|
|
133
|
+
| `/footnote` | Footnote |
|
|
134
|
+
| `/log` | Log block (debug/info/warn/error) |
|
|
135
|
+
| `/stacktrace` | Stack trace block |
|
|
136
|
+
| `/metadata` | Document metadata |
|
|
137
|
+
| `/graphql` | GraphQL query block |
|
|
138
|
+
| `/openapi` | OpenAPI/Swagger embed |
|
|
139
|
+
| `/diagram` | PlantUML/D2 diagram |
|
|
140
|
+
| `/emoji` | Emoji picker |
|
|
141
|
+
|
|
142
|
+
## Internationalization (i18n)
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import { ZmEditor, koLocale, enLocale } from '@zm-editor/react';
|
|
146
|
+
|
|
147
|
+
// Korean
|
|
148
|
+
<ZmEditor locale={koLocale} />
|
|
149
|
+
|
|
150
|
+
// English (default)
|
|
151
|
+
<ZmEditor locale={enLocale} />
|
|
152
|
+
|
|
153
|
+
// Custom locale
|
|
154
|
+
<ZmEditor
|
|
155
|
+
locale={{
|
|
156
|
+
...enLocale,
|
|
157
|
+
editor: {
|
|
158
|
+
placeholder: 'Start writing...',
|
|
159
|
+
},
|
|
160
|
+
}}
|
|
161
|
+
/>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Custom Image Upload
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
<ZmEditor
|
|
168
|
+
onImageUpload={async (file) => {
|
|
169
|
+
const formData = new FormData();
|
|
170
|
+
formData.append('file', file);
|
|
171
|
+
|
|
172
|
+
const response = await fetch('/api/upload', {
|
|
173
|
+
method: 'POST',
|
|
174
|
+
body: formData,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const { url } = await response.json();
|
|
178
|
+
return url;
|
|
179
|
+
}}
|
|
180
|
+
/>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Export Content
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import { useRef } from 'react';
|
|
187
|
+
import { ZmEditor, type ZmEditorRef } from '@zm-editor/react';
|
|
188
|
+
|
|
189
|
+
function MyEditor() {
|
|
190
|
+
const editorRef = useRef<ZmEditorRef>(null);
|
|
191
|
+
|
|
192
|
+
const handleExport = () => {
|
|
193
|
+
const editor = editorRef.current?.editor;
|
|
194
|
+
if (!editor) return;
|
|
195
|
+
|
|
196
|
+
const json = editor.getJSON();
|
|
197
|
+
const html = editor.getHTML();
|
|
198
|
+
const text = editor.getText();
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<>
|
|
203
|
+
<ZmEditor ref={editorRef} />
|
|
204
|
+
<button onClick={handleExport}>Export</button>
|
|
205
|
+
</>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Theming & Customization
|
|
211
|
+
|
|
212
|
+
zm-editor uses CSS custom properties (variables) for theming, making it easy to customize colors, spacing, and more.
|
|
213
|
+
|
|
214
|
+
### Import Styles
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
// Import in your layout or global CSS
|
|
218
|
+
import '@zm-editor/react/styles.css';
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Customize with CSS Variables
|
|
222
|
+
|
|
223
|
+
Override CSS variables to customize the editor appearance:
|
|
224
|
+
|
|
225
|
+
```css
|
|
226
|
+
/* In your global CSS */
|
|
227
|
+
:root {
|
|
228
|
+
/* Primary colors */
|
|
229
|
+
--zm-colors-primary: #8b5cf6;
|
|
230
|
+
--zm-colors-primary-hover: #7c3aed;
|
|
231
|
+
|
|
232
|
+
/* Editor background & text */
|
|
233
|
+
--zm-colors-editor-background: #ffffff;
|
|
234
|
+
--zm-colors-editor-text: #374151;
|
|
235
|
+
--zm-colors-editor-border: #e5e7eb;
|
|
236
|
+
|
|
237
|
+
/* Menu colors */
|
|
238
|
+
--zm-colors-menu-background: #ffffff;
|
|
239
|
+
--zm-colors-menu-hover: #f3f4f6;
|
|
240
|
+
--zm-colors-menu-selected: #eff6ff;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Dark mode */
|
|
244
|
+
.dark,
|
|
245
|
+
[data-theme='dark'] {
|
|
246
|
+
--zm-colors-primary: #a78bfa;
|
|
247
|
+
--zm-colors-editor-background: #1f2937;
|
|
248
|
+
--zm-colors-editor-text: #d1d5db;
|
|
249
|
+
--zm-colors-editor-border: #374151;
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Available CSS Variables
|
|
254
|
+
|
|
255
|
+
| Category | Variables |
|
|
256
|
+
|----------|-----------|
|
|
257
|
+
| **Editor** | `--zm-colors-editor-background`, `--zm-colors-editor-text`, `--zm-colors-editor-border`, `--zm-colors-heading` |
|
|
258
|
+
| **Menu** | `--zm-colors-menu-background`, `--zm-colors-menu-text`, `--zm-colors-menu-hover`, `--zm-colors-menu-selected` |
|
|
259
|
+
| **Primary** | `--zm-colors-primary`, `--zm-colors-primary-hover`, `--zm-colors-primary-text` |
|
|
260
|
+
| **Code** | `--zm-colors-code-background`, `--zm-colors-codeblock-background`, `--zm-colors-codeblock-text` |
|
|
261
|
+
| **Status** | `--zm-colors-success`, `--zm-colors-warning`, `--zm-colors-error`, `--zm-colors-info` |
|
|
262
|
+
| **Spacing** | `--zm-spacing-xs` (0.25rem), `--zm-spacing-sm` (0.5rem), `--zm-spacing-md` (1rem), `--zm-spacing-lg` (1.5rem) |
|
|
263
|
+
| **Radius** | `--zm-radius-sm` (4px), `--zm-radius-md` (6px), `--zm-radius-lg` (8px) |
|
|
264
|
+
| **Typography** | `--zm-font-family-sans`, `--zm-font-family-mono`, `--zm-font-size-*` |
|
|
265
|
+
|
|
266
|
+
See `variables.css` for the complete list of available variables.
|
|
267
|
+
|
|
268
|
+
### Dark Mode Support
|
|
269
|
+
|
|
270
|
+
zm-editor automatically supports dark mode via:
|
|
271
|
+
- `.dark` class (Tailwind CSS / next-themes)
|
|
272
|
+
- `[data-theme="dark"]` attribute
|
|
273
|
+
- `@media (prefers-color-scheme: dark)` system preference
|
|
274
|
+
|
|
275
|
+
## Browser Support
|
|
276
|
+
|
|
277
|
+
- Chrome (latest)
|
|
278
|
+
- Firefox (latest)
|
|
279
|
+
- Safari (latest)
|
|
280
|
+
- Edge (latest)
|
|
281
|
+
|
|
282
|
+
## Requirements
|
|
283
|
+
|
|
284
|
+
- React 18+
|
|
285
|
+
- Node.js 18+
|
|
286
|
+
|
|
287
|
+
## Related Packages
|
|
288
|
+
|
|
289
|
+
| Package | Description |
|
|
290
|
+
|---------|-------------|
|
|
291
|
+
| [@zm-editor/core](https://www.npmjs.com/package/@zm-editor/core) | Core Tiptap extensions and utilities |
|
|
292
|
+
|
|
293
|
+
## Links
|
|
294
|
+
|
|
295
|
+
- [GitHub Repository](https://github.com/hanumoka/zm-editor)
|
|
296
|
+
- [Documentation](https://github.com/hanumoka/zm-editor#readme)
|
|
297
|
+
|
|
298
|
+
## License
|
|
299
|
+
|
|
300
|
+
[MIT](https://github.com/hanumoka/zm-editor/blob/main/LICENSE)
|