@a-vision-software/vue-input-components 1.3.19 → 1.3.21
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/README.md +31 -120
- package/dist/src/components/Checkbox.vue.d.ts +92 -0
- package/dist/src/components/Dropdown.vue.d.ts +3 -3
- package/dist/src/components/TextInput.vue.d.ts +2 -2
- package/dist/src/index.d.ts +2 -1
- package/dist/src/types/checkbox.d.ts +30 -0
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/textinput.d.ts +7 -7
- package/dist/vue-input-components.cjs.js +1 -1
- package/dist/vue-input-components.css +1 -1
- package/dist/vue-input-components.es.js +3814 -3660
- package/dist/vue-input-components.umd.js +1 -1
- package/package.json +1 -1
- package/src/components/Checkbox.vue +337 -0
- package/src/components/TextInput.vue +1 -1
- package/src/index.ts +2 -1
- package/src/router/index.ts +7 -0
- package/src/types/checkbox.ts +31 -0
- package/src/types/index.ts +1 -0
- package/src/types/textinput.ts +7 -7
- package/src/views/CheckboxTestView.vue +209 -0
- package/src/views/DashboardView.vue +99 -79
package/package.json
CHANGED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="checkbox" :class="{
|
|
3
|
+
'checkbox--disabled': disabled,
|
|
4
|
+
'checkbox--has-error': error,
|
|
5
|
+
'checkbox--large-icon': iconSize === 'large',
|
|
6
|
+
[`label-${labelPosition}`]: label,
|
|
7
|
+
[`label-align-${labelAlign}`]: label,
|
|
8
|
+
[`checkbox--${presentation}`]: presentation,
|
|
9
|
+
}" :style="[
|
|
10
|
+
{ width: width || '100%' },
|
|
11
|
+
labelStyle,
|
|
12
|
+
{
|
|
13
|
+
'--checkbox-color': error ? 'var(--danger-color)' : color,
|
|
14
|
+
'--checkbox-hover-color': hoverColor ? hoverColor : 'var(--checkbox-color)',
|
|
15
|
+
'--checkbox-active-color': activeColor ? activeColor : 'var(--checkbox-color)',
|
|
16
|
+
'--checkbox-disabled-color': disabledColor,
|
|
17
|
+
'--checkbox-background-color': backgroundColor,
|
|
18
|
+
'--checkbox-border-radius': borderRadius,
|
|
19
|
+
'--checkbox-padding': padding,
|
|
20
|
+
}
|
|
21
|
+
]">
|
|
22
|
+
<label v-if="label" :for="id" class="label">
|
|
23
|
+
{{ label }}
|
|
24
|
+
</label>
|
|
25
|
+
<div class="checkbox__options" :style="{
|
|
26
|
+
'grid-template-columns': `repeat(${columns || 1}, 1fr)`,
|
|
27
|
+
'gap': presentation === 'minimal' ? '0' : '0.5rem'
|
|
28
|
+
}">
|
|
29
|
+
<div v-for="option in options" :key="option.id" class="checkbox__option" :class="{
|
|
30
|
+
'checkbox__option--disabled': option.disabled || disabled,
|
|
31
|
+
'checkbox__option--selected': isSelected(option),
|
|
32
|
+
'checkbox__option--round': !multiple && options.length > 1
|
|
33
|
+
}" @click="() => toggleOption(option)">
|
|
34
|
+
<div class="checkbox__icon">
|
|
35
|
+
<font-awesome-icon v-if="isSelected(option)" :icon="multiple ? 'square-check' : 'circle-check'" />
|
|
36
|
+
<font-awesome-icon v-else :icon="multiple ? 'square' : 'circle'" />
|
|
37
|
+
</div>
|
|
38
|
+
<div class="checkbox__label">{{ option.label }}</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<span v-if="required && !showSaved && !showChanged && !error"
|
|
42
|
+
class="status-indicator required-indicator">required</span>
|
|
43
|
+
<transition name="fade">
|
|
44
|
+
<span v-if="showSaved && !error" class="status-indicator saved-indicator">saved</span>
|
|
45
|
+
</transition>
|
|
46
|
+
<transition name="fade">
|
|
47
|
+
<span v-if="showChanged && !error" class="status-indicator changed-indicator">changed</span>
|
|
48
|
+
</transition>
|
|
49
|
+
<transition name="fade">
|
|
50
|
+
<span v-if="error" class="status-indicator error-indicator" :data-error="error">error</span>
|
|
51
|
+
</transition>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script setup lang="ts">
|
|
56
|
+
import { ref, computed, onMounted } from 'vue'
|
|
57
|
+
import type { CheckboxProps, CheckboxOption } from '../types/checkbox'
|
|
58
|
+
|
|
59
|
+
const props = withDefaults(defineProps<CheckboxProps>(), {
|
|
60
|
+
multiple: false,
|
|
61
|
+
disabled: false,
|
|
62
|
+
width: '100%',
|
|
63
|
+
color: 'var(--text-primary)',
|
|
64
|
+
hoverColor: '',
|
|
65
|
+
activeColor: '',
|
|
66
|
+
disabledColor: 'var(--text-disabled)',
|
|
67
|
+
backgroundColor: 'white',
|
|
68
|
+
borderRadius: '0.375rem',
|
|
69
|
+
padding: '0.5rem',
|
|
70
|
+
icon: '',
|
|
71
|
+
iconSize: 'normal',
|
|
72
|
+
required: false,
|
|
73
|
+
error: '',
|
|
74
|
+
label: '',
|
|
75
|
+
labelPosition: 'top',
|
|
76
|
+
labelAlign: 'left',
|
|
77
|
+
labelWidth: '',
|
|
78
|
+
columns: 1,
|
|
79
|
+
presentation: 'default',
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const emit = defineEmits<{
|
|
83
|
+
(e: 'update:modelValue', value: string | string[]): void
|
|
84
|
+
(e: 'changed'): void
|
|
85
|
+
(e: 'saved'): void
|
|
86
|
+
}>()
|
|
87
|
+
|
|
88
|
+
const id = ref<string>('')
|
|
89
|
+
const showSaved = ref(false)
|
|
90
|
+
const showChanged = ref(false)
|
|
91
|
+
const isChanged = ref(false)
|
|
92
|
+
const debounceTimer = ref<number | null>(null)
|
|
93
|
+
const changedTimer = ref<number | null>(null)
|
|
94
|
+
|
|
95
|
+
const isSelected = (option: CheckboxOption) => {
|
|
96
|
+
if (Array.isArray(props.modelValue)) {
|
|
97
|
+
return props.modelValue.includes(option.id)
|
|
98
|
+
}
|
|
99
|
+
return option.id === props.modelValue
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const toggleOption = (option: CheckboxOption) => {
|
|
103
|
+
if (option.disabled || props.disabled) return
|
|
104
|
+
|
|
105
|
+
if (props.multiple) {
|
|
106
|
+
const currentValue = Array.isArray(props.modelValue) ? props.modelValue : []
|
|
107
|
+
const newValue = currentValue.includes(option.id)
|
|
108
|
+
? currentValue.filter((id) => id !== option.id)
|
|
109
|
+
: [...currentValue, option.id]
|
|
110
|
+
emit('update:modelValue', newValue)
|
|
111
|
+
debounceAutosave(newValue)
|
|
112
|
+
} else {
|
|
113
|
+
const newValue = option.id === props.modelValue ? '' : option.id
|
|
114
|
+
emit('update:modelValue', newValue)
|
|
115
|
+
debounceAutosave(newValue)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const handleAutosave = async (value: string | string[]) => {
|
|
120
|
+
if (props.autosave) {
|
|
121
|
+
try {
|
|
122
|
+
await props.autosave(value)
|
|
123
|
+
if (!props.error) {
|
|
124
|
+
emit('saved')
|
|
125
|
+
showSaved.value = true
|
|
126
|
+
showChanged.value = false
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
showSaved.value = false
|
|
129
|
+
}, 3000)
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error('Autosave failed:', error)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const debounceAutosave = (value: string | string[]) => {
|
|
138
|
+
if (debounceTimer.value) {
|
|
139
|
+
clearTimeout(debounceTimer.value)
|
|
140
|
+
}
|
|
141
|
+
if (changedTimer.value) {
|
|
142
|
+
clearTimeout(changedTimer.value)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!props.error) {
|
|
146
|
+
showChanged.value = true
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
changedTimer.value = window.setTimeout(() => {
|
|
150
|
+
emit('changed')
|
|
151
|
+
isChanged.value = true
|
|
152
|
+
}, 500)
|
|
153
|
+
|
|
154
|
+
debounceTimer.value = window.setTimeout(() => {
|
|
155
|
+
handleAutosave(value)
|
|
156
|
+
}, 1500)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
onMounted(() => {
|
|
160
|
+
id.value = `checkbox-${Math.random().toString(36).substring(2, 11)}`
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const labelStyle = computed(() => {
|
|
164
|
+
if (!props.label) return {}
|
|
165
|
+
if (props.labelPosition === 'left' && props.labelWidth) {
|
|
166
|
+
return {
|
|
167
|
+
'grid-template-columns': `${props.labelWidth} 1fr`,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return {}
|
|
171
|
+
})
|
|
172
|
+
</script>
|
|
173
|
+
|
|
174
|
+
<style scoped>
|
|
175
|
+
.checkbox {
|
|
176
|
+
position: relative;
|
|
177
|
+
width: var(--checkbox-width);
|
|
178
|
+
font-family: Arial, sans-serif;
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
user-select: none;
|
|
181
|
+
outline: none;
|
|
182
|
+
display: grid;
|
|
183
|
+
gap: 0.5rem;
|
|
184
|
+
margin-top: 0.7rem;
|
|
185
|
+
|
|
186
|
+
.checkbox__options {
|
|
187
|
+
display: grid;
|
|
188
|
+
gap: 0.5rem;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
&.checkbox--minimal .checkbox__options {
|
|
192
|
+
gap: 0;
|
|
193
|
+
margin: -0.5rem 0;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.checkbox--disabled {
|
|
198
|
+
opacity: 0.6;
|
|
199
|
+
cursor: not-allowed;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.checkbox--has-error {
|
|
203
|
+
border-color: var(--danger-color);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
.checkbox__option {
|
|
208
|
+
display: flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
gap: 0.5rem;
|
|
211
|
+
padding: var(--checkbox-padding);
|
|
212
|
+
border: 1px solid var(--checkbox-color);
|
|
213
|
+
border-radius: var(--checkbox-border-radius);
|
|
214
|
+
background-color: var(--checkbox-background-color);
|
|
215
|
+
color: var(--checkbox-color);
|
|
216
|
+
transition: all 0.2s ease;
|
|
217
|
+
min-width: 0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.checkbox--minimal .checkbox__option {
|
|
221
|
+
border: none;
|
|
222
|
+
border-radius: 0;
|
|
223
|
+
padding: 0.25rem 0.5rem;
|
|
224
|
+
margin: 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.checkbox__option:hover {
|
|
228
|
+
border-color: var(--checkbox-hover-color);
|
|
229
|
+
color: var(--checkbox-hover-color);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.checkbox--minimal .checkbox__option:hover {
|
|
233
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.checkbox__option--selected {
|
|
237
|
+
border-color: var(--checkbox-active-color);
|
|
238
|
+
color: var(--checkbox-active-color);
|
|
239
|
+
background-color: rgba(from var(--checkbox-active-color) r g b / 0.1);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.checkbox--minimal .checkbox__option--selected {
|
|
243
|
+
background-color: rgba(from var(--checkbox-active-color) r g b / 0.1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.checkbox__option--disabled {
|
|
247
|
+
opacity: 0.6;
|
|
248
|
+
cursor: not-allowed;
|
|
249
|
+
color: var(--checkbox-disabled-color);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.checkbox--minimal .checkbox__option--disabled {
|
|
253
|
+
background-color: transparent;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.checkbox__icon {
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
justify-content: center;
|
|
260
|
+
font-size: 1.2em;
|
|
261
|
+
flex-shrink: 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.checkbox__label {
|
|
265
|
+
flex: 1;
|
|
266
|
+
min-width: 0;
|
|
267
|
+
overflow: hidden;
|
|
268
|
+
text-overflow: ellipsis;
|
|
269
|
+
white-space: nowrap;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.status-indicator {
|
|
273
|
+
position: absolute;
|
|
274
|
+
top: -1px;
|
|
275
|
+
line-height: 1px;
|
|
276
|
+
right: 0.5rem;
|
|
277
|
+
font-size: 0.75rem;
|
|
278
|
+
color: var(--text-muted);
|
|
279
|
+
background-color: var(--checkbox-background-color);
|
|
280
|
+
padding: 0 0.25rem;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.status-indicator.saved-indicator {
|
|
284
|
+
color: var(--success-color);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.status-indicator.changed-indicator {
|
|
288
|
+
color: var(--warning-color);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.status-indicator.error-indicator {
|
|
292
|
+
color: var(--danger-color);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.fade-enter-active,
|
|
296
|
+
.fade-leave-active {
|
|
297
|
+
transition: opacity 0.2s ease;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.fade-enter-from,
|
|
301
|
+
.fade-leave-to {
|
|
302
|
+
opacity: 0;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.checkbox.label-top {
|
|
306
|
+
grid-template-rows: auto 1fr;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.checkbox.label-left {
|
|
310
|
+
grid-template-columns: 30% 1fr;
|
|
311
|
+
align-items: start;
|
|
312
|
+
gap: 1rem;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.checkbox.label-left .label {
|
|
316
|
+
padding-top: 0.25rem;
|
|
317
|
+
width: 100%;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.label {
|
|
321
|
+
font-weight: 500;
|
|
322
|
+
color: var(--text-color);
|
|
323
|
+
text-align: left;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.label-align-left .label {
|
|
327
|
+
text-align: left;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.label-align-right .label {
|
|
331
|
+
text-align: right;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.label-align-center .label {
|
|
335
|
+
text-align: center;
|
|
336
|
+
}
|
|
337
|
+
</style>
|
|
@@ -177,7 +177,7 @@ const handleInput = (event: Event) => {
|
|
|
177
177
|
const value = (event.target as HTMLTextAreaElement).value
|
|
178
178
|
emit('update:modelValue', value)
|
|
179
179
|
debounceAutosave(value)
|
|
180
|
-
if (props.type === '
|
|
180
|
+
if (props.type === 'textarea' && (event.target as HTMLTextAreaElement).tagName === 'TEXTAREA') {
|
|
181
181
|
adjustHeight(event.target as HTMLTextAreaElement)
|
|
182
182
|
}
|
|
183
183
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,8 @@ import FileUpload from './components/FileUpload.vue'
|
|
|
3
3
|
import Navigation from './components/Navigation.vue'
|
|
4
4
|
import Action from './components/Action.vue'
|
|
5
5
|
import Dropdown from './components/Dropdown.vue'
|
|
6
|
+
import Checkbox from './components/Checkbox.vue'
|
|
6
7
|
|
|
7
|
-
export { TextInput, FileUpload, Navigation, Action, Dropdown }
|
|
8
|
+
export { TextInput, FileUpload, Navigation, Action, Dropdown, Checkbox }
|
|
8
9
|
|
|
9
10
|
export * from './types'
|
package/src/router/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import ActionTestView from '../views/ActionTestView.vue'
|
|
|
5
5
|
import DashboardView from '../views/DashboardView.vue'
|
|
6
6
|
import NavigationTestView from '../views/NavigationTestView.vue'
|
|
7
7
|
import DropdownTestView from '../views/DropdownTestView.vue'
|
|
8
|
+
import CheckboxTestView from '../views/CheckboxTestView.vue'
|
|
8
9
|
|
|
9
10
|
const router = createRouter({
|
|
10
11
|
history: createWebHistory(import.meta.env.BASE_URL),
|
|
@@ -45,6 +46,12 @@ const router = createRouter({
|
|
|
45
46
|
component: DropdownTestView,
|
|
46
47
|
meta: { title: 'Dropdown Test' },
|
|
47
48
|
},
|
|
49
|
+
{
|
|
50
|
+
path: '/checkbox',
|
|
51
|
+
name: 'checkbox',
|
|
52
|
+
component: CheckboxTestView,
|
|
53
|
+
meta: { title: 'Checkbox Test' },
|
|
54
|
+
},
|
|
48
55
|
],
|
|
49
56
|
})
|
|
50
57
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface CheckboxOption {
|
|
2
|
+
id: string
|
|
3
|
+
label: string
|
|
4
|
+
disabled?: boolean
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface CheckboxProps {
|
|
8
|
+
options: CheckboxOption[]
|
|
9
|
+
modelValue: string | string[]
|
|
10
|
+
multiple?: boolean
|
|
11
|
+
disabled?: boolean
|
|
12
|
+
width?: string
|
|
13
|
+
color?: string
|
|
14
|
+
hoverColor?: string
|
|
15
|
+
activeColor?: string
|
|
16
|
+
disabledColor?: string
|
|
17
|
+
backgroundColor?: string
|
|
18
|
+
borderRadius?: string
|
|
19
|
+
padding?: string
|
|
20
|
+
icon?: string
|
|
21
|
+
iconSize?: 'normal' | 'large'
|
|
22
|
+
error?: string
|
|
23
|
+
required?: boolean
|
|
24
|
+
autosave?: (value: string | string[]) => Promise<void>
|
|
25
|
+
label?: string
|
|
26
|
+
labelPosition?: 'top' | 'left'
|
|
27
|
+
labelAlign?: 'left' | 'center' | 'right'
|
|
28
|
+
labelWidth?: string
|
|
29
|
+
columns?: number
|
|
30
|
+
presentation?: 'default' | 'minimal'
|
|
31
|
+
}
|
package/src/types/index.ts
CHANGED
package/src/types/textinput.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
export interface TextInputProps {
|
|
2
2
|
modelValue: string
|
|
3
|
+
required?: boolean
|
|
3
4
|
type?: 'text' | 'textarea' | 'password' | 'email' | 'tel' | 'url' | 'date' | 'number'
|
|
4
5
|
placeholder?: string
|
|
5
6
|
label?: string
|
|
7
|
+
labelPosition?: 'top' | 'left'
|
|
8
|
+
labelAlign?: 'left' | 'center' | 'right'
|
|
9
|
+
labelWidth?: string
|
|
10
|
+
width?: string
|
|
6
11
|
icon?: string
|
|
7
12
|
disabled?: boolean
|
|
8
13
|
readonly?: boolean
|
|
9
14
|
maxlength?: number
|
|
10
|
-
error?: string
|
|
11
15
|
min?: Date | string
|
|
12
16
|
max?: Date | string
|
|
13
|
-
autosave?: (value: string) => Promise<void>
|
|
14
|
-
labelPosition?: 'top' | 'left'
|
|
15
|
-
labelAlign?: 'left' | 'center' | 'right'
|
|
16
|
-
labelWidth?: string
|
|
17
17
|
height?: string
|
|
18
18
|
maxHeight?: string
|
|
19
19
|
bgColor?: string
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
autosave?: (value: string) => Promise<void>
|
|
21
|
+
error?: string
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export interface TextInputEmits {
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="checkbox-test">
|
|
3
|
+
<div class="checkbox-test__back">
|
|
4
|
+
<router-link to="/" class="back-link"> ← Back to Dashboard </router-link>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div class="checkbox-test__section">
|
|
8
|
+
<h2>Single Select Checkbox</h2>
|
|
9
|
+
<Checkbox v-model="selectedSingle" :options="options" label="Select a Color" labelPosition="left"
|
|
10
|
+
labelWidth="100px" labelAlign="right" required @update:modelValue="handleSingleChange"
|
|
11
|
+
error="This is an error" />
|
|
12
|
+
<div v-if="selectedSingle.length" class="selection-info">
|
|
13
|
+
Selected: {{ Array.isArray(selectedSingle) ? getSelectedLabels(selectedSingle).join(', ') :
|
|
14
|
+
getOptionLabel(selectedSingle) }}
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="checkbox-test__section">
|
|
19
|
+
<h2>Multiple Select Checkbox</h2>
|
|
20
|
+
<Checkbox v-model="selectedMultiple" :options="options" label="Select Colors" :multiple="true" icon="paintbrush"
|
|
21
|
+
@update:modelValue="handleMultipleChange" color="#aa0000" />
|
|
22
|
+
<div v-if="selectedMultiple.length" class="selection-info">
|
|
23
|
+
Selected: {{ getSelectedLabels(selectedMultiple).join(', ') }}
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="checkbox-test__section">
|
|
28
|
+
<h2>Checkbox with Disabled Options</h2>
|
|
29
|
+
<Checkbox v-model="selectedWithDisabled" :options="optionsWithDisabled" label="Select with Disabled Options"
|
|
30
|
+
@update:modelValue="handleDisabledChange" />
|
|
31
|
+
<div v-if="selectedWithDisabled" class="selection-info">
|
|
32
|
+
Selected: {{ getOptionLabel(selectedWithDisabled) }}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="checkbox-test__section">
|
|
37
|
+
<h2>Disabled Checkbox</h2>
|
|
38
|
+
<Checkbox v-model="selectedDisabled" :options="options" label="Disabled Checkbox" :disabled="true" />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="checkbox-test__section">
|
|
42
|
+
<h2>Custom Styled Checkbox</h2>
|
|
43
|
+
<Checkbox v-model="selectedCustom" :options="options" label="Custom Style" color="#4a90e2" hoverColor="#357abd"
|
|
44
|
+
activeColor="#2c5a8c" borderRadius="1rem" padding="0.75rem 1rem" @update:modelValue="handleCustomChange" />
|
|
45
|
+
<div v-if="selectedCustom" class="selection-info">
|
|
46
|
+
Selected: {{ getOptionLabel(selectedCustom) }}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="checkbox-test__section">
|
|
51
|
+
<h2>Checkbox with Autosave</h2>
|
|
52
|
+
<Checkbox v-model="selectedAutosave" :options="options" label="With Autosave" :autosave="handleAutosave"
|
|
53
|
+
@update:modelValue="handleAutosaveChange" />
|
|
54
|
+
<div v-if="selectedAutosave" class="selection-info">
|
|
55
|
+
Selected: {{ getOptionLabel(selectedAutosave) }}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="checkbox-test__section">
|
|
60
|
+
<h2>Minimal Presentation</h2>
|
|
61
|
+
<Checkbox v-model="selectedMinimal" :options="options" label="Minimal Style" presentation="minimal"
|
|
62
|
+
@update:modelValue="handleMinimalChange" />
|
|
63
|
+
<div v-if="selectedMinimal" class="selection-info">
|
|
64
|
+
Selected: {{ getOptionLabel(selectedMinimal) }}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div class="checkbox-test__section">
|
|
69
|
+
<h2>Multi-Column Checkbox</h2>
|
|
70
|
+
<Checkbox v-model="selectedMultiColumn" :options="options" label="Multi-Column Layout" :columns="3"
|
|
71
|
+
:multiple="true" presentation="minimal" @update:modelValue="handleMultiColumnChange" />
|
|
72
|
+
<div v-if="selectedMultiColumn" class="selection-info">
|
|
73
|
+
Selected: {{ getSelectedLabels(selectedMultiColumn).join(', ') }}
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
78
|
+
|
|
79
|
+
<script setup lang="ts">
|
|
80
|
+
import { ref } from 'vue'
|
|
81
|
+
import type { CheckboxOption } from '../types/checkbox'
|
|
82
|
+
import Checkbox from '@/components/Checkbox.vue'
|
|
83
|
+
|
|
84
|
+
const options: CheckboxOption[] = [
|
|
85
|
+
{ id: 'red', label: 'Red' },
|
|
86
|
+
{ id: 'blue', label: 'Blue' },
|
|
87
|
+
{ id: 'green', label: 'Green' },
|
|
88
|
+
{ id: 'yellow', label: 'Yellow' },
|
|
89
|
+
{ id: 'purple', label: 'Purple' },
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
const optionsWithDisabled: CheckboxOption[] = [
|
|
93
|
+
{ id: 'red', label: 'Red' },
|
|
94
|
+
{ id: 'blue', label: 'Blue', disabled: true },
|
|
95
|
+
{ id: 'green', label: 'Green' },
|
|
96
|
+
{ id: 'yellow', label: 'Yellow', disabled: true },
|
|
97
|
+
{ id: 'purple', label: 'Purple' },
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
const selectedSingle = ref<string[]>(['red', 'yellow'])
|
|
101
|
+
const selectedMultiple = ref<string[]>(['red', 'yellow'])
|
|
102
|
+
const selectedCustom = ref('')
|
|
103
|
+
const selectedDisabled = ref('green')
|
|
104
|
+
const selectedWithDisabled = ref('')
|
|
105
|
+
const selectedAutosave = ref('')
|
|
106
|
+
const selectedMinimal = ref('')
|
|
107
|
+
const selectedMultiColumn = ref<string[]>(['red', 'yellow'])
|
|
108
|
+
|
|
109
|
+
const getOptionLabel = (id: string) => {
|
|
110
|
+
return options.find((option) => option.id === id)?.label || ''
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const getSelectedLabels = (ids: string[]) => {
|
|
114
|
+
return ids.map((id) => getOptionLabel(id)).filter(Boolean)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const handleSingleChange = (value: string | string[]) => {
|
|
118
|
+
if (typeof value === 'string') {
|
|
119
|
+
console.log('Single selection changed:', value)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const handleMultipleChange = (value: string | string[]) => {
|
|
124
|
+
if (Array.isArray(value)) {
|
|
125
|
+
console.log('Multiple selection changed:', value)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const handleCustomChange = (value: string | string[]) => {
|
|
130
|
+
if (typeof value === 'string') {
|
|
131
|
+
console.log('Custom selection changed:', value)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const handleDisabledChange = (value: string | string[]) => {
|
|
136
|
+
if (typeof value === 'string') {
|
|
137
|
+
console.log('Selection with disabled options changed:', value)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const handleAutosaveChange = (value: string | string[]) => {
|
|
142
|
+
if (typeof value === 'string') {
|
|
143
|
+
console.log('Autosave selection changed:', value)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const handleAutosave = async (value: string | string[]) => {
|
|
148
|
+
console.log('Autosaving:', value)
|
|
149
|
+
// Simulate API call
|
|
150
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const handleMinimalChange = (value: string | string[]) => {
|
|
154
|
+
if (typeof value === 'string') {
|
|
155
|
+
console.log('Minimal selection changed:', value)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const handleMultiColumnChange = (value: string | string[]) => {
|
|
160
|
+
if (typeof value === 'string') {
|
|
161
|
+
console.log('Multi-column selection changed:', value)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
</script>
|
|
165
|
+
|
|
166
|
+
<style scoped>
|
|
167
|
+
.checkbox-test {
|
|
168
|
+
max-width: 800px;
|
|
169
|
+
margin: 0 auto;
|
|
170
|
+
padding: 2rem;
|
|
171
|
+
margin-bottom: 5rem;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.checkbox-test__back {
|
|
175
|
+
margin-bottom: 2rem;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.back-link {
|
|
179
|
+
display: inline-flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
gap: 0.5rem;
|
|
182
|
+
color: #4a90e2;
|
|
183
|
+
text-decoration: none;
|
|
184
|
+
font-weight: 500;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.back-link:hover {
|
|
188
|
+
color: #357abd;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.checkbox-test__section {
|
|
192
|
+
margin-bottom: 3rem;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.checkbox-test__section h2 {
|
|
196
|
+
margin-bottom: 1rem;
|
|
197
|
+
color: #333;
|
|
198
|
+
font-size: 1.5rem;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.selection-info {
|
|
202
|
+
margin-top: 1rem;
|
|
203
|
+
padding: 0.5rem;
|
|
204
|
+
background-color: #f7fafc;
|
|
205
|
+
border-radius: 4px;
|
|
206
|
+
font-size: 0.9rem;
|
|
207
|
+
color: #4a5568;
|
|
208
|
+
}
|
|
209
|
+
</style>
|