All files / src/form/fields ValueSelect.tsx

9.09% Statements 2/22
0% Branches 0/7
0% Functions 0/7
9.09% Lines 2/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85            66x                                 66x                                                                                                                          
import React, { CSSProperties, ReactElement, useMemo } from 'react';
import { Select } from 'antd';
import { useTranslation } from 'react-i18next';
import { getReadOnlyClass } from '@utils/ComponentUtils';
import { SuffixIcon } from '../../components';
 
const { Option } = Select;
 
interface ValueType {
  value: string | number;
  label: string;
}
 
export interface ValueSelectProps {
  placeholder: string;
  value?: string | number;
  style?: CSSProperties;
  notFoundContent: string;
  onSelect?: (val: string | number | undefined) => void;
  updatable?: boolean;
  options?: string[] | number[];
}
 
const ValueSelect = (props: ValueSelectProps): ReactElement => {
  const {
    placeholder, value, style, notFoundContent,
    updatable, options, onSelect,
  } = props;
 
  const { t } = useTranslation();
 
  const disabled = (updatable == null) ? false : !updatable;
  const [data, record] = useMemo(() => {
    const data: ValueType[] = [];
    const record: Record<string, string | number> = {};
    options?.forEach(o => {
      const str = o.toString();
      record[str] = o;
      data.push({
        value: o,
        label: str,
      });
    });
    return [data, record];
  }, [options]);
 
  // **** Attention ****
  // zIndex of the select dropdown should higher than the zIndex of modal(by
  // default 1051) because the dropdown might be displayed on a modal
  // https://stackoverflow.com/questions/53926911/antd-select-not-working-inside-a-full-screen-dialog
  // Set in App.less by .ant-select-dropdown
  return (
    <Select
      showSearch
      style={style}
      disabled={disabled}
      value={value}
      placeholder={t(placeholder)}
      defaultActiveFirstOption={true}
      showArrow={true}
      dropdownMatchSelectWidth={true}
      optionFilterProp="label"
      notFoundContent={notFoundContent}
      dropdownStyle={{ zIndex: 2000 }}
      onClear={() => onSelect?.(undefined)}
      onSelect={(val) => onSelect?.(record[val])}
      filterOption={(input, option) => {
        if (option == null || option.value == null || input == null) {
          return false;
        }
        const il = input.toLowerCase();
        const str = option.value.toString().toLowerCase();
        return str.includes(il);
      }}
      className={`valueSelect ${getReadOnlyClass(updatable)}`}
      suffixIcon={<SuffixIcon updatable={updatable}/>}
      allowClear={true}
    >
      {data?.map(d => <Option key={d.value} value={d.value}>{d.label}</Option>)}
    </Select>
  );
};
 
export default ValueSelect;