@a-vision-software/vue-input-components 1.3.11 → 1.3.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-vision-software/vue-input-components",
3
- "version": "1.3.11",
3
+ "version": "1.3.13",
4
4
  "description": "A collection of reusable Vue 3 input components with TypeScript support",
5
5
  "author": "A-Vision Software",
6
6
  "license": "MIT",
@@ -18,21 +18,24 @@
18
18
  "typescript",
19
19
  "file-upload",
20
20
  "text-input",
21
+ "date-picker",
22
+ "dropdown",
21
23
  "textarea"
22
24
  ],
23
25
  "type": "module",
24
26
  "files": [
25
27
  "src",
28
+ "types",
26
29
  "dist"
27
30
  ],
28
31
  "main": "./dist/vue-input-components.cjs.js",
29
32
  "module": "./dist/vue-input-components.es.js",
30
- "types": "./dist/types.d.ts",
33
+ "types": "./types/index.ts",
31
34
  "exports": {
32
35
  ".": {
33
36
  "import": "./dist/vue-input-components.es.js",
34
37
  "require": "./dist/vue-input-components.cjs.js",
35
- "types": "./dist/types.d.ts"
38
+ "types": "./types/index.ts"
36
39
  },
37
40
  "./styles.css": "./dist/vue-input-components.css",
38
41
  "./styles": "./dist/vue-input-components.css"
@@ -5,18 +5,26 @@
5
5
  'dropdown--multiple': multiple,
6
6
  'dropdown--large-icon': iconSize === 'large',
7
7
  'dropdown--has-error': error,
8
- }" :style="{
9
- '--dropdown-color': error ? 'var(--danger-color)' : color,
10
- '--dropdown-hover-color': hoverColor ? hoverColor : 'var(--dropdown-color)',
11
- '--dropdown-active-color': activeColor ? activeColor : 'var(--dropdown-color)',
12
- '--dropdown-disabled-color': disabledColor,
13
- '--dropdown-background-color': backgroundColor,
14
- '--dropdown-border-radius': borderRadius,
15
- '--dropdown-padding': padding,
16
- '--dropdown-max-height': maxHeight,
17
- '--dropdown-width': width,
18
- }" @click="toggleDropdown" @keydown.esc="closeDropdown" @keydown.space.prevent="toggleDropdown"
8
+ [`label-${labelPosition}`]: label,
9
+ [`label-align-${labelAlign}`]: label,
10
+ }" :style="[
11
+ { width: width || '100%' },
12
+ labelStyle,
13
+ {
14
+ '--dropdown-color': error ? 'var(--danger-color)' : color,
15
+ '--dropdown-hover-color': hoverColor ? hoverColor : 'var(--dropdown-color)',
16
+ '--dropdown-active-color': activeColor ? activeColor : 'var(--dropdown-color)',
17
+ '--dropdown-disabled-color': disabledColor,
18
+ '--dropdown-background-color': backgroundColor,
19
+ '--dropdown-border-radius': borderRadius,
20
+ '--dropdown-padding': padding,
21
+ '--dropdown-max-height': maxHeight,
22
+ }
23
+ ]" @click="toggleDropdown" @keydown.esc="closeDropdown" @keydown.space.prevent="toggleDropdown"
19
24
  @keydown.enter.prevent="toggleDropdown" tabindex="0">
25
+ <label v-if="label" :for="id" class="label">
26
+ {{ label }}
27
+ </label>
20
28
  <div class="dropdown__selected">
21
29
  <div v-if="icon" class="dropdown__icon">
22
30
  <img v-if="icon.startsWith('img:')" :src="icon.substring(4)" :alt="placeholder" class="dropdown__icon-image" />
@@ -74,7 +82,7 @@
74
82
  </template>
75
83
 
76
84
  <script setup lang="ts">
77
- import { ref, computed, watch, nextTick, onUnmounted } from 'vue'
85
+ import { ref, computed, watch, nextTick, onUnmounted, onMounted } from 'vue'
78
86
  import type { DropdownProps, DropdownOption } from '../types/dropdown'
79
87
 
