radioBoolean.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import {forwardRef} from 'react';
  2. type OnChangeHandler = (
  3. value: boolean,
  4. event: React.ChangeEvent<HTMLInputElement>
  5. ) => void;
  6. type OptionProps = {
  7. label: string;
  8. value: string;
  9. checked?: boolean;
  10. disabled?: boolean;
  11. name?: string;
  12. onBlur?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  13. onChange?: OnChangeHandler;
  14. };
  15. const Option = forwardRef(function Option(
  16. {name, disabled, label, value, checked, onChange, onBlur}: OptionProps,
  17. ref: React.Ref<HTMLInputElement>
  18. ) {
  19. function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  20. const isTrue = e.target.value === 'true';
  21. onChange?.(isTrue, e);
  22. // Manually trigger blur to trigger saving on change
  23. onBlur?.(e);
  24. }
  25. return (
  26. <div className="radio">
  27. <label style={{fontWeight: 'normal'}}>
  28. <input
  29. ref={ref}
  30. type="radio"
  31. value={value}
  32. name={name}
  33. checked={checked}
  34. onChange={handleChange}
  35. disabled={disabled}
  36. />{' '}
  37. {label}
  38. </label>
  39. </div>
  40. );
  41. });
  42. type Props = {
  43. disabled?: boolean;
  44. name?: string;
  45. noLabel?: string;
  46. onBlur?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  47. onChange?: OnChangeHandler;
  48. value?: boolean;
  49. yesFirst?: boolean;
  50. yesLabel?: string;
  51. };
  52. const RadioBoolean = forwardRef(function RadioBoolean(
  53. {
  54. disabled,
  55. name,
  56. onChange,
  57. onBlur,
  58. value,
  59. yesFirst = true,
  60. yesLabel = 'Yes',
  61. noLabel = 'No',
  62. }: Props,
  63. ref: React.Ref<HTMLInputElement>
  64. ) {
  65. const yesOption = (
  66. <Option
  67. ref={ref}
  68. value="true"
  69. checked={value === true}
  70. name={name}
  71. disabled={disabled}
  72. label={yesLabel}
  73. onChange={onChange}
  74. onBlur={onBlur}
  75. />
  76. );
  77. const noOption = (
  78. <Option
  79. value="false"
  80. checked={value === false}
  81. name={name}
  82. disabled={disabled}
  83. label={noLabel}
  84. onChange={onChange}
  85. onBlur={onBlur}
  86. />
  87. );
  88. return (
  89. <div>
  90. {yesFirst ? yesOption : noOption}
  91. {yesFirst ? noOption : yesOption}
  92. </div>
  93. );
  94. });
  95. export default RadioBoolean;