diff --git a/packages/editable-html-tip-tap/src/extensions/__tests__/math.test.js b/packages/editable-html-tip-tap/src/extensions/__tests__/math.test.js index ac3d40393..35087bc40 100644 --- a/packages/editable-html-tip-tap/src/extensions/__tests__/math.test.js +++ b/packages/editable-html-tip-tap/src/extensions/__tests__/math.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { render, waitFor, fireEvent } from '@testing-library/react'; +import { render, waitFor, fireEvent, act } from '@testing-library/react'; import { EnsureTextAfterMathPlugin, MathNode, MathNodeView, ZeroWidthSpaceHandlingPlugin } from '../math'; import * as toolbarUtils from '../../utils/toolbar'; @@ -390,6 +390,7 @@ describe('MathNodeView', () => { selection: { from: 0, to: 1, + node: { type: { name: 'math' } }, }, tr: { setSelection: jest.fn().mockReturnThis(), @@ -724,6 +725,54 @@ describe('MathNodeView', () => { }); }); + describe('selection-based toolbar guard', () => { + it('opens toolbar when selected transitions to true and the editor has a NodeSelection on math', async () => { + const { queryByTestId, rerender } = render(); + expect(queryByTestId('math-toolbar')).not.toBeInTheDocument(); + + rerender(); + await waitFor(() => { + expect(queryByTestId('math-toolbar')).toBeInTheDocument(); + }); + }); + + it('does not open toolbar when selected briefly becomes true but editor selection has no node (Cmd+A / drag case)', async () => { + const editor = { + ...defaultProps.editor, + state: { + ...defaultProps.editor.state, + selection: { from: 0, to: 100 }, // no .node — TextSelection / AllSelection shape + }, + }; + + const { queryByTestId, rerender } = render( + , + ); + rerender(); + + await act(async () => {}); + expect(queryByTestId('math-toolbar')).not.toBeInTheDocument(); + }); + + it('does not open toolbar when selected briefly becomes true but NodeSelection targets a non-math node', async () => { + const editor = { + ...defaultProps.editor, + state: { + ...defaultProps.editor.state, + selection: { from: 0, to: 1, node: { type: { name: 'image' } } }, + }, + }; + + const { queryByTestId, rerender } = render( + , + ); + rerender(); + + await act(async () => {}); + expect(queryByTestId('math-toolbar')).not.toBeInTheDocument(); + }); + }); + it('does not close toolbar when clicking equation editor dropdown', async () => { const { queryByTestId } = render(); diff --git a/packages/editable-html-tip-tap/src/extensions/math.js b/packages/editable-html-tip-tap/src/extensions/math.js index 5c100d560..97d297624 100644 --- a/packages/editable-html-tip-tap/src/extensions/math.js +++ b/packages/editable-html-tip-tap/src/extensions/math.js @@ -232,11 +232,19 @@ export const MathNodeView = (props) => { editor.commands.focus(); }; + // Only open the toolbar when this node is *explicitly* selected + // via a NodeSelection — not when it's merely included in a broader + // TextSelection or AllSelection (e.g. click-drag across math, or Cmd+A). useEffect(() => { - if (selected) { + if (!selected) return; + + const { selection } = editor.state; + const isNodeSelected = selection.node?.type?.name === 'math'; + + if (isNodeSelected) { setShowToolbar(true); } - }, [selected]); + }, [selected, editor]); useEffect(() => { setToolbarOpened(editor, selected || showToolbar);