@pnp/spfx-property-controls
Version:
Reusable property pane controls for SharePoint Framework solutions
170 lines • 7.91 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import * as React from 'react';
import styles from './TilesList.module.scss';
import { SelectionZone } from '@fluentui/react/lib/Selection';
import { List } from '@fluentui/react/lib/List';
import { FocusZone } from '@fluentui/react/lib/FocusZone';
import { css } from '@fluentui/react/lib/Utilities';
import { FolderTile } from '../FolderTile';
import { DocumentTile } from '../DocumentTile';
/**
* Rows per page
*/
const ROWS_PER_PAGE = 3;
/**
* Maximum row height
*/
const MAX_ROW_HEIGHT = 250;
/**
* Maximum number of cells per page
*/
const CELLS_PER_PAGE = 48;
/**
* Standard tile margin
*/
const STANDARD_TILE_MARGIN = 4;
/**
* Standard left and right padding
*/
const TILE_HORZ_PADDING = 32;
/**
* Standard bottom margin
*/
const BOTTOM_MARGIN = 36;
export class TilesList extends React.Component {
constructor(props) {
super(props);
this._listElem = undefined;
/**
* Gets called what a file is selected.
*/
this._handleItemInvoked = (item) => {
// If a file is selected, open the library
if (item.isFolder) {
this.props.onFolderOpen(item);
}
else {
// Otherwise, remember it was selected
this.props.onFileSelected(item);
}
};
/**
* Calculates how many items there should be in the page
*/
this._getItemCountForPage = (itemIndex, surfaceRect) => {
if (itemIndex === 0 && surfaceRect.width > 0) {
this._columnCount = Math.ceil(surfaceRect.width / MAX_ROW_HEIGHT);
this._columnWidth = Math.floor(surfaceRect.width / this._columnCount);
this._rowHeight = this._columnWidth;
this._pageWidth = surfaceRect.width;
}
// Get the list of items
const { items } = this.props;
const isFolder = items && items.length > itemIndex && items[itemIndex] ? items[itemIndex].isFolder : undefined;
// Group items by folders and files
let pageLength = 0;
for (let index = itemIndex; index < items.length; index++) {
const element = items[index];
if (element && element.isFolder === isFolder) {
pageLength++;
}
else {
break;
}
}
// Return the page lenght, up to the maximum number of cells per page
return Math.min(pageLength, CELLS_PER_PAGE);
};
/**
* Renders a custom list page
*/
this._onRenderPage = (pageProps, _defaultRender) => {
const { page, className: pageClassName } = pageProps, divProps = __rest(pageProps, ["page", "className"]);
const { items } = page;
// If there are not items to be rendered or the last one is a null mark -> request for next page data
if (!items) {
return null;
}
return (React.createElement("div", Object.assign({}, divProps, { className: css(pageClassName, styles.listPage), key: page.key }),
React.createElement("div", { className: styles.grid, style: {
width: this._pageWidth,
marginTop: -STANDARD_TILE_MARGIN,
marginBottom: BOTTOM_MARGIN,
marginLeft: -STANDARD_TILE_MARGIN,
marginRight: -STANDARD_TILE_MARGIN
} }, items.map((item, index) => {
return this._onRenderCell(item, index);
}))));
};
/** Calculates the list "page" height (a.k.a. row) */
this._getPageHeight = () => {
return this._rowHeight * ROWS_PER_PAGE;
};
/**
* Renders a file folder cover
*/
this._onRenderCell = (item, index) => {
if (!item) {
this.props.onNextPageDataRequest();
return null;
}
const isSelected = this.props.filePickerResult && item.absoluteUrl === this.props.filePickerResult.fileAbsoluteUrl;
// I know this is a lot of divs and spans inside of each other, but my
// goal was to mimic the HTML and style of the out-of-the-box file picker
// to the best of my ability.
return (React.createElement("div", { className: styles.listCell, "data-item-index": index, style: {
flexBasis: this._columnWidth,
maxWidth: this._columnWidth,
margin: STANDARD_TILE_MARGIN,
borderStyle: "none",
borderWidth: 0
} },
React.createElement("div", { role: "presentation", className: styles.cell,
// I don't agree with this magic number. Where does this come from?
style: { paddingTop: "97.16%" } },
React.createElement("div", { role: "presentation", className: styles.cellContent }, item.isFolder ?
React.createElement(FolderTile, { item: item, index: index, isSelected: isSelected, pageWidth: this._pageWidth, tileDimensions: {
width: this._columnWidth - TILE_HORZ_PADDING,
height: this._rowHeight - TILE_HORZ_PADDING
}, onItemInvoked: (itemInvoked) => this._handleItemInvoked(itemInvoked), context: this.props.context })
:
React.createElement(DocumentTile, { fileBrowserService: this.props.fileBrowserService, item: item, index: index, isSelected: isSelected, pageWidth: this._pageWidth, tileDimensions: {
width: this._columnWidth - TILE_HORZ_PADDING,
height: this._rowHeight - TILE_HORZ_PADDING
}, onItemInvoked: (itemInvoked) => this._handleItemInvoked(itemInvoked) })))));
};
}
componentDidUpdate(prevProps) {
if (this.props.filePickerResult !== prevProps.filePickerResult) {
this._listElem.forceUpdate();
}
}
render() {
return (React.createElement(SelectionZone, { selection: this.props.selection, onItemInvoked: (item) => { this._handleItemInvoked(item); } },
React.createElement(FocusZone, null,
React.createElement(List, { ref: (e) => {
const needToUpdate = !this._listElem && !!e && !this._columnWidth;
this._listElem = e;
//
// sometimes getItemCountForPage is called when surfaceRect is still has 0 width
// We need to rerender the list if that happens
//
if (needToUpdate) {
setTimeout(() => {
this._listElem.forceUpdate();
}, 0);
}
}, className: styles.folderList, items: this.props.items, getItemCountForPage: this._getItemCountForPage, getPageHeight: this._getPageHeight, onRenderPage: (pageProps, defaultRender) => this._onRenderPage(pageProps, defaultRender) }))));
}
}
//# sourceMappingURL=TilesList.js.map