group.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. "use client";
  2. import * as React from 'react';
  3. import classNames from 'classnames';
  4. import useId from "rc-util/es/hooks/useId";
  5. import useMergedState from "rc-util/es/hooks/useMergedState";
  6. import pickAttrs from "rc-util/es/pickAttrs";
  7. import { ConfigContext } from '../config-provider';
  8. import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
  9. import useSize from '../config-provider/hooks/useSize';
  10. import { RadioGroupContextProvider } from './context';
  11. import Radio from './radio';
  12. import useStyle from './style';
  13. import { FormItemInputContext } from '../form/context';
  14. import { toNamePathStr } from '../form/hooks/useForm';
  15. const RadioGroup = /*#__PURE__*/React.forwardRef((props, ref) => {
  16. const {
  17. getPrefixCls,
  18. direction
  19. } = React.useContext(ConfigContext);
  20. const {
  21. name: formItemName
  22. } = React.useContext(FormItemInputContext);
  23. const defaultName = useId(toNamePathStr(formItemName));
  24. const {
  25. prefixCls: customizePrefixCls,
  26. className,
  27. rootClassName,
  28. options,
  29. buttonStyle = 'outline',
  30. disabled,
  31. children,
  32. size: customizeSize,
  33. style,
  34. id,
  35. optionType,
  36. name = defaultName,
  37. defaultValue,
  38. value: customizedValue,
  39. block = false,
  40. onChange,
  41. onMouseEnter,
  42. onMouseLeave,
  43. onFocus,
  44. onBlur
  45. } = props;
  46. const [value, setValue] = useMergedState(defaultValue, {
  47. value: customizedValue
  48. });
  49. const onRadioChange = React.useCallback(event => {
  50. const lastValue = value;
  51. const val = event.target.value;
  52. if (!('value' in props)) {
  53. setValue(val);
  54. }
  55. if (val !== lastValue) {
  56. onChange === null || onChange === void 0 ? void 0 : onChange(event);
  57. }
  58. }, [value, setValue, onChange]);
  59. const prefixCls = getPrefixCls('radio', customizePrefixCls);
  60. const groupPrefixCls = `${prefixCls}-group`;
  61. // Style
  62. const rootCls = useCSSVarCls(prefixCls);
  63. const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
  64. let childrenToRender = children;
  65. // 如果存在 options, 优先使用
  66. if (options && options.length > 0) {
  67. childrenToRender = options.map(option => {
  68. if (typeof option === 'string' || typeof option === 'number') {
  69. // 此处类型自动推导为 string
  70. return /*#__PURE__*/React.createElement(Radio, {
  71. key: option.toString(),
  72. prefixCls: prefixCls,
  73. disabled: disabled,
  74. value: option,
  75. checked: value === option
  76. }, option);
  77. }
  78. // 此处类型自动推导为 { label: string value: string }
  79. return /*#__PURE__*/React.createElement(Radio, {
  80. key: `radio-group-value-options-${option.value}`,
  81. prefixCls: prefixCls,
  82. disabled: option.disabled || disabled,
  83. value: option.value,
  84. checked: value === option.value,
  85. title: option.title,
  86. style: option.style,
  87. className: option.className,
  88. id: option.id,
  89. required: option.required
  90. }, option.label);
  91. });
  92. }
  93. const mergedSize = useSize(customizeSize);
  94. const classString = classNames(groupPrefixCls, `${groupPrefixCls}-${buttonStyle}`, {
  95. [`${groupPrefixCls}-${mergedSize}`]: mergedSize,
  96. [`${groupPrefixCls}-rtl`]: direction === 'rtl',
  97. [`${groupPrefixCls}-block`]: block
  98. }, className, rootClassName, hashId, cssVarCls, rootCls);
  99. const memoizedValue = React.useMemo(() => ({
  100. onChange: onRadioChange,
  101. value,
  102. disabled,
  103. name,
  104. optionType,
  105. block
  106. }), [onRadioChange, value, disabled, name, optionType, block]);
  107. return wrapCSSVar(/*#__PURE__*/React.createElement("div", Object.assign({}, pickAttrs(props, {
  108. aria: true,
  109. data: true
  110. }), {
  111. className: classString,
  112. style: style,
  113. onMouseEnter: onMouseEnter,
  114. onMouseLeave: onMouseLeave,
  115. onFocus: onFocus,
  116. onBlur: onBlur,
  117. id: id,
  118. ref: ref
  119. }), /*#__PURE__*/React.createElement(RadioGroupContextProvider, {
  120. value: memoizedValue
  121. }, childrenToRender)));
  122. });
  123. export default /*#__PURE__*/React.memo(RadioGroup);