UNPKG

@parkassist/pa-ui-library

Version:
233 lines 6.39 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useState } from "react"; import { Column, Row } from "../Layout/Flex"; import styled from "@emotion/styled"; import Palette from "../../constants/Palette"; import { Measures } from "../../index"; import Autocomplete from "react-autocomplete"; import { FormLabel } from "../Input"; import FadeIn from "react-fade-in"; import * as Icons from "../Icons"; const Wrapper = styled(Column)(({ height, width }) => ({ backgroundColor: Palette.WHITE, fontSize: 12, height, borderRadius: 3, minWidth: "fit-content", overflow: "hidden", border: `1px solid ${Palette.DIM_GREY}`, justifyContent: "space-between", width })); const OptionWrapper = styled(Row)(({ width }) => ({ boxSizing: "border-box", justifyContent: "space-between", alignItems: "center", height: `calc(${Measures.unit} * 2)`, minHeight: `calc(${Measures.unit} * 2)`, borderBottom: `1px solid ${Palette.VERY_LIGHT_GREY_NEW}`, padding: Measures.minMargin, width: width ? width : "100%", color: Palette.BLACK, transition: "all 0.2s", "&:hover": { backgroundColor: Palette.WARNING_YELLOW } })); const Item = styled.div(({ isHighlighted }) => ({ height: `calc(${Measures.unit} * 2)`, display: "flex", padding: 4, alignItems: "center", background: isHighlighted ? Palette.WARNING_YELLOW : Palette.WHITE })); const Input = styled.input(({ width }) => ({ outline: "none", border: "none", marginTop: -4, marginLeft: 4, zIndex: 1, borderRight: `1px solid ${Palette.DIM_GREY}`, width })); const NoOptionsWrapper = styled.div` height: 100%; display: flex; justify-content: center; align-items: center; text-transform: uppercase; font-size: 11px; color: ${Palette.DIM_GREY}; `; export const ControlWrapper = styled.div(() => ({ fontSize: 12, color: Palette.DIM_GREY })); export const Control = styled.span(() => ({ cursor: "pointer", color: "grey", margin: 2, "&:hover": { color: Palette.BLACK } })); const DownArrowWrapper = styled.span(({ visible }) => ({ display: "flex", transition: "all 0.2s", transformOrigin: "center", width: 18, height: 18, transform: `rotate(${visible ? "180deg" : 0})`, zIndex: 0, cursor: "pointer" })); const menuStyles = (width, maxHeight) => ({ boxShadow: `0 2px 12px ${Palette.VERY_LIGHT_GREY_NEW}`, background: Palette.WHITE, fontSize: "90%", position: "fixed", zIndex: 99, marginLeft: -34, marginTop: 8, width, overflow: "auto", borderRadius: 3, transition: "all 0.2s", maxHeight }); const Option = ({ text, onRemove, width }) => _jsxs(OptionWrapper, { width: width, children: [_jsx(Column, { children: text }), _jsx(Column, { style: { cursor: "pointer" }, onClick: onRemove, children: _jsx(Icons.CloseIcon, {}) })] }); const SearchableSelector = ({ options, selection = [], onChange, width, height, title, optionsMaxHeight = 100, propertyToShow = "label", placeholder = "", allText = "All", clearText = "Clear", noSelectionText = "No selection" }) => { const [value, setValue] = useState(""); const [visible, setVisible] = useState(false); const optionsToShow = options.filter(o => { return o[propertyToShow].toLowerCase().includes(value.toLowerCase()) && !selection.some(s => s[propertyToShow].toLowerCase() === o[propertyToShow].toLowerCase()); }); const handleSelection = text => { const optionToAdd = options.find(o => o[propertyToShow] === text); onChange(selection.concat(optionToAdd)); setValue(""); setVisible(false); }; return _jsxs(Column, { children: [_jsxs(Row, { style: { justifyContent: "space-between" }, children: [_jsxs(FormLabel, { children: [title, " (", selection.length, ")"] }), _jsxs(ControlWrapper, { children: [_jsx(Control, { "data-testid": "all", onClick: () => { onChange(options); }, children: allText }), "|", _jsx(Control, { "data-testid": "clear", onClick: () => { onChange([]); }, children: clearText })] })] }), _jsx(Row, { children: _jsxs(Wrapper, { height: height, width: width, children: [_jsx(Row, { children: _jsxs(Column, { style: { height: height - 32, width: "100%", overflowY: "auto" }, children: [selection.length === 0 && _jsx(NoOptionsWrapper, { children: noSelectionText }), selection.map((s, i) => _jsx(FadeIn, { children: _jsx(Option, { text: s[propertyToShow], onRemove: () => { onChange(selection.filter(o => o[propertyToShow] !== s[propertyToShow])); } }) }))] }) }), _jsxs(Row, { style: { height: 32, justifyContent: "space-between", borderTop: `1px solid ${Palette.DIM_GREY}`, padding: Measures.minMargin }, children: [_jsx(Icons.SearchIcon, {}), _jsx(Autocomplete, { getItemValue: item => item[propertyToShow], menuStyle: menuStyles(width, optionsMaxHeight), items: optionsToShow, renderItem: (item, isHighlighted) => _jsx(Item, { "data-testid": title.toLowerCase() + "-option", isHighlighted: isHighlighted, children: item[propertyToShow] }, item[propertyToShow]), value: value, onChange: e => setValue(e.target.value), onSelect: handleSelection, open: visible, onMenuVisibilityChange: newState => setVisible(newState), renderInput: props => _jsx(Input, Object.assign({ id: "search" + title, placeholder: placeholder, width: width - 64 }, props)) }), _jsx(DownArrowWrapper, { "data-testid": "open-list", visible: visible, onClick: () => { setVisible(!visible); }, children: _jsx(Icons.OpenArrowIcon, {}) })] })] }) })] }); }; export default SearchableSelector;