feat(dees-dashboardgrid): implement collision detection during widget swap to prevent overlaps
This commit is contained in:
BIN
readme.plan.md
BIN
readme.plan.md
Binary file not shown.
28
test/test.dashboardgrid-layout.node.ts
Normal file
28
test/test.dashboardgrid-layout.node.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
|
||||||
|
import {
|
||||||
|
resolveWidgetPlacement,
|
||||||
|
collectCollisions,
|
||||||
|
} from '../ts_web/elements/dees-dashboardgrid/layout.ts';
|
||||||
|
import type { DashboardWidget } from '../ts_web/elements/dees-dashboardgrid/types.ts';
|
||||||
|
|
||||||
|
tap.test('dashboardgrid does not overlap widgets after swap attempt', async () => {
|
||||||
|
const widgets: DashboardWidget[] = [
|
||||||
|
{ id: 'w0', x: 6, y: 5, w: 1, h: 3 },
|
||||||
|
{ id: 'w1', x: 6, y: 1, w: 1, h: 3 },
|
||||||
|
{ id: 'w2', x: 3, y: 0, w: 2, h: 2 },
|
||||||
|
{ id: 'w3', x: 9, y: 0, w: 1, h: 2 },
|
||||||
|
{ id: 'w4', x: 4, y: 3, w: 1, h: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const placement = resolveWidgetPlacement(widgets, 'w0', { x: 6, y: 3 }, 12);
|
||||||
|
expect(placement).toBeTruthy();
|
||||||
|
|
||||||
|
const layout = placement!.widgets;
|
||||||
|
for (const widget of layout) {
|
||||||
|
const collisions = collectCollisions(layout, widget, widget.x, widget.y, widget.w, widget.h);
|
||||||
|
expect(collisions).toBeEmptyArray();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default tap.start();
|
@@ -164,9 +164,20 @@ export const resolveWidgetPlacement = (
|
|||||||
// Use the original position of the moving widget for a clean swap
|
// Use the original position of the moving widget for a clean swap
|
||||||
// This prevents the "snapping together" issue where both widgets end up at the same position
|
// This prevents the "snapping together" issue where both widgets end up at the same position
|
||||||
const swapTarget = original;
|
const swapTarget = original;
|
||||||
|
const previousOtherPosition = { x: otherClone.x, y: otherClone.y };
|
||||||
otherClone.x = swapTarget.x;
|
otherClone.x = swapTarget.x;
|
||||||
otherClone.y = swapTarget.y;
|
otherClone.y = swapTarget.y;
|
||||||
return { widgets: sourceWidgets, movedWidgets: [moving.id, otherClone.id], swappedWith: otherClone.id };
|
|
||||||
|
const swapValid =
|
||||||
|
collectCollisions(sourceWidgets, moving, moving.x, moving.y, moving.w, moving.h).length === 0 &&
|
||||||
|
collectCollisions(sourceWidgets, otherClone, otherClone.x, otherClone.y, otherClone.w, otherClone.h).length === 0;
|
||||||
|
|
||||||
|
if (swapValid) {
|
||||||
|
return { widgets: sourceWidgets, movedWidgets: [moving.id, otherClone.id], swappedWith: otherClone.id };
|
||||||
|
}
|
||||||
|
|
||||||
|
otherClone.x = previousOtherPosition.x;
|
||||||
|
otherClone.y = previousOtherPosition.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user