import _defineProperty from "@babel/runtime/helpers/defineProperty";
// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

import React, { Component, Fragment, cloneElement, isValidElement, createRef } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { CSSTransition } from 'react-transition-group';
import memoize from 'memoize-one';
import Measure from 'react-measure';
import { CLS_PREFIX } from '../../constants';
import Checkbox from '../Checkbox';
import Icon from '../Icon';
import { safeInvoke, isClickable, scrollIntoView, wrapFunction } from '../utils';
import Button from '../Button';
import Translate from '../Translate';
import Text from '../Text';
import { ITEMS_PER_PAGE_OPTIONS } from '../Pagination';
import Spinner from '../Spinner';
import ListOperationContext from './ListOperationContext';
import VerticalContext, { VERTICAL_BREAKPOINT } from '../VerticalContext';
import ListEmptyView from './ListEmptyView';
import Columns, { Column } from '../Columns';
import { FocusVisibleManager, useFocusVisible } from 'use-focus-visible';
import { jsx as _jsx } from "react/jsx-runtime";
import { Fragment as _Fragment } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
import { createElement as _createElement } from "react";
const getRowKey = (row, props) => {
  const {
    rowKey
  } = props;
  if (typeof rowKey === 'function') {
    return rowKey(row);
  }
  return row[rowKey];
};
const Tbody = _ref => {
  let {
    baseClassName,
    className,
    ...props
  } = _ref;
  const {
    focusVisible,
    onFocus,
    onBlur
  } = useFocusVisible();
  return /*#__PURE__*/_jsx("tbody", {
    ...props,
    onFocus: wrapFunction(props.onFocus, onFocus),
    onBlur: wrapFunction(props.onBlur, onBlur),
    className: classNames(className, {
      [`${baseClassName}--focus-visible`]: focusVisible
    })
  });
};
Tbody.propTypes = {
  onFocus: PropTypes.func,
  onBlur: PropTypes.func,
  className: PropTypes.string,
  baseClassName: PropTypes.string
};
Tbody.defaultProps = {
  onFocus: undefined,
  onBlur: undefined,
  className: undefined,
  baseClassName: `${CLS_PREFIX}list__wrapper`
};
const getHumanTotalRows = _ref2 => {
  let {
    selectedRows,
    totalRows,
    allRowsSelected,
    translators
  } = _ref2;
  let mode;
  if (!allRowsSelected && selectedRows === 0) {
    mode = 'totalRows';
  } else if (allRowsSelected || selectedRows === totalRows) {
    mode = 'selectedAllRows';
  } else {
    mode = 'selectedRows';
  }
  const wrapToText = element => /*#__PURE__*/_jsx(Text, {
    fontSize: "sm",
    children: element
  });
  switch (mode) {
    case 'totalRows':
      return wrapToText( /*#__PURE__*/_jsx(Translate, {
        namespace: "List",
        content: "totalRows",
        fallback: "%%totalRows%% items total",
        params: {
          totalRows
        },
        translators: translators
      }));
    case 'selectedRows':
      return wrapToText( /*#__PURE__*/_jsx(Translate, {
        namespace: "List",
        content: "selectedRows",
        fallback: "%%selectedRows%% of %%totalRows%% items selected",
        params: {
          selectedRows: /*#__PURE__*/_jsx(Text, {
            bold: true,
            children: selectedRows
          }),
          totalRows
        },
        translators: translators
      }));
    case 'selectedAllRows':
      return wrapToText( /*#__PURE__*/_jsx(Translate, {
        namespace: "List",
        content: "selectedRows",
        fallback: "%%selectedRows%% of %%totalRows%% items selected",
        params: {
          selectedRows: /*#__PURE__*/_jsx(Text, {
            bold: true,
            children: /*#__PURE__*/_jsx(Translate, {
              namespace: "List",
              content: "all",
              fallback: "All",
              translators: translators
            })
          }),
          totalRows
        },
        translators: translators
      }));
    default:
      return null;
  }
};

/**
 * `List` component is used for displaying a collection of tabular data.
 * [More details about designing of lists.](#!/Sets%20of%20Objects)
 * @since 0.0.42
 */
