@fluentui/react
Version:
Reusable React components for building web experiences.
397 lines • 19.5 kB
JavaScript
var _this = this;
import { __assign, __extends } from "tslib";
import * as React from 'react';
import { initializeComponentRef, classNamesFunction, KeyCodes, getRTLSafeKeyCode, css, getId, EventGroup, } from '../../Utilities';
import { List } from '../../List';
import { SelectionMode, SELECTION_CHANGE } from '../../Selection';
import { FocusZone, FocusZoneDirection } from '../../FocusZone';
import { GroupHeader } from './GroupHeader';
import { GroupShowAll } from './GroupShowAll';
import { GroupFooter } from './GroupFooter';
var flattenItems = function (groups, items, memoItems, getGroupItemLimit) {
if (!groups) {
return items;
}
if (memoItems.length < 1) {
// Not the exact final size but gets us in the ballpark.
// This helps avoid trashing memory when building
// the flattened list.
memoItems = new Array(items.length);
}
var index = 0;
var stack = [];
var j = groups.length - 1;
while (j >= 0) {
stack.push({ group: groups[j], groupIndex: j + 1 });
j--;
}
while (stack.length > 0) {
// eslint-disable-next-line prefer-const
var _a = stack.pop(), group = _a.group, groupIndex = _a.groupIndex;
memoItems[index] = {
group: group,
groupId: getId('GroupedListSection'),
type: 'header',
groupIndex: groupIndex,
};
index++;
while (group.isCollapsed !== true && (group === null || group === void 0 ? void 0 : group.children) && group.children.length > 0) {
j = group.children.length - 1;
while (j > 0) {
stack.push({ group: group.children[j], groupIndex: j + 1 });
j--;
}
group = group.children[0];
memoItems[index] = {
group: group,
groupId: getId('GroupedListSection'),
type: 'header',
groupIndex: 1,
};
index++;
}
if (group.isCollapsed !== true) {
var itemIndex = group.startIndex;
var renderCount = getGroupItemLimit ? getGroupItemLimit(group) : Infinity;
var count = !group.isShowingAll ? group.count : items.length;
var itemEnd = itemIndex + Math.min(count, renderCount);
while (itemIndex < itemEnd) {
memoItems[index] = {
group: group,
item: items[itemIndex],
itemIndex: itemIndex,
type: 'item',
};
itemIndex++;
index++;
}
var isShowAllVisible = !group.children &&
!group.isCollapsed &&
!group.isShowingAll &&
(group.count > renderCount || group.hasMoreData);
if (isShowAllVisible) {
memoItems[index] = {
group: group,
type: 'showAll',
};
index++;
}
}
// Placeholder for a potential footer.
// Whether or not a footer is displayed is resolved
// by the footer render function so this is just a marker
// for where a footer may go.
memoItems[index] = {
group: group,
type: 'footer',
};
index++;
}
memoItems.length = index;
// console.log('MEMO ITEMS', memoItems);
return memoItems;
};
var useIsGroupSelected = function (startIndex, count, selection, eventGroup) {
var _a = React.useState(function () { var _a; return (_a = selection === null || selection === void 0 ? void 0 : selection.isRangeSelected(startIndex, count)) !== null && _a !== void 0 ? _a : false; }), isSelected = _a[0], setIsSelected = _a[1];
React.useEffect(function () {
if (selection && eventGroup) {
var changeHandler_1 = function () {
var _a;
setIsSelected((_a = selection === null || selection === void 0 ? void 0 : selection.isRangeSelected(startIndex, count)) !== null && _a !== void 0 ? _a : false);
};
eventGroup.on(selection, SELECTION_CHANGE, changeHandler_1);
return function () {
eventGroup === null || eventGroup === void 0 ? void 0 : eventGroup.off(selection, SELECTION_CHANGE, changeHandler_1);
};
}
}, [startIndex, count, selection, eventGroup]);
return isSelected;
};
var computeIsSomeGroupExpanded = function (groups) {
return !!(groups && groups.some(function (group) { return (group.children ? computeIsSomeGroupExpanded(group.children) : !group.isCollapsed); }));
};
var setGroupsCollapsedState = function (groups, isCollapsed) {
if (groups === undefined) {
return;
}
for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {
groups[groupIndex].isCollapsed = isCollapsed;
}
};
var isInnerZoneKeystroke = function (ev) {
// eslint-disable-next-line deprecation/deprecation
return ev.which === getRTLSafeKeyCode(KeyCodes.right);
};
var getClassNames = classNamesFunction();
var getKey = function (item, _index) {
var _a, _b;
switch (item.type) {
case 'item':
return (_b = (_a = item.item) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
case 'header':
return item.group.key;
case 'footer':
return "".concat(item.group.key, "-footer");
case 'showAll':
return "".concat(item.group.key, "-showAll");
}
return null;
};
var renderGroupHeader = function (props) {
return React.createElement(GroupHeader, __assign({}, props));
};
var renderGroupShowAll = function (props) {
return React.createElement(GroupShowAll, __assign({}, props));
};
var renderGroupFooter = function (props) {
if (props.group && props.footerText) {
return React.createElement(GroupFooter, __assign({}, props));
}
return null;
};
export var GroupedListV2FC = function (props) {
var selection = props.selection, _a = props.selectionMode, selectionMode = _a === void 0 ? SelectionMode.multiple : _a, _b = props.groupProps, groupProps = _b === void 0 ? {} : _b, _c = props.compact, compact = _c === void 0 ? false : _c, _d = props.items, items = _d === void 0 ? [] : _d, groups = props.groups, onGroupExpandStateChanged = props.onGroupExpandStateChanged, listProps = props.listProps, className = props.className, usePageCache = props.usePageCache, onShouldVirtualize = props.onShouldVirtualize, theme = props.theme, _e = props.role, role = _e === void 0 ? 'treegrid' : _e, styles = props.styles, _f = props.focusZoneProps, focusZoneProps = _f === void 0 ? {} : _f, _g = props.rootListProps, rootListProps = _g === void 0 ? {} : _g, onRenderCell = props.onRenderCell, viewport = props.viewport, groupedListRef = props.groupedListRef, groupExpandedVersion = props.groupExpandedVersion, versionFromProps = props.version;
var _h = groupProps.onRenderHeader, onRenderHeader = _h === void 0 ? renderGroupHeader : _h, _j = groupProps.onRenderFooter, onRenderFooter = _j === void 0 ? renderGroupFooter : _j, _k = groupProps.onRenderShowAll, onRenderShowAll = _k === void 0 ? renderGroupShowAll : _k;
var classNames = getClassNames(styles, {
theme: theme,
className: className,
compact: compact,
});
var events = React.useRef();
var flatList = React.useRef([]);
var isSomeGroupExpanded = React.useRef(computeIsSomeGroupExpanded(groups));
var listRef = React.useRef(null);
var _l = React.useState({}), version = _l[0], setVersion = _l[1];
var _m = React.useState({}), toggleVersion = _m[0], setToggleVersion = _m[1];
// eslint-disable-next-line deprecation/deprecation
var _o = focusZoneProps.shouldEnterInnerZone, shouldEnterInnerZone = _o === void 0 ? isInnerZoneKeystroke : _o;
var listView = React.useMemo(function () {
return flattenItems(groups, items, flatList.current, groupProps === null || groupProps === void 0 ? void 0 : groupProps.getGroupItemLimit);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [groups, groupProps === null || groupProps === void 0 ? void 0 : groupProps.getGroupItemLimit, items, toggleVersion, flatList, groupExpandedVersion]);
var getPageSpecification = React.useCallback(function (flattenedIndex) {
var pageGroup = listView[flattenedIndex];
return {
key: pageGroup.type === 'header' ? pageGroup.group.key : undefined,
};
}, [listView]);
React.useImperativeHandle(groupedListRef, function () {
var indexMap;
return {
scrollToIndex: function (index, measureItem, scrollToMode) {
var _a;
indexMap =
indexMap !== null && indexMap !== void 0 ? indexMap : listView.reduce(function (map, item, listIndex) {
if (item.type === 'item') {
map[item.itemIndex] = listIndex;
}
return map;
}, []);
var scrollIndex = indexMap[index];
var measure = typeof measureItem === 'function'
? function (itemIndex) {
var _a;
if (((_a = listView[itemIndex]) === null || _a === void 0 ? void 0 : _a.type) === 'item') {
return measureItem(listView[itemIndex].itemIndex);
}
return 0;
}
: undefined;
(_a = listRef.current) === null || _a === void 0 ? void 0 : _a.scrollToIndex(scrollIndex, measure, scrollToMode);
},
getStartItemIndexInView: function () {
var _a;
return ((_a = listRef.current) === null || _a === void 0 ? void 0 : _a.getStartItemIndexInView()) || 0;
},
};
}, [listView, listRef]);
React.useEffect(function () {
if (groupProps === null || groupProps === void 0 ? void 0 : groupProps.isAllGroupsCollapsed) {
setGroupsCollapsedState(groups, groupProps.isAllGroupsCollapsed);
}
events.current = new EventGroup(_this);
return function () {
var _a;
(_a = events.current) === null || _a === void 0 ? void 0 : _a.dispose();
events.current = undefined;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(function () {
setVersion({});
}, [versionFromProps]);
React.useEffect(function () {
var newIsSomeGroupExpanded = computeIsSomeGroupExpanded(groups);
if (newIsSomeGroupExpanded !== isSomeGroupExpanded.current) {
isSomeGroupExpanded.current = newIsSomeGroupExpanded;
onGroupExpandStateChanged === null || onGroupExpandStateChanged === void 0 ? void 0 : onGroupExpandStateChanged(newIsSomeGroupExpanded);
}
}, [groups, toggleVersion, onGroupExpandStateChanged, groupExpandedVersion]);
var onToggleCollapse = React.useCallback(function (group) {
var _a;
var onToggleCollapseFn = (_a = groupProps === null || groupProps === void 0 ? void 0 : groupProps.headerProps) === null || _a === void 0 ? void 0 : _a.onToggleCollapse;
if (group) {
onToggleCollapseFn === null || onToggleCollapseFn === void 0 ? void 0 : onToggleCollapseFn(group);
group.isCollapsed = !group.isCollapsed;
setToggleVersion({});
setVersion({});
}
}, [setToggleVersion, groupProps]);
var onToggleSelectGroup = function (group) {
if (group && selection && selectionMode === SelectionMode.multiple) {
selection.toggleRangeSelected(group.startIndex, group.count);
}
};
var onToggleSummarize = function (group) {
var _a;
var onToggleSummarizeFn = (_a = groupProps === null || groupProps === void 0 ? void 0 : groupProps.showAllProps) === null || _a === void 0 ? void 0 : _a.onToggleSummarize;
if (onToggleSummarizeFn) {
onToggleSummarizeFn(group);
}
else {
if (group) {
group.isShowingAll = !group.isShowingAll;
}
setVersion({});
setToggleVersion({});
}
};
var getDividerProps = function (group, flattenedIndex) {
var _a;
var dividerProps = {
group: group,
groupIndex: flattenedIndex,
groupLevel: (_a = group.level) !== null && _a !== void 0 ? _a : 0,
viewport: viewport,
selectionMode: selectionMode,
groups: groups,
compact: compact,
onToggleSelectGroup: onToggleSelectGroup,
onToggleCollapse: onToggleCollapse,
onToggleSummarize: onToggleSummarize,
};
return dividerProps;
};
var renderHeader = function (item, flattenedIndex) {
var group = item.group;
var ariaProps;
if (role === 'treegrid') {
// GroupedList default role
ariaProps = {
ariaLevel: group.level ? group.level + 1 : 1,
ariaSetSize: groups ? groups.length : undefined,
ariaPosInSet: item.groupIndex,
};
}
else {
// Grouped DetailsList
ariaProps = {
ariaRowIndex: flattenedIndex,
};
}
var headerProps = __assign(__assign(__assign(__assign({}, groupProps.headerProps), getDividerProps(item.group, flattenedIndex)), { key: group.key, groupedListId: item.groupId }), ariaProps);
return (React.createElement(GroupItem, { render: onRenderHeader, defaultRender: renderGroupHeader, item: item, selection: selection, eventGroup: events.current, props: headerProps }));
};
var renderShowAll = function (item, flattenedIndex) {
var group = item.group;
var groupShowAllProps = __assign(__assign(__assign({}, groupProps.showAllProps), getDividerProps(group, flattenedIndex)), { key: group.key ? "".concat(group.key, "-show-all") : undefined });
return onRenderShowAll(groupShowAllProps, renderGroupShowAll);
};
var renderFooter = function (item, flattenedIndex) {
var group = item.group;
var groupFooterProps = __assign(__assign(__assign({}, groupProps.footerProps), getDividerProps(group, flattenedIndex)), { key: group.key ? "".concat(group.key, "-footer") : undefined });
return onRenderFooter(groupFooterProps, renderGroupFooter);
};
var renderItem = function (item, flattenedIndex) {
var _a;
if (item.type === 'header') {
return renderHeader(item, flattenedIndex);
}
else if (item.type === 'showAll') {
return renderShowAll(item, flattenedIndex);
}
else if (item.type === 'footer') {
return renderFooter(item, flattenedIndex);
}
else {
var level = item.group.level ? item.group.level + 1 : 1;
return onRenderCell(level, item.item, (_a = item.itemIndex) !== null && _a !== void 0 ? _a : flattenedIndex, item.group);
}
};
return (React.createElement(FocusZone, __assign({ direction: FocusZoneDirection.vertical, "data-automationid": "GroupedList", "data-is-scrollable": "false", role: "presentation" }, focusZoneProps, { shouldEnterInnerZone: shouldEnterInnerZone, className: css(classNames.root, focusZoneProps.className) }),
React.createElement(List, __assign({ ref: listRef, role: role, items: listView,
// eslint-disable-next-line
onRenderCellConditional: renderItem, usePageCache: usePageCache, onShouldVirtualize: onShouldVirtualize, getPageSpecification: getPageSpecification, version: version, getKey: getKey }, listProps, rootListProps))));
};
var GroupItem = function (_a) {
var render = _a.render, defaultRender = _a.defaultRender, item = _a.item, selection = _a.selection, eventGroup = _a.eventGroup, props = _a.props;
var group = item.group;
var isSelected = useIsGroupSelected(group.startIndex, group.count, selection, eventGroup);
var mergedProps = __assign(__assign({}, props), { isSelected: isSelected, selected: isSelected });
return render(mergedProps, defaultRender);
};
export var GroupedListV2Wrapper = /** @class */ (function (_super) {
__extends(GroupedListV2Wrapper, _super);
function GroupedListV2Wrapper(props) {
var _a, _b, _c;
var _this = _super.call(this, props) || this;
_this._groupedList = React.createRef();
initializeComponentRef(_this);
var version = (_a = props.listProps, _b = _a === void 0 ? {} : _a, _c = _b.version, _c === void 0 ? {} : _c), groups = props.groups;
_this.state = {
version: version,
groupExpandedVersion: {},
groups: groups,
};
return _this;
}
GroupedListV2Wrapper.getDerivedStateFromProps = function (nextProps, previousState) {
var groups = nextProps.groups, selectionMode = nextProps.selectionMode, compact = nextProps.compact, items = nextProps.items, listProps = nextProps.listProps;
var nextListVersion = listProps && listProps.version;
var nextState = __assign(__assign({}, previousState), { groups: groups });
if (nextListVersion !== previousState.version ||
items !== previousState.items ||
groups !== previousState.groups ||
selectionMode !== previousState.selectionMode ||
compact !== previousState.compact) {
nextState.version = {};
}
return nextState;
};
GroupedListV2Wrapper.prototype.scrollToIndex = function (index, measureItem, scrollToMode) {
var _a;
(_a = this._groupedList.current) === null || _a === void 0 ? void 0 : _a.scrollToIndex(index, measureItem, scrollToMode);
};
GroupedListV2Wrapper.prototype.getStartItemIndexInView = function () {
var _a;
return ((_a = this._groupedList.current) === null || _a === void 0 ? void 0 : _a.getStartItemIndexInView()) || 0;
};
GroupedListV2Wrapper.prototype.render = function () {
return React.createElement(GroupedListV2FC, __assign({}, this.props, this.state, { groupedListRef: this._groupedList }));
};
GroupedListV2Wrapper.prototype.forceUpdate = function () {
_super.prototype.forceUpdate.call(this);
this._forceListUpdate();
};
GroupedListV2Wrapper.prototype.toggleCollapseAll = function (allCollapsed) {
var _a;
var groups = this.state.groups;
var groupProps = this.props.groupProps;
if (groups && groups.length > 0) {
(_a = groupProps === null || groupProps === void 0 ? void 0 : groupProps.onToggleCollapseAll) === null || _a === void 0 ? void 0 : _a.call(groupProps, allCollapsed);
setGroupsCollapsedState(groups, allCollapsed);
this.setState({
groupExpandedVersion: {},
});
this.forceUpdate();
}
};
GroupedListV2Wrapper.prototype._forceListUpdate = function () {
this.setState({
version: {},
});
};
GroupedListV2Wrapper.displayName = 'GroupedListV2';
return GroupedListV2Wrapper;
}(React.Component));
//# sourceMappingURL=GroupedListV2.base.js.map