"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _constants = require("../../constants");
var _ButtonGroup = _interopRequireDefault(require("../ButtonGroup"));
var _Button = _interopRequireDefault(require("../Button"));
var _Dropdown = _interopRequireDefault(require("../Dropdown"));
var _Menu = _interopRequireWildcard(require("../Menu"));
var _Squeezer = _interopRequireDefault(require("../Squeezer"));
var _ResponsiveContext = _interopRequireDefault(require("../ResponsiveContext"));
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

const alphaSort = (a, b) => a > b ? 1 : -1;

/**
 *  `Segmented Control` is a group of several [Buttons](#!/Button)
 * each of which functions as a mutually exclusive option.
 * @since 0.0.68
 */
class SegmentedControl extends _react.Component {
  constructor() {
    super(...arguments);
    (0, _defineProperty2.default)(this, "state", {
      selected: this.props.selected,
      monoWidth: 0
    });
    (0, _defineProperty2.default)(this, "isCompact", false);
    (0, _defineProperty2.default)(this, "rootRef", /*#__PURE__*/(0, _react.createRef)());
    (0, _defineProperty2.default)(this, "adjustMonospaced", () => {
      const {
        baseClassName,
        monospaced
      } = this.props;
      if (monospaced) {
        let monoWidth = 0;
        this.rootRef.current.querySelectorAll(`.${baseClassName}__button`).forEach(el => {
          monoWidth = Math.max(monoWidth, el.getBoundingClientRect().width);
        });
        if (monoWidth !== this.state.monoWidth) {
          this.setState({
            monoWidth
          });
        }
      }
    });
    (0, _defineProperty2.default)(this, "handleChange", value => () => {
      const {
        multiple,
        onChange
      } = this.props;
      const {
        selected
      } = this.state;
      let newSelected;
      if (multiple) {
        newSelected = selected ? selected.slice() : [];
        if (!selected || !(selected instanceof Array) || selected.indexOf(value) === -1) {
          newSelected.push(value);
        } else {
          newSelected.splice(selected.indexOf(value), 1);
        }
        newSelected.sort(alphaSort);
      } else {
        newSelected = value;
      }
      if (selected instanceof Array) {
        selected.sort(alphaSort);
      }
      if (JSON.stringify(newSelected) !== JSON.stringify(selected)) {
        this.setState({
          selected: newSelected
        });
        onChange(newSelected);
      }
    });
    (0, _defineProperty2.default)(this, "compact", () => {
      if (this.isCompact) {
        return false;
      }
      this.isCompact = true;
      this.forceUpdate();
      return true;
    });
    (0, _defineProperty2.default)(this, "uncompact", () => {
      if (!this.isCompact) {
        return false;
      }
      this.isCompact = false;
      this.forceUpdate();
      return true;
    });
  }
  static getDerivedStateFromProps(props, state) {
    const {
      selected,
      multiple
    } = props;
    const {
      prevSelected
    } = state;
    const nextState = {
      selected: state.selected
    };
    if (selected !== prevSelected) {
      nextState.selected = selected;
    }
    if (multiple && nextState.selected && !(nextState.selected instanceof Array)) {
      nextState.selected = [nextState.selected];
    }
    nextState.prevSelected = selected;
    return nextState;
  }
  componentDidMount() {
    this.adjustMonospaced();
  }
  componentDidUpdate() {
    this.adjustMonospaced();
  }
  isResponsive() {
    return this.context === undefined ? this.isCompact : this.context;
  }
  renderControl() {
    const {
      buttons,
      multiple
    } = this.props;
    const hasIcons = buttons.some(_ref => {
      let {
        icon
      } = _ref;
      return !!icon;
    });
    if (!hasIcons && !multiple && this.isResponsive()) {
      return this.renderDropdown();
    }
    return this.renderButtonGroup();
  }
  renderDropdown() {
    const {
      buttons,
      onChange
    } = this.props;
    const {
      selected
    } = this.state;
    const {
      title
    } = buttons.find(button => button.value === selected) || {};
    const menu = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Menu.default, {
      children: buttons.map(_ref2 => {
        let {
          title,
          value,
          ...buttonProps
        } = _ref2;
        const menuItemProps = {};
        if (onChange !== null) {
          menuItemProps.onClick = this.handleChange(value);
        }
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Menu.MenuItem, {
          ...buttonProps,
          ...menuItemProps,
          children: title
        }, value);
      })
    });
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default, {
      menu: menu,
      children: title
    });
  }
  renderButtonGroup() {
    const {
      buttons,
      monospaced,
      multiple,
      onChange,
      ghost,
      baseClassName
    } = this.props;
    const {
      selected,
      monoWidth
    } = this.state;
    const isCollapsed = this.state.compact;
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ButtonGroup.default, {
      className: `${baseClassName}__button-group`,
      children: buttons.map(_ref3 => {
        let {
          value,
          title,
          ...buttonProps
        } = _ref3;
        // uncontrolled
        const handler = {};
        if (onChange !== null) {
          handler.onClick = this.handleChange(value);
        }
        let buttonSelected = false;
        if (multiple && selected && selected instanceof Array && selected.indexOf(value) !== -1) {
          buttonSelected = true;
        } else if (!multiple && selected === value) {
          buttonSelected = true;
        }
        buttonProps.className = (0, _classnames.default)(buttonProps.className, `${baseClassName}__button`);
        if (!isCollapsed && monospaced && monoWidth) {
          buttonProps.style = {
            width: monoWidth,
            ...buttonProps.style
          };
        }
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
          selected: buttonSelected,
          ghost: ghost,
          ...handler,
          ...buttonProps,
          children: title
        }, value);
      })
    });
  }
  render() {
    const {
      label,
      labelPlacement,
      buttons,
      monospaced,
      multiple,
      selected: selectedProp,
      onChange,
      inline,
      ghost,
      className,
      baseClassName,
      ...props
    } = this.props;
    const isCollapsed = this.isResponsive();
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ResponsiveContext.default.Provider, {
      value: isCollapsed,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Squeezer.default, {
        compact: this.compact,
        uncompact: this.uncompact,
        innerRef: el => {
          this.rootRef.current = el;
        },
        children: _ref4 => {
          let {
            ref
          } = _ref4;
          return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
            ref: ref,
            className: (0, _classnames.default)(baseClassName, {
              [`${baseClassName}--inline`]: inline,
              [`${baseClassName}--collapsed`]: isCollapsed,
              [`${baseClassName}--vertical`]: label && labelPlacement === 'top'
            }, className),
            ...props,
            children: [label && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
              className: `${baseClassName}__label`,
              children: label
            }), this.renderControl()]
          });
        }
      })
    });
  }
}
SegmentedControl.propTypes = {
  /**
   * Label
   * @since 0.0.68
   */
  label: _propTypes.default.node,
  /**
   * Where to place label
   * @since 0.0.68
   */
  labelPlacement: _propTypes.default.oneOf(['top', 'left']),
  /**
   * Array of buttons to display (every array item must contain an unique "value" property)
   * @since 0.0.68
   */
  buttons: _propTypes.default.arrayOf(_propTypes.default.shape({
    value: _propTypes.default.any.isRequired,
    title: _propTypes.default.node
  })).isRequired,
  /**
   * Monospaced version of buttons (all button would have the same width).
   * Attention: using it with buttons dynamic update may cause to wrong behavior!
   * @since 0.0.68
   */
  monospaced: _propTypes.default.bool,
  /**
   * Multiple selected options version (any number of buttons can be selected)
   * @since 0.0.68
   */
  multiple: _propTypes.default.bool,
  /**
   * Selected value or an array of values (for multiple version).
   * Used in controlled version or as default value in uncontrolled version (with onChange property)
   * @since 0.0.68
   */
  selected: _propTypes.default.oneOfType([_propTypes.default.any, _propTypes.default.arrayOf(_propTypes.default.any)]).isRequired,
  /**
   * On change selection callback for uncontrolled mode.
   * @since 0.0.68
   */
  onChange: _propTypes.default.func,
  /**
   * Should component displays as inline element?
   * @since 0.0.68
   */
  inline: _propTypes.default.bool,
  /**
   * Use buttons with transparent background (ghost buttons)
   * @since 2.3.0
   */
  ghost: _propTypes.default.bool,
  /**
   * @ignore
   */
  className: _propTypes.default.string,
  /**
   * @ignore
   */
  baseClassName: _propTypes.default.string
};
SegmentedControl.defaultProps = {
  label: null,
  labelPlacement: 'top',
  monospaced: false,
  multiple: false,
  onChange: null,
  inline: false,
  ghost: false,
  className: null,
  baseClassName: `${_constants.CLS_PREFIX}segmented-control`
};
SegmentedControl.contextType = _ResponsiveContext.default;
var _default = exports.default = SegmentedControl;