"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;exports.__esModule = true;exports.LoaderDataTids = exports.Loader = void 0;var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));var _react = _interopRequireDefault(require("react"));
var _lodash = _interopRequireDefault(require("lodash.debounce"));
var _globalObject = require("@skbkontur/global-object");


var LayoutEvents = _interopRequireWildcard(require("../../lib/LayoutEvents"));

var _Spinner = require("../Spinner");

var _ThemeContext = require("../../lib/theming/ThemeContext");

var _ZIndex = require("../../internal/ZIndex");

var _CommonWrapper = require("../../internal/CommonWrapper");
var _Emotion = require("../../lib/theming/Emotion");
var _currentEnvironment = require("../../lib/currentEnvironment");
var _taskWithDelayAndMinimalDuration = require("../../lib/taskWithDelayAndMinimalDuration");
var _tabbableHelpers = require("../../lib/dom/tabbableHelpers");

var _rootNode = require("../../lib/rootNode");
var _getDOMRect2 = require("../../lib/dom/getDOMRect");
var _createPropsGetter = require("../../lib/createPropsGetter");

var _Loader2 = require("./Loader.styles");var _class, _Loader;

var types = ['mini', 'normal', 'big'];







































var LoaderDataTids = exports.LoaderDataTids = {
  idle: 'Loader__Idle',
  veil: 'Loader__Veil',
  spinner: 'Loader__Spinner'
};





/**
 * Компонент `Loader` принимает внутрь себя контент, поверх которого в активном состоянии `Loader`'а будет отрисован спиннер.
 *
 * Если вам нужен только сам спиннер без дополнительного функционала - используйте компонент Spinner.
 */var

