UNPKG

ttabs-svelte

Version:

A flexible layout management system with draggable, resizable tiles and tabs for Svelte applications. Like in VSCode

111 lines (110 loc) 4.46 kB
/** * Parses a size value string into a SizeInfo object * @param size String representation of size (e.g., "100%", "260px") * @returns Parsed SizeInfo object */ export function parseSizeValue(size) { // Parse percentage values if (size.endsWith('%')) { const percentValue = parseFloat(size); if (isNaN(percentValue)) { throw new Error(`Invalid percentage format: ${size}`); } return { value: percentValue, unit: '%' }; } // Parse pixel values if (size.endsWith('px')) { const pixelValue = parseFloat(size); if (isNaN(pixelValue)) { throw new Error(`Invalid pixel format: ${size}`); } return { value: pixelValue, unit: 'px' }; } // Try to parse as a number and assume it's a percentage (for backward compatibility) const numericValue = parseFloat(size); if (!isNaN(numericValue)) { return { value: numericValue, unit: '%' }; } throw new Error(`Invalid size format: ${size}. Expected format: "100%" or "260px"`); } /** * Calculates sizes for a set of elements in a container * @param containerSize Size of the container in pixels * @param elements Array of elements with their size information * @returns Array of calculated sizes in pixels with possible scale indicators */ export function calculateSizes(containerSize, elements) { if (elements.length === 0) return []; // Identify different types of elements let totalFixedSize = 0; let totalPercentage = 0; const fixedElements = []; const percentElements = []; // First pass: categorize elements and calculate fixed totals elements.forEach(element => { if (element.size.unit === 'px') { totalFixedSize += element.size.value; fixedElements.push({ id: element.id, size: element.size.value }); } else if (element.size.unit === '%') { totalPercentage += element.size.value; percentElements.push({ id: element.id, percent: element.size.value }); } }); // Results array const results = []; // Handle case where all elements are fixed if (percentElements.length === 0 && fixedElements.length > 0) { // Scale fixed elements if they exceed container size const fixedScaleFactor = totalFixedSize > containerSize ? containerSize / totalFixedSize : 1; fixedElements.forEach(element => { results.push({ id: element.id, computedSize: element.size * fixedScaleFactor, scaledDown: fixedScaleFactor < 1 }); }); return results; } // Handle case where all elements are percentage-based if (fixedElements.length === 0 && percentElements.length > 0) { // Normalize percentages to 100% if they don't add up to 100% const percentScaleFactor = totalPercentage !== 100 ? 100 / totalPercentage : 1; percentElements.forEach(element => { const adjustedPercent = element.percent * percentScaleFactor; results.push({ id: element.id, computedSize: (containerSize * adjustedPercent) / 100, scaledDown: false }); }); return results; } // Handle mixed case (both fixed and percentage elements) // First, handle fixed elements (scale them if needed) const availableForFixed = containerSize; const fixedScaleFactor = totalFixedSize > availableForFixed ? availableForFixed / totalFixedSize : 1; const actualFixedSize = totalFixedSize * fixedScaleFactor; fixedElements.forEach(element => { results.push({ id: element.id, computedSize: element.size * fixedScaleFactor, scaledDown: fixedScaleFactor < 1 }); }); // Calculate remaining space for percentage elements const remainingSpace = Math.max(0, containerSize - actualFixedSize); // Always normalize percentages to 100% in mixed layouts // This ensures percentage elements fill exactly the remaining space const percentScaleFactor = 100 / totalPercentage; percentElements.forEach(element => { const adjustedPercent = element.percent * percentScaleFactor; results.push({ id: element.id, computedSize: (remainingSpace * adjustedPercent) / 100, scaledDown: false }); }); return results; }