UNPKG

@bigbinary/neetoui

Version:

neetoUI drives the experience at all neeto products

505 lines (498 loc) 22.6 kB
import _extends$1 from '@babel/runtime/helpers/extends'; import _defineProperty$1 from '@babel/runtime/helpers/defineProperty'; import _objectWithoutProperties$1 from '@babel/runtime/helpers/objectWithoutProperties'; import * as React from 'react'; import React__default, { forwardRef, useRef, useState, useEffect, useCallback } from 'react'; import classnames from 'classnames'; import { isPresent, _existsBy } from '@bigbinary/neeto-cist'; import { Down, Close } from '@bigbinary/neeto-icons'; import { isEmpty, prop, mergeDeepRight, assoc, flatten, pluck } from 'ramda'; import { u as useStateManager, S as Select$1, h as handleInputChange, a as useCreatable, C as CreatableSelect, c as components } from './react-select-creatable.esm-Dx_vEnyD.js'; import _extends from '@babel/runtime/helpers/esm/extends'; import '@babel/runtime/helpers/objectSpread2'; import '@babel/runtime/helpers/slicedToArray'; import '@babel/runtime/helpers/classCallCheck'; import '@babel/runtime/helpers/createClass'; import '@babel/runtime/helpers/inherits'; import '@babel/runtime/helpers/createSuper'; import '@babel/runtime/helpers/toConsumableArray'; import '@babel/runtime/helpers/taggedTemplateLiteral'; import '@babel/runtime/helpers/typeof'; import 'react-dom'; import _defineProperty from '@babel/runtime/helpers/esm/defineProperty'; import _objectSpread$1 from '@babel/runtime/helpers/esm/objectSpread2'; import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray'; import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties'; import { u as useId } from './useId-Jj9hXm-g.js'; import 'react-router-dom'; import '@bigbinary/neeto-hotkeys'; import './overlayManager.js'; import { h as hyphenize } from './index-Dxaw6gl9.js'; import 'qs'; import Label from './Label.js'; import Spinner from './Spinner.js'; import Tooltip from './Tooltip.js'; import '@babel/runtime/helpers/esm/classCallCheck'; import '@babel/runtime/helpers/esm/createClass'; import '@babel/runtime/helpers/esm/inherits'; import '@babel/runtime/helpers/esm/createSuper'; import '@babel/runtime/helpers/esm/toConsumableArray'; import '@babel/runtime/helpers/esm/taggedTemplateLiteral'; import '@babel/runtime/helpers/esm/typeof'; import './en-CIkXIYyl.js'; import 'dayjs'; import 'dayjs/plugin/localeData'; import 'dayjs/plugin/utc'; import 'dayjs/plugin/weekday'; import 'dayjs/plugin/weekOfYear'; import './Button.js'; import '@tippyjs/react'; import 'tippy.js'; import './Popover.js'; import './Typography.js'; var StateManagedSelect = /*#__PURE__*/forwardRef(function (props, ref) { var baseSelectProps = useStateManager(props); return /*#__PURE__*/React.createElement(Select$1, _extends({ ref: ref }, baseSelectProps)); }); var _excluded$1 = ["defaultOptions", "cacheOptions", "loadOptions", "options", "isLoading", "onInputChange", "filterOption"]; function useAsync(_ref) { var _ref$defaultOptions = _ref.defaultOptions, propsDefaultOptions = _ref$defaultOptions === void 0 ? false : _ref$defaultOptions, _ref$cacheOptions = _ref.cacheOptions, cacheOptions = _ref$cacheOptions === void 0 ? false : _ref$cacheOptions, propsLoadOptions = _ref.loadOptions; _ref.options; var _ref$isLoading = _ref.isLoading, propsIsLoading = _ref$isLoading === void 0 ? false : _ref$isLoading, propsOnInputChange = _ref.onInputChange, _ref$filterOption = _ref.filterOption, filterOption = _ref$filterOption === void 0 ? null : _ref$filterOption, restSelectProps = _objectWithoutProperties(_ref, _excluded$1); var propsInputValue = restSelectProps.inputValue; var lastRequest = useRef(undefined); var mounted = useRef(false); var _useState = useState(Array.isArray(propsDefaultOptions) ? propsDefaultOptions : undefined), _useState2 = _slicedToArray(_useState, 2), defaultOptions = _useState2[0], setDefaultOptions = _useState2[1]; var _useState3 = useState(typeof propsInputValue !== 'undefined' ? propsInputValue : ''), _useState4 = _slicedToArray(_useState3, 2), stateInputValue = _useState4[0], setStateInputValue = _useState4[1]; var _useState5 = useState(propsDefaultOptions === true), _useState6 = _slicedToArray(_useState5, 2), isLoading = _useState6[0], setIsLoading = _useState6[1]; var _useState7 = useState(undefined), _useState8 = _slicedToArray(_useState7, 2), loadedInputValue = _useState8[0], setLoadedInputValue = _useState8[1]; var _useState9 = useState([]), _useState10 = _slicedToArray(_useState9, 2), loadedOptions = _useState10[0], setLoadedOptions = _useState10[1]; var _useState11 = useState(false), _useState12 = _slicedToArray(_useState11, 2), passEmptyOptions = _useState12[0], setPassEmptyOptions = _useState12[1]; var _useState13 = useState({}), _useState14 = _slicedToArray(_useState13, 2), optionsCache = _useState14[0], setOptionsCache = _useState14[1]; var _useState15 = useState(undefined), _useState16 = _slicedToArray(_useState15, 2), prevDefaultOptions = _useState16[0], setPrevDefaultOptions = _useState16[1]; var _useState17 = useState(undefined), _useState18 = _slicedToArray(_useState17, 2), prevCacheOptions = _useState18[0], setPrevCacheOptions = _useState18[1]; if (cacheOptions !== prevCacheOptions) { setOptionsCache({}); setPrevCacheOptions(cacheOptions); } if (propsDefaultOptions !== prevDefaultOptions) { setDefaultOptions(Array.isArray(propsDefaultOptions) ? propsDefaultOptions : undefined); setPrevDefaultOptions(propsDefaultOptions); } useEffect(function () { mounted.current = true; return function () { mounted.current = false; }; }, []); var loadOptions = useCallback(function (inputValue, callback) { if (!propsLoadOptions) return callback(); var loader = propsLoadOptions(inputValue, callback); if (loader && typeof loader.then === 'function') { loader.then(callback, function () { return callback(); }); } }, [propsLoadOptions]); useEffect(function () { if (propsDefaultOptions === true) { loadOptions(stateInputValue, function (options) { if (!mounted.current) return; setDefaultOptions(options || []); setIsLoading(!!lastRequest.current); }); } // NOTE: this effect is designed to only run when the component mounts, // so we don't want to include any hook dependencies // eslint-disable-next-line react-hooks/exhaustive-deps }, []); var onInputChange = useCallback(function (newValue, actionMeta) { var inputValue = handleInputChange(newValue, actionMeta, propsOnInputChange); if (!inputValue) { lastRequest.current = undefined; setStateInputValue(''); setLoadedInputValue(''); setLoadedOptions([]); setIsLoading(false); setPassEmptyOptions(false); return; } if (cacheOptions && optionsCache[inputValue]) { setStateInputValue(inputValue); setLoadedInputValue(inputValue); setLoadedOptions(optionsCache[inputValue]); setIsLoading(false); setPassEmptyOptions(false); } else { var request = lastRequest.current = {}; setStateInputValue(inputValue); setIsLoading(true); setPassEmptyOptions(!loadedInputValue); loadOptions(inputValue, function (options) { if (!mounted) return; if (request !== lastRequest.current) return; lastRequest.current = undefined; setIsLoading(false); setLoadedInputValue(inputValue); setLoadedOptions(options || []); setPassEmptyOptions(false); setOptionsCache(options ? _objectSpread$1(_objectSpread$1({}, optionsCache), {}, _defineProperty({}, inputValue, options)) : optionsCache); }); } }, [cacheOptions, loadOptions, loadedInputValue, optionsCache, propsOnInputChange]); var options = passEmptyOptions ? [] : stateInputValue && loadedInputValue ? loadedOptions : defaultOptions || []; return _objectSpread$1(_objectSpread$1({}, restSelectProps), {}, { options: options, isLoading: isLoading || propsIsLoading, onInputChange: onInputChange, filterOption: filterOption }); } var AsyncSelect = /*#__PURE__*/forwardRef(function (props, ref) { var stateManagedProps = useAsync(props); var selectProps = useStateManager(stateManagedProps); return /*#__PURE__*/React.createElement(Select$1, _extends({ ref: ref }, selectProps)); }); var AsyncCreatableSelect = /*#__PURE__*/forwardRef(function (props, ref) { var stateManagerProps = useAsync(props); var creatableProps = useStateManager(stateManagerProps); var selectProps = useCreatable(creatableProps); return /*#__PURE__*/React.createElement(Select$1, _extends({ ref: ref }, selectProps)); }); var _excluded = ["children"], _excluded2 = ["size", "label", "required", "error", "helpText", "className", "innerRef", "isCreateable", "strategy", "id", "labelProps", "value", "defaultValue", "components", "optionRemapping", "onMenuClose", "onMenuOpen", "onKeyDown", "styles", "dataCy"]; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty$1(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } var SIZES = { small: "small", medium: "medium", large: "large" }; var STRATEGIES = { "default": "default", fixed: "fixed" }; var Control = function Control(_ref) { var children = _ref.children, props = _objectWithoutProperties$1(_ref, _excluded); var selectProps = props.selectProps, hasValue = props.hasValue; return /*#__PURE__*/React__default.createElement(components.Control, props, hasValue && selectProps.isMulti && /*#__PURE__*/React__default.createElement("span", { className: "neeto-ui-btn neeto-ui-btn--style-secondary neeto-ui-react-select__add-btn" }, selectProps.addButtonLabel || "Add"), " ", children); }; var DropdownIndicator = function DropdownIndicator(props) { return /*#__PURE__*/React__default.createElement(components.DropdownIndicator, _extends$1({}, props, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, _defineProperty$1({}, "data-cy", "action-select-indicator")) }), /*#__PURE__*/React__default.createElement(Down, { size: 16 })); }; var ClearIndicator = function ClearIndicator(props) { return /*#__PURE__*/React__default.createElement(components.ClearIndicator, _extends$1({}, props, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, { "data-cy": "clear-select-indicator" }) }), /*#__PURE__*/React__default.createElement(Close, { size: 16 })); }; var MultiValueRemove = function MultiValueRemove(props) { return /*#__PURE__*/React__default.createElement(components.MultiValueRemove, props, /*#__PURE__*/React__default.createElement(Close, { size: 16 })); }; var CustomInput = function CustomInput(props) { var selectProps = props.selectProps; return /*#__PURE__*/React__default.createElement(components.Input, _extends$1({}, props, { "data-cy": selectProps ? selectProps["data-cy"] : "select-input", "data-testid": selectProps && selectProps["data-testid"], maxLength: selectProps && selectProps.maxLength })); }; var CustomOption = function CustomOption(props) { var ref = useRef(); var innerProps = props.innerProps, _props$data = props.data, dataCy = _props$data.dataCy, _props$data$tooltipPr = _props$data.tooltipProps, tooltipProps = _props$data$tooltipPr === void 0 ? {} : _props$data$tooltipPr; useEffect(function () { props.isSelected && ref.current.scrollIntoView(); }, [props.isSelected]); var optionComponent = /*#__PURE__*/React__default.createElement(components.Option, _extends$1({}, props, { innerRef: ref, innerProps: _objectSpread(_objectSpread({}, innerProps), {}, { "data-cy": dataCy || "".concat(hyphenize(props.label), "-select-option") }) })); return isPresent(tooltipProps) ? /*#__PURE__*/React__default.createElement(Tooltip, _extends$1({ position: "bottom-start", zIndex: 1000001 }, tooltipProps), /*#__PURE__*/React__default.createElement("div", null, optionComponent)) : optionComponent; }; var Placeholder = function Placeholder(props) { var selectProps = props.selectProps; return /*#__PURE__*/React__default.createElement(components.Placeholder, _extends$1({}, props, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, { "data-cy": selectProps !== null && selectProps !== void 0 && selectProps.hyphenatedDataCyLabel ? "".concat(selectProps.hyphenatedDataCyLabel, "-select-placeholder") : "select-placeholder" }) })); }; var Menu = function Menu(props) { var selectProps = props.selectProps; return /*#__PURE__*/React__default.createElement(components.Menu, _extends$1({}, props, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, { "data-cy": selectProps ? "".concat(selectProps.hyphenatedDataCyLabel, "-select-menu") : "select-menu" }) })); }; var SingleValue = function SingleValue(props) { return /*#__PURE__*/React__default.createElement(components.SingleValue, _extends$1({}, props, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, { "data-cy": "select-single-value" }) })); }; var ValueContainer = function ValueContainer(props) { var selectProps = props.selectProps; return /*#__PURE__*/React__default.createElement(components.ValueContainer, _extends$1({}, props, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, { name: selectProps.name, "data-cy": selectProps ? "".concat(selectProps.hyphenatedDataCyLabel, "-select-value-container") : "select-value-container" }) })); }; var MenuList = function MenuList(props) { var _props$selectProps = props.selectProps, fetchMore = _props$selectProps.fetchMore, totalOptionsCount = _props$selectProps.totalOptionsCount, isAsyncLoadOptionEnabled = _props$selectProps.isAsyncLoadOptionEnabled, options = _props$selectProps.options, _props$selectProps$po = _props$selectProps.portalProps, portalProps = _props$selectProps$po === void 0 ? {} : _props$selectProps$po; var hasMore = isAsyncLoadOptionEnabled && totalOptionsCount > options.length; var loaderRef = useRef(); useEffect(function () { var observer = null; if (loaderRef.current && isAsyncLoadOptionEnabled) { observer = new IntersectionObserver(function (entries) { return entries[0].isIntersecting && fetchMore(); }, { root: null, rootMargin: "0px", threshold: 0.1 }); observer.observe(loaderRef.current); } return function () { var _observer; if (!(loaderRef.current && isAsyncLoadOptionEnabled)) return; (_observer = observer) === null || _observer === void 0 || _observer.unobserve(loaderRef.current); }; }, [hasMore]); return /*#__PURE__*/React__default.createElement(components.MenuList, _extends$1({}, props, portalProps, { innerProps: _objectSpread(_objectSpread({}, props.innerProps), {}, _defineProperty$1({}, "data-testid", "menu-list")) }), props.children, hasMore && /*#__PURE__*/React__default.createElement("div", { className: "neeto-ui-flex neeto-ui-w-full neeto-ui-items-center neeto-ui-justify-center neeto-ui-py-3", "data-testid": "loader", ref: loaderRef }, /*#__PURE__*/React__default.createElement(Spinner, null))); }; var Select = function Select(_ref2) { var _ref3, _otherProps$isMenuOpe; var _ref2$size = _ref2.size, size = _ref2$size === void 0 ? SIZES.medium : _ref2$size, _ref2$label = _ref2.label, label = _ref2$label === void 0 ? "" : _ref2$label, _ref2$required = _ref2.required, required = _ref2$required === void 0 ? false : _ref2$required, _ref2$error = _ref2.error, error = _ref2$error === void 0 ? "" : _ref2$error, _ref2$helpText = _ref2.helpText, helpText = _ref2$helpText === void 0 ? "" : _ref2$helpText, _ref2$className = _ref2.className, className = _ref2$className === void 0 ? "" : _ref2$className, innerRef = _ref2.innerRef, _ref2$isCreateable = _ref2.isCreateable, isCreateable = _ref2$isCreateable === void 0 ? false : _ref2$isCreateable, _ref2$strategy = _ref2.strategy, strategy = _ref2$strategy === void 0 ? STRATEGIES["default"] : _ref2$strategy, id = _ref2.id, labelProps = _ref2.labelProps, value = _ref2.value, defaultValue = _ref2.defaultValue, componentOverrides = _ref2.components, _ref2$optionRemapping = _ref2.optionRemapping, optionRemapping = _ref2$optionRemapping === void 0 ? {} : _ref2$optionRemapping, onMenuClose = _ref2.onMenuClose, onMenuOpen = _ref2.onMenuOpen, onKeyDown = _ref2.onKeyDown, _ref2$styles = _ref2.styles, styles = _ref2$styles === void 0 ? {} : _ref2$styles, _ref2$dataCy = _ref2.dataCy, dataCy = _ref2$dataCy === void 0 ? "nui" : _ref2$dataCy, otherProps = _objectWithoutProperties$1(_ref2, _excluded2); var inputId = useId(id); var isMenuOpen = useRef((_ref3 = (_otherProps$isMenuOpe = otherProps.isMenuOpen) !== null && _otherProps$isMenuOpe !== void 0 ? _otherProps$isMenuOpe : otherProps.defaultMenuIsOpen) !== null && _ref3 !== void 0 ? _ref3 : false); var hyphenatedDataCyLabel = isEmpty(label) ? hyphenize(dataCy) : hyphenize(label); var Parent = StateManagedSelect; if (isCreateable) { Parent = CreatableSelect; } if (otherProps.loadOptions) { Parent = isCreateable ? AsyncCreatableSelect : AsyncSelect; } if (optionRemapping.value) { otherProps.getOptionValue = prop(optionRemapping.value); } if (optionRemapping.label) { otherProps.getOptionLabel = prop(optionRemapping.label); } var portalProps = strategy === STRATEGIES.fixed && { menuPortalTarget: document.body, styles: mergeDeepRight({ menuPortal: assoc("zIndex", 999999) }, styles), menuPosition: "fixed" }; var options = otherProps.options, defaultOptions = otherProps.defaultOptions, getOptionValue = otherProps.getOptionValue; var getRealOptionValue = function getRealOptionValue(option) { if (typeof getOptionValue !== "function") { return option.value; } return getOptionValue(option); }; var findInOptions = function findInOptions(value) { var _currentOptions; var fetchMore = otherProps.fetchMore, isMulti = otherProps.isMulti; if (!value || isMulti || isPresent(fetchMore)) { return value; } var currentOptions = options || defaultOptions; if (Array.isArray(value)) value = value[0]; var isGrouped = _existsBy({ options: Array.isArray }, currentOptions); if (isGrouped) { currentOptions = flatten(pluck("options", currentOptions)); } return (_currentOptions = currentOptions) === null || _currentOptions === void 0 ? void 0 : _currentOptions.filter(function (opt) { return getRealOptionValue(opt) === getRealOptionValue(value); }); }; var handleMenuOpen = function handleMenuOpen() { isMenuOpen.current = true; onMenuOpen === null || onMenuOpen === void 0 || onMenuOpen(); }; var handleMenuClose = function handleMenuClose() { isMenuOpen.current = false; onMenuClose === null || onMenuClose === void 0 || onMenuClose(); }; var handleKeyDown = function handleKeyDown(e) { if (!isMenuOpen.current) return; e.stopPropagation(); onKeyDown === null || onKeyDown === void 0 || onKeyDown(e); }; return /*#__PURE__*/React__default.createElement("div", { className: classnames(["neeto-ui-input__wrapper", className]), "data-cy": "".concat(hyphenatedDataCyLabel, "-select-container-wrapper"), "data-testid": "select" }, label && /*#__PURE__*/React__default.createElement(Label, _extends$1({ required: required, "data-cy": "".concat(hyphenatedDataCyLabel, "-input-label"), "data-testid": "select-label", htmlFor: inputId }, labelProps), label), /*#__PURE__*/React__default.createElement(Parent, _extends$1({ blurInputOnSelect: false, classNamePrefix: "neeto-ui-react-select", closeMenuOnSelect: !otherProps.isMulti, "data-cy": "".concat(hyphenatedDataCyLabel, "-select-container"), defaultValue: findInOptions(defaultValue), ref: innerRef, value: findInOptions(value), className: classnames(["neeto-ui-react-select__container"], { "neeto-ui-react-select__container--error": !!error, "neeto-ui-react-select__container--small": size === SIZES.small, "neeto-ui-react-select__container--medium": size === SIZES.medium, "neeto-ui-react-select__container--large": size === SIZES.large }), components: _objectSpread({ Input: CustomInput, Option: CustomOption, DropdownIndicator: DropdownIndicator, ClearIndicator: ClearIndicator, MultiValueRemove: MultiValueRemove, Placeholder: Placeholder, Menu: Menu, ValueContainer: ValueContainer, MenuList: MenuList, SingleValue: SingleValue, Control: Control }, componentOverrides), onKeyDown: handleKeyDown, onMenuClose: handleMenuClose, onMenuOpen: handleMenuOpen }, _objectSpread(_objectSpread(_objectSpread({ inputId: inputId, label: label, styles: styles }, portalProps), otherProps), {}, { hyphenatedDataCyLabel: hyphenatedDataCyLabel }))), !!error && /*#__PURE__*/React__default.createElement("p", { className: "neeto-ui-input__error", "data-cy": "".concat(hyphenatedDataCyLabel, "-select-error"), "data-testid": "select-error" }, error), helpText && /*#__PURE__*/React__default.createElement("p", { className: "neeto-ui-input__help-text", "data-cy": "".concat(hyphenatedDataCyLabel, "-select-help-text"), "data-testid": "select-help-text" }, helpText)); }; export { Select as default }; //# sourceMappingURL=Select.js.map