Loader = exports.Loader = (0, _rootNode.rootNode)(_class = (_Loader = /*#__PURE__*/function (_React$Component) {






















  function Loader(props) {var _this;
    _this = _React$Component.call(this, props) || this;_this.getProps = (0, _createPropsGetter.createPropsGetter)(Loader.defaultProps);_this.



































































































































    childrenRef = function (element) {
      _this.childrenContainerNode = element;
    };_this.

    spinnerRef = function (element) {
      _this.spinnerContainerNode = element;
    };_this.




















    checkSpinnerPosition = function () {
      if (!_this.spinnerContainerNode || !(0, _globalObject.isBrowser)(_globalObject.globalObject)) {
        return;
      }

      var _getDOMRect =






        (0, _getDOMRect2.getDOMRect)(_this.spinnerContainerNode),containerTop = _getDOMRect.top,containerRight = _getDOMRect.right,containerBottom = _getDOMRect.bottom,containerLeft = _getDOMRect.left,containerHeight = _getDOMRect.height,containerWidth = _getDOMRect.width;

      var windowHeight = _globalObject.globalObject.innerHeight;
      var windowWidth = _globalObject.globalObject.innerWidth;

      // Если контейнер не больше высоты и не шире окна,
      // то просто выравниваем по центру
      if (windowHeight >= containerHeight && windowWidth >= containerWidth) {
        _this.setState({
          isStickySpinner: false,
          spinnerStyle: {}
        });
        return;
      }

      var spinnerStyle =




      {
        top: 30,
        right: 0,
        bottom: 30,
        left: 0
      };

      // ПО ВЕРТИКАЛИ
      // Если верхний край контейнера ниже верхнего края окна,
      // то сдвигаем и лоадер
      if (containerTop > 0) {
        spinnerStyle.top = containerTop + 30;
      }

      // Если нижний край контейнера выше нижнего края окна,
      // то сдвигаем и лоадер
      if (containerBottom < windowHeight) {
        spinnerStyle.bottom = Math.abs(windowHeight - containerBottom) + 30;
      }

      // Если знаем высоту спиннера и нижний край контейнера поднимается
      // выше отступа на высоту спиннера, то убираем верхнюю позицию лоадера

      var spinnerHeight = (0, _getDOMRect2.getDOMRect)(_this.spinnerNode).height;

      if (spinnerHeight && spinnerStyle.bottom >= windowHeight - spinnerHeight) {
        delete spinnerStyle.top;
      }

      // ПО ГОРИЗОНТАЛИ
      // Если левый край контейнера правее левого края окна,
      // то сдвигаем и лоадер
      if (containerLeft > 0) {
        spinnerStyle.left = containerLeft;
      }

      // Если правый край контейнера левее правого края окна,
      // то сдвигаем и лоадер
      if (containerRight < windowWidth) {
        spinnerStyle.right = windowWidth - containerRight;
      }

      _this.setState({
        isStickySpinner: true,
        spinnerStyle: spinnerStyle
      });
    };_this.

    disableChildrenFocus = function () {
      if (!_this.childrenObserver) {
        _this.makeObservable();
      }
      var tabbableElements = (0, _tabbableHelpers.getTabbableElements)(_this.childrenContainerNode);
      tabbableElements.forEach(function (el) {
        if (!el.hasAttribute('origin-tabindex')) {
          el.setAttribute('origin-tabindex', el.tabIndex.toString());
        }
        el.tabIndex = -1;
      });
    };_this.

    enableChildrenFocus = function () {var _globalObject$documen, _globalObject$documen2;
      _this.makeUnobservable();
      // NOTE: NodeList doesn't support 'forEach' method in IE11 and other older browsers
      Array.from((_globalObject$documen = (_globalObject$documen2 = _globalObject.globalObject.document) == null ? void 0 : _globalObject$documen2.querySelectorAll('[origin-tabindex]')) != null ? _globalObject$documen : []).forEach(function (el) {var _el$getAttribute;
        el.setAttribute('tabindex', (_el$getAttribute = el.getAttribute('origin-tabindex')) != null ? _el$getAttribute : '0');
        el.removeAttribute('origin-tabindex');
      });
    };_this.

    makeObservable = function () {
      var target = _this.childrenContainerNode;
      if (!target || !_globalObject.globalObject.MutationObserver) {
        return;
      }
      var config = {
        childList: true,
        subtree: true
      };
      var observer = new _globalObject.globalObject.MutationObserver(_this.disableChildrenFocus);
      observer.observe(target, config);
      _this.childrenObserver = observer;
    };_this.

    makeUnobservable = function () {var _this$childrenObserve;
      (_this$childrenObserve = _this.childrenObserver) == null || _this$childrenObserve.disconnect();
      _this.childrenObserver = null;
    };_this.spinnerContainerNode = null;_this.childrenContainerNode = null;_this.childrenObserver = null;_this.spinnerNode = null;_this.state = { isStickySpinner: false, isSpinnerVisible: false, isLoaderActive: false };_this.spinnerTask = new _taskWithDelayAndMinimalDuration.TaskWithDelayAndMinimalDuration({ delayBeforeTaskStart: _this.getProps().delayBeforeSpinnerShow, durationOfTask: _this.getProps().minimalDelayBeforeSpinnerHide, taskStartCallback: function taskStartCallback() {return _this.setState({ isSpinnerVisible: true });}, taskStopCallback: function taskStopCallback() {return _this.setState({ isSpinnerVisible: false });} });return _this;}(0, _inheritsLoose2.default)(Loader, _React$Component);var _proto = Loader.prototype;_proto.componentDidMount = function componentDidMount() {var active = this.getProps().active;this.checkSpinnerPosition();active && this.spinnerTask.start();this.layoutEvents = LayoutEvents.addListener((0, _lodash.default)(this.checkSpinnerPosition, 10));if (active) {this.disableChildrenFocus();}};_proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {var component = this.props.component;var _this$getProps = this.getProps(),active = _this$getProps.active,delayBeforeSpinnerShow = _this$getProps.delayBeforeSpinnerShow,minimalDelayBeforeSpinnerHide = _this$getProps.minimalDelayBeforeSpinnerHide;var isLoaderActive = this.state.isLoaderActive;if (active && !prevProps.active || prevProps.component !== component) {this.checkSpinnerPosition();}if (delayBeforeSpinnerShow !== prevProps.delayBeforeSpinnerShow || minimalDelayBeforeSpinnerHide !== prevProps.minimalDelayBeforeSpinnerHide) {this.spinnerTask.update({ delayBeforeTaskStart: delayBeforeSpinnerShow, durationOfTask: minimalDelayBeforeSpinnerHide });}if (active !== prevProps.active) {active ? this.spinnerTask.start() : this.spinnerTask.stop();}if (isLoaderActive !== prevState.isLoaderActive) {if (isLoaderActive) {this.disableChildrenFocus();} else {this.enableChildrenFocus();}}};_proto.componentWillUnmount = function componentWillUnmount() {this.makeUnobservable();if (this.layoutEvents) {this.layoutEvents.remove();}this.spinnerTask.clearTask();};Loader.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) {if (props.active && !state.isLoaderActive) {return { isLoaderActive: true };}if (state.isLoaderActive && !(props.active || state.isSpinnerVisible)) {return { isLoaderActive: false };}return state;};_proto.render = function render() {var _this2 = this;return /*#__PURE__*/_react.default.createElement(_ThemeContext.ThemeContext.Consumer, null, function (theme) {_this2.theme = theme;return _this2.renderMain();});};_proto.renderMain = function renderMain() {var _cx;var _this$props = this.props,caption = _this$props.caption,component = _this$props.component;var type = this.getProps().type;var isLoaderActive = this.state.isLoaderActive;return /*#__PURE__*/_react.default.createElement(_CommonWrapper.CommonWrapper, (0, _extends2.default)({ rootNodeRef: this.setRootNode }, this.props), /*#__PURE__*/_react.default.createElement("div", { className: _Loader2.styles.loader(), "data-tid": this.props['data-tid'] || (isLoaderActive ? LoaderDataTids.veil : LoaderDataTids.idle) }, /*#__PURE__*/_react.default.createElement(_ZIndex.ZIndex, { applyZIndex: isLoaderActive, coverChildren: isLoaderActive, style: { height: '100%' }, wrapperRef: this.childrenRef }, this.props.children), isLoaderActive && /*#__PURE__*/_react.default.createElement(_ZIndex.ZIndex, { wrapperRef: this.spinnerRef, className: (0, _Emotion.cx)((_cx = {}, _cx[_Loader2.styles.active(this.theme)] = isLoaderActive, _cx)) }, this.state.isSpinnerVisible && this.renderSpinner(type, caption, component))));};_proto.renderSpinner = function renderSpinner(type, caption, component) {var _cx2,_this3 = this;return /*#__PURE__*/_react.default.createElement("span", { "data-tid": LoaderDataTids.spinner, className: (0, _Emotion.cx)(_Loader2.styles.spinnerContainer(), (_cx2 = {}, _cx2[_Loader2.styles.spinnerContainerSticky()] = this.state.isStickySpinner, _cx2)), style: this.state.spinnerStyle }, /*#__PURE__*/_react.default.createElement("div", { className: _Loader2.styles.spinnerComponentWrapper(), ref: function ref(element) {_this3.spinnerNode = element;} }, component !== undefined ? component : /*#__PURE__*/_react.default.createElement(_Spinner.Spinner, { type: type, caption: caption })));};return Loader;}(_react.default.Component), _Loader.__KONTUR_REACT_UI__ = 'Loader', _Loader.displayName = 'Loader', _Loader.defaultProps = { type: 'normal', active: false, delayBeforeSpinnerShow: _currentEnvironment.isTestEnv ? 0 : 300, minimalDelayBeforeSpinnerHide: _currentEnvironment.isTestEnv ? 0 : 1000 }, _Loader)) || _class;