ketekny-ui-kit 1.0.40 → 1.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +2 -1
- package/package.json +1 -1
- package/src/ui/kDateSelector_v2.vue +1 -1
- package/src/ui/kDrawer.vue +62 -36
- package/src/ui/kToggle_v2.vue +77 -0
- package/src/ui/kToggle_v3.vue +132 -0
- package/src/ui/kToggle_v4.vue +122 -0
package/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import kDialog from './src/ui/kDialog.vue'
|
|
|
7
7
|
import kDrawer from './src/ui/kDrawer.vue'
|
|
8
8
|
import kInput from './src/ui/kInput.vue'
|
|
9
9
|
import kDateSelector from './src/ui/kDateSelector.vue'
|
|
10
|
+
import kDateSelectorV2 from './src/ui/kDateSelector_v2.vue'
|
|
10
11
|
import kToolbar from './src/ui/kToolbar.vue'
|
|
11
12
|
import kSelect from './src/ui/kSelect.vue'
|
|
12
13
|
import kTable from './src/ui/kTable.vue'
|
|
@@ -50,7 +51,7 @@ export {
|
|
|
50
51
|
kMessage, kCode, kToolbar, kTable, kTabs, kChip, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar, kTree,
|
|
51
52
|
|
|
52
53
|
// Form Components
|
|
53
|
-
kButton, kSelect, kUploader, kToggle, kInput, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList, kList, kTextArea,
|
|
54
|
+
kButton, kSelect, kUploader, kToggle, kInput, kDateSelector, kDateSelectorV2, kEditor, kSelectButton, kTags, kSearch, kArrayList, kList, kTextArea,
|
|
54
55
|
|
|
55
56
|
// Dialogs
|
|
56
57
|
kDialog, kDrawer,
|
package/package.json
CHANGED
|
@@ -34,7 +34,7 @@ import { ElDatePicker } from 'element-plus'
|
|
|
34
34
|
const props = defineProps({
|
|
35
35
|
modelValue: { type: [String, Date, Array], default: null },
|
|
36
36
|
id: {
|
|
37
|
-
type: String,
|
|
37
|
+
type: [String, Array],
|
|
38
38
|
default: () => `datepicker-${Math.random().toString(36).slice(2, 11)}`,
|
|
39
39
|
},
|
|
40
40
|
label: { type: String, default: '' },
|
package/src/ui/kDrawer.vue
CHANGED
|
@@ -1,41 +1,50 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<div class="
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
<div
|
|
3
|
+
v-if="visible"
|
|
4
|
+
class="fixed inset-0 z-50 flex overflow-hidden bg-black/50 backdrop-blur-sm"
|
|
5
|
+
:class="side === 'right' ? 'justify-end' : 'justify-start'"
|
|
6
|
+
@click.self="close"
|
|
7
|
+
>
|
|
8
|
+
<transition :name="side === 'right' ? 'drawer-right' : 'drawer-left'">
|
|
9
|
+
<div
|
|
10
|
+
class="relative m-2 flex h-[calc(100dvh-1rem)] w-[calc(100vw-1rem)] max-w-[calc(100vw-1rem)] flex-col overflow-hidden rounded-2xl bg-white shadow-lg dark:bg-zinc-900 sm:m-4 sm:h-[calc(100vh-2rem)] sm:w-[400px]"
|
|
11
|
+
role="dialog"
|
|
12
|
+
aria-modal="true"
|
|
13
|
+
@click.stop
|
|
14
|
+
>
|
|
15
|
+
<div class="flex flex-row items-center border-b border-primary/20 bg-primary/5 px-4 py-3 dark:bg-primary/10">
|
|
16
|
+
<div class="text-sm font-semibold text-primary sm:text-base">{{ title }}</div>
|
|
17
|
+
<div class="flex-1" />
|
|
18
|
+
<button
|
|
19
|
+
type="button"
|
|
20
|
+
class="cursor-pointer rounded-md p-1.5 text-zinc-400 transition-colors hover:bg-primary/10 hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 dark:text-zinc-500 dark:hover:text-primary"
|
|
21
|
+
aria-label="Close drawer"
|
|
22
|
+
@click="close"
|
|
23
|
+
>
|
|
24
|
+
<X class="w-5 h-5" />
|
|
25
|
+
</button>
|
|
26
|
+
</div>
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</div>
|
|
28
|
+
<div class="flex-1 overflow-auto p-3 sm:p-4">
|
|
29
|
+
<slot></slot>
|
|
30
|
+
</div>
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
<div
|
|
33
|
+
v-if="$slots.footer"
|
|
34
|
+
class="flex flex-col-reverse gap-2 border-t border-zinc-200 p-3 dark:border-zinc-800 sm:flex-row sm:justify-end sm:p-4"
|
|
35
|
+
>
|
|
36
|
+
<slot name="footer"></slot>
|
|
37
|
+
</div>
|
|
29
38
|
</div>
|
|
30
|
-
</
|
|
39
|
+
</transition>
|
|
31
40
|
</div>
|
|
32
41
|
</template>
|
|
33
42
|
|
|
34
43
|
<script>
|
|
35
|
-
import { X } from
|
|
44
|
+
import { X } from 'lucide-vue-next'
|
|
36
45
|
|
|
37
46
|
export default {
|
|
38
|
-
name:
|
|
47
|
+
name: 'KDrawer',
|
|
39
48
|
components: {
|
|
40
49
|
X,
|
|
41
50
|
},
|
|
@@ -46,28 +55,45 @@ export default {
|
|
|
46
55
|
},
|
|
47
56
|
title: {
|
|
48
57
|
type: String,
|
|
49
|
-
default:
|
|
58
|
+
default: '',
|
|
50
59
|
},
|
|
51
60
|
side: {
|
|
52
61
|
type: String,
|
|
53
|
-
default:
|
|
54
|
-
validator: (val) => [
|
|
62
|
+
default: 'right', // "left" or "right"
|
|
63
|
+
validator: (val) => ['left', 'right'].includes(val),
|
|
55
64
|
},
|
|
56
65
|
},
|
|
57
66
|
watch: {
|
|
58
67
|
visible(val) {
|
|
59
|
-
document.body.style.overflow = val ?
|
|
68
|
+
document.body.style.overflow = val ? 'hidden' : ''
|
|
60
69
|
},
|
|
61
70
|
},
|
|
62
71
|
beforeUnmount() {
|
|
63
|
-
document.body.style.overflow =
|
|
72
|
+
document.body.style.overflow = ''
|
|
64
73
|
},
|
|
65
74
|
methods: {
|
|
66
75
|
close() {
|
|
67
|
-
this.$emit(
|
|
76
|
+
this.$emit('update:visible', false)
|
|
68
77
|
},
|
|
69
78
|
},
|
|
70
|
-
}
|
|
79
|
+
}
|
|
71
80
|
</script>
|
|
72
81
|
|
|
73
|
-
<style scoped
|
|
82
|
+
<style scoped>
|
|
83
|
+
.drawer-right-enter-active,
|
|
84
|
+
.drawer-right-leave-active,
|
|
85
|
+
.drawer-left-enter-active,
|
|
86
|
+
.drawer-left-leave-active {
|
|
87
|
+
transition: transform 0.25s ease;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.drawer-right-enter-from,
|
|
91
|
+
.drawer-right-leave-to {
|
|
92
|
+
transform: translateX(100%);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.drawer-left-enter-from,
|
|
96
|
+
.drawer-left-leave-to {
|
|
97
|
+
transform: translateX(-100%);
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="labelStyle === 'inline' ? 'flex items-center gap-2' : ''">
|
|
3
|
+
<div
|
|
4
|
+
v-if="showLabel && labelStyle !== 'inline'"
|
|
5
|
+
:class="[
|
|
6
|
+
'block mb-1 text-sm font-bold',
|
|
7
|
+
disabled ? 'text-slate-500' : 'text-primary/90',
|
|
8
|
+
]"
|
|
9
|
+
>
|
|
10
|
+
{{ label }}
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<el-switch
|
|
14
|
+
:model-value="resolvedValue"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
:active-text="activeText"
|
|
17
|
+
:inactive-text="inactiveText"
|
|
18
|
+
:active-color="activeColor"
|
|
19
|
+
:inactive-color="inactiveColor"
|
|
20
|
+
:size="size"
|
|
21
|
+
:width="width"
|
|
22
|
+
:inline-prompt="inlinePrompt"
|
|
23
|
+
@update:model-value="emitModelUpdate"
|
|
24
|
+
@change="$emit('change', $event)"
|
|
25
|
+
/>
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
v-if="showLabel && labelStyle === 'inline'"
|
|
29
|
+
:class="[
|
|
30
|
+
'text-sm font-bold cursor-pointer',
|
|
31
|
+
disabled ? 'text-slate-500 cursor-not-allowed' : 'text-primary/90',
|
|
32
|
+
]"
|
|
33
|
+
@click="!disabled && emitModelUpdate(!resolvedValue)"
|
|
34
|
+
>
|
|
35
|
+
{{ label }}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<script setup>
|
|
41
|
+
import { computed, getCurrentInstance } from 'vue'
|
|
42
|
+
import { ElSwitch } from 'element-plus'
|
|
43
|
+
|
|
44
|
+
const props = defineProps({
|
|
45
|
+
modelValue: { type: Boolean, default: false },
|
|
46
|
+
value: { type: Boolean, default: undefined },
|
|
47
|
+
label: { type: String, default: '' },
|
|
48
|
+
labelStyle: { type: String, default: null },
|
|
49
|
+
disabled: { type: Boolean, default: false },
|
|
50
|
+
size: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: 'default',
|
|
53
|
+
validator: (val) => ['large', 'default', 'small'].includes(val),
|
|
54
|
+
},
|
|
55
|
+
width: { type: [String, Number], default: undefined },
|
|
56
|
+
activeText: { type: String, default: '' },
|
|
57
|
+
inactiveText: { type: String, default: '' },
|
|
58
|
+
activeColor: { type: String, default: '' },
|
|
59
|
+
inactiveColor: { type: String, default: '' },
|
|
60
|
+
inlinePrompt: { type: Boolean, default: false },
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const emit = defineEmits(['update:modelValue', 'update:value', 'change'])
|
|
64
|
+
|
|
65
|
+
const instance = getCurrentInstance()
|
|
66
|
+
const passedProps = new Set(Object.keys(instance?.vnode.props || {}))
|
|
67
|
+
const hasProp = (...names) => names.some((name) => passedProps.has(name))
|
|
68
|
+
|
|
69
|
+
const resolvedValue = computed(() => (hasProp('value') ? props.value : props.modelValue))
|
|
70
|
+
|
|
71
|
+
const showLabel = computed(() => !!props.label && props.label.trim() !== '')
|
|
72
|
+
|
|
73
|
+
function emitModelUpdate(val) {
|
|
74
|
+
emit('update:modelValue', val)
|
|
75
|
+
emit('update:value', val)
|
|
76
|
+
}
|
|
77
|
+
</script>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="labelStyle === 'inline' ? 'flex items-center gap-2' : ''">
|
|
3
|
+
<div
|
|
4
|
+
v-if="showLabel && labelStyle !== 'inline'"
|
|
5
|
+
:class="[
|
|
6
|
+
'block mb-1 text-sm font-bold',
|
|
7
|
+
disabled ? 'text-slate-500' : 'text-primary/90',
|
|
8
|
+
]"
|
|
9
|
+
>
|
|
10
|
+
{{ label }}
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<SwitchRoot
|
|
14
|
+
:checked="resolvedValue"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
class="k-toggle-v3-track"
|
|
17
|
+
:data-state="resolvedValue ? 'checked' : 'unchecked'"
|
|
18
|
+
@update:checked="emitModelUpdate"
|
|
19
|
+
>
|
|
20
|
+
<SwitchThumb class="k-toggle-v3-thumb" />
|
|
21
|
+
</SwitchRoot>
|
|
22
|
+
|
|
23
|
+
<div
|
|
24
|
+
v-if="showLabel && labelStyle === 'inline'"
|
|
25
|
+
:class="[
|
|
26
|
+
'text-sm font-bold cursor-pointer',
|
|
27
|
+
disabled ? 'text-slate-500 cursor-not-allowed' : 'text-primary/90',
|
|
28
|
+
]"
|
|
29
|
+
@click="!disabled && emitModelUpdate(!resolvedValue)"
|
|
30
|
+
>
|
|
31
|
+
{{ label }}
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup>
|
|
37
|
+
import { computed, getCurrentInstance } from 'vue'
|
|
38
|
+
import { SwitchRoot, SwitchThumb } from 'reka-ui'
|
|
39
|
+
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
modelValue: { type: Boolean, default: false },
|
|
42
|
+
value: { type: Boolean, default: undefined },
|
|
43
|
+
label: { type: String, default: '' },
|
|
44
|
+
labelStyle: { type: String, default: null },
|
|
45
|
+
disabled: { type: Boolean, default: false },
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const emit = defineEmits(['update:modelValue', 'update:value'])
|
|
49
|
+
|
|
50
|
+
const instance = getCurrentInstance()
|
|
51
|
+
const passedProps = new Set(Object.keys(instance?.vnode.props || {}))
|
|
52
|
+
const hasProp = (...names) => names.some((name) => passedProps.has(name))
|
|
53
|
+
|
|
54
|
+
const resolvedValue = computed(() => (hasProp('value') ? props.value : props.modelValue))
|
|
55
|
+
|
|
56
|
+
const showLabel = computed(() => !!props.label && props.label.trim() !== '')
|
|
57
|
+
|
|
58
|
+
function emitModelUpdate(val) {
|
|
59
|
+
emit('update:modelValue', val)
|
|
60
|
+
emit('update:value', val)
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<style scoped>
|
|
65
|
+
.k-toggle-v3-track {
|
|
66
|
+
position: relative;
|
|
67
|
+
display: inline-flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
width: 3rem;
|
|
70
|
+
height: 1.75rem;
|
|
71
|
+
padding: 0.15rem;
|
|
72
|
+
border-radius: 9999px;
|
|
73
|
+
border: none;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
flex-shrink: 0;
|
|
76
|
+
background: #94a3b8;
|
|
77
|
+
transition: background-color 0.25s ease, box-shadow 0.25s ease;
|
|
78
|
+
outline: none;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.k-toggle-v3-track:focus-visible {
|
|
82
|
+
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #10b981;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.k-toggle-v3-track[data-state='checked'] {
|
|
86
|
+
background: #10b981;
|
|
87
|
+
box-shadow: 0 0 12px rgba(16, 185, 129, 0.35);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.k-toggle-v3-track[data-state='unchecked'] {
|
|
91
|
+
background: #94a3b8;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.k-toggle-v3-track[data-disabled] {
|
|
95
|
+
cursor: not-allowed;
|
|
96
|
+
opacity: 0.45;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.k-toggle-v3-thumb {
|
|
100
|
+
display: block;
|
|
101
|
+
width: 1.35rem;
|
|
102
|
+
height: 1.35rem;
|
|
103
|
+
border-radius: 9999px;
|
|
104
|
+
background: #fff;
|
|
105
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.04);
|
|
106
|
+
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
|
107
|
+
pointer-events: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.k-toggle-v3-track[data-state='checked'] .k-toggle-v3-thumb {
|
|
111
|
+
transform: translateX(1.25rem);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.k-toggle-v3-track[data-state='unchecked'] .k-toggle-v3-thumb {
|
|
115
|
+
transform: translateX(0);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* Dark mode */
|
|
119
|
+
:global(html.dark) .k-toggle-v3-track[data-state='unchecked'] {
|
|
120
|
+
background: #475569;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
:global(html.dark) .k-toggle-v3-track[data-state='checked'] {
|
|
124
|
+
background: #059669;
|
|
125
|
+
box-shadow: 0 0 14px rgba(5, 150, 105, 0.4);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
:global(html.dark) .k-toggle-v3-thumb {
|
|
129
|
+
background: #f1f5f9;
|
|
130
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="labelStyle === 'inline' ? 'flex items-center gap-2' : ''">
|
|
3
|
+
<div
|
|
4
|
+
v-if="showLabel && labelStyle !== 'inline'"
|
|
5
|
+
:class="[
|
|
6
|
+
'block mb-1 text-sm font-bold',
|
|
7
|
+
disabled ? 'text-slate-500' : 'text-primary/90',
|
|
8
|
+
]"
|
|
9
|
+
>
|
|
10
|
+
{{ label }}
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<button
|
|
14
|
+
type="button"
|
|
15
|
+
role="switch"
|
|
16
|
+
:aria-checked="resolvedValue"
|
|
17
|
+
:aria-label="label || 'Toggle'"
|
|
18
|
+
:disabled="disabled"
|
|
19
|
+
:class="cn(toggleVariants({ state: resolvedValue ? 'checked' : 'unchecked', size }), $attrs.class)"
|
|
20
|
+
@click="!disabled && emitModelUpdate(!resolvedValue)"
|
|
21
|
+
>
|
|
22
|
+
<span
|
|
23
|
+
:class="cn(thumbVariants({ state: resolvedValue ? 'checked' : 'unchecked', size }))"
|
|
24
|
+
/>
|
|
25
|
+
</button>
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
v-if="showLabel && labelStyle === 'inline'"
|
|
29
|
+
:class="[
|
|
30
|
+
'text-sm font-bold cursor-pointer',
|
|
31
|
+
disabled ? 'text-slate-500 cursor-not-allowed' : 'text-primary/90',
|
|
32
|
+
]"
|
|
33
|
+
@click="!disabled && emitModelUpdate(!resolvedValue)"
|
|
34
|
+
>
|
|
35
|
+
{{ label }}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<script setup>
|
|
41
|
+
import { computed, getCurrentInstance } from 'vue'
|
|
42
|
+
import { cva } from 'class-variance-authority'
|
|
43
|
+
import { cn } from '../lib/utils'
|
|
44
|
+
|
|
45
|
+
const toggleVariants = cva(
|
|
46
|
+
'peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-slate-300 dark:focus-visible:ring-offset-slate-950 disabled:cursor-not-allowed disabled:opacity-50',
|
|
47
|
+
{
|
|
48
|
+
variants: {
|
|
49
|
+
state: {
|
|
50
|
+
checked: 'bg-slate-900 dark:bg-slate-50',
|
|
51
|
+
unchecked: 'bg-slate-200 dark:bg-slate-800',
|
|
52
|
+
},
|
|
53
|
+
size: {
|
|
54
|
+
sm: 'h-4 w-7',
|
|
55
|
+
default: 'h-5 w-9',
|
|
56
|
+
lg: 'h-6 w-11',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
defaultVariants: {
|
|
60
|
+
state: 'unchecked',
|
|
61
|
+
size: 'default',
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
const thumbVariants = cva(
|
|
67
|
+
'pointer-events-none block rounded-full bg-white shadow-sm ring-0 transition-transform duration-200 dark:bg-slate-950',
|
|
68
|
+
{
|
|
69
|
+
variants: {
|
|
70
|
+
state: {
|
|
71
|
+
checked: '',
|
|
72
|
+
unchecked: '',
|
|
73
|
+
},
|
|
74
|
+
size: {
|
|
75
|
+
sm: 'h-3 w-3',
|
|
76
|
+
default: 'h-4 w-4',
|
|
77
|
+
lg: 'h-5 w-5',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
compoundVariants: [
|
|
81
|
+
{ state: 'checked', size: 'sm', class: 'translate-x-3' },
|
|
82
|
+
{ state: 'unchecked', size: 'sm', class: 'translate-x-0.5' },
|
|
83
|
+
{ state: 'checked', size: 'default', class: 'translate-x-4' },
|
|
84
|
+
{ state: 'unchecked', size: 'default', class: 'translate-x-0.5' },
|
|
85
|
+
{ state: 'checked', size: 'lg', class: 'translate-x-5' },
|
|
86
|
+
{ state: 'unchecked', size: 'lg', class: 'translate-x-0.5' },
|
|
87
|
+
],
|
|
88
|
+
defaultVariants: {
|
|
89
|
+
state: 'unchecked',
|
|
90
|
+
size: 'default',
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const props = defineProps({
|
|
96
|
+
modelValue: { type: Boolean, default: false },
|
|
97
|
+
value: { type: Boolean, default: undefined },
|
|
98
|
+
label: { type: String, default: '' },
|
|
99
|
+
labelStyle: { type: String, default: null },
|
|
100
|
+
disabled: { type: Boolean, default: false },
|
|
101
|
+
size: {
|
|
102
|
+
type: String,
|
|
103
|
+
default: 'default',
|
|
104
|
+
validator: (val) => ['sm', 'default', 'lg'].includes(val),
|
|
105
|
+
},
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
const emit = defineEmits(['update:modelValue', 'update:value'])
|
|
109
|
+
|
|
110
|
+
const instance = getCurrentInstance()
|
|
111
|
+
const passedProps = new Set(Object.keys(instance?.vnode.props || {}))
|
|
112
|
+
const hasProp = (...names) => names.some((name) => passedProps.has(name))
|
|
113
|
+
|
|
114
|
+
const resolvedValue = computed(() => (hasProp('value') ? props.value : props.modelValue))
|
|
115
|
+
|
|
116
|
+
const showLabel = computed(() => !!props.label && props.label.trim() !== '')
|
|
117
|
+
|
|
118
|
+
function emitModelUpdate(val) {
|
|
119
|
+
emit('update:modelValue', val)
|
|
120
|
+
emit('update:value', val)
|
|
121
|
+
}
|
|
122
|
+
</script>
|