jobiqo-cl
Version:
[](https://circleci.com/gh/jobiqo/jobiqo-cl)
126 lines (120 loc) • 6.05 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var styled = require('styled-components');
var styled__default = _interopDefault(styled);
var index = require('../11-form-item/index.js');
var downshift_esm = require('../../../../../node_modules/downshift/dist/downshift.esm.js');
var matchSorter_esm = require('../../../../../node_modules/match-sorter/dist/match-sorter.esm.js');
var subElements = require('./sub-elements/sub-elements.js');
/**
* @file index.tsx
*
* @fileoverview Renders a searcheable select component using the downshift library.
*/
const DownshiftInput = styled__default.input `
width: calc(100% - 0.5rem);
word-wrap: break-word;
outline: 0;
white-space: normal;
display: inline-block;
box-shadow: none;
transition: box-shadow 0.1s ease, width 0.1s ease;
font-size: ${props => props.theme.select.fontSize};
margin: ${props => props.theme.select.margin};
padding: ${props => props.theme.select.padding};
line-height: ${props => props.theme.select.height};
border-radius: ${props => props.theme.select.borderRadius};
border-width: ${props => props.theme.select.borderWidth};
border-top-width: ${props => props.theme.select.borderTopWidth};
border-left-width: ${props => props.theme.select.borderLeftWidth};
border-right-width: ${props => props.theme.select.borderRightWidth};
border-bottom-width: ${props => props.theme.select.borderBottomWidth};
border-style: ${props => props.theme.select.borderStyle};
border-color: ${props => props.theme.select.borderColor};
background: ${props => props.theme.select.background};
${({ isOpen }) => isOpen &&
`
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
`};
&:focus,
&:focus-within,
&:active {
outline: 0;
border-color: ${props => props.theme.colors.focusRingColor};
box-shadow: ${props => props.theme.select.focus.boxShadowType},
${props => `${props.theme.select.focus.boxShadowVals} ${props.theme.colors.focusRingColor}`};
}
`;
const ControlButton = styled__default.div `
background-color: transparent;
border: none;
position: absolute;
cursor: pointer;
-webkit-appearance: none;
right: ${props => props.theme.select.controlButton.position.right};
top: ${props => props.theme.select.controlButton.position.top};
`;
const parentStyle = {
maxWidth: '250px',
position: 'relative'
};
const WrapDiv = styled__default.div `
position: relative;
display: flex;
width: 100%;
`;
const ArrowIcon = ({ isOpen }) => {
return (React__default.createElement("svg", { viewBox: "0 0 20 20", preserveAspectRatio: "none", width: 16, fill: "transparent", stroke: "#979797", strokeWidth: "1.1px", transform: isOpen ? 'rotate(180)' : null },
React__default.createElement("path", { d: "M1,6 L10,15 L19,6" })));
};
const XIcon = () => {
return (React__default.createElement("svg", { viewBox: "0 0 20 20", preserveAspectRatio: "none", width: 12, fill: "transparent", stroke: "#979797", strokeWidth: "1.1px" },
React__default.createElement("path", { d: "M1,1 L19,19" }),
React__default.createElement("path", { d: "M19,1 L1,19" })));
};
function advancedFilter(theItems, value) {
return matchSorter_esm.default(theItems, value, {
keys: ['name', 'code']
});
}
/**
* Filters for the id that was selected.
*
* @param {SelectItem} items
* The whole value list.
* @param {string} value
* The code that was passed as default value
*
* @return {string}
* The value the pass to the input as default value.
*/
const getDefaultValue = (items, value) => {
const filteredItem = items.filter(i => i.code === value);
if (filteredItem.length > 0) {
return filteredItem[0];
}
return null;
};
/**
* A select widget that uses downshift internally. Renders a select where the user can search items.
* Focuses on accessibility.
*/
const Select = ({ id, items = [], label, required, placeholder = 'Search an item', onChange, onBlur, selectedValue }) => (React__default.createElement(index.FormItem, null,
label && React__default.createElement(index.FormLabel, { htmlFor: id }, label),
React__default.createElement(downshift_esm.default, { itemToString: i => (i ? i.name : ''), onChange: selection => onChange(selection), initialSelectedItem: getDefaultValue(items, selectedValue) }, ({ highlightedIndex, isOpen, clearSelection, inputValue, selectedItem, getToggleButtonProps, getInputProps, getItemProps }) => (React__default.createElement("div", { style: parentStyle },
React__default.createElement(WrapDiv, null,
React__default.createElement(DownshiftInput, Object.assign({}, getInputProps({ onBlur }), { isOpen, placeholder }, { id: id, "data-testid": "jobiqo-cl-select-input", required: required })),
selectedItem ? (React__default.createElement(ControlButton, { onClick: clearSelection, "aria-label": "clear selection", "data-testid": "jobiqo-cl-select-clear-button" },
React__default.createElement(XIcon, null))) : (React__default.createElement(ControlButton, Object.assign({}, getToggleButtonProps({}), { "data-testid": "jobiqo-cl-select-toggle-button" }),
React__default.createElement(ArrowIcon, { isOpen: isOpen })))),
isOpen && (React__default.createElement(subElements.Menu, null, (inputValue ? advancedFilter(items, inputValue) : items).map((item, index) => (React__default.createElement(subElements.Item, Object.assign({ key: item.code }, getItemProps({
item,
isSelected: selectedItem === item
}), { isActive: highlightedIndex === index, "data-testid": `downshift-item-${index}` }), item.name))))))))));
exports.ControlButton = ControlButton;
exports.DownshiftInput = DownshiftInput;
exports.Select = Select;