@razorpay/blade
Version:
The Design System that powers Razorpay
426 lines (415 loc) • 22.6 kB
JavaScript
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 (false) {
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