/**
 * amis-ui v6.14.0-beta.1
 * Copyright 2018-2025 fex
 */

'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var tslib = require('tslib');
var React = require('react');
var ReactDOM = require('react-dom');
var amisCore = require('amis-core');
var Transition = require('react-transition-group/Transition');
var icons = require('./icons.js');
var mobxStateTree = require('mobx-state-tree');
var mobx = require('mobx');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
var Transition__default = /*#__PURE__*/_interopDefaultLegacy(Transition);

var __react_jsx__ = require('react');
var _J$X_ = (__react_jsx__["default"] || __react_jsx__).createElement;
(__react_jsx__["default"] || __react_jsx__).Fragment;
var _a;
var fadeStyles = (_a = {},
    _a[Transition.ENTERED] = 'in',
    _a[Transition.ENTERING] = 'in',
    _a);
var SpinnerSharedStore = mobxStateTree.types
    .model('SpinnerSharedStore', {})
    .volatile(function (self) {
    return {
        // 保存所有可以进入 loading 状态（props.show = true）的 Spinner 的父级容器
        spinningContainers: mobx.observable.set([], {
            deep: false
        })
    };
})
    .actions(function (self) {
    return {
        push: function (spinnerContainer) {
            if (self.spinningContainers.has(spinnerContainer)) {
                return;
            }
            self.spinningContainers.add(spinnerContainer);
        },
        remove: function (spinnerContainer) {
            if (self.spinningContainers.has(spinnerContainer)) {
                self.spinningContainers.delete(spinnerContainer);
            }
        },
        /**
         *  判断当前 Spinner 是否可以进入 loading 状态
         * @param spinnerContainerWillCheck 待检查的 Spinner 父容器
         * @returns {boolean} 是否可以进入 loading
         */
        checkLoading: function (spinnerContainerWillCheck) {
            if (self.spinningContainers.has(spinnerContainerWillCheck)) {
                if (!self.spinningContainers.size) {
                    return false;
                }
                var loading_1 = true;
                // 检查缓存的容器中是否有当前容器的父级元素
                self.spinningContainers.forEach(function (container) {
                    if (container.contains(spinnerContainerWillCheck) &&
                        container !== spinnerContainerWillCheck) {
                        loading_1 = false;
                    }
                });
                return loading_1;
            }
            return false;
        }
    };
});
var store = SpinnerSharedStore.create({});
var Spinner = /** @class */ (function (_super) {
    tslib.__extends(Spinner, _super);
    function Spinner() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            spinning: false,
            showMarker: true,
            idDarkBg: false
        };
        _this.parent = null;
        /**
         * 解决同级（same parent node） spinner 的 show 不全为 true 时
         * 标记 loading 是由当前组件触发的
         */
        _this.loadingTriggered = false;
        _this.spinnerRef = function (dom) {
            if (dom) {
                _this.parent = dom.parentNode;
            }
        };
        /**
         * 监控着 spinningContainers 的变化
         */
        _this.loadingChecker = mobx.reaction(function () { return store.spinningContainers.size; }, function () {
            if (_this.parent) {
                _this.setState({
                    spinning: store.checkLoading(_this.parent) && _this.loadingTriggered
                });
            }
        });
        return _this;
    }
    Spinner.prototype.componentDidUpdate = function () {
        var _a, _b;
        var showLoading = ((_a = this.props.loadingConfig) === null || _a === void 0 ? void 0 : _a.show) === true ||
            typeof ((_b = this.props.loadingConfig) === null || _b === void 0 ? void 0 : _b.show) === 'undefined';
        if (this.parent && showLoading) {
            if (this.props.show) {
                this.loadingTriggered = true;
                store.push(this.parent);
            }
            else if (this.state.spinning && this.loadingTriggered) {
                this.loadingTriggered = false;
                store.remove(this.parent);
            }
        }
    };
    Spinner.prototype.componentDidMount = function () {
        var _a, _b;
        if (this.parent && this.state.showMarker) {
            this.setState({ showMarker: false });
        }
        if (this.parent) {
            var backgroundColor = getComputedStyle(this.parent).getPropertyValue('background-color');
            var rgba = ((_a = backgroundColor.match(/\d+/g)) === null || _a === void 0 ? void 0 : _a.map(Number)) || [];
            var brightness = (rgba[0] * 299 + rgba[1] * 587 + rgba[2] * 114) / 1000;
            rgba[3] = (_b = rgba[3]) !== null && _b !== void 0 ? _b : 1; // 没有设置颜色时取到的是 rgba(0, 0, 0, 0)
            if (brightness < 200 && rgba[3] > 0.4) {
                this.setState({ idDarkBg: true });
            }
        }
    };
    Spinner.prototype.componentWillUnmount = function () {
        // 卸载 reaction
        this.loadingChecker();
        // 删除 当前 parent 元素
        store.remove(this.parent);
    };
    Spinner.prototype.renderBody = function () {
        var _this = this;
        var _a = this.props, cx = _a.classnames, className = _a.className, spinnerClassName = _a.spinnerClassName, _b = _a.size, size = _b === void 0 ? '' : _b, overlay = _a.overlay, delay = _a.delay, iconConfig = _a.icon, tip = _a.tip, _c = _a.tipPlacement, tipPlacement = _c === void 0 ? '' : _c, loadingConfig = _a.loadingConfig, disabled = _a.disabled;
        // 定义了挂载位置时只能使用默认icon
        var icon = (loadingConfig === null || loadingConfig === void 0 ? void 0 : loadingConfig.root) ? undefined : iconConfig;
        var isCustomIcon = icon && React__default["default"].isValidElement(icon);
        var timeout = { enter: delay, exit: 0 };
        var showOverlay = (loadingConfig === null || loadingConfig === void 0 ? void 0 : loadingConfig.root) || overlay;
        return (_J$X_(React__default["default"].Fragment, null,
            this.state.showMarker && (_J$X_("span", { className: cx('Spinner-mark'), ref: this.spinnerRef })),
            _J$X_(Transition__default["default"], { mountOnEnter: true, unmountOnExit: true, in: this.state.spinning, timeout: timeout }, function (status) {
                var _a, _b, _c;
                return (_J$X_(React__default["default"].Fragment, null,
                    showOverlay ? (_J$X_("div", { className: cx("Spinner-overlay", fadeStyles[status]) })) : null,
                    _J$X_("div", { "data-testid": "spinner", className: cx("Spinner", tip && (_a = {},
                            _a["Spinner-tip--".concat(tipPlacement)] = [
                                'top',
                                'right',
                                'bottom',
                                'left'
                            ].includes(tipPlacement),
                            _a), (_b = {}, _b["Spinner--overlay"] = showOverlay, _b), fadeStyles[status], className) },
                        _J$X_("div", { className: cx("Spinner-icon", (_c = {},
                                _c["Spinner-icon--".concat(size)] = ['lg', 'sm'].includes(size),
                                _c['Spinner-icon--default'] = !icon,
                                _c['Spinner-icon--simple'] = !isCustomIcon && icon,
                                _c['Spinner-icon--custom'] = isCustomIcon,
                                _c['Spinner-icon--disabled'] = disabled,
                                _c), spinnerClassName, _this.state.idDarkBg && 'Spinner-icon--darkBg') }, icon ? (_J$X_(icons.Icon, { cx: cx, icon: icon, className: "icon" })) : null),
                        tip ? _J$X_("span", { className: cx("Spinner-tip") }, tip) : '')));
            })));
    };
    Spinner.prototype.render = function () {
        var loadingConfig = this.props.loadingConfig;
        var spinnerBody = this.renderBody();
        var root = loadingConfig === null || loadingConfig === void 0 ? void 0 : loadingConfig.root;
        var dom = root ? document.querySelector(root) : null;
        if (dom) {
            // TODO: 找到准确的 元素
            return ReactDOM__default["default"].createPortal(spinnerBody, dom);
        }
        return spinnerBody;
    };
    Spinner.defaultProps = {
        show: true,
        className: '',
        spinnerClassName: '',
        size: '',
        icon: '',
        tip: '',
        tipPlacement: 'bottom',
        delay: 0,
        overlay: false,
        loadingConfig: {},
        disabled: false
    };
    return Spinner;
}(React__default["default"].Component));
var Spinner$1 = amisCore.themeable(Spinner);

exports.Spinner = Spinner;
exports["default"] = Spinner$1;
