wix-style-react
Version:
481 lines (380 loc) • 23.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createColumns = createColumns;
exports.getDataTableProps = getDataTableProps;
exports.Table = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _defaultTo = _interopRequireDefault(require("lodash/defaultTo"));
var _classnames = _interopRequireDefault(require("classnames"));
var _reactScrollSync = require("react-scroll-sync");
var _deprecationLog = _interopRequireDefault(require("../utils/deprecationLog"));
var _TableSt = require("./Table.st.css");
var _DataTable = _interopRequireDefault(require("./DataTable"));
var _Checkbox = _interopRequireDefault(require("../Checkbox"));
var _TableContext = require("./TableContext");
var _BulkSelection = require("./BulkSelection");
var _TooltipCommon = require("../common/PropTypes/TooltipCommon");
var _components = require("./components");
var _excluded = ["showSelection", "onSelectionChanged", "dataHook", "hideHeader"];
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var hasUnselectablesSymbol = Symbol('hasUnselectables');
function createColumns(_ref2) {
var tableProps = _ref2.tableProps,
bulkSelectionContext = _ref2.bulkSelectionContext;
var createCheckboxColumn = function createCheckboxColumn(_ref3) {
var toggleSelectionById = _ref3.toggleSelectionById,
isSelected = _ref3.isSelected,
selectionDisabled = _ref3.selectionDisabled;
var isRowSelectionDisabled = function isRowSelectionDisabled(rowData) {
return selectionDisabled === true || typeof selectionDisabled === 'function' && selectionDisabled(rowData);
};
return {
title: tableProps.hideBulkSelectionCheckbox ? '' : /*#__PURE__*/_react["default"].createElement(_components.TableBulkSelectionCheckbox, {
dataHook: "table-select"
}),
onCellClick: function onCellClick(column, row, rowNum, event) {
if (row.unselectable) {
return;
}
event.stopPropagation();
if (isRowSelectionDisabled(row)) {
return;
}
var id = (0, _defaultTo["default"])(row.id, rowNum);
toggleSelectionById(id, 'Checkbox');
},
render: function render(row, rowNum) {
var id = (0, _defaultTo["default"])(row.id, rowNum);
var tooltipContent = row.checkboxTooltipContent;
return row.unselectable ? null : /*#__PURE__*/_react["default"].createElement(_Checkbox["default"], {
disabled: isRowSelectionDisabled(row),
dataHook: "row-select",
checked: isSelected(id),
tooltipProps: {
disabled: !tooltipContent
},
tooltipContent: tooltipContent
});
},
// Apply different column width when just the single selection column is marked
// as sticky (looks weird otherwise when stickied with default 12px width).
width: tableProps.stickyColumns === 1 ? '34px' : '12px',
style: function style(_, row) {
return row.unselectable ? undefined : {
cursor: 'pointer'
};
}
};
};
return tableProps.showSelection ? [createCheckboxColumn(bulkSelectionContext)].concat((0, _toConsumableArray2["default"])(tableProps.columns)) : tableProps.columns;
}
function getDataTableProps(tableProps) {
/* eslint-disable no-unused-vars */
var showSelection = tableProps.showSelection,
onSelectionChanged = tableProps.onSelectionChanged,
dataHook = tableProps.dataHook,
hideHeader = tableProps.hideHeader,
props = (0, _objectWithoutProperties2["default"])(tableProps, _excluded);
return _objectSpread(_objectSpread({}, props), {}, {
rowClass: (0, _classnames["default"])(tableProps.rowClass, _TableSt.classes.tableRow)
});
}
/**
* Table is a composite component that allows adding SelectionColumn, Toolbar (on top of the TitleBar).
* It is a context provider, and thus the Table.Consumer, Table.TitleBar and Table.Content can be rendered separately.
*/
var Table = /*#__PURE__*/function (_React$Component) {
(0, _inherits2["default"])(Table, _React$Component);
var _super = _createSuper(Table);
function Table() {
var _this;
(0, _classCallCheck2["default"])(this, Table);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _super.call.apply(_super, [this].concat(args));
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "state", {
leftShadowVisible: false,
rightShadowVisible: false
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_handleUpdateScrollShadows", function (leftShadowVisible, rightShadowVisible) {
if (leftShadowVisible !== _this.state.leftShadowVisible) {
_this.setState({
leftShadowVisible: leftShadowVisible
});
}
if (rightShadowVisible !== _this.state.rightShadowVisible) {
_this.setState({
rightShadowVisible: rightShadowVisible
});
}
});
return _this;
}
(0, _createClass2["default"])(Table, [{
key: "shouldComponentUpdate",
value: function shouldComponentUpdate() {
// Table is not really a PureComponent
return true;
}
}, {
key: "setSelectedIds",
value: function setSelectedIds(selectedIds) {
this.bulkSelection.setSelectedIds(selectedIds);
}
}, {
key: "renderChildren",
value: function renderChildren() {
var _this$props = this.props,
children = _this$props.children,
withWrapper = _this$props.withWrapper,
dataHook = _this$props.dataHook;
return withWrapper ? /*#__PURE__*/_react["default"].createElement("div", {
"data-hook": dataHook
}, children) : children;
}
}, {
key: "render",
value: function render() {
var _this2 = this;
var _this$props2 = this.props,
data = _this$props2.data,
selectedIds = _this$props2.selectedIds,
showSelection = _this$props2.showSelection,
deselectRowsByDefault = _this$props2.deselectRowsByDefault,
infiniteScroll = _this$props2.infiniteScroll,
totalSelectableCount = _this$props2.totalSelectableCount,
onSelectionChanged = _this$props2.onSelectionChanged,
hasMore = _this$props2.hasMore,
horizontalScroll = _this$props2.horizontalScroll,
hideHeader = _this$props2.hideHeader,
selectionDisabled = _this$props2.selectionDisabled;
if (hideHeader) {
(0, _deprecationLog["default"])('<Table>\'s "hideHeader" prop is deprecated. To hide the table header, render "<Table.Content titleBarVisible={false}>" in its "children" prop');
}
var hasUnselectables = null;
var allIds = data.map(function (rowData, rowIndex) {
return rowData.unselectable || typeof selectionDisabled === 'function' && selectionDisabled(rowData) ? hasUnselectables = hasUnselectablesSymbol : (0, _defaultTo["default"])(rowData.id, rowIndex);
});
if (hasUnselectables === hasUnselectablesSymbol) {
allIds = allIds.filter(function (rowId) {
return rowId !== hasUnselectablesSymbol;
});
}
var _this$state = this.state,
leftShadowVisible = _this$state.leftShadowVisible,
rightShadowVisible = _this$state.rightShadowVisible;
var contextValue = _objectSpread(_objectSpread({}, this.props), {}, {
leftShadowVisible: leftShadowVisible,
rightShadowVisible: rightShadowVisible,
onUpdateScrollShadows: this._handleUpdateScrollShadows
});
var table = /*#__PURE__*/_react["default"].createElement(_TableContext.TableContext.Provider, {
value: contextValue
}, showSelection ? /*#__PURE__*/_react["default"].createElement(_BulkSelection.BulkSelection, {
ref: function ref(_ref) {
return _this2.bulkSelection = _ref;
},
selectedIds: selectedIds,
deselectRowsByDefault: deselectRowsByDefault,
selectionDisabled: selectionDisabled,
hasMoreInBulkSelection: infiniteScroll && Boolean(totalSelectableCount) && hasMore,
totalCount: totalSelectableCount,
allIds: allIds,
onSelectionChanged: onSelectionChanged
}, this.renderChildren()) : this.renderChildren());
return horizontalScroll ? /*#__PURE__*/_react["default"].createElement(_reactScrollSync.ScrollSync, {
proportional: false,
horizontal: true,
vertical: false
}, table) : table;
}
}]);
return Table;
}(_react["default"].Component);
exports.Table = Table;
(0, _defineProperty2["default"])(Table, "ToolbarContainer", _components.TableToolbarContainer);
(0, _defineProperty2["default"])(Table, "Titlebar", _components.TableTitleBar);
(0, _defineProperty2["default"])(Table, "Content", _components.TableContent);
(0, _defineProperty2["default"])(Table, "SubToolbar", _components.TableSubToolbar);
(0, _defineProperty2["default"])(Table, "EmptyState", _components.TableEmptyState);
(0, _defineProperty2["default"])(Table, "BulkSelectionCheckbox", _components.TableBulkSelectionCheckbox);
Table.displayName = 'Table';
Table.defaultProps = _objectSpread(_objectSpread({}, _DataTable["default"].defaultProps), {}, {
showSelection: false,
hideBulkSelectionCheckbox: false,
children: [/*#__PURE__*/_react["default"].createElement(Table.Content, {
key: "content"
})],
withWrapper: true,
showLastRowDivider: false,
horizontalScroll: false,
stickyColumns: 0,
isRowDisabled: function isRowDisabled() {
return false;
}
});
Table.propTypes = {
/** Any wrapper element that eventually includes <Table.Content/> as a child */
children: _propTypes["default"].any,
/** Applied as data-hook HTML attribute that can be used in the tests */
dataHook: _propTypes["default"].string,
/** Called when row selection changes.
* Receives 2 arguments: `selectedIds` array, and a `change` object ( in this order).
* `selectedIds` is the updated selected ids.
* The `change` object has a `type` property with the following possible values: 'ALL', 'NONE', 'SINGLE_TOGGLE'.
* In case of 'SINGLE_TOGGLE' the `change` object will also include an `id` prop with the item's id,
* and a `value` prop with the new boolean selection state of the item.
* The `change` object also contains an `origin` property which indicates what initiated the selection change.
* The `origin` property can be set when selection is updated using a `SelectionContext` method. */
onSelectionChanged: _propTypes["default"].func,
/** Indicates whether to show a selection column (with checkboxes).<br>
* To hide the selection checkbox from a specific row, set its `row.unselectable` (in the `data` prop) to `true`. */
showSelection: _propTypes["default"].bool,
/** Indicates whether to hide the bulk selection ("Select All") checkbox in the table header when showing the selection column */
hideBulkSelectionCheckbox: _propTypes["default"].bool,
/** Array of selected row ids.
* Ideally, id should be a property on the data row object.
* If data objects do not have id property, then the data row's index would be used as an id. */
selectedIds: _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].string), _propTypes["default"].arrayOf(_propTypes["default"].number)]),
/** Can be either a boolean or a function.
* If passed a boolean, disables selection for all table rows.
* If passed a function, it will be called for every row in `data` to specify if its checkbox should be disabled. Example: `selectionDisabled={(rowData) => !rowData.isSelectable}` */
selectionDisabled: _propTypes["default"].oneOfType([_propTypes["default"].bool, _propTypes["default"].func]),
/** Indicates the `SelectionContext.toggleAll` behaviour when some rows are selected. `true` means SOME -> NONE, `false` means SOME -> ALL */
deselectRowsByDefault: _propTypes["default"].bool,
/**
* When false then Table would not create a `<div/>` wrapper around it's children.
* Useful when using `<Table/>` to wrap a `<Page/>` component, in that case we use the `<Table/>` only as a context provider and it does not render anything to the DOM by itself.*/
withWrapper: _propTypes["default"].bool,
/**
* A callback function called on each column title click. Signature `onSortClick(colData, colNum)`
*/
onSortClick: _propTypes["default"].func,
// The following props are derived directly from <DataTable/> component
/** Allows to open multiple row details */
allowMultiDetailsExpansion: _propTypes["default"].bool,
/** The data to display.<br>
* For each `row` in `data`, If `row.id` exists then it will be used as the React `key` value for each row, otherwise, the row index will be used.<br>
* When `showSelection` prop is set, if `row.unselectable` is truthy for a `row` in `data`, no checkbox will be displayed for the row in the selection column.
* When `checkboxTooltipContent` is set, a tooltip with the requested content will be displayed over the selection checkbox (content can be either string or a node)if `row.unselectable` is truthy for a `row` in `data`, no checkbox will be displayed for the row in the selection column. */
data: _propTypes["default"].array,
// Not performing any shape validation to not hurt performance.
/** Configuration of the table's columns.<br>
* Each column needs to specify:
* * `title`: a string or an element to display in the table header for this column
* * `render`: a function which will be called for every row in `data` to display this row's value for this column<br>
*
* Each column can also specify these fields:
* * `onCellClick`: A callback method to be called when a cell in this column is clicked. Signature: `onCellClick(column, rowData, rowNum, event)`
* * `sortable`: Sets whether this field is sortable. If `true` clicking the header will call `onSortClick`
* * `sortDescending`: Sets what sort icon to display in the column header. `true` will show an up arrow, `false` will show a down arrow, `undefined' will show no icon
* * `infoTooltipProps`: Props object for column header's [tooltip](/?path=/story/components-api-components--tooltip). Note: `dataHook`, `moveBy` and `children` will not be passed to tooltip.
* * `style`: Can be a CSS style `object` or a function that returns a style `object` (signature: `style(column, rowData, rowNum)`). Sets the column inline style. Vertical padding cannot be set here, please use table's `rowVerticalPadding` prop
* * `align`: Sets the alignment of the column content
* * `width`: CSS value to set the width to use for this column. No value means column will try to contain its children, if possible
* * `important`: Sets whether font color of the column should be stronger, more dominant
* * `stickyActionCell`: Sets the `<TableActionCell/>` to be sticky to the right.
* */
columns: _propTypes["default"].arrayOf(_propTypes["default"].shape({
title: _propTypes["default"].oneOfType([_propTypes["default"].node, _propTypes["default"].string]).isRequired,
render: _propTypes["default"].func.isRequired,
onCellClick: _propTypes["default"].func,
sortable: _propTypes["default"].bool,
sortDescending: _propTypes["default"].bool,
infoTooltipProps: _propTypes["default"].shape(_TooltipCommon.TooltipCommonProps),
style: _propTypes["default"].oneOfType([_propTypes["default"].object, _propTypes["default"].func]),
align: _propTypes["default"].oneOf(['start', 'center', 'end']),
width: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
important: _propTypes["default"].bool,
stickyActionCell: _propTypes["default"].bool
})).isRequired,
/** A func that gets row data and returns a class(es) to apply to that specific row */
dynamicRowClass: _propTypes["default"].func,
/** A func that gets row data and returns boolean if row is highlighted or not */
isRowHighlight: _propTypes["default"].func,
/** Whether there are more items to be loaded. Event listeners are removed if false. */
hasMore: _propTypes["default"].bool,
/** Indicates whether to invoke `loadMore` on the initial rendering. */
initialLoad: _propTypes["default"].bool,
/** [deprecated] This prop has no affect. To hide the table header, render `<Table.Content titleBarVisible={false}>` in `children`. */
hideHeader: _propTypes["default"].bool,
/** An id to pass to the table */
id: _propTypes["default"].string,
/** If true, table will not render all data to begin with, but will gradually render the data as the user scrolls */
infiniteScroll: _propTypes["default"].bool,
/** Indicates the total number of selectable items in the table, including those not yet loaded.
* When `infiniteScroll` and this prop are set and the user does bulk selection ("Select All"), and there are still unloaded items (`hasMore` is 'true`),
* the table enters an "Infinite Bulk Selection" mode, where newly loaded items get selected by default and `SelectionContext` holds the not-selected items rather than the selected items.
* In this case, `SelectionContext.infiniteBulkSelected` is `true` and `SelectionContext.selectedCount` is the value of `totalSelectableCount` minus the count of unselected items. */
totalSelectableCount: _propTypes["default"].number,
/** If infiniteScroll is on, this prop will determine how many rows will be rendered on each load */
itemsPerPage: _propTypes["default"].number,
/** The loader to show when loading more items. */
loader: _propTypes["default"].node,
/** A callback when more items are requested by the user. */
loadMore: _propTypes["default"].func,
/** A callback method to be called on row click. Signature: `onRowClick(rowData, rowNum)`. To enable hover effect you should set this prop.*/
onRowClick: _propTypes["default"].func,
/** A callback method to be called on row mouse enter. Signature: `onMouseEnterRow(rowData, rowNum)` */
onMouseEnterRow: _propTypes["default"].func,
/** A callback method to be called on row mouse leave. Signature: `onMouseLeaveRow(rowData, rowNum)` */
onMouseLeaveRow: _propTypes["default"].func,
/** Add scroll listeners to the window, or else, the component's parentNode. */
useWindow: _propTypes["default"].bool,
/** Add scroll listeners to specified DOM Object. */
scrollElement: _propTypes["default"].object,
/** Table cell vertical padding:
* - `large`: 24px
* - `medium`: 18px
* - `small`: with the feature toggle: 15px, without the feature toggle: 12px
* - `tiny`: 12px
* */
rowVerticalPadding: _propTypes["default"].oneOf(['tiny', 'small', 'medium', 'large']),
/** Function that returns React component that will be rendered in row details section. Example: `rowDetails={(row, rowNum) => <MyRowDetailsComponent {...row} />}` */
rowDetails: _propTypes["default"].func,
/** Removes row details padding */
removeRowDetailsPadding: _propTypes["default"].bool,
/** A string data-hook to apply to all table body rows. or a func which calculates the data-hook for each row - Signature: `(rowData, rowNum) => string` */
rowDataHook: _propTypes["default"].oneOfType([_propTypes["default"].func, _propTypes["default"].string]),
/** A class to apply to all table body rows */
rowClass: _propTypes["default"].string,
/** Should the table show the header when data is empty */
showHeaderWhenEmpty: _propTypes["default"].bool,
/** A flag specifying weather to show a divider after the last row */
showLastRowDivider: _propTypes["default"].bool,
/** ++EXPERIMENTAL++ Virtualize the table scrolling for long list items */
virtualized: _propTypes["default"].bool,
/** ++EXPERIMENTAL++ Set virtualized table height */
virtualizedTableHeight: _propTypes["default"].number,
/** ++EXPERIMENTAL++ Set virtualized table row height */
virtualizedLineHeight: _propTypes["default"].number,
/** ++EXPERIMENTAL++ Set ref on virtualized List containing table rows */
virtualizedListRef: _propTypes["default"].any,
/** The width of the fixed table. Can be in percentages or pixels. */
width: _propTypes["default"].string,
/** Table styling. Supports `standard` and `neutral`. */
skin: _propTypes["default"].oneOf(['standard', 'neutral']),
/** Enable horizontal scroll. */
horizontalScroll: _propTypes["default"].bool,
/** Number of columns to sticky from the left (should be used with horizontal scroll). */
stickyColumns: _propTypes["default"].number,
/** a function which will be called for every row in `data` to specify if it should appear as disabled. Example: `isRowDisabled={(rowData) => !rowData.isEnabled}` */
isRowDisabled: _propTypes["default"].func
}; // export default Table;