Neovici/cosmoz-omnitable

View on GitHub
lib/layout.js

Summary

Maintainability
A
3 hrs
Test Coverage
A
100%
const finite = num => Number.isFinite(num) ? num : 0;
export const
    // eslint-disable-next-line max-lines-per-function,  max-statements
    layout = (columns, container) => {
        const result = [];

        // eslint-disable-next-line one-var
        let [widthSum, lots] = columns.reduce(
                ([widthSum, lots], { width, flex }) => [
                    widthSum + width,
                    lots + flex
                ],
                [0, 0]
            ),
            freeRealEstate = container - widthSum,
            lotSize = finite(freeRealEstate / lots),
            droppedWidth = 0,
            droppedContainerWidth = 0,
            droppedLots = 0;

        // first pass: apply and drop lots with minWidth or flex 0
        for (let i = 0; i < columns.length; i++) {
            const { width, minWidth, flex } = columns[i],
                adjustment = freeRealEstate >= 0
                    ? lotSize * flex
                    : width * freeRealEstate / widthSum;

            if (minWidth > width + adjustment) {
                droppedWidth += width;
                droppedContainerWidth += minWidth;
                droppedLots += flex;
                result[i] = minWidth;
                continue;
            }

            if (flex === 0) {
                droppedWidth += width;
                droppedContainerWidth += width;
                result[i] = width;
                continue;
            }
        }

        widthSum -= droppedWidth;
        freeRealEstate = container - droppedContainerWidth - widthSum;
        lots -= droppedLots;
        lotSize = finite(freeRealEstate / lots);

        // second pass: distribute the remaining space
        for (let i = 0; i < columns.length; i++) {
            if (result[i] != null) {
                continue;
            }

            const { width, flex } = columns[i],
                adjustment = freeRealEstate >= 0
                    ? lotSize * flex
                    : width * freeRealEstate / widthSum;

            result[i] = width + adjustment;
        }

        return result;
    };