@volverjs/ui-vue 0.0.3 → 0.0.4

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.
Files changed (145) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +52 -13
  3. package/dist/Volver.d.ts +5 -1
  4. package/dist/components/VvAccordion/VvAccordion.es.js +113 -66
  5. package/dist/components/VvAccordion/VvAccordion.umd.js +1 -1
  6. package/dist/components/VvAccordionGroup/VvAccordionGroup.es.js +159 -101
  7. package/dist/components/VvAccordionGroup/VvAccordionGroup.umd.js +1 -1
  8. package/dist/components/VvAction/VvAction.es.js +170 -0
  9. package/dist/components/VvAction/VvAction.umd.js +1 -0
  10. package/dist/components/VvAction/VvAction.vue.d.ts +63 -0
  11. package/dist/components/VvAction/index.d.ts +24 -0
  12. package/dist/components/VvBadge/VvBadge.es.js +86 -16
  13. package/dist/components/VvBadge/VvBadge.umd.js +1 -1
  14. package/dist/components/VvBreadcrumb/VvBreadcrumb.es.js +97 -41
  15. package/dist/components/VvBreadcrumb/VvBreadcrumb.umd.js +1 -1
  16. package/dist/components/VvButton/VvButton.es.js +434 -251
  17. package/dist/components/VvButton/VvButton.umd.js +1 -1
  18. package/dist/components/VvButton/VvButton.vue.d.ts +50 -50
  19. package/dist/components/VvButton/index.d.ts +22 -67
  20. package/dist/components/VvButtonGroup/VvButtonGroup.es.js +118 -43
  21. package/dist/components/VvButtonGroup/VvButtonGroup.umd.js +1 -1
  22. package/dist/components/VvCard/VvCard.es.js +38 -25
  23. package/dist/components/VvCard/VvCard.umd.js +1 -1
  24. package/dist/components/VvCheckbox/VvCheckbox.es.js +334 -154
  25. package/dist/components/VvCheckbox/VvCheckbox.umd.js +1 -1
  26. package/dist/components/VvCheckbox/VvCheckbox.vue.d.ts +2 -2
  27. package/dist/components/VvCheckbox/index.d.ts +1 -1
  28. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.es.js +401 -204
  29. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.umd.js +1 -1
  30. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.vue.d.ts +2 -2
  31. package/dist/components/VvCheckboxGroup/index.d.ts +1 -1
  32. package/dist/components/VvCombobox/VvCombobox.es.js +950 -594
  33. package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
  34. package/dist/components/VvCombobox/VvCombobox.vue.d.ts +54 -30
  35. package/dist/components/VvCombobox/index.d.ts +18 -13
  36. package/dist/components/VvDialog/VvDialog.es.js +139 -64
  37. package/dist/components/VvDialog/VvDialog.umd.js +1 -1
  38. package/dist/components/VvDropdown/VvDropdown.es.js +276 -158
  39. package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
  40. package/dist/components/VvDropdown/VvDropdown.vue.d.ts +9 -9
  41. package/dist/components/VvDropdown/VvDropdownAction.vue.d.ts +61 -0
  42. package/dist/components/VvDropdown/VvDropdownOption.vue.d.ts +52 -0
  43. package/dist/components/VvDropdown/index.d.ts +6 -9
  44. package/dist/components/VvDropdownAction/VvDropdownAction.es.js +251 -0
  45. package/dist/components/VvDropdownAction/VvDropdownAction.umd.js +1 -0
  46. package/dist/components/VvDropdownItem/VvDropdownItem.es.js +30 -15
  47. package/dist/components/VvDropdownItem/VvDropdownItem.umd.js +1 -1
  48. package/dist/components/VvDropdownOption/VvDropdownOption.es.js +176 -0
  49. package/dist/components/VvDropdownOption/VvDropdownOption.umd.js +1 -0
  50. package/dist/components/VvIcon/VvIcon.es.js +48 -32
  51. package/dist/components/VvIcon/VvIcon.umd.js +1 -1
  52. package/dist/components/VvInputText/VvInputText.es.js +508 -344
  53. package/dist/components/VvInputText/VvInputText.umd.js +1 -1
  54. package/dist/components/VvInputText/VvInputText.vue.d.ts +11 -4
  55. package/dist/components/VvInputText/index.d.ts +13 -2
  56. package/dist/components/VvProgress/VvProgress.es.js +90 -20
  57. package/dist/components/VvProgress/VvProgress.umd.js +1 -1
  58. package/dist/components/VvRadio/VvRadio.es.js +305 -125
  59. package/dist/components/VvRadio/VvRadio.umd.js +1 -1
  60. package/dist/components/VvRadio/VvRadio.vue.d.ts +2 -2
  61. package/dist/components/VvRadio/index.d.ts +1 -1
  62. package/dist/components/VvRadioGroup/VvRadioGroup.es.js +372 -175
  63. package/dist/components/VvRadioGroup/VvRadioGroup.umd.js +1 -1
  64. package/dist/components/VvRadioGroup/VvRadioGroup.vue.d.ts +2 -2
  65. package/dist/components/VvRadioGroup/index.d.ts +1 -1
  66. package/dist/components/VvSelect/VvSelect.es.js +371 -216
  67. package/dist/components/VvSelect/VvSelect.umd.js +1 -1
  68. package/dist/components/VvSelect/VvSelect.vue.d.ts +11 -4
  69. package/dist/components/VvSelect/index.d.ts +5 -5
  70. package/dist/components/VvTextarea/VvTextarea.es.js +408 -244
  71. package/dist/components/VvTextarea/VvTextarea.umd.js +1 -1
  72. package/dist/components/VvTextarea/VvTextarea.vue.d.ts +11 -4
  73. package/dist/components/VvTextarea/index.d.ts +5 -5
  74. package/dist/components/VvTooltip/VvTooltip.es.js +88 -18
  75. package/dist/components/VvTooltip/VvTooltip.umd.js +1 -1
  76. package/dist/components/index.es.js +1913 -1521
  77. package/dist/components/index.umd.js +1 -1
  78. package/dist/composables/dropdown/useInjectDropdown.d.ts +1 -1
  79. package/dist/composables/dropdown/useProvideDropdown.d.ts +2 -2
  80. package/dist/constants.d.ts +30 -0
  81. package/dist/directives/index.es.js +128 -0
  82. package/dist/directives/index.umd.js +1 -0
  83. package/dist/directives/v-tooltip.es.js +126 -0
  84. package/dist/directives/v-tooltip.umd.js +1 -0
  85. package/dist/icons.es.js +3 -3
  86. package/dist/icons.umd.js +1 -1
  87. package/dist/index.es.js +2102 -1761
  88. package/dist/index.umd.js +1 -1
  89. package/dist/props/index.d.ts +179 -11
  90. package/dist/resolvers/unplugin.d.ts +8 -8
  91. package/dist/resolvers/unplugin.es.js +51 -30
  92. package/dist/resolvers/unplugin.umd.js +1 -1
  93. package/dist/stories/Combobox/Combobox.settings.d.ts +44 -0
  94. package/dist/stories/Dropdown/Dropdown.settings.d.ts +3 -2
  95. package/package.json +60 -34
  96. package/src/Volver.ts +12 -5
  97. package/src/assets/icons/detailed.json +1 -1
  98. package/src/assets/icons/normal.json +1 -1
  99. package/src/assets/icons/simple.json +1 -1
  100. package/src/components/VvAction/VvAction.vue +144 -0
  101. package/src/components/VvAction/index.ts +5 -0
  102. package/src/components/VvButton/VvButton.vue +31 -114
  103. package/src/components/VvButton/index.ts +6 -79
  104. package/src/components/VvCombobox/VvCombobox.vue +54 -42
  105. package/src/components/VvCombobox/index.ts +11 -9
  106. package/src/components/VvDropdown/VvDropdownAction.vue +44 -0
  107. package/src/components/VvDropdown/VvDropdownOption.vue +65 -0
  108. package/src/components/VvDropdown/index.ts +4 -9
  109. package/src/components/VvSelect/index.ts +2 -4
  110. package/src/composables/dropdown/useInjectDropdown.ts +1 -1
  111. package/src/composables/dropdown/useProvideDropdown.ts +7 -9
  112. package/src/composables/useModifiers.ts +4 -7
  113. package/src/constants.ts +36 -0
  114. package/src/props/index.ts +106 -14
  115. package/src/resolvers/unplugin.ts +81 -48
  116. package/src/stories/Accordion/AccordionSlots.stories.mdx +2 -2
  117. package/src/stories/AccordionGroup/AccordionGroupSlots.stories.mdx +2 -1
  118. package/src/stories/Breadcrumb/Breadcrumb.stories.mdx +2 -1
  119. package/src/stories/Button/Button.stories.mdx +4 -2
  120. package/src/stories/Button/Button.test.ts +3 -1
  121. package/src/stories/Button/ButtonModifiers.stories.mdx +2 -2
  122. package/src/stories/Button/ButtonSlots.stories.mdx +8 -7
  123. package/src/stories/Button/ButtonState.stories.mdx +2 -11
  124. package/src/stories/Card/Card.stories.mdx +2 -1
  125. package/src/stories/Checkbox/Checkbox.stories.mdx +2 -1
  126. package/src/stories/CheckboxGroup/CheckboxGroup.stories.mdx +2 -1
  127. package/src/stories/CheckboxGroup/CheckboxGroupSlots.stories.mdx +2 -1
  128. package/src/stories/Combobox/Combobox.settings.ts +44 -0
  129. package/src/stories/Combobox/Combobox.stories.mdx +40 -1
  130. package/src/stories/Dialog/Dialog.stories.mdx +2 -1
  131. package/src/stories/Dropdown/Dropdown.settings.ts +3 -2
  132. package/src/stories/Dropdown/Dropdown.stories.mdx +14 -12
  133. package/src/stories/Dropdown/DropdownMultilevel.stories.mdx +56 -0
  134. package/src/stories/Dropdown/DropdownSlots.stories.mdx +14 -13
  135. package/src/stories/Icon/Icon.stories.mdx +2 -1
  136. package/src/stories/Icon/IconsCollection.stories.mdx +2 -1
  137. package/src/stories/InputText/InputText.stories.mdx +2 -1
  138. package/src/stories/Progress/Progress.stories.mdx +2 -1
  139. package/src/stories/Radio/Radio.stories.mdx +2 -1
  140. package/src/stories/RadioGroup/RadioGroup.stories.mdx +2 -1
  141. package/src/stories/RadioGroup/RadioGroupSlots.stories.mdx +2 -1
  142. package/src/stories/Select/Select.stories.mdx +2 -1
  143. package/src/stories/Textarea/Textarea.stories.mdx +2 -1
  144. package/src/stories/Tooltip/Tooltip.stories.mdx +2 -1
  145. package/src/stories/Tooltip/TooltipDirective.stories.mdx +2 -1
