graphicek/client/src/pages/dashboard/hooks/useResize.ts

105 lines
2.0 KiB
TypeScript
Raw Normal View History

2022-08-23 23:35:36 +02:00
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
) {
2022-08-24 08:59:18 +02:00
newState.w = box.w * cellWidth + e.clientX - state.offsetX
2022-08-23 23:35:36 +02:00
}
setState(newState)
}
})
return {
setResizing: setState,
resizingSize: { w: actualWidth, h: actualHeight },
resizing: state,
}
}