mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: resolve 50+ bugs across editor store, canvas, panels, and tools
- Store: loadImage resets state, applyCrop updates sourceImageSize, setTool clears stale cropState, layer ordering preserved across layers, rotateCanvas/flipCanvas account for object dimensions, trimCanvas implemented, resizeCanvas supports anchor positioning - Canvas: crop overlay interactive, move tool drag events wired, hand tool panning, stage ref effect mount-only, checkerboard tracks pan offset, filter cache clearing - Panels: hslToHex color fix for hue 240-360, adjustments single setAdjustment call, curves draggingIndex after sort, history panel fresh temporal reads, export transparent setting, canvas resize dialog re-sync, hex input respects picker target - Tools: text tool fixed positioning and event cleanup, shape tool deferred addObject, selection mode wired to store, magic wand tolerance controlled, eyedropper coordinate transform - Options: dodge-burn/shape/clone/fill/gradient/pixel-brush use proper store actions instead of raw setState - Added 20+ store actions for tool settings - Updated tests for corrected rotation/flip/trim behavior - Excluded e2e-editor from vitest config
This commit is contained in:
@@ -157,9 +157,10 @@ export function alignObjects(
|
||||
objectIds: string[],
|
||||
objects: { id: string; attrs: Record<string, unknown> }[],
|
||||
updateObject: (id: string, attrs: Record<string, unknown>) => void,
|
||||
canvasSize?: { width: number; height: number },
|
||||
): void {
|
||||
const selected = objects.filter((o) => objectIds.includes(o.id));
|
||||
if (selected.length < 2 && !direction.startsWith("distribute")) return;
|
||||
if (selected.length === 0) return;
|
||||
if (selected.length < 3 && direction.startsWith("distribute")) return;
|
||||
|
||||
const bounds = selected.map((o) => ({
|
||||
@@ -170,6 +171,34 @@ export function alignObjects(
|
||||
h: (o.attrs.height as number) ?? 0,
|
||||
}));
|
||||
|
||||
// Single object: align relative to canvas bounds
|
||||
if (selected.length === 1 && canvasSize) {
|
||||
const b = bounds[0];
|
||||
switch (direction) {
|
||||
case "left":
|
||||
updateObject(b.id, { x: 0 });
|
||||
break;
|
||||
case "center-h":
|
||||
updateObject(b.id, { x: canvasSize.width / 2 - b.w / 2 });
|
||||
break;
|
||||
case "right":
|
||||
updateObject(b.id, { x: canvasSize.width - b.w });
|
||||
break;
|
||||
case "top":
|
||||
updateObject(b.id, { y: 0 });
|
||||
break;
|
||||
case "center-v":
|
||||
updateObject(b.id, { y: canvasSize.height / 2 - b.h / 2 });
|
||||
break;
|
||||
case "bottom":
|
||||
updateObject(b.id, { y: canvasSize.height - b.h });
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected.length < 2) return;
|
||||
|
||||
switch (direction) {
|
||||
case "left": {
|
||||
const minX = Math.min(...bounds.map((b) => b.x));
|
||||
|
||||
Reference in New Issue
Block a user