|
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