UNPKG

sailboat-design

Version:
141 lines (140 loc) 6.14 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useState, createContext, useRef, useEffect } from 'react'; import classNames from 'classnames'; import Input from '../Input'; import Icon from '../Icon'; import useClickOutside from '../../hooks/useClickOutside'; import Transition from '../Transition/transition'; export var SelectContext = createContext({ selectedValues: [] }); /** * 下拉选择器。 * 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。 * ### 引用方法 * * ~~~js * import { Select } from 'sailboatship' * // 然后可以使用 <Select> 和 <Select.Option> * ~~~ */ export var Select = function (props) { var defaultValue = props.defaultValue, placeholder = props.placeholder, children = props.children, multiple = props.multiple, name = props.name, disabled = props.disabled, onChange = props.onChange, onVisibleChange = props.onVisibleChange; var input = useRef(null); var containerRef = useRef(null); var containerWidth = useRef(0); var _a = useState(Array.isArray(defaultValue) ? defaultValue : []), selectedValues = _a[0], setSelectedValues = _a[1]; var _b = useState(false), menuOpen = _b[0], setOpen = _b[1]; var _c = useState(typeof defaultValue === 'string' ? defaultValue : ''), value = _c[0], setValue = _c[1]; var handleOptionClick = function (value, isSelected) { // update value if (!multiple) { setOpen(false); setValue(value); if (onVisibleChange) { onVisibleChange(false); } } else { setValue(''); } var updatedValues = [value]; // click again to remove selected when is multiple mode if (multiple) { updatedValues = isSelected ? selectedValues.filter(function (v) { return v !== value; }) : __spreadArray(__spreadArray([], selectedValues, true), [value], false); setSelectedValues(updatedValues); } if (onChange) { onChange(value, updatedValues); } }; useEffect(function () { // focus input if (input.current) { input.current.focus(); if (multiple && selectedValues.length > 0) { input.current.placeholder = ''; } else { if (placeholder) input.current.placeholder = placeholder; } } }, [selectedValues, multiple, placeholder]); useEffect(function () { if (containerRef.current) { containerWidth.current = containerRef.current.getBoundingClientRect().width; } }); useClickOutside(containerRef, function () { setOpen(false); if (onVisibleChange && menuOpen) { onVisibleChange(false); } }); var passedContext = { onSelect: handleOptionClick, selectedValues: selectedValues, multiple: multiple }; var handleClick = function (e) { e.preventDefault(); if (!disabled) { setOpen(!menuOpen); if (onVisibleChange) { onVisibleChange(!menuOpen); } } }; var generateOptions = function () { return React.Children.map(children, function (child, i) { var childElement = child; if (childElement.type.displayName === 'Option') { return React.cloneElement(childElement, { index: "select-".concat(i) }); } else { console.error('Warning: Select has a child which is not a Option component'); } }); }; var containerClass = classNames('sailboat-select', { 'menu-is-open': menuOpen, 'is-disabled': disabled, 'is-multiple': multiple }); return (_jsxs("div", __assign({ className: containerClass, ref: containerRef }, { children: [_jsx("div", __assign({ className: "sailboat-select-input", onClick: handleClick }, { children: _jsx(Input, { ref: input, placeholder: placeholder, value: value, readOnly: true, icon: "angle-down", disabled: disabled, name: name }) })), _jsx(SelectContext.Provider, __assign({ value: passedContext }, { children: _jsx(Transition, __assign({ in: menuOpen, animation: "zoom-in-top", timeout: 300 }, { children: _jsx("ul", __assign({ className: "sailboat-select-dropdown" }, { children: generateOptions() })) })) })), multiple && (_jsx("div", __assign({ className: "sailboat-selected-tags", style: { maxWidth: containerWidth.current - 32 } }, { children: selectedValues.map(function (value, index) { return (_jsxs("span", __assign({ className: "sailboat-tag" }, { children: [value, _jsx(Icon, { className: "sailboat-tag_icon", icon: "times", onClick: function () { handleOptionClick(value, true); } })] }), "tag-".concat(index))); }) })))] }))); }; Select.defaultProps = { name: 'sailboat-select', placeholder: '请选择' }; export default Select;