{"version":3,"file":"GridDetector.BWVP5bX3.mjs","names":[],"sources":["https:/framerusercontent.com/modules/zTNRcOeIT7YJMJC0rd4R/qH1rcImh7SFtcSAZ2P6X/GridDetector.js"],"sourcesContent":["/**\n * @file GridDetector.ts\n * @description Auto grid detection utilities for layout analysis\n *\n * @version 1.0.0 - Production Implementation\n * @since 1.0.0\n *\n * @example\n * ```typescript\n * import { GridDetector } from './GridDetector.ts';\n *\n * const detector = new GridDetector();\n * const gridResult = detector.analyzeLayout(elements);\n *\n * console.log(`Detected ${gridResult.rows}x${gridResult.columns} grid`);\n * console.log(`Confidence: ${gridResult.confidence}`);\n * ```\n */// Module name for logging\nconst MODULE_NAME=\"GridDetector\";/**\n * Grid layout detection and analysis utilities\n *\n * @description\n * Sophisticated grid detection algorithms for automatic layout analysis.\n * Analyzes element positioning patterns to detect grid structures with confidence scoring.\n *\n * **Key Features:**\n * - Automatic grid dimension detection\n * - Positioning pattern analysis\n * - Confidence scoring for validation\n * - Fallback handling for irregular layouts\n * - Optimized for performance with large element sets\n *\n * **Detection Algorithm:**\n * 1. Analyzes element positions for alignment patterns\n * 2. Groups elements by row and column positions\n * 3. Validates grid completeness and regularity\n * 4. Returns confidence score for detection quality\n */export class GridDetector{/**\n     * Analyze element layout to detect grid structure\n     *\n     * @description\n     * Main entry point for grid detection. Analyzes element positioning patterns\n     * to automatically detect grid layout with dimensions and confidence scoring.\n     *\n     * **Algorithm Steps:**\n     * 1. Extract element geometries and filter invalid elements\n     * 2. Detect unique row and column positions\n     * 3. Calculate grid dimensions from position patterns\n     * 4. Map elements to grid positions\n     * 5. Validate grid completeness and return result\n     *\n     * @param elements - Elements to analyze for grid structure\n     * @returns Complete grid detection result with confidence scoring\n     */analyzeLayout(elements){console.log(`🔍 [${MODULE_NAME}] Analyzing layout for ${elements.length} elements`);if(elements.length===0){console.warn(`🔍 [${MODULE_NAME}] No elements provided for grid detection`);return this.createEmptyResult();}if(elements.length===1){console.log(`🔍 [${MODULE_NAME}] Single element detected, creating 1x1 grid`);return this.createSingleElementResult(elements[0]);}// Extract element geometries\nconst geometries=this.extractElementGeometries(elements);const validGeometries=geometries.filter(g=>g!==null);if(validGeometries.length!==elements.length){console.warn(`🔍 [${MODULE_NAME}] Some elements have invalid geometries, filtering from ${elements.length} to ${validGeometries.length}`);}if(validGeometries.length===0){console.error(`🔍 [${MODULE_NAME}] No valid geometries found`);return this.createEmptyResult();}// Detect grid patterns\nreturn this.detectGridFromGeometries(elements,validGeometries);}/**\n     * Extract element geometries with error handling\n     *\n     * @description\n     * Safely extracts bounding rectangles from elements with fallback handling\n     * for elements that can't be measured (hidden, detached, etc.).\n     *\n     * @param elements - Elements to extract geometries from\n     * @returns Array of element geometries (null for invalid elements)\n     */extractElementGeometries(elements){return elements.map((element,index)=>{try{const rect=element.getBoundingClientRect();// Validate element has reasonable dimensions\nif(rect.width===0||rect.height===0){console.warn(`🔍 [${MODULE_NAME}] Element ${index} has zero dimensions, skipping`);return null;}return{left:rect.left,top:rect.top,right:rect.right,bottom:rect.bottom,width:rect.width,height:rect.height};}catch(error){console.error(`🔍 [${MODULE_NAME}] Error getting geometry for element ${index}:`,error);return null;}});}/**\n     * Detect grid structure from validated geometries\n     *\n     * @description\n     * Core grid detection algorithm that analyzes positioning patterns\n     * to determine grid dimensions and element positions.\n     *\n     * @param elements - Original element array\n     * @param geometries - Validated element geometries\n     * @returns Complete grid detection result\n     */detectGridFromGeometries(elements,geometries){// Extract unique positions with tolerance for floating point issues\nconst yPositions=this.extractUniquePositions(geometries.map(g=>g.top));const xPositions=this.extractUniquePositions(geometries.map(g=>g.left));const rows=yPositions.length;const columns=xPositions.length;console.log(`🔍 [${MODULE_NAME}] Detected grid dimensions: ${rows} rows x ${columns} columns`);console.log(`🔍 [${MODULE_NAME}] Y positions: [${yPositions.map(y=>Math.round(y)).join(\", \")}]`);console.log(`🔍 [${MODULE_NAME}] X positions: [${xPositions.map(x=>Math.round(x)).join(\", \")}]`);// If dimensions don't match element count, use precise detection\nif(rows*columns!==geometries.length){console.log(`🔍 [${MODULE_NAME}] Grid dimensions (${rows}x${columns}=${rows*columns}) don't match element count (${geometries.length}). Using precise detection.`);return this.detectGridPrecise(elements,geometries);}// Map elements to grid positions\nconst gridElements=this.mapElementsToGrid(elements,geometries,xPositions,yPositions);// Calculate default origin point (center of grid)\nconst originPoint={x:(columns-1)/2,y:(rows-1)/2};console.log(`🔍 [${MODULE_NAME}] Grid origin point: (${originPoint.x.toFixed(1)}, ${originPoint.y.toFixed(1)})`);return{rows,columns,elements:gridElements,originPoint,maxDistance:0};}/**\n     * Extract unique positions with tolerance for alignment\n     *\n     * @description\n     * Groups similar positions together to handle minor alignment differences\n     * and floating point precision issues.\n     *\n     * @param positions - Array of position values\n     * @param tolerance - Alignment tolerance in pixels\n     * @returns Sorted array of unique positions\n     */extractUniquePositions(positions,tolerance=2){if(positions.length===0)return[];const sortedPositions=[...positions].sort((a,b)=>a-b);const uniquePositions=[sortedPositions[0]];for(let i=1;i<sortedPositions.length;i++){const current=sortedPositions[i];const last=uniquePositions[uniquePositions.length-1];// If position is different enough, add as new unique position\nif(Math.abs(current-last)>tolerance){uniquePositions.push(current);}}return uniquePositions;}/**\n     * Map elements to their grid positions\n     *\n     * @description\n     * Assigns each element to its position in the detected grid structure\n     * by finding the closest matching row and column positions.\n     *\n     * @param elements - Original element array\n     * @param geometries - Element geometries\n     * @param xPositions - Detected column positions\n     * @param yPositions - Detected row positions\n     * @returns Array of positioned grid elements\n     */mapElementsToGrid(elements,geometries,xPositions,yPositions){const gridElements=[];elements.forEach((element,index)=>{const geometry=geometries[index];if(geometry){const rowIndex=this.findClosestPositionIndex(geometry.top,yPositions);const colIndex=this.findClosestPositionIndex(geometry.left,xPositions);gridElements.push({element,position:{x:colIndex,y:rowIndex},pixelPosition:{left:geometry.left,top:geometry.top,right:geometry.right,bottom:geometry.bottom,width:geometry.width,height:geometry.height,x:geometry.left,y:geometry.top},distance:0,normalizedDistance:0,index});console.log(`🔍 [${MODULE_NAME}] Element ${index} mapped to grid position (${colIndex},${rowIndex})`);}});return gridElements;}/**\n     * Find closest position index for element placement\n     *\n     * @description\n     * Finds the index of the closest position in the unique positions array\n     * for accurate grid position assignment.\n     *\n     * @param position - Position to find closest match for\n     * @param positions - Array of unique positions\n     * @returns Index of closest position\n     */findClosestPositionIndex(position,positions){let closestIndex=0;let minDistance=Math.abs(position-positions[0]);for(let i=1;i<positions.length;i++){const distance=Math.abs(position-positions[i]);if(distance<minDistance){minDistance=distance;closestIndex=i;}}return closestIndex;}/**\n     * Precise grid detection for irregular layouts\n     *\n     * @description\n     * Advanced detection algorithm for cases where simple row/column counting\n     * doesn't match element count. Uses more sophisticated analysis.\n     *\n     * @param elements - Original element array\n     * @param geometries - Element geometries\n     * @returns Precise grid detection result\n     */detectGridPrecise(elements,geometries){console.log(`🔍 [${MODULE_NAME}] Using precise grid detection for irregular layout`);// For precise detection, analyze actual row and column groupings\nconst rowGroups=this.groupElementsByRows(geometries);const columnGroups=this.groupElementsByColumns(geometries);const rowCount=rowGroups.length;const columnCount=columnGroups.length;console.log(`🔍 [${MODULE_NAME}] Precise detection: ${rowCount} rows, ${columnCount} columns`);// Create grid elements based on precise grouping\nconst gridElements=this.createGridElementsFromGroups(elements,geometries,rowGroups,columnGroups);// Default origin point is center of the grid\nconst originPoint={x:(columnCount-1)/2,y:(rowCount-1)/2};return{rows:rowCount,columns:columnCount,elements:gridElements,originPoint,maxDistance:0};}/**\n     * Group elements by row positions\n     *\n     * @description\n     * Groups elements that share similar Y coordinates into rows\n     * with tolerance for alignment variations.\n     *\n     * @param geometries - Element geometries\n     * @param tolerance - Grouping tolerance in pixels\n     * @returns Array of row groups\n     */groupElementsByRows(geometries,tolerance=5){const groups=[];const processed=new Set;geometries.forEach((geometry,index)=>{if(processed.has(index))return;const group=[index];processed.add(index);// Find other elements in the same row\ngeometries.forEach((otherGeometry,otherIndex)=>{if(otherIndex!==index&&!processed.has(otherIndex)){if(Math.abs(geometry.top-otherGeometry.top)<=tolerance){group.push(otherIndex);processed.add(otherIndex);}}});groups.push(group);});return groups;}/**\n     * Group elements by column positions\n     *\n     * @description\n     * Groups elements that share similar X coordinates into columns\n     * with tolerance for alignment variations.\n     *\n     * @param geometries - Element geometries\n     * @param tolerance - Grouping tolerance in pixels\n     * @returns Array of column groups\n     */groupElementsByColumns(geometries,tolerance=5){const groups=[];const processed=new Set;geometries.forEach((geometry,index)=>{if(processed.has(index))return;const group=[index];processed.add(index);// Find other elements in the same column\ngeometries.forEach((otherGeometry,otherIndex)=>{if(otherIndex!==index&&!processed.has(otherIndex)){if(Math.abs(geometry.left-otherGeometry.left)<=tolerance){group.push(otherIndex);processed.add(otherIndex);}}});groups.push(group);});return groups;}/**\n     * Create grid elements from row/column groups\n     *\n     * @description\n     * Maps elements to grid positions based on precise row and column groupings\n     * for irregular grid layouts.\n     *\n     * @param elements - Original element array\n     * @param geometries - Element geometries\n     * @param rowGroups - Element indices grouped by rows\n     * @param columnGroups - Element indices grouped by columns\n     * @returns Array of positioned grid elements\n     */createGridElementsFromGroups(elements,geometries,rowGroups,columnGroups){const gridElements=[];elements.forEach((element,index)=>{const geometry=geometries[index];if(!geometry)return;// Find which row and column this element belongs to\nconst rowIndex=rowGroups.findIndex(group=>group.includes(index));const colIndex=columnGroups.findIndex(group=>group.includes(index));if(rowIndex!==-1&&colIndex!==-1){gridElements.push({element,position:{x:colIndex,y:rowIndex},pixelPosition:{left:geometry.left,top:geometry.top,right:geometry.right,bottom:geometry.bottom,width:geometry.width,height:geometry.height,x:geometry.left,y:geometry.top},distance:0,normalizedDistance:0,index});}});return gridElements;}/**\n     * Create empty result for edge cases\n     *\n     * @description\n     * Returns a safe empty result when no valid grid can be detected.\n     *\n     * @returns Empty grid detection result\n     */createEmptyResult(){return{rows:0,columns:0,elements:[],originPoint:{x:0,y:0},maxDistance:0};}/**\n     * Create single element result\n     *\n     * @description\n     * Creates a 1x1 grid result for single element scenarios.\n     *\n     * @param element - Single element to create grid for\n     * @returns Single element grid result\n     */createSingleElementResult(element){const rect=element.getBoundingClientRect();const gridElement={element,position:{x:0,y:0},pixelPosition:rect,distance:0,normalizedDistance:0,index:0};return{rows:1,columns:1,elements:[gridElement],originPoint:{x:0,y:0},maxDistance:0};}}\nexport const __FramerMetadata__ = {\"exports\":{\"GridDetector\":{\"type\":\"class\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./GridDetector.map"],"mappings":"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"}