import type { DashboardWidget, GridCellMetrics } from './types.js'; export interface PointerPosition { clientX: number; clientY: number; } export interface DragComputationArgs { pointer: PointerPosition; containerRect: DOMRect; metrics: GridCellMetrics; columns: number; widget: DashboardWidget; rtl: boolean; dragOffsetX?: number; dragOffsetY?: number; } export const computeGridCoordinates = ({ pointer, containerRect, metrics, columns, widget, rtl, dragOffsetX = 0, dragOffsetY = 0, }: DragComputationArgs): { x: number; y: number } => { const relativeX = pointer.clientX - containerRect.left - dragOffsetX; const relativeY = pointer.clientY - containerRect.top - dragOffsetY; const marginX = metrics.marginHorizontalPx; const marginY = metrics.marginVerticalPx; const cellWidth = metrics.cellWidthPx; const cellHeight = metrics.cellHeightPx; const clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(max, value)); const adjustedX = clamp(relativeX - marginX, 0, containerRect.width - marginX); const adjustedY = clamp(relativeY - marginY, 0, Number.POSITIVE_INFINITY); const cellPlusMarginX = cellWidth + marginX; const cellPlusMarginY = cellHeight + marginY; let gridX = Math.round(adjustedX / cellPlusMarginX); if (rtl) { gridX = columns - widget.w - gridX; } gridX = clamp(gridX, 0, columns - widget.w); const gridY = clamp(Math.round(adjustedY / cellPlusMarginY), 0, Number.MAX_SAFE_INTEGER); return { x: gridX, y: gridY }; }; export interface ResizeComputationArgs { pointer: PointerPosition; containerRect: DOMRect; metrics: GridCellMetrics; startWidth: number; startHeight: number; startPointer: PointerPosition; handler: 'e' | 's' | 'se'; widget: DashboardWidget; columns: number; } export const computeResizeDimensions = ({ pointer, containerRect, metrics, startWidth, startHeight, startPointer, handler, widget, columns, }: ResizeComputationArgs): { width: number; height: number } => { const deltaX = pointer.clientX - startPointer.clientX; const deltaY = pointer.clientY - startPointer.clientY; let width = startWidth; let height = startHeight; const cellPlusMarginX = metrics.cellWidthPx + metrics.marginHorizontalPx; const cellPlusMarginY = metrics.cellHeightPx + metrics.marginVerticalPx; if (handler.includes('e')) { const deltaCols = Math.round(deltaX / cellPlusMarginX); width = startWidth + deltaCols; } if (handler.includes('s')) { const deltaRows = Math.round(deltaY / cellPlusMarginY); height = startHeight + deltaRows; } const clampedWidth = Math.max(widget.minW || 1, Math.min(width, widget.maxW || columns - widget.x)); const clampedHeight = Math.max(widget.minH || 1, Math.min(height, widget.maxH || Number.MAX_SAFE_INTEGER)); return { width: clampedWidth, height: clampedHeight, }; };