UNPKG

@shopify/polaris

Version:

Shopify’s product component library

341 lines (306 loc) • 10.9 kB
import { objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js'; import React$1, { PureComponent, createRef } from 'react'; import debounce$1 from 'lodash/debounce'; import { EventListener as EventListener$1 } from '../EventListener/EventListener.js'; import { useI18n } from '../../utilities/i18n/hooks.js'; import { headerCell } from '../shared.js'; import { classNames } from '../../utilities/css.js'; import isEqual$1 from 'lodash/isEqual'; import styles from './DataTable.scss.js'; import { Cell as Cell$1 } from './components/Cell/Cell.js'; import { Navigation as Navigation$1 } from './components/Navigation/Navigation.js'; import { measureColumn, getPrevAndCurrentColumns } from './utilities.js'; class DataTableInner extends PureComponent { constructor(...args) { super(...args); this.state = { condensed: false, columnVisibilityData: [], isScrolledFarthestLeft: true, isScrolledFarthestRight: false }; this.dataTable = /*#__PURE__*/createRef(); this.scrollContainer = /*#__PURE__*/createRef(); this.table = /*#__PURE__*/createRef(); this.handleResize = debounce$1(() => { var { table: { current: table }, scrollContainer: { current: scrollContainer } } = this; var condensed = false; if (table && scrollContainer) { condensed = table.scrollWidth > scrollContainer.clientWidth; } this.setState(_objectSpread2({ condensed }, this.calculateColumnVisibilityData(condensed))); }); this.calculateColumnVisibilityData = condensed => { var { table: { current: table }, scrollContainer: { current: scrollContainer }, dataTable: { current: dataTable } } = this; if (condensed && table && scrollContainer && dataTable) { var headerCells = table.querySelectorAll(headerCell.selector); if (headerCells.length > 0) { var firstVisibleColumnIndex = headerCells.length - 1; var tableLeftVisibleEdge = scrollContainer.scrollLeft; var tableRightVisibleEdge = scrollContainer.scrollLeft + dataTable.offsetWidth; var tableData = { firstVisibleColumnIndex, tableLeftVisibleEdge, tableRightVisibleEdge }; var columnVisibilityData = [...headerCells].map(measureColumn(tableData)); var lastColumn = columnVisibilityData[columnVisibilityData.length - 1]; return _objectSpread2(_objectSpread2({ columnVisibilityData }, getPrevAndCurrentColumns(tableData, columnVisibilityData)), {}, { isScrolledFarthestLeft: tableLeftVisibleEdge === 0, isScrolledFarthestRight: lastColumn.rightEdge <= tableRightVisibleEdge }); } } return { columnVisibilityData: [], previousColumn: undefined, currentColumn: undefined }; }; this.scrollListener = () => { this.setState(prevState => _objectSpread2({}, this.calculateColumnVisibilityData(prevState.condensed))); }; this.navigateTable = direction => { var { currentColumn, previousColumn } = this.state; var { current: scrollContainer } = this.scrollContainer; var handleScroll = () => { if (!currentColumn || !previousColumn) { return; } if (scrollContainer) { scrollContainer.scrollLeft = direction === 'right' ? currentColumn.rightEdge : previousColumn.leftEdge; requestAnimationFrame(() => { this.setState(prevState => _objectSpread2({}, this.calculateColumnVisibilityData(prevState.condensed))); }); } }; return handleScroll; }; this.renderHeadings = (heading, headingIndex) => { var { sortable, truncate = false, columnContentTypes, defaultSortDirection, initialSortColumnIndex = 0, verticalAlign } = this.props; var { sortDirection = defaultSortDirection, sortedColumnIndex = initialSortColumnIndex } = this.state; var sortableHeadingProps; var id = "heading-cell-".concat(headingIndex); if (sortable) { var isSortable = sortable[headingIndex]; var isSorted = isSortable && sortedColumnIndex === headingIndex; var _direction = isSorted ? sortDirection : 'none'; sortableHeadingProps = { defaultSortDirection, sorted: isSorted, sortable: isSortable, sortDirection: _direction, onSort: this.defaultOnSort(headingIndex) }; } return /*#__PURE__*/React$1.createElement(Cell$1, Object.assign({ header: true, key: id, content: heading, contentType: columnContentTypes[headingIndex], firstColumn: headingIndex === 0, truncate: truncate }, sortableHeadingProps, { verticalAlign: verticalAlign })); }; this.totalsRowHeading = () => { var { i18n, totals, totalsName } = this.props; var totalsLabel = totalsName ? totalsName : { singular: i18n.translate('Polaris.DataTable.totalRowHeading'), plural: i18n.translate('Polaris.DataTable.totalsRowHeading') }; return totals && totals.filter(total => total !== '').length > 1 ? totalsLabel.plural : totalsLabel.singular; }; this.renderTotals = (total, index) => { var id = "totals-cell-".concat(index); var { truncate = false, verticalAlign } = this.props; var content; var contentType; if (index === 0) { content = this.totalsRowHeading(); } if (total !== '' && index > 0) { contentType = 'numeric'; content = total; } var totalInFooter = this.props.showTotalsInFooter; return /*#__PURE__*/React$1.createElement(Cell$1, { total: true, totalInFooter: totalInFooter, firstColumn: index === 0, key: id, content: content, contentType: contentType, truncate: truncate, verticalAlign: verticalAlign }); }; this.defaultRenderRow = (row, index) => { var className = classNames(styles.TableRow); var { columnContentTypes, truncate = false, verticalAlign } = this.props; return /*#__PURE__*/React$1.createElement("tr", { key: "row-".concat(index), className: className }, row.map((content, cellIndex) => { var id = "cell-".concat(cellIndex, "-row-").concat(index); return /*#__PURE__*/React$1.createElement(Cell$1, { key: id, content: content, contentType: columnContentTypes[cellIndex], firstColumn: cellIndex === 0, truncate: truncate, verticalAlign: verticalAlign }); })); }; this.defaultOnSort = headingIndex => { var { onSort, defaultSortDirection = 'ascending', initialSortColumnIndex } = this.props; var { sortDirection = defaultSortDirection, sortedColumnIndex = initialSortColumnIndex } = this.state; var newSortDirection = defaultSortDirection; if (sortedColumnIndex === headingIndex) { newSortDirection = sortDirection === 'ascending' ? 'descending' : 'ascending'; } var handleSort = () => { this.setState({ sortDirection: newSortDirection, sortedColumnIndex: headingIndex }, () => { if (onSort) { onSort(headingIndex, newSortDirection); } }); }; return handleSort; }; } componentDidMount() { // We need to defer the calculation in development so the styles have time to be injected. if (process.env.NODE_ENV === 'development') { setTimeout(() => { this.handleResize(); }, 10); } else { this.handleResize(); } } componentDidUpdate(prevProps) { if (isEqual$1(prevProps, this.props)) { return; } this.handleResize(); } render() { var { headings, totals, showTotalsInFooter, rows, footerContent, hideScrollIndicator = false } = this.props; var { condensed, columnVisibilityData, isScrolledFarthestLeft, isScrolledFarthestRight } = this.state; var className = classNames(styles.DataTable, condensed && styles.condensed); var wrapperClassName = classNames(styles.TableWrapper, condensed && styles.condensed); var headingMarkup = /*#__PURE__*/React$1.createElement("tr", null, headings.map(this.renderHeadings)); var totalsMarkup = totals ? /*#__PURE__*/React$1.createElement("tr", null, totals.map(this.renderTotals)) : null; var bodyMarkup = rows.map(this.defaultRenderRow); var footerMarkup = footerContent ? /*#__PURE__*/React$1.createElement("div", { className: styles.Footer }, footerContent) : null; var headerTotalsMarkup = !showTotalsInFooter ? totalsMarkup : null; var footerTotalsMarkup = showTotalsInFooter ? /*#__PURE__*/React$1.createElement("tfoot", null, totalsMarkup) : null; var navigationMarkup = hideScrollIndicator ? null : /*#__PURE__*/React$1.createElement(Navigation$1, { columnVisibilityData: columnVisibilityData, isScrolledFarthestLeft: isScrolledFarthestLeft, isScrolledFarthestRight: isScrolledFarthestRight, navigateTableLeft: this.navigateTable('left'), navigateTableRight: this.navigateTable('right') }); return /*#__PURE__*/React$1.createElement("div", { className: wrapperClassName }, navigationMarkup, /*#__PURE__*/React$1.createElement("div", { className: className, ref: this.dataTable }, /*#__PURE__*/React$1.createElement("div", { className: styles.ScrollContainer, ref: this.scrollContainer }, /*#__PURE__*/React$1.createElement(EventListener$1, { event: "resize", handler: this.handleResize }), /*#__PURE__*/React$1.createElement(EventListener$1, { capture: true, event: "scroll", handler: this.scrollListener }), /*#__PURE__*/React$1.createElement("table", { className: styles.Table, ref: this.table }, /*#__PURE__*/React$1.createElement("thead", null, headingMarkup, headerTotalsMarkup), /*#__PURE__*/React$1.createElement("tbody", null, bodyMarkup), footerTotalsMarkup)), footerMarkup)); } } function DataTable(props) { var i18n = useI18n(); return /*#__PURE__*/React$1.createElement(DataTableInner, Object.assign({}, props, { i18n: i18n })); } export { DataTable };