UNPKG

wix-style-react

Version:
157 lines 6.82 kB
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