import * as React from 'react';
import { TextField } from '@fluentui/react/lib/TextField';
import { Toggle } from '@fluentui/react/lib/Toggle';
import { Announced } from '@fluentui/react/lib/Announced';
import { DetailsList, DetailsListLayoutMode, Selection, SelectionMode, IColumn } from '@fluentui/react/lib/DetailsList';
import { MarqueeSelection } from '@fluentui/react/lib/MarqueeSelection';
import { mergeStyleSets } from '@fluentui/react/lib/Styling';
import { TooltipHost } from '@fluentui/react';
const classNames = mergeStyleSets({
fileIconHeaderIcon: {
padding: 0,
fontSize: '16px',
},
fileIconCell: {
textAlign: 'center',
selectors: {
'&:before': {
content: '.',
display: 'inline-block',
verticalAlign: 'middle',
height: '100%',
width: '0px',
visibility: 'hidden',
},
},
},
fileIconImg: {
verticalAlign: 'middle',
maxHeight: '16px',
maxWidth: '16px',
},
controlWrapper: {
display: 'flex',
flexWrap: 'wrap',
},
exampleToggle: {
display: 'inline-block',
marginBottom: '10px',
marginRight: '30px',
},
selectionDetails: {
marginBottom: '20px',
},
});
const controlStyles = {
root: {
margin: '0 30px 20px 0',
maxWidth: '300px',
},
};
export interface IDetailsListDocumentsExampleState {
columns: IColumn[];
items: IDocument[];
selectionDetails: string;
isModalSelection: boolean;
isCompactMode: boolean;
announcedMessage?: string;
}
export interface IDocument {
key: string;
name: string;
value: string;
iconName: string;
fileType: string;
modifiedBy: string;
dateModified: string;
dateModifiedValue: number;
fileSize: string;
fileSizeRaw: number;
}
export class DetailsListDocumentsExample extends React.Component<{}, IDetailsListDocumentsExampleState> {
private _selection: Selection;
private _allItems: IDocument[];
constructor(props: {}) {
super(props);
this._allItems = _generateDocuments();
const columns: IColumn[] = [
{
key: 'column1',
name: 'File Type',
className: classNames.fileIconCell,
iconClassName: classNames.fileIconHeaderIcon,
ariaLabel: 'Column operations for File type, Press to sort on File type',
iconName: 'Page',
isIconOnly: true,
fieldName: 'name',
minWidth: 16,
maxWidth: 16,
onColumnClick: this._onColumnClick,
onRender: (item: IDocument) => (
),
},
{
key: 'column2',
name: 'Name',
fieldName: 'name',
minWidth: 210,
maxWidth: 350,
isRowHeader: true,
isResizable: true,
isSorted: true,
isSortedDescending: false,
sortAscendingAriaLabel: 'Sorted A to Z',
sortDescendingAriaLabel: 'Sorted Z to A',
onColumnClick: this._onColumnClick,
data: 'string',
isPadded: true,
},
{
key: 'column3',
name: 'Date Modified',
fieldName: 'dateModifiedValue',
minWidth: 70,
maxWidth: 90,
isResizable: true,
onColumnClick: this._onColumnClick,
data: 'number',
onRender: (item: IDocument) => {
return {item.dateModified};
},
isPadded: true,
},
{
key: 'column4',
name: 'Modified By',
fieldName: 'modifiedBy',
minWidth: 70,
maxWidth: 90,
isResizable: true,
isCollapsible: true,
data: 'string',
onColumnClick: this._onColumnClick,
onRender: (item: IDocument) => {
return {item.modifiedBy};
},
isPadded: true,
},
{
key: 'column5',
name: 'File Size',
fieldName: 'fileSizeRaw',
minWidth: 70,
maxWidth: 90,
isResizable: true,
isCollapsible: true,
data: 'number',
onColumnClick: this._onColumnClick,
onRender: (item: IDocument) => {
return {item.fileSize};
},
},
];
this._selection = new Selection({
onSelectionChanged: () => {
this.setState({
selectionDetails: this._getSelectionDetails(),
});
},
});
this.state = {
items: this._allItems,
columns: columns,
selectionDetails: this._getSelectionDetails(),
isModalSelection: false,
isCompactMode: false,
announcedMessage: undefined,
};
}
public render() {
const { columns, isCompactMode, items, selectionDetails, isModalSelection, announcedMessage } = this.state;
return (
{selectionDetails}
{announcedMessage ?
: undefined}
{isModalSelection ? (
) : (
)}
);
}
public componentDidUpdate(previousProps: any, previousState: IDetailsListDocumentsExampleState) {
if (previousState.isModalSelection !== this.state.isModalSelection && !this.state.isModalSelection) {
this._selection.setAllSelected(false);
}
}
private _getKey(item: any, index?: number): string {
return item.key;
}
private _onChangeCompactMode = (ev: React.MouseEvent, checked: boolean): void => {
this.setState({ isCompactMode: checked });
};
private _onChangeModalSelection = (ev: React.MouseEvent, checked: boolean): void => {
this.setState({ isModalSelection: checked });
};
private _onChangeText = (ev: React.FormEvent, text: string): void => {
this.setState({
items: text ? this._allItems.filter(i => i.name.toLowerCase().indexOf(text) > -1) : this._allItems,
});
};
private _onItemInvoked(item: any): void {
alert(`Item invoked: ${item.name}`);
}
private _getSelectionDetails(): string {
const selectionCount = this._selection.getSelectedCount();
switch (selectionCount) {
case 0:
return 'No items selected';
case 1:
return '1 item selected: ' + (this._selection.getSelection()[0] as IDocument).name;
default:
return `${selectionCount} items selected`;
}
}
private _onColumnClick = (ev: React.MouseEvent, column: IColumn): void => {
const { columns, items } = this.state;
const newColumns: IColumn[] = columns.slice();
const currColumn: IColumn = newColumns.filter(currCol => column.key === currCol.key)[0];
newColumns.forEach((newCol: IColumn) => {
if (newCol === currColumn) {
currColumn.isSortedDescending = !currColumn.isSortedDescending;
currColumn.isSorted = true;
this.setState({
announcedMessage: `${currColumn.name} is sorted ${
currColumn.isSortedDescending ? 'descending' : 'ascending'
}`,
});
} else {
newCol.isSorted = false;
newCol.isSortedDescending = true;
}
});
const newItems = _copyAndSort(items, currColumn.fieldName!, currColumn.isSortedDescending);
this.setState({
columns: newColumns,
items: newItems,
});
};
}
function _copyAndSort(items: T[], columnKey: string, isSortedDescending?: boolean): T[] {
const key = columnKey as keyof T;
return items.slice(0).sort((a: T, b: T) => ((isSortedDescending ? a[key] < b[key] : a[key] > b[key]) ? 1 : -1));
}
function _generateDocuments() {
const items: IDocument[] = [];
for (let i = 0; i < 500; i++) {
const randomDate = _randomDate(new Date(2012, 0, 1), new Date());
const randomFileSize = _randomFileSize();
const randomFileType = _randomFileIcon();
let fileName = _lorem(2);
fileName = fileName.charAt(0).toUpperCase() + fileName.slice(1).concat(`.${randomFileType.docType}`);
let userName = _lorem(2);
userName = userName
.split(' ')
.map((name: string) => name.charAt(0).toUpperCase() + name.slice(1))
.join(' ');
items.push({
key: i.toString(),
name: fileName,
value: fileName,
iconName: randomFileType.url,
fileType: randomFileType.docType,
modifiedBy: userName,
dateModified: randomDate.dateFormatted,
dateModifiedValue: randomDate.value,
fileSize: randomFileSize.value,
fileSizeRaw: randomFileSize.rawSize,
});
}
return items;
}
function _randomDate(start: Date, end: Date): { value: number; dateFormatted: string } {
const date: Date = new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
return {
value: date.valueOf(),
dateFormatted: date.toLocaleDateString(),
};
}
const FILE_ICONS: { name: string }[] = [
{ name: 'accdb' },
{ name: 'audio' },
{ name: 'code' },
{ name: 'csv' },
{ name: 'docx' },
{ name: 'dotx' },
{ name: 'mpp' },
{ name: 'mpt' },
{ name: 'model' },
{ name: 'one' },
{ name: 'onetoc' },
{ name: 'potx' },
{ name: 'ppsx' },
{ name: 'pdf' },
{ name: 'photo' },
{ name: 'pptx' },
{ name: 'presentation' },
{ name: 'potx' },
{ name: 'pub' },
{ name: 'rtf' },
{ name: 'spreadsheet' },
{ name: 'txt' },
{ name: 'vector' },
{ name: 'vsdx' },
{ name: 'vssx' },
{ name: 'vstx' },
{ name: 'xlsx' },
{ name: 'xltx' },
{ name: 'xsn' },
];
function _randomFileIcon(): { docType: string; url: string } {
const docType: string = FILE_ICONS[Math.floor(Math.random() * FILE_ICONS.length)].name;
return {
docType,
url: `https://static2.sharepointonline.com/files/fabric/assets/item-types/16/${docType}.svg`,
};
}
function _randomFileSize(): { value: string; rawSize: number } {
const fileSize: number = Math.floor(Math.random() * 100) + 30;
return {
value: `${fileSize} KB`,
rawSize: fileSize,
};
}
const LOREM_IPSUM = (
'lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut ' +
'labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut ' +
'aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore ' +
'eu fugiat nulla pariatur excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt '
).split(' ');
let loremIndex = 0;
function _lorem(wordCount: number): string {
const startIndex = loremIndex + wordCount > LOREM_IPSUM.length ? 0 : loremIndex;
loremIndex = startIndex + wordCount;
return LOREM_IPSUM.slice(startIndex, loremIndex).join(' ');
}