UNPKG

wix-style-react

Version:
455 lines (390 loc) • 19 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _Content = _interopRequireDefault(require("./Content")); var _Box = _interopRequireDefault(require("../Box")); var _Search = _interopRequireDefault(require("../Search")); var _Text = _interopRequireDefault(require("../Text")); var _ToggleAllCheckbox = _interopRequireDefault(require("./ToggleAllCheckbox")); var _SelectorList = require("./SelectorList.helpers"); var _SelectorListSt = require("./SelectorList.st.css"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /** * Use this component when needed to select one / multiple items having complex descriptions. * E.g.: choosing products to promote via ShoutOuts */ var SelectorList = /*#__PURE__*/function (_React$PureComponent) { (0, _inherits2["default"])(SelectorList, _React$PureComponent); var _super = _createSuper(SelectorList); function SelectorList() { var _this; (0, _classCallCheck2["default"])(this, SelectorList); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _super.call.apply(_super, [this].concat(args)); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "state", { isLoaded: false, isSearching: false, items: [], searchValue: '', selectedItems: [], noResultsFound: false, isEmpty: false }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_renderList", function () { var _this$props = _this.props, dataHook = _this$props.dataHook, emptyState = _this$props.emptyState, renderNoResults = _this$props.renderNoResults, height = _this$props.height, maxHeight = _this$props.maxHeight, imageSize = _this$props.imageSize, imageShape = _this$props.imageShape, multiple = _this$props.multiple; var _this$state = _this.state, items = _this$state.items, isLoaded = _this$state.isLoaded, isEmpty = _this$state.isEmpty, isSearching = _this$state.isSearching, searchValue = _this$state.searchValue, noResultsFound = _this$state.noResultsFound, selectedItems = _this$state.selectedItems; var hasMore = _this._hasMore(); var contentProps = { items: items, selectedItems: selectedItems, onToggle: _this._onToggle, emptyState: emptyState, renderNoResults: renderNoResults, isEmpty: isEmpty, isLoading: !isLoaded || isSearching, noResultsFound: noResultsFound, imageSize: imageSize, imageShape: imageShape, multiple: multiple, loadMore: _this._loadMore, hasMore: hasMore, checkIsSelected: _this._checkIsSelected, searchValue: searchValue }; var shouldRenderSubheader = isLoaded && !isEmpty; return /*#__PURE__*/_react["default"].createElement(_Box["default"], { direction: "vertical", overflow: "hidden", dataHook: dataHook, height: height, maxHeight: maxHeight }, shouldRenderSubheader && _this._renderSubheader(), /*#__PURE__*/_react["default"].createElement(_Content["default"], contentProps)); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_renderSubheader", function () { var _this$props2 = _this.props, subtitle = _this$props2.subtitle, withSearch = _this$props2.withSearch, searchDebounceMs = _this$props2.searchDebounceMs, searchPlaceholder = _this$props2.searchPlaceholder; var searchValue = _this.state.searchValue; return /*#__PURE__*/_react["default"].createElement("div", { className: (0, _SelectorListSt.st)(_SelectorListSt.classes.subheaderWrapper, { withSearch: withSearch }) }, subtitle && /*#__PURE__*/_react["default"].createElement("div", { className: _SelectorListSt.classes.subtitleWrapper }, typeof subtitle === 'string' ? /*#__PURE__*/_react["default"].createElement(_Text["default"], { dataHook: _SelectorList.dataHooks.subtitle }, subtitle) : subtitle), withSearch && /*#__PURE__*/_react["default"].createElement(_Search["default"], { dataHook: _SelectorList.dataHooks.search, placeholder: searchPlaceholder, onChange: _this._onSearchChange, onClear: _this._onClear, debounceMs: searchDebounceMs, value: searchValue })); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_renderToggleAllCheckbox", function () { var _this$props3 = _this.props, selectAllText = _this$props3.selectAllText, deselectAllText = _this$props3.deselectAllText; var _this$state2 = _this.state, items = _this$state2.items, selectedItems = _this$state2.selectedItems; var enabledItemsAmount = _this._getEnabledItems(items).length; var selectedEnabledItemsAmount = _this._getEnabledItems(selectedItems).length; var checkboxProps = { selectAllText: selectAllText, deselectAllText: deselectAllText, enabledItemsAmount: enabledItemsAmount, selectedEnabledItemsAmount: selectedEnabledItemsAmount, selectAll: _this._selectAll, deselectAll: _this._deselectAll }; return /*#__PURE__*/_react["default"].createElement(_ToggleAllCheckbox["default"], checkboxProps); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_updateSearchValue", function (searchValue) { return _this.setState({ searchValue: searchValue, isSearching: true, items: [] }, function () { return _this._loadInitialItems(searchValue); }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onSearchChange", function (event) { return _this._updateSearchValue(event.target.value); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onClear", function () { return _this._updateSearchValue(''); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_checkIsSelected", function (item) { var selectedItems = _this.state.selectedItems; return !!selectedItems.find(function (_ref) { var id = _ref.id; return item.id === id; }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_toggleItem", function (item) { var multiple = _this.props.multiple; _this.setState(function (_ref2) { var selectedItems = _ref2.selectedItems; return { selectedItems: multiple ? _this._checkIsSelected(item) ? selectedItems.filter(function (_ref3) { var id = _ref3.id; return item.id !== id; }) : selectedItems.concat(item) : [item] }; }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onToggle", function (item) { var onSelect = _this.props.onSelect; _this._toggleItem(item); if (onSelect) { onSelect(item); } }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_selectAll", function () { var _this$state3 = _this.state, selectedItems = _this$state3.selectedItems, items = _this$state3.items; var enabledItems = _this._getEnabledItems(items); _this.setState({ selectedItems: selectedItems.concat(enabledItems) }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_deselectAll", function () { return _this.setState(function (_ref4) { var selectedItems = _ref4.selectedItems; return { selectedItems: selectedItems.filter(function (_ref5) { var disabled = _ref5.disabled; return disabled; }) }; }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_updateItems", function (_ref6) { var nextPageItems = _ref6.items, totalCount = _ref6.totalCount, searchValue = _ref6.searchValue; var _this$state4 = _this.state, items = _this$state4.items, selectedItems = _this$state4.selectedItems; // react only to the resolve of the relevant search if (searchValue !== _this.state.searchValue) { return; } var newItems = [].concat((0, _toConsumableArray2["default"])(items), (0, _toConsumableArray2["default"])(nextPageItems)); var newSelectedItems = selectedItems.concat(nextPageItems.filter(function (_ref7) { var selected = _ref7.selected; return selected; })); var noResultsFound = newItems.length === 0 && Boolean(searchValue); var isEmpty = newItems.length === 0 && !searchValue; _this.setState({ items: newItems, selectedItems: newSelectedItems, isLoaded: true, isEmpty: isEmpty, isSearching: false, totalCount: totalCount, noResultsFound: noResultsFound }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_loadInitialItems", function () { var searchValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var _this$props4 = _this.props, dataSource = _this$props4.dataSource, itemsPerPage = _this$props4.itemsPerPage; var initialAmountToLoad = _this.props.initialAmountToLoad || itemsPerPage; dataSource(searchValue, 0, initialAmountToLoad).then(function (dataSourceProps) { return _this._updateItems(_objectSpread(_objectSpread({}, dataSourceProps), {}, { searchValue: searchValue })); }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_loadMore", function () { var _this$props5 = _this.props, dataSource = _this$props5.dataSource, itemsPerPage = _this$props5.itemsPerPage; var _this$state5 = _this.state, items = _this$state5.items, searchValue = _this$state5.searchValue; dataSource(searchValue, items.length, itemsPerPage).then(function (dataSourceProps) { return _this._updateItems(_objectSpread(_objectSpread({}, dataSourceProps), {}, { searchValue: searchValue })); }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_getEnabledItems", function (items) { return items.filter(function (_ref8) { var disabled = _ref8.disabled; return !disabled; }); }); return _this; } (0, _createClass2["default"])(SelectorList, [{ key: "componentDidMount", value: function componentDidMount() { this._loadInitialItems(); } /** Resets list items and loads first page from dataSource while persisting searchValue */ }, { key: "reloadInitialItems", value: function reloadInitialItems() { var searchValue = this.state.searchValue; this.setState({ items: [], searchValue: searchValue, isSearching: Boolean(searchValue), isLoaded: false }); this._loadInitialItems(searchValue); } }, { key: "render", value: function render() { var children = this.props.children; var selectedItems = this.state.selectedItems; if (typeof children === 'function') { return children({ renderList: this._renderList, renderToggleAllCheckbox: this._renderToggleAllCheckbox, selectedItems: selectedItems }); } return this._renderList(); } }, { key: "_hasMore", value: function _hasMore() { var _this$state6 = this.state, items = _this$state6.items, isLoaded = _this$state6.isLoaded, totalCount = _this$state6.totalCount, isSearching = _this$state6.isSearching; return items.length === 0 && !isLoaded || items.length < totalCount || isSearching; } }]); return SelectorList; }(_react["default"].PureComponent); exports["default"] = SelectorList; (0, _defineProperty2["default"])(SelectorList, "displayName", 'SelectorList'); (0, _defineProperty2["default"])(SelectorList, "propTypes", { /** applied as data-hook HTML attribute that can be used to create driver in testing */ dataHook: _propTypes["default"].string, /** * 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["default"].func.isRequired, /** Image icon size */ imageSize: _propTypes["default"].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: function imageShape(props, propName, componentName) { if (['portrait', 'cinema'].includes(props.imageSize) && props[propName] === 'circle') { return new Error("".concat(componentName, ": prop \"imageSize\" with value of \"").concat(props.imageSize, "\" is incompatible with prop imageShape with value of \"circle\" \u2014 use \"rectangular\" instead.")); } }, /** Placeholder text of the search input */ searchPlaceholder: _propTypes["default"].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["default"].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 * */ renderNoResults: _propTypes["default"].func, /** Number of items loaded each time the user scrolls down */ itemsPerPage: _propTypes["default"].number, /** Whether to display the search input or not */ withSearch: _propTypes["default"].bool, /** Search debounce in milliseconds */ searchDebounceMs: _propTypes["default"].number, /** Height classes property, sets the height of the list container */ height: _propTypes["default"].string, /** Max-height classes property, sets the maximum height of the list container. */ maxHeight: _propTypes["default"].string, /** display checkbox and allow multi selection */ multiple: _propTypes["default"].bool, /** callback that triggers on select and return selected item object*/ onSelect: _propTypes["default"].func, /** string to be displayed in footer when `multiple` prop is used and no items are selected */ selectAllText: _propTypes["default"].string, /** string to be displayed in footer when `multiple` prop is used and some or all items ar selected */ deselectAllText: _propTypes["default"].string, /** amount of items to load on initial render or after search */ initialAmountToLoad: _propTypes["default"].number, /** Fixed text displayed above the list */ subtitle: _propTypes["default"].node }); (0, _defineProperty2["default"])(SelectorList, "defaultProps", { searchPlaceholder: 'Search...', imageSize: 'large', imageShape: 'rectangular', itemsPerPage: 50, withSearch: true, height: '100%', maxHeight: '100%' });