import { useWindowEvent } from '@/utils/hooks/useWindowEvent' import { useState } from 'preact/hooks' import { BoxDefinition } from '../types' import { GRID_WIDTH } from '../constants' export enum ResizingMode { NONE, WIDTH, HEIGHT, ALL, } type Props = { cellWidth: number boxes: BoxDefinition[] box: BoxDefinition } // TODO: This is not optimized at all export const useResize = ({ cellWidth, box, boxes }: Props) => { const [state, setState] = useState({ mode: ResizingMode.NONE, w: 0, h: 0, offsetX: 0, offsetY: 0, }) const isResizing = state.mode !== ResizingMode.NONE const maxHeights = isResizing ? Array(GRID_WIDTH) .fill(null) .map((_, index) => { return boxes .filter( (b) => b.id !== box.id && b.x <= index && b.x + b.w > index && b.y > box.y ) .reduce( (acc, item) => (item.y - box.y > acc ? item.y - box.y : acc), 0 ) }) : [] const actualHeight = isResizing ? Math.min( ...Array(box.w) .fill(null) .map((_, x) => maxHeights[box.x + x]) .filter((x) => x > 0), Math.round(state.h / 16) * 16 ) : 0 const maxWidth = isResizing ? boxes .filter( (b) => b.id !== box.id && b.x > box.x && b.y < box.y + box.h && box.y < b.y + b.h ) .map((b) => b.x - box.x) .reduce((acc, item) => (item < acc ? item : acc), GRID_WIDTH) : 0 const actualWidth = Math.min(maxWidth, Math.round(state.w / cellWidth)) useWindowEvent('mousemove', (e) => { if (isResizing) { const newState = { ...state, } if ( state.mode === ResizingMode.ALL || state.mode === ResizingMode.HEIGHT ) { newState.h = box.h + e.clientY - state.offsetY } if ( state.mode === ResizingMode.ALL || state.mode === ResizingMode.WIDTH ) { newState.w = box.w * cellWidth + e.clientX - state.offsetX } setState(newState) } }) return { setResizing: setState, resizingSize: { w: actualWidth, h: actualHeight }, resizing: state, } }