refactor: radio context
parent
a435e2c090
commit
44be8722f8
|
@ -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 (
|
||||
<Radio
|
||||
key={option}
|
||||
prefixCls={optionsPrefixCls}
|
||||
prefixCls={prefixCls.value}
|
||||
disabled={props.disabled}
|
||||
value={option}
|
||||
checked={stateValue.value === option}
|
||||
|
@ -112,7 +113,7 @@ export default defineComponent({
|
|||
return (
|
||||
<Radio
|
||||
key={`radio-group-value-options-${value}`}
|
||||
prefixCls={optionsPrefixCls}
|
||||
prefixCls={prefixCls.value}
|
||||
disabled={disabled || props.disabled}
|
||||
value={value}
|
||||
checked={stateValue.value === value}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
import { defineComponent, inject, ref } from 'vue';
|
||||
import { computed, defineComponent, ref } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import VcCheckbox from '../vc-checkbox/Checkbox';
|
||||
import classNames from '../_util/classNames';
|
||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||
import type { RadioChangeEvent, RadioGroupContext } from './interface';
|
||||
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||
import type { RadioChangeEvent } from './interface';
|
||||
import { FormItemInputContext, useInjectFormItemContext } from '../form/FormItemContext';
|
||||
import omit from '../_util/omit';
|
||||
import type { FocusEventHandler, MouseEventHandler } from '../_util/EventInterface';
|
||||
import { useInjectRadioGroupContext, useInjectRadioOptionTypeContext } from './context';
|
||||
|
||||
export const radioProps = () => ({
|
||||
prefixCls: String,
|
||||
|
@ -31,13 +32,19 @@ export type RadioProps = Partial<ExtractPropTypes<ReturnType<typeof radioProps>>
|
|||
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<HTMLElement>();
|
||||
const radioGroupContext = inject<RadioGroupContext>('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 (
|
||||
|
|
|
@ -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>('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 <Radio {...rProps}>{slots.default?.()}</Radio>;
|
||||
return (
|
||||
<Radio {...props} prefixCls={prefixCls.value} type="radio">
|
||||
{slots.default?.()}
|
||||
</Radio>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import type { InjectionKey } from 'vue';
|
||||
import { inject, provide } from 'vue';
|
||||
import type { RadioGroupContext, RadioOptionTypeContextProps } from './interface';
|
||||
|
||||
const radioGroupContextKey: InjectionKey<RadioGroupContext> = Symbol('radioGroupContextKey');
|
||||
export const useProvideRadioGroupContext = (props: RadioGroupContext) => {
|
||||
provide(radioGroupContextKey, props);
|
||||
};
|
||||
|
||||
export const useInjectRadioGroupContext = () => {
|
||||
return inject(radioGroupContextKey, undefined);
|
||||
};
|
||||
|
||||
const radioOptionTypeContextKey: InjectionKey<RadioOptionTypeContextProps> = Symbol(
|
||||
'radioOptionTypeContextKey',
|
||||
);
|
||||
export const useProvideRadioOptionTypeContext = (props: RadioOptionTypeContextProps) => {
|
||||
provide(radioOptionTypeContextKey, props);
|
||||
};
|
||||
|
||||
export const useInjectRadioOptionTypeContext = () => {
|
||||
return inject(radioOptionTypeContextKey, undefined);
|
||||
};
|
|
@ -15,7 +15,17 @@ export interface RadioChangeEvent {
|
|||
}
|
||||
|
||||
export interface RadioGroupContext {
|
||||
stateValue: Ref;
|
||||
props: RadioProps;
|
||||
onRadioChange: (e: RadioChangeEvent) => void;
|
||||
onChange: (e: RadioChangeEvent) => void;
|
||||
value: Ref<any>;
|
||||
disabled: Ref<boolean>;
|
||||
name: Ref<string>;
|
||||
/**
|
||||
* Control the appearance for Radio to display as button or not
|
||||
*
|
||||
* @default 'default'
|
||||
* @internal
|
||||
*/
|
||||
optionType?: Ref<RadioGroupOptionType>;
|
||||
}
|
||||
|
||||
export type RadioOptionTypeContextProps = RadioGroupOptionType;
|
||||
|
|
|
@ -42,6 +42,13 @@
|
|||
overflow: hidden;
|
||||
content: '\a0';
|
||||
}
|
||||
|
||||
&&-in-form-item {
|
||||
input[type='radio'] {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls} {
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
// deps-lint-skip: form
|
||||
|
|
Loading…
Reference in New Issue