@@ -0,0 +1,144 @@
1
+ <script lang="ts">
2
+ export default {
3
+ name: 'VvAction',
4
+ }
5
+ </script>
6
+
7
+ <script setup lang="ts">
8
+ import { VvActionProps, VvActionEvents } from '@/components/VvAction'
9
+ import { ActionTag } from '@/constants'
10
+
11
+ // props and emits
12
+ const props = defineProps(VvActionProps)
13
+ const emits = defineEmits(VvActionEvents)
14
+
15
+ // inject plugin
16
+ const volver = useVolver()
17
+
18
+ const element = ref<HTMLElement | null>(null)
19
+ defineExpose({ $el: element })
20
+
21
+ // drowpdown trigger
22
+ const {
23
+ reference: dropdownTriggerReference,
24
+ bus: dropdownEventBus,
25
+ aria: dropdownAria,
26
+ expanded: dropdownExpanded,
27
+ } = useInjectedDropdownTrigger()
28
+ watch(
29
+ () => element.value,
30
+ (newValue) => {
31
+ if (dropdownTriggerReference) {
32
+ dropdownTriggerReference.value = newValue
33
+ }
34
+ },
35
+ )
36
+
37
+ // pressed
38
+ const pressed = computed(() => {
39
+ return props.pressed || dropdownExpanded?.value
40
+ })
41
+
42
+ // dropdown parent
43
+ const { role } = useInjectedDropdownAction()
44
+
45
+ /**
46
+ * @description The tag defined by props.
47
+ * @returns {string} The tag.
48
+ */
49
+ const hasTag = computed(() => {
50
+ switch (true) {
51
+ case props.disabled:
52
+ return ActionTag.button
53
+ case props.to !== undefined:
54
+ return volver?.nuxt ? ActionTag.nuxtLink : ActionTag.routerLink
55
+ case props.href !== undefined:
56
+ return ActionTag.a
57
+ default:
58
+ return ActionTag.button
59
+ }
60
+ })
61
+
62
+ /**
63
+ * @description Define component attributes.
64
+ * @returns {Object} The component attributes.
65
+ */
66
+ const hasProps = computed(() => {
67
+ const toReturn = {
68
+ ...dropdownAria?.value,
69
+ 'aria-pressed': pressed.value ? true : undefined,
70
+ role,
71
+ }
72
+ switch (hasTag.value) {
73
+ case ActionTag.a:
74
+ return {
75
+ ...toReturn,
76
+ href: props.href,
77
+ target: props.target,
78
+ rel: props.rel,
79
+ }
80
+ case ActionTag.routerLink:
81
+ case ActionTag.nuxtLink:
82
+ return {
83
+ ...toReturn,
84
+ to: props.to,
85
+ target: props.target,
86
+ }
87
+ default:
88
+ return {
89
+ ...toReturn,
90
+ type: props.type,
91
+ disabled: props.disabled,
92
+ }
93
+ }
94
+ })
95
+
96
+ /**
97
+ * @description Catch click event
98
+ */
99
+ const onClick = (e: Event) => {
100
+ if (props.disabled) {
101
+ e.preventDefault()
102
+ return
103
+ }
104
+ dropdownEventBus?.emit('click', e)
105
+ emits('click', e)
106
+ }
107
+
108
+ /**
109
+ * @description Catch mouseover event
110
+ */
111
+ const onMouseover = (e: Event) => {
112
+ dropdownEventBus?.emit('mouseover', e)
113
+ emits('mouseover', e)
114
+ }
115
+
116
+ /**
117
+ * @description Catch mouseleave event
118
+ */
119
+ const onMouseleave = (e: Event) => {
120
+ dropdownEventBus?.emit('mouseleave', e)
121
+ emits('mouseleave', e)
122
+ }
123
+ </script>
124
+
125
+ <template>
126
+ <component
127
+ v-bind="hasProps"
128
+ :is="hasTag"
129
+ ref="element"
130
+ :class="{
131
+ active,
132
+ pressed,
133
+ disabled,
134
+ }"
135
+ @click.passive="onClick"
136
+ @mouseover.passive="onMouseover"
137
+ @mouseleave.passive="onMouseleave"
138
+ >
139
+ <!-- @slot Default slot -->
140
+ <slot>
141
+ {{ label }}
142
+ </slot>
143
+ </component>
144
+ </template>
@@ -0,0 +1,5 @@
1
+ import { ActionProps } from '@/props'
2
+
3
+ export const VvActionEvents = ['click', 'mouseover', 'mouseleave']
4
+
5
+ export const VvActionProps = ActionProps
@@ -6,9 +6,9 @@
6
6
 
