"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Table = Table;
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _resizeObserverPolyfill = _interopRequireDefault(require("resize-observer-polyfill"));
var _reactTable = require("@tanstack/react-table");
var _uniqueId = _interopRequireDefault(require("lodash-es/uniqueId"));
var _tableHeader = require("./table-header");
var _tableBody = require("./table-body");
var _tableHeaderCell = require("./table-header-cell");
var _tableBodyCell = require("./table-body-cell");
var _tableToolbar = require("./table-toolbar");
var _emptyStateWrapper = require("./empty-state-wrapper");
var _useColumns = require("../hooks/useColumns");
var _useVirtual = require("../hooks/useVirtual");
var _useScroll = require("../hooks/useScroll");
var _useLoading = require("../hooks/useLoading");
var _useDebounce = require("../../hooks/use-debounce");
var _useTableKeyboardNavigation = require("../../hooks/use-table-keyboard-navigation");
var _useInnerStateFallback = require("../hooks/useInnerStateFallback");
var _decoreatePinnedColumns = require("../utils/decoreatePinnedColumns");
var _paginationNew = require("../../pagination-new");
var _types = require("../types");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function Table({
  columns,
  data,
  getFilterBody,
  getToolBarActions,
  getToolbarRightActions,
  getEmptyState = () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_emptyStateWrapper.EmptyStateWrapper, {}),
  TableBodyComponent = _tableBody.TableBody,
  TableHeaderComponent = _tableHeader.TableHeader,
  ThComponent = _tableHeaderCell.TableHeaderCell,
  TdComponent = _tableBodyCell.TableBodyCell,
  trClassName,
  thClassName,
  tdClassName,
  expandedContentClassName,
  tableMeta,
  onCellClick,
  onColumnHeaderClick,
  selected,
  sorting,
  onSortingChange,
  pinned,
  expandedRows,
  ExpandedRowComponent,
  columnOrder,
  onColumnOrderChange,
  pagination,
  onPaginationChange,
  totalCount,
  totalLimit,
  isExceededTotalLimit = !!totalLimit && (!totalCount || totalCount >= totalLimit),
  nextPage,
  width,
  errorMessage,
  loadingRowCount,
  getRowId,
  visible,
  onRowClick,
  isRowClickDisabled,
  isRowSelectionDisabled = () => false,
  pageSizeOptions,
  enableRowSelection = false,
  enableCheckBoxes = false,
  enableMultiRowSelection = true,
  isLoading = false,
  defaultColumnSizing = {},
  touched,
  onTouchedChange = () => {},
  onColumnSizingChange = () => {},
  onPinningChange = () => {},
  onExpandedChange = () => {},
  onRowSelectionChange = () => {},
  getRowActions,
  getRowFooterAction,
  getCustomRowContent,
  localizationProps = {},
  defaultState = {},
  onVisibilityChange = () => {},
  enableToolbar = false,
  enableSettings = false,
  bottomEndScrollOffset = 200,
  onScroll = () => {},
  onScrollEnd = () => {},
  afterLoading = false,
  enablePagination = false,
  enableSorting = false,
  enableSortingRemoval = true,
  enableColumnResizing = true,
  tableTestId = 'react-table',
  tableRowTestId = 'react-table-tr',
  tableHeaderRowTestId = 'react-table-tr',
  tableHeaderCellTestId = 'react-table-th',
  tableBodyCellTestId = 'react-table-td',
  size = _types.TABLE_SIZE.MEDIUM,
  enablePinning = true
}) {
  const [columnSizing, setColumnSizing] = (0, _react.useState)(defaultColumnSizing);
  const [centerScrolled, setCenterScrolled] = (0, _react.useState)(false);
  const [scrollableRight, setScrollableRight] = (0, _react.useState)(false);
  const [tableId] = (0, _react.useState)(() => (0, _uniqueId.default)());
  const [visibility, setVisibility] = (0, _react.useState)(visible || {});
  const tableRef = (0, _react.useRef)(null);
  const [isVerticalScrollPresent, setIsVerticalScrollPresent] = (0, _react.useState)(tableRef?.current?.scrollHeight !== tableRef?.current?.clientHeight);

  // we need change width depending on whether we have the scroll or not
  (0, _react.useEffect)(() => {
    const checkScroll = () => {
      setIsVerticalScrollPresent(tableRef?.current?.scrollHeight !== tableRef?.current?.clientHeight);
    };
    if (tableRef?.current) {
      const observer = new _resizeObserverPolyfill.default(() => window.requestAnimationFrame(checkScroll));
      observer.observe(tableRef?.current);
      return () => observer.disconnect();
    }
  }, []);
  const debouncedColumnSizingChange = (0, _useDebounce.useDebounce)(onColumnSizingChange, 600);
  const [columnPinning, onColumnPinningChange] = (0, _useInnerStateFallback.useInnerStateFallback)(onPinningChange, pinned, _decoreatePinnedColumns.decoratePinnedColumns);
  const [rowSelection, setRowSelection] = (0, _useInnerStateFallback.useInnerStateFallback)(onRowSelectionChange, selected);
  const [expanded, setExpanded] = (0, _useInnerStateFallback.useInnerStateFallback)(onExpandedChange, expandedRows);
  const isRowExpandEnabled = !!ExpandedRowComponent;
  const isPaginationLoading = !totalCount && isLoading && !errorMessage;
  const pageCount = (0, _react.useMemo)(() => {
    if (isExceededTotalLimit) {
      return undefined;
    }
    return Math.ceil((totalCount ?? 0) / (pagination?.pageSize ?? 1));
  }, [pagination?.pageSize, totalCount, totalLimit, isExceededTotalLimit]);
  (0, _react.useEffect)(() => {
    debouncedColumnSizingChange(columnSizing);
  }, [columnSizing]);
  (0, _react.useEffect)(() => onVisibilityChange(visibility), [visibility]);
  (0, _react.useEffect)(() => {
    // only row actions can be pinned right, so no need to trigger state updates if table doesn't have row actions
    if (getRowActions) {
      const hasReachedEnd = (tableRef?.current?.clientWidth ?? 0) + (tableRef?.current?.scrollLeft ?? 0) >= (tableRef?.current?.scrollWidth ?? 0);
      setScrollableRight(!hasReachedEnd);
    }
    // Component width depends on Vertical scroll
  }, [columnSizing, width, isVerticalScrollPresent]);
  const decoratedColumns = (0, _useColumns.useColumns)(columns, enableCheckBoxes, width - (isVerticalScrollPresent ? _types.COLUMN_SIZE.SCROLL_OFFSET : 0), visibility, columnSizing, isRowExpandEnabled, !!getRowActions, localizationProps?.tableBody);
  const onChangeSize = fn => {
    const nextData = typeof fn === 'function' ? fn(columnSizing) : fn;
    const targetData = typeof fn === 'function' ? fn({}) : fn;
    const isEmpty = !Object.keys(nextData).length;
    if (isEmpty) {
      onTouchedChange();
      return setColumnSizing({});
    }
    const baseData = decoratedColumns.reduce((acc, current) => ({
      ...acc,
      [current.accessorKey]: current.size
    }), {});
    onTouchedChange({
      width,
      columns: [...(touched?.columns || []), ...Object.keys(targetData)]
    });
    setColumnSizing({
      ...baseData,
      ...nextData
    });
  };
  (0, _react.useEffect)(() => {
    // if container width changed we should resize table for full width but save touched resized columns
    if (touched && touched.width !== width) {
      const touchedResizedColumns = touched.columns.reduce((acc, current) => {
        if (columnSizing[current]) {
          return {
            ...acc,
            [current]: columnSizing[current]
          };
        }
        return acc;
      }, {});
      onTouchedChange({
        ...touched,
        width
      });
      setColumnSizing(touchedResizedColumns);
    }
  }, [width]);
  const tableData = (0, _useLoading.useLoading)(isLoading, afterLoading, data, loadingRowCount || pagination?.pageSize);
  const isEmpty = tableData.length === 0 && !errorMessage;
  const tableModel = (0, _reactTable.useReactTable)({
    data: tableData,
    columns: decoratedColumns,
    getCoreRowModel: (0, _reactTable.getCoreRowModel)(),
    state: {
      rowSelection,
      columnPinning,
      columnSizing,
      sorting,
      pagination,
      columnVisibility: visible || visibility,
      expanded,
      columnOrder
    },
    pageCount,
    onColumnVisibilityChange: setVisibility,
    onColumnOrderChange,
    manualPagination: true,
    onPaginationChange,
    columnResizeMode: 'onChange',
    onColumnSizingChange: onChangeSize,
    onSortingChange,
    onColumnPinningChange,
    onRowSelectionChange: enableRowSelection || enableCheckBoxes ? setRowSelection : undefined,
    enableRowSelection: enableRowSelection || enableCheckBoxes ? row => !isRowSelectionDisabled(row.original) : false,
    enableMultiRowSelection,
    enableSorting,
    enableSortingRemoval,
    sortDescFirst: true,
    manualSorting: true,
    enablePinning,
    enableColumnResizing,
    enableExpanding: isRowExpandEnabled,
    onExpandedChange: isRowExpandEnabled ? setExpanded : undefined,
    getRowCanExpand: () => true,
    // TODO add an ability to define it from outside @vovkvlad
    manualExpanding: true,
    getRowId,
    meta: {
      ...tableMeta,
      tableId,
      isLoading
    }
  });
  const {
    paddingTop,
    paddingBottom,
    virtualRows,
    measureElement
  } = (0, _useVirtual.useVirtual)(tableRef, tableModel, size);
  const keyboardNavigationController = (0, _useTableKeyboardNavigation.useTableKeyboardNavigation)({
    tableRef,
    columnsCount: tableModel.getVisibleFlatColumns().length,
    // for both infinite scroll and paginated tables, we would rely on how much is available atm
    // (on one page for paginated version and how much loaded so fat for infinite scroll)
    rowsCount: tableData.length
  });
  (0, _useScroll.useScroll)(tableRef, bottomEndScrollOffset, onScrollEnd, afterLoading);
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
    className: "table-components-container",
    children: [(enableToolbar || enableSettings) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_tableToolbar.TableToolbar, {
      getToolBarActions: getToolBarActions,
      getToolbarRightActions: getToolbarRightActions,
      enableSorting: enableSorting,
      enablePinning: enablePinning,
      tableModel: tableModel,
      defaultState: defaultState,
      baseColumns: decoratedColumns,
      hideSettings: !enableSettings,
      tableContainerWidth: width,
      localizationText: localizationProps?.headerToolbar
    }), getFilterBody && getFilterBody(), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
      className: (0, _classnames.default)('react-table-container', size === _types.TABLE_SIZE.NESTED && 'nested'),
      children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
        className: "table-container",
        ref: tableRef,
        onScroll: e => {
          // only row actions can be pinned right, so no need to trigger state updates if table doesn't have row actions
          if (getRowActions) {
            const hasReachedEnd = e.target.clientWidth + e.target.scrollLeft >= e.target.scrollWidth;
            setScrollableRight(!hasReachedEnd);
          }
          setCenterScrolled(!!e.target.scrollLeft);
          onScroll(e);
        },
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_useTableKeyboardNavigation.TableKeyboardNavigationContext.Provider, {
          value: keyboardNavigationController,
          children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("table", {
            className: (0, _classnames.default)('react-table', isLoading && 'react-table-loading'),
            "test-id": tableTestId
            // eslint-disable-next-line react/forbid-dom-props
            ,
            style: {
              width: tableModel.getTotalSize()
            },
            role: tableModel.options.enableExpanding ? 'treegrid' : 'grid',
            onKeyDown: keyboardNavigationController.onTableKeyDownHandler,
            "aria-label": localizationProps?.tableAriaLabel,
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(TableHeaderComponent, {
              size: size,
              tableModel: tableModel,
              ThElement: ThComponent,
              trClassName: typeof trClassName !== 'function' ? trClassName : '',
              thClassName: thClassName,
              centerScrolled: centerScrolled,
              scrollableRight: scrollableRight,
              onColumnHeaderClick: onColumnHeaderClick,
              tableContainerWidth: width,
              localizationText: localizationProps?.tableHeader,
              tableRowTestId: tableHeaderRowTestId,
              tableHeaderCellTestId: tableHeaderCellTestId
            }), !isEmpty && !errorMessage ? /*#__PURE__*/(0, _jsxRuntime.jsx)(TableBodyComponent, {
              trClassName: trClassName,
              tableRowTestId: tableRowTestId,
              size: size,
              tableModel: tableModel,
              TdElement: TdComponent,
              tdClassName: tdClassName,
              selectable: enableRowSelection,
              centerScrolled: centerScrolled,
              scrollableRight: scrollableRight,
              onCellClick: onCellClick,
              paddingTop: paddingTop,
              onRowClick: onRowClick,
              isRowClickDisabled: isRowClickDisabled,
              isRowSelectionDisabled: isRowSelectionDisabled,
              paddingBottom: paddingBottom,
              virtualRows: virtualRows,
              ExpandedRowComponent: ExpandedRowComponent,
              measureElement: measureElement,
              getCustomRowContent: getCustomRowContent,
              getRowActions: getRowActions,
              getRowFooterAction: getRowFooterAction,
              expandedContentClassName: expandedContentClassName,
              tableContainerWidth: width - (isVerticalScrollPresent ? _types.COLUMN_SIZE.SCROLL_OFFSET : 0),
              localizationProps: localizationProps?.tableBody,
              tableBodyCellTestId: tableBodyCellTestId
            }) : null]
          })
        }), isEmpty ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
          className: "table-empty-state",
          children: getEmptyState()
        }) : null, errorMessage ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
          className: "table-error-message",
          "test-id": "table-error-message",
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
            className: "error-message",
            children: errorMessage
          })
        }) : null]
      }), enablePagination ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        className: "table-footer",
        "test-id": "table-pagination-container",
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_paginationNew.PaginationNew, {
          isLoading: isPaginationLoading,
          selectedPage: tableModel.getState().pagination.pageIndex,
          total: totalCount || 0,
          totalLimit: totalLimit,
          isExceededTotalLimit: isExceededTotalLimit,
          nextPage: nextPage,
          itemsPerPage: tableModel.getState().pagination.pageSize,
          onItemsPerPageChange: tableModel.setPageSize,
          onPageSelect: tableModel.setPageIndex,
          pageSizeOptions: pageSizeOptions,
          ...localizationProps?.pagination
        })
      }) : null]
    })]
  });
}