UNPKG

@parkassist/pa-ui-library

Version:
200 lines 7.13 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useEffect, useLayoutEffect, useRef, useState } from "react"; import Input from "../Input"; import { Column, Row } from "../Layout/Flex"; import Checkbox from "../Checkbox"; import Palette from "../../constants/Palette"; import Separator from "../Separator"; import { Control, ControlWrapper } from "../SearchableSelector"; import styled from "styled-components"; import * as Icons from "../Icons"; import _ from 'lodash'; import { FontStyles } from "../../index"; const OptionWrapper = styled(Row)` align-items: center; border-radius: 3px; min-height: 32px; font: ${FontStyles.BODY1_FONT}; background-color: transparent; cursor: pointer; margin-left: 0; padding-left: 10px; padding-right: 10px; padding-top: ${props => props.bigMargin ? '8px' : '0'}; padding-bottom: ${props => props.bigMargin ? '8px' : '0'}; justify-content: space-between; width: 100%; &:hover { background-color: ${props => props.highlightColor}; } `; const LongSearchableSelector = ({ noun = "Item", inputLabel, searchPlaceHolder, hideSearchInput = false, hideHeader = false, searchValue, width = 300, height = 300, options = [], disableHighlight = false, highlightColor = Palette.WARNING_YELLOW, selection = [], onChange = () => null, onHover = () => {}, onEndHover = () => {}, sortByChecked = false, visibleItems, showSelectAll, bigMargin, disableSeparatorMargin, disabled, allSelectedText = "All selected", noneSelectedText = "None selected", allText = "All", clearText = "Clear", selectAll = "Select all" }) => { const [search, setSearch] = useState(''); const [calculatedHeight, setCalculatedHeight] = useState(null); const optionRef = useRef(null); const sortedOptions = options.filter(option => option.label.toLowerCase().includes(search.toLowerCase())).map(option => Object.assign(Object.assign({}, option), { isSelected: selection.some(e => e.name === option.name) })).sort((a, b) => { if (sortByChecked) { if (a.isSelected === b.isSelected) { return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); } if (a.isSelected > b.isSelected) { return -1; } else { return 1; } } else { return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); } }); const selectedSortedOptions = sortedOptions.filter(option => option.isSelected); useLayoutEffect(() => { var _a; if (((_a = optionRef.current) === null || _a === void 0 ? void 0 : _a.clientHeight) && visibleItems) { setCalculatedHeight(optionRef.current.clientHeight * visibleItems); } }, [optionRef, visibleItems]); useEffect(() => { setSearch(searchValue || ''); }, [searchValue]); let textToShow = `(${selection.length})`; if (selection.length === options.length) { textToShow = `(${allSelectedText})`; } if (selection.length === 0) { textToShow = `(${noneSelectedText})`; } const handleClick = option => { if (option.isSelected) { onChange(selection.filter(e => e.name !== option.name), option); } else { onChange(selection.concat(option), option); } }; const handleSelectAll = () => { if (!search) { onChange(selection.length === options.length ? [] : options); } else { onChange(selectedSortedOptions.length === sortedOptions.length ? selection.filter(option => !sortedOptions.map(item => item.name).includes(option.name)) : _.uniqBy([...selection, ...sortedOptions], 'name')); } }; return _jsxs(Column, { children: [!hideHeader && _jsx(Row, { style: { width, height: 0, overflowY: "visible", fontSize: 12, zIndex: 1, color: Palette.DIM_GREY, justifyContent: "flex-end" }, children: _jsxs(ControlWrapper, { children: [_jsx(Control, { "data-testid": 'select-all', onClick: () => { onChange(options); }, children: allText }), "|", _jsx(Control, { "data-testid": 'select-clear', onClick: () => { onChange([]); }, children: clearText })] }) }), !hideSearchInput && _jsx(Row, { children: _jsx(Input, { value: search, onChange: e => setSearch(e.target.value), iconComponent: _jsx(Icons.SearchIcon, {}), label: (inputLabel || noun + "s") + " " + textToShow, placeholder: searchPlaceHolder || "Enter some " + noun, width: width }) }), _jsx(Row, { children: _jsxs(Column, { style: { width, height: calculatedHeight ? null : height - 32, maxHeight: calculatedHeight || null, overflowY: "auto" }, children: [sortedOptions.length === 0 && _jsx("p", { style: { paddingLeft: '16px', font: FontStyles.BODY1_FONT, color: Palette.DIM_GREY }, children: "No results found" }), showSelectAll && sortedOptions.length > 0 && _jsx("div", { children: _jsx(OptionWrapper, { onClick: () => !disabled && handleSelectAll(), highlightColor: !disableHighlight && highlightColor, bigMargin: bigMargin, onMouseOver: () => onHover(sortedOptions), onMouseLeave: onEndHover, children: _jsx(Checkbox, { text: selectAll, checked: selectedSortedOptions.length > 0 && selectedSortedOptions.length === sortedOptions.length, indeterminate: selectedSortedOptions.length > 0 && selectedSortedOptions.length !== sortedOptions.length, disabled: disabled }) }) }), sortedOptions.map((option, i) => { const nextOption = sortedOptions[i + 1]; return _jsxs("div", { children: [_jsxs(OptionWrapper, { "data-testid": `${noun}-option-${option.name}`, ref: optionRef, onClick: () => !disabled && handleClick(option), onMouseOver: () => onHover([option]), onMouseLeave: onEndHover, highlightColor: !disableHighlight && highlightColor, bigMargin: bigMargin, children: [_jsx(Checkbox, { component: option.component, text: option.Label || option.label, checked: option.isSelected, disabled: disabled }), option.extraContent] }), option.isSelected && sortByChecked && nextOption && !nextOption.isSelected && _jsx(Separator, { noMarginTop: disableSeparatorMargin, noMarginBottom: disableSeparatorMargin })] }, option.name); })] }) })] }); }; export default LongSearchableSelector;