"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DrawerContentSelector = exports.Drawer = void 0;
const react_1 = __importStar(require("react"));
const react_dom_1 = require("react-dom");
const use_forwarded_ref_1 = require("@bedrock-layout/use-forwarded-ref");
const oop_timers_1 = require("oop-timers");
const HandleEsc_1 = require("../../utils/HandleEsc");
const Drawer_styled_1 = require("./Drawer.styled");
const RENDER_TIMEOUT = 500;
const TRANSITION_MS = 300;
const DEFAULT_CONTENT_SCALE = 0.92;
const DEFAULT_TINT_OPACITY = 0.1;
const PARTIAL_RADIUS = "16px";
const DEFAULT_SCALE_SELECTORS = ["#__next", "#root", "#storybook-root", "body>*:first-child"];
const closedTransform = {
    bottom: "translate(0, 100%)",
    top: "translate(0, -100%)",
    left: "translate(-100%, 0)",
    right: "translate(100%, 0)",
};
const getSizeCss = (size) => {
    if (size === undefined) {
        return undefined;
    }
    if (typeof size === "string") {
        return size;
    }
    if (size >= 0) {
        return `${size}px`;
    }
    return `calc(100% + ${size}px)`;
};
const positioningPresets = {
    bottom: (size) => ({ top: "auto", height: size }),
    top: (size) => ({ bottom: "auto", height: size }),
    left: (size) => ({ right: "auto", width: size }),
    right: (size) => ({ left: "auto", width: size }),
};
const radiusPresets = {
    bottom: { borderTopLeftRadius: PARTIAL_RADIUS, borderTopRightRadius: PARTIAL_RADIUS },
    top: { borderBottomLeftRadius: PARTIAL_RADIUS, borderBottomRightRadius: PARTIAL_RADIUS },
    left: { borderTopRightRadius: PARTIAL_RADIUS, borderBottomRightRadius: PARTIAL_RADIUS },
    right: { borderTopLeftRadius: PARTIAL_RADIUS, borderBottomLeftRadius: PARTIAL_RADIUS },
};
const getStaticStyle = (from, size) => {
    const sizeCss = getSizeCss(size);
    if (sizeCss === undefined) {
        return {};
    }
    return Object.assign(Object.assign({}, positioningPresets[from](sizeCss)), radiusPresets[from]);
};
const findScaleTargets = (selectors, mode) => {
    for (const sel of selectors) {
        if (mode === "first") {
            const el = document.querySelector(sel);
            if (el) {
                return [el];
            }
        }
        else {
            const els = Array.from(document.querySelectorAll(sel));
            if (els.length > 0) {
                return els;
            }
        }
    }
    return [];
};
const applyScale = (target, transform) => {
    target.style.setProperty("transition", `transform ${TRANSITION_MS}ms`);
    target.style.setProperty("transform-origin", "50% 0");
    target.style.setProperty("transform", transform);
};
const Drawer = (0, react_1.forwardRef)((props, ref) => {
    var _a, _b, _c;
    const drawerRef = (0, use_forwarded_ref_1.useForwardedRef)(ref);
    const [shouldRenderWhenClosed, setShouldRenderWhenClosed] = (0, react_1.useState)(false);
    const [isVisible, setIsVisible] = (0, react_1.useState)(props.isOpen);
    const timeoutRef = (0, react_1.useRef)(null);
    (0, react_1.useEffect)(() => {
        timeoutRef.current = new oop_timers_1.Timeout(() => {
            setShouldRenderWhenClosed(false);
        }, RENDER_TIMEOUT);
        return () => {
            var _a;
            (_a = timeoutRef.current) === null || _a === void 0 ? void 0 : _a.stop();
            timeoutRef.current = null;
        };
    }, []);
    (0, react_1.useEffect)(() => {
        var _a, _b;
        if (!props.isOpen) {
            (_a = timeoutRef.current) === null || _a === void 0 ? void 0 : _a.start();
            setIsVisible(false);
            return undefined;
        }
        (_b = timeoutRef.current) === null || _b === void 0 ? void 0 : _b.stop();
        setShouldRenderWhenClosed(true);
        const id = requestAnimationFrame(() => {
            setIsVisible(true);
        });
        return () => {
            cancelAnimationFrame(id);
        };
    }, [props.isOpen]);
    const { scaleContent, scaleSelectors, scaleSelectorsMode } = props;
    (0, react_1.useEffect)(() => {
        if (!scaleContent || !props.isOpen) {
            return undefined;
        }
        const selectors = scaleSelectors === undefined
            ? DEFAULT_SCALE_SELECTORS
            : (Array.isArray(scaleSelectors) ? scaleSelectors : [scaleSelectors]);
        const mode = scaleSelectorsMode !== null && scaleSelectorsMode !== void 0 ? scaleSelectorsMode : "first";
        const targets = findScaleTargets(selectors, mode);
        if (targets.length === 0) {
            return undefined;
        }
        const scale = typeof scaleContent === "number" ? scaleContent : DEFAULT_CONTENT_SCALE;
        targets.forEach((el) => {
            applyScale(el, `scale(${scale})`);
        });
        return () => {
            targets.forEach((el) => {
                applyScale(el, "");
            });
        };
    }, [props.isOpen, scaleContent, scaleSelectors, scaleSelectorsMode]);
    const from = (_a = props.from) !== null && _a !== void 0 ? _a : "bottom";
    const style = Object.assign(Object.assign({}, getStaticStyle(from, props.size)), { transform: isVisible ? "translate(0, 0)" : closedTransform[from], transition: props.isOpen && !isVisible ? "none" : undefined });
    const shouldRender = props.isOpen || shouldRenderWhenClosed;
    const closeOnEsc = (_b = props.closeOnEsc) !== null && _b !== void 0 ? _b : true;
    const esc = closeOnEsc && react_1.default.createElement(HandleEsc_1.HandleEsc, { onPress: props.onClose });
    const portal = (_c = props.portal) !== null && _c !== void 0 ? _c : true;
    const overlayClick = props.onOverlayClick === undefined ? "close" : props.onOverlayClick;
    const { onClose } = props;
    const handleOverlayClick = (0, react_1.useCallback)(() => {
        if (overlayClick === "close") {
            onClose();
            return;
        }
        if (typeof overlayClick === "function") {
            overlayClick();
        }
    }, [overlayClick, onClose]);
    const hasOverlay = props.size !== undefined || Boolean(scaleContent);
    const overlayInteractive = overlayClick !== null && props.isOpen;
    const tintStyle = {
        opacity: isVisible ? DEFAULT_TINT_OPACITY : 0,
        pointerEvents: (overlayInteractive ? "auto" : "none"),
    };
    const tree = (react_1.default.createElement(react_1.default.Fragment, null,
        hasOverlay && (react_1.default.createElement(Drawer_styled_1.Tint, { style: tintStyle, onClick: handleOverlayClick, "aria-hidden": true })),
        react_1.default.createElement(Drawer_styled_1.StyledDrawer, { className: props.className, style: style, ref: drawerRef },
            esc,
            react_1.default.createElement(Drawer_styled_1.Content, null, shouldRender && props.children))));
    if (portal) {
        const root = typeof portal === "boolean" ? document.body : portal;
        return (0, react_dom_1.createPortal)(tree, root);
    }
    return tree;
});
exports.Drawer = Drawer;
Drawer.displayName = "Drawer";
Drawer.toString = () => Drawer_styled_1.StyledDrawer.toString();
const DrawerContentSelector = Drawer_styled_1.Content.toString();
exports.DrawerContentSelector = DrawerContentSelector;
//# sourceMappingURL=Drawer.js.map