UNPKG

@prefect9/ui

Version:

UI React components

343 lines (340 loc) 14.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "UserCustomizedOption", { enumerable: true, get: function get() { return _Option.default; } }); exports.default = void 0; require("core-js/modules/es.array.includes.js"); require("core-js/modules/es.promise.js"); require("core-js/modules/es.regexp.constructor.js"); require("core-js/modules/es.regexp.exec.js"); require("core-js/modules/es.regexp.test.js"); require("core-js/modules/es.regexp.to-string.js"); require("core-js/modules/es.string.replace.js"); require("core-js/modules/es.string.trim.js"); require("core-js/modules/web.dom-collections.iterator.js"); var _react = require("react"); var _isType = require("@prefect9/is-type"); var _index = require("../../index"); var _icons = _interopRequireDefault(require("../../icons")); var _Scroll = _interopRequireDefault(require("../Scroll")); var _Option = _interopRequireDefault(require("./Option")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } const UserCustomizedSelect = /*#__PURE__*/(0, _react.forwardRef)((_ref, outsideApiRef) => { let { state, children, label, placeholder = '', onChange: changeHandler, disabled } = _ref; const insideApiRef = (0, _react.useRef)(null); const apiRef = outsideApiRef !== null && outsideApiRef !== void 0 ? outsideApiRef : insideApiRef; const fieldRef = (0, _react.useRef)(null); const [text, setText] = (0, _react.useState)(null); const options = (0, _react.useMemo)(() => { const result = []; const childrenArray = _react.Children.toArray(children); for (let option of childrenArray) { if (option.type !== _Option.default) throw new Error('Option must be user customized option'); const value = option.props.value; if (!(0, _isType.isStr)(value)) throw new Error('Value of option must be string'); let name = option.props.name; if (!(0, _isType.isStr)(name)) throw new Error('Name of option must be string'); name = name.toLowerCase().trim().replace(/\s+/, ' '); result.push({ el: option, value, name }); } return result; }, [children]); const optionsWithCreateButton = (0, _react.useMemo)(() => { const nowText = (0, _isType.isStr)(text) ? text.toLowerCase().trim().replace(/\s+/, ' ') : null; const filteredOptions = []; const filter = (0, _isType.isStr)(nowText) && nowText.length > 0 ? new RegExp((0, _index.escapeRegExp)(nowText), 'i') : null; for (let index in options) { let option = options[index]; if (!filter || filter.test(option.name)) filteredOptions.push(option); } const result = []; let issetName = false; for (let index in filteredOptions) { let option = filteredOptions[index]; if ((0, _isType.isStr)(text) && option.name === nowText) issetName = true; result.push( /*#__PURE__*/(0, _react.cloneElement)(option.el, _objectSpread(_objectSpread({}, option.el.props), {}, { key: index }))); } if (!issetName && (0, _isType.isStr)(text) && text.length > 0) result.push( /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { className: "prefect9-user-customized-select__create", children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { children: ["Add new \"", text, "\""] })] }, 'create')); return result; }, [options, text]); const optionsContent = (0, _react.useMemo)(() => { if (optionsWithCreateButton.length) return optionsWithCreateButton; return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "prefect9-user-customized-select__empty", children: "Nothing was found" }); }, [optionsWithCreateButton]); const [focus, setFocus] = (0, _react.useState)(false); (0, _react.useEffect)(() => { if (!(0, _isType.isObj)(fieldRef) || !fieldRef.current) return; if (!(0, _isType.isObj)(apiRef)) return; const input = fieldRef.current.querySelector('.prefect9-user-customized-select__input'); if (!(0, _isType.isObj)(apiRef.current)) apiRef.current = { input, value: '', focus: false, isSelected: false, disabled: false }; const api = apiRef.current; const saveValue = newValue => { api.value = newValue; setText(newValue.trim().length < 1 ? null : newValue); }; const setValue = newValue => { api.input.value = newValue; saveValue(newValue); }; const selectOption = (value, text) => { if (!(0, _isType.isFunc)(changeHandler)) return; changeHandler({ type: 'selected', value, text }); /*api.selected = 'option' setValue(text) changeHandler({ type: 'option', value, text }) blur() api.input.setAttribute('disabled', 'disabled')*/ }; const createOption = () => { if (!(0, _isType.isFunc)(changeHandler)) return; const text = api.value; changeHandler({ type: 'created', value: null, text }); /*api.selected = 'create_option' const text = api.value setValue(text) changeHandler({ type: 'create_option', text }) blur() api.input.setAttribute('disabled', 'disabled')*/ }; const clearSelect = () => { if (!(0, _isType.isFunc)(changeHandler)) return; changeHandler(null); /*api.isSelected = false setValue('') api.input.removeAttribute('disabled', 'disabled') focus()*/ /*api.selected = null setValue('') changeHandler(null) api.input.removeAttribute('disabled', 'disabled') focus()*/ }; const focus = () => { if (api.isSelected) return; api.focus = true; api.input.focus(); setFocus(true); }; api.focus = focus; const blur = () => { api.focus = false; api.input.blur(); setFocus(false); if (!api.isSelected) setValue(''); }; api.blur = blur; const keyDownHandler = e => { const keyCode = e.code; if (keyCode === 'Enter') e.preventDefault(); }; api.input.addEventListener('keydown', keyDownHandler); const inputHandler = () => { const newValue = api.input.value; saveValue(newValue); }; api.input.addEventListener('input', inputHandler); const clickHandler = e => { const target = e.target; const fieldParent = target.closest('.prefect9-user-customized-select'); const isField = target.classList.contains('prefect9-user-customized-select') && target === fieldRef.current || fieldParent && fieldParent === fieldRef.current; if (isField && !api.disabled) { const inputParent = target.closest('.prefect9-user-customized-select__input'); const isInput = target.classList.contains('prefect9-user-customized-select__input') || inputParent; const labelParent = target.closest('.prefect9-field__label'); const isLabel = target.classList.contains('prefect9-field__label') || labelParent; const arrowParent = target.closest('.prefect9-user-customized-select__arrow'); const isArrow = target.classList.contains('prefect9-user-customized-select__arrow') || arrowParent; const closeParent = target.closest('.prefect9-user-customized-select__close'); const isClose = target.classList.contains('prefect9-user-customized-select__close') || closeParent; const optionParent = target.closest('.prefect9-user-customized-select__option'); const isOpiton = target.classList.contains('prefect9-user-customized-select__option') || optionParent; const newOptionParent = target.closest('.prefect9-user-customized-select__create'); const isNewOpiton = target.classList.contains('prefect9-user-customized-select__create') || newOptionParent; if (isNewOpiton) createOption();else if (isOpiton) { const option = target.classList.contains('prefect9-user-customized-select__option') ? target : optionParent; const value = option.getAttribute('data-value'); const text = option.innerText; selectOption(value, text); } else if (isClose) clearSelect();else if (isInput || isLabel || isArrow) focus();else blur(); } else blur(); }; window.addEventListener('click', clickHandler); const update = () => { if (api.isSelected) { setValue(api.value); api.input.setAttribute('disabled', 'disabled'); blur(); } else { setValue(''); api.input.removeAttribute('disabled', 'disabled'); } }; api.update = update; return () => { if (api.input) api.input.removeEventListener('keydown', keyDownHandler); if (api.input) api.input.removeEventListener('input', inputHandler); if (window) window.removeEventListener('click', clickHandler); }; }, [fieldRef, apiRef, changeHandler]); (0, _react.useEffect)(() => { if (!(0, _isType.isObj)(apiRef)) return; const api = apiRef.current; if (!(0, _isType.isFunc)(api.update)) return; if ((0, _isType.isObj)(state) && (0, _isType.isStr)(state.type) && (0, _isType.isStr)(state.name) && ['selected', 'created'].includes(state.type)) { api.isSelected = true; api.value = state.name; } else { api.isSelected = false; api.value = ''; } api.update(); }, [apiRef, state]); (0, _react.useEffect)(() => { if (!(0, _isType.isObj)(apiRef)) return; const api = apiRef.current; api.disabled = disabled; }, [apiRef, disabled]); const [modalSize, setModalSize] = (0, _react.useState)({ width: 0, left: 0, top: 0 }); (0, _react.useEffect)(() => { if (!(0, _isType.isObj)(fieldRef) || !fieldRef.current) return; if (!(0, _isType.isObj)(apiRef) || !(0, _isType.isObj)(apiRef.current)) return; const api = apiRef.current; const field = fieldRef.current.querySelector('.prefect9-user-customized-select__field'); const modal = fieldRef.current.querySelector('.prefect9-user-customized-select__modal'); let nowSize = { width: 0, left: 0, top: 0 }; const setSize = (width, left, top) => { if (width === nowSize.width && left === nowSize.left && top === nowSize.top) return; nowSize = { width, left, top }; setModalSize(nowSize); }; const resize = () => { const size = field.getBoundingClientRect(); const width = size.width; const left = size.left; const top = size.top + size.height + 4; setSize(width, left, top); }; api.resize = resize; resize(); window.addEventListener('resize', resize, { passive: true }); window.addEventListener('mousewheel', resize, { passive: true }); const resizeObserver = new ResizeObserver(resize); resizeObserver.observe(field); resizeObserver.observe(modal); return () => { if (window) window.removeEventListener('resize', resize, { passive: true }); if (window) window.removeEventListener('mousewheel', resize, { passive: true }); resizeObserver.disconnect(); }; }, [fieldRef, apiRef]); (0, _react.useEffect)(() => { if (!(0, _isType.isObj)(apiRef) || !(0, _isType.isObj)(apiRef.current) || !(0, _isType.isFunc)(apiRef.current.resize)) return; apiRef.current.resize(); }, [apiRef, focus]); const isSelected = (0, _react.useMemo)(() => { return (0, _isType.isObj)(state) && (0, _isType.isStr)(state.type) && ['selected', 'created'].includes(state.type); }, [state]); const className = (0, _react.useMemo)(() => { const result = ['prefect9-field', 'prefect9-user-customized-select']; if (focus && !disabled) result.push('prefect9-user-customized-select__show-modal'); if (isSelected) result.push('prefect9-user-customized-select__selected'); return result.join(' '); }, [focus, isSelected, disabled]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { ref: fieldRef, className: className, children: [(0, _isType.isStr)(label) && label.length ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "prefect9-field__label", children: label }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { className: "prefect9-user-customized-select__field", children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", { className: "prefect9-user-customized-select__input", placeholder: placeholder, disabled: disabled }), isSelected ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.default.Close, { className: "prefect9-ico prefect9-user-customized-select__close" }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.default.ArrowBottom, { className: "prefect9-ico prefect9-user-customized-select__arrow" })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "prefect9-user-customized-select__modal", style: { width: "".concat(modalSize.width, "px"), left: "".concat(modalSize.left, "px"), top: "".concat(modalSize.top, "px") }, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scroll.default, { children: optionsContent }) })] }); }); var _default = exports.default = UserCustomizedSelect;