UNPKG

@teamsnap/teamsnap-ui

Version:

a CSS component library for TeamSnap

233 lines (232 loc) 11.9 kB
"use strict"; /** * @name Table * * @description * A Table component that works like a helper in composing the Panel components and various other options. * See the Teamsnap patterns library for more information. https://teamsnap-ui-patterns.netlify.com/patterns/components/table.html * * @example * <Table * defaultSort='col2' * columns=[ * { name: 'col1', label: 'Column One', isSortable: true }, * { name: 'col2', label: 'Column Two', isSortable: true }, * { name: 'col3', label: 'Column Three', render: (column, row) => <a href={`/path/to/${row.id}`}>{ row.col3 }</a> } * ] * rows=[ * { id: 1, col1: 'Row 1 Column One', col2: 'Row 1 Column 2', col3: 'Row 1 Column 3' }, * { id: 2, col1: 'Row 2 Column One', col2: 'Row 2 Column 2', col3: 'Row 2 Column 3' }, * { id: 3, col1: 'Row 3 Column One', col2: 'Row 3 Column 2', col3: 'Row 3 Column 3' } * ] /> * */ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); var React = __importStar(require("react")); var PropTypes = __importStar(require("prop-types")); var helpers_1 = require("../../utils/helpers"); var sort_1 = require("../../utils/sort"); var Icon_1 = require("../Icon"); var Panel_1 = require("../Panel"); var PanelBody_1 = require("../PanelBody"); var PanelRow_1 = require("../PanelRow"); var PanelCell_1 = require("../PanelCell"); var Loader_1 = require("../Loader"); var Table = /** @class */ (function (_super) { __extends(Table, _super); function Table(props) { var _this = _super.call(this, props) || this; _this.handleSortClick = function (sortName) { var items = _this.state.items; var sortDirection = sortName === _this.state.sortByColumn ? !_this.state.sortByReverse : false; // If an function is provided here, we let the parent component figure out the sorting // This is valuable when we sort beyond the data thats currently in the table // IE: We keep data on the server and want to sort against that or are supporting pagination. if (_this.props.externalSortingFunction != null) { _this.props.externalSortingFunction(sortName, sortDirection); var state = Table.getTableState(_this.props, sortName, sortDirection); _this.setState(state); } else { var tableState = Table.sortItems(_this.props, items, sortName, sortDirection); _this.setState(__assign({}, tableState)); } }; _this.renderSortLabel = function (label) { return (React.createElement("span", { className: "u-colorInfo u-textNoWrap" }, label)); }; _this.renderSortLink = function (column) { var _a = _this.state, items = _a.items, sortByColumn = _a.sortByColumn, sortByReverse = _a.sortByReverse; var activeColumn = items.length && column.name === sortByColumn; var ascLinkMods = (0, helpers_1.getClassName)("u-block", activeColumn && !sortByReverse && "u-colorHighlight"); var descLinkMods = (0, helpers_1.getClassName)("u-block", activeColumn && sortByReverse && "u-colorHighlight"); var textLinkMods = (0, helpers_1.getClassName)("u-flex", column.align === "right" && "u-flexJustifyEnd u-spaceNegativeRightSm", column.align === "center" && "u-flexJustifyCenter"); return (React.createElement("span", { role: "button", style: { cursor: "pointer" }, onClick: function () { _this.handleSortClick(column.name); }, className: textLinkMods }, _this.renderSortLabel(column.label), React.createElement("div", { className: "u-colorGrey u-fontSizeXs u-spaceLeftXs" }, React.createElement(Icon_1.Icon, { name: "up", mods: ascLinkMods }), React.createElement(Icon_1.Icon, { name: "down", mods: descLinkMods })))); }; _this.renderPanelCell = function (role, children, column) { var cellMods = (0, helpers_1.getClassName)(column.mods, "u-text" + (0, helpers_1.capitalize)(column.align || "Left")); return (React.createElement(PanelCell_1.PanelCell, __assign({ key: column.key, mods: cellMods, role: role, style: column.style, isTitle: column.isTitle }, column.otherProps), children)); }; _this.renderColumn = function (column, row) { var data = row[column.name]; var children = column.render ? column.render(column, row) : data; return _this.renderPanelCell("cell", children, __assign({ key: row.id + "-" + column.name, itTitle: false }, column)); }; _this.renderHeaderColumn = function (column) { var children = column.isSortable ? _this.renderSortLink(column) : _this.renderSortLabel(column.label); return _this.renderPanelCell("columnheader", children, __assign({ key: column.name, isTitle: true }, column)); }; _this.renderRow = function (row) { var columns = _this.props.columns; return (React.createElement(PanelRow_1.PanelRow, { key: row.id, isWithCells: true }, columns.map(function (column) { return _this.renderColumn(column, row); }))); }; _this.renderTableColumns = function () { var columns = _this.props.columns; return columns.map(_this.renderHeaderColumn); }; _this.renderTableRows = function (placeHolder, isLoading) { var items = _this.state.items; if (isLoading) { return (React.createElement("div", { className: "u-padMd u-textCenter" }, React.createElement(Loader_1.Loader, { type: "spin", text: "loading..." }))); } if (!isLoading && items.length) { return items.map(_this.renderRow); } return React.createElement("div", { className: "u-padMd u-textCenter" }, placeHolder); }; var defaultSort = _this.props.defaultSort; // Establish initial sortDirection by checking for '-' value var sortDirection = defaultSort.charAt(0) === "-" ? true : false; var sortName = sortDirection ? defaultSort.substr(1) : defaultSort; var state = Table.getTableState(props, sortName, sortDirection); _this.state = __assign({}, state); return _this; } Table.getDerivedStateFromProps = function (props, state) { var sortByColumn = state.sortByColumn, sortByReverse = state.sortByReverse; return Table.getTableState(props, sortByColumn, sortByReverse); }; Table.getTableState = function (props, sortName, sortDirection) { var rows = props.rows; var items = (0, helpers_1.setUniqueId)(rows); var tableState = sortName ? Table.sortItems(props, items, sortName, sortDirection) : { items: items }; return tableState; }; Table.prototype.render = function () { var _a = this.props, isStriped = _a.isStriped, className = _a.className, mods = _a.mods, style = _a.style, otherProps = _a.otherProps, maxTableHeight = _a.maxTableHeight, placeHolder = _a.placeHolder, isLoading = _a.isLoading; return (React.createElement(Panel_1.Panel, __assign({ className: className, mods: mods, isStriped: isStriped, style: style }, otherProps), React.createElement(PanelBody_1.PanelBody, { role: "table" }, React.createElement(PanelRow_1.PanelRow, { isWithCells: true }, this.renderTableColumns()), maxTableHeight && (React.createElement("div", { style: { height: maxTableHeight, overflow: "scroll" } }, this.renderTableRows(placeHolder, isLoading))), !maxTableHeight && this.renderTableRows(placeHolder, isLoading)))); }; Table.defaultProps = { columns: [], rows: [], defaultSort: "", isStriped: true, className: "Panel", mods: null, style: {}, otherProps: {}, placeHolder: "Nothing to see here", maxTableHeight: null, isLoading: false, }; Table.propTypes = { columns: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string.isRequired, label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), render: PropTypes.func, isSortable: PropTypes.bool, sortType: PropTypes.string, sortFn: PropTypes.func, align: PropTypes.oneOf(["right", "left", "center"]), mods: PropTypes.string, style: PropTypes.object, otherProps: PropTypes.object, })), rows: PropTypes.arrayOf(PropTypes.object), defaultSort: PropTypes.string, externalSortingFunction: PropTypes.func, isStriped: PropTypes.bool, className: PropTypes.string, mods: PropTypes.string, style: PropTypes.object, otherProps: PropTypes.object, maxTableHeight: PropTypes.string, isLoading: PropTypes.bool, placeHolder: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), }; Table.sortItems = function (props, newItems, sortByColumn, sortByReverse) { var columns = props.columns; var sortColumn = columns.find(function (c) { return c.name === sortByColumn; }); var items = newItems; if (sortColumn) { var name_1 = sortColumn.name, sortType = sortColumn.sortType, sortFn = sortColumn.sortFn; items = (0, sort_1.sortBy)(newItems, { name: name_1, sortType: sortType, sortFn: sortFn, isReverse: sortByReverse, }); } return { items: items, sortByColumn: sortByColumn, sortByReverse: sortByReverse }; }; return Table; }(React.PureComponent)); exports.default = Table;