dropdown-setting.tsx 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import OLFormSelect from '@/features/ui/components/ol/ol-form-select'
  2. import { ChangeEventHandler, useCallback } from 'react'
  3. import Setting from './setting'
  4. import classNames from 'classnames'
  5. import { Spinner } from 'react-bootstrap-5'
  6. type PossibleValue = string | number
  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. description: string
  21. options: Array<Option<T>>
  22. onChange: (val: T) => void
  23. value?: T
  24. disabled?: boolean
  25. width?: 'default' | 'wide'
  26. loading?: boolean
  27. }
  28. export default function DropdownSetting<T extends PossibleValue = string>({
  29. id,
  30. label,
  31. description,
  32. options,
  33. onChange,
  34. value,
  35. disabled = false,
  36. width = 'default',
  37. loading = false,
  38. }: SettingsMenuSelectProps<T>) {
  39. const handleChange: ChangeEventHandler<HTMLSelectElement> = useCallback(
  40. event => {
  41. const selectedValue = event.target.value
  42. let onChangeValue: PossibleValue = selectedValue
  43. if (typeof value === 'number') {
  44. onChangeValue = parseInt(selectedValue, 10)
  45. }
  46. onChange(onChangeValue as T)
  47. },
  48. [onChange, value]
  49. )
  50. return (
  51. <Setting controlId={id} label={label} description={description}>
  52. {loading ? (
  53. <Spinner
  54. animation="border"
  55. aria-hidden="true"
  56. size="sm"
  57. role="status"
  58. />
  59. ) : (
  60. <OLFormSelect
  61. id={id}
  62. className={classNames('ide-dropdown-setting', {
  63. 'ide-dropdown-setting-wide': width === 'wide',
  64. })}
  65. size="sm"
  66. onChange={handleChange}
  67. value={value?.toString()}
  68. disabled={disabled}
  69. >
  70. {options.map(option => (
  71. <option
  72. key={`${id}-${option.value}`}
  73. value={option.value.toString()}
  74. aria-hidden={option.ariaHidden}
  75. disabled={option.disabled}
  76. >
  77. {option.label}
  78. </option>
  79. ))}
  80. </OLFormSelect>
  81. )}
  82. </Setting>
  83. )
  84. }