{"version":3,"file":"GridDetector.BUQLFfTW.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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"}