80
88
  const props = withDefaults(defineProps<DropdownProps>(), {
@@ -95,6 +103,10 @@ const props = withDefaults(defineProps<DropdownProps>(), {
95
103
  iconSize: 'normal',
96
104
  required: false,
97
105
  error: '',
106
+ label: '',
107
+ labelPosition: 'top',
108
+ labelAlign: 'left',
109
+ labelWidth: '',
98
110
  })
99
111
 
100
112
  const emit = defineEmits<{
@@ -257,6 +269,22 @@ onUnmounted(() => {
257
269
  clearTimeout(changedTimer.value)
258
270
  }
259
271
  })
272
+
273
+ const id = ref<string>('')
274
+
275
+ const labelStyle = computed(() => {
276
+ if (!props.label) return {}
277
+ if (props.labelPosition === 'left' && props.labelWidth) {
278
+ return {
279
+ 'grid-template-columns': `${props.labelWidth} 1fr`,
280
+ }
281
+ }
282
+ return {}
283
+ })
284
+
285
+ onMounted(() => {
286
+ id.value = `dropdown-${Math.random().toString(36).substr(2, 9)}`
287
+ })
260
288
  </script>
261
289
 
262
290
  <style scoped>
@@ -267,6 +295,9 @@ onUnmounted(() => {
267
295
  cursor: pointer;
268
296
  user-select: none;
269
297
  outline: none;
298
+ display: grid;
299
+ gap: 0.5rem;
300
+ margin-top: 0.7rem;
270
301
 
271
302
  &.dropdown--has-error {
272
303
  border-color: var(--danger-color);
@@ -546,4 +577,37 @@ onUnmounted(() => {
546
577
  .fade-leave-to {
547
578
  opacity: 0;
548
579
  }
580
+
581
+ .dropdown.label-top {
582
+ grid-template-rows: auto 1fr;
583
+ }
584
+
585
+ .dropdown.label-left {
586
+ grid-template-columns: 30% 1fr;
587
+ align-items: start;
588
+ gap: 1rem;
589
+ }
590
+
591
+ .dropdown.label-left .label {
592
+ padding-top: 0.25rem;
593
+ width: 100%;
594
+ }
595
+
596
+ .label {
597
+ font-weight: 500;
598
+ color: var(--text-color);
599
+ text-align: left;
600
+ }
601
+
602
+ .label-align-left .label {
603
+ text-align: left;
604
+ }
605
+
606
+ .label-align-right .label {
607
+ text-align: right;
608
+ }
609
+
610
+ .label-align-center .label {
611
+ text-align: center;
612
+ }
549
613
  </style>
@@ -1,47 +1,53 @@
1
1
  <template>
2
2
  <div class="text-input" :class="{
3
+ 'text-input--disabled': disabled,
4
+ 'text-input--has-error': error,
3
5
  [`label-${labelPosition}`]: label,
4
6
  [`label-align-${labelAlign}`]: label,
7
+ 'text-input--has-icon': icon,
5
8
  }" :style="[
6
- { width: type === 'date' ? totalWidth || '12rem' : totalWidth || '100%' },
9
+ { width: (width || '100%') },
7
10
  labelStyle,
8
11
  {
9
- '--max-textarea-height': props.maxHeight || props.height || '14rem',
10
- '--textarea-height': props.height || '5.5rem',
11
- '--input-bg-color': props.bgColor || 'var(--input-color, #ffffffaa)',
12
- '--datepicker-bg-color': props.bgColor || 'var(--background-color, white)',
13
- },
12
+ '--text-input-color': error ? 'var(--danger-color)' : 'var(--text-primary)',
13
+ '--text-input-hover-color': 'var(--primary-color)',
14
+ '--text-input-active-color': 'var(--primary-color)',
15
+ '--text-input-disabled-color': 'var(--text-disabled)',
16
+ '--text-input-background-color': bgColor || 'var(--input-color, #ffffffaa)',
17
+ '--text-dp-background-color': bgColor || '#ffffff',
18
+ '--text-input-border-radius': '0.5rem',
19
+ '--text-input-padding': '0.5rem',
20
+ '--max-textarea-height': maxHeight || height || '14rem',
21
+ '--textarea-height': height || '5.5rem',
22
+ }
14
23
  ]">
15
24
  <label v-if="label" :for="id" class="label">
16
25
  {{ label }}
17
26
  </label>
18
- <div class="input-wrapper" :class="{
19
- 'has-error': error,
20
- 'has-icon': icon,
21
- }">
22
- <div v-if="icon" class="icon-wrapper" @click="focusInput">
23
- <font-awesome-icon :icon="icon" class="icon" />
27
+ <div class="text-input__wrapper">
28
+ <div v-if="icon" class="text-input__icon" @click="focusInput">
29
+ <font-awesome-icon :icon="icon" />
24
30
  </div>
25
31
  <Datepicker v-if="type === 'date'" :id="id" v-model="dateValue" :placeholder="placeholder" :disabled="disabled"
26
32
  :readonly="readonly" :min-date="min" :max-date="max" :format="dateFormat" :enable-time-picker="false"
27
33
  :auto-apply="true" :close-on-auto-apply="true" :clearable="true"
28
- :input-class-name="['input', { 'has-icon': icon }]" @update:model-value="handleDateChange" @focus="handleFocus"
29
- @blur="handleBlur" />
30
- <input v-else-if="!isTextarea" :id="id" :type="type" :value="modelValue" :placeholder="placeholder"
31
- :required="required" :disabled="disabled" :readonly="readonly" :maxlength="maxlength" class="input"
34
+ :input-class-name="['text-input__input', { 'text-input__input--has-icon': icon }]"
35
+ @update:model-value="handleDateChange" @focus="handleFocus" @blur="handleBlur" />
36
+ <input v-else-if="type !== 'textarea'" :id="id" :type="type" :value="modelValue" :placeholder="placeholder"
37
+ :required="required" :disabled="disabled" :readonly="readonly" :maxlength="maxlength" class="text-input__input"
32
38
  @input="handleInput" @focus="handleFocus" @blur="handleBlur" @keydown="handleKeydown" ref="inputRef" />
33
39
  <textarea v-else :id="id" :value="modelValue" :placeholder="placeholder" :required="required" :disabled="disabled"
34
- class="input" @input="handleInput" ref="inputRef"></textarea>
40
+ class="text-input__input" @input="handleInput" ref="inputRef"></textarea>
35
41
  <span v-if="required && !showSaved && !showChanged && !error"
36
- class="status-indicator required-indicator">required</span>
42
+ class="text-input__status required-indicator">required</span>
37
43
  <transition name="fade">
38
- <span v-if="showSaved && !showChanged && !error" class="status-indicator saved-indicator">saved</span>
44
+ <span v-if="showSaved && !showChanged && !error" class="text-input__status saved-indicator">saved</span>
39
45
  </transition>
40
46
  <transition name="fade">
41
- <span v-if="showChanged && !error" class="status-indicator changed-indicator">changed</span>
47
+ <span v-if="showChanged && !error" class="text-input__status changed-indicator">changed</span>
42
48
  </transition>
43
49
  <transition name="fade">
44
- <span v-if="error" class="status-indicator error-indicator" :data-error="error">error</span>
50
+ <span v-if="error" class="text-input__status error-indicator" :data-error="error">error</span>
45
51
  </transition>
46
52
  </div>
47
53
  </div>
@@ -49,7 +55,7 @@
49
55
 
50
56
  <script setup lang="ts">
51
57
  import { computed, ref, onUnmounted, onMounted } from 'vue'
52
- import { TextInputProps } from '../types'
58
+ import { TextInputProps } from '../types/textinput'
53
59
  import Datepicker from '@vuepic/vue-datepicker'
54
60
  import '@vuepic/vue-datepicker/dist/main.css'
55
61
 
@@ -65,6 +71,13 @@ const props = withDefaults(defineProps<TextInputProps>(), {
65
71
  error: '',
66
72
  min: undefined,
67
73
  max: undefined,
74
+ labelPosition: 'top',
75
+ labelAlign: 'left',
76
+ labelWidth: '',
77
+ height: '5.5rem',
78
+ maxHeight: '14rem',
79
+ bgColor: 'var(--input-color, #ffffffee)',
80
+ width: (props) => (props.type === 'date') ? '10rem' : '100%',
68
81
  })
69
82
 
70
83
  const emit = defineEmits<{
@@ -130,7 +143,6 @@ const handleAutosave = async (value: string) => {
130
143
  }
131
144
 
132
145
  const debounceAutosave = (value: string) => {
133
- // Clear existing timers
134
146
  if (debounceTimer.value) {
135
147
  clearTimeout(debounceTimer.value)
136
148
  }
@@ -138,18 +150,15 @@ const debounceAutosave = (value: string) => {
138
150
  clearTimeout(changedTimer.value)
139
151
  }
140
152
 
141
- // Show changed indicator immediately
142
153
  if (!props.error) {
143
154
  showChanged.value = true
144
155
  }
145
156
 
146
- // Trigger changed event after 500ms
147
157
  changedTimer.value = window.setTimeout(() => {
148
158
  emit('changed')
149
159
  isChanged.value = true
150
160
  }, 500)
151
161
 
152
- // Trigger autosave after 1500ms
153
162
  debounceTimer.value = window.setTimeout(() => {
154
163
  handleAutosave(value)
155
164
  }, 1500)
@@ -160,15 +169,17 @@ const focusInput = () => {
160
169
  }
161
170
 
162
171
  const adjustHeight = (element: HTMLTextAreaElement) => {
163
- element.style.height = 'auto' // Reset height to auto to calculate new height
164
- element.style.height = `${element.scrollHeight}px` // Set height to scrollHeight
172
+ element.style.height = 'auto'
173
+ element.style.height = `${element.scrollHeight}px`
165
174
  }
166
175
 
167
176
  const handleInput = (event: Event) => {
168
177
  const value = (event.target as HTMLTextAreaElement).value
169
178
  emit('update:modelValue', value)
170
179
  debounceAutosave(value)
171
- adjustHeight(event.target as HTMLTextAreaElement) // Adjust height on input
180
+ if (props.type === 'text' && (event.target as HTMLTextAreaElement).tagName === 'TEXTAREA') {
181
+ adjustHeight(event.target as HTMLTextAreaElement)
182
+ }
172
183
  }
173
184
 
174
185
  const handleFocus = () => {
@@ -189,7 +200,6 @@ const handleDateChange = (date: Date | null) => {
189
200
  debounceAutosave(formattedDate)
190
201
  }
191
202
 
192
- // Cleanup timers on unmount
193
203
  onUnmounted(() => {
194
204
  if (debounceTimer.value) {
195
205
  clearTimeout(debounceTimer.value)
@@ -218,6 +228,12 @@ defineExpose({
218
228
  gap: 0.5rem;
219
229
  width: 100%;
220
230
  margin-top: 0.7rem;
231
+
232
+ &:not(.text-input--has-icon) {
233
+ .text-input__wrapper {
234
+ grid-template-columns: 1fr;
235
+ }
236
+ }
221
237
  }
222
238
 
223
239
  .text-input.label-top {
@@ -231,7 +247,7 @@ defineExpose({
231
247
  }
232
248
 
233
249
  .text-input.label-left .label {
234
- padding-top: 0.75rem;
250
+ padding-top: 0.25rem;
235
251
  width: 100%;
236
252
  }
237
253
 
@@ -253,40 +269,31 @@ defineExpose({
253
269
  text-align: center;
254
270
  }
255
271
 
256
- .required {
257
- color: var(--danger-color);
258
- margin-left: 0.25rem;
259
- }
260
-
261
- .input-wrapper {
272
+ .text-input__wrapper {
262
273
  position: relative;
263
274
  display: grid;
264
- grid-template-columns: 1fr;
265
- border: 1px solid var(--border-color);
266
- border-radius: 0.5rem;
275
+ grid-template-columns: 2em auto;
276
+ border: 1px solid var(--text-input-color);
277
+ border-radius: var(--text-input-border-radius);
267
278
  transition: all 0.2s ease;
268
279
  width: 100%;
269
280
  min-height: 2rem;
270
- background: var(--input-bg-color);
271
-
272
- &.has-icon {
273
- grid-template-columns: auto 1fr;
274
- }
281
+ background: var(--text-input-background-color);
275
282
 
276
283
  &:hover {
277
- border-color: var(--primary-color);
278
- box-shadow: 0 0 2px var(--primary-color) inset;
284
+ border-color: var(--text-input-hover-color);
285
+ box-shadow: 0 0 2px var(--text-input-hover-color) inset;
279
286
  }
280
287
 
281
288
  &:focus-within {
282
- border-color: var(--primary-color);
283
- box-shadow: 0 0 2px var(--primary-color) inset;
289
+ border-color: var(--text-input-active-color);
290
+ box-shadow: 0 0 2px var(--text-input-active-color) inset;
284
291
  }
285
292
 
286
- &.has-error {
293
+ &.text-input--has-error {
287
294
  border-color: var(--danger-color);
288
295
 
289
- .icon {
296
+ .text-input__icon {
290
297
  color: var(--danger-color);
291
298
  }
292
299
 
@@ -307,11 +314,16 @@ defineExpose({
307
314
  }
308
315
  }
309
316
 
310
- .icon-wrapper {
317
+ .text-input--disabled {
318
+ opacity: 0.6;
319
+ cursor: not-allowed;
320
+ }
321
+
322
+ .text-input__icon {
311
323
  display: grid;
312
324
  place-items: start;
313
325
  padding: 0.5rem;
314
- border-right: 1px solid rgb(from var(--border-color) r g b / 20%);
326
+ border-right: 1px solid rgb(from var(--text-input-color) r g b / 20%);
315
327
  cursor: pointer;
316
328
  overflow: hidden;
317
329
 
@@ -325,10 +337,10 @@ defineExpose({
325
337
  }
326
338
  }
327
339
 
328
- .input {
340
+ .text-input__input {
329
341
  padding: 0.25rem 0.5rem;
330
342
  border: none;
331
- border-radius: 0.5rem;
343
+ border-radius: var(--text-input-border-radius);
332
344
  outline: none;
333
345
  font-size: 1rem;
334
346
  color: var(--text-color);
@@ -346,7 +358,7 @@ defineExpose({
346
358
  }
347
359
  }
348
360
 
349
- .status-indicator {
361
+ .text-input__status {
350
362
  position: absolute;
351
363
  display: block;
352
364
  top: -1px;
@@ -354,7 +366,7 @@ defineExpose({
354
366
  right: 0.5rem;
355
367
  font-size: 0.75rem;
356
368
  color: var(--text-muted);
357
- background-color: var(--input-bg-color);
369
+ background-color: var(--text-input-background-color);
358
370
  padding: 0 0.25rem;
359
371
 
360
372
  &.saved-indicator {
@@ -381,8 +393,8 @@ defineExpose({
381
393
  }
382
394
 
383
395
  textarea {
384
- min-height: var(--textarea-height, 5.5rem);
385
- max-height: var(--max-textarea-height, 14rem);
396
+ min-height: var(--textarea-height);
397
+ max-height: var(--max-textarea-height);
386
398
  overflow-y: auto;
387
399
  resize: none;
388
400
  }
@@ -407,7 +419,7 @@ textarea {
407
419
  cursor: not-allowed;
408
420
  }
409
421
 
410
- :deep(.dp__input.has-icon) {
422
+ :deep(.dp__input.text-input__input--has-icon) {
411
423
  padding-left: 2.5rem;
412
424
  }
413
425
 
@@ -420,9 +432,9 @@ textarea {
420
432
  }
421
433
 
422
434
  :deep(.dp__menu) {
423
- background-color: var(--datepicker-bg-color);
424
- border: 1px solid var(--border-color);
425
- border-radius: 0.5rem;
435
+ background-color: var(--text-dp-background-color);
436
+ border: 1px solid var(--text-input-color);
437
+ border-radius: var(--text-input-border-radius);
426
438
  box-shadow:
427
439
  0 4px 6px -1px rgba(0, 0, 0, 0.1),
428
440
  0 2px 4px -1px rgba(0, 0, 0, 0.06);
@@ -433,17 +445,17 @@ textarea {
433
445
  }
434
446
 
435
447
  :deep(.dp__today) {
436
- border-color: var(--primary-color);
448
+ border-color: var(--text-input-active-color);
437
449
  }
438
450
 
439
451
  :deep(.dp__active_date) {
440
- background-color: var(--primary-color);
452
+ background-color: var(--text-input-active-color);
441
453
  color: white;
442
454
  }
443
455
 
444
456
  :deep(.dp__range_start),
445
457
  :deep(.dp__range_end) {
446
- background-color: var(--primary-color);
458
+ background-color: var(--text-input-active-color);
447
459
  color: white;
448
460
  }
449
461
 
@@ -452,10 +464,7 @@ textarea {
452
464
  color: var(--text-color);
453
465
  }
454
466
 
455
- :deep(.dp__arrow_bottom) {
456
- background-color: inherit;
457
- }
458
-
467
+ :deep(.dp__arrow_bottom),
459
468
  :deep(.dp__arrow_top) {
460
469
  background-color: inherit;
461
470
  }
@@ -0,0 +1,19 @@
1
+ export interface ActionProps {
2
+ icon?: string
3
+ label?: string
4
+ href?: string
5
+ type?: 'button' | 'submit' | 'reset'
6
+ disabled?: boolean
7
+ color?: string
8
+ size?: 'small' | 'regular' | 'large'
9
+ variant?: 'solid' | 'transparent'
10
+ }
11
+
12
+ export interface ActionEmits {
13
+ (e: 'click', event: MouseEvent): void
14
+ }
15
+
16
+ export interface ActionComponent {
17
+ focus: () => void
18
+ blur: () => void
19
+ }
@@ -25,4 +25,8 @@ export interface DropdownProps {
25
25
  error?: string
26
26
  required?: boolean
27
27
  autosave?: (value: string | string[]) => Promise<void>
28
+ label?: string
29
+ labelPosition?: 'top' | 'left'
30
+ labelAlign?: 'left' | 'center' | 'right'
31
+ labelWidth?: string
28
32
  }
@@ -0,0 +1,26 @@
1
+ export interface FileUploadProps {
2
+ modelValue: File[]
3
+ label?: string
4
+ placeholder?: string
5
+ error?: string
6
+ disabled?: boolean
7
+ required?: boolean
8
+ multiple?: boolean
9
+ accept?: string
10
+ maxSize?: number
11
+ uploadUrl?: string
12
+ }
13
+
14
+ export interface FileUploadEmits {
15
+ (e: 'update:modelValue', files: File[]): void
16
+ (e: 'files-selected', files: File[]): void
17
+ (e: 'start-upload', files: File[]): void
18
+ (e: 'upload-progress', progress: number): void
19
+ (e: 'upload-success', response: any): void
20
+ (e: 'upload-error', error: Error): void
21
+ }
22
+
23
+ export interface FileUploadComponent {
24
+ focus: () => void
25
+ blur: () => void
26
+ }
@@ -1,3 +1,9 @@
1
1
  import type { NavigationProps, NavigationItem } from './navigation'
2
2
 
3
3
  export type { NavigationProps, NavigationItem }
4
+
5
+ export * from './textinput'
6
+ export * from './fileupload'
7
+ export * from './action'
8
+ export * from './navigation'
9
+ export * from './dropdown'
@@ -0,0 +1,36 @@
1
+ export interface TextInputProps {
2
+ modelValue: string
3
+ type?: 'text' | 'textarea' | 'password' | 'email' | 'tel' | 'url' | 'date' | 'number'
4
+ placeholder?: string
5
+ label?: string
6
+ icon?: string
7
+ disabled?: boolean
8
+ readonly?: boolean
9
+ maxlength?: number
10
+ error?: string
11
+ min?: Date | string
12
+ max?: Date | string
13
+ autosave?: (value: string) => Promise<void>
14
+ labelPosition?: 'top' | 'left'
15
+ labelAlign?: 'left' | 'center' | 'right'
16
+ labelWidth?: string
17
+ height?: string
18
+ maxHeight?: string
19
+ bgColor?: string
20
+ width?: string
21
+ required?: boolean
22
+ }
23
+
24
+ export interface TextInputEmits {
25
+ (e: 'update:modelValue', value: string): void
26
+ (e: 'changed'): void
27
+ (e: 'saved'): void
28
+ (e: 'focus'): void
29
+ (e: 'blur'): void
30
+ (e: 'keydown', event: KeyboardEvent): void
31
+ }
32
+
33
+ export interface TextInputComponent {
34
+ focus: () => void
35
+ blur: () => void
36
+ }
@@ -6,8 +6,9 @@
6
6
 
7
7
  <div class="dropdown-test__section">
8
8
  <h2>Single Select Dropdown</h2>
9
- <Dropdown v-model="selectedSingle" :options="options" placeholder="Select a color" filterable required
10
- @update:modelValue="handleSingleChange" error="This is an error" />
9
+ <Dropdown v-model="selectedSingle" :options="options" label="Color" labelPosition="left" labelWidth="100px"
10
+ labelAlign="right" placeholder="Select a color" filterable required @update:modelValue="handleSingleChange"
11
+ error="This is an error" />
11
12
  <div v-if="selectedSingle" class="selection-info">
12
13
  Selected: {{ getOptionLabel(selectedSingle) }}
13
14
  </div>
@@ -15,8 +16,8 @@
15
16
 
16
17
  <div class="dropdown-test__section">
17
18
  <h2>Multiple Select Dropdown</h2>
18
- <Dropdown v-model="selectedMultiple" :options="options" multiple filterable placeholder="Select colors"
19
- icon="paintbrush" @update:modelValue="handleMultipleChange" color="#aa0000" />
19
+ <Dropdown v-model="selectedMultiple" :options="options" label="Multiple colors" multiple filterable
20
+ placeholder="Select colors" icon="paintbrush" @update:modelValue="handleMultipleChange" color="#aa0000" />
20
21
  <div v-if="selectedMultiple.length" class="selection-info">
21
22
  Selected: {{ getSelectedLabels(selectedMultiple).join(', ') }}
22
23
  </div>