|
1 |
| -import type { ExtractPropTypes } from 'vue'; |
2 |
| -import { defineComponent, inject, nextTick } from 'vue'; |
3 |
| -import PropTypes from '../_util/vue-types'; |
| 1 | +import { watchEffect, onMounted, defineComponent, inject, onBeforeUnmount, ref } from 'vue'; |
4 | 2 | import classNames from '../_util/classNames';
|
5 |
| -import VcCheckbox from '../vc-checkbox'; |
6 |
| -import hasProp, { getOptionProps, getSlot } from '../_util/props-util'; |
7 |
| -import { defaultConfigProvider } from '../config-provider'; |
| 3 | +import VcCheckbox from '../vc-checkbox/Checkbox'; |
| 4 | +import { flattenChildren } from '../_util/props-util'; |
8 | 5 | import warning from '../_util/warning';
|
9 | 6 | import type { RadioChangeEvent } from '../radio/interface';
|
10 | 7 | import type { EventHandler } from '../_util/EventInterface';
|
11 | 8 | import { useInjectFormItemContext } from '../form/FormItemContext';
|
12 |
| -function noop() {} |
| 9 | +import useConfigInject from '../_util/hooks/useConfigInject'; |
13 | 10 |
|
14 |
| -export const checkboxProps = () => { |
15 |
| - return { |
16 |
| - prefixCls: PropTypes.string, |
17 |
| - defaultChecked: PropTypes.looseBool, |
18 |
| - checked: PropTypes.looseBool, |
19 |
| - disabled: PropTypes.looseBool, |
20 |
| - isGroup: PropTypes.looseBool, |
21 |
| - value: PropTypes.any, |
22 |
| - name: PropTypes.string, |
23 |
| - id: PropTypes.string, |
24 |
| - indeterminate: PropTypes.looseBool, |
25 |
| - type: PropTypes.string.def('checkbox'), |
26 |
| - autofocus: PropTypes.looseBool, |
27 |
| - onChange: PropTypes.func, |
28 |
| - 'onUpdate:checked': PropTypes.func, |
29 |
| - skipGroup: PropTypes.looseBool, |
30 |
| - }; |
31 |
| -}; |
32 |
| - |
33 |
| -export type CheckboxProps = Partial<ExtractPropTypes<ReturnType<typeof checkboxProps>>>; |
| 11 | +import type { CheckboxProps } from './interface'; |
| 12 | +import { CheckboxGroupContextKey, checkboxProps } from './interface'; |
34 | 13 |
|
35 | 14 | export default defineComponent({
|
36 | 15 | name: 'ACheckbox',
|
37 | 16 | inheritAttrs: false,
|
38 | 17 | __ANT_CHECKBOX: true,
|
39 | 18 | props: checkboxProps(),
|
40 | 19 | emits: ['change', 'update:checked'],
|
41 |
| - setup() { |
| 20 | + setup(props, { emit, attrs, slots, expose }) { |
42 | 21 | const formItemContext = useInjectFormItemContext();
|
43 |
| - return { |
44 |
| - formItemContext, |
45 |
| - configProvider: inject('configProvider', defaultConfigProvider), |
46 |
| - checkboxGroupContext: inject('checkboxGroupContext', undefined), |
47 |
| - }; |
48 |
| - }, |
| 22 | + const { prefixCls, direction } = useConfigInject('checkbox', props); |
| 23 | + const checkboxGroup = inject(CheckboxGroupContextKey, undefined); |
| 24 | + const uniId = Symbol('checkboxUniId'); |
49 | 25 |
|
50 |
| - watch: { |
51 |
| - value(value, prevValue) { |
52 |
| - if (this.skipGroup) { |
53 |
| - return; |
| 26 | + watchEffect(() => { |
| 27 | + if (!props.skipGroup && checkboxGroup) { |
| 28 | + checkboxGroup.registerValue(uniId, props.value); |
54 | 29 | }
|
55 |
| - nextTick(() => { |
56 |
| - const { checkboxGroupContext: checkboxGroup = {} } = this; |
57 |
| - if (checkboxGroup.registerValue && checkboxGroup.cancelValue) { |
58 |
| - checkboxGroup.cancelValue(prevValue); |
59 |
| - checkboxGroup.registerValue(value); |
60 |
| - } |
61 |
| - }); |
62 |
| - }, |
63 |
| - }, |
64 |
| - |
65 |
| - mounted() { |
66 |
| - const { value, checkboxGroupContext: checkboxGroup = {} } = this; |
67 |
| - if (checkboxGroup.registerValue) { |
68 |
| - checkboxGroup.registerValue(value); |
69 |
| - } |
| 30 | + }); |
| 31 | + onBeforeUnmount(() => { |
| 32 | + if (checkboxGroup) { |
| 33 | + checkboxGroup.cancelValue(uniId); |
| 34 | + } |
| 35 | + }); |
| 36 | + onMounted(() => { |
| 37 | + warning( |
| 38 | + props.checked !== undefined || checkboxGroup || props.value === undefined, |
| 39 | + 'Checkbox', |
| 40 | + '`value` is not validate prop, do you mean `checked`?', |
| 41 | + ); |
| 42 | + }); |
70 | 43 |
|
71 |
| - warning( |
72 |
| - hasProp(this, 'checked') || this.checkboxGroupContext || !hasProp(this, 'value'), |
73 |
| - 'Checkbox', |
74 |
| - '`value` is not validate prop, do you mean `checked`?', |
75 |
| - ); |
76 |
| - }, |
77 |
| - beforeUnmount() { |
78 |
| - const { value, checkboxGroupContext: checkboxGroup = {} } = this; |
79 |
| - if (checkboxGroup.cancelValue) { |
80 |
| - checkboxGroup.cancelValue(value); |
81 |
| - } |
82 |
| - }, |
83 |
| - methods: { |
84 |
| - handleChange(event: RadioChangeEvent) { |
| 44 | + const handleChange = (event: RadioChangeEvent) => { |
85 | 45 | const targetChecked = event.target.checked;
|
86 |
| - this.$emit('update:checked', targetChecked); |
87 |
| - // this.$emit('input', targetChecked); |
88 |
| - this.$emit('change', event); |
89 |
| - }, |
90 |
| - focus() { |
91 |
| - (this.$refs.vcCheckbox as HTMLInputElement).focus(); |
92 |
| - }, |
93 |
| - blur() { |
94 |
| - (this.$refs.vcCheckbox as HTMLInputElement).blur(); |
95 |
| - }, |
96 |
| - }, |
97 |
| - |
98 |
| - render() { |
99 |
| - const props = getOptionProps(this); |
100 |
| - const { checkboxGroupContext: checkboxGroup, $attrs } = this; |
101 |
| - const children = getSlot(this); |
102 |
| - const { |
103 |
| - indeterminate, |
104 |
| - prefixCls: customizePrefixCls, |
105 |
| - skipGroup, |
106 |
| - id = this.formItemContext.id.value, |
107 |
| - ...restProps |
108 |
| - } = props; |
109 |
| - const getPrefixCls = this.configProvider.getPrefixCls; |
110 |
| - const prefixCls = getPrefixCls('checkbox', customizePrefixCls); |
111 |
| - const { |
112 |
| - onMouseenter = noop, |
113 |
| - onMouseleave = noop, |
114 |
| - onInput, |
115 |
| - class: className, |
116 |
| - style, |
117 |
| - ...restAttrs |
118 |
| - } = $attrs; |
119 |
| - const checkboxProps: any = { |
120 |
| - ...restProps, |
121 |
| - id, |
122 |
| - prefixCls, |
123 |
| - ...restAttrs, |
| 46 | + emit('update:checked', targetChecked); |
| 47 | + emit('change', event); |
124 | 48 | };
|
125 |
| - if (checkboxGroup && !skipGroup) { |
126 |
| - checkboxProps.onChange = (...args) => { |
127 |
| - this.$emit('change', ...args); |
128 |
| - this.formItemContext.onFieldChange(); |
129 |
| - checkboxGroup.toggleOption({ label: children, value: props.value }); |
130 |
| - }; |
131 |
| - checkboxProps.name = checkboxGroup.name; |
132 |
| - checkboxProps.checked = checkboxGroup.sValue.indexOf(props.value) !== -1; |
133 |
| - checkboxProps.disabled = props.disabled || checkboxGroup.disabled; |
134 |
| - checkboxProps.indeterminate = indeterminate; |
135 |
| - } else { |
136 |
| - checkboxProps.onChange = this.handleChange; |
137 |
| - } |
138 |
| - const classString = classNames( |
139 |
| - { |
140 |
| - [`${prefixCls}-wrapper`]: true, |
141 |
| - [`${prefixCls}-wrapper-checked`]: checkboxProps.checked, |
142 |
| - [`${prefixCls}-wrapper-disabled`]: checkboxProps.disabled, |
143 |
| - }, |
144 |
| - className, |
145 |
| - ); |
146 |
| - const checkboxClass = classNames({ |
147 |
| - [`${prefixCls}-indeterminate`]: indeterminate, |
| 49 | + const checkboxRef = ref(); |
| 50 | + const focus = () => { |
| 51 | + checkboxRef.value?.focus(); |
| 52 | + }; |
| 53 | + const blur = () => { |
| 54 | + checkboxRef.value?.blur(); |
| 55 | + }; |
| 56 | + expose({ |
| 57 | + focus, |
| 58 | + blur, |
148 | 59 | });
|
149 |
| - return ( |
150 |
| - <label |
151 |
| - class={classString} |
152 |
| - style={style} |
153 |
| - onMouseenter={onMouseenter as EventHandler} |
154 |
| - onMouseleave={onMouseleave as EventHandler} |
155 |
| - > |
156 |
| - <VcCheckbox {...checkboxProps} class={checkboxClass} ref="vcCheckbox" /> |
157 |
| - {children.length ? <span>{children}</span> : null} |
158 |
| - </label> |
159 |
| - ); |
| 60 | + return () => { |
| 61 | + const children = flattenChildren(slots.default?.()); |
| 62 | + const { indeterminate, skipGroup, id = formItemContext.id.value, ...restProps } = props; |
| 63 | + const { onMouseenter, onMouseleave, onInput, class: className, style, ...restAttrs } = attrs; |
| 64 | + const checkboxProps: CheckboxProps = { |
| 65 | + ...restProps, |
| 66 | + id, |
| 67 | + prefixCls: prefixCls.value, |
| 68 | + ...restAttrs, |
| 69 | + }; |
| 70 | + if (checkboxGroup && !skipGroup) { |
| 71 | + checkboxProps.onChange = (...args) => { |
| 72 | + emit('change', ...args); |
| 73 | + checkboxGroup.toggleOption({ label: children, value: props.value }); |
| 74 | + }; |
| 75 | + checkboxProps.name = checkboxGroup.name.value; |
| 76 | + checkboxProps.checked = checkboxGroup.mergedValue.value.indexOf(props.value) !== -1; |
| 77 | + checkboxProps.disabled = props.disabled || checkboxGroup.disabled.value; |
| 78 | + checkboxProps.indeterminate = indeterminate; |
| 79 | + } else { |
| 80 | + checkboxProps.onChange = handleChange; |
| 81 | + } |
| 82 | + const classString = classNames( |
| 83 | + { |
| 84 | + [`${prefixCls.value}-wrapper`]: true, |
| 85 | + [`${prefixCls.value}-rtl`]: direction.value === 'rtl', |
| 86 | + [`${prefixCls.value}-wrapper-checked`]: checkboxProps.checked, |
| 87 | + [`${prefixCls.value}-wrapper-disabled`]: checkboxProps.disabled, |
| 88 | + }, |
| 89 | + className, |
| 90 | + ); |
| 91 | + const checkboxClass = classNames({ |
| 92 | + [`${prefixCls.value}-indeterminate`]: indeterminate, |
| 93 | + }); |
| 94 | + return ( |
| 95 | + <label |
| 96 | + class={classString} |
| 97 | + style={style} |
| 98 | + onMouseenter={onMouseenter as EventHandler} |
| 99 | + onMouseleave={onMouseleave as EventHandler} |
| 100 | + > |
| 101 | + <VcCheckbox {...checkboxProps} class={checkboxClass} ref={checkboxRef} /> |
| 102 | + {children.length ? <span>{children}</span> : null} |
| 103 | + </label> |
| 104 | + ); |
| 105 | + }; |
160 | 106 | },
|
161 | 107 | });
|
0 commit comments