import React, { RefObject, Dispatch, SetStateAction, useEffect } from 'react'; import { IContainerModel } from '../../Interfaces/IContainerModel'; import { IPoint } from '../../Interfaces/IPoint'; import { findContainerById } from '../../utils/itertools'; export function useMouseEvents( isContextMenuOpen: boolean, elementRef: RefObject, setIsContextMenuOpen: Dispatch>, setOnClickContainerId: Dispatch>, setContextMenuPosition: Dispatch> ): void { useEffect(() => { const onContextMenu = (event: MouseEvent): void => handleRightClick( event, setIsContextMenuOpen, setOnClickContainerId, setContextMenuPosition ); const onLeftClick = (): void => handleLeftClick( isContextMenuOpen, setIsContextMenuOpen, setOnClickContainerId ); elementRef.current?.addEventListener( 'contextmenu', onContextMenu ); window.addEventListener( 'click', onLeftClick ); return () => { elementRef.current?.removeEventListener( 'contextmenu', onContextMenu ); window.removeEventListener( 'click', onLeftClick ); }; }); } export function handleRightClick( event: MouseEvent, setIsContextMenuOpen: React.Dispatch>, setOnClickContainerId: React.Dispatch>, setContextMenuPosition: React.Dispatch> ): void { event.preventDefault(); if (!(event.target instanceof HTMLButtonElement)) { setIsContextMenuOpen(false); setOnClickContainerId(''); return; } const contextMenuPosition: IPoint = { x: event.pageX, y: event.pageY }; setIsContextMenuOpen(true); setOnClickContainerId(event.target.id); setContextMenuPosition(contextMenuPosition); } export function handleLeftClick( isContextMenuOpen: boolean, setIsContextMenuOpen: React.Dispatch>, setOnClickContainerId: React.Dispatch> ): void { if (!isContextMenuOpen) { return; } setIsContextMenuOpen(false); setOnClickContainerId(''); } export function removeBorderClasses(target: HTMLButtonElement): void { const bordersClasses = ['border-t-8', 'border-8', 'border-b-8']; target.classList.remove(...bordersClasses); } export function handleDragLeave(event: React.DragEvent): void { const target: HTMLButtonElement = event.target as HTMLButtonElement; removeBorderClasses(target); } export function handleDragOver( event: React.DragEvent, mainContainer: IContainerModel ): void { event.preventDefault(); const target: HTMLButtonElement = event.target as HTMLButtonElement; const rect = target.getBoundingClientRect(); const y = event.clientY - rect.top; // y position within the element. removeBorderClasses(target); if (target.id === mainContainer.properties.id) { target.classList.add('border-8'); return; } if (y < 12) { target.classList.add('border-t-8'); } else if (y < 24) { target.classList.add('border-8'); } else { target.classList.add('border-b-8'); } } export function handleOnDrop( event: React.DragEvent, mainContainer: IContainerModel, addContainer: (index: number, type: string, parent: string) => void ): void { event.preventDefault(); const type = event.dataTransfer.getData('type'); const target: HTMLButtonElement = event.target as HTMLButtonElement; removeBorderClasses(target); const targetContainer: IContainerModel | undefined = findContainerById( mainContainer, target.id ); if (targetContainer === undefined) { throw new Error('[handleOnDrop] Tried to drop onto a unknown container!'); } if (targetContainer === mainContainer) { // if the container is the root, only add type as child addContainer( targetContainer.children.length, type, targetContainer.properties.id); return; } if (targetContainer.parent === null || targetContainer.parent === undefined) { throw new Error('[handleDrop] Tried to drop into a child container without a parent!'); } const rect = target.getBoundingClientRect(); const y = event.clientY - rect.top; // y position within the element. // locate the hitboxes if (y < 12) { const index = targetContainer.parent.children.indexOf(targetContainer); addContainer( index, type, targetContainer.parent.properties.id ); } else if (y < 24) { addContainer( targetContainer.children.length, type, targetContainer.properties.id); } else { const index = targetContainer.parent.children.indexOf(targetContainer); addContainer( index + 1, type, targetContainer.parent.properties.id ); } }