UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

426 lines (415 loc) 22.6 kB
import _slicedToArray from '@babel/runtime/helpers/slicedToArray'; import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties'; import _defineProperty from '@babel/runtime/helpers/defineProperty'; import React__default, { useEffect, useMemo, useCallback } from 'react'; import { Table as Table$1 } from '@table-library/react-table-library/table'; import { useTheme as useTheme$1 } from '@table-library/react-table-library/theme'; import { useSort } from '@table-library/react-table-library/sort'; import { usePagination } from '@table-library/react-table-library/pagination'; import { SelectTypes, useRowSelect, SelectClickTypes } from '@table-library/react-table-library/select'; import styled from 'styled-components'; import usePresence from 'use-presence'; import { TableContext } from './TableContext.js'; import { ComponentIds } from './componentIds.js'; import { tableBackgroundColor, firstColumnStickyZIndex, checkboxCellWidth, tablePagination, refreshWrapperZIndex } from './tokens.js'; import './commonStyles/index.js'; import '../../utils/index.js'; import '../../utils/isValidAllowedChildren/index.js'; import '../../utils/logger/index.js'; import { getBaseBoxStyles } from '../Box/BaseBox/baseBoxStyles.js'; import '../Box/BaseBox/index.js'; import '../Spinner/index.js'; import '../Box/styledProps/index.js'; import '../../utils/metaAttribute/index.js'; import '../../utils/assignWithoutSideEffects/index.js'; import '../BladeProvider/index.js'; import getIn from '../../utils/lodashButBetter/get.js'; import '../../utils/makeAccessible/index.js'; import { useIsMobile } from '../../utils/useIsMobile.js'; import '../../utils/makeAnalyticsAttribute/index.js'; import { jsx, jsxs } from 'react/jsx-runtime'; import { getComponentId, isValidAllowedChildren } from '../../utils/isValidAllowedChildren/isValidAllowedChildren.js'; import useTheme from '../BladeProvider/useTheme.js'; import { getTableBodyStyles } from './commonStyles/tableBodyStyles.js'; import { BaseBox } from '../Box/BaseBox/BaseBox.web.js'; import { makeMotionTime } from '../../utils/makeMotionTime/makeMotionTime.web.js'; import { makeBorderSize } from '../../utils/makeBorderSize/makeBorderSize.js'; import { throwBladeError } from '../../utils/logger/logger.js'; import { getStyledProps } from '../Box/styledProps/getStyledProps.js'; import { metaAttribute } from '../../utils/metaAttribute/metaAttribute.web.js'; import { MetaConstants } from '../../utils/metaAttribute/metaConstants.js'; import { makeAnalyticsAttribute } from '../../utils/makeAnalyticsAttribute/makeAnalyticsAttribute.js'; import { Spinner } from '../Spinner/Spinner/Spinner.js'; import { makeAccessible } from '../../utils/makeAccessible/makeAccessible.web.js'; import { assignWithoutSideEffects } from '../../utils/assignWithoutSideEffects/assignWithoutSideEffects.js'; var _excluded = ["children", "data", "multiSelectTrigger", "selectionType", "onSelectionChange", "isHeaderSticky", "isFooterSticky", "isFirstColumnSticky", "rowDensity", "onSortChange", "sortFunctions", "toolbar", "pagination", "height", "showStripedRows", "gridTemplateColumns", "isLoading", "isRefreshing", "showBorderedCells", "defaultSelectedIds", "backgroundColor"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var rowSelectType = { single: SelectTypes.SingleSelect, multiple: SelectTypes.MultiSelect, none: undefined }; // Get the number of TableHeaderCell components. // This is very complicated but the only way to iterate through the structure and get number of header cells. // Assuming number of header cells is the same as number of columns var getTableHeaderCellCount = function getTableHeaderCellCount(children) { var tableRootComponent = children([]); if (tableRootComponent && /*#__PURE__*/React__default.isValidElement(tableRootComponent)) { var tableComponentArray = React__default.Children.toArray(tableRootComponent); if ( /*#__PURE__*/React__default.isValidElement(tableComponentArray[0])) { var _tableHeaderCells$len; var tableComponentArrayChildren = React__default.Children.toArray(tableComponentArray[0].props.children); var tableHeader = tableComponentArrayChildren.find(function (child) { return getComponentId(child) === ComponentIds.TableHeader; }); var tableHeaderChildrenArray = /*#__PURE__*/React__default.isValidElement(tableHeader) ? React__default.Children.toArray(tableHeader.props.children) : null; var tableHeaderRow = tableHeaderChildrenArray === null || tableHeaderChildrenArray === void 0 ? void 0 : tableHeaderChildrenArray.find(function (child) { return getComponentId(child) === ComponentIds.TableHeaderRow; }); var tableHeaderRowChildrenArray = /*#__PURE__*/React__default.isValidElement(tableHeaderRow) ? React__default.Children.toArray(tableHeaderRow.props.children) : null; var tableHeaderCells = tableHeaderRowChildrenArray ? tableHeaderRowChildrenArray.filter(function (child) { return getComponentId(child) === ComponentIds.TableHeaderCell; }) : null; return (_tableHeaderCells$len = tableHeaderCells === null || tableHeaderCells === void 0 ? void 0 : tableHeaderCells.length) !== null && _tableHeaderCells$len !== void 0 ? _tableHeaderCells$len : 0; } } return 0; }; var StyledReactTable = /*#__PURE__*/styled(Table$1).withConfig({ displayName: "Tableweb__StyledReactTable", componentId: "h0v0s8-0" })(function (_ref) { var $styledProps = _ref.$styledProps; var _useTheme = useTheme(), theme = _useTheme.theme; var styledPropsCSSObject = getBaseBoxStyles(_objectSpread({ theme: theme, height: $styledProps === null || $styledProps === void 0 ? void 0 : $styledProps.height }, ($styledProps === null || $styledProps === void 0 ? void 0 : $styledProps.isVirtualized) && { width: '100%' })); var $isSelectable = $styledProps === null || $styledProps === void 0 ? void 0 : $styledProps.isSelectable; var $showStripedRows = $styledProps === null || $styledProps === void 0 ? void 0 : $styledProps.showStripedRows; return _objectSpread({ '&&&': _objectSpread(_objectSpread({}, styledPropsCSSObject), {}, { overflow: "".concat($styledProps !== null && $styledProps !== void 0 && $styledProps.isVirtualized ? 'unset' : 'auto', " !important") }) }, $styledProps !== null && $styledProps !== void 0 && $styledProps.isVirtualized ? getTableBodyStyles({ isVirtualized: $styledProps === null || $styledProps === void 0 ? void 0 : $styledProps.isVirtualized, theme: theme, height: $styledProps === null || $styledProps === void 0 ? void 0 : $styledProps.height, width: '100%', isSelectable: $isSelectable, showStripedRows: $showStripedRows }) : null); }); var RefreshWrapper = /*#__PURE__*/styled(BaseBox).withConfig({ displayName: "Tableweb__RefreshWrapper", componentId: "h0v0s8-1" })(function (_ref2) { var isRefreshSpinnerVisible = _ref2.isRefreshSpinnerVisible, isRefreshSpinnerEntering = _ref2.isRefreshSpinnerEntering, isRefreshSpinnerExiting = _ref2.isRefreshSpinnerExiting, theme = _ref2.theme; return { opacity: isRefreshSpinnerVisible ? 1 : 0, transition: "opacity ".concat(makeMotionTime(theme.motion.duration.quick), " ").concat(isRefreshSpinnerEntering ? theme.motion.easing.entrance : isRefreshSpinnerExiting ? theme.motion.easing.exit : '') }; }); var _Table = function _Table(_ref3) { var _ref4; var children = _ref3.children, data = _ref3.data, _ref3$multiSelectTrig = _ref3.multiSelectTrigger, multiSelectTrigger = _ref3$multiSelectTrig === void 0 ? 'row' : _ref3$multiSelectTrig, _ref3$selectionType = _ref3.selectionType, selectionType = _ref3$selectionType === void 0 ? 'none' : _ref3$selectionType, onSelectionChange = _ref3.onSelectionChange, isHeaderSticky = _ref3.isHeaderSticky, isFooterSticky = _ref3.isFooterSticky, isFirstColumnSticky = _ref3.isFirstColumnSticky, _ref3$rowDensity = _ref3.rowDensity, rowDensity = _ref3$rowDensity === void 0 ? 'normal' : _ref3$rowDensity, onSortChange = _ref3.onSortChange, sortFunctions = _ref3.sortFunctions, toolbar = _ref3.toolbar, pagination = _ref3.pagination, height = _ref3.height, showStripedRows = _ref3.showStripedRows, gridTemplateColumns = _ref3.gridTemplateColumns, _ref3$isLoading = _ref3.isLoading, isLoading = _ref3$isLoading === void 0 ? false : _ref3$isLoading, _ref3$isRefreshing = _ref3.isRefreshing, isRefreshing = _ref3$isRefreshing === void 0 ? false : _ref3$isRefreshing, _ref3$showBorderedCel = _ref3.showBorderedCells, showBorderedCells = _ref3$showBorderedCel === void 0 ? false : _ref3$showBorderedCel, _ref3$defaultSelected = _ref3.defaultSelectedIds, defaultSelectedIds = _ref3$defaultSelected === void 0 ? [] : _ref3$defaultSelected, _ref3$backgroundColor = _ref3.backgroundColor, backgroundColor = _ref3$backgroundColor === void 0 ? tableBackgroundColor : _ref3$backgroundColor, rest = _objectWithoutProperties(_ref3, _excluded); var _useTheme2 = useTheme(), theme = _useTheme2.theme; var _React$useState = React__default.useState(selectionType !== 'none' ? defaultSelectedIds : []), _React$useState2 = _slicedToArray(_React$useState, 2), selectedRows = _React$useState2[0], setSelectedRows = _React$useState2[1]; var _React$useState3 = React__default.useState([]), _React$useState4 = _slicedToArray(_React$useState3, 2), disabledRows = _React$useState4[0], setDisabledRows = _React$useState4[1]; var _React$useState5 = React__default.useState(data.nodes.length || 0), _React$useState6 = _slicedToArray(_React$useState5, 2), totalItems = _React$useState6[0], setTotalItems = _React$useState6[1]; var _React$useState7 = React__default.useState('client'), _React$useState8 = _slicedToArray(_React$useState7, 2), paginationType = _React$useState8[0], setPaginationType = _React$useState8[1]; var _React$useState9 = React__default.useState(undefined), _React$useState10 = _slicedToArray(_React$useState9, 2), headerRowDensity = _React$useState10[0], setHeaderRowDensity = _React$useState10[1]; var _React$useState11 = React__default.useState(false), _React$useState12 = _slicedToArray(_React$useState11, 2), hasHoverActions = _React$useState12[0], setHasHoverActions = _React$useState12[1]; var tableRootComponent = children([]); var isVirtualized = getComponentId(tableRootComponent) === ComponentIds.VirtualizedTable; // Need to make header is sticky if first column is sticky otherwise the first header cell will not be sticky var shouldHeaderBeSticky = (_ref4 = isVirtualized !== null && isVirtualized !== void 0 ? isVirtualized : isHeaderSticky) !== null && _ref4 !== void 0 ? _ref4 : isFirstColumnSticky; var isMobile = useIsMobile(); var lastHoverActionsColWidth = isMobile ? '1fr' : '0px'; var _usePresence = usePresence(isRefreshing, { transitionDuration: theme.motion.duration.quick }), isRefreshSpinnerEntering = _usePresence.isEntering, isRefreshSpinnerMounted = _usePresence.isMounted, isRefreshSpinnerExiting = _usePresence.isExiting, isRefreshSpinnerVisible = _usePresence.isVisible; // Table Theme var columnCount = getTableHeaderCellCount(children); var firstColumnStickyHeaderCellCSS = isFirstColumnSticky ? "\n &:nth-of-type(1) {\n left: 0 !important;\n position: sticky !important;\n z-index: ".concat(firstColumnStickyZIndex, " !important;\n }\n ").concat(selectionType === 'multiple' && "&:nth-of-type(2) {\n left: ".concat(checkboxCellWidth, "px !important;\n position: sticky !important;\n z-index: ").concat(firstColumnStickyZIndex, " !important;\n }\n ")) : ''; var firstColumnStickyFooterCellCSS = isFirstColumnSticky ? "\n &:nth-of-type(1) {\n left: 0 !important;\n position: sticky !important;\n z-index: ".concat(firstColumnStickyZIndex, " !important;\n }\n ").concat(selectionType === 'multiple' && "&:nth-of-type(2) {\n left: ".concat(checkboxCellWidth, "px !important;\n position: sticky !important;\n z-index: ").concat(firstColumnStickyZIndex, " !important;\n }\n ")) : ''; var firstColumnStickyBodyCellCSS = isFirstColumnSticky ? "\n &:nth-of-type(1) {\n left: 0 !important;\n position: sticky !important;\n z-index: ".concat(firstColumnStickyZIndex, " !important;\n }\n ").concat(selectionType === 'multiple' && "&:nth-of-type(2) {\n left: ".concat(checkboxCellWidth, "px !important;\n position: sticky !important;\n z-index: ").concat(firstColumnStickyZIndex, " !important;\n }\n ")) : ''; var tableTheme = useTheme$1({ Table: "\n height:".concat(isFooterSticky ? "100%" : undefined, ";\n border: ").concat(makeBorderSize(theme.border.width.thin), " solid ").concat(theme.colors.surface.border.gray.muted, ";\n --data-table-library_grid-template-columns: ").concat(gridTemplateColumns ? "".concat(gridTemplateColumns, " ").concat(hasHoverActions ? lastHoverActionsColWidth : '') : " ".concat(selectionType === 'multiple' ? 'min-content' : '', " repeat(").concat(columnCount, ",minmax(100px, 1fr)) ").concat(hasHoverActions ? lastHoverActionsColWidth : '', " !important;"), " !important;\n background-color: ").concat(getIn(theme.colors, backgroundColor), ";\n "), HeaderCell: "\n position: ".concat(shouldHeaderBeSticky ? 'sticky' : 'relative', ";\n \n top: ").concat(shouldHeaderBeSticky ? '0' : undefined, ";\n ").concat(firstColumnStickyHeaderCellCSS, "\n "), Cell: "\n ".concat(firstColumnStickyBodyCellCSS, "\n "), FooterCell: "\n position: ".concat(isFooterSticky ? 'sticky' : 'relative', ";\n bottom: ").concat(isFooterSticky ? '0' : undefined, ";\n ").concat(firstColumnStickyFooterCellCSS, "\n ") }); useEffect(function () { // Get the total number of items setTotalItems(data.nodes.length); }, [data.nodes]); // Selection Logic var onSelectChange = function onSelectChange(_, state) { var _state$ids; var selectedIds = state.id ? [state.id] : (_state$ids = state.ids) !== null && _state$ids !== void 0 ? _state$ids : []; setSelectedRows(selectedIds); onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({ selectedIds: selectedIds, values: data.nodes.filter(function (node) { return selectedIds.includes(node.id); }) }); }; var rowSelectConfig = useRowSelect(data, { onChange: onSelectChange, state: _objectSpread({}, selectionType === 'multiple' ? { ids: selectedRows } : selectionType === 'single' ? { id: selectedRows[0] } : {}) }, { clickType: multiSelectTrigger === 'row' ? SelectClickTypes.RowClick : SelectClickTypes.ButtonClick, rowSelect: selectionType !== 'none' ? rowSelectType[selectionType] : undefined }); var toggleRowSelectionById = useMemo(function () { return function (id) { rowSelectConfig.fns.onToggleById(id); }; }, [rowSelectConfig.fns]); var deselectAllRows = useMemo(function () { return function () { rowSelectConfig.fns.onRemoveAll(); }; }, [rowSelectConfig.fns]); var toggleAllRowsSelection = useMemo(function () { return function () { if (selectedRows.length > 0) { rowSelectConfig.fns.onRemoveAll(); } else { var ids = data.nodes.map(function (item) { return disabledRows.includes(item.id) ? null : item.id; }).filter(Boolean); rowSelectConfig.fns.onAddAll(ids); } }; }, [rowSelectConfig.fns, data.nodes, selectedRows, disabledRows]); // Sort Logic var handleSortChange = function handleSortChange(_, state) { onSortChange === null || onSortChange === void 0 ? void 0 : onSortChange({ sortKey: state.sortKey, isSortReversed: state.reverse }); }; var sort = useSort(data, { onChange: handleSortChange }, { // @ts-expect-error ignore this, if sortFunctions is undefined, it will be ignored sortFns: sortFunctions }); var currentSortedState = useMemo(function () { return { sortKey: sort.state.sortKey, isSortReversed: sort.state.reverse, sortableColumns: Object.keys(sortFunctions !== null && sortFunctions !== void 0 ? sortFunctions : {}) }; }, [sort.state, sortFunctions]); var toggleSort = useCallback(function (sortKey) { sort.fns.onToggleSort({ sortKey: sortKey }); }, [sort.fns]); // Pagination var hasPagination = Boolean(pagination); var paginationConfig = usePagination(data, { state: { page: 0, size: tablePagination.defaultPageSize } }, { isServer: paginationType === 'server' }); var currentPaginationState = useMemo(function () { return hasPagination ? { page: paginationConfig.state.page, size: paginationConfig.state.size } : undefined; }, [paginationConfig.state, hasPagination]); var setPaginationPage = useCallback(function (page) { paginationConfig.fns.onSetPage(page); }, [paginationConfig.fns]); var setPaginationRowSize = useCallback(function (size) { paginationConfig.fns.onSetSize(size); }, [paginationConfig.fns]); // Toolbar Component if (true) { if (toolbar && !isValidAllowedChildren(toolbar, ComponentIds.TableToolbar)) { throwBladeError({ message: 'Only TableToolbar component is allowed in the `toolbar` prop', moduleName: 'Table' }); } } // Table Context var tableContext = useMemo(function () { return { selectionType: selectionType, selectedRows: selectedRows, totalItems: totalItems, toggleRowSelectionById: toggleRowSelectionById, toggleAllRowsSelection: toggleAllRowsSelection, deselectAllRows: deselectAllRows, rowDensity: rowDensity, toggleSort: toggleSort, currentSortedState: currentSortedState, setPaginationPage: setPaginationPage, setPaginationRowSize: setPaginationRowSize, currentPaginationState: currentPaginationState, showStripedRows: showStripedRows, disabledRows: disabledRows, setDisabledRows: setDisabledRows, paginationType: paginationType, setPaginationType: setPaginationType, backgroundColor: backgroundColor, headerRowDensity: headerRowDensity, setHeaderRowDensity: setHeaderRowDensity, showBorderedCells: showBorderedCells, hasHoverActions: hasHoverActions, setHasHoverActions: setHasHoverActions, columnCount: columnCount, gridTemplateColumns: gridTemplateColumns, isVirtualized: isVirtualized, tableData: data.nodes }; }, [selectionType, selectedRows, totalItems, toggleRowSelectionById, toggleAllRowsSelection, deselectAllRows, gridTemplateColumns, rowDensity, toggleSort, columnCount, currentSortedState, setPaginationPage, setPaginationRowSize, currentPaginationState, showStripedRows, disabledRows, setDisabledRows, paginationType, setPaginationType, backgroundColor, headerRowDensity, setHeaderRowDensity, showBorderedCells, hasHoverActions, setHasHoverActions, isVirtualized, data]); return /*#__PURE__*/jsx(TableContext.Provider, { value: tableContext, children: isLoading ? /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread(_objectSpread(_objectSpread({ display: "flex", flex: 1, alignItems: "center", justifyContent: "center", height: height }, getStyledProps(rest)), metaAttribute({ name: MetaConstants.Table })), makeAnalyticsAttribute(rest)), {}, { children: /*#__PURE__*/jsx(Spinner, { accessibilityLabel: "Loading Table", size: "large", testID: "table-spinner" }) })) : /*#__PURE__*/jsxs(BaseBox // ref={ref as never} , _objectSpread(_objectSpread(_objectSpread({ flex: 1, position: "relative" }, getStyledProps(rest)), metaAttribute({ name: MetaConstants.Table })), {}, { width: isVirtualized ? "100%" : undefined, children: [isRefreshSpinnerMounted && /*#__PURE__*/jsx(RefreshWrapper, { position: "absolute", width: "100%", height: "100%", zIndex: refreshWrapperZIndex, backgroundColor: "overlay.background.subtle", justifyContent: "center", alignItems: "center", display: "flex", isRefreshSpinnerEntering: isRefreshSpinnerEntering, isRefreshSpinnerExiting: isRefreshSpinnerExiting, isRefreshSpinnerVisible: isRefreshSpinnerVisible, children: /*#__PURE__*/jsx(Spinner, { color: "white", accessibilityLabel: "Refreshing Table", size: "large" }) }), toolbar, /*#__PURE__*/jsx(StyledReactTable, _objectSpread(_objectSpread(_objectSpread(_objectSpread({ role: "table", layout: { fixedHeader: shouldHeaderBeSticky, horizontalScroll: true }, data: data // @ts-expect-error ignore this, theme clashes with styled-component's theme. We're using useTheme from blade to get actual theme , theme: tableTheme, select: selectionType !== 'none' ? rowSelectConfig : null, sort: sortFunctions ? sort : null, $styledProps: { height: height, width: isVirtualized ? "100%" : undefined, isVirtualized: isVirtualized, isSelectable: selectionType !== 'none', showStripedRows: showStripedRows }, pagination: hasPagination ? paginationConfig : null }, makeAccessible({ multiSelectable: selectionType === 'multiple' })), metaAttribute({ name: MetaConstants.Table })), makeAnalyticsAttribute(rest)), {}, { children: children })), pagination] })) }); }; var Table = /*#__PURE__*/assignWithoutSideEffects(_Table, { componentId: ComponentIds.Table }); export { Table }; //# sourceMappingURL=Table.web.js.map