"use strict";
'use client';
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var jsx_runtime_1 = require("react/jsx-runtime");
var react_1 = require("react");
var detect_element_overflow_1 = __importDefault(require("detect-element-overflow"));
var warning_1 = __importDefault(require("warning"));
var isBrowser = typeof document !== 'undefined';
var isMutationObserverSupported = isBrowser && 'MutationObserver' in window;
function capitalize(string) {
    return (string.charAt(0).toUpperCase() + string.slice(1));
}
function findScrollContainer(element) {
    var parent = element.parentElement;
    while (parent) {
        var overflow = window.getComputedStyle(parent).overflow;
        if (overflow.split(' ').every(function (o) { return o === 'auto' || o === 'scroll'; })) {
            return parent;
        }
        parent = parent.parentElement;
    }
    return document.documentElement;
}
function alignAxis(_a) {
    var axis = _a.axis, container = _a.container, element = _a.element, invertAxis = _a.invertAxis, scrollContainer = _a.scrollContainer, secondary = _a.secondary, spacing = _a.spacing;
    var style = window.getComputedStyle(element);
    var parent = container.parentElement;
    if (!parent) {
        return;
    }
    var scrollContainerCollisions = (0, detect_element_overflow_1.default)(parent, scrollContainer);
    var documentCollisions = (0, detect_element_overflow_1.default)(parent, document.documentElement);
    var isX = axis === 'x';
    var startProperty = isX ? 'left' : 'top';
    var endProperty = isX ? 'right' : 'bottom';
    var sizeProperty = isX ? 'width' : 'height';
    var overflowStartProperty = "overflow".concat(capitalize(startProperty));
    var overflowEndProperty = "overflow".concat(capitalize(endProperty));
    var scrollProperty = "scroll".concat(capitalize(startProperty));
    var uppercasedSizeProperty = capitalize(sizeProperty);
    var offsetSizeProperty = "offset".concat(uppercasedSizeProperty);
    var clientSizeProperty = "client".concat(uppercasedSizeProperty);
    var minSizeProperty = "min-".concat(sizeProperty);
    var scrollbarWidth = scrollContainer[offsetSizeProperty] - scrollContainer[clientSizeProperty];
    var startSpacing = typeof spacing === 'object' ? spacing[startProperty] : spacing;
    var availableStartSpace = -Math.max(scrollContainerCollisions[overflowStartProperty], documentCollisions[overflowStartProperty] + document.documentElement[scrollProperty]) - startSpacing;
    var endSpacing = typeof spacing === 'object' ? spacing[endProperty] : spacing;
    var availableEndSpace = -Math.max(scrollContainerCollisions[overflowEndProperty], documentCollisions[overflowEndProperty] - document.documentElement[scrollProperty]) -
        endSpacing -
        scrollbarWidth;
    if (secondary) {
        availableStartSpace += parent[clientSizeProperty];
        availableEndSpace += parent[clientSizeProperty];
    }
    var offsetSize = element[offsetSizeProperty];
    function displayStart() {
        element.style[startProperty] = 'auto';
        element.style[endProperty] = secondary ? '0' : '100%';
    }
    function displayEnd() {
        element.style[startProperty] = secondary ? '0' : '100%';
        element.style[endProperty] = 'auto';
    }
    function displayIfFits(availableSpace, display) {
        var fits = offsetSize <= availableSpace;
        if (fits) {
            display();
        }
        return fits;
    }
    function displayStartIfFits() {
        return displayIfFits(availableStartSpace, displayStart);
    }
    function displayEndIfFits() {
        return displayIfFits(availableEndSpace, displayEnd);
    }
    function displayWhereverShrinkedFits() {
        var moreSpaceStart = availableStartSpace > availableEndSpace;
        var rawMinSize = style.getPropertyValue(minSizeProperty);
        var minSize = rawMinSize ? parseInt(rawMinSize, 10) : null;
        function shrinkToSize(size) {
            (0, warning_1.default)(!minSize || size >= minSize, "<Fit />'s child will not fit anywhere with its current ".concat(minSizeProperty, " of ").concat(minSize, "px."));
            var newSize = Math.max(size, minSize || 0);
            (0, warning_1.default)(false, "<Fit />'s child needed to have its ".concat(sizeProperty, " decreased to ").concat(newSize, "px."));
            element.style[sizeProperty] = "".concat(newSize, "px");
        }
        if (moreSpaceStart) {
            shrinkToSize(availableStartSpace);
            displayStart();
        }
        else {
            shrinkToSize(availableEndSpace);
            displayEnd();
        }
    }
    var fits;
    if (invertAxis) {
        fits = displayStartIfFits() || displayEndIfFits();
    }
    else {
        fits = displayEndIfFits() || displayStartIfFits();
    }
    if (!fits) {
        displayWhereverShrinkedFits();
    }
}
function alignMainAxis(args) {
    alignAxis(args);
}
function alignSecondaryAxis(args) {
    alignAxis(__assign(__assign({}, args), { axis: args.axis === 'x' ? 'y' : 'x', secondary: true }));
}
function alignBothAxis(args) {
    var invertAxis = args.invertAxis, invertSecondaryAxis = args.invertSecondaryAxis, commonArgs = __rest(args, ["invertAxis", "invertSecondaryAxis"]);
    alignMainAxis(__assign(__assign({}, commonArgs), { invertAxis: invertAxis }));
    alignSecondaryAxis(__assign(__assign({}, commonArgs), { invertAxis: invertSecondaryAxis }));
}
function Fit(_a) {
    var children = _a.children, invertAxis = _a.invertAxis, invertSecondaryAxis = _a.invertSecondaryAxis, _b = _a.mainAxis, mainAxis = _b === void 0 ? 'y' : _b, _c = _a.spacing, spacing = _c === void 0 ? 8 : _c;
    var container = (0, react_1.useRef)(undefined);
    var element = (0, react_1.useRef)(undefined);
    var elementWidth = (0, react_1.useRef)(undefined);
    var elementHeight = (0, react_1.useRef)(undefined);
    var scrollContainer = (0, react_1.useRef)(undefined);
    var fit = (0, react_1.useCallback)(function () {
        if (!scrollContainer.current || !container.current || !element.current) {
            return;
        }
        var currentElementWidth = element.current.clientWidth;
        var currentElementHeight = element.current.clientHeight;
        // No need to recalculate - already did that for current dimensions
        if (elementWidth.current === currentElementWidth &&
            elementHeight.current === currentElementHeight) {
            return;
        }
        // Save the dimensions so that we know we don't need to repeat the function if unchanged
        elementWidth.current = currentElementWidth;
        elementHeight.current = currentElementHeight;
        var parent = container.current.parentElement;
        // Container was unmounted
        if (!parent) {
            return;
        }
        /**
         * We need to ensure that <Fit />'s child has a absolute position. Otherwise,
         * we wouldn't be able to place the child in the correct position.
         */
        var style = window.getComputedStyle(element.current);
        var position = style.position;
        if (position !== 'absolute') {
            element.current.style.position = 'absolute';
        }
        /**
         * We need to ensure that <Fit />'s parent has a relative or absolute position. Otherwise,
         * we wouldn't be able to place the child in the correct position.
         */
        var parentStyle = window.getComputedStyle(parent);
        var parentPosition = parentStyle.position;
        if (parentPosition !== 'relative' && parentPosition !== 'absolute') {
            parent.style.position = 'relative';
        }
        alignBothAxis({
            axis: mainAxis,
            container: container.current,
            element: element.current,
            invertAxis: invertAxis,
            invertSecondaryAxis: invertSecondaryAxis,
            scrollContainer: scrollContainer.current,
            spacing: spacing,
        });
    }, [invertAxis, invertSecondaryAxis, mainAxis, spacing]);
    var child = react_1.Children.only(children);
    (0, react_1.useEffect)(function () {
        fit();
        function onMutation() {
            fit();
        }
        if (isMutationObserverSupported && element.current) {
            var mutationObserver = new MutationObserver(onMutation);
            mutationObserver.observe(element.current, {
                attributes: true,
                attributeFilter: ['class', 'style'],
            });
        }
    }, [fit]);
    function assignRefs(domElement) {
        if (!domElement || !(domElement instanceof HTMLElement)) {
            return;
        }
        element.current = domElement;
        scrollContainer.current = findScrollContainer(domElement);
    }
    return ((0, jsx_runtime_1.jsx)("span", { ref: function (domContainer) {
            if (!domContainer) {
                return;
            }
            container.current = domContainer;
            var domElement = domContainer === null || domContainer === void 0 ? void 0 : domContainer.firstElementChild;
            assignRefs(domElement);
        }, style: { display: 'contents' }, children: child }));
}
exports.default = Fit;
