|
| 1 | +// Copyright (c) Cosmo Tech. |
| 2 | +// Licensed under the MIT license. |
| 3 | +import React, { useMemo } from 'react'; |
| 4 | +import PropTypes from 'prop-types'; |
| 5 | +import { Stack, Autocomplete, TextField } from '@mui/material'; |
| 6 | +import makeStyles from '@mui/styles/makeStyles'; |
| 7 | +import { TooltipInfo } from '../../misc'; |
| 8 | +import { BasicInputPlaceholder } from '../BasicInputs'; |
| 9 | +import { getCommonInputStyles } from '../style'; |
| 10 | + |
| 11 | +const useStyles = makeStyles(getCommonInputStyles); |
| 12 | + |
| 13 | +export const SingleSelect = (props) => { |
| 14 | + const classes = useStyles(); |
| 15 | + const { id, labels, tooltipText, value, options, disabled, onChange, isDirty } = props; |
| 16 | + |
| 17 | + const optionValue = useMemo(() => { |
| 18 | + return { key: value, label: options?.find((el) => el.key === value)?.label }; |
| 19 | + }, [options, value]); |
| 20 | + |
| 21 | + if (disabled) { |
| 22 | + const selectedValues = optionValue.label ?? labels.noValue; |
| 23 | + return ( |
| 24 | + <BasicInputPlaceholder |
| 25 | + id={`single-select-${id}`} |
| 26 | + label={labels.label ?? id} |
| 27 | + tooltipText={tooltipText} |
| 28 | + value={selectedValues} |
| 29 | + /> |
| 30 | + ); |
| 31 | + } |
| 32 | + |
| 33 | + return ( |
| 34 | + <Stack |
| 35 | + data-cy={`single-select-${id}`} |
| 36 | + direction="row" |
| 37 | + spacing={1} |
| 38 | + alignItems="center" |
| 39 | + className={isDirty ? classes.dirtyInput : isDirty === false ? classes.notDirtyInput : ''} |
| 40 | + > |
| 41 | + <Autocomplete |
| 42 | + id={id} |
| 43 | + options={options} |
| 44 | + noOptionsText={labels.noOptions} |
| 45 | + value={optionValue} |
| 46 | + isOptionEqualToValue={(option, value) => option.key === value.key || value.key == null} |
| 47 | + onChange={(event, newValue) => onChange(newValue?.key)} |
| 48 | + getOptionLabel={(option) => option?.label ?? ''} |
| 49 | + renderOption={(props, option) => ( |
| 50 | + <li data-cy={'single-select-option-' + option.key} {...props} key={option.key}> |
| 51 | + {option.label} |
| 52 | + </li> |
| 53 | + )} |
| 54 | + style={{ width: 500 }} |
| 55 | + ListboxProps={{ 'data-cy': 'single-select-listbox' }} |
| 56 | + renderInput={(params) => ( |
| 57 | + <TextField {...params} data-cy={`single-select-text-${id}`} placeholder={labels.label} label={labels.label} /> |
| 58 | + )} |
| 59 | + /> |
| 60 | + <TooltipInfo title={tooltipText} variant="small" /> |
| 61 | + </Stack> |
| 62 | + ); |
| 63 | +}; |
| 64 | + |
| 65 | +SingleSelect.propTypes = { |
| 66 | + /** |
| 67 | + * Component's id that is used as test selector |
| 68 | + */ |
| 69 | + id: PropTypes.string, |
| 70 | + /** |
| 71 | + * Component's labels: |
| 72 | + * Structure: |
| 73 | + * <pre> |
| 74 | + { |
| 75 | + label: 'string', |
| 76 | + noValues: 'string', |
| 77 | + noOptions: 'string', |
| 78 | + } |
| 79 | + </pre> |
| 80 | + */ |
| 81 | + labels: PropTypes.shape({ |
| 82 | + label: PropTypes.string, |
| 83 | + noValue: PropTypes.string, |
| 84 | + noOptions: PropTypes.string, |
| 85 | + }), |
| 86 | + /** |
| 87 | + * Tooltip text |
| 88 | + */ |
| 89 | + tooltipText: PropTypes.string, |
| 90 | + /** |
| 91 | + * Selected value |
| 92 | + */ |
| 93 | + value: PropTypes.string, |
| 94 | + /** |
| 95 | + * Whether the component is disabled |
| 96 | + */ |
| 97 | + disabled: PropTypes.bool, |
| 98 | + /** |
| 99 | + * Function used when the user changes current value |
| 100 | + */ |
| 101 | + onChange: PropTypes.func.isRequired, |
| 102 | + /** |
| 103 | + * List of all possible options. A value (JS object) has two attributes : **key** and **value** |
| 104 | + * `{ key: 'option_key', value: 'My option value' }` |
| 105 | + */ |
| 106 | + options: PropTypes.array.isRequired, |
| 107 | + /** |
| 108 | + * Boolean value that defines whether the input has been modified or not; if true, a special css class is applied. |
| 109 | + */ |
| 110 | + isDirty: PropTypes.bool, |
| 111 | +}; |
| 112 | + |
| 113 | +SingleSelect.defaultProps = { |
| 114 | + disabled: false, |
| 115 | + labels: { |
| 116 | + label: 'Selection', |
| 117 | + noValue: 'No value selected', |
| 118 | + noOptions: 'No options available', |
| 119 | + }, |
| 120 | +}; |
0 commit comments