'use client' /** * Poignée drag globale (Novel / tiptap-extension-global-drag-handle). * L’extension TipTap positionne cet élément ; le clic ouvre le menu bloc. */ import { memo, useEffect, useRef } from 'react' import type { Editor } from '@tiptap/core' import { BLOCK_DRAG_HANDLE_ID, resolveBlockAtDragHandle } from '@/lib/editor/block-at-drag-handle' type EditorBlockDragHandleProps = { editor: Editor | null onOpenMenu: (anchorRect: DOMRect) => void } export const EditorBlockDragHandle = memo(function EditorBlockDragHandle({ editor, onOpenMenu, }: EditorBlockDragHandleProps) { const dragStartedRef = useRef(false) const onOpenMenuRef = useRef(onOpenMenu) onOpenMenuRef.current = onOpenMenu useEffect(() => { if (!editor || editor.isDestroyed) return const el = document.getElementById(BLOCK_DRAG_HANDLE_ID) if (!el) return const onPointerDown = () => { dragStartedRef.current = false } const onDragStart = () => { dragStartedRef.current = true } const onClick = (e: MouseEvent) => { if (dragStartedRef.current) { dragStartedRef.current = false return } e.preventDefault() e.stopPropagation() const block = resolveBlockAtDragHandle(editor) if (!block) return onOpenMenuRef.current(el.getBoundingClientRect()) } el.addEventListener('pointerdown', onPointerDown) el.addEventListener('dragstart', onDragStart) el.addEventListener('click', onClick) return () => { el.removeEventListener('pointerdown', onPointerDown) el.removeEventListener('dragstart', onDragStart) el.removeEventListener('click', onClick) } }, [editor]) return ( ) })