@ctzhian/tiptap 1.6.4 → 1.6.6
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/README.md +121 -12
- package/dist/component/Toolbar/EditorInsert/index.js +0 -15
- package/dist/index.css +2 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,39 +3,148 @@
|
|
|
3
3
|
[](https://npmjs.org/package/@ctzhian/tiptap)
|
|
4
4
|
[](https://npmjs.org/package/@ctzhian/tiptap)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
基于 Tiptap v3 二次开发的 React 富文本编辑器组件集,内置工具栏、主题、结构化 Diff、高亮、表格、附件/音视频/数学等常用扩展,开箱即用。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
- 核心能力:`useTiptap`、`Editor`、`EditorToolbar`、`EditorDiff`
|
|
9
|
+
- 技术栈:React 18、Tiptap v3、MUI v7、Emotion 11
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## 安装
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @ctzhian/tiptap
|
|
15
|
+
# 同时安装 peer 依赖
|
|
16
|
+
pnpm add @mui/material @mui/icons-material @emotion/react @emotion/styled
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
样式(必须):
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import '@ctzhian/tiptap/dist/index.css';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 快速开始
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import React from 'react';
|
|
29
|
+
import {
|
|
30
|
+
EditorThemeProvider,
|
|
31
|
+
EditorToolbar,
|
|
32
|
+
Editor,
|
|
33
|
+
useTiptap,
|
|
34
|
+
} from '@ctzhian/tiptap';
|
|
35
|
+
import '@ctzhian/tiptap/dist/index.css';
|
|
36
|
+
|
|
37
|
+
export default function Demo() {
|
|
38
|
+
const { editor } = useTiptap({
|
|
39
|
+
editable: true,
|
|
40
|
+
content: '<p>Hello Tiptap</p>',
|
|
41
|
+
exclude: ['invisibleCharacters'],
|
|
42
|
+
onSave: (ed) => console.log('save:', ed.getHTML()),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<EditorThemeProvider mode="light">
|
|
47
|
+
<div
|
|
48
|
+
style={{
|
|
49
|
+
border: '1px solid #eee',
|
|
50
|
+
borderRadius: 10,
|
|
51
|
+
padding: '0 10px 10px',
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
<div style={{ borderBottom: '1px solid #eee', marginBottom: 30 }}>
|
|
55
|
+
<EditorToolbar editor={editor} />
|
|
56
|
+
</div>
|
|
57
|
+
<Editor editor={editor} />
|
|
58
|
+
</div>
|
|
59
|
+
</EditorThemeProvider>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 模块说明
|
|
65
|
+
|
|
66
|
+
### useTiptap(核心 Hook)
|
|
67
|
+
|
|
68
|
+
创建并管理 Tiptap 实例,统一扩展与回调。
|
|
69
|
+
|
|
70
|
+
- 常用入参:
|
|
71
|
+
- `editable?: boolean` 是否可编辑(默认 true)
|
|
72
|
+
- `content?: string | JSON` 初始内容
|
|
73
|
+
- `exclude?: string[]` 需要禁用的内置扩展名
|
|
74
|
+
- `extensions?: Extension[]` 自定义扩展
|
|
75
|
+
- `mentionItems?: string[]`、`onMentionFilter?: ({ query }) => Promise<string[]>`
|
|
76
|
+
- `onSave?(editor)`、`onError?(error)`
|
|
77
|
+
- `onUpload?(file, onProgress)` 自定义上传,返回可访问地址
|
|
78
|
+
- `onTocUpdate?(toc)`、`onAiWritingGetSuggestion?({ prefix, suffix }) => Promise<string>`
|
|
79
|
+
- 返回:`{ editor, getText, getHTML, getJSON, getMarkdownByJSON }`
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
const { editor } = useTiptap({
|
|
83
|
+
editable: true,
|
|
84
|
+
onSave: (ed) => console.log(ed.getHTML()),
|
|
85
|
+
onUpload: async (file, onProgress) => {
|
|
86
|
+
onProgress?.({ progress: 1 });
|
|
87
|
+
return 'https://example.com/file/url';
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### EditorToolbar(工具栏)
|
|
93
|
+
|
|
94
|
+
与 `editor` 绑定的可视化工具栏:撤销/重做、标题/字号、加粗/斜体/上下标、颜色、列表、对齐、链接、更多菜单,以及 AI 伴写开关。
|
|
95
|
+
|
|
96
|
+
- Props:`{ editor: Editor; menuInToolbarMore?: ToolbarItemType[] }`
|
|
13
97
|
|
|
14
|
-
|
|
98
|
+
```tsx
|
|
99
|
+
<EditorToolbar
|
|
100
|
+
editor={editor}
|
|
101
|
+
menuInToolbarMore={[{ id: 'my-action', label: '自定义' }]}
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Editor(编辑区)
|
|
106
|
+
|
|
107
|
+
渲染编辑区域,包含文字选择气泡菜单与拖拽锚点菜单。
|
|
108
|
+
|
|
109
|
+
- Props:`{ editor: Editor; menuInDragHandle?: MenuItem[]; menuInBubbleMenu?: MenuItem[]; onTip?: (type, tip) => void }`
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
<Editor editor={editor} />
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### EditorDiff(结构化对比)
|
|
116
|
+
|
|
117
|
+
以只读方式展示两段 HTML 的结构化差异。
|
|
118
|
+
|
|
119
|
+
- Props:`{ oldHtml: string; newHtml: string }`
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
<EditorDiff oldHtml={'<p>old</p>'} newHtml={'<p><strong>new</strong></p>'} />
|
|
123
|
+
```
|
|
15
124
|
|
|
16
125
|
## Development
|
|
17
126
|
|
|
18
127
|
```bash
|
|
19
128
|
# install dependencies
|
|
20
|
-
|
|
129
|
+
pnpm install
|
|
21
130
|
|
|
22
131
|
# develop library by docs demo
|
|
23
|
-
|
|
132
|
+
pnpm start
|
|
24
133
|
|
|
25
134
|
# build library source code
|
|
26
|
-
|
|
135
|
+
pnpm run build
|
|
27
136
|
|
|
28
137
|
# build library source code in watch mode
|
|
29
|
-
|
|
138
|
+
pnpm run build:watch
|
|
30
139
|
|
|
31
140
|
# build docs
|
|
32
|
-
|
|
141
|
+
pnpm run docs:build
|
|
33
142
|
|
|
34
143
|
# Locally preview the production build.
|
|
35
|
-
|
|
144
|
+
pnpm run docs:preview
|
|
36
145
|
|
|
37
146
|
# check your project for potential problems
|
|
38
|
-
|
|
147
|
+
pnpm run doctor
|
|
39
148
|
```
|
|
40
149
|
|
|
41
150
|
## LICENSE
|
|
@@ -287,21 +287,6 @@ var EditorInsert = function EditorInsert(_ref) {
|
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
289
|
}]
|
|
290
|
-
}, {
|
|
291
|
-
label: 'Iframe 链接',
|
|
292
|
-
key: 'iframe',
|
|
293
|
-
icon: /*#__PURE__*/React.createElement(WindowFillIcon, {
|
|
294
|
-
sx: {
|
|
295
|
-
fontSize: '1rem'
|
|
296
|
-
}
|
|
297
|
-
}),
|
|
298
|
-
onClick: function onClick() {
|
|
299
|
-
return editor.commands.setIframe({
|
|
300
|
-
src: '',
|
|
301
|
-
width: 760,
|
|
302
|
-
height: 400
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
290
|
}, {
|
|
306
291
|
customLabel: /*#__PURE__*/React.createElement(Typography, {
|
|
307
292
|
sx: {
|
package/dist/index.css
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
.tiptap.ProseMirror {
|
|
4
4
|
overflow-y: auto;
|
|
5
5
|
outline: none;
|
|
6
|
-
color: var(--mui-palette-text-
|
|
6
|
+
color: var(--mui-palette-text-primary);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/* 节点缩进(依赖 data-indent 属性) */
|
|
@@ -74,7 +74,6 @@
|
|
|
74
74
|
margin: 0 0 20px;
|
|
75
75
|
border-radius: 10px;
|
|
76
76
|
border: 1px solid var(--mui-palette-divider);
|
|
77
|
-
color: var(--mui-palette-text-secondary);
|
|
78
77
|
background-color: var(--mui-palette-background-paper3);
|
|
79
78
|
}
|
|
80
79
|
|
|
@@ -291,7 +290,6 @@
|
|
|
291
290
|
position: relative;
|
|
292
291
|
color: inherit;
|
|
293
292
|
font-style: inherit;
|
|
294
|
-
color: var(--mui-palette-text-primary);
|
|
295
293
|
}
|
|
296
294
|
|
|
297
295
|
.tiptap.ProseMirror h1 {
|
|
@@ -389,7 +387,6 @@
|
|
|
389
387
|
.tiptap.ProseMirror table th {
|
|
390
388
|
background-color: var(--mui-palette-background-paper3);
|
|
391
389
|
font-weight: 600;
|
|
392
|
-
color: var(--mui-palette-text-primary);
|
|
393
390
|
text-transform: uppercase;
|
|
394
391
|
letter-spacing: 0.5px;
|
|
395
392
|
text-align: left;
|
|
@@ -556,7 +553,7 @@
|
|
|
556
553
|
|
|
557
554
|
/* AI 续写建议样式 */
|
|
558
555
|
.tiptap.ProseMirror .ai-writing-suggestion {
|
|
559
|
-
color: var(--mui-palette-text-
|
|
556
|
+
color: color-mix(in srgb, var(--mui-palette-text-primary) 15%, transparent);
|
|
560
557
|
pointer-events: none;
|
|
561
558
|
user-select: none;
|
|
562
559
|
white-space: pre-wrap;
|