|
| 1 | +<template> |
| 2 | + <div |
| 3 | + class="mv-flex mv-gap-0.5 mv-cursor-pointer mv-items-center" |
| 4 | + @click.stop="handleClick" |
| 5 | + > |
| 6 | + <div class="mv-w-12 mv-h-12 mv-relative"> |
| 7 | + <div class="mv-absolute mv-inset-1 mv-rounded-full mv-overflow-hidden"> |
| 8 | + <MStateLayer |
| 9 | + classes="mv-rounded-full" |
| 10 | + :background="stateBackground" |
| 11 | + :ripple-background="rippleBackground" |
| 12 | + @click="handleClick" |
| 13 | + /> |
| 14 | + </div> |
| 15 | + <span |
| 16 | + class="material-symbols-rounded mv-m-3 mv-z-10 mv-pointer-events-none mv-absolute mv-w-6 mv-h-6" |
| 17 | + :class="iconClasses" |
| 18 | + v-text="isSelected ? 'check_box' : 'check_box_outline_blank'" |
| 19 | + /> |
| 20 | + </div> |
| 21 | + <p |
| 22 | + v-if="text" |
| 23 | + class="body-large mv-lowercase first-letter:mv-uppercase mv-text-[--md-sys-color-on-surface]" |
| 24 | + v-text="text" |
| 25 | + /> |
| 26 | + </div> |
| 27 | +</template> |
| 28 | + |
| 29 | +<script setup> |
| 30 | +import { computed, ref } from 'vue' |
| 31 | +import { useLocalModel } from '../../composables/useLocalModel.js' |
| 32 | +import MStateLayer from '../MStateLayer.vue' |
| 33 | +
|
| 34 | +const props = defineProps({ |
| 35 | + modelValue: { |
| 36 | + type: [Boolean, Array], |
| 37 | + default: false, |
| 38 | + }, |
| 39 | + value: { |
| 40 | + required: true, |
| 41 | + }, |
| 42 | + text: { |
| 43 | + type: String, |
| 44 | + default: null, |
| 45 | + }, |
| 46 | +}) |
| 47 | +
|
| 48 | +const localModal = ref() |
| 49 | +useLocalModel(props.modelValue, localModal) |
| 50 | +
|
| 51 | +const isSelected = computed(() => { |
| 52 | + if (typeof localModal.value === 'boolean') return localModal.value === true |
| 53 | + return localModal.value.includes(props.value) |
| 54 | +}) |
| 55 | +
|
| 56 | +const iconClasses = computed(() => { |
| 57 | + return isSelected.value |
| 58 | + ? 'mv-text-[--md-sys-color-primary] filled-icon' |
| 59 | + : 'mv-text-[--md-sys-color-on-surface-variant]' |
| 60 | +}) |
| 61 | +
|
| 62 | +const rippleBackground = computed(() => { |
| 63 | + return isSelected.value |
| 64 | + ? 'var(--md-sys-color-on-surface)' |
| 65 | + : 'var(--md-sys-color-primary)' |
| 66 | +}) |
| 67 | +
|
| 68 | +const stateBackground = computed(() => { |
| 69 | + return isSelected.value |
| 70 | + ? 'background: var(--md-sys-color-primary)' |
| 71 | + : 'background: var(--md-sys-color-on-surface)' |
| 72 | +}) |
| 73 | +
|
| 74 | +const emits = defineEmits(['update:modelValue', 'click']) |
| 75 | +
|
| 76 | +function handleClick() { |
| 77 | + if (typeof localModal.value === 'boolean') { |
| 78 | + localModal.value = !localModal.value |
| 79 | + } else { |
| 80 | + if (isSelected.value) |
| 81 | + localModal.value.splice(localModal.value.indexOf(props.value), 1) |
| 82 | + else localModal.value.push(props.value) |
| 83 | + } |
| 84 | + emits('update:modelValue', localModal.value) |
| 85 | + emits('click') |
| 86 | +} |
| 87 | +</script> |
| 88 | + |
| 89 | +<script> |
| 90 | +export default { |
| 91 | + name: 'MCheckbox', |
| 92 | +} |
| 93 | +</script> |
0 commit comments