7
7
  <script setup lang="ts">
8
8
  import VvIcon from '@/components/VvIcon/VvIcon.vue'
9
+ import VvAction from '@/components/VvAction/VvAction.vue'
9
10
  import {
10
11
  VvButtonEvents,
11
- ButtonTag,
12
12
  VvButtonProps,
13
13
  useGroupProps,
14
14
  } from '@/components/VvButton'
@@ -35,58 +35,23 @@
35
35
  const hasId = useUniqueId(id)
36
36
  const name = computed(() => (attrs?.name as string) || hasId.value)
37
37
 
38
- // inject plugin
39
- const volver = useVolver()
40
-
41
38
  // expose el
42
- const $el = ref<HTMLElement | null>(null)
39
+ const element = ref<{ $el: HTMLElement } | null>(null)
40
+ const $el = computed(() => element.value?.$el)
43
41
  defineExpose({ $el })
44
42
 
45
- // drowpdown trigger
46
- const {
47
- reference: dropdownTriggerReference,
48
- bus: dropdownEventBus,
49
- aria: dropdownAria,
50
- } = useInjectedDropdownTrigger()
51
- watch(
52
- () => $el.value,
53
- (newValue) => {
54
- if (dropdownTriggerReference) {
55
- dropdownTriggerReference.value = newValue
56
- }
57
- },
58
- )
59
-
60
- // dropdown parent
61
- const { role } = useInjectedDropdownAction()
62
-
63
- /**
64
- * @description The tag defined by props.
65
- * @returns {string} The tag.
66
- */
67
- const hasTag = computed(() => {
68
- switch (true) {
69
- case disabled.value:
70
- return ButtonTag.button
71
- case props.to !== undefined:
72
- return volver?.nuxt ? ButtonTag.nuxtLink : ButtonTag.routerLink
73
- case props.href !== undefined:
74
- return ButtonTag.a
75
- default:
76
- return ButtonTag.button
77
- }
78
- })
79
-
80
43
  /**
81
44
  * @description The component pressed state by prop or group.
82
45
  * @returns {string} The component tag.
83
46
  */
