u
This commit is contained in:
1 parent
104e0a78c6
commit
4d0d2f875e
13 files changed
+802
-226
No files matched your search
@@ -0,0 +1,225 @@
|
||||
import type { PropType, VNode } from 'vue'
|
||||
import type { CheckboxGroupContext } from './context'
|
||||
import { computed, defineComponent, inject, ref, watch } from 'vue'
|
||||
import { getPrefixCls } from '../_utils/getPrefixCls'
|
||||
import Icon from '../icon/index'
|
||||
import { checkboxGroupKey } from './context'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Checkbox',
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: undefined,
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
||||
default: true,
|
||||
},
|
||||
indeterminate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
defaultChecked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<'default' | 'card' | 'pureCard'>,
|
||||
default: 'default',
|
||||
},
|
||||
extra: {
|
||||
type: [String, Object, Function] as unknown as () => string | VNode | (() => VNode),
|
||||
default: '',
|
||||
},
|
||||
class: {
|
||||
type: [String, Array, Object],
|
||||
default: '',
|
||||
},
|
||||
style: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'update:checked', 'change'],
|
||||
setup(props, { slots, emit }) {
|
||||
const prefixCls = getPrefixCls('checkbox')
|
||||
|
||||
const checkboxGroupCtx = inject<CheckboxGroupContext | undefined>(checkboxGroupKey, undefined)
|
||||
const inGroup = computed(() => !!checkboxGroupCtx)
|
||||
|
||||
const isDisabled = computed(() => props.disabled || checkboxGroupCtx?.disabled)
|
||||
const _checked = ref(props.defaultChecked)
|
||||
|
||||
const mergedType = computed(() =>
|
||||
props.type || checkboxGroupCtx?.type || 'default',
|
||||
)
|
||||
|
||||
const isChecked = computed(() => {
|
||||
if (inGroup.value && checkboxGroupCtx) {
|
||||
const groupValue = checkboxGroupCtx.value
|
||||
if (Array.isArray(groupValue)) {
|
||||
return groupValue.includes(props.value)
|
||||
}
|
||||
return groupValue === props.value
|
||||
}
|
||||
return props.checked ?? props.modelValue ?? _checked.value
|
||||
})
|
||||
|
||||
const handleClick = (event: Event) => {
|
||||
if (isDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (inGroup.value && checkboxGroupCtx) {
|
||||
checkboxGroupCtx.handleChange(props.value, event)
|
||||
}
|
||||
else {
|
||||
const newChecked = !isChecked.value
|
||||
if (props.checked === undefined)
|
||||
_checked.value = newChecked
|
||||
|
||||
emit('update:modelValue', newChecked)
|
||||
emit('update:checked', newChecked)
|
||||
}
|
||||
emit('change', { value: props.value, event })
|
||||
}
|
||||
|
||||
watch(() => props.checked, (val) => {
|
||||
if (val !== undefined) {
|
||||
_checked.value = val
|
||||
}
|
||||
})
|
||||
|
||||
const renderDefault = () => (
|
||||
<label
|
||||
class={[
|
||||
`${prefixCls}-default`,
|
||||
{ [`${prefixCls}-checked`]: isChecked.value },
|
||||
{ [`${prefixCls}-disabled`]: isDisabled.value },
|
||||
props.class,
|
||||
]}
|
||||
style={{ ...props.style }}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span class={`${prefixCls}-main`}>
|
||||
<input
|
||||
class={`${prefixCls}-input`}
|
||||
type="checkbox"
|
||||
onClick={e => e.stopPropagation()}
|
||||
/>
|
||||
<span class={`${prefixCls}-inner`}>
|
||||
{
|
||||
props.indeterminate
|
||||
? (
|
||||
<Icon icon="garden:dash-fill-12" />
|
||||
)
|
||||
: isChecked.value
|
||||
? (
|
||||
<Icon icon="garden:check-sm-fill-12" />
|
||||
)
|
||||
: null
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
<div class={`${prefixCls}-content`}>
|
||||
<div class={`${prefixCls}-label`}>
|
||||
{slots.default?.()}
|
||||
</div>
|
||||
{props.extra && (
|
||||
<div class={`${prefixCls}-extra`}>
|
||||
{typeof props.extra === 'function' ? props.extra() : props.extra}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</label>
|
||||
)
|
||||
|
||||
const renderCard = () => (
|
||||
<label
|
||||
class={[
|
||||
`${prefixCls}-card`,
|
||||
{ [`${prefixCls}-checked`]: isChecked.value },
|
||||
{ [`${prefixCls}-disabled`]: isDisabled.value },
|
||||
props.class,
|
||||
]}
|
||||
style={{ ...props.style }}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span class={`${prefixCls}-main`}>
|
||||
<input
|
||||
class={`${prefixCls}-input`}
|
||||
type="checkbox"
|
||||
onClick={e => e.stopPropagation()}
|
||||
/>
|
||||
<span class={`${prefixCls}-inner`}>
|
||||
{
|
||||
props.indeterminate
|
||||
? (
|
||||
<Icon icon="garden:dash-fill-12" />
|
||||
)
|
||||
: isChecked.value
|
||||
? (
|
||||
<Icon icon="garden:check-sm-fill-12" />
|
||||
)
|
||||
: null
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
<div class={`${prefixCls}-content`}>
|
||||
<div class={`${prefixCls}-label`}>
|
||||
{slots.default?.()}
|
||||
</div>
|
||||
{props.extra && (
|
||||
<div class={`${prefixCls}-extra`}>
|
||||
{typeof props.extra === 'function' ? props.extra() : props.extra}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</label>
|
||||
)
|
||||
|
||||
const renderPureCard = () => (
|
||||
<label
|
||||
class={[
|
||||
`${prefixCls}-pureCard`,
|
||||
{ [`${prefixCls}-checked`]: isChecked.value },
|
||||
{ [`${prefixCls}-disabled`]: isDisabled.value },
|
||||
props.class,
|
||||
]}
|
||||
style={{ ...props.style }}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div class={`${prefixCls}-content`}>
|
||||
<div class={`${prefixCls}-label`}>
|
||||
{slots.default?.()}
|
||||
</div>
|
||||
{props.extra && (
|
||||
<div class={`${prefixCls}-extra`}>
|
||||
{typeof props.extra === 'function' ? props.extra() : props.extra}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</label>
|
||||
)
|
||||
|
||||
return () => {
|
||||
switch (mergedType.value) {
|
||||
case 'card':
|
||||
return renderCard()
|
||||
case 'pureCard':
|
||||
return renderPureCard()
|
||||
default:
|
||||
return renderDefault()
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
Reference in new issue
Block a user