11import { findParentNodeClosestToPos , posToDOMRect } from "@tiptap/core" ;
2- import { useMemo } from "react" ;
2+ import { useMemo , useCallback , useEffect , useState } from "react" ;
33import { makeStyles } from "tss-react/mui" ;
44import type { Except } from "type-fest" ;
55import { type PopoverVirtualElement } from "@mui/material" ;
@@ -13,14 +13,8 @@ import { useRichTextEditorContext } from "../context";
1313import TableMenuControls , {
1414 type TableMenuControlsProps ,
1515} from "./table-menu-controls" ;
16- import useDebouncedFocus from "../hooks/use-debounced-focus" ;
17- import DebounceRender , {
18- type DebounceRenderProps ,
19- } from "../utils/debounce-render" ;
2016
2117export type TableBubbleMenuProps = {
22- disableDebounce ?: boolean ;
23- DebounceProps ?: Except < DebounceRenderProps , "children" > ;
2418 labels ?: TableMenuControlsProps [ "labels" ] ;
2519} & Partial < Except < ControlledBubbleMenuProps , "open" | "editor" | "children" > > ;
2620
@@ -34,15 +28,12 @@ const useStyles = makeStyles({
3428} ) ) ;
3529
3630export default function TableBubbleMenu ( {
37- disableDebounce = false ,
38- DebounceProps,
3931 labels,
4032 ...controlledBubbleMenuProps
4133} : TableBubbleMenuProps ) {
4234 const editor = useRichTextEditorContext ( ) ;
4335 const { classes } = useStyles ( ) ;
44-
45- const isEditorFocusedDebounced = useDebouncedFocus ( { editor } ) ;
36+ const [ isManuallyHidden , setIsManuallyHidden ] = useState ( false ) ;
4637
4738 const bubbleMenuAnchorEl = useMemo (
4839 ( ) =>
@@ -61,7 +52,7 @@ export default function TableBubbleMenu({
6152 nearestTableParent . pos
6253 ) as Maybe < HTMLElement | undefined > ;
6354
64- const tableDomNode = wrapperDomNode ?. querySelector ( "admin " ) ;
55+ const tableDomNode = wrapperDomNode ?. querySelector ( "table " ) ;
6556 if ( tableDomNode ) {
6657 return tableDomNode . getBoundingClientRect ( ) ;
6758 }
@@ -77,18 +68,52 @@ export default function TableBubbleMenu({
7768 [ editor ]
7869 ) ;
7970
71+ const handleClose = useCallback ( ( ) => {
72+ setIsManuallyHidden ( true ) ;
73+ if ( editor ) {
74+ editor . commands . blur ( ) ;
75+ }
76+ } , [ editor ] ) ;
77+
78+ useEffect ( ( ) => {
79+ if ( ! editor ?. isActive ( "table" ) ) {
80+ setIsManuallyHidden ( false ) ;
81+ }
82+ } , [ editor ?. isActive ( "table" ) ] ) ;
83+
84+ useEffect ( ( ) => {
85+ const handleKeyDown = ( event : KeyboardEvent ) => {
86+ if ( event . key === "Escape" && editor ?. isActive ( "table" ) ) {
87+ handleClose ( ) ;
88+ }
89+ } ;
90+
91+ document . addEventListener ( "keydown" , handleKeyDown ) ;
92+ return ( ) => {
93+ document . removeEventListener ( "keydown" , handleKeyDown ) ;
94+ } ;
95+ } , [ editor , handleClose ] ) ;
96+
8097 if ( ! editor ?. isEditable ) {
8198 return null ;
8299 }
83100
84101 const controls = (
85- < TableMenuControls className = { classes . controls } labels = { labels } />
102+ < TableMenuControls
103+ className = { classes . controls }
104+ labels = { labels }
105+ onClose = { handleClose }
106+ />
86107 ) ;
87108
109+ // Логика показа меню - активная таблица и не скрыто вручную
110+ const shouldShowMenu = editor . isActive ( "table" ) && ! isManuallyHidden ;
111+
88112 return (
89113 < ControlledBubbleMenu
90114 editor = { editor }
91- open = { isEditorFocusedDebounced && editor . isActive ( "table" ) }
115+ open = { shouldShowMenu }
116+ onClose = { handleClose }
92117 anchorEl = { bubbleMenuAnchorEl as PopoverVirtualElement }
93118 placement = { {
94119 anchorOrigin : { vertical : "top" , horizontal : "left" } ,
@@ -104,11 +129,7 @@ export default function TableBubbleMenu({
104129 flipPadding = { { top : 35 , left : 8 , right : 8 , bottom : - Infinity } }
105130 { ...controlledBubbleMenuProps }
106131 >
107- { disableDebounce ? (
108- controls
109- ) : (
110- < DebounceRender { ...DebounceProps } > { controls } </ DebounceRender >
111- ) }
132+ { controls }
112133 </ ControlledBubbleMenu >
113134 ) ;
114135}
0 commit comments