import { clamp } from './model'; import type { CanvasLayer } from './types'; export type CanvasLayerResizeHandle = | 'left' | 'top' | 'right' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; export type CanvasLayerTransformBounds = Pick< CanvasLayer, 'x' | 'y' | 'width' | 'height' >; const MIN_LAYER_SIZE = 1; export function resizeCanvasLayerBounds({ initial, handle, deltaX, deltaY, preserveAspectRatio, minSize = MIN_LAYER_SIZE, }: { initial: CanvasLayerTransformBounds; handle: CanvasLayerResizeHandle; deltaX: number; deltaY: number; preserveAspectRatio: boolean; minSize?: number; }): CanvasLayerTransformBounds { const safeMinSize = Math.max(MIN_LAYER_SIZE, minSize); const movesLeft = handle.includes('left'); const movesRight = handle.includes('right'); const movesTop = handle.includes('top'); const movesBottom = handle.includes('bottom'); let width = initial.width + (movesRight ? deltaX : movesLeft ? -deltaX : 0); let height = initial.height + (movesBottom ? deltaY : movesTop ? -deltaY : 0); if (preserveAspectRatio) { const ratio = initial.width / Math.max(initial.height, safeMinSize); if (movesLeft || movesRight) { height = width / Math.max(ratio, Number.EPSILON); } else { width = height * ratio; } } width = clamp(width, safeMinSize, Number.MAX_SAFE_INTEGER); height = clamp(height, safeMinSize, Number.MAX_SAFE_INTEGER); return { x: movesLeft ? initial.x + initial.width - width : initial.x, y: movesTop ? initial.y + initial.height - height : initial.y, width, height, }; } export function transformCanvasLayers( layers: CanvasLayer[], transforms: ReadonlyMap>, ) { return layers.map((layer) => { const transform = transforms.get(layer.id); if (!transform || layer.locked) { return layer; } return { ...layer, x: transform.x ?? layer.x, y: transform.y ?? layer.y, width: Math.max(MIN_LAYER_SIZE, transform.width ?? layer.width), height: Math.max(MIN_LAYER_SIZE, transform.height ?? layer.height), }; }); }