106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | 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, | ||
|  |   }; | ||
|  | }; |