Skip to content

Commit ee61bd0

Browse files
committed
Made all menus/toolbars scroll with page
1 parent 279b70c commit ee61bd0

File tree

4 files changed

+86
-37
lines changed

4 files changed

+86
-37
lines changed

packages/core/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ export class BlockMenuView {
268268
// Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.
269269
document.body.addEventListener("mousemove", this.onMouseMove, true);
270270

271+
// Makes menu scroll with the page.
272+
document.addEventListener("scroll", this.onScroll);
273+
271274
// Hides and unfreezes the menu whenever the user selects the editor with the mouse or presses a key.
272275
// TODO: Better integration with suggestions menu and only editor scope?
273276
document.body.addEventListener("mousedown", this.onMouseDown, true);
@@ -411,6 +414,12 @@ export class BlockMenuView {
411414
}
412415
};
413416

417+
onScroll = () => {
418+
if (this.menuOpen) {
419+
this.blockMenu.render(this.getDynamicParams(), false);
420+
}
421+
};
422+
414423
destroy() {
415424
if (this.menuOpen) {
416425
this.menuOpen = false;
@@ -420,6 +429,7 @@ export class BlockMenuView {
420429
document.body.removeEventListener("dragover", this.onDragOver);
421430
document.body.removeEventListener("drop", this.onDrop);
422431
document.body.removeEventListener("mousedown", this.onMouseDown);
432+
document.removeEventListener("scroll", this.onScroll);
423433
document.body.removeEventListener("keydown", this.onKeyDown);
424434
}
425435

packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ export class FormattingToolbarView {
8686
this.view.dom.addEventListener("mouseup", this.viewMouseupHandler);
8787
this.view.dom.addEventListener("dragstart", this.dragstartHandler);
8888

89+
document.addEventListener("scroll", this.scrollHandler);
90+
8991
this.ttEditor.on("focus", this.focusHandler);
9092
this.ttEditor.on("blur", this.blurHandler);
9193
}
@@ -131,6 +133,12 @@ export class FormattingToolbarView {
131133
}
132134
};
133135

136+
scrollHandler = () => {
137+
if (this.toolbarIsOpen) {
138+
this.formattingToolbar.render(this.getDynamicParams(), false);
139+
}
140+
};
141+
134142
update(view: EditorView, oldState?: EditorState) {
135143
const { state, composing } = view;
136144
const { doc, selection } = state;
@@ -207,6 +215,8 @@ export class FormattingToolbarView {
207215
this.view.dom.removeEventListener("mouseup", this.viewMouseupHandler);
208216
this.view.dom.removeEventListener("dragstart", this.dragstartHandler);
209217

218+
document.removeEventListener("scroll", this.scrollHandler);
219+
210220
this.ttEditor.off("focus", this.focusHandler);
211221
this.ttEditor.off("blur", this.blurHandler);
212222
}

packages/core/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -56,47 +56,56 @@ class HyperlinkToolbarView {
5656
return false;
5757
};
5858

59-
editor.view.dom.addEventListener("mouseover", (event) => {
60-
// Resets the hyperlink mark currently hovered by the mouse cursor.
61-
this.mouseHoveredHyperlinkMark = undefined;
62-
this.mouseHoveredHyperlinkMarkRange = undefined;
63-
64-
this.stopMenuUpdateTimer();
65-
66-
if (
67-
event.target instanceof HTMLAnchorElement &&
68-
event.target.nodeName === "A"
69-
) {
70-
// Finds link mark at the hovered element's position to update mouseHoveredHyperlinkMark and
71-
// mouseHoveredHyperlinkMarkRange.
72-
const hoveredHyperlinkElement = event.target;
73-
const posInHoveredHyperlinkMark =
74-
editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;
75-
const resolvedPosInHoveredHyperlinkMark = editor.state.doc.resolve(
76-
posInHoveredHyperlinkMark
77-
);
78-
const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();
79-
80-
for (const mark of marksAtPos) {
81-
if (mark.type.name === editor.schema.mark("link").type.name) {
82-
this.mouseHoveredHyperlinkMark = mark;
83-
this.mouseHoveredHyperlinkMarkRange =
84-
getMarkRange(
85-
resolvedPosInHoveredHyperlinkMark,
86-
mark.type,
87-
mark.attrs
88-
) || undefined;
89-
90-
break;
91-
}
59+
this.editor.view.dom.addEventListener("mouseover", this.mouseOverHandler);
60+
document.addEventListener("scroll", this.scrollHandler);
61+
}
62+
63+
mouseOverHandler = (event: MouseEvent) => {
64+
// Resets the hyperlink mark currently hovered by the mouse cursor.
65+
this.mouseHoveredHyperlinkMark = undefined;
66+
this.mouseHoveredHyperlinkMarkRange = undefined;
67+
68+
this.stopMenuUpdateTimer();
69+
70+
if (
71+
event.target instanceof HTMLAnchorElement &&
72+
event.target.nodeName === "A"
73+
) {
74+
// Finds link mark at the hovered element's position to update mouseHoveredHyperlinkMark and
75+
// mouseHoveredHyperlinkMarkRange.
76+
const hoveredHyperlinkElement = event.target;
77+
const posInHoveredHyperlinkMark =
78+
this.editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;
79+
const resolvedPosInHoveredHyperlinkMark = this.editor.state.doc.resolve(
80+
posInHoveredHyperlinkMark
81+
);
82+
const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();
83+
84+
for (const mark of marksAtPos) {
85+
if (mark.type.name === this.editor.schema.mark("link").type.name) {
86+
this.mouseHoveredHyperlinkMark = mark;
87+
this.mouseHoveredHyperlinkMarkRange =
88+
getMarkRange(
89+
resolvedPosInHoveredHyperlinkMark,
90+
mark.type,
91+
mark.attrs
92+
) || undefined;
93+
94+
break;
9295
}
9396
}
97+
}
9498

95-
this.startMenuUpdateTimer();
99+
this.startMenuUpdateTimer();
96100

97-
return false;
98-
});
99-
}
101+
return false;
102+
};
103+
104+
scrollHandler = () => {
105+
if (this.hyperlinkMark !== undefined) {
106+
this.hyperlinkToolbar.render(this.getDynamicParams(), false);
107+
}
108+
};
100109

101110
update() {
102111
if (!this.editor.view.hasFocus()) {
@@ -187,6 +196,14 @@ class HyperlinkToolbarView {
187196
}
188197
}
189198

199+
destroy() {
200+
this.editor.view.dom.removeEventListener(
201+
"mouseover",
202+
this.mouseOverHandler
203+
);
204+
document.removeEventListener("scroll", this.scrollHandler);
205+
}
206+
190207
getStaticParams(): HyperlinkToolbarStaticParams {
191208
return {
192209
editHyperlink: (url: string, text: string) => {

packages/core/src/shared/plugins/suggestion/SuggestionPlugin.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,16 @@ class SuggestionPluginView<T extends SuggestionItem> {
127127
};
128128

129129
this.suggestionsMenu = suggestionsMenuFactory(this.getStaticParams());
130+
131+
document.addEventListener("scroll", this.handleScroll);
130132
}
131133

134+
handleScroll = () => {
135+
if (this.pluginKey.getState(this.editor._tiptapEditor.state).active) {
136+
this.suggestionsMenu.render(this.getDynamicParams(), false);
137+
}
138+
};
139+
132140
update(view: EditorView, prevState: EditorState) {
133141
const prev = this.pluginKey.getState(prevState);
134142
const next = this.pluginKey.getState(view.state);
@@ -170,6 +178,10 @@ class SuggestionPluginView<T extends SuggestionItem> {
170178
}
171179
}
172180

181+
destroy() {
182+
document.removeEventListener("scroll", this.handleScroll);
183+
}
184+
173185
getStaticParams(): SuggestionsMenuStaticParams<T> {
174186
return {
175187
itemCallback: (item: T) => this.itemCallback(item),

0 commit comments

Comments
 (0)