import type { FolkShape } from "./folk-shape"; interface StoredDimensions { x: number; y: number; width: number; height: number; rotation: number; } // Store original dimensions for each maximized shape const originalDimensions = new WeakMap(); /** * Check if a shape is currently maximized */ export function isMaximized(shape: FolkShape): boolean { return originalDimensions.has(shape); } /** * Maximize a shape to fill the viewport * @param shape - The shape to maximize * @param padding - Padding from viewport edges (default 40px) * @param animate - Whether to animate the transition (default true) */ export function maximizeShape( shape: FolkShape, padding = 40, animate = true ): void { if (isMaximized(shape)) { // Already maximized, restore instead restoreShape(shape, animate); return; } // Store original dimensions originalDimensions.set(shape, { x: shape.x, y: shape.y, width: shape.width, height: shape.height, rotation: shape.rotation, }); // Calculate viewport dimensions const viewportWidth = window.innerWidth - padding * 2; const viewportHeight = window.innerHeight - padding * 2; // Get canvas element to account for any transforms const canvas = shape.closest("#canvas") as HTMLElement | null; const canvasRect = canvas?.getBoundingClientRect(); const scrollX = window.scrollX || 0; const scrollY = window.scrollY || 0; // Calculate centered position const newX = padding + scrollX - (canvasRect?.left || 0); const newY = padding + scrollY - (canvasRect?.top || 0); if (animate) { shape.style.transition = "all 0.3s ease-out"; } // Apply maximized dimensions shape.x = newX; shape.y = newY; shape.width = viewportWidth; shape.height = viewportHeight; shape.rotation = 0; // Add maximized state shape.setAttribute("data-maximized", "true"); // Remove transition after animation if (animate) { setTimeout(() => { shape.style.transition = ""; }, 300); } // Dispatch event shape.dispatchEvent( new CustomEvent("maximize", { detail: { maximized: true }, bubbles: true, }) ); } /** * Restore a maximized shape to its original dimensions * @param shape - The shape to restore * @param animate - Whether to animate the transition (default true) */ export function restoreShape(shape: FolkShape, animate = true): void { const original = originalDimensions.get(shape); if (!original) return; if (animate) { shape.style.transition = "all 0.3s ease-out"; } // Restore original dimensions shape.x = original.x; shape.y = original.y; shape.width = original.width; shape.height = original.height; shape.rotation = original.rotation; // Remove maximized state shape.removeAttribute("data-maximized"); originalDimensions.delete(shape); // Remove transition after animation if (animate) { setTimeout(() => { shape.style.transition = ""; }, 300); } // Dispatch event shape.dispatchEvent( new CustomEvent("maximize", { detail: { maximized: false }, bubbles: true, }) ); } /** * Toggle maximize state of a shape * @param shape - The shape to toggle * @param padding - Padding from viewport edges (default 40px) * @param animate - Whether to animate the transition (default true) */ export function toggleMaximize( shape: FolkShape, padding = 40, animate = true ): void { if (isMaximized(shape)) { restoreShape(shape, animate); } else { maximizeShape(shape, padding, animate); } }