UNPKG

@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
"use strict"; 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