import { PropType, defineComponent, InjectionKey } from 'vue'; import { truthProp, createNamespace } from '../utils'; import { BORDER_TOP_BOTTOM } from '../utils/constant'; import { useChildren } from '@vant/use'; const [name, bem] = createNamespace('collapse'); export type CollapseProvide = { toggle: (name: number | string, expanded: boolean) => void; isExpanded: (name: number | string) => boolean; }; export const COLLAPSE_KEY: InjectionKey = Symbol(name); function validateModelValue( modelValue: string | number | Array, accordion: boolean ) { if (accordion && Array.isArray(modelValue)) { console.error( '[Vant] Collapse: "v-model" should not be Array in accordion mode' ); return false; } if (!accordion && !Array.isArray(modelValue)) { console.error( '[Vant] Collapse: "v-model" should be Array in non-accordion mode' ); return false; } return true; } export default defineComponent({ name, props: { border: truthProp, accordion: Boolean, modelValue: { type: [String, Number, Array] as PropType< string | number | Array >, default: '', }, }, emits: ['change', 'update:modelValue'], setup(props, { emit, slots }) { const { linkChildren } = useChildren(COLLAPSE_KEY); const updateName = (name: number | string | Array) => { emit('change', name); emit('update:modelValue', name); }; const toggle = (name: number | string, expanded: boolean) => { const { accordion, modelValue } = props; if (accordion) { updateName(name === modelValue ? '' : name); } else if (expanded) { updateName((modelValue as Array).concat(name)); } else { updateName( (modelValue as Array).filter( (activeName) => activeName !== name ) ); } }; const isExpanded = (name: number | string) => { const { accordion, modelValue } = props; if ( process.env.NODE_ENV !== 'production' && !validateModelValue(modelValue, accordion) ) { return false; } return accordion ? modelValue === name : (modelValue as Array).includes(name); }; linkChildren({ toggle, isExpanded }); return () => (
{slots.default?.()}
); }, });