calcite-react
Version:
Calcite components for React
412 lines (334 loc) • 15.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _downshift = _interopRequireDefault(require("downshift"));
var _memoizeOne = _interopRequireDefault(require("memoize-one"));
var _reactVirtualized = require("react-virtualized");
var _reactPopper = require("react-popper");
var _helpers = require("../utils/helpers");
var _MultiSelectStyled = require("./MultiSelect-styled");
var _MultiSelectMenu = _interopRequireDefault(require("./MultiSelectMenu"));
var _FormControl = require("../Form/FormControl");
var _Popover = require("../Popover/Popover");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
var MultiSelect = function MultiSelect(_ref) {
var children = _ref.children,
selectedValues = _ref.selectedValues,
placeholder = _ref.placeholder,
wrapperStyle = _ref.wrapperStyle,
menuStyle = _ref.menuStyle,
id = _ref.id,
fullWidth = _ref.fullWidth,
minimal = _ref.minimal,
onChange = _ref.onChange,
renderValue = _ref.renderValue,
positionFixed = _ref.positionFixed,
appendToBody = _ref.appendToBody,
disabled = _ref.disabled,
onBlur = _ref.onBlur,
field = _ref.field,
form = _ref.form,
closeOnSelect = _ref.closeOnSelect,
virtualized = _ref.virtualized,
virtualizedRowHeight = _ref.virtualizedRowHeight,
virtualizedMenuWidth = _ref.virtualizedMenuWidth,
popperModifiers = _ref.popperModifiers,
other = _objectWithoutProperties(_ref, ["children", "selectedValues", "placeholder", "wrapperStyle", "menuStyle", "id", "fullWidth", "minimal", "onChange", "renderValue", "positionFixed", "appendToBody", "disabled", "onBlur", "field", "form", "closeOnSelect", "virtualized", "virtualizedRowHeight", "virtualizedMenuWidth", "popperModifiers"]);
var name, touched, errors, isSubmitting, setFieldValue;
if (field) {
name = field.name;
touched = form.touched;
errors = form.errors;
isSubmitting = form.isSubmitting;
setFieldValue = form.setFieldValue;
}
var menuHeight = menuStyle && parseInt(menuStyle.height, 10) || menuStyle && parseInt(menuStyle.maxHeight, 10) || 300;
function itemToString(item) {
var label = item;
if (item && item.props) {
label = item.props.label || item.props.children || item;
}
return label;
}
function downshiftRenderValue(items) {
if (renderValue) return renderValue(items);
if (!items || !items.length) return placeholder;
return items.map(function (item) {
return itemToString(item);
}).join(', ');
}
function downshiftOnChange(selectedItem, downshiftProps) {
var selectedItems = downshiftProps.selectedItem; // Ignore onChange if not item was selected (e.g. escape key)
if (!selectedItem) return;
var existingValues = selectedItems.map(function (item) {
return item.props.value;
});
var values;
if (existingValues.indexOf(selectedItem.props.value) !== -1) {
// Already selected item was clicked, remove it
values = selectedItems.filter(function (item) {
return item.props.value !== selectedItem.props.value;
}).map(function (item) {
return item.props.value;
});
} else {
// An unselected item was clicked, add it selection
values = [].concat(_toConsumableArray(existingValues), [selectedItem.props.value]);
}
if (setFieldValue) {
setFieldValue(name, values);
}
onChange(values);
}
function _getItemsFromValues(values) {
return _react.Children.toArray(children).filter(function (child) {
return values.indexOf(child.props.value) !== -1;
});
}
function getSelectedValues() {
return field ? field.value : selectedValues;
}
function handleBlur(e) {
if (field) {
field.onBlur(e);
}
onBlur(e);
}
function isSuccess(formControlContext) {
if (touched) {
return touched[name] && !errors[name] ? true : false;
}
return formControlContext.success;
}
function isError(formControlContext) {
if (touched) {
return touched[name] && errors[name] ? true : false;
}
return formControlContext.error;
}
function isDisabled() {
return isSubmitting || disabled;
}
function _getPopper(popper, isOpen, isInPopover, appendToBody) {
if (isOpen || isInPopover) {
if (appendToBody) {
return _reactDom.default.createPortal(popper, document.body);
}
return popper;
}
}
function _stateReducer(state, changes) {
if (closeOnSelect) {
return changes;
}
switch (changes.type) {
case _downshift.default.stateChangeTypes.keyDownEnter:
case _downshift.default.stateChangeTypes.clickItem:
return _objectSpread({}, changes, {
isOpen: state.isOpen,
highlightedIndex: state.highlightedIndex
});
default:
return changes;
}
}
var getValues = (0, _memoizeOne.default)(function (selectedItems) {
return selectedItems.map(function (selectedItem) {
return selectedItem.props.value;
});
});
function getMenuItems(filteredList, params) {
var getItemProps = params.getItemProps,
highlightedIndex = params.highlightedIndex,
selectedValues = params.selectedValues;
if (virtualized) {
return _react.default.createElement(_reactVirtualized.List, {
width: virtualizedMenuWidth || 9999,
autoWidth: !virtualizedMenuWidth,
scrollToIndex: highlightedIndex || 0,
scrollToAlignment: "auto",
height: filteredList.length < 7 ? filteredList.length * virtualizedRowHeight : menuHeight,
rowCount: filteredList.length,
rowHeight: virtualizedRowHeight,
rowRenderer: function rowRenderer(_ref2) {
var index = _ref2.index,
rowRenderStyle = _ref2.style;
return getMenuItem(filteredList[index], {
getItemProps: getItemProps,
highlightedIndex: highlightedIndex,
index: index,
selectedValues: selectedValues,
rowRenderStyle: rowRenderStyle
});
},
style: {
direction: document && document.documentElement.dir || 'ltr'
}
});
}
return filteredList.map(function (item, index) {
return getMenuItem(item, {
getItemProps: getItemProps,
highlightedIndex: highlightedIndex,
index: index,
selectedValues: selectedValues
});
});
}
function getMenuItem(item, params) {
var getItemProps = params.getItemProps,
highlightedIndex = params.highlightedIndex,
index = params.index,
selectedValues = params.selectedValues,
rowRenderStyle = params.rowRenderStyle;
return _react.default.cloneElement(item, _objectSpread({}, getItemProps({
style: _objectSpread({}, item.props.style, rowRenderStyle),
item: item,
index: index,
active: highlightedIndex === index,
selected: selectedValues.indexOf(item.props.value) > -1,
key: item.props.value
})));
}
return _react.default.createElement(_reactPopper.Manager, null, _react.default.createElement(_downshift.default, {
itemToString: itemToString,
onChange: downshiftOnChange,
onBlur: handleBlur,
stateReducer: _stateReducer,
selectedItem: _getItemsFromValues(getSelectedValues())
}, function (_ref3) {
var getRootProps = _ref3.getRootProps,
getToggleButtonProps = _ref3.getToggleButtonProps,
getInputProps = _ref3.getInputProps,
getItemProps = _ref3.getItemProps,
isOpen = _ref3.isOpen,
openMenu = _ref3.openMenu,
selectedItem = _ref3.selectedItem,
highlightedIndex = _ref3.highlightedIndex,
selectHighlightedItem = _ref3.selectHighlightedItem;
var selectedValues = getValues(selectedItem);
var onKeyDown = function onKeyDown(event) {
if (!event) return;
if (event.key === 'Enter') {} else if (event.key === ' ') {
if (highlightedIndex === null) openMenu();else {
event.nativeEvent.preventDefault(); // Avoids an extra space after value
selectHighlightedItem();
}
}
};
return _react.default.createElement(_MultiSelectStyled.StyledMultiSelectWrapper, _extends({}, getRootProps({}, {
suppressRefError: true
}), {
style: wrapperStyle
}), _react.default.createElement(_reactPopper.Reference, {
style: {
display: 'inline-block'
}
}, function (_ref4) {
var ref = _ref4.ref;
return _react.default.createElement(_FormControl.FormControlContext.Consumer, null, function (formControlContext) {
return _react.default.createElement(_MultiSelectStyled.StyledMultiSelectButton, _extends({
ref: ref,
success: isSuccess(formControlContext),
error: isError(formControlContext),
disabled: isDisabled(),
as: "button"
}, getToggleButtonProps(), getInputProps({
id: id || formControlContext._generatedId,
fullWidth: fullWidth,
minimal: minimal,
onKeyDown: onKeyDown
}), other), downshiftRenderValue(selectedItem));
});
}), _react.default.createElement(_Popover.PopoverContext.Consumer, null, function (popoverContext) {
return _getPopper(_react.default.createElement(_reactPopper.Popper, {
positionFixed: positionFixed,
placement: (0, _helpers.rtlPlacement)(other.placement),
modifiers: _objectSpread({
preventOverflow: {
boundariesElement: positionFixed || appendToBody ? 'window' : 'scrollParent'
}
}, popperModifiers)
}, function (_ref5) {
var popperRef = _ref5.ref,
style = _ref5.style,
placement = _ref5.placement,
scheduleUpdate = _ref5.scheduleUpdate;
return _react.default.createElement(_MultiSelectMenu.default, {
innerRef: popperRef,
style: _objectSpread({}, style, menuStyle),
fullWidth: fullWidth,
"data-placement": placement,
isOpen: isOpen,
scheduleUpdate: scheduleUpdate
}, getMenuItems(children, {
getItemProps: getItemProps,
highlightedIndex: highlightedIndex,
selectedValues: selectedValues
}));
}), isOpen, popoverContext.isInPopover, appendToBody);
}));
}));
};
MultiSelect.propTypes = {
/** Nodes to be used as options in the Select. */
children: _propTypes.default.node,
/** Callback function fired when the value of the Select changes. */
onChange: _propTypes.default.func,
/** Callback function fired when the Select element is blurred. */
onBlur: _propTypes.default.func,
/** The selected item of the Select. */
selectedItem: _propTypes.default.node,
/** Value of the selected item. */
selectedValue: _propTypes.default.node,
/** Function to run when determining how to display selected values in a collapsed MultiSelect. */
renderValue: _propTypes.default.func,
/** Placement of the popover in relation to the target. */
placement: _propTypes.default.oneOf(['top', 'right', 'bottom', 'left', 'top-start', 'right-start', 'bottom-start', 'left-start', 'top-end', 'right-end', 'bottom-end', 'left-end']),
/** Placeholder text for the input. */
placeholder: _propTypes.default.string,
/** Whether or not the Select will fill its container's width. */
fullWidth: _propTypes.default.bool,
/** A style variant for Select inputs. */
minimal: _propTypes.default.bool,
/** Style prop applied to the menu wrapper. */
menuStyle: _propTypes.default.object,
/** Uses `position: fixed` on the tooltip allowing it to show up outside of containers that have `overflow: hidden`. */
positionFixed: _propTypes.default.bool,
/** Whether or not to close the menu on each selection. */
closeOnSelect: _propTypes.default.bool,
/** Use react-virtualized to render rows as the user scrolls. */
virtualized: _propTypes.default.bool,
/** (virtualized only) Row height used to calculate how many rows to render in a virtualized Menu. */
virtualizedRowHeight: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.func]),
/** (virtualized only) Width of the menu; unloaded rows may be wider than the initial set. */
virtualizedMenuWidth: _propTypes.default.number,
/** Modifiers to be passed to the Popper element */
popperModifiers: _propTypes.default.object
};
MultiSelect.defaultProps = {
placeholder: 'Select...',
placement: 'bottom-start',
closeOnSelect: true,
virtualizedRowHeight: 42,
onChange: function onChange() {},
onBlur: function onBlur() {}
};
MultiSelect.displayName = 'MultiSelect';
var _default = MultiSelect;
exports.default = _default;