@kubit-ui-web/react-components
Version:
Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience
212 lines • 9.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useInputSearch = void 0;
const react_1 = require("react");
const useCustomHeightFromChildren_1 = require("../../../hooks/useCustomHeightFromChildrens/useCustomHeightFromChildren");
const useInput_1 = require("../../../hooks/useInput/useInput");
const useMediaDevice_1 = require("../../../hooks/useMediaDevice/useMediaDevice");
const keyboard_utility_1 = require("../../../utils/keyboard/keyboard.utility");
const mask_utility_1 = require("../../../utils/maskUtility/mask.utility");
const syntheticEvent_1 = require("../../../utils/syntheticComponents/syntheticEvent/syntheticEvent");
const useInternalValidations_1 = require("../../input/hooks/useInternalValidations");
const internalErrors_1 = require("../../input/types/internalErrors");
// helpers
const filterOptions_1 = require("../helpers/filterOptions");
const useInputSearch = ({ executeInternalOpenOptions = true, ...props }) => {
const device = (0, useMediaDevice_1.useMediaDevice)();
const [openOptions, setOpenOptions] = (0, react_1.useState)(props.open);
const [searchText, setSearchText] = (0, react_1.useState)(props.value ?? '');
const [inputPopoverText, setInputPopoverText] = (0, react_1.useState)('');
const [showHighlightedOption, setShowHighlightedOption] = (0, react_1.useState)(!!props.highlightedOption);
// References
const iconRef = (0, react_1.useRef)();
const { internalErrors, addInternalError, removeInternalError } = (0, useInternalValidations_1.useInternalValidations)(props.type, undefined, props.onInternalErrors);
// Methods
const handleValueSelected = (value) => {
setSearchText(value);
setInputPopoverText(value);
props.onOptionClick?.(value);
removeInternalError(internalErrors_1.InternalErrorType.INVALID_OPTION);
showHighlightedOption && setShowHighlightedOption(false);
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
if (props.onChange && inputRef?.current && isBrowser) {
// Need to have the current input value into dispatch synthetic event
inputRef.current.value = value;
const event = (0, syntheticEvent_1.dispatchSyntheticEvent)({
element: inputRef.current,
eventType: 'change',
});
props.onChange(event);
}
};
const handleOpenOptions = (open) => {
setOpenOptions(prevOpen => {
if (prevOpen !== open) {
props.onPopoverOpen?.(open);
}
return open;
});
};
// Input search handlers
const handleChangeInputSearch = event => {
handleOpenOptions(true);
if (props.regex) {
const newMaskedValue = (0, mask_utility_1.matchInputValue)(searchText, event.target.value, props.regex);
event.target.value = newMaskedValue;
}
const newSearchText = event.target.value;
setSearchText(newSearchText);
setInputPopoverText(newSearchText);
showHighlightedOption && setShowHighlightedOption(false);
removeInternalError(internalErrors_1.InternalErrorType.INVALID_OPTION);
props.onChange?.(event);
};
const handleClickInputSearch = event => {
handleOpenOptions(!openOptions);
props.onClick?.(event);
};
const handleIconClick = (e) => {
executeInternalOpenOptions && handleOpenOptions(!openOptions);
props.onIconClick?.(e);
};
const handleRightIconClick = (e) => {
executeInternalOpenOptions && handleOpenOptions(!openOptions);
props.onRightIconClick?.(e);
};
const handleInputKeyDown = event => {
if ((0, keyboard_utility_1.isKeyEscapePressed)(event.key)) {
handleOpenOptions(false);
}
// Focus first element of the list
if ((0, keyboard_utility_1.isArrowDownPressed)(event.key)) {
optionsListCollectionRef?.current?.[0]?.firstElementChild?.focus();
event.preventDefault();
}
props.onKeyDown?.(event);
};
const handleInputBlur = event => {
props.onBlur?.(event);
const allOptions = props.options.map(option => option.options).flat();
const hasMatch = (0, filterOptions_1.hasMatchWithOptions)(searchText, allOptions, props.caseSensitive);
// if the input loses focus and there is no valid option in the input value, show an error message
if (!hasMatch && !props.hasResultTextWrittenByUser && !props.disableErrorInvalidOption) {
addInternalError(internalErrors_1.InternalErrorType.INVALID_OPTION);
}
};
// Input popover handlers
const handleInputPopoverChange = event => {
props.onChange?.(event);
setInputPopoverText(event.target.value);
};
const handleInputPopoverKeyDown = event => {
if ((0, keyboard_utility_1.isKeyEnterPressed)(event.key) && props.onInputPopoverEnterKeyDown) {
props.onInputPopoverEnterKeyDown(event);
}
// Focus first element of the list
if ((0, keyboard_utility_1.isArrowDownPressed)(event.key)) {
optionsListCollectionRef?.current?.[0]?.firstElementChild?.focus();
event.preventDefault();
}
};
const handleInputPopoverIconClick = () => {
props.onInputPopoverIconClick?.();
if (props.clearTextInputPopoverIconClick) {
setInputPopoverText('');
}
};
// OnKeyDown list
const handleOptionsListKeyDown = event => {
let selectedOption = 0;
const options = document.querySelectorAll('[role="option"]');
const getSelectedIndex = (operator) => {
event.preventDefault();
for (let i = 0; i < options.length; i++) {
if (options[i] === document.activeElement) {
selectedOption = i + operator;
}
}
// Focus the item
options[selectedOption]?.focus();
};
// When arrow down
if ((0, keyboard_utility_1.isArrowDownPressed)(event.key)) {
getSelectedIndex(1);
}
else if ((0, keyboard_utility_1.isArrowUpPressed)(event.key)) {
// When arrow up
getSelectedIndex(-1);
}
};
// Input Basic hook
const { state, inputRef, handleBlurInternal, handleFocusInternal, handlePasteInternal } = (0, useInput_1.useInput)({
internalErrorExecution: props.internalErrorExecution,
ref: props.ref,
disabled: props.disabled,
error: props.error || internalErrors.length > 0,
maxLength: props.maxLength,
// need for update the state
currentValue: searchText,
informationAssociated: props.informationAssociated,
disabledCopyAndPaste: props.disabledCopyAndPaste,
onBlur: handleInputBlur,
onFocus: props.onFocus,
onInternalErrors: props.onInternalErrors,
onPaste: props.onPaste,
});
const useActionBottomSheet = (0, react_1.useMemo)(() => props.styles?.[state]?.useActionBottomSheet?.[device], [state, device]);
// Returns references (OptionsList Collection, ActionBottomSheet and InputPopover) and OptionsList height
const { optionsListRefCollection, optionsListCollectionRef, height: listOptionsHeight, } = (0, useCustomHeightFromChildren_1.useCustomHeightFromChildrens)({
limit: props.elementsToShow,
observer: [props.options, searchText, inputPopoverText],
shouldCalculateHeight: !useActionBottomSheet,
});
// Uses effects
// Update value when new prop value
(0, react_1.useEffect)(() => {
setSearchText(props.value ?? '');
setInputPopoverText(props.value ?? '');
}, [props.value]);
// Open or close the popover from external props
(0, react_1.useEffect)(() => {
handleOpenOptions(props.open);
}, [props.open]);
// Set focus on popover input when show
const actionBottomSheetRefCb = (0, react_1.useCallback)(node => {
node?.querySelector('input')?.focus();
}, []);
// references
const ref = {
refInput: inputRef,
refList: optionsListRefCollection,
refIcon: iconRef,
refActionBottomSheet: actionBottomSheetRefCb,
};
// Filter options
const { optionsFiltered } = (0, filterOptions_1.filterOptions)(useActionBottomSheet ? inputPopoverText : searchText, props.options, props.searchFilterConfig?.wordSeparator, props.searchFilterConfig?.suggestInit);
return {
openOptions,
searchText,
inputPopoverText,
optionsFiltered,
showHighlightedOption,
handleOpenOptions,
handleClickInputSearch,
handleIconClick,
handleRightIconClick,
handleInputPopoverIconClick,
handleValueSelected,
handleChangeInputSearch,
handleInputKeyDown,
handleInputPopoverKeyDown,
state,
ref,
listOptionsHeight,
handleBlurInternal,
handleFocusInternal,
handleInputPopoverChange,
handleOptionsListKeyDown,
handlePasteInternal,
};
};
exports.useInputSearch = useInputSearch;
//# sourceMappingURL=useInputSearch.js.map