dropdown-setting.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. optgroups?: Array<Optgroup<T>>
  24. value?: T
  25. disabled?: boolean
  26. width?: 'default' | 'wide'
  27. loading?: boolean
  28. translateOptions?: 'yes' | 'no'
  29. }
  30. export default function DropdownSetting<T extends PossibleValue = string>({
  31. id,
  32. label,
  33. options,
  34. onChange,
  35. value,
  36. optgroups,
  37. description = undefined,
  38. disabled = false,
  39. width = 'default',
  40. loading = false,
  41. translateOptions,
  42. }: SettingsMenuSelectProps<T>) {
  43. const handleChange: ChangeEventHandler<HTMLSelectElement> = useCallback(
  44. event => {
  45. const selectedValue = event.target.value
  46. let onChangeValue: PossibleValue = selectedValue
  47. if (typeof value === 'boolean') {
  48. onChangeValue = selectedValue === 'true'
  49. } else if (typeof value === 'number') {
  50. onChangeValue = parseInt(selectedValue, 10)
  51. }
  52. onChange(onChangeValue as T)
  53. },
  54. [onChange, value]
  55. )
  56. return (
  57. <Setting controlId={id} label={label} description={description}>
  58. {loading ? (
  59. <OLSpinner size="sm" />
  60. ) : (
  61. <OLFormSelect
  62. id={id}
  63. className={classNames('ide-dropdown-setting', {
  64. 'ide-dropdown-setting-wide': width === 'wide',
  65. })}
  66. size="sm"
  67. onChange={handleChange}
  68. value={value?.toString()}
  69. disabled={disabled}
  70. translate={translateOptions}
  71. >
  72. {options?.map(option => (
  73. <option
  74. key={`${id}-${option.value}`}
  75. value={option.value.toString()}
  76. aria-hidden={option.ariaHidden}
  77. disabled={option.disabled}
  78. >
  79. {option.label}
  80. </option>
  81. ))}
  82. {optgroups?.map(optgroup => (
  83. <optgroup label={optgroup.label} key={optgroup.label}>
  84. {optgroup.options.map(option => (
  85. <option
  86. value={option.value.toString()}
  87. key={option.value.toString()}
  88. >
  89. {option.label}
  90. </option>
  91. ))}
  92. </optgroup>
  93. ))}
  94. </OLFormSelect>
  95. )}
  96. </Setting>
  97. )
  98. }