UNPKG

@geezee/react-ui

Version:

Modern and minimalist React UI library.

251 lines (222 loc) 10.1 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _JSXStyle from "styled-jsx/style"; import React, { useEffect, useMemo, useRef, useState, useImperativeHandle } from 'react'; import Input, { defaultProps as inputDefaultProps } from '../input/input'; import { useAutoCompleteHandle } from '../input/use-input-handle'; import Loading from '../loading'; import CSSTransition, { defaultProps as CSSTransitionDefaultProps } from '../shared/css-transition'; import { pickChild } from '../utils/collections'; import useClickAway from '../utils/use-click-away'; import { AutoCompleteContext } from './auto-complete-context'; import AutoCompleteDropdown from './auto-complete-dropdown'; import AutoCompleteEmpty from './auto-complete-empty'; import AutoCompleteItem from './auto-complete-item'; import AutoCompleteSearching from './auto-complete-searching'; var DEFAULT_CSS_TRANSITION_LEAVE_TIME = CSSTransitionDefaultProps.leaveTime + CSSTransitionDefaultProps.clearTime; export var defaultProps = Object.assign({}, inputDefaultProps, { width: 'max-content', defaultOpen: false, options: [], disableMatchWidth: false, disableFreeSolo: false }); var childrenToOptionsNode = function childrenToOptionsNode(options, variant) { return options.map(function (item, index) { var key = "auto-complete-item-".concat(index); if (React.isValidElement(item)) return React.cloneElement(item, { key: key }); var validItem = item; return /*#__PURE__*/React.createElement(AutoCompleteItem, { variant: variant, key: key, label: validItem.label, isLabelOnly: true }); }); }; // When the search is not set, the "clearable" icon can be displayed in the original location. // When the search is set, at least one element should exist to avoid re-render. var getSearchIcon = function getSearchIcon(searching) { if (searching === undefined) return null; return searching ? /*#__PURE__*/React.createElement(Loading, { size: "small" }) : /*#__PURE__*/React.createElement("span", null); }; var AutoComplete = React.forwardRef(function (_ref, ref) { var variant = _ref.variant, options = _ref.options, defaultValue = _ref.defaultValue, onSelect = _ref.onSelect, onSearch = _ref.onSearch, onChange = _ref.onChange, searching = _ref.searching, onClearClick = _ref.onClearClick, children = _ref.children, size = _ref.size, value = _ref.value, width = _ref.width, clearable = _ref.clearable, disabled = _ref.disabled, dropdownClassName = _ref.dropdownClassName, dropdownStyle = _ref.dropdownStyle, disableMatchWidth = _ref.disableMatchWidth, disableFreeSolo = _ref.disableFreeSolo, open = _ref.open, onFocus = _ref.onFocus, onBlur = _ref.onBlur, defaultOpen = _ref.defaultOpen, props = _objectWithoutProperties(_ref, ["variant", "options", "defaultValue", "onSelect", "onSearch", "onChange", "searching", "onClearClick", "children", "size", "value", "width", "clearable", "disabled", "dropdownClassName", "dropdownStyle", "disableMatchWidth", "disableFreeSolo", "open", "onFocus", "onBlur", "defaultOpen"]); var isValueControlled = value !== undefined; var isOpenControlled = open !== undefined; var autoCompleteDivRef = useRef(null); var _useAutoCompleteHandl = useAutoCompleteHandle(), inputRef = _useAutoCompleteHandl.ref, focusInput = _useAutoCompleteHandl.focus; useImperativeHandle(ref, function () { return inputRef.current; }); var resetTimer = useRef(); var _useState = useState(defaultValue || ''), _useState2 = _slicedToArray(_useState, 2), inputValue = _useState2[0], setInputValue = _useState2[1]; var computedInputValue = isValueControlled ? value : inputValue; var _useState3 = useState(defaultValue || ''), _useState4 = _slicedToArray(_useState3, 2), selectVal = _useState4[0], setSelectVal = _useState4[1]; var _useState5 = useState(defaultOpen), _useState6 = _slicedToArray(_useState5, 2), dropdownOpen = _useState6[0], setDropdownOpen = _useState6[1]; var isDropdownOpen = isOpenControlled ? open : dropdownOpen; var _useState7 = useState(false), _useState8 = _slicedToArray(_useState7, 2), focus = _useState8[0], setFocus = _useState8[1]; var _pickChild = pickChild(children, AutoCompleteSearching), _pickChild2 = _slicedToArray(_pickChild, 2), searchChild = _pickChild2[1]; var _pickChild3 = pickChild(children, AutoCompleteEmpty), _pickChild4 = _slicedToArray(_pickChild3, 2), emptyChild = _pickChild4[1]; var autoCompleteItems = useMemo(function () { var hasSearchChild = searchChild && React.Children.count(searchChild) > 0; var hasEmptyChild = emptyChild && React.Children.count(emptyChild) > 0; if (searching) { return hasSearchChild ? searchChild : /*#__PURE__*/React.createElement(AutoCompleteSearching, null, "Searching..."); } if (options.length === 0) { if (computedInputValue === '') return null; return hasEmptyChild ? emptyChild : /*#__PURE__*/React.createElement(AutoCompleteEmpty, null, "No Options"); } return childrenToOptionsNode(options, variant); }, [searching, options, variant]); var showClearIcon = useMemo(function () { return clearable && searching === undefined; }, [clearable, searching]); var onSelectHandler = function onSelectHandler(val) { if (disabled) return; setSelectVal(val); onSelect && onSelect(val); if (!isValueControlled) setInputValue(val); focusInput(); }; var onInputChange = function onInputChange(event) { if (!isOpenControlled) setDropdownOpen(true); if (!isValueControlled) setInputValue(event.target.value); onSearch && onSearch(event.target.value); }; var resetInputValueOnClickAway = function resetInputValueOnClickAway() { if (isValueControlled) return; if (!disableFreeSolo) return; if (!computedInputValue || computedInputValue === '') return; if (computedInputValue !== selectVal) { setInputValue(selectVal); } }; var defaultContextValue = useMemo(function () { return { ref: autoCompleteDivRef, size: size, focus: focus, value: computedInputValue, onSelect: onSelectHandler, visible: isDropdownOpen, updateVisible: function updateVisible(open) { if (!isOpenControlled) setDropdownOpen(open); } }; }, [computedInputValue, isDropdownOpen, size, focus]); var onInputFocus = function onInputFocus(e) { setFocus(true); onFocus && onFocus(e); if (!isOpenControlled) setDropdownOpen(true); clearTimeout(resetTimer.current); }; var onInputClearClick = function onInputClearClick(event) { if (!isValueControlled) setInputValue(''); onClearClick && onClearClick(event); }; useClickAway(autoCompleteDivRef, function (e) { if (!isOpenControlled) setDropdownOpen(false); resetTimer.current = window.setTimeout(function () { resetInputValueOnClickAway(); clearTimeout(resetTimer.current); onBlur && onBlur(e); setFocus(false); }, DEFAULT_CSS_TRANSITION_LEAVE_TIME); }); var inputProps = _extends(_extends({}, props), {}, { value: computedInputValue, defaultValue: undefined, width: width, disabled: disabled }); var dropdownVisible = isOpenControlled ? open : dropdownOpen && Boolean(autoCompleteItems); useEffect(function () { onChange && onChange(computedInputValue); }, [computedInputValue]); return /*#__PURE__*/React.createElement(AutoCompleteContext.Provider, { value: defaultContextValue }, /*#__PURE__*/React.createElement("div", { ref: autoCompleteDivRef, className: _JSXStyle.dynamic([["297735136", [width]]]) + " " + "auto-complete ".concat(variant === 'solid' ? 'solid' : 'line') }, /*#__PURE__*/React.createElement(CSSTransition, { renderable: true, visible: dropdownVisible, clearTime: computedInputValue === '' ? 0 : 60, leaveTime: computedInputValue === '' ? 0 : 60, className: "in-auto-complete ".concat(focus ? 'auto-complete-focus' : '') }, /*#__PURE__*/React.createElement(Input, _extends({ variant: variant, ref: inputRef, size: size, onChange: onInputChange, onFocus: onInputFocus, onClick: onInputFocus, clearable: showClearIcon, onClearClick: onInputClearClick, iconRight: getSearchIcon(searching) }, inputProps))), /*#__PURE__*/React.createElement(AutoCompleteDropdown, { variant: variant, visible: dropdownVisible, disableMatchWidth: disableMatchWidth, className: dropdownClassName, dropdownStyle: dropdownStyle }, autoCompleteItems), /*#__PURE__*/React.createElement(_JSXStyle, { id: "297735136", dynamic: [width] }, ".auto-complete.__jsx-style-dynamic-selector{width:".concat(width, ";}.auto-complete.__jsx-style-dynamic-selector .loading{left:-3px;right:-3px;width:-webkit-max-content;width:-moz-max-content;width:max-content;}.auto-complete.__jsx-style-dynamic-selector .in-auto-complete .input-wrapper{-webkit-transition:0s;transition:0s;}.auto-complete.__jsx-style-dynamic-selector .in-auto-complete.transition-leave .input-wrapper.focus:not(.disabled),.auto-complete.__jsx-style-dynamic-selector .in-auto-complete.transition-enter .input-wrapper.focus:not(.disabled){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-color:transparent;}")))); }); var AutoCompleteComponent = AutoComplete; AutoCompleteComponent.defaultProps = defaultProps; AutoCompleteComponent.Item = AutoCompleteItem; AutoCompleteComponent.Option = AutoCompleteItem; AutoCompleteComponent.Searching = AutoCompleteSearching; AutoCompleteComponent.Empty = AutoCompleteEmpty; AutoCompleteComponent.useAutoCompleteHandle = useAutoCompleteHandle; export { useAutoCompleteHandle }; export default AutoCompleteComponent;