@teamsnap/teamsnap-ui
Version:
a CSS component library for TeamSnap
233 lines (232 loc) • 11.9 kB
JavaScript
;
/**
* @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;