vant/src/checkbox-group/CheckboxGroup.tsx

110 lines
2.5 KiB
TypeScript

import {
watch,
PropType,
InjectionKey,
defineComponent,
ExtractPropTypes,
ComponentPublicInstance,
} from 'vue';
// Utils
import { createNamespace } from '../utils';
// Composables
import { useChildren } from '@vant/use';
import { useExpose } from '../composables/use-expose';
import { useLinkField } from '../composables/use-link-field';
// Types
import { CheckerParent, CheckerDirection } from '../checkbox/Checker';
const [name, bem] = createNamespace('checkbox-group');
const props = {
max: [Number, String],
disabled: Boolean,
direction: String as PropType<CheckerDirection>,
iconSize: [Number, String],
checkedColor: String,
modelValue: {
type: Array as PropType<unknown[]>,
default: () => [],
},
};
export type CheckboxGroupToggleAllOptions =
| boolean
| {
checked?: boolean;
skipDisabled?: boolean;
};
type CheckboxGroupProps = ExtractPropTypes<typeof props>;
type CheckboxGroupExpose = {
toggleAll: (options?: CheckboxGroupToggleAllOptions) => void;
};
export type CheckboxGroupInstance = ComponentPublicInstance<
CheckboxGroupProps,
CheckboxGroupExpose
>;
export type CheckboxGroupProvide = CheckerParent & {
props: CheckboxGroupProps;
updateValue: (value: unknown[]) => void;
};
export const CHECKBOX_GROUP_KEY: InjectionKey<CheckboxGroupProvide> = Symbol(
name
);
export default defineComponent({
name,
props,
emits: ['change', 'update:modelValue'],
setup(props, { emit, slots }) {
const { children, linkChildren } = useChildren(CHECKBOX_GROUP_KEY);
const updateValue = (value: unknown[]) => emit('update:modelValue', value);
const toggleAll = (options: CheckboxGroupToggleAllOptions = {}) => {
if (typeof options === 'boolean') {
options = { checked: options };
}
const { checked, skipDisabled } = options;
const checkedChildren = children.filter((item: any) => {
if (!item.props.bindGroup) {
return false;
}
if (item.props.disabled && skipDisabled) {
return item.checked.value;
}
return checked ?? !item.checked.value;
});
const names = checkedChildren.map((item: any) => item.name);
updateValue(names);
};
watch(
() => props.modelValue,
(value) => emit('change', value)
);
useExpose<CheckboxGroupExpose>({ toggleAll });
useLinkField(() => props.modelValue);
linkChildren({
props,
updateValue,
});
return () => <div class={bem([props.direction])}>{slots.default?.()}</div>;
},
});