wix-style-react
Version:
wix-style-react
157 lines • 6.82 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import SelectorList from '../SelectorList';
import HeaderLayout from '../MessageBoxFunctionalLayout/HeaderLayout';
import FooterLayout from '../MessageBoxFunctionalLayout/FooterLayout';
import { classes } from './ModalSelectorLayout.st.css';
import { dataHooks } from './ModalSelectorLayout.helpers';
/**
* Use this component when needed to select one / multiple items having complex descriptions.
* E.g.: choosing products to promote via ShoutOuts
*/
class ModalSelectorLayout extends React.PureComponent {
constructor() {
super(...arguments);
this._getEnabledItems = items => items.filter(({ disabled }) => !disabled);
}
render() {
const {
// SelectorList props
dataSource, imageSize, imageShape, searchPlaceholder, emptyState, noResultsFoundStateFactory: renderNoResults, itemsPerPage, withSearch, searchDebounceMs, onSelect, multiple, subtitle,
// Modal props
dataHook, title, onClose, onCancel, onOk, height, maxHeight, cancelButtonText, okButtonText, disableConfirmation, sideActions, } = this.props;
return (React.createElement(SelectorList, { dataSource,
imageSize,
imageShape,
searchPlaceholder,
emptyState,
renderNoResults,
itemsPerPage,
withSearch,
searchDebounceMs,
onSelect,
multiple,
subtitle, dataHook: dataHooks.selectorList }, ({ renderList, renderToggleAllCheckbox, selectedItems }) => {
const enabledItems = this._getEnabledItems(selectedItems);
return (React.createElement("div", { "data-hook": dataHook, className: classes.modalContent, style: { height, maxHeight } },
React.createElement(HeaderLayout, { title: title, onCancel: onClose }),
renderList(),
React.createElement(FooterLayout, { onCancel: onCancel, onOk: () => onOk(multiple ? enabledItems : enabledItems[0]), cancelText: cancelButtonText, confirmText: okButtonText, enableOk: !disableConfirmation && !!selectedItems.length, children: !sideActions && multiple && renderToggleAllCheckbox(), sideActions: sideActions })));
}));
}
}
ModalSelectorLayout.displayName = 'ModalSelectorLayout';
ModalSelectorLayout.propTypes = {
/** applied as data-hook HTML attribute that can be used to create driver in testing */
dataHook: PropTypes.string,
/** Title of the modal */
title: PropTypes.node,
/** Fixed text displayed above the list */
subtitle: PropTypes.node,
/** OK button callback, called with the currently selected item */
onOk: PropTypes.func,
/** X button callback */
onClose: PropTypes.func,
/** Cancel button callback */
onCancel: PropTypes.func,
/**
* paging function that should have a signature of
* ```typescript
* (searchQuery: string, offset: number, limit: number) =>
* Promise<{
* items: Array<{
* id: number | string,
* title: node,
* subtitle?: string,
* extraText?: string,
* extraNode?: node,
* disabled?: boolean // show item as disabled, dont count it in "select all", exclude from `onOk`
* selected?: boolean // force item as selected
* image?: node
* subtitleNode?: node,
* belowNode?: node,
* showBelowNodeOnSelect?: boolean,
* }>,
* totalCount: number
* }>
* ```
* `offset` - next requested item's index<br>
* `limit` - number of items requested<br>
* `totalCount` - total number of items that suffice the current search query
* */
dataSource: PropTypes.func.isRequired,
/** Cancel button's text */
cancelButtonText: PropTypes.string,
/** OK button's text */
okButtonText: PropTypes.string,
/** Image icon size */
imageSize: PropTypes.oneOf([
'tiny',
'small',
'portrait',
'large',
'cinema',
]),
/**
* Image icon shape, `rectangular` or `circle`.<br>
* NOTE: `circle` is not compatible with `imageSize` of `portrait` or `cinema`
* */
imageShape: (props, propName, componentName) => {
if (['portrait', 'cinema'].includes(props.imageSize) &&
props[propName] === 'circle') {
return new Error(`${componentName}: prop "imageSize" with value of "${props.imageSize}" is incompatible with prop imageShape with value of "circle" — use "rectangular" instead.`);
}
},
/** Placeholder text of the search input */
searchPlaceholder: PropTypes.string,
/**
* Component/element that will be rendered when there is nothing to display,
* i.e. empty `{items:[], totalCount: 0}` was returned on the first call to `dataSource`
* */
emptyState: PropTypes.node,
/**
* Function that will get the current `searchQuery` and should return the component/element
* that will be rendered when there are no items that suffice the entered search query
* */
noResultsFoundStateFactory: PropTypes.func,
/** Number of items loaded each time the user scrolls down */
itemsPerPage: PropTypes.number,
/** Whether to display the search input or not */
withSearch: PropTypes.bool,
/** Search debounce in milliseconds */
searchDebounceMs: PropTypes.number,
/** Height CSS property, sets the height of the modal */
height: PropTypes.string,
/** Max-height CSS property, sets the maximum height of the modal. */
maxHeight: PropTypes.string,
/** display checkbox and allow multi selection */
multiple: PropTypes.bool,
/** string to be displayed in footer when `multiple` prop is used and no items are selected */
selectAllText: PropTypes.string,
/** string to be displayed in footer when `multiple` prop is used and some or all items ar selected */
deselectAllText: PropTypes.string,
/** to disable confirm button */
disableConfirmation: PropTypes.bool,
/** callback that triggers on select and return selected item object*/
onSelect: PropTypes.func,
/** Used to display some side component in the footer.
* Will override element select all in the footer when multiple=true */
sideActions: PropTypes.node,
};
ModalSelectorLayout.defaultProps = {
title: 'Choose Your Items',
okButtonText: 'Select',
cancelButtonText: 'Cancel',
searchPlaceholder: 'Search...',
imageSize: 'large',
imageShape: 'rectangular',
itemsPerPage: 50,
withSearch: true,
height: '100%',
maxHeight: '100%',
selectAllText: 'Select All',
deselectAllText: 'Deselect All',
disableConfirmation: false,
};
export default ModalSelectorLayout;
//# sourceMappingURL=ModalSelectorLayout.js.map