ultra-design
Version:
324 lines (284 loc) • 11.4 kB
JavaScript
import _taggedTemplateLiteral from '@babel/runtime/helpers/taggedTemplateLiteral';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import React, { forwardRef, useRef, useState, useCallback, useMemo, isValidElement, useEffect, useImperativeHandle } from 'react';
import { selectStyles, selectLayerStyles } from './select-style.js';
import clsx from 'clsx';
import Option from './option.js';
import { Close, Up, Down } from '@icon-park/react';
import Trigger from '../trigger/trigger.js';
import { useMergeProps } from '../utils/mergeProps.js';
import withStyle from '../utils/withStyle.js';
import { css } from '@emotion/react';
import { jsxs, jsx } from '@emotion/react/jsx-runtime';
var _templateObject;
var _excluded = ["onClick", "onMouseEnter", "className"];
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (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 = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var defaultProps = {
name: 'ultra-select'
};
var SelectComponent = /*#__PURE__*/forwardRef(function (p, ref) {
var props = useMergeProps(defaultProps, p);
var disabled = props.disabled,
onChange = props.onChange,
value = props.value,
defaultValue = props.defaultValue,
placeholder = props.placeholder,
clearable = props.clearable,
filterable = props.filterable,
children = props.children,
className = props.className,
style = props.style;
var selfRef = useRef(null);
var _useState = useState(''),
_useState2 = _slicedToArray(_useState, 2),
inputValue = _useState2[0],
setInputValue = _useState2[1];
var _useState3 = useState(true),
_useState4 = _slicedToArray(_useState3, 2),
filterFinished = _useState4[0],
setFilterFinished = _useState4[1];
var _useState5 = useState('value' in props ? value : defaultValue),
_useState6 = _slicedToArray(_useState5, 2),
selectValue = _useState6[0],
setSelectValue = _useState6[1];
var _useState7 = useState(-1),
_useState8 = _slicedToArray(_useState7, 2),
hoverIndex = _useState8[0],
setHoverIndex = _useState8[1];
var _useState9 = useState(false),
_useState10 = _slicedToArray(_useState9, 2),
dropdownVisivle = _useState10[0],
setDropdownVisivle = _useState10[1];
var _useState11 = useState(false),
_useState12 = _slicedToArray(_useState11, 2),
focus = _useState12[0],
setFocus = _useState12[1];
var _useState13 = useState('0'),
_useState14 = _slicedToArray(_useState13, 2),
layerMinWidth = _useState14[0],
setLayerMinWidth = _useState14[1];
var selfFilterMethod = function selfFilterMethod(option) {
var label_ = 'label' in option ? option.label : typeof option.children === 'string' ? option.children : '';
if (!label_) return false;
return label_.toLowerCase().includes(inputValue.toLowerCase());
};
var filterMethod = useCallback(function (option) {
if (typeof filterable === 'function') {
return filterable(inputValue, option);
} else {
return selfFilterMethod(option);
}
}, [filterable, inputValue]);
var optionList = useMemo(function () {
var childs = [];
React.Children.toArray(children).forEach(function (child) {
if ( /*#__PURE__*/isValidElement(child)) {
childs.push(child.props);
}
});
return childs;
}, [children]);
var filteredOptionList = useMemo(function () {
var filteredData = !filterable || filterFinished ? optionList : optionList.filter(filterMethod);
return filteredData;
}, [filterable, filterFinished, optionList, filterMethod]);
var selectIndex = filteredOptionList.findIndex(function (opt) {
return (opt.value || opt.label || opt.children) === selectValue;
});
var selectionLabel = useMemo(function () {
if (!selectValue) return undefined;
if (selectIndex >= 0) {
setHoverIndex(selectIndex);
var _filteredOptionList$s = filteredOptionList[selectIndex],
_children = _filteredOptionList$s.children,
label = _filteredOptionList$s.label;
if (filterable) {
setInputValue(typeof _children === 'string' ? _children : label);
}
return _children || label;
}
}, [selectValue, filteredOptionList, selectIndex]);
useEffect(function () {
setSelectValue(value);
}, [value]);
useImperativeHandle(ref, function () {
return {
value: selectValue
};
}, [selectValue]);
var handleChange = function handleChange(data) {
var optionValue = data.value;
var finalValue = optionValue !== null && optionValue !== void 0 ? optionValue : data.children || data.label;
setSelectValue(finalValue);
if (!data.label && typeof data.children === 'string') {
setInputValue(data.children);
}
setFilterFinished(true);
var v = filteredOptionList.find(function (o) {
return o.value === optionValue;
});
if (v) {
setTimeout(function () {
onChange === null || onChange === void 0 ? void 0 : onChange(finalValue);
});
}
setDropdownVisivle(false);
};
var handleKeyDown = function handleKeyDown(e) {
e.preventDefault();
var optsLen = filteredOptionList.length;
if (disabled || !optsLen) return;
if (filteredOptionList.every(function (o) {
return o.disabled;
})) return;
if (e.code === 'ArrowDown' && dropdownVisivle) {
setHoverIndex(function (i) {
while (filteredOptionList[(i + 1) % optsLen].disabled) {
i += 1;
}
return (i + 1) % optsLen;
});
} else if (e.code === 'ArrowUp' && dropdownVisivle) {
setHoverIndex(function (i) {
while (filteredOptionList[(i - 1 + optsLen) % optsLen].disabled) {
i -= 1;
}
return (i - 1 + optsLen) % optsLen;
});
} else if (e.code === 'Enter') {
var noHover = hoverIndex <= -1;
if (noHover) {
return;
}
setDropdownVisivle(!dropdownVisivle);
if (dropdownVisivle && !noHover) {
if (!filteredOptionList[hoverIndex]) {
return;
}
handleChange(filteredOptionList[hoverIndex]);
}
}
};
var handleInputKeyDown = function handleInputKeyDown(_e) {
_e.stopPropagation(); // if (!['ArrowDown', 'ArrowUp', 'Enter', 'Backspace'].includes(e.code)) {
// e.stopPropagation();
// }
};
var handleMouseDown = function handleMouseDown(e) {
if (dropdownVisivle) {
e.preventDefault();
}
};
var handleInput = function handleInput(e) {
setInputValue(e.currentTarget.value);
setDropdownVisivle(true);
setFilterFinished(false);
};
var handleClear = function handleClear() {
setInputValue('');
setSelectValue(undefined);
setTimeout(function () {
onChange === null || onChange === void 0 ? void 0 : onChange(selectValue);
});
};
useEffect(function () {
if (!dropdownVisivle && !filteredOptionList.length) {
if (typeof selectionLabel === 'string') {
setInputValue(selectionLabel);
}
}
}, [dropdownVisivle]);
var renderOptionItem = function renderOptionItem(props, index) {
var _onClick = props.onClick,
_onMouseEnter = props.onMouseEnter,
className = props.className,
rest = _objectWithoutProperties(props, _excluded);
var idx = filteredOptionList.findIndex(function (opt) {
return (opt.value || opt.children || opt.label) === selectValue;
});
return /*#__PURE__*/React.cloneElement(jsx(Option, {}), _objectSpread(_objectSpread({}, rest), {}, {
key: index,
id: "ultra-select-option_".concat(index),
className: clsx(className, idx === index && 'ultra-select-option--active', hoverIndex === index && 'ultra-select-option--hover'),
onClick: function onClick(e) {
_onClick === null || _onClick === void 0 ? void 0 : _onClick(e);
!props.disabled && handleChange(props);
},
onMouseEnter: function onMouseEnter(e) {
_onMouseEnter === null || _onMouseEnter === void 0 ? void 0 : _onMouseEnter(e);
setHoverIndex(index);
}
}));
};
return jsxs("div", {
className: clsx(['ultra-select', className, focus && 'ultra-select--focused', disabled && 'ultra-select--disabled']),
tabIndex: 1,
style: style,
css: selectStyles(props),
onKeyDown: handleKeyDown,
onMouseDown: handleMouseDown,
onFocus: function onFocus() {
return setFocus(true);
},
onBlur: function onBlur() {
return setFocus(false);
},
ref: function ref(node) {
if (!node) return;
selfRef.current = node;
setLayerMinWidth(getComputedStyle(node).width);
},
children: [jsx(Trigger, _objectSpread(_objectSpread({
triggerRef: selfRef,
visible: dropdownVisivle,
showDelay: 0,
onVisibleChange: function onVisibleChange(v) {
return setDropdownVisivle(v);
},
showArrow: false,
placement: "bottomLeft",
trigger: "click",
content: filteredOptionList.length ? filteredOptionList.map(renderOptionItem) : jsx("p", {
style: {
textAlign: 'center'
},
children: "No Data"
})
}, props), {}, {
name: "ultra-select",
transitionClassName: "ultra-select-layer-slide",
getLayerContainer: function getLayerContainer(node) {
return node === null || node === void 0 ? void 0 : node.parentNode;
},
css: [selectLayerStyles(props), css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n min-width: ", ";\n "])), layerMinWidth)]
})), filterable ? jsx("input", {
onKeyDown: handleInputKeyDown,
onInput: handleInput,
value: inputValue,
disabled: disabled,
placeholder: placeholder
}) : jsx("div", {
className: "ultra-select__selection",
children: selectionLabel || selectValue || jsx("span", {
className: "ultra-select__placeholder",
children: placeholder
})
}), jsx("div", {
className: "ultra-select__icon",
children: clearable ? jsx(Close, {
onClick: handleClear
}) : dropdownVisivle ? jsx(Up, {
className: "ultra-icon"
}) : jsx(Down, {
className: "ultra-icon"
})
})]
});
});
SelectComponent.displayName = 'UltraSelect';
var Select = withStyle(SelectComponent);
var SelectComponent$1 = Select;
export { SelectComponent$1 as default };