@block-kit/react 1.0.21 → 1.0.23
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/dist/es/hooks/use-limit.d.ts +4 -0
- package/dist/es/hooks/use-limit.js +17 -0
- package/dist/es/index.d.ts +1 -0
- package/dist/es/index.js +1 -0
- package/dist/es/model/block.js +29 -8
- package/dist/es/model/leaf.d.ts +0 -1
- package/dist/es/model/leaf.js +3 -3
- package/dist/es/model/line.d.ts +0 -1
- package/dist/es/model/line.js +8 -6
- package/dist/es/preset/editable.js +5 -0
- package/dist/es/preset/isolate.d.ts +1 -0
- package/dist/es/preset/isolate.js +6 -1
- package/dist/es/preset/text.js +5 -4
- package/dist/lib/hooks/use-limit.d.ts +4 -0
- package/dist/lib/hooks/use-limit.js +22 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +4 -1
- package/dist/lib/model/block.js +28 -7
- package/dist/lib/model/leaf.d.ts +0 -1
- package/dist/lib/model/leaf.js +2 -2
- package/dist/lib/model/line.d.ts +0 -1
- package/dist/lib/model/line.js +7 -5
- package/dist/lib/preset/editable.js +5 -0
- package/dist/lib/preset/isolate.d.ts +1 -0
- package/dist/lib/preset/isolate.js +6 -1
- package/dist/lib/preset/text.js +5 -4
- package/package.json +4 -4
- package/dist/es/model/effect.d.ts +0 -12
- package/dist/es/model/effect.js +0 -36
- package/dist/lib/model/effect.d.ts +0 -12
- package/dist/lib/model/effect.js +0 -62
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Func } from "@block-kit/utils";
|
|
2
|
+
import { debounce, throttle } from "@block-kit/utils";
|
|
3
|
+
export declare const useDebounceMemoFn: <T extends Func.Any>(fn: T, options: Func.Parameters<typeof debounce>[1]) => import("@block-kit/utils").DebouncedFn<T>;
|
|
4
|
+
export declare const useThrottleMemoFn: <T extends Func.Any>(fn: T, options: Func.Parameters<typeof throttle>[1]) => import("@block-kit/utils").ThrottledFn<T>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { debounce, throttle } from "@block-kit/utils";
|
|
2
|
+
import { useMemoFn } from "@block-kit/utils/dist/es/hooks";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
export const useDebounceMemoFn = (fn, options) => {
|
|
5
|
+
const memorized = useMemoFn(fn);
|
|
6
|
+
const debouncedFn = useMemo(() => {
|
|
7
|
+
return debounce(memorized, options);
|
|
8
|
+
}, [memorized]);
|
|
9
|
+
return debouncedFn;
|
|
10
|
+
};
|
|
11
|
+
export const useThrottleMemoFn = (fn, options) => {
|
|
12
|
+
const memorized = useMemoFn(fn);
|
|
13
|
+
const throttledFn = useMemo(() => {
|
|
14
|
+
return throttle(memorized, options);
|
|
15
|
+
}, [memorized]);
|
|
16
|
+
return throttledFn;
|
|
17
|
+
};
|
package/dist/es/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { useComposing } from "./hooks/use-composing";
|
|
2
2
|
export { BlockKitContext, useEditorStatic } from "./hooks/use-editor";
|
|
3
|
+
export { useDebounceMemoFn, useThrottleMemoFn } from "./hooks/use-limit";
|
|
3
4
|
export { ReadonlyContext, useReadonly } from "./hooks/use-readonly";
|
|
4
5
|
export { BlockModel } from "./model/block";
|
|
5
6
|
export { EOLModel } from "./model/eol";
|
package/dist/es/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { useComposing } from "./hooks/use-composing";
|
|
2
2
|
export { BlockKitContext, useEditorStatic } from "./hooks/use-editor";
|
|
3
|
+
export { useDebounceMemoFn, useThrottleMemoFn } from "./hooks/use-limit";
|
|
3
4
|
export { ReadonlyContext, useReadonly } from "./hooks/use-readonly";
|
|
4
5
|
export { BlockModel } from "./model/block";
|
|
5
6
|
export { EOLModel } from "./model/eol";
|
package/dist/es/model/block.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { BLOCK_ID_KEY, BLOCK_KEY, EDITOR_EVENT, EDITOR_STATE } from "@block-kit/core";
|
|
3
3
|
import { useMemoFn } from "@block-kit/utils/dist/es/hooks";
|
|
4
|
-
import React, { useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { withWrapLineNodes } from "../plugin/modules/wrap";
|
|
6
6
|
import { rewriteRemoveChild } from "../utils/dirty-dom";
|
|
7
7
|
import { JSX_TO_STATE } from "../utils/weak-map";
|
|
8
|
-
import { PaintEffectModel } from "./effect";
|
|
9
8
|
import { LineModel } from "./line";
|
|
10
9
|
import { Placeholder } from "./ph";
|
|
11
10
|
const BlockView = props => {
|
|
@@ -15,14 +14,13 @@ const BlockView = props => {
|
|
|
15
14
|
/**
|
|
16
15
|
* 设置 Block DOM 节点
|
|
17
16
|
*/
|
|
18
|
-
const setModel =
|
|
17
|
+
const setModel = (ref) => {
|
|
19
18
|
if (ref) {
|
|
20
19
|
// ref 触发时机最早 ref -> layout effect -> effect
|
|
21
|
-
// 需要保证 editor 稳定, 重渲染并不会触发执行, 导致 DOM 映射关系失效
|
|
22
20
|
editor.model.setBlockModel(ref, state);
|
|
23
21
|
rewriteRemoveChild(ref);
|
|
24
22
|
}
|
|
25
|
-
}
|
|
23
|
+
};
|
|
26
24
|
/**
|
|
27
25
|
* 数据同步变更, 异步批量绘制变更
|
|
28
26
|
*/
|
|
@@ -48,6 +46,29 @@ const BlockView = props => {
|
|
|
48
46
|
editor.event.off(EDITOR_EVENT.CONTENT_CHANGE, onContentChange);
|
|
49
47
|
};
|
|
50
48
|
}, [editor.event, onContentChange]);
|
|
49
|
+
/**
|
|
50
|
+
* 视图更新需要重新设置选区, 依赖于行状态变更
|
|
51
|
+
*/
|
|
52
|
+
useLayoutEffect(() => {
|
|
53
|
+
const selection = editor.selection.get();
|
|
54
|
+
// 同步计算完成后更新浏览器选区, 等待 Paint
|
|
55
|
+
if (editor.state.isFocused() && selection) {
|
|
56
|
+
editor.logger.debug("UpdateDOMSelection");
|
|
57
|
+
editor.selection.updateDOMSelection(true);
|
|
58
|
+
}
|
|
59
|
+
}, [editor, lines]);
|
|
60
|
+
/**
|
|
61
|
+
* 视图更新需要触发视图绘制完成事件, 依赖于行状态变更
|
|
62
|
+
*/
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
// state -> parent -> node -> child ->|
|
|
65
|
+
// effect <- parent <- node <- child <-|
|
|
66
|
+
editor.logger.debug("OnPaint");
|
|
67
|
+
editor.state.set(EDITOR_STATE.PAINTING, false);
|
|
68
|
+
Promise.resolve().then(() => {
|
|
69
|
+
editor.event.trigger(EDITOR_EVENT.PAINT, {});
|
|
70
|
+
});
|
|
71
|
+
}, [editor, lines]);
|
|
51
72
|
/**
|
|
52
73
|
* 处理行节点
|
|
53
74
|
*/
|
|
@@ -60,8 +81,8 @@ const BlockView = props => {
|
|
|
60
81
|
}
|
|
61
82
|
}
|
|
62
83
|
}
|
|
63
|
-
return lines.map(
|
|
64
|
-
const node =
|
|
84
|
+
return lines.map(line => {
|
|
85
|
+
const node = _jsx(LineModel, { editor: editor, lineState: line }, line.key);
|
|
65
86
|
JSX_TO_STATE.set(node, line);
|
|
66
87
|
return node;
|
|
67
88
|
});
|
|
@@ -72,7 +93,7 @@ const BlockView = props => {
|
|
|
72
93
|
const children = useMemo(() => {
|
|
73
94
|
return withWrapLineNodes(editor, elements);
|
|
74
95
|
}, [editor, elements]);
|
|
75
|
-
return (_jsxs("div", { [BLOCK_KEY]: true, [BLOCK_ID_KEY]: state.key, ref: setModel, children: [_jsx(
|
|
96
|
+
return (_jsxs("div", { [BLOCK_KEY]: true, [BLOCK_ID_KEY]: state.key, ref: setModel, children: [_jsx(Placeholder, { editor: editor, lines: lines, placeholder: props.placeholder }), children] }));
|
|
76
97
|
};
|
|
77
98
|
/** Block Model */
|
|
78
99
|
export const BlockModel = React.memo(BlockView);
|
package/dist/es/model/leaf.d.ts
CHANGED
package/dist/es/model/leaf.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { LEAF_KEY, PLUGIN_FUNC } from "@block-kit/core";
|
|
3
3
|
import { SPACE } from "@block-kit/utils";
|
|
4
|
-
import { useForceUpdate
|
|
4
|
+
import { useForceUpdate } from "@block-kit/utils/dist/es/hooks";
|
|
5
5
|
import React, { useMemo } from "react";
|
|
6
6
|
import { Text } from "../preset/text";
|
|
7
7
|
import { rewriteRemoveChild } from "../utils/dirty-dom";
|
|
@@ -12,13 +12,13 @@ const LeafView = props => {
|
|
|
12
12
|
/**
|
|
13
13
|
* 设置叶子 DOM 节点
|
|
14
14
|
*/
|
|
15
|
-
const setModel =
|
|
15
|
+
const setModel = (ref) => {
|
|
16
16
|
if (ref) {
|
|
17
17
|
rewriteRemoveChild(ref);
|
|
18
18
|
editor.model.setLeafModel(ref, leafState);
|
|
19
19
|
}
|
|
20
20
|
LEAF_TO_REMOUNT.set(leafState, forceUpdate);
|
|
21
|
-
}
|
|
21
|
+
};
|
|
22
22
|
/**
|
|
23
23
|
* 处理叶子节点的渲染
|
|
24
24
|
*/
|
package/dist/es/model/line.d.ts
CHANGED
package/dist/es/model/line.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { CALLER_TYPE, NODE_KEY, PLUGIN_FUNC } from "@block-kit/core";
|
|
3
3
|
import { EOL, EOL_OP } from "@block-kit/delta";
|
|
4
4
|
import { SPACE } from "@block-kit/utils";
|
|
5
|
-
import {
|
|
5
|
+
import { useUpdateEffect, useUpdateLayoutEffect } from "@block-kit/utils/dist/es/hooks";
|
|
6
6
|
import React, { useMemo } from "react";
|
|
7
7
|
import { withWrapLeafNodes } from "../plugin/modules/wrap";
|
|
8
8
|
import { rewriteRemoveChild, updateDirtyLeaf, updateDirtyText } from "../utils/dirty-dom";
|
|
@@ -14,12 +14,12 @@ const LineView = props => {
|
|
|
14
14
|
/**
|
|
15
15
|
* 设置行 DOM 节点
|
|
16
16
|
*/
|
|
17
|
-
const setModel =
|
|
17
|
+
const setModel = (ref) => {
|
|
18
18
|
if (ref) {
|
|
19
19
|
editor.model.setLineModel(ref, lineState);
|
|
20
20
|
rewriteRemoveChild(ref);
|
|
21
21
|
}
|
|
22
|
-
}
|
|
22
|
+
};
|
|
23
23
|
/**
|
|
24
24
|
* 编辑器行结构布局计算后同步调用
|
|
25
25
|
* - 首次处理会将所有 DOM 渲染, 不需要执行脏数据检查
|
|
@@ -55,13 +55,15 @@ const LineView = props => {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
const leaves = lineState.getLeaves();
|
|
58
|
+
// 首先渲染所有非 EOL 的叶子节点
|
|
58
59
|
const textLeaves = leaves.slice(0, -1);
|
|
59
|
-
const nodes = textLeaves.map(
|
|
60
|
-
const node = _jsx(LeafModel, { editor: editor,
|
|
60
|
+
const nodes = textLeaves.map(n => {
|
|
61
|
+
const node = _jsx(LeafModel, { editor: editor, leafState: n }, n.key);
|
|
61
62
|
JSX_TO_STATE.set(node, n);
|
|
62
63
|
return node;
|
|
63
64
|
});
|
|
64
|
-
//
|
|
65
|
+
// 存在内容时不渲染 EOL, 避免块级元素出现额外视觉上的换行
|
|
66
|
+
// 若是空行则仅存在一个 Leaf, 此时需要渲染空的占位节点
|
|
65
67
|
if (!nodes.length && leaves[0]) {
|
|
66
68
|
const leaf = leaves[0];
|
|
67
69
|
const node = _jsx(EOLModel, { editor: editor, leafState: leaf }, EOL);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { EDITOR_KEY, Point, Range } from "@block-kit/core";
|
|
3
3
|
import { cs } from "@block-kit/utils";
|
|
4
|
+
import { useUpdateEffect } from "@block-kit/utils/dist/es/hooks";
|
|
4
5
|
import { useEffect, useLayoutEffect, useRef } from "react";
|
|
5
6
|
import { useEditorStatic } from "../hooks/use-editor";
|
|
6
7
|
import { useReadonly } from "../hooks/use-readonly";
|
|
@@ -22,6 +23,10 @@ export const Editable = props => {
|
|
|
22
23
|
!preventDestroy && editor.destroy();
|
|
23
24
|
};
|
|
24
25
|
}, [editor, preventDestroy]);
|
|
26
|
+
useUpdateEffect(() => {
|
|
27
|
+
// 需要保证 editor 实例稳定, 重渲染并不会触发 ref 执行, 导致 DOM 映射关系失效
|
|
28
|
+
editor.logger.warning("Confirm the uniqueness of the editor instance.", editor);
|
|
29
|
+
}, [editor]);
|
|
25
30
|
useEffect(() => {
|
|
26
31
|
// COMPAT: 这里有个奇怪的表现
|
|
27
32
|
// 当自动聚焦时, 必须要先更新浏览器选区再聚焦
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { EDITOR_EVENT, ISOLATED_KEY } from "@block-kit/core";
|
|
3
3
|
import { stopNativeEvent } from "@block-kit/utils";
|
|
4
|
+
import { useMemoFn } from "@block-kit/utils/dist/es/hooks";
|
|
4
5
|
import { useEffect, useState } from "react";
|
|
5
6
|
/**
|
|
6
7
|
* 独立节点嵌入 HOC
|
|
@@ -9,6 +10,10 @@ import { useEffect, useState } from "react";
|
|
|
9
10
|
*/
|
|
10
11
|
export const Isolate = props => {
|
|
11
12
|
const [ref, setRef] = useState(null);
|
|
13
|
+
const onRef = useMemoFn((dom) => {
|
|
14
|
+
setRef(dom);
|
|
15
|
+
props.onRef && props.onRef(dom);
|
|
16
|
+
});
|
|
12
17
|
useEffect(() => {
|
|
13
18
|
const el = ref;
|
|
14
19
|
if (!el)
|
|
@@ -47,5 +52,5 @@ export const Isolate = props => {
|
|
|
47
52
|
el.removeEventListener(COMPOSITION_END, stopNativeEvent);
|
|
48
53
|
};
|
|
49
54
|
}, [ref]);
|
|
50
|
-
return (_jsx("span", { ref:
|
|
55
|
+
return (_jsx("span", { ref: onRef, [ISOLATED_KEY]: true, className: props.className, style: props.style, contentEditable: false, children: props.children }));
|
|
51
56
|
};
|
package/dist/es/preset/text.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { LEAF_STRING } from "@block-kit/core";
|
|
3
|
-
import { useMemoFn } from "@block-kit/utils/dist/es/hooks";
|
|
4
3
|
/**
|
|
5
4
|
* 文本节点
|
|
6
5
|
* @param props
|
|
@@ -9,11 +8,13 @@ export const Text = props => {
|
|
|
9
8
|
/**
|
|
10
9
|
* 处理 ref 回调
|
|
11
10
|
* - 节点执行时机为 ref -> layout effect -> effect
|
|
12
|
-
* -
|
|
11
|
+
* - 若是不保持引用不变, 会导致回调在 rerender 时被多次调用 null/span 状态
|
|
13
12
|
* - https://18.react.dev/reference/react-dom/components/common#ref-callback
|
|
13
|
+
* - 而若是保持引用不变, 会导致节点变化渲染时, 即使文本内容变化了, 也不会触发回调
|
|
14
|
+
* - 因为 LEAF 映射 TEXT 依赖于回调函数的执行, 就会导致叶子对象变化时, 不会重新映射
|
|
14
15
|
*/
|
|
15
|
-
const onRef =
|
|
16
|
+
const onRef = (dom) => {
|
|
16
17
|
props.onRef && props.onRef(dom);
|
|
17
|
-
}
|
|
18
|
+
};
|
|
18
19
|
return (_jsx("span", { ref: onRef, [LEAF_STRING]: true, children: props.children }));
|
|
19
20
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Func } from "@block-kit/utils";
|
|
2
|
+
import { debounce, throttle } from "@block-kit/utils";
|
|
3
|
+
export declare const useDebounceMemoFn: <T extends Func.Any>(fn: T, options: Func.Parameters<typeof debounce>[1]) => import("@block-kit/utils").DebouncedFn<T>;
|
|
4
|
+
export declare const useThrottleMemoFn: <T extends Func.Any>(fn: T, options: Func.Parameters<typeof throttle>[1]) => import("@block-kit/utils").ThrottledFn<T>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useThrottleMemoFn = exports.useDebounceMemoFn = void 0;
|
|
4
|
+
const utils_1 = require("@block-kit/utils");
|
|
5
|
+
const hooks_1 = require("@block-kit/utils/dist/es/hooks");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const useDebounceMemoFn = (fn, options) => {
|
|
8
|
+
const memorized = (0, hooks_1.useMemoFn)(fn);
|
|
9
|
+
const debouncedFn = (0, react_1.useMemo)(() => {
|
|
10
|
+
return (0, utils_1.debounce)(memorized, options);
|
|
11
|
+
}, [memorized]);
|
|
12
|
+
return debouncedFn;
|
|
13
|
+
};
|
|
14
|
+
exports.useDebounceMemoFn = useDebounceMemoFn;
|
|
15
|
+
const useThrottleMemoFn = (fn, options) => {
|
|
16
|
+
const memorized = (0, hooks_1.useMemoFn)(fn);
|
|
17
|
+
const throttledFn = (0, react_1.useMemo)(() => {
|
|
18
|
+
return (0, utils_1.throttle)(memorized, options);
|
|
19
|
+
}, [memorized]);
|
|
20
|
+
return throttledFn;
|
|
21
|
+
};
|
|
22
|
+
exports.useThrottleMemoFn = useThrottleMemoFn;
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { useComposing } from "./hooks/use-composing";
|
|
2
2
|
export { BlockKitContext, useEditorStatic } from "./hooks/use-editor";
|
|
3
|
+
export { useDebounceMemoFn, useThrottleMemoFn } from "./hooks/use-limit";
|
|
3
4
|
export { ReadonlyContext, useReadonly } from "./hooks/use-readonly";
|
|
4
5
|
export { BlockModel } from "./model/block";
|
|
5
6
|
export { EOLModel } from "./model/eol";
|
package/dist/lib/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LEAF_TO_ZERO_TEXT = exports.LEAF_TO_TEXT = exports.LEAF_TO_REMOUNT = exports.JSX_TO_STATE = exports.MountNode = exports.preventReactEvent = exports.preventNativeEvent = exports.rewriteRemoveChild = exports.NO_CURSOR = exports.ZeroSpace = exports.Void = exports.Text = exports.Isolate = exports.Embed = exports.Editable = exports.BlockKit = exports.InjectWrapKeys = exports.Priority = exports.EditorPlugin = exports.LineModel = exports.LeafModel = exports.EOLModel = exports.BlockModel = exports.useReadonly = exports.ReadonlyContext = exports.useEditorStatic = exports.BlockKitContext = exports.useComposing = void 0;
|
|
3
|
+
exports.LEAF_TO_ZERO_TEXT = exports.LEAF_TO_TEXT = exports.LEAF_TO_REMOUNT = exports.JSX_TO_STATE = exports.MountNode = exports.preventReactEvent = exports.preventNativeEvent = exports.rewriteRemoveChild = exports.NO_CURSOR = exports.ZeroSpace = exports.Void = exports.Text = exports.Isolate = exports.Embed = exports.Editable = exports.BlockKit = exports.InjectWrapKeys = exports.Priority = exports.EditorPlugin = exports.LineModel = exports.LeafModel = exports.EOLModel = exports.BlockModel = exports.useReadonly = exports.ReadonlyContext = exports.useThrottleMemoFn = exports.useDebounceMemoFn = exports.useEditorStatic = exports.BlockKitContext = exports.useComposing = void 0;
|
|
4
4
|
var use_composing_1 = require("./hooks/use-composing");
|
|
5
5
|
Object.defineProperty(exports, "useComposing", { enumerable: true, get: function () { return use_composing_1.useComposing; } });
|
|
6
6
|
var use_editor_1 = require("./hooks/use-editor");
|
|
7
7
|
Object.defineProperty(exports, "BlockKitContext", { enumerable: true, get: function () { return use_editor_1.BlockKitContext; } });
|
|
8
8
|
Object.defineProperty(exports, "useEditorStatic", { enumerable: true, get: function () { return use_editor_1.useEditorStatic; } });
|
|
9
|
+
var use_limit_1 = require("./hooks/use-limit");
|
|
10
|
+
Object.defineProperty(exports, "useDebounceMemoFn", { enumerable: true, get: function () { return use_limit_1.useDebounceMemoFn; } });
|
|
11
|
+
Object.defineProperty(exports, "useThrottleMemoFn", { enumerable: true, get: function () { return use_limit_1.useThrottleMemoFn; } });
|
|
9
12
|
var use_readonly_1 = require("./hooks/use-readonly");
|
|
10
13
|
Object.defineProperty(exports, "ReadonlyContext", { enumerable: true, get: function () { return use_readonly_1.ReadonlyContext; } });
|
|
11
14
|
Object.defineProperty(exports, "useReadonly", { enumerable: true, get: function () { return use_readonly_1.useReadonly; } });
|
package/dist/lib/model/block.js
CHANGED
|
@@ -31,7 +31,6 @@ const react_1 = __importStar(require("react"));
|
|
|
31
31
|
const wrap_1 = require("../plugin/modules/wrap");
|
|
32
32
|
const dirty_dom_1 = require("../utils/dirty-dom");
|
|
33
33
|
const weak_map_1 = require("../utils/weak-map");
|
|
34
|
-
const effect_1 = require("./effect");
|
|
35
34
|
const line_1 = require("./line");
|
|
36
35
|
const ph_1 = require("./ph");
|
|
37
36
|
const BlockView = props => {
|
|
@@ -41,14 +40,13 @@ const BlockView = props => {
|
|
|
41
40
|
/**
|
|
42
41
|
* 设置 Block DOM 节点
|
|
43
42
|
*/
|
|
44
|
-
const setModel = (
|
|
43
|
+
const setModel = (ref) => {
|
|
45
44
|
if (ref) {
|
|
46
45
|
// ref 触发时机最早 ref -> layout effect -> effect
|
|
47
|
-
// 需要保证 editor 稳定, 重渲染并不会触发执行, 导致 DOM 映射关系失效
|
|
48
46
|
editor.model.setBlockModel(ref, state);
|
|
49
47
|
(0, dirty_dom_1.rewriteRemoveChild)(ref);
|
|
50
48
|
}
|
|
51
|
-
}
|
|
49
|
+
};
|
|
52
50
|
/**
|
|
53
51
|
* 数据同步变更, 异步批量绘制变更
|
|
54
52
|
*/
|
|
@@ -74,6 +72,29 @@ const BlockView = props => {
|
|
|
74
72
|
editor.event.off(core_1.EDITOR_EVENT.CONTENT_CHANGE, onContentChange);
|
|
75
73
|
};
|
|
76
74
|
}, [editor.event, onContentChange]);
|
|
75
|
+
/**
|
|
76
|
+
* 视图更新需要重新设置选区, 依赖于行状态变更
|
|
77
|
+
*/
|
|
78
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
79
|
+
const selection = editor.selection.get();
|
|
80
|
+
// 同步计算完成后更新浏览器选区, 等待 Paint
|
|
81
|
+
if (editor.state.isFocused() && selection) {
|
|
82
|
+
editor.logger.debug("UpdateDOMSelection");
|
|
83
|
+
editor.selection.updateDOMSelection(true);
|
|
84
|
+
}
|
|
85
|
+
}, [editor, lines]);
|
|
86
|
+
/**
|
|
87
|
+
* 视图更新需要触发视图绘制完成事件, 依赖于行状态变更
|
|
88
|
+
*/
|
|
89
|
+
(0, react_1.useEffect)(() => {
|
|
90
|
+
// state -> parent -> node -> child ->|
|
|
91
|
+
// effect <- parent <- node <- child <-|
|
|
92
|
+
editor.logger.debug("OnPaint");
|
|
93
|
+
editor.state.set(core_1.EDITOR_STATE.PAINTING, false);
|
|
94
|
+
Promise.resolve().then(() => {
|
|
95
|
+
editor.event.trigger(core_1.EDITOR_EVENT.PAINT, {});
|
|
96
|
+
});
|
|
97
|
+
}, [editor, lines]);
|
|
77
98
|
/**
|
|
78
99
|
* 处理行节点
|
|
79
100
|
*/
|
|
@@ -86,8 +107,8 @@ const BlockView = props => {
|
|
|
86
107
|
}
|
|
87
108
|
}
|
|
88
109
|
}
|
|
89
|
-
return lines.map(
|
|
90
|
-
const node = (
|
|
110
|
+
return lines.map(line => {
|
|
111
|
+
const node = (0, jsx_runtime_1.jsx)(line_1.LineModel, { editor: editor, lineState: line }, line.key);
|
|
91
112
|
weak_map_1.JSX_TO_STATE.set(node, line);
|
|
92
113
|
return node;
|
|
93
114
|
});
|
|
@@ -98,7 +119,7 @@ const BlockView = props => {
|
|
|
98
119
|
const children = (0, react_1.useMemo)(() => {
|
|
99
120
|
return (0, wrap_1.withWrapLineNodes)(editor, elements);
|
|
100
121
|
}, [editor, elements]);
|
|
101
|
-
return ((0, jsx_runtime_1.jsxs)("div", { [core_1.BLOCK_KEY]: true, [core_1.BLOCK_ID_KEY]: state.key, ref: setModel, children: [(0, jsx_runtime_1.jsx)(
|
|
122
|
+
return ((0, jsx_runtime_1.jsxs)("div", { [core_1.BLOCK_KEY]: true, [core_1.BLOCK_ID_KEY]: state.key, ref: setModel, children: [(0, jsx_runtime_1.jsx)(ph_1.Placeholder, { editor: editor, lines: lines, placeholder: props.placeholder }), children] }));
|
|
102
123
|
};
|
|
103
124
|
/** Block Model */
|
|
104
125
|
exports.BlockModel = react_1.default.memo(BlockView);
|
package/dist/lib/model/leaf.d.ts
CHANGED
package/dist/lib/model/leaf.js
CHANGED
|
@@ -38,13 +38,13 @@ const LeafView = props => {
|
|
|
38
38
|
/**
|
|
39
39
|
* 设置叶子 DOM 节点
|
|
40
40
|
*/
|
|
41
|
-
const setModel = (
|
|
41
|
+
const setModel = (ref) => {
|
|
42
42
|
if (ref) {
|
|
43
43
|
(0, dirty_dom_1.rewriteRemoveChild)(ref);
|
|
44
44
|
editor.model.setLeafModel(ref, leafState);
|
|
45
45
|
}
|
|
46
46
|
weak_map_1.LEAF_TO_REMOUNT.set(leafState, forceUpdate);
|
|
47
|
-
}
|
|
47
|
+
};
|
|
48
48
|
/**
|
|
49
49
|
* 处理叶子节点的渲染
|
|
50
50
|
*/
|
package/dist/lib/model/line.d.ts
CHANGED
package/dist/lib/model/line.js
CHANGED
|
@@ -40,12 +40,12 @@ const LineView = props => {
|
|
|
40
40
|
/**
|
|
41
41
|
* 设置行 DOM 节点
|
|
42
42
|
*/
|
|
43
|
-
const setModel = (
|
|
43
|
+
const setModel = (ref) => {
|
|
44
44
|
if (ref) {
|
|
45
45
|
editor.model.setLineModel(ref, lineState);
|
|
46
46
|
(0, dirty_dom_1.rewriteRemoveChild)(ref);
|
|
47
47
|
}
|
|
48
|
-
}
|
|
48
|
+
};
|
|
49
49
|
/**
|
|
50
50
|
* 编辑器行结构布局计算后同步调用
|
|
51
51
|
* - 首次处理会将所有 DOM 渲染, 不需要执行脏数据检查
|
|
@@ -81,13 +81,15 @@ const LineView = props => {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
const leaves = lineState.getLeaves();
|
|
84
|
+
// 首先渲染所有非 EOL 的叶子节点
|
|
84
85
|
const textLeaves = leaves.slice(0, -1);
|
|
85
|
-
const nodes = textLeaves.map(
|
|
86
|
-
const node = (0, jsx_runtime_1.jsx)(leaf_1.LeafModel, { editor: editor,
|
|
86
|
+
const nodes = textLeaves.map(n => {
|
|
87
|
+
const node = (0, jsx_runtime_1.jsx)(leaf_1.LeafModel, { editor: editor, leafState: n }, n.key);
|
|
87
88
|
weak_map_1.JSX_TO_STATE.set(node, n);
|
|
88
89
|
return node;
|
|
89
90
|
});
|
|
90
|
-
//
|
|
91
|
+
// 存在内容时不渲染 EOL, 避免块级元素出现额外视觉上的换行
|
|
92
|
+
// 若是空行则仅存在一个 Leaf, 此时需要渲染空的占位节点
|
|
91
93
|
if (!nodes.length && leaves[0]) {
|
|
92
94
|
const leaf = leaves[0];
|
|
93
95
|
const node = (0, jsx_runtime_1.jsx)(eol_1.EOLModel, { editor: editor, leafState: leaf }, delta_1.EOL);
|
|
@@ -4,6 +4,7 @@ exports.Editable = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const core_1 = require("@block-kit/core");
|
|
6
6
|
const utils_1 = require("@block-kit/utils");
|
|
7
|
+
const hooks_1 = require("@block-kit/utils/dist/es/hooks");
|
|
7
8
|
const react_1 = require("react");
|
|
8
9
|
const use_editor_1 = require("../hooks/use-editor");
|
|
9
10
|
const use_readonly_1 = require("../hooks/use-readonly");
|
|
@@ -25,6 +26,10 @@ const Editable = props => {
|
|
|
25
26
|
!preventDestroy && editor.destroy();
|
|
26
27
|
};
|
|
27
28
|
}, [editor, preventDestroy]);
|
|
29
|
+
(0, hooks_1.useUpdateEffect)(() => {
|
|
30
|
+
// 需要保证 editor 实例稳定, 重渲染并不会触发 ref 执行, 导致 DOM 映射关系失效
|
|
31
|
+
editor.logger.warning("Confirm the uniqueness of the editor instance.", editor);
|
|
32
|
+
}, [editor]);
|
|
28
33
|
(0, react_1.useEffect)(() => {
|
|
29
34
|
// COMPAT: 这里有个奇怪的表现
|
|
30
35
|
// 当自动聚焦时, 必须要先更新浏览器选区再聚焦
|
|
@@ -4,6 +4,7 @@ exports.Isolate = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const core_1 = require("@block-kit/core");
|
|
6
6
|
const utils_1 = require("@block-kit/utils");
|
|
7
|
+
const hooks_1 = require("@block-kit/utils/dist/es/hooks");
|
|
7
8
|
const react_1 = require("react");
|
|
8
9
|
/**
|
|
9
10
|
* 独立节点嵌入 HOC
|
|
@@ -12,6 +13,10 @@ const react_1 = require("react");
|
|
|
12
13
|
*/
|
|
13
14
|
const Isolate = props => {
|
|
14
15
|
const [ref, setRef] = (0, react_1.useState)(null);
|
|
16
|
+
const onRef = (0, hooks_1.useMemoFn)((dom) => {
|
|
17
|
+
setRef(dom);
|
|
18
|
+
props.onRef && props.onRef(dom);
|
|
19
|
+
});
|
|
15
20
|
(0, react_1.useEffect)(() => {
|
|
16
21
|
const el = ref;
|
|
17
22
|
if (!el)
|
|
@@ -50,6 +55,6 @@ const Isolate = props => {
|
|
|
50
55
|
el.removeEventListener(COMPOSITION_END, utils_1.stopNativeEvent);
|
|
51
56
|
};
|
|
52
57
|
}, [ref]);
|
|
53
|
-
return ((0, jsx_runtime_1.jsx)("span", { ref:
|
|
58
|
+
return ((0, jsx_runtime_1.jsx)("span", { ref: onRef, [core_1.ISOLATED_KEY]: true, className: props.className, style: props.style, contentEditable: false, children: props.children }));
|
|
54
59
|
};
|
|
55
60
|
exports.Isolate = Isolate;
|
package/dist/lib/preset/text.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Text = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const core_1 = require("@block-kit/core");
|
|
6
|
-
const hooks_1 = require("@block-kit/utils/dist/es/hooks");
|
|
7
6
|
/**
|
|
8
7
|
* 文本节点
|
|
9
8
|
* @param props
|
|
@@ -12,12 +11,14 @@ const Text = props => {
|
|
|
12
11
|
/**
|
|
13
12
|
* 处理 ref 回调
|
|
14
13
|
* - 节点执行时机为 ref -> layout effect -> effect
|
|
15
|
-
* -
|
|
14
|
+
* - 若是不保持引用不变, 会导致回调在 rerender 时被多次调用 null/span 状态
|
|
16
15
|
* - https://18.react.dev/reference/react-dom/components/common#ref-callback
|
|
16
|
+
* - 而若是保持引用不变, 会导致节点变化渲染时, 即使文本内容变化了, 也不会触发回调
|
|
17
|
+
* - 因为 LEAF 映射 TEXT 依赖于回调函数的执行, 就会导致叶子对象变化时, 不会重新映射
|
|
17
18
|
*/
|
|
18
|
-
const onRef = (
|
|
19
|
+
const onRef = (dom) => {
|
|
19
20
|
props.onRef && props.onRef(dom);
|
|
20
|
-
}
|
|
21
|
+
};
|
|
21
22
|
return ((0, jsx_runtime_1.jsx)("span", { ref: onRef, [core_1.LEAF_STRING]: true, children: props.children }));
|
|
22
23
|
};
|
|
23
24
|
exports.Text = Text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@block-kit/react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/lib/index.js",
|
|
6
6
|
"types": "./dist/es/index.d.ts",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"react-dom": ">=17"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@block-kit/core": "1.0.
|
|
43
|
-
"@block-kit/delta": "1.0.
|
|
44
|
-
"@block-kit/utils": "1.0.
|
|
42
|
+
"@block-kit/core": "1.0.23",
|
|
43
|
+
"@block-kit/delta": "1.0.23",
|
|
44
|
+
"@block-kit/utils": "1.0.23"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@babel/core": "7.20.12",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Editor, LineState } from "@block-kit/core";
|
|
2
|
-
import React from "react";
|
|
3
|
-
/**
|
|
4
|
-
* 副作用依赖视图
|
|
5
|
-
* - 父组件渲染会引发子组件渲染问题, memo 并未严格控制对比, 例如 ph 变更会导致重渲染
|
|
6
|
-
* - 避免 memo 的渲染穿透问题, 参考 packages/react/test/render/effect.test.tsx
|
|
7
|
-
* - 同样也可以直接将依赖即 [lines] 作为以来放置于 effect 中, 但抽离出独立组件能够更清晰
|
|
8
|
-
*/
|
|
9
|
-
export declare const PaintEffectModel: React.NamedExoticComponent<{
|
|
10
|
-
editor: Editor;
|
|
11
|
-
lines: LineState[];
|
|
12
|
-
}>;
|
package/dist/es/model/effect.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { EDITOR_EVENT, EDITOR_STATE } from "@block-kit/core";
|
|
2
|
-
import React, { useEffect, useLayoutEffect } from "react";
|
|
3
|
-
const PaintEffectView = props => {
|
|
4
|
-
const editor = props.editor;
|
|
5
|
-
/**
|
|
6
|
-
* 视图更新需要重新设置选区 无依赖数组
|
|
7
|
-
*/
|
|
8
|
-
useLayoutEffect(() => {
|
|
9
|
-
const selection = editor.selection.get();
|
|
10
|
-
// 同步计算完成后更新浏览器选区, 等待 Paint
|
|
11
|
-
if (editor.state.isFocused() && selection) {
|
|
12
|
-
editor.logger.debug("UpdateDOMSelection");
|
|
13
|
-
editor.selection.updateDOMSelection(true);
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
/**
|
|
17
|
-
* 视图更新需要触发视图绘制完成事件 无依赖数组
|
|
18
|
-
* state -> parent -> node -> child ->|
|
|
19
|
-
* effect <- parent <- node <- child <-|
|
|
20
|
-
*/
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
editor.logger.debug("OnPaint");
|
|
23
|
-
editor.state.set(EDITOR_STATE.PAINTING, false);
|
|
24
|
-
Promise.resolve().then(() => {
|
|
25
|
-
editor.event.trigger(EDITOR_EVENT.PAINT, {});
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
return null;
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* 副作用依赖视图
|
|
32
|
-
* - 父组件渲染会引发子组件渲染问题, memo 并未严格控制对比, 例如 ph 变更会导致重渲染
|
|
33
|
-
* - 避免 memo 的渲染穿透问题, 参考 packages/react/test/render/effect.test.tsx
|
|
34
|
-
* - 同样也可以直接将依赖即 [lines] 作为以来放置于 effect 中, 但抽离出独立组件能够更清晰
|
|
35
|
-
*/
|
|
36
|
-
export const PaintEffectModel = React.memo(PaintEffectView);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Editor, LineState } from "@block-kit/core";
|
|
2
|
-
import React from "react";
|
|
3
|
-
/**
|
|
4
|
-
* 副作用依赖视图
|
|
5
|
-
* - 父组件渲染会引发子组件渲染问题, memo 并未严格控制对比, 例如 ph 变更会导致重渲染
|
|
6
|
-
* - 避免 memo 的渲染穿透问题, 参考 packages/react/test/render/effect.test.tsx
|
|
7
|
-
* - 同样也可以直接将依赖即 [lines] 作为以来放置于 effect 中, 但抽离出独立组件能够更清晰
|
|
8
|
-
*/
|
|
9
|
-
export declare const PaintEffectModel: React.NamedExoticComponent<{
|
|
10
|
-
editor: Editor;
|
|
11
|
-
lines: LineState[];
|
|
12
|
-
}>;
|
package/dist/lib/model/effect.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.PaintEffectModel = void 0;
|
|
27
|
-
const core_1 = require("@block-kit/core");
|
|
28
|
-
const react_1 = __importStar(require("react"));
|
|
29
|
-
const PaintEffectView = props => {
|
|
30
|
-
const editor = props.editor;
|
|
31
|
-
/**
|
|
32
|
-
* 视图更新需要重新设置选区 无依赖数组
|
|
33
|
-
*/
|
|
34
|
-
(0, react_1.useLayoutEffect)(() => {
|
|
35
|
-
const selection = editor.selection.get();
|
|
36
|
-
// 同步计算完成后更新浏览器选区, 等待 Paint
|
|
37
|
-
if (editor.state.isFocused() && selection) {
|
|
38
|
-
editor.logger.debug("UpdateDOMSelection");
|
|
39
|
-
editor.selection.updateDOMSelection(true);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
/**
|
|
43
|
-
* 视图更新需要触发视图绘制完成事件 无依赖数组
|
|
44
|
-
* state -> parent -> node -> child ->|
|
|
45
|
-
* effect <- parent <- node <- child <-|
|
|
46
|
-
*/
|
|
47
|
-
(0, react_1.useEffect)(() => {
|
|
48
|
-
editor.logger.debug("OnPaint");
|
|
49
|
-
editor.state.set(core_1.EDITOR_STATE.PAINTING, false);
|
|
50
|
-
Promise.resolve().then(() => {
|
|
51
|
-
editor.event.trigger(core_1.EDITOR_EVENT.PAINT, {});
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
return null;
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* 副作用依赖视图
|
|
58
|
-
* - 父组件渲染会引发子组件渲染问题, memo 并未严格控制对比, 例如 ph 变更会导致重渲染
|
|
59
|
-
* - 避免 memo 的渲染穿透问题, 参考 packages/react/test/render/effect.test.tsx
|
|
60
|
-
* - 同样也可以直接将依赖即 [lines] 作为以来放置于 effect 中, 但抽离出独立组件能够更清晰
|
|
61
|
-
*/
|
|
62
|
-
exports.PaintEffectModel = react_1.default.memo(PaintEffectView);
|