office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
1 lines • 17.7 kB
JavaScript
module.exports = "import * as React from 'react';\nimport {\n CheckboxVisibility,\n ColumnActionsMode,\n CommandBar,\n ConstrainMode,\n ContextualMenu,\n DetailsList,\n DetailsListLayoutMode as LayoutMode,\n DirectionalHint,\n IColumn,\n IContextualMenuItem,\n IContextualMenuProps,\n IGroup,\n Link,\n Selection,\n TextField,\n autobind,\n buildColumns\n} from '../../../../index';\nimport { SelectionMode } from '../../../../utilities/selection/interfaces';\nimport { createListItems, isGroupable } from '../../../utilities/data';\nimport './DetailsList.Advanced.Example.scss';\n\nconst DEFAULT_ITEM_LIMIT = 5;\nconst PAGING_SIZE = 10;\nconst PAGING_DELAY = 5000;\nconst ITEMS_COUNT = 5000;\n\nlet _items;\n\nexport interface IDetailsListAdvancedExampleState {\n canResizeColumns?: boolean;\n checkboxVisibility?: CheckboxVisibility;\n columns?: IColumn[];\n constrainMode?: ConstrainMode;\n contextualMenuProps?: IContextualMenuProps;\n groupItemLimit?: number;\n groups?: IGroup[];\n isHeaderVisible?: boolean;\n isLazyLoaded?: boolean;\n isSortedDescending?: boolean;\n items?: any[];\n layoutMode?: LayoutMode;\n selectionMode?: SelectionMode;\n sortedColumnKey?: string;\n}\n\nexport class DetailsListAdvancedExample extends React.Component<any, IDetailsListAdvancedExampleState> {\n public refs: {\n [key: string]: React.ReactInstance;\n list: DetailsList\n };\n\n private _isFetchingItems: boolean;\n private _selection: Selection;\n\n constructor() {\n super();\n\n if (!_items) {\n _items = createListItems(ITEMS_COUNT);\n }\n\n this._selection = new Selection();\n this._selection.setItems(_items, false);\n\n this.state = {\n items: _items,\n groups: null,\n groupItemLimit: DEFAULT_ITEM_LIMIT,\n layoutMode: LayoutMode.justified,\n constrainMode: ConstrainMode.horizontalConstrained,\n selectionMode: SelectionMode.multiple,\n canResizeColumns: true,\n checkboxVisibility: CheckboxVisibility.onHover,\n columns: this._buildColumns(_items, true, this._onColumnClick, ''),\n contextualMenuProps: null,\n sortedColumnKey: 'name',\n isSortedDescending: false,\n isLazyLoaded: false,\n isHeaderVisible: true\n };\n }\n\n public render() {\n let {\n checkboxVisibility,\n columns,\n constrainMode,\n contextualMenuProps,\n groupItemLimit,\n groups,\n isHeaderVisible,\n items,\n layoutMode,\n selectionMode\n } = this.state;\n\n let isGrouped = groups && groups.length > 0;\n let groupProps = {\n getGroupItemLimit: (group: IGroup) => {\n if (group) {\n return group.isShowingAll ? group.count : Math.min(group.count, groupItemLimit);\n } else {\n return items.length;\n }\n },\n footerProps: {\n showAllLinkText: 'Show all'\n }\n };\n\n return (\n <div className='ms-DetailsListAdvancedExample'>\n <CommandBar items={ this._getCommandItems() } />\n\n {\n (isGrouped) ?\n <TextField label='Group Item Limit' onChanged={ this._onItemLimitChanged } /> :\n (null)\n }\n\n <DetailsList\n ref='list'\n setKey='items'\n items={ items }\n groups={ groups }\n columns={ columns }\n checkboxVisibility={ checkboxVisibility }\n layoutMode={ layoutMode }\n isHeaderVisible={ isHeaderVisible }\n selectionMode={ selectionMode }\n constrainMode={ constrainMode }\n groupProps={ groupProps }\n onItemInvoked={ this._onItemInvoked }\n ariaLabelForListHeader='Column headers. Use menus to perform column operations like sort and filter'\n ariaLabelForSelectAllCheckbox='Toggle selection for all items'\n onRenderMissingItem={ (index) => {\n this._onDataMiss(index);\n return null;\n } }\n />\n\n { contextualMenuProps && (\n <ContextualMenu { ...contextualMenuProps } />\n ) }\n </div>\n );\n }\n\n private _onDataMiss(index) {\n index = Math.floor(index / PAGING_SIZE) * PAGING_SIZE;\n\n if (!this._isFetchingItems) {\n\n this._isFetchingItems = true;\n\n setTimeout(() => {\n this._isFetchingItems = false;\n let itemsCopy = [].concat(this.state.items);\n\n itemsCopy.splice.apply(itemsCopy, [index, PAGING_SIZE].concat(_items.slice(index, index + PAGING_SIZE)));\n\n this.setState({\n items: itemsCopy\n });\n }, PAGING_DELAY);\n }\n }\n\n @autobind\n private _onToggleLazyLoad() {\n let { isLazyLoaded } = this.state;\n\n isLazyLoaded = !isLazyLoaded;\n\n this.setState({\n isLazyLoaded: isLazyLoaded,\n items: isLazyLoaded ? _items.slice(0, PAGING_SIZE).concat(new Array(ITEMS_COUNT - PAGING_SIZE)) : _items\n });\n }\n\n @autobind\n private _onToggleResizing() {\n let { items, canResizeColumns, sortedColumnKey, isSortedDescending } = this.state;\n\n canResizeColumns = !canResizeColumns;\n\n this.setState({\n canResizeColumns: canResizeColumns,\n columns: this._buildColumns(items, canResizeColumns, this._onColumnClick, sortedColumnKey, isSortedDescending)\n });\n }\n\n @autobind\n private _onLayoutChanged(ev: React.MouseEvent<HTMLElement>, menuItem: IContextualMenuItem) {\n this.setState({\n layoutMode: menuItem.data\n });\n }\n\n @autobind\n private _onConstrainModeChanged(ev: React.MouseEvent<HTMLElement>, menuItem: IContextualMenuItem) {\n this.setState({\n constrainMode: menuItem.data\n });\n }\n\n @autobind\n private _onSelectionChanged(ev: React.MouseEvent<HTMLElement>, menuItem: IContextualMenuItem) {\n this.setState({\n selectionMode: menuItem.data\n });\n }\n\n @autobind\n private _onItemLimitChanged(value: string) {\n let newValue = parseInt(value, 10);\n if (isNaN(newValue)) {\n newValue = DEFAULT_ITEM_LIMIT;\n }\n this.setState({\n groupItemLimit: newValue\n });\n }\n\n private _getCommandItems(): IContextualMenuItem[] {\n let {\n canResizeColumns,\n checkboxVisibility,\n constrainMode,\n isHeaderVisible,\n isLazyLoaded,\n layoutMode,\n selectionMode\n } = this.state;\n\n return [\n {\n key: 'addRow',\n name: 'Insert row',\n icon: 'Add',\n onClick: this._onAddRow\n },\n {\n key: 'deleteRow',\n name: 'Delete row',\n icon: 'Delete',\n onClick: this._onDeleteRow\n },\n {\n key: 'configure',\n name: 'Configure',\n icon: 'Settings',\n items: [\n {\n key: 'resizing',\n name: 'Allow column resizing',\n canCheck: true,\n isChecked: canResizeColumns,\n onClick: this._onToggleResizing\n },\n {\n key: 'headerVisible',\n name: 'Is header visible',\n canCheck: true,\n isChecked: isHeaderVisible,\n onClick: () => this.setState({ isHeaderVisible: !isHeaderVisible })\n },\n {\n key: 'lazyload',\n name: 'Simulate async loading',\n canCheck: true,\n isChecked: isLazyLoaded,\n onClick: this._onToggleLazyLoad\n },\n {\n key: 'dash',\n name: '-'\n },\n {\n key: 'checkboxVisibility',\n name: 'Checkbox visibility',\n items: [\n {\n key: 'checkboxVisibility.always',\n name: 'Always',\n canCheck: true,\n isChecked: checkboxVisibility === CheckboxVisibility.always,\n onClick: () => this.setState({ checkboxVisibility: CheckboxVisibility.always })\n },\n {\n key: 'checkboxVisibility.onHover',\n name: 'On hover',\n canCheck: true,\n isChecked: checkboxVisibility === CheckboxVisibility.onHover,\n onClick: () => this.setState({ checkboxVisibility: CheckboxVisibility.onHover })\n },\n {\n key: 'checkboxVisibility.hidden',\n name: 'Hidden',\n canCheck: true,\n isChecked: checkboxVisibility === CheckboxVisibility.hidden,\n onClick: () => this.setState({ checkboxVisibility: CheckboxVisibility.hidden })\n },\n ]\n },\n {\n key: 'layoutMode',\n name: 'Layout mode',\n items: [\n {\n key: LayoutMode[LayoutMode.fixedColumns],\n name: 'Fixed columns',\n canCheck: true,\n isChecked: layoutMode === LayoutMode.fixedColumns,\n onClick: this._onLayoutChanged,\n data: LayoutMode.fixedColumns\n },\n {\n key: LayoutMode[LayoutMode.justified],\n name: 'Justified columns',\n canCheck: true,\n isChecked: layoutMode === LayoutMode.justified,\n onClick: this._onLayoutChanged,\n data: LayoutMode.justified\n }\n ]\n },\n {\n key: 'selectionMode',\n name: 'Selection mode',\n items: [\n {\n key: SelectionMode[SelectionMode.none],\n name: 'None',\n canCheck: true,\n isChecked: selectionMode === SelectionMode.none,\n onClick: this._onSelectionChanged,\n data: SelectionMode.none\n\n },\n {\n key: SelectionMode[SelectionMode.single],\n name: 'Single select',\n canCheck: true,\n isChecked: selectionMode === SelectionMode.single,\n onClick: this._onSelectionChanged,\n data: SelectionMode.single\n },\n {\n key: SelectionMode[SelectionMode.multiple],\n name: 'Multi select',\n canCheck: true,\n isChecked: selectionMode === SelectionMode.multiple,\n onClick: this._onSelectionChanged,\n data: SelectionMode.multiple\n },\n ]\n },\n {\n key: 'constrainMode',\n name: 'Constrain mode',\n items: [\n {\n key: ConstrainMode[ConstrainMode.unconstrained],\n name: 'Unconstrained',\n canCheck: true,\n isChecked: constrainMode === ConstrainMode.unconstrained,\n onClick: this._onConstrainModeChanged,\n data: ConstrainMode.unconstrained\n },\n {\n key: ConstrainMode[ConstrainMode.horizontalConstrained],\n name: 'Horizontal constrained',\n canCheck: true,\n isChecked: constrainMode === ConstrainMode.horizontalConstrained,\n onClick: this._onConstrainModeChanged,\n data: ConstrainMode.horizontalConstrained\n }\n ]\n }\n ]\n }\n ];\n }\n\n private _getContextualMenuProps(ev: React.MouseEvent<HTMLElement>, column: IColumn): IContextualMenuProps {\n let items = [\n {\n key: 'aToZ',\n name: 'A to Z',\n icon: 'SortUp',\n canCheck: true,\n isChecked: column.isSorted && !column.isSortedDescending,\n onClick: () => this._onSortColumn(column.key, false)\n },\n {\n key: 'zToA',\n name: 'Z to A',\n icon: 'SortDown',\n canCheck: true,\n isChecked: column.isSorted && column.isSortedDescending,\n onClick: () => this._onSortColumn(column.key, true)\n }\n ];\n if (isGroupable(column.key)) {\n items.push({\n key: 'groupBy',\n name: 'Group By ' + column.name,\n icon: 'GroupedDescending',\n canCheck: true,\n isChecked: column.isGrouped,\n onClick: () => this._onGroupByColumn(column)\n });\n }\n return {\n items: items,\n targetElement: ev.currentTarget as HTMLElement,\n directionalHint: DirectionalHint.bottomLeftEdge,\n gapSpace: 10,\n isBeakVisible: true,\n onDismiss: this._onContextualMenuDismissed\n };\n }\n\n @autobind\n private _onItemInvoked(item: any, index: number) {\n console.log('Item invoked', item, index);\n }\n\n @autobind\n private _onColumnClick(ev: React.MouseEvent<HTMLElement>, column: IColumn) {\n this.setState({\n contextualMenuProps: this._getContextualMenuProps(ev, column)\n });\n }\n\n @autobind\n private _onContextualMenuDismissed() {\n this.setState({\n contextualMenuProps: null\n });\n }\n\n @autobind\n private _onSortColumn(key: string, isSortedDescending: boolean) {\n let sortedItems = _items.slice(0).sort((a, b) => (isSortedDescending ? a[key] < b[key] : a[key] > b[key]) ? 1 : -1);\n\n this.setState({\n items: sortedItems,\n groups: null,\n columns: this._buildColumns(sortedItems, true, this._onColumnClick, key, isSortedDescending),\n isSortedDescending: isSortedDescending,\n sortedColumnKey: key\n });\n }\n\n @autobind\n private _onGroupByColumn(column: IColumn) {\n let { key, isGrouped } = column;\n let { sortedColumnKey, isSortedDescending, groups, items, columns } = this.state;\n\n if (isGrouped) { // ungroup\n this._onSortColumn(sortedColumnKey, isSortedDescending);\n } else {\n let groupedItems = [];\n let newGroups = null;\n if (groups) {\n newGroups = groups.concat([]);\n groupedItems = this._groupByKey(newGroups, items, key);\n } else {\n groupedItems = this._groupItems(items, key);\n newGroups = this._getGroups(groupedItems, key);\n }\n\n let newColumns = columns;\n newColumns.filter(matchColumn => matchColumn.key === key).forEach((groupedColumn: IColumn) => {\n groupedColumn.isGrouped = true;\n });\n this.setState({\n items: groupedItems,\n columns: newColumns,\n groups: newGroups\n });\n }\n }\n\n private _groupByKey(groups: IGroup[], items: any[], key: string): any[] {\n let groupedItems = [];\n if (groups) {\n groups.forEach((group: IGroup) => {\n if (group.children && group.children.length > 0) {\n let childGroupedItems = this._groupByKey(group.children, items, key);\n groupedItems = groupedItems.concat(childGroupedItems);\n } else {\n let itemsInGroup = items.slice(group.startIndex, group.startIndex + group.count);\n let nextLevelGroupedItems = this._groupItems(itemsInGroup, key);\n groupedItems = groupedItems.concat(nextLevelGroupedItems);\n group.children = this._getGroups(nextLevelGroupedItems, key, group);\n }\n });\n }\n return groupedItems;\n }\n\n private _groupItems(items: any[], columnKey: string): any[] {\n return items.slice(0).sort((a, b) => ((a[columnKey] < b[columnKey]) ? -1 : 1));\n }\n\n private _getGroups(groupedItems: any[], key: string, parentGroup?: IGroup): IGroup[] {\n let separator = '-';\n let groups = groupedItems.reduce((current, item, index) => {\n let currentGroup = current[current.length - 1];\n\n if (!currentGroup || (this._getLeafGroupKey(currentGroup.key, separator) !== item[key])) {\n current.push({\n key: (parentGroup ? parentGroup.key + separator : '') + item[key],\n name: key + ': ' + item[key],\n startIndex: parentGroup ? parentGroup.startIndex + index : index,\n count: 1,\n level: parentGroup ? parentGroup.level + 1 : 0\n });\n } else {\n currentGroup.count++;\n }\n return current;\n }, []);\n\n return groups;\n }\n\n private _getLeafGroupKey(key: string, separator: string): string {\n let leafKey = key;\n if (key.indexOf(separator) !== -1) {\n let arrKeys = key.split(separator);\n leafKey = arrKeys[arrKeys.length - 1];\n }\n return leafKey;\n }\n\n @autobind\n private _onAddRow() {\n this.setState({\n items: createListItems(1).concat(this.state.items)\n });\n }\n\n @autobind\n private _onDeleteRow() {\n this.setState({\n items: this.state.items.slice(1)\n });\n }\n\n private _buildColumns(\n items: any[],\n canResizeColumns?: boolean,\n onColumnClick?: (ev: React.MouseEvent<HTMLElement>, column: IColumn) => any,\n sortedColumnKey?: string,\n isSortedDescending?: boolean,\n groupedColumnKey?: string) {\n let columns = buildColumns(items, canResizeColumns, onColumnClick, sortedColumnKey, isSortedDescending, groupedColumnKey);\n\n columns.forEach(column => {\n if (column.key === 'description') {\n column.isMultiline = true;\n column.minWidth = 200;\n } else if (column.key === 'name') {\n column.onRender = (item) => (\n <Link>{ item.name }</Link>\n );\n } else if (column.key === 'key') {\n column.columnActionsMode = ColumnActionsMode.disabled;\n column.onRender = (item) => (\n <Link href='#'>{ item.key }</Link>\n );\n column.minWidth = 90;\n column.maxWidth = 90;\n }\n });\n\n return columns;\n }\n}\n";