phx-react
Version:
PHX REACT
162 lines • 10.9 kB
JavaScript
"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