rayine-ui/src/runtime/components/forms/Toggle.vue
2024-11-27 22:08:15 +08:00

101 lines
2.5 KiB
Vue

<script lang="ts">
import { computed, defineComponent, toRef, type PropType } from 'vue'
import { twJoin, twMerge } from 'tailwind-merge'
import { toggle } from '../../themes'
import type { DeepPartial, Strategy, ToggleColor, ToggleSize } from '../../types'
import { useRayUI } from '#build/imports'
const config = toggle
export default defineComponent({
props: {
modelValue: {
type: Boolean as PropType<boolean | null>,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
rounded: {
type: Boolean,
default: false,
},
size: {
type: String as PropType<ToggleSize>,
default: config.default.size,
},
color: {
type: String as PropType<ToggleColor>,
default: config.default.color,
},
class: {
type: String,
default: '',
},
ui: {
type: Object as PropType<DeepPartial<typeof config> & { strategy?: Strategy }>,
default: () => ({}),
},
},
emits: [
'update:modelValue',
'change',
],
setup(props, { emit }) {
const { ui, attrs } = useRayUI('toggle', toRef(props, 'ui'), config)
const checked = computed({
get: () => props.modelValue,
set: (value: boolean) => {
emit('update:modelValue', value)
emit('change', value)
},
})
const toggleClass = computed(() => {
return twMerge(twJoin(
ui.value.base,
props.rounded ? 'rounded-full' : ui.value.rounded,
ui.value.size[props.size],
ui.value.ring.replaceAll('{color}', props.color),
checked.value ? ui.value.active.replaceAll('{color}', props.color) : ui.value.inactive,
), props.class)
})
const bulletClass = computed(() => {
return twJoin(
ui.value.bullet.base,
props.rounded ? 'rounded-full' : ui.value.bullet.rounded,
ui.value.bullet.shadow,
ui.value.bullet.size[props.size],
!props.disabled && ui.value.bullet.translate[props.size],
checked.value ? ui.value.bullet.active[props.size] : ui.value.bullet.inactive,
)
})
const handleClick = () => {
if (!props.disabled) {
checked.value = !checked.value
}
}
return {
// eslint-disable-next-line vue/no-dupe-keys
ui,
attrs,
checked,
toggleClass,
bulletClass,
handleClick,
}
},
})
</script>
<template>
<button :class="toggleClass" :disabled="disabled" v-bind="attrs" @click="handleClick">
<span :class="bulletClass" />
</button>
</template>