84
- const isPressed = computed(() => {
85
- if (!toggle.value) return props.pressed
86
-
87
- return Array.isArray(modelValue.value)
88
- ? contains(name.value, modelValue.value)
89
- : equals(name.value, modelValue.value)
47
+ const pressed = computed(() => {
48
+ if (!toggle.value) {
49
+ return props.pressed
50
+ }
51
+ if (Array.isArray(modelValue.value)) {
52
+ return contains(name.value, modelValue.value)
53
+ }
54
+ return equals(name.value, modelValue.value)
90
55
  })
91
56
 
92
57
  /**
@@ -97,12 +62,11 @@
97
62
  'vv-button',
98
63
  modifiers,
99
64
  computed(() => ({
100
- active: props.active,
101
- pressed: isPressed.value,
102
- disabled: disabled.value,
103
65
  reverse: [Side.right, Side.bottom].includes(iconPosition.value),
104
66
  column: [Side.top, Side.bottom].includes(iconPosition.value),
105
- iconOnly: Boolean(icon?.value && !label?.value && !slots.default),
67
+ 'icon-only': Boolean(
68
+ icon?.value && !label?.value && !slots.default,
69
+ ),
106
70
  })),
107
71
  )
108
72
 
@@ -114,48 +78,10 @@
114
78
  typeof icon?.value === 'string' ? { name: icon?.value } : icon?.value,
115
79
  )
116
80
 
117
- /**
118
- * @description Define component attributes.
119
- * @returns {Object} The component attributes.
120
- */
121
- const hasProps = computed(() => {
122
- const toReturn = {
123
- ...dropdownAria?.value,
124
- 'aria-pressed': isPressed.value ? true : undefined,
125
- class: bemCssClasses.value,
126
- role,
127
- }
128
- switch (hasTag.value) {
129
- case ButtonTag.a:
130
- return {
131
- ...toReturn,
132
- role: toReturn.role ?? 'button',
133
- href: props.href,
134
- target: props.target,
135
- rel: props.rel,
136
- }
137
- case ButtonTag.routerLink:
138
- case ButtonTag.nuxtLink:
139
- return {
140
- ...toReturn,
141
- role: toReturn.role ?? 'button',
142
- to: props.to,
143
- target: props.target,
144
- }
145
- default:
146
- return {
147
- ...toReturn,
148
- type: props.type,
149
- disabled: disabled.value,
150
- }
151
- }
152
- })
153
-
154
81
  /**
155
82
  * @description Catch click event
156
83
  */
157
- const onClick = (e: Event) => {
158
- dropdownEventBus?.emit('click', e)
84
+ const onClick = () => {
159
85
  if (toggle.value) {
160
86
  if (Array.isArray(modelValue.value)) {
161
87
  if (contains(name.value, modelValue.value)) {
@@ -169,39 +95,31 @@
169
95
  modelValue.value.push(name.value)
170
96
  return
171
97
  }
172
- if (equals(name, modelValue.value) && unselectable.value) {
98
+ if (equals(name.value, modelValue.value) && unselectable.value) {
173
99
  modelValue.value = undefined
174
100
  return
175
101
  }
176
102
  modelValue.value = name.value
177
103
  }
178
104
  }
179
-
180
- /**
181
- * @description Catch mouseover event
182
- */
183
- const onMouseover = (e: Event) => {
184
- dropdownEventBus?.emit('mouseover', e)
185
- }
186
-
187
- /**
188
- * @description Catch mouseleave event
189
- */
190
- const onMouseleave = (e: Event) => {
191
- dropdownEventBus?.emit('mouseleave', e)
192
- }
193
105
  </script>
194
106
 
195
107
  <template>
196
- <!-- #region component: "button" | "a" | "router-link" | "nuxt-link" -->
197
- <component
198
- v-bind="hasProps"
199
- :is="hasTag"
108
+ <VvAction
109
+ v-bind="{
110
+ disabled,
111
+ pressed,
112
+ active,
113
+ type,
114
+ to,
115
+ href,
116
+ target,
117
+ rel,
118
+ }"
200
119
  :id="hasId"
201
- ref="$el"
202
- @click.passive="onClick"
203
- @mouseover.passive="onMouseover"
204
- @mouseleave.passive="onMouseleave"
120
+ ref="element"
121
+ :class="bemCssClasses"
122
+ @click="onClick"
205
123
  >
206
124
  <!-- @slot Default slot -->
207
125
  <slot>
@@ -238,6 +156,5 @@
238
156
  </template>
239
157
  <!-- #endregion -->
240
158
  </slot>
241
- </component>
242
- <!-- #endregion -->
159
+ </VvAction>
243
160
  </template>
@@ -1,40 +1,22 @@
1
1
  import type { Ref, PropType, ExtractPropTypes } from 'vue'
2
2
  import type { ButtonGroupState } from '@/types/group'
3
3
  import {
4
- DisabledProps,
4
+ ActionProps,
5
5
  IdProps,
6
+ LoadingProps,
6
7
  ModifiersProps,
7
8
  UnselectableProps,
8
9
  } from '@/props'
9
10
  import { INJECTION_KEY_BUTTON_GROUP, Side } from '@/constants'
10
11
 
11
- export enum ButtonType {
12
- button = 'button',
13
- submit = 'submit',
14
- reset = 'reset',
15
- }
16
-
17
- export enum ButtonTag {
18
- nuxtLink = 'nuxt-link',
19
- routerLink = 'router-link',
20
- a = 'a',
21
- button = 'button',
22
- }
23
-
24
- export enum ButtonTarget {
25
- _blank = '_blank',
26
- _self = '_self',
27
- _parent = '_parent',
28
- _top = '_top',
29
- }
30
-
31
12
  export const VvButtonEvents = ['update:modelValue']
32
13
 
33
14
  export const VvButtonProps = {
15
+ ...ActionProps,
34
16
  ...IdProps,
35
17
  ...ModifiersProps,
36
- ...DisabledProps,
37
18
  ...UnselectableProps,
19
+ ...LoadingProps,
38
20
  /**
39
21
  * Button icon
40
22
  */
@@ -47,65 +29,10 @@ export const VvButtonProps = {
47
29
  default: Side.left,
48
30
  validator: (value: Side) => Object.values(Side).includes(value),
49
31
  },
50
- /**
51
- * Button label
52
- */
53
- label: [String, Number],
54
- /**
55
- * Loading status
56
- */
57
- loading: Boolean,
58
32
  /**
59
33
  * Loading icon
60
34
  */
61
35
  loadingIcon: { type: String, default: 'eos-icons:bubble-loading' },
62
- /**
63
- * Loading label
64
- */
65
- loadingLabel: {
66
- type: String,
67
- default: 'Loading...',
68
- },
69
- /**
70
- * The router-link/nuxt-link property, if it is defined the button is rendered as a ruouter-link or nuxt-link.
71
- * @see Documentation of [router-link](https://router.vuejs.org/api/#router-link) and [nuxt-link](https://nuxtjs.org/api/components-nuxt-link/)
72
- */
73
- to: {
74
- type: [String, Object],
75
- },
76
- /**
77
- * Link href
78
- */
79
- href: String,
80
- /**
81
- * Link target
82
- */
83
- target: {
84
- type: String as PropType<ButtonTarget>,
85
- validator: (value: ButtonTarget) =>
86
- Object.values(ButtonTarget).includes(value),
87
- },
88
- active: Boolean,
89
- /**
90
- * Button pressed mode
91
- */
92
- pressed: Boolean,
93
- /**
94
- * Link rel
95
- */
96
- rel: {
97
- type: String,
98
- default: 'noopener noreferrer',
99
- },
100
- /**
101
- * Button type
102
- */
103
- type: {
104
- type: String,
105
- default: ButtonType.button,
106
- validator: (value: ButtonType) =>
107
- Object.values(ButtonType).includes(value),
108
- },
109
36
  toggle: {
110
37
  type: Boolean,
111
38
  default: false,
@@ -151,12 +78,12 @@ export function useGroupProps(
151
78
  const localValue = localModifiers?.value
152
79
  ? Array.isArray(localModifiers.value)
153
80
  ? localModifiers.value
154
- : [localModifiers.value]
81
+ : localModifiers.value.split(' ')
155
82
  : []
156
83
  const groupValue = group?.value.itemModifiers?.value
157
84
  ? Array.isArray(group.value.itemModifiers.value)
158
85
  ? group.value.itemModifiers.value
159
- : [group.value.itemModifiers.value]
86
+ : group.value.itemModifiers.value.split(' ')
160
87
  : []
161
88
  return [...localValue, ...groupValue]
162
89
  })
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  export default {
3
3
  name: 'VvCombobox',
4
- components: { VvDropdown, VvDropdownItem },
4
+ components: { VvDropdown, VvDropdownOption },
5
5
  }
6
6
  </script>
7
7
 
@@ -10,11 +10,12 @@
10
10
  import { VvComboboxProps, VvComboboxEvents } from '@/components/VvCombobox'
11
11
  import VvIcon from '@/components/VvIcon/VvIcon.vue'
12
12
  import VvDropdown from '@/components/VvDropdown/VvDropdown.vue'
13
- import VvDropdownItem from '@/components/VvDropdown/VvDropdownItem.vue'
13
+ import VvDropdownOption from '@/components/VvDropdown/VvDropdownOption.vue'
14
14
  import VvSelect from '@/components/VvSelect/VvSelect.vue'
15
15
  import VvBadge from '@/components/VvBadge/VvBadge.vue'
16
16
  import HintSlotFactory from '@/components/common/HintSlot'
17
17
  import type { Option } from '@/types/generic'
18
+ import { DropdownRole } from '@/constants'
18
19
 
19
20
  // props, emit and slots
20
21
  const props = defineProps(VvComboboxProps)
@@ -327,9 +328,14 @@
327
328
  <VvDropdown
328
329
  v-model="expanded"
329
330
  v-bind="dropdownProps"
330
- role="listbox"
331
+ :role="DropdownRole.listbox"
331
332
  >
332
- <template v-if="searchable" #before>
333
+ <template
334
+ v-if="searchable || $slots['dropdown::before']"
335
+ #before
336
+ >
337
+ <!-- @slot Slot before dropdown items -->
338
+ <slot name="dropdown::before" />
333
339
  <input
334
340
  v-if="searchable"
335
341
  v-show="expanded"
@@ -392,7 +398,7 @@
392
398
  !readonly &&
393
399
  !disabled
394
400
  "
395
- :aria-label="deselectLabel"
401
+ :aria-label="deselectActionLabel"
396
402
  @click.stop="onInput(option)"
397
403
  >
398
404
  <VvIcon name="close" />
@@ -416,48 +422,54 @@
416
422
  </div>
417
423
  </template>
418
424
  <template #items>
419
- <VvDropdownItem
420
- v-for="(option, index) in filteredOptions"
421
- :key="index"
422
- class="vv-dropdown-action"
423
- :tabindex="getOptionDisabled(option) ? -1 : 0"
424
- :class="{
425
- disabled: getOptionDisabled(option),
426
- selected: getOptionSelected(option),
427
- 'vv-dropdown-action--unselectable':
428
- unselectable && getOptionSelected(option),
429
- }"
430
- :aria-selected="getOptionSelected(option)"
431
- :aria-disabled="getOptionDisabled(option)"
432
- @click.passive="onInput(option)"
433
- >
434
- <!-- @slot Slot for option customization -->
435
- <slot
436
- name="option"
425
+ <template v-if="filteredOptions.length">
426
+ <VvDropdownOption
427
+ v-for="(option, index) in filteredOptions"
437
428
  v-bind="{
438
- option,
439
- selectedOptions,
440
- selected: getOptionSelected(option),
441
429
  disabled: getOptionDisabled(option),
430
+ selected: getOptionSelected(option),
431
+ unselectable,
432
+ deselectHintLabel,
433
+ selectHintLabel,
434
+ selectedHintLabel,
442
435
  }"
436
+ :key="index"
437
+ class="vv-dropdown-option"
438
+ @click.passive="onInput(option)"
443
439
  >
444
- {{ getOptionLabel(option) }}
445
- <span class="vv-dropdown-action__hint">
446
- <template v-if="getOptionSelected(option)">
447
- {{
448
- unselectable
449
- ? pressToDeselectLabel
450
- : selectedLabel
451
- }}
452
- </template>
453
- <template
454
- v-else-if="!getOptionDisabled(option)"
455
- >
456
- {{ pressToSelectLabel }}
457
- </template>
458
- </span>
440
+ <!-- @slot Slot for option customization -->
441
+ <slot
442
+ name="option"
443
+ v-bind="{
444
+ option,
445
+ selectedOptions,
446
+ selected: getOptionSelected(option),
447
+ disabled: getOptionDisabled(option),
448
+ }"
449
+ >
450
+ {{ getOptionLabel(option) }}
451
+ </slot>
452
+ </VvDropdownOption>
453
+ </template>
454
+ <VvDropdownOption
455
+ v-else-if="!options.length"
456
+ modifiers="inert"
457
+ >
458
+ <!-- @slot Slot for no options available -->
459
+ <slot name="no-options">
460
+ {{ noOptionsLabel }}
459
461
  </slot>
460
- </VvDropdownItem>
462
+ </VvDropdownOption>
463
+ <VvDropdownOption v-else modifiers="inert">
464
+ <!-- @slot Slot for no results available -->
465
+ <slot name="no-results">
466
+ {{ noResultsLabel }}
467
+ </slot>
468
+ </VvDropdownOption>
469
+ </template>
470
+ <template v-if="$slots['dropdown::after']" #after>
471
+ <!-- @slot Slot after dropdown items -->
472
+ <slot name="dropdown::after" />
461
473
  </template>
462
474
  </VvDropdown>
463
475
  </div>
@@ -14,6 +14,7 @@ import {
14
14
  UnselectableProps,
15
15
  IdNameProps,
16
16
  DropdownProps,
17
+ LabelProps,
17
18
  } from '@/props'
18
19
 
19
20
  export const VvComboboxEvents = [
@@ -38,6 +39,7 @@ export const VvComboboxProps = {
38
39
  ...FloatingLabelProps,
39
40
  ...UnselectableProps,
40
41
  ...DropdownProps,
42
+ ...LabelProps,
41
43
  /**
42
44
  * modelValue can be a string, number, boolean, object or array of string, number, boolean, object
43
45
  */
@@ -45,30 +47,30 @@ export const VvComboboxProps = {
45
47
  type: [String, Number, Boolean, Object, Array],
46
48
  default: undefined,
47
49
  },
48
- /**
49
- * Select input label
50
- */
51
- label: String,
52
50
  /**
53
51
  * Label for no search results
54
52
  */
55
53
  noResultsLabel: { type: String, default: 'No results' },
54
+ /**
55
+ * Label for no options available
56
+ */
57
+ noOptionsLabel: { type: String, default: 'No options available' },
56
58
  /**
57
59
  * Label for selected option hint
58
60
  */
59
- selectedLabel: { type: String, default: 'Selected' },
61
+ selectedHintLabel: { type: String, default: 'Selected' },
60
62
  /**
61
- * Label for deselect button
63
+ * Label for deselect action button
62
64
  */
63
- deselectLabel: { type: String, default: 'Deselect' },
65
+ deselectActionLabel: { type: String, default: 'Deselect' },
64
66
  /**
65
67
  * Label for select option hint
66
68
  */
67
- pressToSelectLabel: { type: String, default: 'Press enter to select' },
69
+ selectHintLabel: { type: String, default: 'Press enter to select' },
68
70
  /**
69
71
  * Label for deselected option hint
70
72
  */
71
- pressToDeselectLabel: { type: String, default: 'Press enter to remove' },
73
+ deselectHintLabel: { type: String, default: 'Press enter to remove' },
72
74
  /**
73
75
  * Select input placeholder
74
76
  */