class List extends Component {
  constructor() {
    super(...arguments);
    _defineProperty(this, "state", {
      sortInPlace: !this.props.pagination,
      vertical: false,
      expandedRows: this.props.expandedRows,
      prevExpandedRows: this.props.expandedRows,
      selection: this.props.selection,
      prevSelection: this.props.selection,
      ReorderableList: () => null,
      reorderableItemWidths: []
    });
    _defineProperty(this, "anchorRef", /*#__PURE__*/createRef());
    _defineProperty(this, "flatData", data => data.reduce((acc, _ref3) => {
      let {
        data,
        ...row
      } = _ref3;
      const {
        virtual
      } = this.getRowProps(row);
      if (virtual) {
        return [...acc, ...(data ? this.flatData(data) : [])];
      }
      return [...acc, row, ...(data ? this.flatData(data) : [])];
    }, []));
    _defineProperty(this, "handleRowSelectionChange", (checked, rowKey) => {
      const {
        onAllRowsSelectedChange
      } = this.props;
      let selection;
      if (checked) {
        selection = this.state.selection.slice();
        selection.push(rowKey);
      } else {
        selection = this.state.selection.filter(value => value !== rowKey);
        safeInvoke(onAllRowsSelectedChange, false);
      }
      this.setSelection(selection);
    });
    _defineProperty(this, "handleGlobalSelectionChange", headerChecked => {
      const {
        onAllRowsSelectedChange
      } = this.props;
      const {
        selection
      } = this.state;
      const nextSelection = [];
      this.flatData(this.props.data).forEach(row => {
        const key = getRowKey(row, this.props);
        if (row.disabled || this.isRowLoading(row)) {
          if (selection.indexOf(key) !== -1) {
            nextSelection.push(key);
          }
          return;
        }
        if (headerChecked) {
          nextSelection.push(key);
        }
      });
      if (!headerChecked) {
        safeInvoke(onAllRowsSelectedChange, false);
      }
      this.setSelection(nextSelection);
    });
    _defineProperty(this, "handleResize", _ref4 => {
      let {
        bounds
      } = _ref4;
      this.setState({
        vertical: bounds.width < this.props.vertical
      });
    });
    _defineProperty(this, "isRowLoading", row => this.props.loadingRows.indexOf(getRowKey(row, this.props)) !== -1);
    _defineProperty(this, "getRowTitle", row => {
      const {
        columns
      } = this.props;
      const column = columns.find(c => c.type === 'title');
      if (column && column.key) {
        return row[column.key];
      }
      return undefined;
    });
    _defineProperty(this, "getRowProps", row => {
      const {
        rowProps
      } = this.props;
      if (typeof rowProps === 'function') {
        return {
          ...rowProps(row)
        };
      }
      return {
        ...rowProps
      };
    });
    _defineProperty(this, "isAllRowsChecked", memoize((rows, selectedKeys) => {
      const filteredRows = this.flatData(rows).filter(row => !row.disabled);
      if (filteredRows.length > 0) {
        return filteredRows.every(row => {
          const key = getRowKey(row, this.props);
          return selectedKeys.indexOf(key) !== -1;
        });
      }
      return false;
    }));
    _defineProperty(this, "isAnyRowsExpanded", memoize((rows, expandedRows) => this.flatData(rows).some(row => {
      const key = getRowKey(row, this.props);
      return expandedRows.indexOf(key) !== -1;
    })));
    _defineProperty(this, "handleGlobalExpandingChange", () => {
      const {
        data
      } = this.props;
      const {
        expandedRows
      } = this.state;
      const headerExpanded = this.isAnyRowsExpanded(data, expandedRows);
      const nextExpandedRows = [];
      this.flatData(this.props.data).forEach(row => {
        const key = getRowKey(row, this.props);
        if (!this.isRowExpandable(row)) {
          if (expandedRows.indexOf(key) !== -1) {
            nextExpandedRows.push(key);
          }
          return;
        }
        if (!headerExpanded) {
          nextExpandedRows.push(key);
        }
      });
      this.setExpandedRows(nextExpandedRows);
    });
    _defineProperty(this, "createRowClickHandler", row => e => {
      if (isClickable(e)) {
        return;
      }
      if (this.isRowExpandable(row)) {
        this.handleRowExpandingChange(row);
      }
    });
  }
  static getDerivedStateFromProps(_ref5, _ref6) {
    let {
      sortColumn,
      sortDirection,
      selection,
      expandedRows,
      notExpandableRows,
      renderRowBody,
      data,
      pagination,
      vertical,
      rowKey,
      totalRows,
      filtered
    } = _ref5;
    let {
      prevSortColumn,
      prevSortDirection,
      prevData,
      prevSelection,
      prevPagination,
      prevExpandedRows,
      ...state
    } = _ref6;
    let nextState = {};
    if (prevSortColumn !== sortColumn || prevSortDirection !== sortDirection) {
      nextState = {
        ...nextState,
        sortColumn,
        sortDirection
      };
    }
    const additionalExpanded = [];
    if (prevData !== data) {
      const isSingleElementInCurrentExpanded = () => state.expandedRows.includes(getRowKey(data[0], {
        rowKey
      }));
      if (renderRowBody && data?.length === 1 && (!pagination || totalRows === 1) && (!prevData || prevData?.length === 0 || isSingleElementInCurrentExpanded()) && (!filtered || isSingleElementInCurrentExpanded())) {
        const key = getRowKey(data[0], {
          rowKey
        });
        if (notExpandableRows.indexOf(key) === -1) {
          additionalExpanded.push(key);
        }
      }
      const keys = data.map(row => getRowKey(row, {
        rowKey
      }));
      const nextSelection = state.selection.filter(key => keys.indexOf(key) !== -1);
      nextState = {
        ...nextState,
        selection: nextSelection
      };
    }
    if (prevSelection !== selection) {
      nextState = {
        ...nextState,
        selection
      };
    }
    if (prevExpandedRows !== expandedRows || additionalExpanded.length) {
      nextState = {
        ...nextState,
        expandedRows: [...expandedRows, ...additionalExpanded]
      };
    }
    if (prevPagination !== pagination) {
      nextState = {
        ...nextState,
        sortInPlace: !pagination
      };
    }
    if (typeof vertical === 'boolean') {
      nextState.vertical = vertical;
    }
    nextState.prevSortColumn = sortColumn;
    nextState.prevSortDirection = sortDirection;
    nextState.prevData = data;
    nextState.prevSelection = selection;
    nextState.prevPagination = pagination;
    nextState.prevExpandedRows = expandedRows;
    return nextState;
  }
  componentDidMount() {
    if (this.props.reorderable) {
      this.applyReorderableList();
    }
  }
  componentDidUpdate(prevProps) {
    const {
      data
    } = this.props;
    const {
      data: prevData
    } = prevProps;
    if (data !== prevData && this.needScroll && this.anchorRef.current) {
      scrollIntoView(this.anchorRef.current, {
        scrollMode: 'if-needed'
      });
      this.needScroll = false;
    }
    if (prevProps.reorderable !== this.props.reorderable && this.props.reorderable) {
      this.applyReorderableList();
    }
  }
  applyReorderableList() {
    import( /* webpackChunkName: "react-movable" */'@plesk/react-movable').then(_ref7 => {
      let {
        List: ReorderableList
      } = _ref7;
      this.setState({
        ReorderableList
      });
    });
  }
  getData() {
    const {
      sortInPlace,
      sortColumn,
      sortDirection
    } = this.state;
    const {
      data,
      columns
    } = this.props;
    if (!sortInPlace) {
      return data;
    }
    const [column] = columns.filter(_ref8 => {
      let {
        key
      } = _ref8;
      return key === sortColumn;
    });
    const defaultSort = (a, b) => {
      if (a > b) {
        return 1;
      }
      if (a < b) {
        return -1;
      }
      return 0;
    };
    if (!column) {
      return data;
    }
    return data.sort((a, b) => (column.sort ? column.sort(a, b) : defaultSort(a[sortColumn], b[sortColumn])) * (sortDirection === 'ASC' ? 1 : -1));
  }
  sort(columnKey) {
    const {
      sortInPlace
    } = this.state;
    let {
      sortColumn,
      sortDirection
    } = this.state;
    sortDirection = sortColumn === columnKey && sortDirection === 'ASC' ? 'DESC' : 'ASC';
    sortColumn = columnKey;
    if (sortInPlace) {
      this.setState({
        sortColumn,
        sortDirection
      });
    }
    if (this.props.onSortChange) {
      this.props.onSortChange({
        sortColumn,
        sortDirection
      });
    }
  }
  isRowSelected(row) {
    return this.state.selection.indexOf(getRowKey(row, this.props)) !== -1;
  }
  setSelection(selection) {
    this.setState({
      selection
    });
    if (this.props.onSelectionChange) {
      this.props.onSelectionChange(selection.slice());
    }
  }
  isRowExpanded(row) {
    return this.state.expandedRows.indexOf(getRowKey(row, this.props)) !== -1;
  }
  isRowExpandable(row) {
    const {
      virtual
    } = this.getRowProps(row);
    if (virtual) {
      return false;
    }
    return this.props.notExpandableRows.indexOf(getRowKey(row, this.props)) === -1;
  }
  handleRowExpandingChange(row) {
    let expandedRows;
    const rowKey = getRowKey(row, this.props);
    if (this.isRowExpanded(row)) {
      expandedRows = this.state.expandedRows.filter(value => value !== rowKey);
    } else {
      expandedRows = this.state.expandedRows.slice();
      expandedRows.push(rowKey);
    }
    this.setExpandedRows(expandedRows);
  }
  setExpandedRows(expandedRows) {
    this.setState({
      expandedRows
    });
    safeInvoke(this.props.onExpandedRowsChange, expandedRows.slice());
  }
  renderRow(_ref9) {
    let {
      row,
      index,
      hasTitle,
      realColumn,
      parent,
      isDragged,
      reorderableProps
    } = _ref9;
    const {
      baseClassName,
      renderRowBody,
      reorderable
    } = this.props;
    const {
      vertical,
      reorderableItemWidths
    } = this.state;
    const hasActions = realColumn.some(_ref10 => {
      let {
        type
      } = _ref10;
      return type === 'actions';
    });
    const {
      className,
      virtual,
      ...rowProps
    } = this.getRowProps(row);
    let skipCells = 0;
    const Wrapper = reorderable && !parent ? Tbody : Fragment;
    const element = /*#__PURE__*/_createElement(Wrapper, {
      ...(Wrapper === Tbody && !isDragged ? reorderableProps : undefined),
      key: getRowKey(row, this.props)
    }, /*#__PURE__*/_jsx("tr", {
      className: classNames({
        'is-selected': this.isRowSelected(row),
        [`${baseClassName}__row--expanded`]: this.isRowExpanded(row),
        [`${baseClassName}__row--expandable`]: renderRowBody && this.isRowExpandable(row),
        [`${baseClassName}__row--parent`]: row.data,
        [`${baseClassName}__row--virtual`]: virtual,
        [`${baseClassName}__row--child`]: parent,
        [`${baseClassName}__row--reorderable`]: reorderable,
        [`${baseClassName}__row--${row.intent}`]: row.intent
      }, className),
      ...rowProps,
      onClick: renderRowBody ? this.createRowClickHandler(row) : undefined,
      children: realColumn.map((_ref11, index) => {
        let {
          key,
          title,
          render,
          width,
          cellProps,
          truncate,
          type
        } = _ref11;
        if (skipCells > 0) {
          skipCells -= 1;
          return null;
        }
        let style;
        if (!hasTitle && width && !vertical) {
          style = {
            width
          };
        }
        if (isDragged) {
          style = {
            width: reorderableItemWidths[index]
          };
        }
        let content = render ? render(row, {
          parent
        }) : row[key];
        // cell props from render
        if (content && content.children && ! /*#__PURE__*/isValidElement(content)) {
          const {
            children,
            ...other
          } = content;
          content = children;
          cellProps = {
            ...cellProps,
            ...other
          };
          if (other.colSpan) {
            skipCells += other.colSpan - 1;
          }
        }
        const isCellEmpty = !title && !content;
        if (truncate) {
          content = /*#__PURE__*/_jsx("div", {
            className: `${baseClassName}__truncate`,
            children: /*#__PURE__*/_jsx(Text, {
              truncate: true,
              children: content
            })
          });
        }
        if (vertical) {
          const hasColumnTitle = type !== 'internal' && type !== 'actions' && type !== 'title' && title;
          if (!isCellEmpty && type !== 'internal') {
            content = /*#__PURE__*/_jsxs(_Fragment, {
              children: [hasColumnTitle && /*#__PURE__*/_jsx("div", {
                className: `${baseClassName}__cell-inner-title`,
                children: title
              }), /*#__PURE__*/_jsx("div", {
                className: `${baseClassName}__cell-inner-content`,
                children: content
              })]
            });
          }
          if (type === 'actions') {
            content = /*#__PURE__*/_jsx(VerticalContext.Provider, {
              value: true,
              children: content
            });
          }
        }

        // do not render reorderable handler for nested rows
        if (key === 'reorderable' && type === 'internal' && parent) {
          content = null;
        }
        return /*#__PURE__*/_jsx("td", {
          style: style,
          ...cellProps,
          className: classNames(cellProps && cellProps.className, {
            [`${baseClassName}__cell-controls`]: type === 'controls',
            [`${baseClassName}__cell-actions`]: type === 'actions',
            [`${baseClassName}__cell-title`]: type === 'title',
            [`${baseClassName}__cell-has-actions`]: type === 'title' && hasActions
          }) || undefined,
          children: content
        }, key);
      })
    }), renderRowBody && !virtual && this.renderRowBody({
      row,
      index,
      realColumn,
      parent
    }), row.data ? row.data.map((childRow, index) => this.renderRow({
      row: childRow,
      index,
      hasTitle,
      realColumn,
      parent: row
    })) : null);
    if (isDragged) {
      return /*#__PURE__*/_jsx("div", {
        className: classNames(baseClassName, `${baseClassName}--dragged`),
        ...reorderableProps,
        children: /*#__PURE__*/_jsx("table", {
          className: classNames(`${baseClassName}__table`, `${baseClassName}__table--reorderable`, {
            [`${baseClassName}--expandable`]: renderRowBody,
            [`${baseClassName}__table--vertical`]: vertical
          }),
          children: element
        })
      });
    }
    return element;
  }
  renderRowBody(_ref12) {
    let {
      row,
      index,
      realColumn,
      parent
    } = _ref12;
    const {
      baseClassName,
      renderRowBody
    } = this.props;
    const {
      vertical
    } = this.state;
    if (!renderRowBody) {
      return null;
    }
    const reorderable = realColumn.find(_ref13 => {
      let {
        key
      } = _ref13;
      return key === 'reorderable';
    });
    const expander = realColumn.find(_ref14 => {
      let {
        key
      } = _ref14;
      return key === 'expander';
    });
    const isRowExpanded = this.isRowExpanded(row);
    const trRef = /*#__PURE__*/createRef();
    return /*#__PURE__*/_jsx(CSSTransition, {
      in: isRowExpanded,
      unmountOnExit: true,
      timeout: {
        enter: 0,
        exit: 300
      },
      classNames: `${baseClassName}__row-body-`,
      nodeRef: trRef,
      children: state => /*#__PURE__*/_jsxs("tr", {
        className: `${baseClassName}__row-body`,
        ref: trRef,
        children: [reorderable ? /*#__PURE__*/_jsx("td", {
          className: `${baseClassName}__cell-reorderable`
        }) : null, expander ? /*#__PURE__*/_jsx("td", {
          className: `${baseClassName}__cell-expander`
        }) : null, /*#__PURE__*/_jsx("td", {
          colSpan: realColumn.length - (reorderable ? 1 : 0) - (expander ? 1 : 0),
          className: `${baseClassName}__cell-body`,
          children: /*#__PURE__*/_jsx("div", {
            className: `${baseClassName}__row-body-content-wrapper`,
            children: /*#__PURE__*/_jsx("div", {
              className: `${baseClassName}__row-body-content ${baseClassName}__row-body-content--${state}`,
              children: /*#__PURE__*/_jsx(VerticalContext.Provider, {
                value: vertical,
                children: renderRowBody(row, {
                  index,
                  parent
                })
              })
            })
          })
        })]
      })
    });
  }
  renderSelectAllButton() {
    const {
      allRowsSelected,
      totalRows,
      onAllRowsSelectedChange,
      onSelectionChange,
      locale
    } = this.props;
    const {
      selection
    } = this.state;
    if (allRowsSelected || selection.length === totalRows || !onSelectionChange) {
      return null;
    }
    return /*#__PURE__*/_jsx(Button, {
      ghost: true,
      onClick: () => {
        this.handleGlobalSelectionChange(true);
        safeInvoke(onAllRowsSelectedChange, true);
      },
      children: /*#__PURE__*/_jsx(Translate, {
        namespace: "List",
        content: "selectAll",
        fallback: "Select all",
        translators: locale
      })
    });
  }
  renderDeselectAllButton() {
    const {
      allRowsSelected,
      onAllRowsSelectedChange,
      onSelectionChange,
      locale
    } = this.props;
    const {
      selection
    } = this.state;
    if (!allRowsSelected && selection.length === 0 || !onSelectionChange) {
      return null;
    }
    return /*#__PURE__*/_jsx(Button, {
      ghost: true,
      onClick: () => {
        this.handleGlobalSelectionChange(false);
        safeInvoke(onAllRowsSelectedChange, false);
      },
      children: /*#__PURE__*/_jsx(Translate, {
        namespace: "List",
        content: "deselectAll",
        fallback: "Deselect",
        translators: locale
      })
    });
  }
  renderToolbar() {
    const {
      toolbar,
      allRowsSelected,
      totalRows,
      data,
      locale
    } = this.props;
    const {
      selection
    } = this.state;
    let selectedRowTitle;
    if (selection.length === 1) {
      const row = this.flatData(data).find(row => getRowKey(row, this.props) === selection[0]);
      if (row) {
        selectedRowTitle = this.getRowTitle(row);
      }
    }
    if (!toolbar) {
      return null;
    }
    // eslint-disable-next-line react/jsx-no-constructed-context-values
    const context = {
      selectedRows: allRowsSelected ? totalRows || /*#__PURE__*/_jsx(Translate, {
        namespace: "List",
        content: "all",
        fallback: "all",
        translators: locale
      }) : selection.length,
      selectedRowTitle
    };
    return /*#__PURE__*/_jsx(ListOperationContext.Provider, {
      value: context,
      children: toolbar
    });
  }
  shouldBePagination() {
    const {
      totalRows,
      pagination
    } = this.props;
    if (!pagination || !totalRows) {
      return false;
    }
    if (totalRows && /*#__PURE__*/isValidElement(pagination)) {
      const {
        itemsPerPageOptions = ITEMS_PER_PAGE_OPTIONS
      } = pagination.props;
      if (Array.isArray(itemsPerPageOptions)) {
        const numericOptions = itemsPerPageOptions.filter(v => Number(v) === v);
        if (numericOptions.length) {
          const min = Math.min(...numericOptions);
          if (totalRows <= min) {
            return false;
          }
        }
      }
    }
    return true;
  }
  renderHeader() {
    const {
      baseClassName,
      allRowsSelected,
      totalRows,
      locale
    } = this.props;
    const {
      selection
    } = this.state;
    const shouldBePagination = this.shouldBePagination();
    if (totalRows === undefined && !shouldBePagination) {
      return null;
    }
    return /*#__PURE__*/_jsxs("div", {
      className: `${baseClassName}__header`,
      children: [totalRows === undefined ? /*#__PURE__*/_jsx("span", {}) : /*#__PURE__*/_jsxs("span", {
        children: [/*#__PURE__*/_jsx("span", {
          className: `${baseClassName}__header-text`,
          children: getHumanTotalRows({
            selectedRows: selection.length,
            totalRows,
            allRowsSelected,
            translators: locale
          })
        }), ` `, /*#__PURE__*/_jsxs("span", {
          className: `${baseClassName}__header-buttons`,
          children: [this.renderSelectAllButton(), this.renderDeselectAllButton()]
        })]
      }), shouldBePagination && /*#__PURE__*/_jsx("div", {
        className: `${baseClassName}__header-text`,
        children: this.renderPagination('header')
      })]
    });
  }
  renderEmptyView() {
    const {
      emptyView,
      filtered
    } = this.props;
    if (emptyView === undefined) {
      return filtered ? /*#__PURE__*/_jsx(ListEmptyView, {
        reason: "filtered"
      }) : /*#__PURE__*/_jsx(ListEmptyView, {});
    }
    return emptyView;
  }
  renderPagination(placement) {
    const {
      pagination,
      loading
    } = this.props;
    const paginationProps = {
      loading
    };
    switch (placement) {
      case 'header':
        paginationProps.view = 'popover';
        break;
      case 'footer':
        paginationProps.onSelect = current => {
          this.needScroll = true;
          safeInvoke(pagination.props.onSelect, current);
        };
        if (pagination.props.onItemsPerPageChange) {
          paginationProps.onItemsPerPageChange = itemsPerPage => {
            this.needScroll = true;
            safeInvoke(pagination.props.onItemsPerPageChange, itemsPerPage);
          };
        }
        break;
    }
    return /*#__PURE__*/cloneElement(pagination, {
      ...paginationProps
    });
  }
  render() {
    const {
      baseClassName,
      className,
      data,
      columns,
      sortColumn,
      sortDirection,
      onSortChange,
      selection,
      onSelectionChange,
      renderSelectionCheckbox,
      rowKey,
      renderRowBody,
      expandedRows,
      notExpandableRows,
      onExpandedRowsChange,
      loadingRows,
      pagination,
      totalRows,
      toolbar,
      allRowsSelected,
      onAllRowsSelectedChange,
      filtered,
      emptyView,
      emptyViewMode,
      sidebar,
      locale,
      vertical: verticalProp,
      loading,
      rowProps,
      reorderable,
      onReorderEnd,
      ...props
    } = this.props;
    const {
      vertical
    } = this.state;
    if (false === (data && data.length > 0) && !filtered && emptyViewMode === 'all') {
      return this.renderEmptyView();
    }
    const realColumn = columns.map((column, i) => {
      const classList = [];
      const cellClassList = [];
      if (i === 0) {
        cellClassList.push(`${baseClassName}__cell-first`);
      }
      if (column.align && !vertical) {
        const className = `${baseClassName}__cell-${column.align}`;
        classList.push(className);
        cellClassList.push(className);
      }
      if (column.className) {
        classList.push(column.className);
        cellClassList.push(column.className);
      }
      const newColumn = {
        ...column
      };
      if (classList.length) {
        newColumn.className = classNames(...classList);
      }
      if (cellClassList.length) {
        newColumn.cellProps = {
          className: classNames(...cellClassList)
        };
      }
      return newColumn;
    });
    if (onSelectionChange) {
      const headerChecked = this.isAllRowsChecked(data, this.state.selection);
      const headerCheckboxProps = {
        checked: headerChecked,
        onChange: this.handleGlobalSelectionChange
      };
      realColumn.unshift({
        key: 'selection',
        type: 'internal',
        className: `${baseClassName}__cell-selection`,
        cellProps: {
          className: `${baseClassName}__cell-selection`
        },
        title: typeof renderSelectionCheckbox === 'function' ? renderSelectionCheckbox(headerCheckboxProps) : /*#__PURE__*/_jsx(Checkbox, {
          ...headerCheckboxProps
        }),
        render: row => {
          const {
            virtual
          } = this.getRowProps(row);
          if (virtual) {
            return null;
          }
          if (this.isRowLoading(row)) {
            return /*#__PURE__*/_jsx(Spinner, {
              className: `${baseClassName}__spinner`
            });
          }
          const checkboxProps = {
            checked: this.isRowSelected(row),
            disabled: row.disabled,
            onChange: checked => this.handleRowSelectionChange(checked, getRowKey(row, this.props)),
            inputProps: {
              value: getRowKey(row, this.props)
            }
          };
          if (typeof renderSelectionCheckbox === 'function') {
            return renderSelectionCheckbox(checkboxProps, row);
          }
          return /*#__PURE__*/_jsx(Checkbox, {
            ...checkboxProps
          });
        }
      });
    }
    if (renderRowBody) {
      realColumn.unshift({
        key: 'expander',
        type: 'internal',
        className: `${baseClassName}__cell-expander`,
        cellProps: {
          className: `${baseClassName}__cell-expander`
        },
        title: /*#__PURE__*/_jsx(Button, {
          ghost: true,
          className: `${baseClassName}__row-expander`,
          icon: /*#__PURE__*/_jsx(Icon, {
            className: `${baseClassName}__row-expander-icon`,
            children: /*#__PURE__*/_jsx("svg", {
              xmlns: "http://www.w3.org/2000/svg",
              viewBox: "0 0 10 10",
              children: /*#__PURE__*/_jsx("path", {
                fill: "none",
                stroke: "currentColor",
                strokeLinecap: "round",
                strokeLinejoin: "round",
                d: "M1.5 1.4L5 4.9l3.5-3.5M1.5 5.1L5 8.6l3.5-3.5"
              })
            })
          }),
          onClick: this.handleGlobalExpandingChange
        }),
        render: row => this.isRowExpandable(row) && /*#__PURE__*/_jsx(Button, {
          ghost: true,
          className: `${baseClassName}__row-expander`,
          icon: /*#__PURE__*/_jsx(Icon, {
            className: `${baseClassName}__row-expander-icon`,
            children: /*#__PURE__*/_jsx("svg", {
              xmlns: "http://www.w3.org/2000/svg",
              viewBox: "0 0 10 10",
              children: /*#__PURE__*/_jsx("path", {
                fill: "none",
                stroke: "currentColor",
                strokeLinecap: "round",
                strokeLinejoin: "round",
                d: "M1.5 3.2L5 6.7l3.5-3.5"
              })
            })
          }),
          onClick: () => this.handleRowExpandingChange(row)
        })
      });
    }
    if (reorderable) {
      realColumn.unshift({
        key: 'reorderable',
        type: 'internal',
        className: `${baseClassName}__cell-reorderable`,
        cellProps: {
          className: `${baseClassName}__cell-reorderable`
        },
        title: null,
        render: () => /*#__PURE__*/_jsx("span", {
          className: `${baseClassName}__cell-reorderable-indicator`,
          "data-movable-handle": true,
          children: /*#__PURE__*/_jsx("svg", {
            width: "6",
            height: "14",
            fill: "none",
            xmlns: "http://www.w3.org/2000/svg",
            "aria-hidden": "true",
            children: /*#__PURE__*/_jsx("path", {
              d: "M0 0h2v2H0zM0 4h2v2H0zM0 8h2v2H0zM0 12h2v2H0zM4 0h2v2H4zM4 4h2v2H4zM4 8h2v2H4zM4 12h2v2H4z",
              fill: "currentColor"
            })
          })
        })
      });
    }
    const hasTitle = !vertical && columns.some(column => column.title);
    let content;
    if (false === (data && data.length > 0) && (filtered || emptyViewMode === 'items')) {
      content = this.renderEmptyView();
    } else {
      const renderList = _ref15 => {
        let {
          children,
          props: reorderableProps
        } = _ref15;
        return /*#__PURE__*/_jsx(FocusVisibleManager, {
          children: /*#__PURE__*/_jsxs("table", {
            className: classNames(`${baseClassName}__table`, {
              [`${baseClassName}--expandable`]: renderRowBody,
              [`${baseClassName}__table--vertical`]: vertical,
              [`${baseClassName}__table--reorderable`]: reorderable
            }),
            ...reorderableProps,
            children: [hasTitle && /*#__PURE__*/_jsx("thead", {
              children: /*#__PURE__*/_jsx("tr", {
                className: classNames(`${baseClassName}__table-thead`, {
                  [`${baseClassName}__row--expanded`]: this.isAnyRowsExpanded(data, this.state.expandedRows)
                }),
                children: realColumn.map(_ref16 => {
                  let {
                    key,
                    title,
                    sortable,
                    sort,
                    width,
                    render,
                    truncate,
                    type,
                    cellProps,
                    ...headerProps
                  } = _ref16;
                  if (sortable) {
                    title = /*#__PURE__*/_jsx("div", {
                      className: "th__action",
                      children: title
                    });
                    headerProps.className = classNames({
                      'is-sortable': sortable,
                      'is-sorted is-sorted--up': this.state.sortColumn === key && this.state.sortDirection === 'ASC',
                      'is-sorted is-sorted--down': this.state.sortColumn === key && this.state.sortDirection === 'DESC'
                    }, headerProps.className);
                    headerProps.onClick = () => this.sort(key);
                  }
                  if (width) {
                    headerProps.style = {
                      ...headerProps.style,
                      width
                    };
                  }
                  return /*#__PURE__*/_jsx("th", {
                    ...headerProps,
                    children: title
                  }, key);
                })
              })
            }), reorderable ? children : /*#__PURE__*/_jsx("tbody", {
              children: children
            })]
          })
        });
      };
      const renderItem = _ref17 => {
        let {
          value: {
            row
          },
          index,
          props: reorderableProps,
          isDragged
        } = _ref17;
        return this.renderRow({
          row,
          index,
          hasTitle,
          realColumn,
          reorderableProps,
          isDragged
        });
      };
      if (reorderable) {
        const {
          ReorderableList
        } = this.state;
        content = /*#__PURE__*/_jsx(ReorderableList, {
          beforeDrag: _ref18 => {
            let {
              elements,
              index
            } = _ref18;
            const cells = Array.from(elements[index].firstElementChild.children);
            const reorderableItemWidths = cells.map(cell => window.getComputedStyle(cell).width);
            this.setState({
              reorderableItemWidths
            });
          },
          onChange: _ref19 => {
            let {
              oldIndex,
              newIndex
            } = _ref19;
            safeInvoke(onReorderEnd, {
              oldIndex,
              newIndex
            });
          },
          values: this.getData().map(row => ({
            row
          })),
          renderList: renderList,
          renderItem: renderItem,
          lockVertically: true,
          hooks: {
            getChildren: children => children.filter(node => node.nodeName !== 'THEAD')
          },
          useDragHandle: true
        });
      } else {
        content = renderList({
          children: this.getData().map((row, index) => renderItem({
            value: {
              row
            },
            index
          }))
        });
      }
    }
    content = /*#__PURE__*/_jsx("div", {
      className: classNames(`${baseClassName}__table-container`, {
        [`${baseClassName}__table-container--loading`]: loading
      }),
      children: content
    });
    if (sidebar) {
      content = /*#__PURE__*/_jsxs(Columns, {
        gap: "md",
        children: [/*#__PURE__*/_jsx(Column, {
          fill: true,
          children: content
        }), /*#__PURE__*/_jsx(Column, {
          className: `${baseClassName}__sidebar`,
          children: sidebar
        })]
      });
    }
    const shouldBePagination = this.shouldBePagination();
    const createRoot = ref => /*#__PURE__*/_jsxs("div", {
      ref: ref,
      className: classNames(baseClassName, className),
      ...props,
      children: [this.renderHeader(), this.renderToolbar(), shouldBePagination && /*#__PURE__*/_jsx("span", {
        ref: this.anchorRef
      }), content, shouldBePagination && /*#__PURE__*/_jsx("div", {
        className: `${baseClassName}__footer`,
        children: this.renderPagination('footer')
      })]
    });
    if (typeof verticalProp === 'number') {
      return /*#__PURE__*/_jsx(Measure, {
        bounds: true,
        onResize: this.handleResize,
        children: _ref20 => {
          let {
            measureRef
          } = _ref20;
          return createRoot(measureRef);
        }
      });
    }
    return createRoot();
  }
}
List.propTypes = {
  /**
   * Columns definition.
   *
   * In addition to the properties described below, you can use any native properties
   * supported by the `TH` element like `className`, `style`, etc.
   * @since 0.0.42
   */
  columns: PropTypes.arrayOf(PropTypes.shape({
    /**
     * Unique column key.
     */
    key: PropTypes.string.isRequired,
    /**
     * Column title.
     */
    title: PropTypes.node,
    /**
     * Optional cell renderer function: `row => Component`. By default render value of cell.
     * The renderer function can also returns a configuration object like: `{children: 'cell content', colSpan: 3}`
     */
    render: PropTypes.func,
    /**
     * Is column sortable.
     * Default is `false`
     */
    sortable: PropTypes.bool,
    /**
     * Optional function for row comparison: `(row1, row2) => -1 | 0 | 1`
     */
    sort: PropTypes.func,
    /**
     * Column alignment.
     */
    align: PropTypes.oneOf(['left', 'center', 'right']),
    /**
     * Truncate the text in cell with an ellipsis.
     */
    truncate: PropTypes.bool,
    /**
     * Determine type of column content.
     *
     * * title - There should a title of the row.
     * * controls - There should be some control: a button or a dropdown.
     * * actions - There should be the ListAction component.
     */
    type: PropTypes.oneOf(['title', 'controls', 'actions'])
  })).isRequired,
  /**
   * Array of row objects.
   *
   * Each row must contains `key` property, all columns keys, and can contain `disabled` property.
   * @since 0.0.42
   */
  data: PropTypes.arrayOf(PropTypes.shape({
    /**
     * Unique column key. This property can by renamed using `rowKey` property of List.
     */
    key: PropTypes.string,
    /**
     * Optional property for disabling ability to select this row.
     */
    disabled: PropTypes.bool,
    /**
     * Optional array of children rows.
     */
    data: PropTypes.array,
    /**
     * An optional property to change the appearance of this row.<br />
     *  `inactive, info, success, warning, danger`. (Since: 3.33.0)
     */
    intent: PropTypes.oneOf(['inactive', 'info', 'success', 'warning', 'danger'])
  })),
  /**
   * Current sort column key
   * @since 0.0.42
   */
  sortColumn: PropTypes.string,
  /**
   * Sort direction of the column being sorted.
   * @since 0.0.42
   */
  sortDirection: PropTypes.oneOf(['ASC', 'DESC']),
  /**
   * Sort change handler
   * @since 0.0.42
   */
  onSortChange: PropTypes.func,
  /**
   * Array of keys of selected rows
   * @since 0.0.42
   */
  selection: PropTypes.array,
  /**
   * Selection change handler for list. Checkboxes will only be rendered if this prop is defined.
   * @since 0.0.42
   */
  onSelectionChange: PropTypes.func,
  /**
   * Renderer for a selection checkbox. Allow to replace checkboxes in the List by a custom implementation.
   * @since 3.19.0
   */
  renderSelectionCheckbox: PropTypes.func,
  /**
   * Row's key getter. Could be a string or function like: `row => <unique_string>`
   * @since 0.0.45
   */
  rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  /**
   * Renderer for a row body. Should return ReactNode.
   * @since 1.12.0
   */
  renderRowBody: PropTypes.func,
  /**
   * Array of keys of expanded rows
   * @since 1.12.0
   */
  expandedRows: PropTypes.array,
  /**
   * Array of keys of rows which not have expand indicator
   * @since 1.12.0
   */
  notExpandableRows: PropTypes.array,
  /**
   * Rows expanding change handler.
   * @since 1.12.0
   */
  onExpandedRowsChange: PropTypes.func,
  /**
   * Array of keys of loading rows. They are displayed instead of checkboxes.
   * @since 2.5.0
   */
  loadingRows: PropTypes.array,
  /**
   * A `Pagination` element. It displays at the top and the bottom of the list. When pagination is defined, the built-in sort is disabled.
   * @since 2.4.0
   */
  pagination: PropTypes.node,
  /**
   * Total rows count, including nested rows. Usually, it uses together with pagination.
   * @since 2.4.0
   */
  totalRows: PropTypes.number,
  /**
   * A `Toolbar` element.
   * @since 2.4.0
   */
  toolbar: PropTypes.node,
  /**
   * A flag that all rows are selected.
   * @since 2.4.0
   */
  allRowsSelected: PropTypes.bool,
  /**
   * A callback executed when the allRowsSelected prop is changed.
   * @since 2.4.0
   */
  onAllRowsSelectedChange: PropTypes.func,
  /**
   * Filtered list. Manages toolbar visibility when data is absent and defines the defaults for empty view.
   * @since 3.0.1
   */
  filtered: PropTypes.bool,
  /**
   * A custom view for the case when data is absent.
   * @since 2.5.0
   */
  emptyView: PropTypes.node,
  /**
   * Which part of the List component should be replaced by the empty view.
   * @since 2.6.0
   * @deprecated Use `filtered` instead.
   */
  emptyViewMode: PropTypes.oneOf(['all', 'items']),
  /**
   * A slot on the right of the items.
   * @since 2.6.0
   */
  sidebar: PropTypes.node,
  /**
   * Custom localization messages.
   * @since 2.6.0
   */
  locale: PropTypes.shape({
    selectAll: PropTypes.node,
    deselectAll: PropTypes.node,
    all: PropTypes.node,
    totalRows: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
    selectedRows: PropTypes.oneOfType([PropTypes.func, PropTypes.node])
  }),
  /**
   * Render List row's content vertically.
   * When some number is specified, it turns into vertical mode automatically if the List's width is less than the provided number.
   * @since 3.3.0
   */
  vertical: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
  /**
   * Indicate the loading state of the list.
   * @since 3.3.1
   */
  loading: PropTypes.bool,
  /**
   * Apply some props to each row.
   *
   * `virtual` - Virtual row does not have any controls.
   *
   * @since 3.11.0
   */
  rowProps: PropTypes.oneOfType([PropTypes.shape({
    virtual: PropTypes.bool
  }), PropTypes.func]),
  /**
   * Enable reorderable view.
   * @since 3.18.0
   */
  reorderable: PropTypes.bool,
  /**
   * Reorder end handler.
   * @since 3.18.0
   */
  onReorderEnd: PropTypes.func,
  /**
   * @ignore
   */
  className: PropTypes.string,
  /**
   * @ignore
   */
  baseClassName: PropTypes.string
};
List.defaultProps = {
  data: [],
  sortColumn: null,
  sortDirection: 'ASC',
  onSortChange: null,
  onSelectionChange: null,
  selection: [],
  renderSelectionCheckbox: undefined,
  rowKey: 'key',
  renderRowBody: undefined,
  expandedRows: [],
  notExpandableRows: [],
  onExpandedRowsChange: undefined,
  loadingRows: [],
  className: null,
  baseClassName: `${CLS_PREFIX}list`,
  pagination: undefined,
  totalRows: undefined,
  toolbar: undefined,
  allRowsSelected: false,
  onAllRowsSelectedChange: undefined,
  filtered: false,
  emptyView: undefined,
  emptyViewMode: 'all',
  sidebar: undefined,
  locale: undefined,
  vertical: VERTICAL_BREAKPOINT,
  loading: false,
  rowProps: undefined,
  reorderable: false,
  onReorderEnd: undefined
};
export default List;