@parkassist/pa-ui-library
Version:
INX Platform elements
200 lines • 7.13 kB
JavaScript
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;