Select.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Libraries
  2. import classNames from 'classnames';
  3. import React, { PureComponent } from 'react';
  4. import { default as ReactSelect } from '@torkelo/react-select';
  5. import { default as ReactAsyncSelect } from '@torkelo/react-select/lib/Async';
  6. import { components } from '@torkelo/react-select';
  7. // Components
  8. import { Option, SingleValue } from './PickerOption';
  9. import OptionGroup from './OptionGroup';
  10. import IndicatorsContainer from './IndicatorsContainer';
  11. import NoOptionsMessage from './NoOptionsMessage';
  12. import ResetStyles from './ResetStyles';
  13. import CustomScrollbar from '../CustomScrollbar/CustomScrollbar';
  14. export interface SelectOptionItem {
  15. label?: string;
  16. value?: any;
  17. imgUrl?: string;
  18. description?: string;
  19. [key: string]: any;
  20. }
  21. interface CommonProps {
  22. defaultValue?: any;
  23. getOptionLabel?: (item: SelectOptionItem) => string;
  24. getOptionValue?: (item: SelectOptionItem) => string;
  25. onChange: (item: SelectOptionItem) => {} | void;
  26. placeholder?: string;
  27. width?: number;
  28. value?: SelectOptionItem;
  29. className?: string;
  30. isDisabled?: boolean;
  31. isSearchable?: boolean;
  32. isClearable?: boolean;
  33. autoFocus?: boolean;
  34. openMenuOnFocus?: boolean;
  35. onBlur?: () => void;
  36. maxMenuHeight?: number;
  37. isLoading: boolean;
  38. noOptionsMessage?: () => string;
  39. isMulti?: boolean;
  40. backspaceRemovesValue: boolean;
  41. }
  42. interface SelectProps {
  43. options: SelectOptionItem[];
  44. }
  45. interface AsyncProps {
  46. defaultOptions: boolean;
  47. loadOptions: (query: string) => Promise<SelectOptionItem[]>;
  48. loadingMessage?: () => string;
  49. }
  50. export const MenuList = props => {
  51. return (
  52. <components.MenuList {...props}>
  53. <CustomScrollbar autoHide={false}>{props.children}</CustomScrollbar>
  54. </components.MenuList>
  55. );
  56. };
  57. export class Select extends PureComponent<CommonProps & SelectProps> {
  58. static defaultProps = {
  59. width: null,
  60. className: '',
  61. isDisabled: false,
  62. isSearchable: true,
  63. isClearable: false,
  64. isMulti: false,
  65. openMenuOnFocus: false,
  66. autoFocus: false,
  67. isLoading: false,
  68. backspaceRemovesValue: true,
  69. maxMenuHeight: 300,
  70. };
  71. render() {
  72. const {
  73. defaultValue,
  74. getOptionLabel,
  75. getOptionValue,
  76. onChange,
  77. options,
  78. placeholder,
  79. width,
  80. value,
  81. className,
  82. isDisabled,
  83. isLoading,
  84. isSearchable,
  85. isClearable,
  86. backspaceRemovesValue,
  87. isMulti,
  88. autoFocus,
  89. openMenuOnFocus,
  90. onBlur,
  91. maxMenuHeight,
  92. noOptionsMessage,
  93. } = this.props;
  94. let widthClass = '';
  95. if (width) {
  96. widthClass = 'width-' + width;
  97. }
  98. const selectClassNames = classNames('gf-form-input', 'gf-form-input--form-dropdown', widthClass, className);
  99. return (
  100. <ReactSelect
  101. classNamePrefix="gf-form-select-box"
  102. className={selectClassNames}
  103. components={{
  104. Option,
  105. SingleValue,
  106. IndicatorsContainer,
  107. MenuList,
  108. Group: OptionGroup,
  109. }}
  110. defaultValue={defaultValue}
  111. value={value}
  112. getOptionLabel={getOptionLabel}
  113. getOptionValue={getOptionValue}
  114. menuShouldScrollIntoView={false}
  115. isSearchable={isSearchable}
  116. onChange={onChange}
  117. options={options}
  118. placeholder={placeholder || 'Choose'}
  119. styles={ResetStyles}
  120. isDisabled={isDisabled}
  121. isLoading={isLoading}
  122. isClearable={isClearable}
  123. autoFocus={autoFocus}
  124. onBlur={onBlur}
  125. openMenuOnFocus={openMenuOnFocus}
  126. maxMenuHeight={maxMenuHeight}
  127. noOptionsMessage={noOptionsMessage}
  128. isMulti={isMulti}
  129. backspaceRemovesValue={backspaceRemovesValue}
  130. />
  131. );
  132. }
  133. }
  134. export class AsyncSelect extends PureComponent<CommonProps & AsyncProps> {
  135. static defaultProps = {
  136. width: null,
  137. className: '',
  138. components: {},
  139. loadingMessage: () => 'Loading...',
  140. isDisabled: false,
  141. isClearable: false,
  142. isMulti: false,
  143. isSearchable: true,
  144. backspaceRemovesValue: true,
  145. autoFocus: false,
  146. openMenuOnFocus: false,
  147. maxMenuHeight: 300,
  148. };
  149. render() {
  150. const {
  151. defaultValue,
  152. getOptionLabel,
  153. getOptionValue,
  154. onChange,
  155. placeholder,
  156. width,
  157. value,
  158. className,
  159. loadOptions,
  160. defaultOptions,
  161. isLoading,
  162. loadingMessage,
  163. noOptionsMessage,
  164. isDisabled,
  165. isSearchable,
  166. isClearable,
  167. backspaceRemovesValue,
  168. autoFocus,
  169. onBlur,
  170. openMenuOnFocus,
  171. maxMenuHeight,
  172. isMulti,
  173. } = this.props;
  174. let widthClass = '';
  175. if (width) {
  176. widthClass = 'width-' + width;
  177. }
  178. const selectClassNames = classNames('gf-form-input', 'gf-form-input--form-dropdown', widthClass, className);
  179. return (
  180. <ReactAsyncSelect
  181. classNamePrefix="gf-form-select-box"
  182. className={selectClassNames}
  183. components={{
  184. Option,
  185. SingleValue,
  186. IndicatorsContainer,
  187. NoOptionsMessage,
  188. }}
  189. defaultValue={defaultValue}
  190. value={value}
  191. getOptionLabel={getOptionLabel}
  192. getOptionValue={getOptionValue}
  193. menuShouldScrollIntoView={false}
  194. onChange={onChange}
  195. loadOptions={loadOptions}
  196. isLoading={isLoading}
  197. defaultOptions={defaultOptions}
  198. placeholder={placeholder || 'Choose'}
  199. styles={ResetStyles}
  200. loadingMessage={loadingMessage}
  201. noOptionsMessage={noOptionsMessage}
  202. isDisabled={isDisabled}
  203. isSearchable={isSearchable}
  204. isClearable={isClearable}
  205. autoFocus={autoFocus}
  206. onBlur={onBlur}
  207. openMenuOnFocus={openMenuOnFocus}
  208. maxMenuHeight={maxMenuHeight}
  209. isMulti={isMulti}
  210. backspaceRemovesValue={backspaceRemovesValue}
  211. />
  212. );
  213. }
  214. }
  215. export default Select;