UNPKG

@chayns-components/person-finder

Version:

A set of beautiful React components for developing your own applications with chayns.

162 lines 5.34 kB
import { DropdownBodyWrapper, Icon, TagInput } from '@chayns-components/core'; import { useDevice } from 'chayns-api'; import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { v4 as uuidV4 } from 'uuid'; import { PersonFinderFilterTypes, Priority } from '../../../types/personFinder'; import { StyledPersonFinder, StyledPersonFinderLeftElement } from './PersonFinderWrapper.styles'; import PersonFinderBody from './person-finder-body/PersonFinderBody'; import { usePersonFinder } from '../../PersonFinderProvider'; const PersonFinderWrapper = /*#__PURE__*/forwardRef(({ container, dropdownDirection, filterTypes, leftElement: leftElementProp, maxEntries = Infinity, onAdd, onDropdownHide, onDropdownShow, friendsPriority, onRemove, placeholder, shouldAllowMultiple, shouldHideResultsOnAdd }, ref) => { const { data, updateSearch, setTags, tags, search } = usePersonFinder(); const [isFocused, setIsFocused] = useState(false); const [shouldShowBody, setShouldShowBody] = useState(false); const boxRef = useRef(null); const contentRef = useRef(null); const keyRef = useRef(`person-finder-${uuidV4()}`); const tagInputRef = useRef(null); const { isTouch } = useDevice(); const leftElement = leftElementProp ?? /*#__PURE__*/React.createElement(StyledPersonFinderLeftElement, null, /*#__PURE__*/React.createElement(Icon, { icons: ['fa fa-search'] })); const handleTagInputBlur = useCallback(() => { setIsFocused(false); }, []); const handleTagInputFocus = useCallback(() => { setIsFocused(true); }, []); const handleRemove = useCallback(id => { if (typeof setTags !== 'function') { return; } setTags(prevState => prevState.filter(entry => entry.id !== id)); if (typeof onRemove === 'function') { onRemove(id); } }, [onRemove, setTags]); const handleClose = useCallback(() => { setShouldShowBody(false); }, []); const handleOpen = useCallback(() => { setShouldShowBody(true); }, []); const handleClear = useCallback(() => { if (typeof setTags !== 'function') { return; } tagInputRef.current?.resetValue(); setTags([]); }, [setTags]); const handleDropdownOutsideClick = useCallback(() => { tagInputRef.current?.blur(); return isFocused && isTouch; }, [isFocused, isTouch]); const handleAdd = useCallback(id => { if (typeof setTags !== 'function') { return; } const selectedEntry = Object.values(data ?? {}).flat().map(({ entries }) => entries).flat().find(entry => (typeof entry.id === 'string' ? entry.id : entry.id.toString()) === id); if (!selectedEntry) { return; } const { name, firstName, lastName } = selectedEntry; const tag = { id, text: name ?? `${firstName ?? ''} ${lastName ?? ''}` }; setTags(prevState => { if (prevState.some(t => t.id === id) || prevState.length >= maxEntries) { return prevState; } tagInputRef.current?.resetValue(); if (typeof onAdd === 'function') { onAdd(selectedEntry); } if (shouldHideResultsOnAdd) { setShouldShowBody(false); } return [...prevState, tag]; }); }, [data, maxEntries, onAdd, setTags, shouldHideResultsOnAdd]); const handleChange = useCallback(event => { if (typeof updateSearch === 'function') { updateSearch(event.target.value); } }, [updateSearch]); useImperativeHandle(ref, () => ({ clear: () => handleClear() }), [handleClear]); useEffect(() => { if (shouldShowBody) { if (typeof onDropdownShow === 'function') { onDropdownShow(); } } else if (typeof onDropdownHide === 'function') { onDropdownHide(); } }, [onDropdownHide, onDropdownShow, shouldShowBody]); const showBody = useMemo(() => { if (filterTypes?.length === 1 && (filterTypes.includes(PersonFinderFilterTypes.SITE) || filterTypes.includes(PersonFinderFilterTypes.PERSON) && friendsPriority !== Priority.HIGH)) { return shouldShowBody && !!search && search?.length > 2; } return shouldShowBody; }, [filterTypes, friendsPriority, search, shouldShowBody]); return /*#__PURE__*/React.createElement(StyledPersonFinder, { ref: boxRef, onFocus: handleOpen, key: keyRef.current }, /*#__PURE__*/React.createElement(TagInput, { leftElement: leftElement, onBlur: handleTagInputBlur, onChange: handleChange, onFocus: handleTagInputFocus, onRemove: handleRemove, placeholder: placeholder, ref: tagInputRef, shouldAllowMultiple: shouldAllowMultiple, shouldPreventEnter: true, tags: tags }), boxRef.current && /*#__PURE__*/React.createElement(DropdownBodyWrapper, { anchorElement: boxRef.current, container: container, direction: dropdownDirection, onClose: handleClose, onOutsideClick: handleDropdownOutsideClick, shouldShowDropdown: showBody }, /*#__PURE__*/React.createElement(PersonFinderBody, { filterTypes: filterTypes, onAdd: handleAdd, onRemove: handleRemove, ref: contentRef }))); }); PersonFinderWrapper.displayName = 'PersonFinderWrapper'; export default PersonFinderWrapper; //# sourceMappingURL=PersonFinderWrapper.js.map