refactor: checkbox (#5091)
* style: remove not use pkg * refactor: vc-checkbox * refactor: checkbox * fix: radio typepull/5092/head
parent
620214d536
commit
26496ba0a9
|
@ -1,36 +1,15 @@
|
||||||
import type { ExtractPropTypes } from 'vue';
|
import { watchEffect, onMounted, defineComponent, inject, onBeforeUnmount, ref } from 'vue';
|
||||||
import { defineComponent, inject, nextTick } from 'vue';
|
|
||||||
import PropTypes from '../_util/vue-types';
|
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import VcCheckbox from '../vc-checkbox';
|
import VcCheckbox from '../vc-checkbox/Checkbox';
|
||||||
import hasProp, { getOptionProps, getSlot } from '../_util/props-util';
|
import { flattenChildren } from '../_util/props-util';
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
import type { RadioChangeEvent } from '../radio/interface';
|
import type { RadioChangeEvent } from '../radio/interface';
|
||||||
import type { EventHandler } from '../_util/EventInterface';
|
import type { EventHandler } from '../_util/EventInterface';
|
||||||
import { useInjectFormItemContext } from '../form/FormItemContext';
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
function noop() {}
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
|
|
||||||
export const checkboxProps = () => {
|
import type { CheckboxProps } from './interface';
|
||||||
return {
|
import { CheckboxGroupContextKey, checkboxProps } from './interface';
|
||||||
prefixCls: PropTypes.string,
|
|
||||||
defaultChecked: PropTypes.looseBool,
|
|
||||||
checked: PropTypes.looseBool,
|
|
||||||
disabled: PropTypes.looseBool,
|
|
||||||
isGroup: PropTypes.looseBool,
|
|
||||||
value: PropTypes.any,
|
|
||||||
name: PropTypes.string,
|
|
||||||
id: PropTypes.string,
|
|
||||||
indeterminate: PropTypes.looseBool,
|
|
||||||
type: PropTypes.string.def('checkbox'),
|
|
||||||
autofocus: PropTypes.looseBool,
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
'onUpdate:checked': PropTypes.func,
|
|
||||||
skipGroup: PropTypes.looseBool,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CheckboxProps = Partial<ExtractPropTypes<ReturnType<typeof checkboxProps>>>;
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ACheckbox',
|
name: 'ACheckbox',
|
||||||
|
@ -38,113 +17,79 @@ export default defineComponent({
|
||||||
__ANT_CHECKBOX: true,
|
__ANT_CHECKBOX: true,
|
||||||
props: checkboxProps(),
|
props: checkboxProps(),
|
||||||
emits: ['change', 'update:checked'],
|
emits: ['change', 'update:checked'],
|
||||||
setup() {
|
setup(props, { emit, attrs, slots, expose }) {
|
||||||
const formItemContext = useInjectFormItemContext();
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
const { prefixCls, direction } = useConfigInject('checkbox', props);
|
||||||
formItemContext,
|
const checkboxGroup = inject(CheckboxGroupContextKey, undefined);
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
const uniId = Symbol('checkboxUniId');
|
||||||
checkboxGroupContext: inject('checkboxGroupContext', undefined),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
watchEffect(() => {
|
||||||
value(value, prevValue) {
|
if (!props.skipGroup && checkboxGroup) {
|
||||||
if (this.skipGroup) {
|
checkboxGroup.registerValue(uniId, props.value);
|
||||||
return;
|
|
||||||
}
|
|
||||||
nextTick(() => {
|
|
||||||
const { checkboxGroupContext: checkboxGroup = {} } = this;
|
|
||||||
if (checkboxGroup.registerValue && checkboxGroup.cancelValue) {
|
|
||||||
checkboxGroup.cancelValue(prevValue);
|
|
||||||
checkboxGroup.registerValue(value);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
onBeforeUnmount(() => {
|
||||||
},
|
if (checkboxGroup) {
|
||||||
|
checkboxGroup.cancelValue(uniId);
|
||||||
mounted() {
|
|
||||||
const { value, checkboxGroupContext: checkboxGroup = {} } = this;
|
|
||||||
if (checkboxGroup.registerValue) {
|
|
||||||
checkboxGroup.registerValue(value);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
warning(
|
warning(
|
||||||
hasProp(this, 'checked') || this.checkboxGroupContext || !hasProp(this, 'value'),
|
props.checked !== undefined || checkboxGroup || props.value === undefined,
|
||||||
'Checkbox',
|
'Checkbox',
|
||||||
'`value` is not validate prop, do you mean `checked`?',
|
'`value` is not validate prop, do you mean `checked`?',
|
||||||
);
|
);
|
||||||
},
|
});
|
||||||
beforeUnmount() {
|
|
||||||
const { value, checkboxGroupContext: checkboxGroup = {} } = this;
|
|
||||||
if (checkboxGroup.cancelValue) {
|
|
||||||
checkboxGroup.cancelValue(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleChange(event: RadioChangeEvent) {
|
|
||||||
const targetChecked = event.target.checked;
|
|
||||||
this.$emit('update:checked', targetChecked);
|
|
||||||
// this.$emit('input', targetChecked);
|
|
||||||
this.$emit('change', event);
|
|
||||||
},
|
|
||||||
focus() {
|
|
||||||
(this.$refs.vcCheckbox as HTMLInputElement).focus();
|
|
||||||
},
|
|
||||||
blur() {
|
|
||||||
(this.$refs.vcCheckbox as HTMLInputElement).blur();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
const handleChange = (event: RadioChangeEvent) => {
|
||||||
const props = getOptionProps(this);
|
const targetChecked = event.target.checked;
|
||||||
const { checkboxGroupContext: checkboxGroup, $attrs } = this;
|
emit('update:checked', targetChecked);
|
||||||
const children = getSlot(this);
|
emit('change', event);
|
||||||
const {
|
};
|
||||||
indeterminate,
|
const checkboxRef = ref();
|
||||||
prefixCls: customizePrefixCls,
|
const focus = () => {
|
||||||
skipGroup,
|
checkboxRef.value?.focus();
|
||||||
id = this.formItemContext.id.value,
|
};
|
||||||
...restProps
|
const blur = () => {
|
||||||
} = props;
|
checkboxRef.value?.blur();
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
};
|
||||||
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
|
expose({
|
||||||
const {
|
focus,
|
||||||
onMouseenter = noop,
|
blur,
|
||||||
onMouseleave = noop,
|
});
|
||||||
onInput,
|
return () => {
|
||||||
class: className,
|
const children = flattenChildren(slots.default?.());
|
||||||
style,
|
const { indeterminate, skipGroup, id = formItemContext.id.value, ...restProps } = props;
|
||||||
...restAttrs
|
const { onMouseenter, onMouseleave, onInput, class: className, style, ...restAttrs } = attrs;
|
||||||
} = $attrs;
|
const checkboxProps: CheckboxProps = {
|
||||||
const checkboxProps: any = {
|
|
||||||
...restProps,
|
...restProps,
|
||||||
id,
|
id,
|
||||||
prefixCls,
|
prefixCls: prefixCls.value,
|
||||||
...restAttrs,
|
...restAttrs,
|
||||||
};
|
};
|
||||||
if (checkboxGroup && !skipGroup) {
|
if (checkboxGroup && !skipGroup) {
|
||||||
checkboxProps.onChange = (...args) => {
|
checkboxProps.onChange = (...args) => {
|
||||||
this.$emit('change', ...args);
|
emit('change', ...args);
|
||||||
this.formItemContext.onFieldChange();
|
|
||||||
checkboxGroup.toggleOption({ label: children, value: props.value });
|
checkboxGroup.toggleOption({ label: children, value: props.value });
|
||||||
};
|
};
|
||||||
checkboxProps.name = checkboxGroup.name;
|
checkboxProps.name = checkboxGroup.name.value;
|
||||||
checkboxProps.checked = checkboxGroup.sValue.indexOf(props.value) !== -1;
|
checkboxProps.checked = checkboxGroup.mergedValue.value.indexOf(props.value) !== -1;
|
||||||
checkboxProps.disabled = props.disabled || checkboxGroup.disabled;
|
checkboxProps.disabled = props.disabled || checkboxGroup.disabled.value;
|
||||||
checkboxProps.indeterminate = indeterminate;
|
checkboxProps.indeterminate = indeterminate;
|
||||||
} else {
|
} else {
|
||||||
checkboxProps.onChange = this.handleChange;
|
checkboxProps.onChange = handleChange;
|
||||||
}
|
}
|
||||||
const classString = classNames(
|
const classString = classNames(
|
||||||
{
|
{
|
||||||
[`${prefixCls}-wrapper`]: true,
|
[`${prefixCls.value}-wrapper`]: true,
|
||||||
[`${prefixCls}-wrapper-checked`]: checkboxProps.checked,
|
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||||
[`${prefixCls}-wrapper-disabled`]: checkboxProps.disabled,
|
[`${prefixCls.value}-wrapper-checked`]: checkboxProps.checked,
|
||||||
|
[`${prefixCls.value}-wrapper-disabled`]: checkboxProps.disabled,
|
||||||
},
|
},
|
||||||
className,
|
className,
|
||||||
);
|
);
|
||||||
const checkboxClass = classNames({
|
const checkboxClass = classNames({
|
||||||
[`${prefixCls}-indeterminate`]: indeterminate,
|
[`${prefixCls.value}-indeterminate`]: indeterminate,
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
|
@ -153,9 +98,10 @@ export default defineComponent({
|
||||||
onMouseenter={onMouseenter as EventHandler}
|
onMouseenter={onMouseenter as EventHandler}
|
||||||
onMouseleave={onMouseleave as EventHandler}
|
onMouseleave={onMouseleave as EventHandler}
|
||||||
>
|
>
|
||||||
<VcCheckbox {...checkboxProps} class={checkboxClass} ref="vcCheckbox" />
|
<VcCheckbox {...checkboxProps} class={checkboxClass} ref={checkboxRef} />
|
||||||
{children.length ? <span>{children}</span> : null}
|
{children.length ? <span>{children}</span> : null}
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,134 +1,116 @@
|
||||||
import type { PropType } from 'vue';
|
import { computed, ref, watch, defineComponent, provide } from 'vue';
|
||||||
import { defineComponent, inject, provide } from 'vue';
|
|
||||||
import PropTypes from '../_util/vue-types';
|
|
||||||
import Checkbox from './Checkbox';
|
import Checkbox from './Checkbox';
|
||||||
import hasProp, { getSlot } from '../_util/props-util';
|
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
|
||||||
import type { VueNode } from '../_util/type';
|
|
||||||
import { useInjectFormItemContext } from '../form/FormItemContext';
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
|
import type { CheckboxOptionType } from './interface';
|
||||||
|
import { CheckboxGroupContextKey, checkboxGroupProps } from './interface';
|
||||||
|
|
||||||
export type CheckboxValueType = string | number | boolean;
|
|
||||||
export interface CheckboxOptionType {
|
|
||||||
label: VueNode;
|
|
||||||
value: CheckboxValueType;
|
|
||||||
disabled?: boolean;
|
|
||||||
indeterminate?: boolean;
|
|
||||||
onChange?: (e: Event) => void;
|
|
||||||
}
|
|
||||||
function noop() {}
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ACheckboxGroup',
|
name: 'ACheckboxGroup',
|
||||||
props: {
|
props: checkboxGroupProps(),
|
||||||
name: PropTypes.string,
|
|
||||||
prefixCls: PropTypes.string,
|
|
||||||
defaultValue: { type: Array as PropType<Array<CheckboxValueType>> },
|
|
||||||
value: { type: Array as PropType<Array<CheckboxValueType>> },
|
|
||||||
options: { type: Array as PropType<Array<CheckboxOptionType | string>> },
|
|
||||||
disabled: PropTypes.looseBool,
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
id: PropTypes.string,
|
|
||||||
},
|
|
||||||
emits: ['change', 'update:value'],
|
emits: ['change', 'update:value'],
|
||||||
setup() {
|
setup(props, { slots, emit, expose }) {
|
||||||
const formItemContext = useInjectFormItemContext();
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
const { prefixCls, direction } = useConfigInject('checkbox', props);
|
||||||
formItemContext,
|
const mergedValue = ref((props.value === undefined ? props.defaultValue : props.value) || []);
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
watch(
|
||||||
};
|
() => props.value,
|
||||||
|
() => {
|
||||||
|
mergedValue.value = props.value || [];
|
||||||
},
|
},
|
||||||
|
);
|
||||||
data() {
|
const options = computed(() => {
|
||||||
const { value, defaultValue } = this;
|
return props.options.map(option => {
|
||||||
return {
|
|
||||||
sValue: value || defaultValue || [],
|
|
||||||
registeredValues: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(val) {
|
|
||||||
this.sValue = val || [];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
provide('checkboxGroupContext', this);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getOptions() {
|
|
||||||
const { options = [], $slots } = this;
|
|
||||||
return options.map(option => {
|
|
||||||
if (typeof option === 'string') {
|
if (typeof option === 'string') {
|
||||||
return {
|
return {
|
||||||
label: option,
|
label: option,
|
||||||
value: option,
|
value: option,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let label = option.label;
|
return option;
|
||||||
if (label === undefined && $slots.label) {
|
|
||||||
label = $slots.label(option);
|
|
||||||
}
|
|
||||||
return { ...option, label };
|
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
cancelValue(value: CheckboxValueType) {
|
const triggerUpdate = ref(Symbol());
|
||||||
this.registeredValues = this.registeredValues.filter(val => val !== value);
|
const registeredValuesMap = ref<Map<Symbol, string>>(new Map());
|
||||||
},
|
const cancelValue = (id: Symbol) => {
|
||||||
|
registeredValuesMap.value.delete(id);
|
||||||
|
triggerUpdate.value = Symbol();
|
||||||
|
};
|
||||||
|
const registerValue = (id: Symbol, value: string) => {
|
||||||
|
registeredValuesMap.value.set(id, value);
|
||||||
|
triggerUpdate.value = Symbol();
|
||||||
|
};
|
||||||
|
|
||||||
registerValue(value: CheckboxValueType) {
|
const registeredValues = ref(new Map());
|
||||||
this.registeredValues = [...this.registeredValues, value];
|
watch(triggerUpdate, () => {
|
||||||
},
|
const valuseMap = new Map();
|
||||||
toggleOption(option: CheckboxOptionType) {
|
for (const value of registeredValuesMap.value.values()) {
|
||||||
const { registeredValues } = this;
|
valuseMap.set(value, true);
|
||||||
const optionIndex = this.sValue.indexOf(option.value);
|
}
|
||||||
const value = [...this.sValue];
|
registeredValues.value = valuseMap;
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleOption = (option: CheckboxOptionType) => {
|
||||||
|
const optionIndex = mergedValue.value.indexOf(option.value);
|
||||||
|
const value = [...mergedValue.value];
|
||||||
if (optionIndex === -1) {
|
if (optionIndex === -1) {
|
||||||
value.push(option.value);
|
value.push(option.value);
|
||||||
} else {
|
} else {
|
||||||
value.splice(optionIndex, 1);
|
value.splice(optionIndex, 1);
|
||||||
}
|
}
|
||||||
if (!hasProp(this, 'value')) {
|
if (props.value === undefined) {
|
||||||
this.sValue = value;
|
mergedValue.value = value;
|
||||||
}
|
}
|
||||||
const options = this.getOptions();
|
|
||||||
const val = value
|
const val = value
|
||||||
.filter(val => registeredValues.indexOf(val) !== -1)
|
.filter(val => registeredValues.value.has(val))
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const indexA = options.findIndex(opt => opt.value === a);
|
const indexA = options.value.findIndex(opt => opt.value === a);
|
||||||
const indexB = options.findIndex(opt => opt.value === b);
|
const indexB = options.value.findIndex(opt => opt.value === b);
|
||||||
return indexA - indexB;
|
return indexA - indexB;
|
||||||
});
|
});
|
||||||
// this.$emit('input', val);
|
emit('update:value', val);
|
||||||
this.$emit('update:value', val);
|
emit('change', val);
|
||||||
this.$emit('change', val);
|
formItemContext.onFieldChange();
|
||||||
this.formItemContext.onFieldChange();
|
};
|
||||||
},
|
provide(CheckboxGroupContextKey, {
|
||||||
},
|
cancelValue,
|
||||||
render() {
|
registerValue,
|
||||||
const { $props: props, $data: state } = this;
|
toggleOption,
|
||||||
const { prefixCls: customizePrefixCls, options, id = this.formItemContext.id.value } = props;
|
mergedValue,
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
name: computed(() => props.name),
|
||||||
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
|
disabled: computed(() => props.disabled),
|
||||||
let children = getSlot(this);
|
});
|
||||||
const groupPrefixCls = `${prefixCls}-group`;
|
expose({
|
||||||
if (options && options.length > 0) {
|
mergedValue,
|
||||||
children = this.getOptions().map(option => (
|
});
|
||||||
|
return () => {
|
||||||
|
const { id = formItemContext.id.value } = props;
|
||||||
|
let children = null;
|
||||||
|
const groupPrefixCls = `${prefixCls.value}-group`;
|
||||||
|
if (options.value && options.value.length > 0) {
|
||||||
|
children = options.value.map(option => (
|
||||||
<Checkbox
|
<Checkbox
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls.value}
|
||||||
key={option.value.toString()}
|
key={option.value.toString()}
|
||||||
disabled={'disabled' in option ? option.disabled : props.disabled}
|
disabled={'disabled' in option ? option.disabled : props.disabled}
|
||||||
indeterminate={option.indeterminate}
|
indeterminate={option.indeterminate}
|
||||||
value={option.value}
|
value={option.value}
|
||||||
checked={state.sValue.indexOf(option.value) !== -1}
|
checked={mergedValue.value.indexOf(option.value) !== -1}
|
||||||
onChange={option.onChange || noop}
|
onChange={option.onChange}
|
||||||
class={`${groupPrefixCls}-item`}
|
class={`${groupPrefixCls}-item`}
|
||||||
>
|
>
|
||||||
{option.label}
|
{option.label === undefined ? slots.label?.(option) : option.label}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div class={groupPrefixCls} id={id}>
|
<div
|
||||||
{children}
|
class={[groupPrefixCls, { [`${groupPrefixCls}-rtl`]: direction.value === 'rtl' }]}
|
||||||
|
id={id}
|
||||||
|
>
|
||||||
|
{children || slots.default?.()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
exports[`renders ./components/checkbox/demo/basic.vue correctly 1`] = `<label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span><span>Checkbox</span></label>`;
|
exports[`renders ./components/checkbox/demo/basic.vue correctly 1`] = `<label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span><span>Checkbox</span></label>`;
|
||||||
|
|
||||||
exports[`renders ./components/checkbox/demo/check-all.vue correctly 1`] = `
|
exports[`renders ./components/checkbox/demo/check-all.vue correctly 1`] = `
|
||||||
<div style="border-bottom: 1px solid #E9E9E9;"><label class="ant-checkbox-wrapper"><span class="ant-checkbox ant-checkbox-indeterminate"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span><span> Check all </span></label></div>
|
<div><label class="ant-checkbox-wrapper"><span class="ant-checkbox ant-checkbox-indeterminate"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span><span> Check all </span></label></div>
|
||||||
<br>
|
<div class="ant-divider ant-divider-horizontal" role="separator">
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ exports[`renders ./components/checkbox/demo/disabled.vue correctly 1`] = `
|
||||||
<!---->
|
<!---->
|
||||||
</label>
|
</label>
|
||||||
<br>
|
<br>
|
||||||
<label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
|
<label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-wrapper-disabled"><span class="ant-checkbox ant-checkbox-checked ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
|
||||||
<!---->
|
<!---->
|
||||||
</label>
|
</label>
|
||||||
`;
|
`;
|
||||||
|
@ -30,15 +32,18 @@ exports[`renders ./components/checkbox/demo/disabled.vue correctly 1`] = `
|
||||||
exports[`renders ./components/checkbox/demo/group.vue correctly 1`] = `
|
exports[`renders ./components/checkbox/demo/group.vue correctly 1`] = `
|
||||||
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input name="checkboxgroup" type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input name="checkboxgroup" type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input name="checkboxgroup" type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input name="checkboxgroup" type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input name="checkboxgroup" type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input name="checkboxgroup" type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
||||||
<br>
|
<br>
|
||||||
|
<br>
|
||||||
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
||||||
<br>
|
<br>
|
||||||
|
<br>
|
||||||
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span>Apple</span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-group-item"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
||||||
<br>
|
<br>
|
||||||
|
<br>
|
||||||
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-wrapper-disabled ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span><span style="color: red;">Apple</span></span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
<div class="ant-checkbox-group"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked ant-checkbox-wrapper-disabled ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-checked ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value="Apple"><span class="ant-checkbox-inner"></span></span><span><span style="color: red;">Apple</span></span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value="Pear"><span class="ant-checkbox-inner"></span></span><span>Pear</span></label><label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled ant-checkbox-group-item"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value="Orange"><span class="ant-checkbox-inner"></span></span><span>Orange</span></label></div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/checkbox/demo/layout.vue correctly 1`] = `
|
exports[`renders ./components/checkbox/demo/layout.vue correctly 1`] = `
|
||||||
<div class="ant-checkbox-group">
|
<div class="ant-checkbox-group" style="width: 100%;">
|
||||||
<div class="ant-row">
|
<div class="ant-row">
|
||||||
<div class="ant-col ant-col-8"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="A"><span class="ant-checkbox-inner"></span></span><span>A</span></label></div>
|
<div class="ant-col ant-col-8"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="A"><span class="ant-checkbox-inner"></span></span><span>A</span></label></div>
|
||||||
<div class="ant-col ant-col-8"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="B"><span class="ant-checkbox-inner"></span></span><span>B</span></label></div>
|
<div class="ant-col ant-col-8"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value="B"><span class="ant-checkbox-inner"></span></span><span>B</span></label></div>
|
||||||
|
|
|
@ -103,11 +103,10 @@ describe('CheckboxGroup', () => {
|
||||||
props: { options },
|
props: { options },
|
||||||
sync: false,
|
sync: false,
|
||||||
});
|
});
|
||||||
|
expect(wrapper.vm.mergedValue).toEqual([]);
|
||||||
expect(wrapper.vm.sValue).toEqual([]);
|
|
||||||
wrapper.setProps({ value: ['Apple'] });
|
wrapper.setProps({ value: ['Apple'] });
|
||||||
await asyncExpect(() => {
|
await asyncExpect(() => {
|
||||||
expect(wrapper.vm.sValue).toEqual(['Apple']);
|
expect(wrapper.vm.mergedValue).toEqual(['Apple']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ The `indeterminate` property can help you to achieve a 'check all' effect.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :style="{ borderBottom: '1px solid #E9E9E9' }">
|
<div>
|
||||||
<a-checkbox
|
<a-checkbox
|
||||||
v-model:checked="checkAll"
|
v-model:checked="checkAll"
|
||||||
:indeterminate="indeterminate"
|
:indeterminate="indeterminate"
|
||||||
|
@ -26,7 +26,7 @@ The `indeterminate` property can help you to achieve a 'check all' effect.
|
||||||
Check all
|
Check all
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<a-divider />
|
||||||
<a-checkbox-group v-model:value="checkedList" :options="plainOptions" />
|
<a-checkbox-group v-model:value="checkedList" :options="plainOptions" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
checked1: ref(false),
|
checked1: ref(false),
|
||||||
checked2: ref(false),
|
checked2: ref(true),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,10 +19,13 @@ Generate a group of checkboxes from an array
|
||||||
<template>
|
<template>
|
||||||
<a-checkbox-group v-model:value="value1" name="checkboxgroup" :options="plainOptions" />
|
<a-checkbox-group v-model:value="value1" name="checkboxgroup" :options="plainOptions" />
|
||||||
<br />
|
<br />
|
||||||
|
<br />
|
||||||
<a-checkbox-group v-model:value="value2" :options="plainOptions" />
|
<a-checkbox-group v-model:value="value2" :options="plainOptions" />
|
||||||
<br />
|
<br />
|
||||||
|
<br />
|
||||||
<a-checkbox-group v-model:value="value3" :options="options" />
|
<a-checkbox-group v-model:value="value3" :options="options" />
|
||||||
<br />
|
<br />
|
||||||
|
<br />
|
||||||
<a-checkbox-group v-model:value="value4" :options="optionsWithDisabled" disabled>
|
<a-checkbox-group v-model:value="value4" :options="optionsWithDisabled" disabled>
|
||||||
<template #label="{ value }">
|
<template #label="{ value }">
|
||||||
<span style="color: red">{{ value }}</span>
|
<span style="color: red">{{ value }}</span>
|
||||||
|
@ -51,7 +54,6 @@ export default defineComponent({
|
||||||
value3: ['Pear'],
|
value3: ['Pear'],
|
||||||
value4: ['Apple'],
|
value4: ['Apple'],
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plainOptions,
|
plainOptions,
|
||||||
options,
|
options,
|
||||||
|
|
|
@ -17,7 +17,7 @@ We can use Checkbox and Grid Checkbox.group, to implement complex layout
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-checkbox-group v-model:value="value">
|
<a-checkbox-group v-model:value="value" style="width: 100%">
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="8">
|
<a-col :span="8">
|
||||||
<a-checkbox value="A">A</a-checkbox>
|
<a-checkbox value="A">A</a-checkbox>
|
||||||
|
@ -41,8 +41,9 @@ We can use Checkbox and Grid Checkbox.group, to implement complex layout
|
||||||
import { defineComponent, ref } from 'vue';
|
import { defineComponent, ref } from 'vue';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
|
const value = ref([]);
|
||||||
return {
|
return {
|
||||||
value: ref([]),
|
value,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import type { App, Plugin } from 'vue';
|
import type { App, Plugin } from 'vue';
|
||||||
import Checkbox, { checkboxProps } from './Checkbox';
|
import Checkbox from './Checkbox';
|
||||||
import CheckboxGroup from './Group';
|
import CheckboxGroup from './Group';
|
||||||
export type { CheckboxProps } from './Checkbox';
|
export type { CheckboxProps, CheckboxGroupProps, CheckboxOptionType } from './interface';
|
||||||
|
export { checkboxProps, checkboxGroupProps } from './interface';
|
||||||
|
|
||||||
Checkbox.Group = CheckboxGroup;
|
Checkbox.Group = CheckboxGroup;
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@ Checkbox.install = function (app: App) {
|
||||||
app.component(CheckboxGroup.name, CheckboxGroup);
|
app.component(CheckboxGroup.name, CheckboxGroup);
|
||||||
return app;
|
return app;
|
||||||
};
|
};
|
||||||
export { CheckboxGroup, checkboxProps };
|
export { CheckboxGroup };
|
||||||
export default Checkbox as typeof Checkbox &
|
export default Checkbox as typeof Checkbox &
|
||||||
Plugin & {
|
Plugin & {
|
||||||
readonly Group: typeof CheckboxGroup;
|
readonly Group: typeof CheckboxGroup;
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import type { ExtractPropTypes, InjectionKey, PropType, Ref } from 'vue';
|
||||||
|
import type { VueNode } from '../_util/type';
|
||||||
|
import PropTypes from '../_util/vue-types';
|
||||||
|
|
||||||
|
export type CheckboxValueType = string | number | boolean;
|
||||||
|
export interface CheckboxOptionType {
|
||||||
|
label?: VueNode;
|
||||||
|
value: CheckboxValueType;
|
||||||
|
disabled?: boolean;
|
||||||
|
indeterminate?: boolean;
|
||||||
|
onChange?: (e: Event) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const abstractCheckboxGroupProps = () => {
|
||||||
|
return {
|
||||||
|
name: String,
|
||||||
|
prefixCls: String,
|
||||||
|
options: {
|
||||||
|
type: Array as PropType<Array<CheckboxOptionType | string>>,
|
||||||
|
default: () => [] as Array<CheckboxOptionType | string>,
|
||||||
|
},
|
||||||
|
disabled: Boolean,
|
||||||
|
id: String,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkboxGroupProps = () => {
|
||||||
|
return {
|
||||||
|
...abstractCheckboxGroupProps(),
|
||||||
|
defaultValue: { type: Array as PropType<Array<CheckboxValueType>> },
|
||||||
|
value: { type: Array as PropType<Array<CheckboxValueType>> },
|
||||||
|
onChange: { type: Function as PropType<(checkedValue: Array<CheckboxValueType>) => void> },
|
||||||
|
'onUpdate:value': {
|
||||||
|
type: Function as PropType<(checkedValue: Array<CheckboxValueType>) => void>,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CheckboxGroupProps = Partial<ExtractPropTypes<ReturnType<typeof checkboxGroupProps>>>;
|
||||||
|
|
||||||
|
export const abstractCheckboxProps = () => {
|
||||||
|
return {
|
||||||
|
prefixCls: String,
|
||||||
|
defaultChecked: { type: Boolean, default: undefined },
|
||||||
|
checked: { type: Boolean, default: undefined },
|
||||||
|
disabled: { type: Boolean, default: undefined },
|
||||||
|
isGroup: { type: Boolean, default: undefined },
|
||||||
|
value: PropTypes.any,
|
||||||
|
name: String,
|
||||||
|
id: String,
|
||||||
|
indeterminate: { type: Boolean, default: undefined },
|
||||||
|
type: { type: String, default: 'checkbox' },
|
||||||
|
autofocus: { type: Boolean, default: undefined },
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
'onUpdate:checked': PropTypes.func,
|
||||||
|
skipGroup: { type: Boolean, default: false },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkboxProps = () => {
|
||||||
|
return {
|
||||||
|
...abstractCheckboxProps(),
|
||||||
|
indeterminate: { type: Boolean, default: false },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CheckboxProps = Partial<ExtractPropTypes<ReturnType<typeof checkboxProps>>>;
|
||||||
|
|
||||||
|
export type CheckboxGroupContext = {
|
||||||
|
cancelValue: (id: Symbol) => void;
|
||||||
|
registerValue: (id: Symbol, value: string) => void;
|
||||||
|
toggleOption: (option: CheckboxOptionType) => void;
|
||||||
|
name: Ref<string>;
|
||||||
|
disabled: Ref<boolean>;
|
||||||
|
mergedValue: Ref<CheckboxValueType[]>;
|
||||||
|
};
|
||||||
|
export const CheckboxGroupContextKey: InjectionKey<CheckboxGroupContext> =
|
||||||
|
Symbol('CheckboxGroupContext');
|
|
@ -2,3 +2,5 @@
|
||||||
@import './mixin';
|
@import './mixin';
|
||||||
|
|
||||||
.antCheckboxFn();
|
.antCheckboxFn();
|
||||||
|
|
||||||
|
@import './rtl';
|
||||||
|
|
|
@ -7,11 +7,9 @@
|
||||||
.reset-component();
|
.reset-component();
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -0.09em;
|
top: 0.2em;
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
vertical-align: middle;
|
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
@ -28,7 +26,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border: 1px solid @checkbox-color;
|
border: 1px solid @checkbox-color;
|
||||||
border-radius: @border-radius-sm;
|
border-radius: @border-radius-base;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
animation: antCheckboxEffect 0.36s ease-in-out;
|
animation: antCheckboxEffect 0.36s ease-in-out;
|
||||||
animation-fill-mode: backwards;
|
animation-fill-mode: backwards;
|
||||||
|
@ -47,9 +45,10 @@
|
||||||
display: block;
|
display: block;
|
||||||
width: @checkbox-size;
|
width: @checkbox-size;
|
||||||
height: @checkbox-size;
|
height: @checkbox-size;
|
||||||
|
direction: ltr;
|
||||||
background-color: @checkbox-check-bg;
|
background-color: @checkbox-check-bg;
|
||||||
border: @checkbox-border-width @border-style-base @border-color-base;
|
border: @checkbox-border-width @border-style-base @border-color-base;
|
||||||
border-radius: @border-radius-sm;
|
border-radius: @checkbox-border-radius;
|
||||||
// Fix IE checked style
|
// Fix IE checked style
|
||||||
// https://github.com/ant-design/ant-design/issues/12597
|
// https://github.com/ant-design/ant-design/issues/12597
|
||||||
border-collapse: separate;
|
border-collapse: separate;
|
||||||
|
@ -61,6 +60,8 @@
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
// https://github.com/ant-design/ant-design/pull/19452
|
||||||
|
// https://github.com/ant-design/ant-design/pull/31726
|
||||||
left: 21.5%;
|
left: 21.5%;
|
||||||
display: table;
|
display: table;
|
||||||
width: @check-width;
|
width: @check-width;
|
||||||
|
@ -126,6 +127,7 @@
|
||||||
.@{checkbox-inner-prefix-cls} {
|
.@{checkbox-inner-prefix-cls} {
|
||||||
background-color: @input-disabled-bg;
|
background-color: @input-disabled-bg;
|
||||||
border-color: @border-color-base !important;
|
border-color: @border-color-base !important;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
border-color: @input-disabled-bg;
|
border-color: @input-disabled-bg;
|
||||||
border-collapse: separate;
|
border-collapse: separate;
|
||||||
|
@ -147,13 +149,22 @@
|
||||||
|
|
||||||
.@{checkbox-prefix-cls}-wrapper {
|
.@{checkbox-prefix-cls}-wrapper {
|
||||||
.reset-component();
|
.reset-component();
|
||||||
|
display: inline-flex;
|
||||||
display: inline-block;
|
align-items: baseline;
|
||||||
line-height: unset;
|
line-height: unset;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: inline-block;
|
||||||
|
width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
content: '\a0';
|
||||||
|
}
|
||||||
|
|
||||||
&.@{checkbox-prefix-cls}-wrapper-disabled {
|
&.@{checkbox-prefix-cls}-wrapper-disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
& + & {
|
& + & {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
@ -166,15 +177,16 @@
|
||||||
|
|
||||||
.@{checkbox-prefix-cls}-group {
|
.@{checkbox-prefix-cls}-group {
|
||||||
.reset-component();
|
.reset-component();
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
&-item {
|
&-item {
|
||||||
display: inline-block;
|
margin-right: @checkbox-group-item-margin-right;
|
||||||
margin-right: 8px;
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-item + &-item {
|
&-item + &-item {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +195,7 @@
|
||||||
// 半选状态
|
// 半选状态
|
||||||
.@{checkbox-prefix-cls}-indeterminate {
|
.@{checkbox-prefix-cls}-indeterminate {
|
||||||
.@{checkbox-inner-prefix-cls} {
|
.@{checkbox-inner-prefix-cls} {
|
||||||
background-color: @component-background;
|
background-color: @checkbox-check-bg;
|
||||||
border-color: @border-color-base;
|
border-color: @border-color-base;
|
||||||
}
|
}
|
||||||
.@{checkbox-inner-prefix-cls}::after {
|
.@{checkbox-inner-prefix-cls}::after {
|
||||||
|
@ -213,6 +225,7 @@
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: scale(1.6);
|
transform: scale(1.6);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
|
.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-checkbox') {
|
||||||
|
.@{checkbox-prefix-cls}-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{checkbox-prefix-cls}-group {
|
||||||
|
&-item {
|
||||||
|
.@{checkbox-prefix-cls}-group-rtl & {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: @checkbox-group-item-margin-right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
.@{checkbox-prefix-cls}-group-rtl & {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-item + &-item {
|
||||||
|
.@{checkbox-prefix-cls}-group-rtl & {
|
||||||
|
margin-left: @checkbox-group-item-margin-right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,6 +40,7 @@ export { default as Carousel } from './carousel';
|
||||||
export type { CascaderProps } from './cascader';
|
export type { CascaderProps } from './cascader';
|
||||||
export { default as Cascader } from './cascader';
|
export { default as Cascader } from './cascader';
|
||||||
|
|
||||||
|
export type { CheckboxProps, CheckboxGroupProps, CheckboxOptionType } from './checkbox';
|
||||||
export { default as Checkbox, CheckboxGroup } from './checkbox';
|
export { default as Checkbox, CheckboxGroup } from './checkbox';
|
||||||
|
|
||||||
export type { ColProps } from './col';
|
export type { ColProps } from './col';
|
||||||
|
|
|
@ -17,7 +17,7 @@ const RadioGroupOptionTypes = tuple('default', 'button');
|
||||||
export type RadioGroupOption = typeof RadioGroupOptionTypes[number];
|
export type RadioGroupOption = typeof RadioGroupOptionTypes[number];
|
||||||
|
|
||||||
export type RadioGroupChildOption = {
|
export type RadioGroupChildOption = {
|
||||||
label: any;
|
label?: any;
|
||||||
value: any;
|
value: any;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ExtractPropTypes } from 'vue';
|
import type { ExtractPropTypes } from 'vue';
|
||||||
import { defineComponent, inject, ref } from 'vue';
|
import { defineComponent, inject, ref } from 'vue';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import VcCheckbox from '../vc-checkbox';
|
import VcCheckbox from '../vc-checkbox/Checkbox';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
import type { RadioChangeEvent, RadioGroupContext } from './interface';
|
import type { RadioChangeEvent, RadioGroupContext } from './interface';
|
||||||
|
|
|
@ -241,6 +241,8 @@
|
||||||
@checkbox-check-color: #fff;
|
@checkbox-check-color: #fff;
|
||||||
@checkbox-check-bg: @checkbox-check-color;
|
@checkbox-check-bg: @checkbox-check-color;
|
||||||
@checkbox-border-width: @border-width-base;
|
@checkbox-border-width: @border-width-base;
|
||||||
|
@checkbox-border-radius: @border-radius-base;
|
||||||
|
@checkbox-group-item-margin-right: 8px;
|
||||||
|
|
||||||
// Descriptions
|
// Descriptions
|
||||||
@descriptions-bg: #fafafa;
|
@descriptions-bg: #fafafa;
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
// based on rc-checkbox 2.3.2
|
||||||
|
import type { HTMLAttributes } from 'vue';
|
||||||
|
import { nextTick, defineComponent, ref, watch, onMounted } from 'vue';
|
||||||
|
import classNames from '../_util/classNames';
|
||||||
|
import PropTypes from '../_util/vue-types';
|
||||||
|
import { initDefaultProps } from '../_util/props-util';
|
||||||
|
|
||||||
|
const checkboxProps = {
|
||||||
|
prefixCls: String,
|
||||||
|
name: String,
|
||||||
|
id: String,
|
||||||
|
type: String,
|
||||||
|
defaultChecked: { type: [Boolean, Number], default: undefined },
|
||||||
|
checked: { type: [Boolean, Number], default: undefined },
|
||||||
|
disabled: Boolean,
|
||||||
|
tabindex: { type: [Number, String] },
|
||||||
|
readonly: Boolean,
|
||||||
|
autofocus: Boolean,
|
||||||
|
value: PropTypes.any,
|
||||||
|
required: Boolean,
|
||||||
|
};
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Checkbox',
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: initDefaultProps(checkboxProps, {
|
||||||
|
prefixCls: 'rc-checkbox',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultChecked: false,
|
||||||
|
}),
|
||||||
|
emits: ['click', 'change'],
|
||||||
|
setup(props, { attrs, emit, expose }) {
|
||||||
|
const checked = ref(props.checked === undefined ? props.defaultChecked : props.checked);
|
||||||
|
const inputRef = ref<HTMLInputElement>();
|
||||||
|
watch(
|
||||||
|
() => props.checked,
|
||||||
|
() => {
|
||||||
|
checked.value = props.checked;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (process.env.NODE_ENV === 'test') {
|
||||||
|
if (props.autofocus) {
|
||||||
|
inputRef.value?.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
expose({
|
||||||
|
focus() {
|
||||||
|
inputRef.value?.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
blur() {
|
||||||
|
inputRef.value?.blur();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const eventShiftKey = ref();
|
||||||
|
const handleChange = e => {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (props.checked === undefined) {
|
||||||
|
checked.value = e.target.checked;
|
||||||
|
}
|
||||||
|
e.shiftKey = eventShiftKey.value;
|
||||||
|
const eventObj = {
|
||||||
|
target: {
|
||||||
|
...props,
|
||||||
|
checked: e.target.checked,
|
||||||
|
},
|
||||||
|
stopPropagation() {
|
||||||
|
e.stopPropagation();
|
||||||
|
},
|
||||||
|
preventDefault() {
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
|
nativeEvent: e,
|
||||||
|
};
|
||||||
|
|
||||||
|
// fix https://github.com/vueComponent/ant-design-vue/issues/3047
|
||||||
|
// 受控模式下维持现有状态
|
||||||
|
if (props.checked !== undefined) {
|
||||||
|
inputRef.value.checked = !!props.checked;
|
||||||
|
}
|
||||||
|
emit('change', eventObj);
|
||||||
|
eventShiftKey.value = false;
|
||||||
|
};
|
||||||
|
const onClick = (e: MouseEvent) => {
|
||||||
|
emit('click', e);
|
||||||
|
// onChange没能获取到shiftKey,使用onClick hack
|
||||||
|
eventShiftKey.value = e.shiftKey;
|
||||||
|
};
|
||||||
|
return () => {
|
||||||
|
const {
|
||||||
|
prefixCls,
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
disabled,
|
||||||
|
readonly,
|
||||||
|
tabindex,
|
||||||
|
autofocus,
|
||||||
|
value,
|
||||||
|
required,
|
||||||
|
...others
|
||||||
|
} = props;
|
||||||
|
const {
|
||||||
|
class: className,
|
||||||
|
onFocus,
|
||||||
|
onBlur,
|
||||||
|
onKeydown,
|
||||||
|
onKeypress,
|
||||||
|
onKeyup,
|
||||||
|
} = attrs as HTMLAttributes;
|
||||||
|
const globalProps = Object.keys({ ...others, ...attrs }).reduce((prev, key) => {
|
||||||
|
if (key.substr(0, 5) === 'aria-' || key.substr(0, 5) === 'data-' || key === 'role') {
|
||||||
|
prev[key] = others[key];
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const classString = classNames(prefixCls, className, {
|
||||||
|
[`${prefixCls}-checked`]: checked.value,
|
||||||
|
[`${prefixCls}-disabled`]: disabled,
|
||||||
|
});
|
||||||
|
const inputProps = {
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
readonly,
|
||||||
|
disabled,
|
||||||
|
tabindex,
|
||||||
|
class: `${prefixCls}-input`,
|
||||||
|
checked: !!checked.value,
|
||||||
|
autofocus,
|
||||||
|
value,
|
||||||
|
...globalProps,
|
||||||
|
onChange: handleChange,
|
||||||
|
onClick,
|
||||||
|
onFocus,
|
||||||
|
onBlur,
|
||||||
|
onKeydown,
|
||||||
|
onKeypress,
|
||||||
|
onKeyup,
|
||||||
|
required,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span class={classString}>
|
||||||
|
<input ref={inputRef} {...inputProps} />
|
||||||
|
<span class={`${prefixCls}-inner`} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,155 +0,0 @@
|
||||||
@checkboxWarpPrefixCls: rc-checkbox;
|
|
||||||
@checkboxInnerPrefixCls: ~'@{checkboxWarpPrefixCls}-inner';
|
|
||||||
|
|
||||||
/* 一般状态 */
|
|
||||||
.@{checkboxWarpPrefixCls} {
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
line-height: 1;
|
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
&:hover .@{checkboxInnerPrefixCls},
|
|
||||||
&-input:focus + .@{checkboxInnerPrefixCls} {
|
|
||||||
border-color: #3dbcf6;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-inner {
|
|
||||||
&:after {
|
|
||||||
-webkit-transform: rotate(45deg);
|
|
||||||
transform: rotate(45deg);
|
|
||||||
position: absolute;
|
|
||||||
left: 4px;
|
|
||||||
top: 1px;
|
|
||||||
display: table;
|
|
||||||
width: 5px;
|
|
||||||
height: 8px;
|
|
||||||
border: 2px solid #ffffff;
|
|
||||||
border-top: 0;
|
|
||||||
border-left: 0;
|
|
||||||
content: ' ';
|
|
||||||
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
|
||||||
animation-duration: 0.3s;
|
|
||||||
animation-name: amCheckboxOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
display: inline-block;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
border-radius: 3px;
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
background-color: #ffffff;
|
|
||||||
transition: border-color 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55),
|
|
||||||
background-color 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
|
||||||
}
|
|
||||||
|
|
||||||
&-input {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
z-index: 9999;
|
|
||||||
cursor: pointer;
|
|
||||||
opacity: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 选中状态 */
|
|
||||||
.@{checkboxWarpPrefixCls}-checked {
|
|
||||||
&:hover {
|
|
||||||
.@{checkboxInnerPrefixCls} {
|
|
||||||
border-color: #3dbcf6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{checkboxInnerPrefixCls} {
|
|
||||||
border-color: #3dbcf6;
|
|
||||||
background-color: #3dbcf6;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
transform: rotate(45deg);
|
|
||||||
position: absolute;
|
|
||||||
left: 4px;
|
|
||||||
top: 1px;
|
|
||||||
display: table;
|
|
||||||
width: 5px;
|
|
||||||
height: 8px;
|
|
||||||
border: 2px solid #ffffff;
|
|
||||||
border-top: 0;
|
|
||||||
border-left: 0;
|
|
||||||
content: ' ';
|
|
||||||
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
|
||||||
animation-duration: 0.3s;
|
|
||||||
animation-name: amCheckboxOut;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{checkboxWarpPrefixCls}-disabled {
|
|
||||||
&.@{checkboxWarpPrefixCls}-checked {
|
|
||||||
&:hover {
|
|
||||||
.@{checkboxInnerPrefixCls} {
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{checkboxInnerPrefixCls} {
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
animation-name: none;
|
|
||||||
border-color: #cccccc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.@{checkboxInnerPrefixCls} {
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{checkboxInnerPrefixCls} {
|
|
||||||
border-color: #d9d9d9;
|
|
||||||
background-color: #f3f3f3;
|
|
||||||
&:after {
|
|
||||||
animation-name: none;
|
|
||||||
border-color: #f3f3f3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{checkboxInnerPrefixCls}-input {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes amCheckboxIn {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform-origin: 50% 50%;
|
|
||||||
transform: scale(0, 0) rotate(45deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform-origin: 50% 50%;
|
|
||||||
transform: scale(1, 1) rotate(45deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes amCheckboxOut {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
// based on rc-checkbox 2.1.7
|
|
||||||
export { default } from './src/';
|
|
|
@ -1,143 +0,0 @@
|
||||||
import { nextTick, defineComponent } from 'vue';
|
|
||||||
import classNames from '../../_util/classNames';
|
|
||||||
import PropTypes, { withUndefined } from '../../_util/vue-types';
|
|
||||||
import BaseMixin from '../../_util/BaseMixin';
|
|
||||||
import { getOptionProps, hasProp, initDefaultProps } from '../../_util/props-util';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'Checkbox',
|
|
||||||
mixins: [BaseMixin],
|
|
||||||
inheritAttrs: false,
|
|
||||||
props: initDefaultProps(
|
|
||||||
{
|
|
||||||
prefixCls: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
id: PropTypes.string,
|
|
||||||
type: PropTypes.string,
|
|
||||||
defaultChecked: withUndefined(PropTypes.oneOfType([PropTypes.number, PropTypes.looseBool])),
|
|
||||||
checked: withUndefined(PropTypes.oneOfType([PropTypes.number, PropTypes.looseBool])),
|
|
||||||
disabled: PropTypes.looseBool,
|
|
||||||
// onFocus: PropTypes.func,
|
|
||||||
// onBlur: PropTypes.func,
|
|
||||||
// onChange: PropTypes.func,
|
|
||||||
// onClick: PropTypes.func,
|
|
||||||
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
readonly: PropTypes.looseBool,
|
|
||||||
autofocus: PropTypes.looseBool,
|
|
||||||
value: PropTypes.any,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prefixCls: 'rc-checkbox',
|
|
||||||
type: 'checkbox',
|
|
||||||
defaultChecked: false,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
data() {
|
|
||||||
const checked = hasProp(this, 'checked') ? this.checked : this.defaultChecked;
|
|
||||||
return {
|
|
||||||
sChecked: checked,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
checked(val) {
|
|
||||||
this.sChecked = val;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
nextTick(() => {
|
|
||||||
if (process.env.NODE_ENV === 'test') {
|
|
||||||
if (this.autofocus) {
|
|
||||||
this.$refs.input && this.$refs.input.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
focus() {
|
|
||||||
this.$refs.input.focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
blur() {
|
|
||||||
this.$refs.input.blur();
|
|
||||||
},
|
|
||||||
|
|
||||||
handleChange(e) {
|
|
||||||
const props = getOptionProps(this);
|
|
||||||
if (props.disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!('checked' in props)) {
|
|
||||||
this.sChecked = e.target.checked;
|
|
||||||
}
|
|
||||||
e.shiftKey = this.eventShiftKey;
|
|
||||||
const eventObj = {
|
|
||||||
target: {
|
|
||||||
...props,
|
|
||||||
checked: e.target.checked,
|
|
||||||
},
|
|
||||||
stopPropagation() {
|
|
||||||
e.stopPropagation();
|
|
||||||
},
|
|
||||||
preventDefault() {
|
|
||||||
e.preventDefault();
|
|
||||||
},
|
|
||||||
nativeEvent: e,
|
|
||||||
};
|
|
||||||
|
|
||||||
// fix https://github.com/vueComponent/ant-design-vue/issues/3047
|
|
||||||
// 受控模式下维持现有状态
|
|
||||||
if ('checked' in props) {
|
|
||||||
this.$refs.input.checked = props.checked;
|
|
||||||
}
|
|
||||||
this.__emit('change', eventObj);
|
|
||||||
this.eventShiftKey = false;
|
|
||||||
},
|
|
||||||
onClick(e) {
|
|
||||||
this.__emit('click', e);
|
|
||||||
// onChange没能获取到shiftKey,使用onClick hack
|
|
||||||
this.eventShiftKey = e.shiftKey;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { prefixCls, name, id, type, disabled, readonly, tabindex, autofocus, value, ...others } =
|
|
||||||
getOptionProps(this);
|
|
||||||
const { class: className, onFocus, onBlur } = this.$attrs;
|
|
||||||
const globalProps = Object.keys({ ...others, ...this.$attrs }).reduce((prev, key) => {
|
|
||||||
if (key.substr(0, 5) === 'aria-' || key.substr(0, 5) === 'data-' || key === 'role') {
|
|
||||||
prev[key] = others[key];
|
|
||||||
}
|
|
||||||
return prev;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const { sChecked } = this;
|
|
||||||
const classString = classNames(prefixCls, className, {
|
|
||||||
[`${prefixCls}-checked`]: sChecked,
|
|
||||||
[`${prefixCls}-disabled`]: disabled,
|
|
||||||
});
|
|
||||||
const inputProps = {
|
|
||||||
name,
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
readonly,
|
|
||||||
disabled,
|
|
||||||
tabindex,
|
|
||||||
class: `${prefixCls}-input`,
|
|
||||||
checked: !!sChecked,
|
|
||||||
autofocus,
|
|
||||||
value,
|
|
||||||
...globalProps,
|
|
||||||
onChange: this.handleChange,
|
|
||||||
onClick: this.onClick,
|
|
||||||
onFocus,
|
|
||||||
onBlur,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span class={classString}>
|
|
||||||
<input ref="input" {...inputProps} />
|
|
||||||
<span class={`${prefixCls}-inner`} />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Checkbox from './Checkbox';
|
|
||||||
|
|
||||||
export default Checkbox;
|
|
|
@ -1,2 +0,0 @@
|
||||||
import LazyLoad from './src/LazyLoad';
|
|
||||||
export default LazyLoad;
|
|
|
@ -1,151 +0,0 @@
|
||||||
import PropTypes from '../../_util/vue-types';
|
|
||||||
import BaseMixin from '../../_util/BaseMixin';
|
|
||||||
import addEventListener from '../../vc-util/Dom/addEventListener';
|
|
||||||
import { initDefaultProps, findDOMNode, getSlot } from '../../_util/props-util';
|
|
||||||
import warning from '../../_util/warning';
|
|
||||||
import debounce from 'lodash-es/debounce';
|
|
||||||
import throttle from 'lodash-es/throttle';
|
|
||||||
import parentScroll from './utils/parentScroll';
|
|
||||||
import inViewport from './utils/inViewport';
|
|
||||||
import { watchEffect, defineComponent } from 'vue';
|
|
||||||
|
|
||||||
const lazyLoadProps = {
|
|
||||||
debounce: PropTypes.looseBool,
|
|
||||||
elementType: PropTypes.string,
|
|
||||||
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
offset: PropTypes.number,
|
|
||||||
offsetBottom: PropTypes.number,
|
|
||||||
offsetHorizontal: PropTypes.number,
|
|
||||||
offsetLeft: PropTypes.number,
|
|
||||||
offsetRight: PropTypes.number,
|
|
||||||
offsetTop: PropTypes.number,
|
|
||||||
offsetVertical: PropTypes.number,
|
|
||||||
threshold: PropTypes.number,
|
|
||||||
throttle: PropTypes.number,
|
|
||||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'LazyLoad',
|
|
||||||
mixins: [BaseMixin],
|
|
||||||
inheritAttrs: false,
|
|
||||||
props: initDefaultProps(lazyLoadProps, {
|
|
||||||
elementType: 'div',
|
|
||||||
debounce: true,
|
|
||||||
offset: 0,
|
|
||||||
offsetBottom: 0,
|
|
||||||
offsetHorizontal: 0,
|
|
||||||
offsetLeft: 0,
|
|
||||||
offsetRight: 0,
|
|
||||||
offsetTop: 0,
|
|
||||||
offsetVertical: 0,
|
|
||||||
throttle: 250,
|
|
||||||
}),
|
|
||||||
data() {
|
|
||||||
if (this.throttle > 0) {
|
|
||||||
if (this.debounce) {
|
|
||||||
this.lazyLoadHandler = debounce(this.lazyLoadHandler, this.throttle);
|
|
||||||
} else {
|
|
||||||
this.lazyLoadHandler = throttle(this.lazyLoadHandler, this.throttle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
watchEffect(() => {
|
|
||||||
if (!this.visible) {
|
|
||||||
this.lazyLoadHandler(this.$props);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const eventNode = this.getEventNode();
|
|
||||||
|
|
||||||
if (this.lazyLoadHandler.flush) {
|
|
||||||
this.lazyLoadHandler.flush();
|
|
||||||
}
|
|
||||||
this.resizeHander = addEventListener(window, 'resize', this.lazyLoadHandler);
|
|
||||||
this.scrollHander = addEventListener(eventNode, 'scroll', this.lazyLoadHandler);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
if (this.lazyLoadHandler.cancel) {
|
|
||||||
this.lazyLoadHandler.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.detachListeners();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getEventNode() {
|
|
||||||
return parentScroll(findDOMNode(this));
|
|
||||||
},
|
|
||||||
getOffset() {
|
|
||||||
const {
|
|
||||||
offset,
|
|
||||||
offsetVertical,
|
|
||||||
offsetHorizontal,
|
|
||||||
offsetTop,
|
|
||||||
offsetBottom,
|
|
||||||
offsetLeft,
|
|
||||||
offsetRight,
|
|
||||||
threshold,
|
|
||||||
} = this.$props;
|
|
||||||
|
|
||||||
const _offsetAll = threshold || offset;
|
|
||||||
const _offsetVertical = offsetVertical || _offsetAll;
|
|
||||||
const _offsetHorizontal = offsetHorizontal || _offsetAll;
|
|
||||||
|
|
||||||
return {
|
|
||||||
top: offsetTop || _offsetVertical,
|
|
||||||
bottom: offsetBottom || _offsetVertical,
|
|
||||||
left: offsetLeft || _offsetHorizontal,
|
|
||||||
right: offsetRight || _offsetHorizontal,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
lazyLoadHandler() {
|
|
||||||
if (!this._.isMounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const offset = this.getOffset();
|
|
||||||
const node = findDOMNode(this);
|
|
||||||
const eventNode = this.getEventNode();
|
|
||||||
|
|
||||||
if (inViewport(node, eventNode, offset)) {
|
|
||||||
this.setState({ visible: true }, () => {
|
|
||||||
this.__emit('contentVisible');
|
|
||||||
});
|
|
||||||
this.detachListeners();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
detachListeners() {
|
|
||||||
this.resizeHander && this.resizeHander.remove();
|
|
||||||
this.scrollHander && this.scrollHander.remove();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
const children = getSlot(this);
|
|
||||||
if (children.length !== 1) {
|
|
||||||
warning(false, 'lazyLoad组件只能包含一个子元素');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const { height, width, elementType: ElementType } = this.$props;
|
|
||||||
const { visible } = this;
|
|
||||||
const { class: className } = this.$attrs;
|
|
||||||
|
|
||||||
const elStyles = {
|
|
||||||
height: typeof height === 'number' ? height + 'px' : height,
|
|
||||||
width: typeof width === 'number' ? width + 'px' : width,
|
|
||||||
};
|
|
||||||
const elClasses = {
|
|
||||||
LazyLoad: true,
|
|
||||||
'is-visible': visible,
|
|
||||||
[className]: className,
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<ElementType class={elClasses} style={elStyles}>
|
|
||||||
{visible ? children[0] : null}
|
|
||||||
</ElementType>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,12 +0,0 @@
|
||||||
/*
|
|
||||||
* Finds element's position relative to the whole document,
|
|
||||||
* rather than to the viewport as it is the case with .getBoundingClientRect().
|
|
||||||
*/
|
|
||||||
export default function getElementPosition(element) {
|
|
||||||
const rect = element.getBoundingClientRect();
|
|
||||||
|
|
||||||
return {
|
|
||||||
top: rect.top + window.pageYOffset,
|
|
||||||
left: rect.left + window.pageXOffset,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
import getElementPosition from './getElementPosition';
|
|
||||||
|
|
||||||
const isHidden = element => element.offsetParent === null;
|
|
||||||
|
|
||||||
export default function inViewport(element, container, customOffset) {
|
|
||||||
if (isHidden(element)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let top;
|
|
||||||
let bottom;
|
|
||||||
let left;
|
|
||||||
let right;
|
|
||||||
|
|
||||||
if (typeof container === 'undefined' || container === window) {
|
|
||||||
top = window.pageYOffset;
|
|
||||||
left = window.pageXOffset;
|
|
||||||
bottom = top + window.innerHeight;
|
|
||||||
right = left + window.innerWidth;
|
|
||||||
} else {
|
|
||||||
const containerPosition = getElementPosition(container);
|
|
||||||
|
|
||||||
top = containerPosition.top;
|
|
||||||
left = containerPosition.left;
|
|
||||||
bottom = top + container.offsetHeight;
|
|
||||||
right = left + container.offsetWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
const elementPosition = getElementPosition(element);
|
|
||||||
|
|
||||||
return (
|
|
||||||
top <= elementPosition.top + element.offsetHeight + customOffset.top &&
|
|
||||||
bottom >= elementPosition.top - customOffset.bottom &&
|
|
||||||
left <= elementPosition.left + element.offsetWidth + customOffset.left &&
|
|
||||||
right >= elementPosition.left - customOffset.right
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
const style = (element, prop) => {
|
|
||||||
let styleVal = '';
|
|
||||||
if (typeof getComputedStyle !== 'undefined') {
|
|
||||||
styleVal = window.getComputedStyle(element, null).getPropertyValue(prop);
|
|
||||||
} else {
|
|
||||||
styleVal = element.style[prop];
|
|
||||||
}
|
|
||||||
return styleVal;
|
|
||||||
};
|
|
||||||
|
|
||||||
const overflow = element =>
|
|
||||||
style(element, 'overflow') + style(element, 'overflow-y') + style(element, 'overflow-x');
|
|
||||||
|
|
||||||
const scrollParent = element => {
|
|
||||||
if (!(element instanceof window.HTMLElement)) {
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent = element;
|
|
||||||
|
|
||||||
while (parent) {
|
|
||||||
if (parent === document.body || parent === document.documentElement) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parent.parentNode) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (/(scroll|auto)/.test(overflow(parent))) {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent = parent.parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default scrollParent;
|
|
|
@ -1,3 +0,0 @@
|
||||||
// based on 2.0.0
|
|
||||||
import TouchFeedback from './src/TouchFeedback';
|
|
||||||
export default TouchFeedback;
|
|
|
@ -1,13 +0,0 @@
|
||||||
import PropTypes from '../../_util/vue-types';
|
|
||||||
|
|
||||||
export const ITouchProps = {
|
|
||||||
disabled: PropTypes.looseBool,
|
|
||||||
activeClassName: PropTypes.string,
|
|
||||||
activeStyle: PropTypes.any,
|
|
||||||
// onTouchStart: PropTypes.func,
|
|
||||||
// onTouchEnd: PropTypes.func,
|
|
||||||
// onTouchCancel: PropTypes.func,
|
|
||||||
// onMouseDown: PropTypes.func,
|
|
||||||
// onMouseUp: PropTypes.func,
|
|
||||||
// onMouseLeave: PropTypes.func,
|
|
||||||
};
|
|
|
@ -1,109 +0,0 @@
|
||||||
import classNames from '../../_util/classNames';
|
|
||||||
import { initDefaultProps, getSlot } from '../../_util/props-util';
|
|
||||||
import { cloneElement } from '../../_util/vnode';
|
|
||||||
import warning from '../../_util/warning';
|
|
||||||
import BaseMixin from '../../_util/BaseMixin';
|
|
||||||
import { ITouchProps } from './PropTypes';
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import supportsPassive from '../../_util/supportsPassive';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'TouchFeedback',
|
|
||||||
mixins: [BaseMixin],
|
|
||||||
inheritAttrs: false,
|
|
||||||
props: initDefaultProps(ITouchProps, {
|
|
||||||
disabled: false,
|
|
||||||
}),
|
|
||||||
data() {
|
|
||||||
this.child = null;
|
|
||||||
return {
|
|
||||||
active: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.disabled && this.active) {
|
|
||||||
this.setState({
|
|
||||||
active: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
triggerEvent(type, isActive, ev) {
|
|
||||||
const eventType = `on${type}`;
|
|
||||||
const { child } = this;
|
|
||||||
|
|
||||||
if (child.props[eventType]) {
|
|
||||||
child.props[eventType](ev);
|
|
||||||
}
|
|
||||||
if (isActive !== this.active) {
|
|
||||||
this.setState({
|
|
||||||
active: isActive,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onTouchStart(e) {
|
|
||||||
this.triggerEvent('Touchstart', true, e);
|
|
||||||
},
|
|
||||||
onTouchMove(e) {
|
|
||||||
this.triggerEvent('Touchmove', false, e);
|
|
||||||
},
|
|
||||||
onTouchEnd(e) {
|
|
||||||
this.triggerEvent('Touchend', false, e);
|
|
||||||
},
|
|
||||||
onTouchCancel(e) {
|
|
||||||
this.triggerEvent('Touchcancel', false, e);
|
|
||||||
},
|
|
||||||
onMouseDown(e) {
|
|
||||||
// pc simulate mobile
|
|
||||||
this.triggerEvent('Mousedown', true, e);
|
|
||||||
},
|
|
||||||
onMouseUp(e) {
|
|
||||||
this.triggerEvent('Mouseup', false, e);
|
|
||||||
},
|
|
||||||
onMouseLeave(e) {
|
|
||||||
this.triggerEvent('Mouseleave', false, e);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
const { disabled, activeClassName = '', activeStyle = {} } = this.$props;
|
|
||||||
|
|
||||||
let child = getSlot(this);
|
|
||||||
if (child.length !== 1) {
|
|
||||||
warning(false, 'm-feedback组件只能包含一个子元素');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const events = disabled
|
|
||||||
? undefined
|
|
||||||
: {
|
|
||||||
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']: this.onTouchStart,
|
|
||||||
[supportsPassive ? 'onTouchmovePassive' : 'onTouchmove']: this.onTouchMove,
|
|
||||||
onTouchend: this.onTouchEnd,
|
|
||||||
onTouchcancel: this.onTouchCancel,
|
|
||||||
onMousedown: this.onMouseDown,
|
|
||||||
onMouseup: this.onMouseUp,
|
|
||||||
onMouseleave: this.onMouseLeave,
|
|
||||||
};
|
|
||||||
|
|
||||||
child = child[0];
|
|
||||||
this.child = child;
|
|
||||||
if (!disabled && this.active) {
|
|
||||||
let { style, class: className } = child.props;
|
|
||||||
|
|
||||||
if (activeStyle !== false) {
|
|
||||||
if (activeStyle) {
|
|
||||||
style = { ...style, ...activeStyle };
|
|
||||||
}
|
|
||||||
className = classNames(className, activeClassName);
|
|
||||||
}
|
|
||||||
return cloneElement(child, {
|
|
||||||
class: className,
|
|
||||||
style,
|
|
||||||
...events,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return cloneElement(child, events);
|
|
||||||
},
|
|
||||||
});
|
|
Loading…
Reference in New Issue