From 96168cbfb0ed7917f88ec2ceb419d3acd6b2d74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Thu, 26 Mar 2026 15:35:28 +0400 Subject: [PATCH] Fix listeners cleaning on unmount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Émile Ré --- .../TableCellMenu/TableCellMenuTrigger.tsx | 14 +++++++++++++- .../RichEditor/TableColumnMenu/TableColumnMenu.tsx | 2 -- .../TableColumnMenu/TableColumnMenuContent.tsx | 4 ++-- .../TableColumnMenu/TableColumnMenuTrigger.tsx | 12 ++++++++++++ .../src/RichEditor/TableRowMenu/TableRowMenu.tsx | 2 -- .../TableRowMenu/TableRowMenuTrigger.tsx | 12 ++++++++++++ 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/packages/ui/src/RichEditor/TableCellMenu/TableCellMenuTrigger.tsx b/packages/ui/src/RichEditor/TableCellMenu/TableCellMenuTrigger.tsx index 0fff904df..aecf08090 100644 --- a/packages/ui/src/RichEditor/TableCellMenu/TableCellMenuTrigger.tsx +++ b/packages/ui/src/RichEditor/TableCellMenu/TableCellMenuTrigger.tsx @@ -6,7 +6,7 @@ import { autoUpdate, offset, useFloating } from "@floating-ui/react"; import { CircleIcon, DotsThreeCircleVerticalIcon } from "@phosphor-icons/react"; import { cellAround, CellSelection, TableMap } from "@tiptap/pm/tables"; import { type Editor } from "@tiptap/react"; -import { useLayoutEffect, useRef, useState } from "react"; +import { useEffect, useLayoutEffect, useRef, useState } from "react"; import { cellDomElement } from "../_lib/cellDomElement"; import { DRAG_THRESHOLD } from "../_lib/constants"; @@ -41,6 +41,13 @@ export function TableCellMenuTrigger({ bottomRow: number; tableStart: number; } | null>(null); + const dragCleanupRef = useRef<(() => void) | null>(null); + + useEffect(() => { + return () => { + dragCleanupRef.current?.(); + }; + }, []); const { refs: handleRefs, @@ -196,6 +203,7 @@ export function TableCellMenuTrigger({ const onMouseUp = () => { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); + dragCleanupRef.current = null; if (!draggingRef.current) { setMenuOpen(prev => !prev); @@ -208,6 +216,10 @@ export function TableCellMenuTrigger({ document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); + dragCleanupRef.current = () => { + document.removeEventListener("mousemove", onMouseMove); + document.removeEventListener("mouseup", onMouseUp); + }; }; return ( diff --git a/packages/ui/src/RichEditor/TableColumnMenu/TableColumnMenu.tsx b/packages/ui/src/RichEditor/TableColumnMenu/TableColumnMenu.tsx index 577223014..842a28a32 100644 --- a/packages/ui/src/RichEditor/TableColumnMenu/TableColumnMenu.tsx +++ b/packages/ui/src/RichEditor/TableColumnMenu/TableColumnMenu.tsx @@ -102,8 +102,6 @@ export function TableColumnMenu({ editor }: TableColumnMenuProps) { const [hoveredCol, setHoveredCol] = useState(null); - if (!hoveredCol && !menuOpen) return null; - return ( <> (null); const hoveredColRef = useRef(null); + const dragCleanupRef = useRef<(() => void) | null>(null); useEffect(() => { hoveredColRef.current = hoveredCol; }, [hoveredCol]); + useEffect(() => { + return () => { + dragCleanupRef.current?.(); + }; + }, []); + useEffect(() => { if (editor.isDestroyed || !editor.isEditable) return; @@ -285,6 +292,7 @@ export function TableColumnMenuTrigger({ const onMouseUp = (ev: MouseEvent) => { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); + dragCleanupRef.current = null; if (draggingRef.current) { setDragIndicator(null); @@ -327,6 +335,10 @@ export function TableColumnMenuTrigger({ document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); + dragCleanupRef.current = () => { + document.removeEventListener("mousemove", onMouseMove); + document.removeEventListener("mouseup", onMouseUp); + }; }; return ( diff --git a/packages/ui/src/RichEditor/TableRowMenu/TableRowMenu.tsx b/packages/ui/src/RichEditor/TableRowMenu/TableRowMenu.tsx index 9fb69eb73..87108fbbc 100644 --- a/packages/ui/src/RichEditor/TableRowMenu/TableRowMenu.tsx +++ b/packages/ui/src/RichEditor/TableRowMenu/TableRowMenu.tsx @@ -98,8 +98,6 @@ export function TableRowMenu({ editor }: TableRowMenuProps) { const [hoveredRow, setHoveredRow] = useState(null); - if (!hoveredRow && !menuOpen) return null; - return ( <> (null); const hoveredRowRef = useRef(null); + const dragCleanupRef = useRef<(() => void) | null>(null); useEffect(() => { hoveredRowRef.current = hoveredRow; }, [hoveredRow]); + useEffect(() => { + return () => { + dragCleanupRef.current?.(); + }; + }, []); + useEffect(() => { if (editor.isDestroyed || !editor.isEditable) return; @@ -285,6 +292,7 @@ export function TableRowMenuTrigger({ const onMouseUp = (ev: MouseEvent) => { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); + dragCleanupRef.current = null; if (draggingRef.current) { setDragIndicator(null); @@ -327,6 +335,10 @@ export function TableRowMenuTrigger({ document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); + dragCleanupRef.current = () => { + document.removeEventListener("mousemove", onMouseMove); + document.removeEventListener("mouseup", onMouseUp); + }; }; return (