Skip to content

Commit a389b50

Browse files
committed
fix: toolbar dom & memory leak
1 parent da5a1f5 commit a389b50

File tree

3 files changed

+20
-22
lines changed

3 files changed

+20
-22
lines changed

packages/plugin/src/float-toolbar/index.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { HYPER_LINK_KEY } from "../hyper-link/types";
1515
import { LINE_HEIGHT_KEY } from "../line-height/types";
1616
import { useMemoFn } from "../shared/hooks/preset";
1717
import { MenuItems } from "./components/menu";
18-
import { execSelectMarks, getSelectionRect, maskMenuToolBar, Portal } from "./utils/selection";
18+
import { execSelectMarks, getSelectionRect, Portal } from "./utils/selection";
1919

2020
const TOOLBAR_OFFSET_HEIGHT = 40;
2121
const TOOLBAR_OFFSET_WIDTH = 340;
@@ -29,36 +29,38 @@ export const MenuToolBar: FC<{
2929
}> = props => {
3030
const editor = props.editor;
3131
const keepStatus = useRef(false);
32+
const [top, setTop] = useState(0);
33+
const [left, setLeft] = useState(0);
34+
const [visible, setVisible] = useState(false);
3235
const toolbarRef = useRef<HTMLDivElement>(null);
36+
const [isMouseDown, setIsMouseDown] = useState(false);
3337
const [selectedMarks, setSelectedMarks] = useState<string[]>([]);
3438

3539
const wakeUpToolbar = useMemoFn((wakeUp: boolean) => {
36-
const toolbar = toolbarRef.current;
37-
if (!toolbar) return void 0;
3840
if (ReactEditor.isFocused(editor.raw) && wakeUp) {
3941
setSelectedMarks(
4042
Collection.omit(Object.keys(Editor.marks(editor.raw) || []), NOT_INIT_SELECT)
4143
);
4244
const rect = getSelectionRect();
4345
if (rect) {
44-
toolbar.style.top = `${rect.top + window.pageYOffset - TOOLBAR_OFFSET_HEIGHT - 10}px`;
45-
toolbar.style.left = `${
46-
rect.left + window.pageXOffset - TOOLBAR_OFFSET_WIDTH / 2 + rect.width / 2
47-
}px`;
46+
const t = rect.top + window.scrollY - TOOLBAR_OFFSET_HEIGHT - 10;
47+
const l = rect.left + window.scrollX - TOOLBAR_OFFSET_WIDTH / 2 + rect.width / 2;
48+
setTop(t);
49+
setLeft(l);
4850
}
51+
setVisible(true);
4952
} else {
50-
maskMenuToolBar(toolbar);
53+
setVisible(false);
5154
}
5255
});
5356

5457
useEffect(() => {
55-
const toolbar = toolbarRef.current;
56-
if (!toolbar || props.readonly) return void 0;
58+
if (props.readonly) return void 0;
5759
const mouseUpHandler = () => {
58-
!keepStatus.current && (toolbar.style.display = "");
60+
!keepStatus.current && setIsMouseDown(false);
5961
};
6062
const mouseDownHandler = () => {
61-
!keepStatus.current && (toolbar.style.display = "none");
63+
!keepStatus.current && setIsMouseDown(true);
6264
};
6365
const selectionChangeHandler = () => {
6466
if (keepStatus.current) return void 0;
@@ -72,7 +74,7 @@ export const MenuToolBar: FC<{
7274
return () => {
7375
document.removeEventListener(EVENT_ENUM.MOUSE_UP, mouseUpHandler);
7476
document.removeEventListener(EVENT_ENUM.MOUSE_DOWN, mouseDownHandler);
75-
document.addEventListener(EVENT_ENUM.SELECTION_CHANGE, selectionChangeHandler);
77+
document.removeEventListener(EVENT_ENUM.SELECTION_CHANGE, selectionChangeHandler);
7678
};
7779
}, [editor, wakeUpToolbar, props.readonly]);
7880

@@ -115,9 +117,10 @@ export const MenuToolBar: FC<{
115117
[exec, selectedMarks]
116118
);
117119

118-
return props.readonly ? null : (
120+
// 只读状态 / 不可见 / 鼠标按下 时隐藏
121+
return props.readonly || !visible || isMouseDown ? null : (
119122
<Portal>
120-
<div ref={toolbarRef} className="hover-menu-container">
123+
<div ref={toolbarRef} style={{ left, top }} className="hover-menu-container">
121124
{HoverMenu}
122125
</div>
123126
</Portal>

packages/plugin/src/float-toolbar/styles/index.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@
4343
justify-content: center;
4444
}
4545

46-
@keyframes fade-out {
46+
@keyframes fade-in {
4747
from { opacity: 0; }
4848
to { opacity: 1; }
4949
}
5050

5151
.hover-menu-container {
52-
animation: fade-out 0.3s;
52+
animation: fade-in 0.3s;
5353
background-color: var(--color-bg-2);
5454
border: 1px solid var(--color-border-1);
5555
box-shadow: $box-shadow;

packages/plugin/src/float-toolbar/utils/selection.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { Collection } from "doc-editor-utils";
22
import ReactDOM from "react-dom";
33

4-
export const maskMenuToolBar = (element: HTMLDivElement) => {
5-
element.style.left = "-1000px";
6-
element.style.top = "-1000px";
7-
};
8-
94
export const getSelectionRect = () => {
105
const domSelection = window.getSelection();
116
if (domSelection && domSelection.rangeCount > 0) {

0 commit comments

Comments
 (0)