@kaitify/react 0.0.1-beta.3 → 0.0.1-beta.5
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/docs/changelog.md +10 -0
- package/docs/guide/install.md +5 -5
- package/docs/guide/wrapper.md +4 -0
- package/examples/App.tsx +13 -11
- package/lib/editor/wrapper/props.d.ts +4 -0
- package/lib/kaitify-react.es.js +38 -17
- package/lib/kaitify-react.umd.js +2 -2
- package/package.json +3 -4
- package/src/editor/wrapper/props.ts +4 -0
- package/src/editor/wrapper/wrapper.tsx +1 -0
package/docs/changelog.md
CHANGED
|
@@ -5,6 +5,16 @@ title: 更新日志
|
|
|
5
5
|
|
|
6
6
|
# 更新日志
|
|
7
7
|
|
|
8
|
+
## v0.0.1-beta.5 <Badge type="tip" text='2026.02.09' />
|
|
9
|
+
|
|
10
|
+
- 更新 `@kaitify/core` 的依赖版本
|
|
11
|
+
- `Wrapper` 组件新增 `onRedressSelection` 属性
|
|
12
|
+
|
|
13
|
+
## v0.0.1-beta.4 <Badge type="tip" text='2026.02.04' />
|
|
14
|
+
|
|
15
|
+
- 更新 `@kaitify/core` 的依赖版本
|
|
16
|
+
- 升级依赖的less版本
|
|
17
|
+
|
|
8
18
|
## v0.0.1-beta.3 <Badge type="tip" text='2025.10.30' />
|
|
9
19
|
|
|
10
20
|
- kaitify-react 的第一个发布版本
|
package/docs/guide/install.md
CHANGED
|
@@ -6,7 +6,7 @@ title: 安装
|
|
|
6
6
|
|
|
7
7
|
## 下载 kaitify-react 本地到使用
|
|
8
8
|
|
|
9
|
-
- 下载地址:[kaitify-react](https://registry.npmmirror.com/@kaitify/react/download/@kaitify/react-0.0.1-beta.
|
|
9
|
+
- 下载地址:[kaitify-react](https://registry.npmmirror.com/@kaitify/react/download/@kaitify/react-0.0.1-beta.5.tgz)
|
|
10
10
|
- 下载完成后最终解压得到一个 package 文件夹,进入 package 文件夹后,将 package 目录下的整个 lib 目录拷贝到你的项目下
|
|
11
11
|
- 在 html 页面中引入 js
|
|
12
12
|
|
|
@@ -28,7 +28,7 @@ title: 安装
|
|
|
28
28
|
|
|
29
29
|
```html
|
|
30
30
|
<!-- 引入固定版本的kaitify -->
|
|
31
|
-
<script src="https://unpkg.com/@kaitify/react@0.0.1-beta.
|
|
31
|
+
<script src="https://unpkg.com/@kaitify/react@0.0.1-beta.5/lib/kaitify-react.umd.js"></script>
|
|
32
32
|
<!-- 始终引入最新的kaitify -->
|
|
33
33
|
<script src="https://unpkg.com/@kaitify/react/lib/kaitify-react.umd.js"></script>
|
|
34
34
|
```
|
|
@@ -50,21 +50,21 @@ title: 安装
|
|
|
50
50
|
npm install @kaitify/react
|
|
51
51
|
|
|
52
52
|
# 安装指定版本
|
|
53
|
-
npm install @kaitify/react@0.0.1-beta.
|
|
53
|
+
npm install @kaitify/react@0.0.1-beta.5
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
```bash [yarn]
|
|
57
57
|
yarn install @kaitify/react
|
|
58
58
|
|
|
59
59
|
# 安装指定版本
|
|
60
|
-
yarn install @kaitify/react@0.0.1-beta.
|
|
60
|
+
yarn install @kaitify/react@0.0.1-beta.5
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
```bash [pnpm]
|
|
64
64
|
pnpm install @kaitify/react
|
|
65
65
|
|
|
66
66
|
# 安装指定版本
|
|
67
|
-
pnpm install @kaitify/react@0.0.1-beta.
|
|
67
|
+
pnpm install @kaitify/react@0.0.1-beta.5
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
:::
|
package/docs/guide/wrapper.md
CHANGED
|
@@ -216,6 +216,10 @@ export default function App() {
|
|
|
216
216
|
|
|
217
217
|
编辑器 `updateView` 执行时,通过比对新旧节点数组获取需要格式化的节点,在这些节点被格式化前,触发此方法,回调参数即当前需要被格式化的节点,该方法返回一个节点,返回的节点将会被格式化,如果你不需要任何特殊处理,返回入参提供的节点即可
|
|
218
218
|
|
|
219
|
+
##### onRedressSelection <Badge type="danger" text="(this: Editor) => void" />
|
|
220
|
+
|
|
221
|
+
编辑器进行光标纠正时触发,在这里可以修改虚拟光标的位置
|
|
222
|
+
|
|
219
223
|
##### onSelectionUpdate <Badge type="danger" text="(this: Editor, selection: Selection) => void" />
|
|
220
224
|
|
|
221
225
|
编辑器光标发生变化触发的事件,回调参数为编辑器的 `Selection` 对象实例
|
package/examples/App.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo, useState } from 'react'
|
|
2
|
-
import { Wrapper as EditorWrapper, BoldMenu, AlignLeftMenu, AlignCenterMenu, AlignRightMenu, AlignJustifyMenu, AttachmentMenu, BackColorMenu, BlockquoteMenu, CodeMenu, CodeBlockMenu, ColorMenu, FontFamilyMenu, FontSizeMenu, HeadingMenu, RedoMenu, UndoMenu, HorizontalMenu, ImageMenu, IncreaseIndentMenu, DecreaseIndentMenu, ItalicMenu, LineHeightMenu, LinkMenu, OrderedListMenu, UnorderedListMenu, MathMenu, StrikethroughMenu, SubscriptMenu, SuperscriptMenu, TableMenu, UnderlineMenu, VideoMenu, TaskMenu, ClearFormatMenu, Divider, FullScreenMenu, EmojiMenu, Editor, StateType, KNodeMatchOptionType, Bubble, VideoControlsMenu, VideoMutedMenu, VideoLoopMenu, WrapUpMenu, CodeBlockLanguagesMenu, WrapDownMenu, LinkUnsetMenu, TableAddRowMenu, TableDeleteRowMenu, TableAddColumnMenu, TableDeleteColumnMenu, TableMergeCellMenu, TableUnsetMenu } from '../src/index'
|
|
2
|
+
import { Wrapper as EditorWrapper, BoldMenu, AlignLeftMenu, AlignCenterMenu, AlignRightMenu, AlignJustifyMenu, AttachmentMenu, BackColorMenu, BlockquoteMenu, CodeMenu, CodeBlockMenu, ColorMenu, FontFamilyMenu, FontSizeMenu, HeadingMenu, RedoMenu, UndoMenu, HorizontalMenu, ImageMenu, IncreaseIndentMenu, DecreaseIndentMenu, ItalicMenu, LineHeightMenu, LinkMenu, OrderedListMenu, UnorderedListMenu, MathMenu, StrikethroughMenu, SubscriptMenu, SuperscriptMenu, TableMenu, UnderlineMenu, VideoMenu, TaskMenu, ClearFormatMenu, Divider, FullScreenMenu, EmojiMenu, Editor, StateType, KNodeMatchOptionType, Bubble, VideoControlsMenu, VideoMutedMenu, VideoLoopMenu, WrapUpMenu, CodeBlockLanguagesMenu, WrapDownMenu, LinkUnsetMenu, TableAddRowMenu, TableDeleteRowMenu, TableAddColumnMenu, TableDeleteColumnMenu, TableMergeCellMenu, TableUnsetMenu, Menu } from '../src/index'
|
|
3
3
|
import './style.less'
|
|
4
4
|
|
|
5
5
|
export default function App() {
|
|
@@ -38,15 +38,7 @@ export default function App() {
|
|
|
38
38
|
<>
|
|
39
39
|
<div style={{ padding: 10 }}>
|
|
40
40
|
<div style={{ padding: 5 }}>
|
|
41
|
-
<button onClick={() => setDark(!dark)}>深色/浅色主题</button>
|
|
42
41
|
<button onClick={() => setShow(!show)}>显示/隐藏编辑器</button>
|
|
43
|
-
<button
|
|
44
|
-
onClick={() => {
|
|
45
|
-
console.log(state?.editor.value?.getHTML())
|
|
46
|
-
}}
|
|
47
|
-
>
|
|
48
|
-
获取HTML
|
|
49
|
-
</button>
|
|
50
42
|
</div>
|
|
51
43
|
<div id='area'>
|
|
52
44
|
<div id='before' style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', flexWrap: 'wrap', height: 100, background: dark ? '#1b1b1f' : '#fff' }}></div>
|
|
@@ -64,8 +56,18 @@ export default function App() {
|
|
|
64
56
|
onChange={setContent}
|
|
65
57
|
onCreated={onCreated}
|
|
66
58
|
appendBeforeTo={'#before'}
|
|
67
|
-
before={
|
|
59
|
+
before={state => (
|
|
68
60
|
<>
|
|
61
|
+
<Menu
|
|
62
|
+
onOperate={() => {
|
|
63
|
+
console.log(state?.editor.value?.getHTML())
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
获取HTML
|
|
67
|
+
</Menu>
|
|
68
|
+
<Menu onOperate={() => setDark(!dark)} active={state.editor.value?.isDark()}>
|
|
69
|
+
深色主题
|
|
70
|
+
</Menu>
|
|
69
71
|
<UndoMenu />
|
|
70
72
|
<RedoMenu />
|
|
71
73
|
<Divider />
|
|
@@ -109,7 +111,7 @@ export default function App() {
|
|
|
109
111
|
<TableMenu />
|
|
110
112
|
<FullScreenMenu target='#area' zIndex={2} />
|
|
111
113
|
</>
|
|
112
|
-
}
|
|
114
|
+
)}
|
|
113
115
|
after={<>总字数:{state?.editor.value?.getContent().length ?? 0}</>}
|
|
114
116
|
>
|
|
115
117
|
<Bubble visible={shouldBubble.visible} match={shouldBubble.match} style={{ padding: 5 }}>
|
|
@@ -149,6 +149,10 @@ export type WrapperPropsType = {
|
|
|
149
149
|
* 编辑器updateView执行时,通过比对新旧节点数组获取需要格式化的节点,在这些节点被格式化前,触发此方法,回调参数即当前需要被格式化的节点,该方法返回一个节点,返回的节点将会被格式化,如果你不需要任何特殊处理,返回入参提供的节点即可
|
|
150
150
|
*/
|
|
151
151
|
onBeforePatchNodeToFormat?: EditorConfigureOptionType['onBeforePatchNodeToFormat'];
|
|
152
|
+
/**
|
|
153
|
+
* 编辑器进行光标纠正时触发,在这里可以修改虚拟光标的位置
|
|
154
|
+
*/
|
|
155
|
+
onRedressSelection?: EditorConfigureOptionType['onRedressSelection'];
|
|
152
156
|
/**
|
|
153
157
|
* 编辑器光标发生变化触发的事件
|
|
154
158
|
*/
|
package/lib/kaitify-react.es.js
CHANGED
|
@@ -2530,6 +2530,13 @@ const registerExtension = function(extension) {
|
|
|
2530
2530
|
return node;
|
|
2531
2531
|
};
|
|
2532
2532
|
}
|
|
2533
|
+
if (extension.onRedressSelection) {
|
|
2534
|
+
const fn2 = this.onRedressSelection;
|
|
2535
|
+
this.onRedressSelection = () => {
|
|
2536
|
+
extension.onRedressSelection.apply(this);
|
|
2537
|
+
if (fn2) fn2.apply(this);
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2533
2540
|
if (extension.addCommands) {
|
|
2534
2541
|
const commands = extension.addCommands.apply(this);
|
|
2535
2542
|
this.commands = { ...this.commands, ...commands };
|
|
@@ -2606,21 +2613,20 @@ const updateSelection$1 = function() {
|
|
|
2606
2613
|
};
|
|
2607
2614
|
const redressSelection = function() {
|
|
2608
2615
|
if (!this.selection.focused()) {
|
|
2609
|
-
return
|
|
2616
|
+
return;
|
|
2610
2617
|
}
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2618
|
+
const startNode = this.selection.start.node;
|
|
2619
|
+
const endNode = this.selection.end.node;
|
|
2620
|
+
const startOffset = this.selection.start.offset;
|
|
2621
|
+
const endOffset = this.selection.end.offset;
|
|
2615
2622
|
const startNextNode = this.getNextSelectionNode(startNode);
|
|
2616
2623
|
if (startNextNode && startNextNode.isEqual(endNode) && startOffset == (startNode.isText() ? startNode.textContent.length : 1) && endOffset == 0) {
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2624
|
+
this.selection.end.node = startNode;
|
|
2625
|
+
this.selection.end.offset = startOffset;
|
|
2626
|
+
}
|
|
2627
|
+
if (this.onRedressSelection) {
|
|
2628
|
+
this.onRedressSelection.apply(this);
|
|
2622
2629
|
}
|
|
2623
|
-
return false;
|
|
2624
2630
|
};
|
|
2625
2631
|
const checkNodes = function() {
|
|
2626
2632
|
const nodes = this.stackNodes.filter((item) => {
|
|
@@ -3155,11 +3161,7 @@ const onSelectionChange = async function() {
|
|
|
3155
3161
|
if (!hasUpdate) {
|
|
3156
3162
|
return;
|
|
3157
3163
|
}
|
|
3158
|
-
|
|
3159
|
-
if (hasRedress) {
|
|
3160
|
-
await this.updateRealSelection();
|
|
3161
|
-
return;
|
|
3162
|
-
}
|
|
3164
|
+
redressSelection.apply(this);
|
|
3163
3165
|
this.history.updateSelection(this.selection);
|
|
3164
3166
|
if (typeof this.onSelectionUpdate == "function") {
|
|
3165
3167
|
this.onSelectionUpdate.apply(this, [this.selection]);
|
|
@@ -3307,6 +3309,7 @@ class Extension {
|
|
|
3307
3309
|
__publicField(this, "onAfterUpdateView");
|
|
3308
3310
|
__publicField(this, "onDetachMentBlockFromParent");
|
|
3309
3311
|
__publicField(this, "onBeforePatchNodeToFormat");
|
|
3312
|
+
__publicField(this, "onRedressSelection");
|
|
3310
3313
|
__publicField(this, "addCommands");
|
|
3311
3314
|
this.name = name;
|
|
3312
3315
|
}
|
|
@@ -3332,6 +3335,7 @@ class Extension {
|
|
|
3332
3335
|
if (options.onAfterUpdateView) extension.onAfterUpdateView = options.onAfterUpdateView;
|
|
3333
3336
|
if (options.onDetachMentBlockFromParent) extension.onDetachMentBlockFromParent = options.onDetachMentBlockFromParent;
|
|
3334
3337
|
if (options.onBeforePatchNodeToFormat) extension.onBeforePatchNodeToFormat = options.onBeforePatchNodeToFormat;
|
|
3338
|
+
if (options.onRedressSelection) extension.onRedressSelection = options.onRedressSelection;
|
|
3335
3339
|
if (options.addCommands) extension.addCommands = options.addCommands;
|
|
3336
3340
|
return extension;
|
|
3337
3341
|
}
|
|
@@ -36115,6 +36119,20 @@ const TableExtension = () => Extension.create({
|
|
|
36115
36119
|
}
|
|
36116
36120
|
}
|
|
36117
36121
|
},
|
|
36122
|
+
onRedressSelection() {
|
|
36123
|
+
if (this.selection.focused()) {
|
|
36124
|
+
const startNode = this.selection.start.node;
|
|
36125
|
+
const endNode = this.selection.end.node;
|
|
36126
|
+
if (!!startNode.getMatchNode({ tag: "td" }) && !!endNode.getMatchNode({ tag: "td" })) {
|
|
36127
|
+
const startOffset = this.selection.start.offset;
|
|
36128
|
+
const startNextNode = this.getNextSelectionNode(startNode);
|
|
36129
|
+
if (startNextNode && startNextNode.isEqual(endNode) && startOffset == (startNode.isText() ? startNode.textContent.length : 1)) {
|
|
36130
|
+
this.selection.start.node = endNode;
|
|
36131
|
+
this.selection.start.offset = 0;
|
|
36132
|
+
}
|
|
36133
|
+
}
|
|
36134
|
+
}
|
|
36135
|
+
},
|
|
36118
36136
|
addCommands() {
|
|
36119
36137
|
const getTable = () => {
|
|
36120
36138
|
return this.getMatchNodeBySelection({
|
|
@@ -36867,6 +36885,7 @@ class Editor {
|
|
|
36867
36885
|
__publicField(this, "onAfterUpdateView");
|
|
36868
36886
|
__publicField(this, "onDetachMentBlockFromParent");
|
|
36869
36887
|
__publicField(this, "onBeforePatchNodeToFormat");
|
|
36888
|
+
__publicField(this, "onRedressSelection");
|
|
36870
36889
|
__publicField(this, "guid", createGuid());
|
|
36871
36890
|
__publicField(this, "selection", new Selection());
|
|
36872
36891
|
__publicField(this, "history", new History());
|
|
@@ -37088,7 +37107,7 @@ class Editor {
|
|
|
37088
37107
|
config2.children = [];
|
|
37089
37108
|
}
|
|
37090
37109
|
let node = KNode.create(config2);
|
|
37091
|
-
if (!
|
|
37110
|
+
if (!node.isClosed()) {
|
|
37092
37111
|
Array.from(dom.childNodes).forEach((child) => {
|
|
37093
37112
|
if (child.nodeType == 1 || child.nodeType == 3) {
|
|
37094
37113
|
const childNode = this.domParseNode(child);
|
|
@@ -38354,6 +38373,7 @@ class Editor {
|
|
|
38354
38373
|
if (options.onAfterUpdateView) editor.onAfterUpdateView = options.onAfterUpdateView;
|
|
38355
38374
|
if (options.onDetachMentBlockFromParent) editor.onDetachMentBlockFromParent = options.onDetachMentBlockFromParent;
|
|
38356
38375
|
if (options.onBeforePatchNodeToFormat) editor.onBeforePatchNodeToFormat = options.onBeforePatchNodeToFormat;
|
|
38376
|
+
if (options.onRedressSelection) editor.onRedressSelection = options.onRedressSelection;
|
|
38357
38377
|
editor.extensions.forEach((item) => registerExtension.apply(editor, [item]));
|
|
38358
38378
|
editor.setEditable(typeof options.editable == "boolean" ? options.editable : true);
|
|
38359
38379
|
await editor.review(options.value || "");
|
|
@@ -40211,6 +40231,7 @@ const Wrapper = forwardRef((props, ref) => {
|
|
|
40211
40231
|
onPasteFile: props.onPasteFile,
|
|
40212
40232
|
onDetachMentBlockFromParent: props.onDetachMentBlockFromParent,
|
|
40213
40233
|
onBeforePatchNodeToFormat: props.onBeforePatchNodeToFormat,
|
|
40234
|
+
onRedressSelection: props.onRedressSelection,
|
|
40214
40235
|
onInsertParagraph: props.onInsertParagraph,
|
|
40215
40236
|
onDeleteComplete: props.onDeleteComplete,
|
|
40216
40237
|
onKeydown: props.onKeydown,
|