Fixed dragging not positioning properly
This commit is contained in:
parent
dddcfa7154
commit
1a75e7bad0
|
|
@ -2,6 +2,7 @@ import { useWindowEvent } from '@/utils/hooks/useWindowEvent'
|
||||||
import { useState } from 'preact/hooks'
|
import { useState } from 'preact/hooks'
|
||||||
import { BoxDefinition } from '../types'
|
import { BoxDefinition } from '../types'
|
||||||
import { GRID_H_SNAP, GRID_WIDTH } from '../constants'
|
import { GRID_H_SNAP, GRID_WIDTH } from '../constants'
|
||||||
|
import { range } from '@/utils/range'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
cellWidth: number
|
cellWidth: number
|
||||||
|
|
@ -26,22 +27,42 @@ export const useDragging = ({ cellWidth, boxes, box }: Props) => {
|
||||||
|
|
||||||
const dragY = Math.max(0, Math.round(state.y / GRID_H_SNAP) * GRID_H_SNAP)
|
const dragY = Math.max(0, Math.round(state.y / GRID_H_SNAP) * GRID_H_SNAP)
|
||||||
|
|
||||||
const gridHeights = Array(GRID_WIDTH)
|
const maxHeight = Math.max(
|
||||||
.fill(null)
|
...range(actualX, actualX + box.w).map((x) => {
|
||||||
.map((_, index) => {
|
// All boxes that are in this column
|
||||||
return boxes
|
const boxesAtColumn = boxes.filter(
|
||||||
.filter(
|
(b) => b.id !== box.id && b.x <= x && b.x + b.w > x
|
||||||
(b) =>
|
)
|
||||||
b.id !== box.id &&
|
|
||||||
b.x <= index &&
|
// Find boxes that would be colliding at this position
|
||||||
b.x + b.w > index &&
|
const collisions = boxesAtColumn.filter(
|
||||||
((b.y < dragY + box.h && dragY < b.y + b.h) || b.y < dragY)
|
(b) => b.y < dragY + box.h && dragY < b.y + b.h
|
||||||
)
|
)
|
||||||
.reduce(
|
|
||||||
(acc, item) => (item.y + item.h > acc ? item.y + item.h : acc),
|
if (collisions.length > 0) {
|
||||||
0
|
const upperBoxes = boxesAtColumn.filter((b) => b.y + b.h > dragY)
|
||||||
)
|
|
||||||
|
// Try to find a space to fit somewhere up
|
||||||
|
for (let i = 1; i < upperBoxes.length; i++) {
|
||||||
|
const prevBox = upperBoxes[i - 1]
|
||||||
|
const thisBox = upperBoxes[i]
|
||||||
|
|
||||||
|
if (thisBox.y - (prevBox.y + prevBox.h) >= box.h) {
|
||||||
|
return prevBox.y + prevBox.h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing found, we'll have to stack to the upper box
|
||||||
|
const lastBox = boxesAtColumn[boxesAtColumn.length - 1]
|
||||||
|
|
||||||
|
return lastBox ? lastBox.y + lastBox.h : 0
|
||||||
|
} else {
|
||||||
|
const bottomBox = boxesAtColumn.reverse().find((b) => b.y < dragY)
|
||||||
|
|
||||||
|
return bottomBox ? bottomBox.y + bottomBox.h : 0
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
|
||||||
useWindowEvent('mousemove', (e) => {
|
useWindowEvent('mousemove', (e) => {
|
||||||
if (state.active) {
|
if (state.active) {
|
||||||
|
|
@ -58,11 +79,7 @@ export const useDragging = ({ cellWidth, boxes, box }: Props) => {
|
||||||
setDragging: setState,
|
setDragging: setState,
|
||||||
draggingPosition: {
|
draggingPosition: {
|
||||||
x: actualX,
|
x: actualX,
|
||||||
y: Math.max(
|
y: maxHeight,
|
||||||
...Array(box.w)
|
|
||||||
.fill(null)
|
|
||||||
.map((_, x) => gridHeights[actualX + x])
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
export function range(length: number): number[]
|
||||||
|
export function range(start: number, end: number, step?: number): number[]
|
||||||
|
|
||||||
|
export function range(a1: number, a2?: number, a3?: number): number[] {
|
||||||
|
const start = typeof a2 === 'undefined' ? 0 : a1
|
||||||
|
const end = typeof a2 === 'undefined' ? a1 : a2
|
||||||
|
const step = a3 ?? 1
|
||||||
|
|
||||||
|
return Array(end - start)
|
||||||
|
.fill(null)
|
||||||
|
.map((_, i) => start + i * step)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue