import React, { useState, useEffect, useRef } from "react"; import { Icon } from "@iconify/react"; import { useAppDispatch } from "../../store/hooks"; import { togglePreviewMode } from "../../store/slices/uiSlice"; interface MarkdownToolbarProps { onInsert: (before: string, after?: string) => void; onImageClick?: () => void; onFileClick?: () => void; onPreviewToggle?: () => void; isPreviewMode?: boolean; onInsertColor?: () => void; } export const MarkdownToolbar: React.FC = ({ onInsert, onImageClick, onFileClick, onPreviewToggle, isPreviewMode, onInsertColor, }) => { const [showHeaderDropdown, setShowHeaderDropdown] = useState(false); const dispatch = useAppDispatch(); const dropdownRef = useRef(null); const buttonRef = useRef(null); const menuRef = useRef(null); const containerRef = useRef(null); const [isDragging, setIsDragging] = useState(false); const [startX, setStartX] = useState(0); const [scrollLeft, setScrollLeft] = useState(0); const [menuPosition, setMenuPosition] = useState<{ top: number; left: number; } | null>(null); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) && menuRef.current && !menuRef.current.contains(event.target as Node) ) { setShowHeaderDropdown(false); setMenuPosition(null); } }; const updateMenuPosition = () => { if (buttonRef.current && showHeaderDropdown) { const rect = buttonRef.current.getBoundingClientRect(); setMenuPosition({ top: rect.bottom + window.scrollY + 2, left: rect.left + window.scrollX, }); } }; if (showHeaderDropdown) { updateMenuPosition(); // Используем небольшой таймаут, чтобы не перехватить клик на кнопке const timeoutId = setTimeout(() => { document.addEventListener("mousedown", handleClickOutside); window.addEventListener("resize", updateMenuPosition); window.addEventListener("scroll", updateMenuPosition); }, 100); return () => { clearTimeout(timeoutId); document.removeEventListener("mousedown", handleClickOutside); window.removeEventListener("resize", updateMenuPosition); window.removeEventListener("scroll", updateMenuPosition); }; } else { setMenuPosition(null); } }, [showHeaderDropdown]); const handleMouseDown = (e: React.MouseEvent) => { // Не начинаем перетаскивание если кликнули на кнопку if ((e.target as HTMLElement).closest(".btnMarkdown")) return; if (!containerRef.current) return; setIsDragging(true); setStartX(e.pageX - containerRef.current.offsetLeft); setScrollLeft(containerRef.current.scrollLeft); }; const handleMouseMove = (e: MouseEvent) => { if (!isDragging || !containerRef.current) return; e.preventDefault(); const x = e.pageX - containerRef.current.offsetLeft; const walk = (x - startX) * 2; // Увеличиваем скорость прокрутки containerRef.current.scrollLeft = scrollLeft - walk; }; const handleMouseUp = () => { setIsDragging(false); }; // Обработчики для document чтобы отслеживать mouseMove и mouseUp даже вне элемента useEffect(() => { if (isDragging) { document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); } else { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); } return () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; }, [isDragging]); const buttons = []; return (
containerRef.current.clientWidth ? "grab" : "default", }} > {buttons.map((btn) => ( ))}
{showHeaderDropdown && menuPosition && (
{[1, 2, 3, 4, 5].map((level) => ( ))}
)}
); };