diff --git a/src/radio/Radio.tsx b/src/radio/Radio.tsx index c222abb1..a4cd4f6f 100644 --- a/src/radio/Radio.tsx +++ b/src/radio/Radio.tsx @@ -2,8 +2,8 @@ import React, { createContext, forwardRef, useContext, useRef } from 'react'; import type { CSSProperties, Ref } from 'react'; import classNames from 'classnames'; import { CheckIcon, CheckCircleFilledIcon } from 'tdesign-icons-react'; +import { usePrefixClass } from 'tdesign-mobile-react/hooks/useClass'; import forwardRefWithStatics from '../_util/forwardRefWithStatics'; -import useConfig from '../_util/useConfig'; import useDefault from '../_util/useDefault'; import type { TdRadioProps } from './type'; import RadioGroup from './RadioGroup'; @@ -27,8 +27,7 @@ const getLimitRow = (row: number): CSSProperties => ({ }); const Radio = forwardRef((_props: RadioProps, ref: Ref) => { - const { classPrefix: prefix } = useConfig(); - const classPrefix = `${prefix}-radio`; + const radioClass = usePrefixClass('radio'); const inputRef = useRef(); const context = useContext(RadioContext); const props = context ? context.inject(_props) : _props; @@ -50,12 +49,13 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref) => { value, borderless, onChange, + readonly, } = useDefaultProps(props, radioDefaultProps); const [radioChecked, setRadioChecked] = useDefault(checked, defaultChecked, onChange); const switchRadioChecked = (area?: string) => { - if (disabled) { + if (disabled || readonly) { return; } if (area === 'content' && contentDisabled) { @@ -73,20 +73,20 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref) => { } if (radioChecked) { if (icon === 'circle') { - return ; + return ; } if (icon === 'line') { - return ; + return ; } if (icon === 'dot') { - let dotIconClassName = `${classPrefix}__icon-${icon}`; - disabled && (dotIconClassName += ` ${classPrefix}__icon-${icon}--disabled`); + let dotIconClassName = `${radioClass}__icon-${icon}`; + disabled && (dotIconClassName += ` ${radioClass}__icon-${icon}--disabled`); return
; } } else { if (icon === 'circle' || icon === 'dot') { - let circleIconClassName = `${classPrefix}__icon-circle`; - disabled && (circleIconClassName += ` ${classPrefix}__icon-circle--disabled`); + let circleIconClassName = `${radioClass}__icon-circle`; + disabled && (circleIconClassName += ` ${radioClass}__icon-circle--disabled`); return
; } if (icon === 'line') { @@ -95,27 +95,22 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref) => { } }; - const labelStyle = { - ...getLimitRow(maxLabelRow), - color: disabled ? '#dcdcdc' : 'inherit', - }; - - const radioClassName = classNames(`${classPrefix}`, `${classPrefix}--${placement}`, { - [`${classPrefix}--block`]: block, + const radioClassName = classNames(`${radioClass}`, `${radioClass}--${placement}`, { + [`${radioClass}--block`]: block, }); - const titleClassName = classNames(`${classPrefix}__title`, { [`${classPrefix}__title--disabled`]: disabled }); + const titleClassName = classNames(`${radioClass}__title`, { [`${radioClass}__title--disabled`]: disabled }); const input = ( { e.stopPropagation(); @@ -127,23 +122,23 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref) => { /> ); - const iconClass = classNames(`${classPrefix}__icon`, `${classPrefix}__icon--${placement}`, { - [`${classPrefix}__icon--checked`]: radioChecked, - [`${classPrefix}__icon--disabled`]: disabled, + const iconClass = classNames(`${radioClass}__icon`, `${radioClass}__icon--${placement}`, { + [`${radioClass}__icon--checked`]: radioChecked, + [`${radioClass}__icon--disabled`]: disabled, }); return (
switchRadioChecked()}> {input}
{renderIcon()}
-
+
{label && ( - + {label} )} {content && (
{content} @@ -151,7 +146,7 @@ const Radio = forwardRef((_props: RadioProps, ref: Ref) => { )}
- {!borderless && block &&
} + {!borderless && block &&
}
); }); diff --git a/src/radio/RadioGroup.tsx b/src/radio/RadioGroup.tsx index 059b3523..e894dfc7 100644 --- a/src/radio/RadioGroup.tsx +++ b/src/radio/RadioGroup.tsx @@ -11,7 +11,7 @@ export interface RadioGroupProps extends TdRadioGroupProps { const RadioGroup: FC = (props) => { const { classPrefix } = useConfig(); - const { disabled, options, value, defaultValue, children, onChange } = props; + const { disabled, options, value, defaultValue, children, onChange, allowUncheck, borderless } = props; const groupRef = useRef(null); const [internalValue, setInternalValue] = useDefault(value, defaultValue, onChange); @@ -27,6 +27,8 @@ const RadioGroup: FC = (props) => { typeof radioProps.value !== 'undefined' && internalValue === radioProps.value, disabled: radioProps.disabled || disabled, + allowUncheck: radioProps.allowUncheck || allowUncheck, + borderless: radioProps.borderless || borderless, onChange: (checked, { e }) => { if (typeof radioProps.onChange === 'function') { radioProps.onChange(checked, { e }); diff --git a/src/radio/defaultProps.ts b/src/radio/defaultProps.ts index 781f4fa0..8beff2f0 100644 --- a/src/radio/defaultProps.ts +++ b/src/radio/defaultProps.ts @@ -16,6 +16,7 @@ export const radioDefaultProps: TdRadioProps = { maxContentRow: 5, maxLabelRow: 3, placement: 'left', + readonly: false, value: undefined, }; diff --git a/src/radio/radio.en-US.md b/src/radio/radio.en-US.md index 92810c64..c2911e20 100644 --- a/src/radio/radio.en-US.md +++ b/src/radio/radio.en-US.md @@ -24,7 +24,8 @@ maxContentRow | Number | 5 | \- | N maxLabelRow | Number | 3 | \- | N name | String | - | \- | N placement | String | left | options: left/right | N -value | String / Number / Boolean | undefined | Typescript:`string \| number \| boolean` | N +readonly | Boolean | false | \- | N +value | String / Number / Boolean | undefined | Typescript:`T` | N onChange | Function | | Typescript:`(checked: boolean, context: { e: ChangeEvent }) => void`
| N @@ -44,4 +45,4 @@ options | Array | - | Typescript:`Array` `type RadioOption = stri placement | String | left | options: left/right | N value | String / Number / Boolean | - | Typescript:`T` `type RadioValue = string \| number \| boolean`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/radio/type.ts) | N defaultValue | String / Number / Boolean | - | uncontrolled property。Typescript:`T` `type RadioValue = string \| number \| boolean`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/radio/type.ts) | N -onChange | Function | | Typescript:`(value: T, context: { e: ChangeEvent }) => void`
| N +onChange | Function | | Typescript:`(value: T, context: { e: ChangeEvent; name?: string }) => void`
| N diff --git a/src/radio/radio.md b/src/radio/radio.md index 6bbe974c..832c1a20 100644 --- a/src/radio/radio.md +++ b/src/radio/radio.md @@ -24,7 +24,8 @@ maxContentRow | Number | 5 | 内容最大行数限制 | N maxLabelRow | Number | 3 | 主文案最大行数限制 | N name | String | - | HTML 元素原生属性 | N placement | String | left | 复选框和内容相对位置。可选项:left/right | N -value | String / Number / Boolean | undefined | 单选按钮的值。TS 类型:`string \| number \| boolean` | N +readonly | Boolean | false | 只读状态 | N +value | String / Number / Boolean | undefined | 单选按钮的值。TS 类型:`T` | N onChange | Function | | TS 类型:`(checked: boolean, context: { e: ChangeEvent }) => void`
选中状态变化时触发 | N @@ -44,4 +45,4 @@ options | Array | - | 单选组件按钮形式。RadioOption 数据类型为 str placement | String | left | 复选框和内容相对位置。可选项:left/right | N value | String / Number / Boolean | - | 选中的值。TS 类型:`T` `type RadioValue = string \| number \| boolean`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/radio/type.ts) | N defaultValue | String / Number / Boolean | - | 选中的值。非受控属性。TS 类型:`T` `type RadioValue = string \| number \| boolean`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/radio/type.ts) | N -onChange | Function | | TS 类型:`(value: T, context: { e: ChangeEvent }) => void`
选中值发生变化时触发 | N +onChange | Function | | TS 类型:`(value: T, context: { e: ChangeEvent; name?: string }) => void`
选中值发生变化时触发, `context.name` 指 RadioGroup 的 name 属性 | N diff --git a/src/radio/style/index.js b/src/radio/style/index.js index 1b755a93..dab3f1cc 100644 --- a/src/radio/style/index.js +++ b/src/radio/style/index.js @@ -1,2 +1 @@ import '../../_common/style/mobile/components/radio/v2/_index.less'; -import '../../_common/style/mobile/components/radio-group/_index.less'; diff --git a/src/radio/type.ts b/src/radio/type.ts index cfc5954d..0972209c 100644 --- a/src/radio/type.ts +++ b/src/radio/type.ts @@ -7,7 +7,7 @@ import { TNode, KeysType } from '../common'; import { ChangeEvent } from 'react'; -export interface TdRadioProps { +export interface TdRadioProps { /** * 已废弃。复选框和内容相对位置 * @default left @@ -83,10 +83,15 @@ export interface TdRadioProps { * @default left */ placement?: 'left' | 'right'; + /** + * 只读状态 + * @default false + */ + readonly?: boolean; /** * 单选按钮的值 */ - value?: string | number | boolean; + value?: T; /** * 选中状态变化时触发 */ @@ -140,9 +145,9 @@ export interface TdRadioGroupProps { */ defaultValue?: T; /** - * 选中值发生变化时触发 + * 选中值发生变化时触发, `context.name` 指 RadioGroup 的 name 属性 */ - onChange?: (value: T, context: { e: ChangeEvent }) => void; + onChange?: (value: T, context: { e: ChangeEvent; name?: string }) => void; } export type RadioOption = string | number | RadioOptionObj;