UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Office 365.

334 lines • 22.2 kB
define(["require", "exports", "tslib", "react", "react-dom", "../../Utilities", "./DetailsList.types", "../../FocusZone", "../../Icon", "../../Layer", "../GroupedList/GroupSpacer", "../../GroupedList", "./DetailsRowCheck", "./DetailsRowCheck.scss", "../../utilities/selection/interfaces", "./DetailsHeader.scss"], function (require, exports, tslib_1, React, ReactDOM, Utilities_1, DetailsList_types_1, FocusZone_1, Icon_1, Layer_1, GroupSpacer_1, GroupedList_1, DetailsRowCheck_1, checkStylesModule, interfaces_1, stylesImport) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var styles = stylesImport; var checkStyles = checkStylesModule; var MOUSEDOWN_PRIMARY_BUTTON = 0; // for mouse down event we are using ev.button property, 0 means left button var MOUSEMOVE_PRIMARY_BUTTON = 1; // for mouse move event we are using ev.buttons property, 1 means left button var INNER_PADDING = 16; var ISPADDED_WIDTH = 24; var SelectAllVisibility; (function (SelectAllVisibility) { SelectAllVisibility[SelectAllVisibility["none"] = 0] = "none"; SelectAllVisibility[SelectAllVisibility["hidden"] = 1] = "hidden"; SelectAllVisibility[SelectAllVisibility["visible"] = 2] = "visible"; })(SelectAllVisibility = exports.SelectAllVisibility || (exports.SelectAllVisibility = {})); var DetailsHeader = /** @class */ (function (_super) { tslib_1.__extends(DetailsHeader, _super); function DetailsHeader(props) { var _this = _super.call(this, props) || this; _this.state = { columnResizeDetails: undefined, groupNestingDepth: _this.props.groupNestingDepth, isAllCollapsed: _this.props.isAllCollapsed }; _this._onToggleCollapseAll = _this._onToggleCollapseAll.bind(_this); _this._onSelectAllClicked = _this._onSelectAllClicked.bind(_this); _this._id = Utilities_1.getId('header'); return _this; } DetailsHeader.prototype.componentDidMount = function () { var selection = this.props.selection; this._events.on(selection, interfaces_1.SELECTION_CHANGE, this._onSelectionChanged); var rootElement = ReactDOM.findDOMNode(this._root); // We need to use native on this to avoid MarqueeSelection from handling the event before us. this._events.on(rootElement, 'mousedown', this._onRootMouseDown); this._events.on(rootElement, 'keydown', this._onRootKeyDown); }; DetailsHeader.prototype.componentWillReceiveProps = function (newProps) { var groupNestingDepth = this.state.groupNestingDepth; if (newProps.groupNestingDepth !== groupNestingDepth) { this.setState({ groupNestingDepth: newProps.groupNestingDepth }); } }; DetailsHeader.prototype.render = function () { var _this = this; var _a = this.props, columns = _a.columns, ariaLabel = _a.ariaLabel, ariaLabelForSelectAllCheckbox = _a.ariaLabelForSelectAllCheckbox, selectAllVisibility = _a.selectAllVisibility, ariaLabelForSelectionColumn = _a.ariaLabelForSelectionColumn; var _b = this.state, isAllSelected = _b.isAllSelected, columnResizeDetails = _b.columnResizeDetails, isSizing = _b.isSizing, groupNestingDepth = _b.groupNestingDepth, isAllCollapsed = _b.isAllCollapsed; var showCheckbox = selectAllVisibility !== SelectAllVisibility.none; var _c = this.props.onRenderColumnHeaderTooltip, onRenderColumnHeaderTooltip = _c === void 0 ? this._onRenderColumnHeaderTooltip : _c; return (React.createElement(FocusZone_1.FocusZone, { role: 'row', "aria-label": ariaLabel, className: Utilities_1.css('ms-DetailsHeader', styles.root, isAllSelected && ('is-allSelected ' + styles.rootIsAllSelected), (selectAllVisibility === SelectAllVisibility.hidden) && ('is-selectAllHidden ' + styles.rootIsSelectAllHidden), (!!columnResizeDetails && isSizing) && 'is-resizingColumn'), ref: this._resolveRef('_root'), onMouseMove: this._onRootMouseMove, "data-automationid": 'DetailsHeader', direction: FocusZone_1.FocusZoneDirection.horizontal }, showCheckbox ? ([ React.createElement("div", { key: '__checkbox', className: Utilities_1.css('ms-DetailsHeader-cell', 'ms-DetailsHeader-cellIsCheck', styles.cell, styles.cellIsCheck, checkStyles.owner, isAllSelected && checkStyles.isSelected), "aria-labelledby": this._id + "-check", onClick: this._onSelectAllClicked, "aria-colindex": 0, role: 'columnheader' }, onRenderColumnHeaderTooltip({ hostClassName: Utilities_1.css(styles.checkTooltip), id: this._id + "-checkTooltip", setAriaDescribedBy: false, content: ariaLabelForSelectAllCheckbox, children: (React.createElement(DetailsRowCheck_1.DetailsRowCheck, { id: this._id + "-check", "aria-label": ariaLabelForSelectionColumn, "aria-describedby": this._id + "-checkTooltip", "data-is-focusable": true, isHeader: true, selected: isAllSelected, anySelected: false, canSelect: true })) }, this._onRenderColumnHeaderTooltip)), ariaLabelForSelectAllCheckbox && !this.props.onRenderColumnHeaderTooltip ? (React.createElement("label", { key: '__checkboxLabel', id: this._id + "-checkTooltip", className: styles.accessibleLabel }, ariaLabelForSelectAllCheckbox)) : null ]) : null, groupNestingDepth > 0 && this.props.collapseAllVisibility === GroupedList_1.CollapseAllVisibility.visible ? (React.createElement("div", { className: Utilities_1.css('ms-DetailsHeader-cell', styles.cell), onClick: this._onToggleCollapseAll, "data-is-focusable": true }, React.createElement(Icon_1.Icon, { className: Utilities_1.css('ms-DetailsHeader-collapseButton', styles.collapseButton, isAllCollapsed && ('is-collapsed ' + styles.collapseButtonIsCollapsed)), iconName: 'ChevronDown' }))) : (null), GroupSpacer_1.GroupSpacer({ count: groupNestingDepth - 1 }), columns.map(function (column, columnIndex) { return ([ React.createElement("div", { key: column.key, role: 'columnheader', "aria-sort": column.isSorted ? (column.isSortedDescending ? 'descending' : 'ascending') : 'none', "aria-disabled": column.columnActionsMode === DetailsList_types_1.ColumnActionsMode.disabled, "aria-colindex": (showCheckbox ? 1 : 0) + columnIndex, className: Utilities_1.css('ms-DetailsHeader-cell', styles.cell, column.headerClassName, (column.columnActionsMode !== DetailsList_types_1.ColumnActionsMode.disabled) && ('is-actionable ' + styles.cellIsActionable), !column.name && ('is-empty ' + styles.cellIsEmpty), (column.isSorted || column.isGrouped || column.isFiltered) && 'is-icon-visible', column.isPadded && styles.cellWrapperPadded), style: { width: column.calculatedWidth + INNER_PADDING + (column.isPadded ? ISPADDED_WIDTH : 0) }, "data-automationid": 'ColumnsHeaderColumn', "data-item-key": column.key }, onRenderColumnHeaderTooltip({ hostClassName: Utilities_1.css(styles.cellTooltip), id: _this._id + "-" + column.key + "-tooltip", setAriaDescribedBy: false, content: column.columnActionsMode !== DetailsList_types_1.ColumnActionsMode.disabled ? column.ariaLabel : '', children: (React.createElement("span", { id: _this._id + "-" + column.key, "aria-label": column.isIconOnly ? column.name : undefined, "aria-labelledby": column.isIconOnly ? undefined : _this._id + "-" + column.key + "-name ", className: Utilities_1.css('ms-DetailsHeader-cellTitle', styles.cellTitle), "data-is-focusable": column.columnActionsMode !== DetailsList_types_1.ColumnActionsMode.disabled, role: column.columnActionsMode !== DetailsList_types_1.ColumnActionsMode.disabled ? 'button' : undefined, "aria-describedby": _this._id + "-" + column.key + "-tooltip", onContextMenu: _this._onColumnContextMenu.bind(_this, column), onClick: _this._onColumnClick.bind(_this, column), "aria-haspopup": column.columnActionsMode === DetailsList_types_1.ColumnActionsMode.hasDropdown }, React.createElement("span", { id: _this._id + "-" + column.key + "-name", className: Utilities_1.css('ms-DetailsHeader-cellName', styles.cellName, (_a = {}, _a[styles.iconOnlyHeader] = column.isIconOnly, _a)) }, (column.iconName || column.iconClassName) && (React.createElement(Icon_1.Icon, { className: Utilities_1.css(styles.nearIcon, column.iconClassName), iconName: column.iconName })), !column.isIconOnly ? column.name : undefined), column.isFiltered && (React.createElement(Icon_1.Icon, { className: styles.nearIcon, iconName: 'Filter' })), column.isSorted && (React.createElement(Icon_1.Icon, { className: Utilities_1.css(styles.nearIcon, styles.sortIcon), iconName: column.isSortedDescending ? 'SortDown' : 'SortUp' })), column.isGrouped && (React.createElement(Icon_1.Icon, { className: styles.nearIcon, iconName: 'GroupedDescending' })), column.columnActionsMode === DetailsList_types_1.ColumnActionsMode.hasDropdown && !column.isIconOnly && (React.createElement(Icon_1.Icon, { className: Utilities_1.css('ms-DetailsHeader-filterChevron', styles.filterChevron), iconName: 'ChevronDown' })))) }, _this._onRenderColumnHeaderTooltip)), column.ariaLabel && !_this.props.onRenderColumnHeaderTooltip ? (React.createElement("label", { key: column.key + "_label", id: _this._id + "-" + column.key + "-tooltip", className: styles.accessibleLabel }, column.ariaLabel)) : null, (column.isResizable) && _this._renderColumnSizer(columnIndex) ]); var _a; }), isSizing && (React.createElement(Layer_1.Layer, null, React.createElement("div", { className: Utilities_1.css(isSizing && styles.sizingOverlay), onMouseMove: this._onSizerMouseMove, onMouseUp: this._onSizerMouseUp }))))); }; /** Set focus to the active thing in the focus area. */ DetailsHeader.prototype.focus = function () { return this._root.focus(); }; DetailsHeader.prototype._renderColumnSizer = function (columnIndex) { var columns = this.props.columns; var column = this.props.columns[columnIndex]; var columnResizeDetails = this.state.columnResizeDetails; return (React.createElement("div", { key: column.key + "_sizer", "aria-hidden": true, role: 'button', "data-is-focusable": false, onClick: stopPropagation, "data-sizer-index": columnIndex, onBlur: this._onSizerBlur, className: Utilities_1.css('ms-DetailsHeader-cellSizer', styles.cellSizer, columnIndex < columns.length - 1 ? styles.cellSizerStart : styles.cellSizerEnd, (_a = {}, _a['is-resizing ' + styles.cellIsResizing] = columnResizeDetails && columnResizeDetails.columnIndex === columnIndex, _a)), onDoubleClick: this._onSizerDoubleClick.bind(this, columnIndex) })); var _a; }; DetailsHeader.prototype._onRenderColumnHeaderTooltip = function (tooltipHostProps, defaultRender) { return (React.createElement("span", { className: tooltipHostProps.hostClassName }, tooltipHostProps.children)); }; /** * double click on the column sizer will auto ajust column width * to fit the longest content among current rendered rows. * * @private * @param {number} columnIndex (index of the column user double clicked) * @param {React.MouseEvent} ev (mouse double click event) */ DetailsHeader.prototype._onSizerDoubleClick = function (columnIndex, ev) { var _a = this.props, onColumnAutoResized = _a.onColumnAutoResized, columns = _a.columns; if (onColumnAutoResized) { onColumnAutoResized(columns[columnIndex], columnIndex); } }; /** * Called when the select all toggle is clicked. */ DetailsHeader.prototype._onSelectAllClicked = function () { var selection = this.props.selection; selection.toggleAllSelected(); }; DetailsHeader.prototype._onRootMouseDown = function (ev) { var columnIndexAttr = ev.target.getAttribute('data-sizer-index'); var columnIndex = Number(columnIndexAttr); var columns = this.props.columns; if (columnIndexAttr === null || ev.button !== MOUSEDOWN_PRIMARY_BUTTON) { // Ignore anything except the primary button. return; } this.setState({ columnResizeDetails: { columnIndex: columnIndex, columnMinWidth: columns[columnIndex].calculatedWidth, originX: ev.clientX } }); ev.preventDefault(); ev.stopPropagation(); }; DetailsHeader.prototype._onRootMouseMove = function (ev) { var _a = this.state, columnResizeDetails = _a.columnResizeDetails, isSizing = _a.isSizing; if (columnResizeDetails && !isSizing && ev.clientX !== columnResizeDetails.originX) { this.setState({ isSizing: true }); } }; DetailsHeader.prototype._onRootKeyDown = function (ev) { var _a = this.state, columnResizeDetails = _a.columnResizeDetails, isSizing = _a.isSizing; var _b = this.props, columns = _b.columns, onColumnResized = _b.onColumnResized; var columnIndexAttr = ev.target.getAttribute('data-sizer-index'); if (!columnIndexAttr || isSizing) { return; } var columnIndex = Number(columnIndexAttr); if (!columnResizeDetails) { if (ev.which === 13 /* enter */) { this.setState({ columnResizeDetails: { columnIndex: columnIndex, columnMinWidth: columns[columnIndex].calculatedWidth } }); ev.preventDefault(); ev.stopPropagation(); } } else { var increment = void 0; if (ev.which === 13 /* enter */) { this.setState({ columnResizeDetails: undefined }); ev.preventDefault(); ev.stopPropagation(); } else if (ev.which === 37 /* left */) { increment = Utilities_1.getRTL() ? 1 : -1; } else if (ev.which === 39 /* right */) { increment = Utilities_1.getRTL() ? -1 : 1; } if (increment) { if (!ev.shiftKey) { increment *= 10; } this.setState({ columnResizeDetails: tslib_1.__assign({}, columnResizeDetails, { columnMinWidth: columnResizeDetails.columnMinWidth + increment }) }); if (onColumnResized) { onColumnResized(columns[columnIndex], columnResizeDetails.columnMinWidth + increment, columnIndex); } ev.preventDefault(); ev.stopPropagation(); } } }; /** * mouse move event handler in the header * it will set isSizing state to true when user clicked on the sizer and move the mouse. * * @private * @param {React.MouseEvent} ev (mouse move event) */ DetailsHeader.prototype._onSizerMouseMove = function (ev) { var // use buttons property here since ev.button in some edge case is not upding well during the move. // but firefox doesn't support it, so we set the default value when it is not defined. buttons = ev.buttons; var _a = this.props, onColumnIsSizingChanged = _a.onColumnIsSizingChanged, onColumnResized = _a.onColumnResized, columns = _a.columns; var columnResizeDetails = this.state.columnResizeDetails; if (buttons !== undefined && buttons !== MOUSEMOVE_PRIMARY_BUTTON) { // cancel mouse down event and return early when the primary button is not pressed this._onSizerMouseUp(ev); return; } if (ev.clientX !== columnResizeDetails.originX) { if (onColumnIsSizingChanged) { onColumnIsSizingChanged(columns[columnResizeDetails.columnIndex], true); } } if (onColumnResized) { var movement = ev.clientX - columnResizeDetails.originX; if (Utilities_1.getRTL()) { movement = -movement; } onColumnResized(columns[columnResizeDetails.columnIndex], columnResizeDetails.columnMinWidth + movement, columnResizeDetails.columnIndex); } }; DetailsHeader.prototype._onSizerBlur = function (ev) { var columnResizeDetails = this.state.columnResizeDetails; if (columnResizeDetails) { this.setState({ columnResizeDetails: undefined, isSizing: false }); } }; /** * mouse up event handler in the header * clear the resize related state. * This is to ensure we can catch double click event * * @private * @param {React.MouseEvent} ev (mouse up event) */ DetailsHeader.prototype._onSizerMouseUp = function (ev) { var _a = this.props, columns = _a.columns, onColumnIsSizingChanged = _a.onColumnIsSizingChanged; var columnResizeDetails = this.state.columnResizeDetails; this.setState({ columnResizeDetails: undefined, isSizing: false }); if (onColumnIsSizingChanged) { onColumnIsSizingChanged(columns[columnResizeDetails.columnIndex], false); } }; DetailsHeader.prototype._onSelectionChanged = function () { var isAllSelected = this.props.selection.isAllSelected(); if (this.state.isAllSelected !== isAllSelected) { this.setState({ isAllSelected: isAllSelected }); } }; DetailsHeader.prototype._onColumnClick = function (column, ev) { var onColumnClick = this.props.onColumnClick; if (column.onColumnClick) { column.onColumnClick(ev, column); } if (onColumnClick) { onColumnClick(ev, column); } }; DetailsHeader.prototype._onColumnContextMenu = function (column, ev) { var onColumnContextMenu = this.props.onColumnContextMenu; if (column.onColumnContextMenu) { column.onColumnContextMenu(column, ev); ev.preventDefault(); } if (onColumnContextMenu) { onColumnContextMenu(column, ev); ev.preventDefault(); } }; DetailsHeader.prototype._onToggleCollapseAll = function () { var onToggleCollapseAll = this.props.onToggleCollapseAll; var newCollapsed = !this.state.isAllCollapsed; this.setState({ isAllCollapsed: newCollapsed }); if (onToggleCollapseAll) { onToggleCollapseAll(newCollapsed); } }; DetailsHeader.defaultProps = { selectAllVisibility: SelectAllVisibility.visible, collapseAllVisibility: GroupedList_1.CollapseAllVisibility.visible }; tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onRenderColumnHeaderTooltip", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onSelectAllClicked", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onRootMouseDown", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onRootMouseMove", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onRootKeyDown", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onSizerMouseMove", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onSizerBlur", null); tslib_1.__decorate([ Utilities_1.autobind ], DetailsHeader.prototype, "_onSizerMouseUp", null); return DetailsHeader; }(Utilities_1.BaseComponent)); exports.DetailsHeader = DetailsHeader; function stopPropagation(ev) { ev.stopPropagation(); } }); //# sourceMappingURL=DetailsHeader.js.map