dropdown-setting.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import OLFormSelect from '@/shared/components/ol/ol-form-select'
  2. import { ChangeEventHandler, useCallback } from 'react'
  3. import Setting from './setting'
  4. import classNames from 'classnames'
  5. import OLSpinner from '@/shared/components/ol/ol-spinner'
  6. type PossibleValue = string | number | boolean
  7. export type Option<T extends PossibleValue = string> = {
  8. value: T
  9. label: string
  10. ariaHidden?: 'true' | 'false'
  11. disabled?: boolean
  12. }
  13. export type Optgroup<T extends PossibleValue = string> = {
  14. label: string
  15. options: Array<Option<T>>
  16. }
  17. type SettingsMenuSelectProps<T extends PossibleValue = string> = {
  18. id: string
  19. label: string
  20. options: Array<Option<T>>
  21. onChange: (val: T) => void
  22. description?: string
  23. // TODO: We can remove optgroup when the spellcheck setting is
  24. // split into 2 and no longer uses it.
  25. optgroup?: Optgroup<T>
  26. value?: T
  27. disabled?: boolean
  28. width?: 'default' | 'wide'
  29. loading?: boolean
  30. translateOptions?: 'yes' | 'no'
  31. }
  32. export default function DropdownSetting<T extends PossibleValue = string>({
  33. id,
  34. label,
  35. options,
  36. onChange,
  37. value,
  38. optgroup,
  39. description = undefined,
  40. disabled = false,
  41. width = 'default',
  42. loading = false,
  43. translateOptions,
  44. }: SettingsMenuSelectProps<T>) {
  45. const handleChange: ChangeEventHandler<HTMLSelectElement> = useCallback(
  46. event => {
  47. const selectedValue = event.target.value
  48. let onChangeValue: PossibleValue = selectedValue
  49. if (typeof value === 'boolean') {
  50. onChangeValue = selectedValue === 'true'
  51. } else if (typeof value === 'number') {
  52. onChangeValue = parseInt(selectedValue, 10)
  53. }
  54. onChange(onChangeValue as T)
  55. },
  56. [onChange, value]
  57. )
  58. return (
  59. <Setting controlId={id} label={label} description={description}>
  60. {loading ? (
  61. <OLSpinner size="sm" />
  62. ) : (
  63. <OLFormSelect
  64. id={id}
  65. className={classNames('ide-dropdown-setting', {
  66. 'ide-dropdown-setting-wide': width === 'wide',
  67. })}
  68. size="sm"
  69. onChange={handleChange}
  70. value={value?.toString()}
  71. disabled={disabled}
  72. translate={translateOptions}
  73. >
  74. {options.map(option => (
  75. <option
  76. key={`${id}-${option.value}`}
  77. value={option.value.toString()}
  78. aria-hidden={option.ariaHidden}
  79. disabled={option.disabled}
  80. >
  81. {option.label}
  82. </option>
  83. ))}
  84. {optgroup ? (
  85. <optgroup label={optgroup.label}>
  86. {optgroup.options.map(option => (
  87. <option
  88. value={option.value.toString()}
  89. key={option.value.toString()}
  90. >
  91. {option.label}
  92. </option>
  93. ))}
  94. </optgroup>
  95. ) : null}
  96. </OLFormSelect>
  97. )}
  98. </Setting>
  99. )
  100. }