UNPKG

phx-react

Version:

PHX REACT

162 lines 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PHXCombobox = void 0; const tslib_1 = require("tslib"); const solid_1 = require("@heroicons/react/24/solid"); const react_1 = tslib_1.__importStar(require("react")); const Checkbox_1 = require("../Checkbox"); const ErrorMessage_1 = tslib_1.__importDefault(require("../../commons/ErrorMessage")); const types_1 = require("../types"); const helpers_1 = require("../../helpers/helpers"); const remove_vn_tones_1 = require("../SelectWithAction/remove-vn-tones"); const PHXCombobox = ({ className, defaultValue, disabled = false, error, id, label, listOptions, onChange, optionHeight = 300, placeholder, selectFieldPosition = 'bottom', errorType, errorMessageCustom, helpText, isAllOptions = true, }) => { const message = (type) => { let errorMessage = ''; switch (type) { case 'required-field': errorMessage = 'Vui lòng chọn thông tin'; break; case 'duplicate-field': errorMessage = 'Thông tin đã tồn tại'; break; case 'custom-message': errorMessage = errorMessageCustom; break; default: break; } return errorMessage; }; const inputRef = (0, react_1.useRef)(null); const [isFocused, setIsFocused] = (0, react_1.useState)(false); const [selectedItems, setSelectedItems] = (0, react_1.useState)(defaultValue || []); const isHaveSelected = selectedItems.length > 0; const [options, setOptions] = (0, react_1.useState)(listOptions || []); const checkedAll = (listOptions === null || listOptions === void 0 ? void 0 : listOptions.length) === (selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length); const wrapperRef = (0, react_1.useRef)(null); const handleChange = (data) => { if (onChange) { onChange(data); } }; function clearInput() { if (inputRef.current) { inputRef.current.value = ''; } } const handleItemClick = (item) => { clearInput(); const isSelected = selectedItems.some((selectedItem) => selectedItem.id === item.id); if (isSelected) { const newSelectedItem = selectedItems.filter((selectedItem) => selectedItem.id !== item.id); setSelectedItems(newSelectedItem); handleChange(newSelectedItem); return; } setOptions(listOptions); handleChange([...selectedItems, item]); setSelectedItems([...selectedItems, item]); }; const handleRemoveItem = (item) => { const newSelectedItems = selectedItems.filter((selectedItem) => selectedItem.id !== item.id); setSelectedItems(newSelectedItems); handleChange(newSelectedItems); }; const handleChangeInput = (value) => { if (value === '') { setOptions(listOptions); } else { const searchValue = value.toLowerCase().trim(); const searchValueUnaccent = (0, remove_vn_tones_1.normalizeVietnameseText)(searchValue); const filteredOptions = listOptions.filter((option) => { var _a, _b; const nameOriginal = (option.name || '').toLowerCase(); const nameUnaccent = (option.name_unaccent || (0, remove_vn_tones_1.normalizeVietnameseText)(nameOriginal)).toLowerCase(); return (nameOriginal.includes(searchValue) || nameUnaccent.includes(searchValueUnaccent) || ((_b = (_a = option === null || option === void 0 ? void 0 : option.name_unaccent) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === null || _b === void 0 ? void 0 : _b.includes((0, helpers_1.unaccentValue)(searchValue)))); }); setOptions(filteredOptions); } }; const handleCheckAll = () => { if (checkedAll) { setSelectedItems([]); handleChange([]); } else { clearInput(); setSelectedItems(options); handleChange(options); } }; (0, react_1.useEffect)(() => { const handleClickOutside = (event) => { var _a; if (wrapperRef.current && !((_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) { setOptions(listOptions); setIsFocused(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [wrapperRef, listOptions]); (0, react_1.useEffect)(() => { setOptions(listOptions); }, [listOptions]); (0, react_1.useEffect)(() => { if (defaultValue) { setSelectedItems(defaultValue); } }, [defaultValue]); return (react_1.default.createElement("div", { className: className, id: id }, label && react_1.default.createElement("label", { className: 'mb-1 block text-xs font-normal text-gray-700' }, label), react_1.default.createElement("div", { ref: wrapperRef, className: 'relative w-full rounded-lg bg-gray-100' }, react_1.default.createElement("div", { className: `${error ? 'border-red-800 bg-red-50 hover:bg-red-50 focus:border-red-800 focus:bg-red-50' : ''} ${!disabled ? 'hover:bg-gray-50' : isHaveSelected ? 'border-0 !bg-gray-100 py-1.5' : 'border-0'} shadow-sm block w-full space-y-1 rounded-lg border border-gray-500 bg-white text-sm focus:border-gray-500 focus:bg-gray-50 focus:outline-none focus:outline-offset-1 focus:outline-indigo-500 focus:ring-transparent ` }, selectedItems.length > 0 && !checkedAll && listOptions.length > 0 && (react_1.default.createElement("div", { className: (0, types_1.classNames)('mx-2 flex flex-wrap items-center gap-2', !disabled && 'mt-2') }, selectedItems.map((item) => (react_1.default.createElement("div", { key: item.name + item.id, className: 'flex items-center rounded-xl bg-gray-200' }, react_1.default.createElement("p", { style: { wordBreak: 'break-word', }, className: `text-wrap pl-2 text-xs text-gray-700 ${disabled ? 'py-[2px] pr-2' : 'pr-[2px]'}` }, item.name), !disabled && (react_1.default.createElement("button", { className: 'rounded-xl p-[3px] hover:cursor-pointer hover:bg-gray-300', onClick: () => handleRemoveItem(item), type: 'button' }, react_1.default.createElement(solid_1.XMarkIcon, { className: 'h-4 w-4' })))))))), react_1.default.createElement("input", { ref: inputRef, className: (0, types_1.classNames)('w-full rounded-lg border-none border-transparent py-[0.4rem] pl-3 text-xs outline-none focus:border-none focus:border-transparent focus:ring-0 ', disabled ? 'disabled:bg-neutral-200' : '', disabled && isHaveSelected && 'hidden'), disabled: disabled, id: 'main', tabIndex: -1, onChange: (e) => handleChangeInput(e.target.value), onFocus: () => setIsFocused(true), placeholder: selectedItems.length === (listOptions === null || listOptions === void 0 ? void 0 : listOptions.length) && selectedItems.length > 0 ? 'Tất cả' : placeholder })), options.length > 0 ? (react_1.default.createElement("div", { // eslint-disable-next-line prettier/prettier className: `shadow-xl absolute z-50 mt-2 w-full overflow-y-auto rounded-lg border bg-white p-2 ${!isFocused ? 'hidden' : ''}`, style: { maxHeight: optionHeight, ...(selectFieldPosition === 'top' ? { bottom: '100%', marginBottom: '2px' } : { top: '100%', marginTop: '8px' }), } }, isAllOptions && (react_1.default.createElement("div", { key: 'selectAllCheckBox', className: 'relative mb-1 rounded-lg px-2 py-[1.5px] hover:bg-gray-200' }, react_1.default.createElement(Checkbox_1.PHXCheckbox, { checked: checkedAll, className: 'mb-1 rounded-lg px-2 py-[1.5px] hover:bg-gray-200', id: `checkbox_${Math.floor(Math.random() * 1000000) + 1}`, onClick: () => { handleCheckAll(); }, title: 'T\u1EA5t c\u1EA3' }), react_1.default.createElement("button", { className: 'absolute inset-0 cursor-pointer', onClick: () => { handleCheckAll(); }, type: 'button' }))), options === null || options === void 0 ? void 0 : options.map((item) => { const randomNum = Math.floor(Math.random() * 1000000) + 1; return (react_1.default.createElement("div", { key: item.id, className: 'relative mb-1 rounded-lg px-2 py-[1.5px] hover:bg-gray-200' }, react_1.default.createElement(Checkbox_1.PHXCheckbox, { checked: selectedItems.some((selectedItem) => selectedItem.id === item.id), className: 'mb-1 rounded-lg px-2 py-[1.5px] hover:bg-gray-200', id: `checkbox_${randomNum}`, onClick: () => handleItemClick(item), title: item.name }), react_1.default.createElement("button", { className: 'absolute inset-0 cursor-pointer', onClick: () => handleItemClick(item), type: 'button' }))); }))) : (react_1.default.createElement("div", { // eslint-disable-next-line prettier/prettier className: `shadow-xl absolute z-50 mt-2 w-full overflow-y-auto rounded-lg bg-white p-2 ${!isFocused ? 'hidden' : ''}`, style: { ...(selectFieldPosition === 'top' && { top: -90 }), } }, react_1.default.createElement("div", { className: 'mt-3 h-[50px] text-center' }, react_1.default.createElement("div", null, react_1.default.createElement("svg", { className: 'mx-auto h-4 w-4 text-gray-700', fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, react_1.default.createElement("path", { d: 'M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z', strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: '2' })), react_1.default.createElement("h3", { className: 'mt-[2px] text-sm text-gray-700' }, "Kh\u00F4ng c\u00F3 d\u1EEF li\u1EC7u")))))), helpText ? react_1.default.createElement("div", { className: 'mt-1 text-xs text-gray-500' }, helpText) : null, error && errorType ? react_1.default.createElement(ErrorMessage_1.default, { message: message(errorType) }) : null)); }; exports.PHXCombobox = PHXCombobox; //# sourceMappingURL=Combobox.js.map