diff --git a/components/radio/Group.tsx b/components/radio/Group.tsx index 59c901dce..c05bccada 100644 --- a/components/radio/Group.tsx +++ b/components/radio/Group.tsx @@ -1,4 +1,4 @@ -import { provide, nextTick, defineComponent, ref, watch } from 'vue'; +import { nextTick, defineComponent, ref, watch, computed } from 'vue'; import type { PropType, ExtractPropTypes } from 'vue'; import classNames from '../_util/classNames'; import PropTypes from '../_util/vue-types'; @@ -7,6 +7,7 @@ import useConfigInject from '../_util/hooks/useConfigInject'; import { tuple } from '../_util/type'; import type { RadioChangeEvent, RadioGroupButtonStyle, RadioGroupOptionType } from './interface'; import { useInjectFormItemContext } from '../form/FormItemContext'; +import { useProvideRadioGroupContext } from './context'; const RadioGroupSizeTypes = tuple('large', 'default', 'small'); @@ -74,14 +75,16 @@ export default defineComponent({ }); }; - provide('radioGroupContext', { - onRadioChange, - stateValue, - props, + useProvideRadioGroupContext({ + onChange: onRadioChange, + value: stateValue, + disabled: computed(() => props.disabled), + name: computed(() => props.name), + optionType: computed(() => props.optionType), }); return () => { - const { options, optionType, buttonStyle, id = formItemContext.id.value } = props; + const { options, buttonStyle, id = formItemContext.id.value } = props; const groupPrefixCls = `${prefixCls.value}-group`; @@ -92,14 +95,12 @@ export default defineComponent({ let children = null; if (options && options.length > 0) { - const optionsPrefixCls = - optionType === 'button' ? `${prefixCls.value}-button` : prefixCls.value; children = options.map(option => { if (typeof option === 'string' || typeof option === 'number') { return ( ({ prefixCls: String, @@ -31,13 +32,19 @@ export type RadioProps = Partial> export default defineComponent({ name: 'ARadio', props: radioProps(), - // emits: ['update:checked', 'update:value', 'change', 'blur', 'focus'], setup(props, { emit, expose, slots }) { const formItemContext = useInjectFormItemContext(); + const formItemInputContext = FormItemInputContext.useInject(); + const radioOptionTypeContext = useInjectRadioOptionTypeContext(); + const radioGroupContext = useInjectRadioGroupContext(); const vcCheckbox = ref(); - const radioGroupContext = inject('radioGroupContext', undefined); - const { prefixCls, direction } = useConfigInject('radio', props); + const { prefixCls: radioPrefixCls, direction } = useConfigInject('radio', props); + const prefixCls = computed(() => + (radioGroupContext?.optionType.value || radioOptionTypeContext) === 'button' + ? `${radioPrefixCls.value}-button` + : radioPrefixCls.value, + ); const focus = () => { vcCheckbox.value.focus(); }; @@ -58,8 +65,8 @@ export default defineComponent({ const onChange = (e: RadioChangeEvent) => { emit('change', e); - if (radioGroupContext && radioGroupContext.onRadioChange) { - radioGroupContext.onRadioChange(e); + if (radioGroupContext && radioGroupContext.onChange) { + radioGroupContext.onChange(e); } }; @@ -74,10 +81,10 @@ export default defineComponent({ }; if (radioGroup) { - rProps.name = radioGroup.props.name; + rProps.name = radioGroup.name.value; rProps.onChange = onChange; - rProps.checked = props.value === radioGroup.stateValue.value; - rProps.disabled = props.disabled || radioGroup.props.disabled; + rProps.checked = props.value === radioGroup.value.value; + rProps.disabled = props.disabled || radioGroup.disabled.value; } else { rProps.onChange = handleChange; } @@ -86,6 +93,7 @@ export default defineComponent({ [`${prefixCls.value}-wrapper-checked`]: rProps.checked, [`${prefixCls.value}-wrapper-disabled`]: rProps.disabled, [`${prefixCls.value}-wrapper-rtl`]: direction.value === 'rtl', + [`${prefixCls.value}-wrapper-in-form-item`]: formItemInputContext.isFormItemInput, }); return ( diff --git a/components/radio/RadioButton.tsx b/components/radio/RadioButton.tsx index e2c37d2c3..8ddc7275b 100644 --- a/components/radio/RadioButton.tsx +++ b/components/radio/RadioButton.tsx @@ -1,28 +1,20 @@ -import { defineComponent, inject } from 'vue'; -import type { RadioProps } from './Radio'; +import { defineComponent } from 'vue'; import Radio, { radioProps } from './Radio'; import useConfigInject from '../_util/hooks/useConfigInject'; -import type { RadioGroupContext } from './interface'; +import { useProvideRadioOptionTypeContext } from './context'; export default defineComponent({ name: 'ARadioButton', props: radioProps(), setup(props, { slots }) { const { prefixCls } = useConfigInject('radio-button', props); - const radioGroupContext = inject('radioGroupContext', undefined); - + useProvideRadioOptionTypeContext('button'); return () => { - const rProps: RadioProps = { - ...props, - prefixCls: prefixCls.value, - }; - - if (radioGroupContext) { - rProps.onChange = radioGroupContext.onRadioChange; - rProps.checked = rProps.value === radioGroupContext.stateValue.value; - rProps.disabled = rProps.disabled || radioGroupContext.props.disabled; - } - return {slots.default?.()}; + return ( + + {slots.default?.()} + + ); }; }, }); diff --git a/components/radio/context.ts b/components/radio/context.ts new file mode 100644 index 000000000..8748f6e23 --- /dev/null +++ b/components/radio/context.ts @@ -0,0 +1,23 @@ +import type { InjectionKey } from 'vue'; +import { inject, provide } from 'vue'; +import type { RadioGroupContext, RadioOptionTypeContextProps } from './interface'; + +const radioGroupContextKey: InjectionKey = Symbol('radioGroupContextKey'); +export const useProvideRadioGroupContext = (props: RadioGroupContext) => { + provide(radioGroupContextKey, props); +}; + +export const useInjectRadioGroupContext = () => { + return inject(radioGroupContextKey, undefined); +}; + +const radioOptionTypeContextKey: InjectionKey = Symbol( + 'radioOptionTypeContextKey', +); +export const useProvideRadioOptionTypeContext = (props: RadioOptionTypeContextProps) => { + provide(radioOptionTypeContextKey, props); +}; + +export const useInjectRadioOptionTypeContext = () => { + return inject(radioOptionTypeContextKey, undefined); +}; diff --git a/components/radio/interface.ts b/components/radio/interface.ts index ee860fc90..005f5ca67 100644 --- a/components/radio/interface.ts +++ b/components/radio/interface.ts @@ -15,7 +15,17 @@ export interface RadioChangeEvent { } export interface RadioGroupContext { - stateValue: Ref; - props: RadioProps; - onRadioChange: (e: RadioChangeEvent) => void; + onChange: (e: RadioChangeEvent) => void; + value: Ref; + disabled: Ref; + name: Ref; + /** + * Control the appearance for Radio to display as button or not + * + * @default 'default' + * @internal + */ + optionType?: Ref; } + +export type RadioOptionTypeContextProps = RadioGroupOptionType; diff --git a/components/radio/style/index.less b/components/radio/style/index.less index 713dc25d0..357801590 100644 --- a/components/radio/style/index.less +++ b/components/radio/style/index.less @@ -42,6 +42,13 @@ overflow: hidden; content: '\a0'; } + + &&-in-form-item { + input[type='radio'] { + width: 14px; + height: 14px; + } + } } .@{radio-prefix-cls} { diff --git a/components/radio/style/index.tsx b/components/radio/style/index.tsx index 3a3ab0de5..d53a9fa2e 100644 --- a/components/radio/style/index.tsx +++ b/components/radio/style/index.tsx @@ -1,2 +1,3 @@ import '../../style/index.less'; import './index.less'; +// deps-lint-skip: form