@volverjs/ui-vue 0.0.10-beta.5 → 0.0.10-beta.51

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 (496) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +148 -51
  3. package/auto-imports.d.ts +25 -12
  4. package/bin/icons.cjs +1 -1
  5. package/bin/icons.js +28 -20
  6. package/dist/Volver.d.ts +11 -11
  7. package/dist/components/VvAccordion/VvAccordion.es.js +192 -104
  8. package/dist/components/VvAccordion/VvAccordion.umd.js +1 -1
  9. package/dist/components/VvAccordion/VvAccordion.vue.d.ts +29 -10
  10. package/dist/components/VvAccordion/index.d.ts +8 -9
  11. package/dist/components/VvAccordionGroup/VvAccordionGroup.es.js +485 -206
  12. package/dist/components/VvAccordionGroup/VvAccordionGroup.umd.js +1 -1
  13. package/dist/components/VvAccordionGroup/VvAccordionGroup.vue.d.ts +61 -18
  14. package/dist/components/VvAccordionGroup/index.d.ts +16 -8
  15. package/dist/components/VvAction/VvAction.es.js +84 -33
  16. package/dist/components/VvAction/VvAction.umd.js +1 -1
  17. package/dist/components/VvAction/VvAction.vue.d.ts +61 -28
  18. package/dist/components/VvAction/index.d.ts +26 -10
  19. package/dist/components/VvAlert/VvAlert.es.js +350 -318
  20. package/dist/components/VvAlert/VvAlert.umd.js +1 -1
  21. package/dist/components/VvAlert/VvAlert.vue.d.ts +25 -17
  22. package/dist/components/VvAlert/index.d.ts +20 -11
  23. package/dist/components/VvAlertGroup/VvAlertGroup.es.js +388 -327
  24. package/dist/components/VvAlertGroup/VvAlertGroup.umd.js +1 -1
  25. package/dist/components/VvAlertGroup/VvAlertGroup.vue.d.ts +22 -17
  26. package/dist/components/VvAlertGroup/index.d.ts +10 -18
  27. package/dist/components/VvAvatar/VvAvatar.es.js +66 -28
  28. package/dist/components/VvAvatar/VvAvatar.umd.js +1 -1
  29. package/dist/components/VvAvatar/VvAvatar.vue.d.ts +13 -5
  30. package/dist/components/VvAvatar/index.d.ts +4 -1
  31. package/dist/components/VvAvatarGroup/VvAvatarGroup.es.js +147 -74
  32. package/dist/components/VvAvatarGroup/VvAvatarGroup.umd.js +1 -1
  33. package/dist/components/VvAvatarGroup/VvAvatarGroup.vue.d.ts +17 -10
  34. package/dist/components/VvAvatarGroup/index.d.ts +6 -3
  35. package/dist/components/VvBadge/VvBadge.es.js +78 -34
  36. package/dist/components/VvBadge/VvBadge.umd.js +1 -1
  37. package/dist/components/VvBadge/VvBadge.vue.d.ts +13 -5
  38. package/dist/components/VvBadge/index.d.ts +4 -1
  39. package/dist/components/VvBreadcrumb/VvBreadcrumb.es.js +294 -83
  40. package/dist/components/VvBreadcrumb/VvBreadcrumb.umd.js +1 -1
  41. package/dist/components/VvBreadcrumb/VvBreadcrumb.vue.d.ts +28 -8
  42. package/dist/components/VvBreadcrumb/index.d.ts +6 -10
  43. package/dist/components/VvButton/VvButton.es.js +510 -488
  44. package/dist/components/VvButton/VvButton.umd.js +1 -1
  45. package/dist/components/VvButton/VvButton.vue.d.ts +97 -45
  46. package/dist/components/VvButton/index.d.ts +52 -30
  47. package/dist/components/VvButtonGroup/VvButtonGroup.es.js +95 -45
  48. package/dist/components/VvButtonGroup/VvButtonGroup.umd.js +1 -1
  49. package/dist/components/VvButtonGroup/VvButtonGroup.vue.d.ts +35 -17
  50. package/dist/components/VvButtonGroup/index.d.ts +13 -4
  51. package/dist/components/VvCard/VvCard.es.js +87 -42
  52. package/dist/components/VvCard/VvCard.umd.js +1 -1
  53. package/dist/components/VvCard/VvCard.vue.d.ts +13 -5
  54. package/dist/components/VvCard/index.d.ts +4 -1
  55. package/dist/components/VvCheckbox/VvCheckbox.es.js +177 -136
  56. package/dist/components/VvCheckbox/VvCheckbox.umd.js +1 -1
  57. package/dist/components/VvCheckbox/VvCheckbox.vue.d.ts +105 -35
  58. package/dist/components/VvCheckbox/index.d.ts +52 -19
  59. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.es.js +408 -322
  60. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.umd.js +1 -1
  61. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.vue.d.ts +103 -34
  62. package/dist/components/VvCheckboxGroup/index.d.ts +45 -12
  63. package/dist/components/VvCombobox/VvCombobox.es.js +1963 -1639
  64. package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
  65. package/dist/components/VvCombobox/VvCombobox.vue.d.ts +260 -672
  66. package/dist/components/VvCombobox/index.d.ts +385 -135
  67. package/dist/components/VvDialog/VvDialog.es.js +177 -297
  68. package/dist/components/VvDialog/VvDialog.umd.js +1 -1
  69. package/dist/components/VvDialog/VvDialog.vue.d.ts +23 -7
  70. package/dist/components/VvDialog/index.d.ts +12 -0
  71. package/dist/components/VvDropdown/VvDropdown.es.js +172 -102
  72. package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
  73. package/dist/components/VvDropdown/VvDropdown.vue.d.ts +110 -315
  74. package/dist/components/VvDropdown/VvDropdownAction.vue.d.ts +77 -28
  75. package/dist/components/VvDropdown/VvDropdownItem.vue.d.ts +13 -1
  76. package/dist/components/VvDropdown/VvDropdownOptgroup.vue.d.ts +13 -5
  77. package/dist/components/VvDropdown/VvDropdownOption.vue.d.ts +38 -10
  78. package/dist/components/VvDropdown/index.d.ts +52 -118
  79. package/dist/components/VvDropdownAction/VvDropdownAction.es.js +165 -60
  80. package/dist/components/VvDropdownAction/VvDropdownAction.umd.js +1 -1
  81. package/dist/components/VvDropdownItem/VvDropdownItem.es.js +337 -10
  82. package/dist/components/VvDropdownItem/VvDropdownItem.umd.js +1 -1
  83. package/dist/components/VvDropdownOptgroup/VvDropdownOptgroup.es.js +63 -20
  84. package/dist/components/VvDropdownOptgroup/VvDropdownOptgroup.umd.js +1 -1
  85. package/dist/components/VvDropdownOption/VvDropdownOption.es.js +188 -80
  86. package/dist/components/VvDropdownOption/VvDropdownOption.umd.js +1 -1
  87. package/dist/components/VvIcon/VvIcon.es.js +24 -102
  88. package/dist/components/VvIcon/VvIcon.umd.js +1 -1
  89. package/dist/components/VvIcon/VvIcon.vue.d.ts +4 -68
  90. package/dist/components/VvIcon/index.d.ts +33 -48
  91. package/dist/components/VvInputFile/VvInputFile.es.js +1777 -0
  92. package/dist/components/VvInputFile/VvInputFile.umd.js +1 -0
  93. package/dist/components/VvInputFile/VvInputFile.vue.d.ts +317 -0
  94. package/dist/components/VvInputFile/index.d.ts +193 -0
  95. package/dist/components/VvInputText/VvInputClearAction.d.ts +16 -10
  96. package/dist/components/VvInputText/VvInputPasswordAction.d.ts +20 -14
  97. package/dist/components/VvInputText/VvInputStepAction.d.ts +11 -7
  98. package/dist/components/VvInputText/VvInputText.es.js +1495 -548
  99. package/dist/components/VvInputText/VvInputText.umd.js +1 -1
  100. package/dist/components/VvInputText/VvInputText.vue.d.ts +216 -68
  101. package/dist/components/VvInputText/index.d.ts +101 -31
  102. package/dist/components/VvNav/VvNav.es.js +155 -75
  103. package/dist/components/VvNav/VvNav.umd.js +1 -1
  104. package/dist/components/VvNav/VvNav.vue.d.ts +32 -11
  105. package/dist/components/VvNav/VvNavItem.vue.d.ts +1 -1
  106. package/dist/components/VvNav/VvNavSeparator.vue.d.ts +1 -1
  107. package/dist/components/VvNav/index.d.ts +5 -2
  108. package/dist/components/VvNavItem/VvNavItem.es.js +100 -39
  109. package/dist/components/VvNavItem/VvNavItem.umd.js +1 -1
  110. package/dist/components/VvProgress/VvProgress.es.js +73 -27
  111. package/dist/components/VvProgress/VvProgress.umd.js +1 -1
  112. package/dist/components/VvProgress/VvProgress.vue.d.ts +13 -6
  113. package/dist/components/VvProgress/index.d.ts +4 -1
  114. package/dist/components/VvRadio/VvRadio.es.js +175 -135
  115. package/dist/components/VvRadio/VvRadio.umd.js +1 -1
  116. package/dist/components/VvRadio/VvRadio.vue.d.ts +103 -33
  117. package/dist/components/VvRadio/index.d.ts +50 -17
  118. package/dist/components/VvRadioGroup/VvRadioGroup.es.js +406 -321
  119. package/dist/components/VvRadioGroup/VvRadioGroup.umd.js +1 -1
  120. package/dist/components/VvRadioGroup/VvRadioGroup.vue.d.ts +103 -34
  121. package/dist/components/VvRadioGroup/index.d.ts +45 -12
  122. package/dist/components/VvSelect/VvSelect.es.js +677 -611
  123. package/dist/components/VvSelect/VvSelect.umd.js +1 -1
  124. package/dist/components/VvSelect/VvSelect.vue.d.ts +107 -199
  125. package/dist/components/VvSelect/index.d.ts +196 -16
  126. package/dist/components/VvTab/VvTab.es.js +230 -110
  127. package/dist/components/VvTab/VvTab.umd.js +1 -1
  128. package/dist/components/VvTab/VvTab.vue.d.ts +34 -12
  129. package/dist/components/VvTab/index.d.ts +6 -3
  130. package/dist/components/VvTextarea/VvTextarea.es.js +278 -255
  131. package/dist/components/VvTextarea/VvTextarea.umd.js +1 -1
  132. package/dist/components/VvTextarea/VvTextarea.vue.d.ts +159 -54
  133. package/dist/components/VvTextarea/index.d.ts +69 -20
  134. package/dist/components/VvTooltip/VvTooltip.es.js +83 -30
  135. package/dist/components/VvTooltip/VvTooltip.umd.js +1 -1
  136. package/dist/components/VvTooltip/VvTooltip.vue.d.ts +16 -9
  137. package/dist/components/VvTooltip/index.d.ts +5 -2
  138. package/dist/components/common/HintSlot.d.ts +8 -9
  139. package/dist/components/index.d.ts +10 -0
  140. package/dist/components/index.es.js +4303 -2228
  141. package/dist/components/index.umd.js +1 -1
  142. package/dist/composables/alert/useAlerInject.d.ts +4 -0
  143. package/dist/composables/alert/useAlert.d.ts +71 -6
  144. package/dist/composables/alert/{useProvideAlert.d.ts → useAlertProvide.d.ts} +1 -1
  145. package/dist/composables/dropdown/useDropdownContextmenu.d.ts +18 -0
  146. package/dist/composables/dropdown/useDropdownInject.d.ts +12 -0
  147. package/dist/composables/dropdown/{useProvideDropdown.d.ts → useDropdownProvide.d.ts} +6 -7
  148. package/dist/composables/dropdown/useDropdownVirtualElement.d.ts +17 -0
  149. package/dist/composables/group/useGroupStateInject.d.ts +9 -0
  150. package/dist/composables/group/useGroupStateProvide.d.ts +6 -0
  151. package/dist/composables/index.d.ts +3 -0
  152. package/dist/composables/index.es.js +178 -6
  153. package/dist/composables/index.umd.js +1 -1
  154. package/dist/composables/useBlurhash.d.ts +7 -0
  155. package/dist/composables/useComponentFocus.d.ts +2 -2
  156. package/dist/composables/useComponentIcon.d.ts +9 -8
  157. package/dist/composables/useOptions.d.ts +5 -5
  158. package/dist/composables/usePersistence.d.ts +3 -0
  159. package/dist/composables/useUniqueId.d.ts +2 -2
  160. package/dist/composables/useVolver.d.ts +1 -1
  161. package/dist/constants.d.ts +35 -33
  162. package/dist/directives/index.d.ts +3 -5
  163. package/dist/directives/index.es.js +247 -82
  164. package/dist/directives/index.umd.js +1 -1
  165. package/dist/directives/v-contextmenu.es.js +137 -31
  166. package/dist/directives/v-contextmenu.umd.js +1 -1
  167. package/dist/directives/v-tooltip.es.js +101 -39
  168. package/dist/directives/v-tooltip.umd.js +1 -1
  169. package/dist/icons.d.ts +17 -17
  170. package/dist/icons.es.js +516 -516
  171. package/dist/icons.umd.js +1 -1
  172. package/dist/index.d.ts +3 -1
  173. package/dist/index.es.js +74 -6
  174. package/dist/index.umd.js +1 -1
  175. package/dist/props/index.d.ts +288 -198
  176. package/dist/resolvers/unplugin.d.ts +6 -1
  177. package/dist/resolvers/unplugin.es.js +87 -10
  178. package/dist/resolvers/unplugin.umd.js +1 -1
  179. package/dist/stories/Accordion/Accordion.settings.d.ts +2 -57
  180. package/dist/stories/AccordionGroup/AccordionGroup.settings.d.ts +2 -66
  181. package/dist/stories/AccordionGroup/AccordionGroup.stories.d.ts +2 -127
  182. package/dist/stories/AccordionGroup/AccordionGroupSlots.stories.d.ts +1304 -538
  183. package/dist/stories/Alert/Alert.settings.d.ts +2 -109
  184. package/dist/stories/AlertGroup/AlertGroup.settings.d.ts +2 -85
  185. package/dist/stories/AlertGroup/AlertGroupWithComposable.stories.d.ts +1 -1
  186. package/dist/stories/AvatarGroup/AvatarGroup.settings.d.ts +2 -38
  187. package/dist/stories/Badge/Badge.settings.d.ts +2 -26
  188. package/dist/stories/Badge/Badge.test.d.ts +1 -1
  189. package/dist/stories/Blurhash/BlurhashComposable.stories.d.ts +4 -0
  190. package/dist/stories/Breadcrumb/Breadcrumb.settings.d.ts +2 -18
  191. package/dist/stories/Breadcrumb/Breadcrumb.test.d.ts +1 -1
  192. package/dist/stories/Button/Button.settings.d.ts +2 -194
  193. package/dist/stories/ButtonGroup/ButtonGroup.settings.d.ts +2 -40
  194. package/dist/stories/Card/Card.settings.d.ts +2 -63
  195. package/dist/stories/Checkbox/Checkbox.settings.d.ts +2 -132
  196. package/dist/stories/CheckboxGroup/CheckboxGroup.settings.d.ts +1 -141
  197. package/dist/stories/Combobox/Combobox.settings.d.ts +2 -609
  198. package/dist/stories/Combobox/Combobox.stories.d.ts +1 -0
  199. package/dist/stories/Combobox/ComboboxMultiple.stories.d.ts +1 -0
  200. package/dist/stories/Dialog/Dialog.settings.d.ts +2 -47
  201. package/dist/stories/Dialog/DialogModifiers.stories.d.ts +8 -0
  202. package/dist/stories/Dropdown/Dropdown.settings.d.ts +2 -205
  203. package/dist/stories/Icon/Icon.settings.d.ts +3 -68
  204. package/dist/stories/InputFile/InputFile.settings.d.ts +6 -0
  205. package/dist/stories/InputFile/InputFile.stories.d.ts +13 -0
  206. package/dist/stories/InputFile/InputFileDropArea.stories.d.ts +9 -0
  207. package/dist/stories/InputFile/InputFileIconPosition.stories.d.ts +8 -0
  208. package/dist/stories/InputFile/InputFileSlots.stories.d.ts +7 -0
  209. package/dist/stories/InputText/InputText.settings.d.ts +2 -438
  210. package/dist/stories/Nav/Nav.settings.d.ts +2 -10
  211. package/dist/stories/Progress/Progress.settings.d.ts +2 -27
  212. package/dist/stories/Radio/Radio.settings.d.ts +1 -110
  213. package/dist/stories/RadioGroup/RadioGroup.settings.d.ts +1 -141
  214. package/dist/stories/Select/Select.settings.d.ts +2 -246
  215. package/dist/stories/Select/Select.stories.d.ts +1 -0
  216. package/dist/stories/Tab/Tab.settings.d.ts +2 -15
  217. package/dist/stories/Textarea/Textarea.settings.d.ts +2 -287
  218. package/dist/stories/argTypes.d.ts +27 -866
  219. package/dist/test/expect.d.ts +1 -2
  220. package/dist/test/options.d.ts +1 -1
  221. package/dist/test/sleep.d.ts +1 -1
  222. package/dist/types/alert.d.ts +9 -7
  223. package/dist/types/blurhash.d.ts +12 -0
  224. package/dist/types/floating-ui.d.ts +1 -1
  225. package/dist/types/generic.d.ts +1 -2
  226. package/dist/types/group.d.ts +37 -15
  227. package/dist/types/index.d.ts +7 -0
  228. package/dist/types/input-file.d.ts +9 -0
  229. package/dist/types/nav.d.ts +2 -2
  230. package/dist/utils/DomUtilities.d.ts +1 -0
  231. package/dist/utils/ObjectUtilities.d.ts +8 -9
  232. package/dist/workers/blurhash.d.ts +1 -0
  233. package/package.json +238 -246
  234. package/src/Volver.ts +251 -246
  235. package/src/assets/icons/detailed.json +1 -1
  236. package/src/assets/icons/normal.json +1 -1
  237. package/src/assets/icons/simple.json +1 -1
  238. package/src/components/VvAccordion/VvAccordion.vue +163 -100
  239. package/src/components/VvAccordion/index.ts +65 -80
  240. package/src/components/VvAccordionGroup/VvAccordionGroup.vue +224 -106
  241. package/src/components/VvAccordionGroup/index.ts +42 -42
  242. package/src/components/VvAction/VvAction.vue +144 -130
  243. package/src/components/VvAlert/VvAlert.vue +72 -70
  244. package/src/components/VvAlert/index.ts +149 -147
  245. package/src/components/VvAlertGroup/VvAlertGroup.vue +57 -56
  246. package/src/components/VvAlertGroup/index.ts +102 -118
  247. package/src/components/VvAvatar/VvAvatar.vue +20 -14
  248. package/src/components/VvAvatar/index.ts +5 -5
  249. package/src/components/VvAvatarGroup/VvAvatarGroup.vue +58 -53
  250. package/src/components/VvAvatarGroup/index.ts +21 -21
  251. package/src/components/VvBadge/VvBadge.vue +15 -14
  252. package/src/components/VvBadge/index.ts +2 -2
  253. package/src/components/VvBreadcrumb/VvBreadcrumb.vue +50 -48
  254. package/src/components/VvBreadcrumb/index.ts +3 -9
  255. package/src/components/VvButton/VvButton.vue +163 -152
  256. package/src/components/VvButton/index.ts +104 -111
  257. package/src/components/VvButtonGroup/VvButtonGroup.vue +73 -65
  258. package/src/components/VvButtonGroup/index.ts +23 -22
  259. package/src/components/VvCard/VvCard.vue +30 -30
  260. package/src/components/VvCard/index.ts +2 -2
  261. package/src/components/VvCheckbox/VvCheckbox.vue +186 -184
  262. package/src/components/VvCheckbox/index.ts +45 -45
  263. package/src/components/VvCheckboxGroup/VvCheckboxGroup.vue +88 -87
  264. package/src/components/VvCombobox/VvCombobox.vue +657 -619
  265. package/src/components/VvCombobox/index.ts +212 -168
  266. package/src/components/VvDialog/VvDialog.vue +139 -129
  267. package/src/components/VvDialog/index.ts +42 -36
  268. package/src/components/VvDropdown/VvDropdown.vue +466 -445
  269. package/src/components/VvDropdown/VvDropdownAction.vue +37 -39
  270. package/src/components/VvDropdown/VvDropdownItem.vue +30 -26
  271. package/src/components/VvDropdown/VvDropdownOptgroup.vue +13 -12
  272. package/src/components/VvDropdown/VvDropdownOption.vue +47 -64
  273. package/src/components/VvDropdown/index.ts +61 -27
  274. package/src/components/VvIcon/README.md +1 -1
  275. package/src/components/VvIcon/VvIcon.vue +133 -133
  276. package/src/components/VvIcon/index.ts +84 -97
  277. package/src/components/VvInputFile/VvInputFile.vue +413 -0
  278. package/src/components/VvInputFile/index.ts +143 -0
  279. package/src/components/VvInputText/VvInputClearAction.ts +51 -47
  280. package/src/components/VvInputText/VvInputPasswordAction.ts +66 -62
  281. package/src/components/VvInputText/VvInputStepAction.ts +43 -43
  282. package/src/components/VvInputText/VvInputText.vue +653 -516
  283. package/src/components/VvInputText/VvInputTextActions.ts +87 -87
  284. package/src/components/VvInputText/index.ts +201 -186
  285. package/src/components/VvNav/VvNav.vue +40 -36
  286. package/src/components/VvNav/VvNavItem.vue +12 -12
  287. package/src/components/VvNav/VvNavSeparator.vue +6 -6
  288. package/src/components/VvNav/index.ts +2 -2
  289. package/src/components/VvProgress/VvProgress.vue +27 -27
  290. package/src/components/VvProgress/index.ts +28 -28
  291. package/src/components/VvRadio/VvRadio.vue +115 -112
  292. package/src/components/VvRadio/index.ts +29 -29
  293. package/src/components/VvRadioGroup/VvRadioGroup.vue +91 -90
  294. package/src/components/VvSelect/VvSelect.vue +262 -241
  295. package/src/components/VvSelect/index.ts +88 -63
  296. package/src/components/VvTab/VvTab.vue +79 -69
  297. package/src/components/VvTab/index.ts +13 -13
  298. package/src/components/VvTextarea/VvTextarea.vue +218 -219
  299. package/src/components/VvTextarea/index.ts +35 -35
  300. package/src/components/VvTooltip/VvTooltip.vue +22 -16
  301. package/src/components/VvTooltip/index.ts +12 -12
  302. package/src/components/common/HintSlot.ts +151 -152
  303. package/src/components/index.ts +10 -0
  304. package/src/composables/alert/{useInjectAlert.ts → useAlerInject.ts} +1 -1
  305. package/src/composables/alert/useAlert.ts +76 -73
  306. package/src/composables/alert/{useProvideAlert.ts → useAlertProvide.ts} +12 -12
  307. package/src/composables/dropdown/useDropdownContextmenu.ts +22 -0
  308. package/src/composables/dropdown/{useInjectDropdown.ts → useDropdownInject.ts} +6 -6
  309. package/src/composables/dropdown/useDropdownProvide.ts +94 -0
  310. package/src/composables/dropdown/useDropdownVirtualElement.ts +53 -0
  311. package/src/composables/group/useGroupStateInject.ts +55 -0
  312. package/src/composables/group/useGroupStateProvide.ts +14 -0
  313. package/src/composables/index.ts +3 -0
  314. package/src/composables/useBlurhash.ts +68 -0
  315. package/src/composables/useComponentFocus.ts +9 -9
  316. package/src/composables/useComponentIcon.ts +36 -35
  317. package/src/composables/useDebouncedInput.ts +25 -25
  318. package/src/composables/useDefaults.ts +81 -80
  319. package/src/composables/useModifiers.ts +29 -29
  320. package/src/composables/useOptions.ts +51 -42
  321. package/src/composables/usePersistence.ts +74 -0
  322. package/src/composables/useTextCount.ts +46 -46
  323. package/src/composables/useUniqueId.ts +4 -4
  324. package/src/composables/useVolver.ts +1 -1
  325. package/src/constants.ts +98 -83
  326. package/src/directives/index.ts +3 -6
  327. package/src/directives/v-contextmenu.ts +26 -34
  328. package/src/directives/v-tooltip.ts +20 -11
  329. package/src/icons.ts +2 -2
  330. package/src/index.ts +6 -4
  331. package/src/props/index.ts +467 -383
  332. package/src/resolvers/unplugin.ts +154 -144
  333. package/src/shims.d.ts +4 -5
  334. package/src/stories/Accordion/Accordion.settings.ts +51 -50
  335. package/src/stories/Accordion/Accordion.stories.ts +21 -21
  336. package/src/stories/Accordion/Accordion.test.ts +56 -54
  337. package/src/stories/Accordion/AccordionSlots.stories.ts +13 -13
  338. package/src/stories/AccordionGroup/AccordionGroup.settings.ts +70 -67
  339. package/src/stories/AccordionGroup/AccordionGroup.stories.ts +41 -39
  340. package/src/stories/AccordionGroup/AccordionGroup.test.ts +49 -45
  341. package/src/stories/AccordionGroup/AccordionGroupSlots.stories.ts +36 -36
  342. package/src/stories/Alert/Alert.settings.ts +117 -116
  343. package/src/stories/Alert/Alert.stories.ts +30 -30
  344. package/src/stories/Alert/Alert.test.ts +78 -80
  345. package/src/stories/Alert/AlertModifiers.stories.ts +45 -45
  346. package/src/stories/Alert/AlertSlots.stories.ts +35 -35
  347. package/src/stories/AlertGroup/AlertGroup.settings.ts +107 -105
  348. package/src/stories/AlertGroup/AlertGroup.stories.ts +25 -25
  349. package/src/stories/AlertGroup/AlertGroup.test.ts +69 -71
  350. package/src/stories/AlertGroup/AlertGroupPosition.stories.ts +68 -68
  351. package/src/stories/AlertGroup/AlertGroupSlots.stories.ts +23 -23
  352. package/src/stories/AlertGroup/AlertGroupWithComposable.stories.ts +58 -58
  353. package/src/stories/Avatar/Avatar.settings.ts +29 -29
  354. package/src/stories/Avatar/Avatar.stories.ts +22 -22
  355. package/src/stories/Avatar/Avatar.test.ts +22 -24
  356. package/src/stories/Avatar/AvatarBadge.stories.ts +15 -15
  357. package/src/stories/Avatar/AvatarModifiers.stories.ts +60 -60
  358. package/src/stories/Avatar/AvatarSlots.stories.ts +17 -17
  359. package/src/stories/AvatarGroup/AvatarGroup.settings.ts +54 -53
  360. package/src/stories/AvatarGroup/AvatarGroup.stories.ts +17 -17
  361. package/src/stories/AvatarGroup/AvatarGroup.test.ts +24 -26
  362. package/src/stories/AvatarGroup/AvatarGroupModifiers.stories.ts +15 -15
  363. package/src/stories/AvatarGroup/AvatarGroupSlotDefault.stories.ts +17 -17
  364. package/src/stories/Badge/Badge.settings.ts +21 -20
  365. package/src/stories/Badge/Badge.stories.ts +24 -24
  366. package/src/stories/Badge/Badge.test.ts +8 -8
  367. package/src/stories/Badge/BadgeSlots.stories.ts +10 -10
  368. package/src/stories/Blurhash/BlurhashComposable.stories.ts +116 -0
  369. package/src/stories/Breadcrumb/Breadcrumb.settings.ts +35 -34
  370. package/src/stories/Breadcrumb/Breadcrumb.stories.ts +23 -23
  371. package/src/stories/Breadcrumb/Breadcrumb.test.ts +44 -43
  372. package/src/stories/Breadcrumb/BreadcrumbSlots.stories.ts +19 -19
  373. package/src/stories/Button/Button.settings.ts +147 -151
  374. package/src/stories/Button/Button.stories.ts +19 -19
  375. package/src/stories/Button/Button.test.ts +41 -42
  376. package/src/stories/Button/ButtonIcon.stories.ts +42 -42
  377. package/src/stories/Button/ButtonLink.stories.ts +24 -24
  378. package/src/stories/Button/ButtonLoading.stories.ts +22 -22
  379. package/src/stories/Button/ButtonModifiers.stories.ts +91 -91
  380. package/src/stories/Button/ButtonSlots.stories.ts +47 -47
  381. package/src/stories/Button/ButtonState.stories.ts +23 -23
  382. package/src/stories/Button/ButtonToggle.stories.ts +30 -30
  383. package/src/stories/ButtonGroup/ButtonGroup.settings.ts +33 -24
  384. package/src/stories/ButtonGroup/ButtonGroup.stories.ts +19 -19
  385. package/src/stories/ButtonGroup/ButtonGroup.test.ts +23 -26
  386. package/src/stories/ButtonGroup/ButtonGroupModifiers.stories.ts +20 -20
  387. package/src/stories/ButtonGroup/ButtonGroupSlots.stories.ts +17 -17
  388. package/src/stories/ButtonGroup/ButtonGroupToggle.stories.ts +22 -22
  389. package/src/stories/Card/Card.settings.ts +49 -48
  390. package/src/stories/Card/Card.stories.ts +22 -22
  391. package/src/stories/Card/Card.test.ts +14 -16
  392. package/src/stories/Card/CardSlots.stories.ts +42 -42
  393. package/src/stories/Checkbox/Checkbox.settings.ts +36 -35
  394. package/src/stories/Checkbox/Checkbox.stories.ts +57 -57
  395. package/src/stories/Checkbox/Checkbox.test.ts +63 -66
  396. package/src/stories/Checkbox/CheckboxBinary.stories.ts +18 -18
  397. package/src/stories/Checkbox/CheckboxSlots.stories.ts +15 -15
  398. package/src/stories/CheckboxGroup/CheckboxGroup.settings.ts +9 -9
  399. package/src/stories/CheckboxGroup/CheckboxGroup.stories.ts +50 -50
  400. package/src/stories/CheckboxGroup/CheckboxGroup.test.ts +64 -68
  401. package/src/stories/CheckboxGroup/CheckboxGroupOptions.stories.ts +34 -34
  402. package/src/stories/CheckboxGroup/CheckboxGroupSlots.stories.ts +23 -23
  403. package/src/stories/Combobox/Combobox.settings.ts +408 -385
  404. package/src/stories/Combobox/Combobox.stories.ts +116 -107
  405. package/src/stories/Combobox/Combobox.test.ts +92 -92
  406. package/src/stories/Combobox/ComboboxIconPosition.stories.ts +25 -24
  407. package/src/stories/Combobox/ComboboxMultiple.stories.ts +32 -22
  408. package/src/stories/Combobox/ComboboxOptions.stories.ts +81 -84
  409. package/src/stories/Combobox/ComboboxSlots.stories.ts +55 -54
  410. package/src/stories/Dialog/Dialog.settings.ts +49 -40
  411. package/src/stories/Dialog/Dialog.stories.ts +28 -28
  412. package/src/stories/Dialog/Dialog.test.ts +49 -54
  413. package/src/stories/Dialog/DialogModifiers.stories.ts +42 -0
  414. package/src/stories/Dialog/DialogSlots.stories.ts +20 -20
  415. package/src/stories/Dropdown/Dropdown.settings.ts +62 -61
  416. package/src/stories/Dropdown/Dropdown.stories.ts +60 -60
  417. package/src/stories/Dropdown/Dropdown.test.ts +9 -13
  418. package/src/stories/Dropdown/DropdownContextmenuDirective.stories.ts +18 -19
  419. package/src/stories/Dropdown/DropdownMultilevel.stories.ts +19 -19
  420. package/src/stories/Dropdown/DropdownSlots.stories.ts +51 -51
  421. package/src/stories/Icon/Icon.settings.ts +66 -65
  422. package/src/stories/Icon/Icon.stories.ts +29 -30
  423. package/src/stories/Icon/IconsCollection.stories.ts +24 -24
  424. package/src/stories/InputFile/InputFile.settings.ts +37 -0
  425. package/src/stories/InputFile/InputFile.stories.ts +97 -0
  426. package/src/stories/InputFile/InputFileDropArea.stories.ts +56 -0
  427. package/src/stories/InputFile/InputFileIconPosition.stories.ts +43 -0
  428. package/src/stories/InputFile/InputFileSlots.stories.ts +33 -0
  429. package/src/stories/InputText/InputText.settings.ts +248 -246
  430. package/src/stories/InputText/InputText.stories.ts +68 -68
  431. package/src/stories/InputText/InputText.test.ts +119 -122
  432. package/src/stories/InputText/InputTextIconPosition.stories.ts +24 -24
  433. package/src/stories/InputText/InputTextLength.stories.ts +33 -33
  434. package/src/stories/InputText/InputTextMask.stories.ts +91 -91
  435. package/src/stories/InputText/InputTextMinMax.stories.ts +30 -30
  436. package/src/stories/InputText/InputTextSlots.stories.ts +20 -20
  437. package/src/stories/InputText/InputTextType.stories.ts +70 -70
  438. package/src/stories/Nav/Nav.settings.ts +27 -27
  439. package/src/stories/Nav/Nav.stories.ts +18 -18
  440. package/src/stories/Nav/Nav.test.ts +10 -12
  441. package/src/stories/Nav/NavModifiers.stories.ts +25 -25
  442. package/src/stories/Progress/Progress.settings.ts +24 -23
  443. package/src/stories/Progress/Progress.stories.ts +23 -23
  444. package/src/stories/Progress/Progress.test.ts +5 -5
  445. package/src/stories/Radio/Radio.settings.ts +9 -9
  446. package/src/stories/Radio/Radio.stories.ts +47 -47
  447. package/src/stories/Radio/Radio.test.ts +54 -57
  448. package/src/stories/Radio/RadioSlots.stories.ts +15 -15
  449. package/src/stories/RadioGroup/RadioGroup.settings.ts +9 -9
  450. package/src/stories/RadioGroup/RadioGroup.stories.ts +51 -52
  451. package/src/stories/RadioGroup/RadioGroup.test.ts +64 -68
  452. package/src/stories/RadioGroup/RadioGroupOptions.stories.ts +35 -35
  453. package/src/stories/RadioGroup/RadioGroupSlots.stories.ts +23 -23
  454. package/src/stories/Select/Select.settings.ts +72 -71
  455. package/src/stories/Select/Select.stories.ts +75 -66
  456. package/src/stories/Select/Select.test.ts +67 -70
  457. package/src/stories/Select/SelectIconPosition.stories.ts +27 -26
  458. package/src/stories/Select/SelectOptions.stories.ts +55 -55
  459. package/src/stories/Select/SelectSlots.stories.ts +21 -20
  460. package/src/stories/Tab/Tab.settings.ts +34 -34
  461. package/src/stories/Tab/Tab.stories.ts +16 -16
  462. package/src/stories/Tab/Tab.test.ts +17 -19
  463. package/src/stories/Textarea/Textarea.settings.ts +80 -78
  464. package/src/stories/Textarea/Textarea.stories.ts +63 -63
  465. package/src/stories/Textarea/Textarea.test.ts +70 -73
  466. package/src/stories/Textarea/TextareaLength.stories.ts +33 -33
  467. package/src/stories/Textarea/TextareaSlots.stories.ts +20 -20
  468. package/src/stories/Textarea/TextareatIconPosition.stories.ts +24 -24
  469. package/src/stories/Tooltip/Tooltip.settings.ts +16 -17
  470. package/src/stories/Tooltip/Tooltip.stories.ts +18 -18
  471. package/src/stories/Tooltip/Tooltip.test.ts +53 -54
  472. package/src/stories/Tooltip/TooltipDirective.stories.ts +37 -37
  473. package/src/stories/argTypes.ts +506 -505
  474. package/src/test/expect.ts +74 -79
  475. package/src/test/options.ts +17 -16
  476. package/src/test/sleep.ts +3 -2
  477. package/src/test/types.d.ts +12 -12
  478. package/src/types/alert.ts +21 -17
  479. package/src/types/blurhash.ts +21 -0
  480. package/src/types/floating-ui.ts +1 -1
  481. package/src/types/generic.ts +2 -3
  482. package/src/types/group.ts +35 -27
  483. package/src/types/index.ts +7 -0
  484. package/src/types/input-file.ts +10 -0
  485. package/src/types/nav.ts +13 -14
  486. package/src/utils/DomUtilities.ts +15 -0
  487. package/src/utils/ObjectUtilities.ts +192 -188
  488. package/src/workers/blurhash.ts +9 -0
  489. package/dist/composables/alert/useInjectAlert.d.ts +0 -9
  490. package/dist/composables/dropdown/useInjectDropdown.d.ts +0 -32
  491. package/dist/composables/group/useInjectedGroupState.d.ts +0 -10
  492. package/dist/composables/group/useProvideGroupState.d.ts +0 -6
  493. package/src/composables/dropdown/useProvideDropdown.ts +0 -94
  494. package/src/composables/group/useInjectedGroupState.ts +0 -51
  495. package/src/composables/group/useProvideGroupState.ts +0 -20
  496. /package/src/assets/icons/normal/{dulicate.svg → duplicate.svg} +0 -0
@@ -1,625 +1,663 @@
1
- <script lang="ts">
2
- export default {
3
- name: 'VvCombobox',
4
- components: {
5
- VvDropdown,
6
- VvDropdownOption,
7
- VvDropdownOptgroup,
8
- VvButton,
9
- },
10
- }
1
+ <script setup lang="ts" generic="T extends string | Option">
2
+ import type { Ref } from 'vue'
3
+ import { toRefs } from 'vue'
4
+ import type { Option } from '../../types/generic'
5
+ import { DropdownRole } from '../../constants'
6
+ import HintSlotFactory from '../common/HintSlot'
7
+ import VvBadge from '../VvBadge/VvBadge.vue'
8
+ import VvButton from '../VvButton/VvButton.vue'
9
+ import VvDropdown from '../VvDropdown/VvDropdown.vue'
10
+ import VvDropdownOptgroup from '../VvDropdown/VvDropdownOptgroup.vue'
11
+ import VvDropdownOption from '../VvDropdown/VvDropdownOption.vue'
12
+ import VvIcon from '../VvIcon/VvIcon.vue'
13
+ import VvSelect from '../VvSelect/VvSelect.vue'
14
+ import { type VvComboboxEvents, useVvComboboxProps } from '.'
15
+
16
+ // props, emit and slots
17
+ // WARNING: This is a provisiaonal implementation, it may change in the future
18
+ const props = defineProps(useVvComboboxProps<T>())
19
+ const emit = defineEmits<VvComboboxEvents>()
20
+ const slots = useSlots()
21
+
22
+ // props merged with volver defaults (now only for labels)
23
+ const VvComboboxProps = useVvComboboxProps<T>()
24
+ const propsDefaults = useDefaults<typeof VvComboboxProps>(
25
+ 'VvCombobox',
26
+ VvComboboxProps,
27
+ props,
28
+ )
29
+
30
+ // template ref
31
+ const inputEl: Ref<HTMLElement | null> = ref(null)
32
+ const inputSearchEl: Ref<HTMLElement | null> = ref(null)
33
+ const wrapperEl: Ref<HTMLElement | null> = ref(null)
34
+ const dropdownEl = ref<typeof VvDropdown>()
35
+
36
+ // hint slot
37
+ const {
38
+ HintSlot,
39
+ hasHintLabelOrSlot,
40
+ hasInvalidLabelOrSlot,
41
+ hintSlotScope,
42
+ } = HintSlotFactory(propsDefaults, slots)
43
+
44
+ // focus
45
+ const { focused } = useComponentFocus(inputEl, emit)
46
+ const { focused: focusedWithin } = useFocusWithin(wrapperEl)
47
+
48
+ watch(focused, (newValue) => {
49
+ if (!props.autoOpen) {
50
+ return
51
+ }
52
+ if (newValue && !expanded.value) {
53
+ expand()
54
+ return
55
+ }
56
+ if (!newValue && expanded.value && !focusedWithin.value) {
57
+ collapse()
58
+ }
59
+ })
60
+
61
+ watch(focusedWithin, (newValue) => {
62
+ if (!focused.value && !newValue && expanded.value) {
63
+ collapse()
64
+ }
65
+ })
66
+
67
+ // search
68
+ const searchText = ref('')
69
+ const debouncedSearchText = refDebounced(
70
+ searchText,
71
+ computed(() => Number(props.debounceSearch)),
72
+ )
73
+ watch(debouncedSearchText, () => {
74
+ emit('update:search', debouncedSearchText.value)
75
+ // DEPRECATED: Must be removed in the future
76
+ // eslint-disable-next-line vue/custom-event-name-casing
77
+ emit('change:search', debouncedSearchText.value)
78
+ })
79
+
80
+ // expanded
81
+ const expanded = ref(false)
82
+ function toggleExpanded() {
83
+ if (isDisabledOrReadonly.value)
84
+ return
85
+ expanded.value = !expanded.value
86
+ }
87
+ function expand() {
88
+ if (isDisabledOrReadonly.value || expanded.value)
89
+ return
90
+ expanded.value = true
91
+ }
92
+ function collapse() {
93
+ if (isDisabledOrReadonly.value || !expanded.value)
94
+ return
95
+ expanded.value = false
96
+ }
97
+ function onAfterExpand() {
98
+ if (propsDefaults.value.searchable) {
99
+ if (inputSearchEl.value) {
100
+ inputSearchEl.value.focus({
101
+ preventScroll: true,
102
+ })
103
+ }
104
+ }
105
+ }
106
+ function onAfterCollapse() {
107
+ if (propsDefaults.value.searchable) {
108
+ searchText.value = ''
109
+ }
110
+ }
111
+
112
+ // group
113
+ function isGroup(option: T) {
114
+ if (typeof option === 'string') {
115
+ return false
116
+ }
117
+ return option.options?.length
118
+ }
119
+
120
+ // data
121
+ const {
122
+ id,
123
+ icon,
124
+ iconPosition,
125
+ modifiers,
126
+ disabled,
127
+ required,
128
+ readonly,
129
+ loading,
130
+ valid,
131
+ invalid,
132
+ floating,
133
+ } = toRefs(props)
134
+ const hasId = useUniqueId(id)
135
+ const hasHintId = computed(() => `${hasId.value}-hint`)
136
+ const hasDropdownId = computed(() => `${hasId.value}-dropdown`)
137
+ const hasSearchId = computed(() => `${hasId.value}-search`)
138
+ const hasLabelId = computed(() => `${hasId.value}-label`)
139
+
140
+ // tabindex
141
+ const isDisabledOrReadonly = computed(() => props.disabled || props.readonly)
142
+ const hasTabindex = computed(() => {
143
+ return isDisabledOrReadonly.value ? -1 : props.tabindex
144
+ })
145
+
146
+ // modelValue
147
+ const localModelValue = computed({
148
+ get: () => {
149
+ if (Array.isArray(props.modelValue)) {
150
+ return props.modelValue
151
+ }
152
+ return props.modelValue !== undefined && props.modelValue !== null ? [props.modelValue] : []
153
+ },
154
+ set: (value: unknown[]) => {
155
+ emit('update:modelValue', props.multiple || Array.isArray(props.modelValue) ? value : value.pop())
156
+ },
157
+ })
158
+ const sizeOfModelValue = computed(() => localModelValue.value.length)
159
+ const isDirty = computed(() => sizeOfModelValue.value > 0)
160
+ const hasMaxValues = computed(() => {
161
+ if (!props.multiple) {
162
+ return 1
163
+ }
164
+ if (props.maxValues === undefined) {
165
+ return Infinity
166
+ }
167
+ return Number(props.maxValues)
168
+ })
169
+ const isUnselectable = computed(() => {
170
+ if (isDisabledOrReadonly.value) {
171
+ return false
172
+ }
173
+ // DEPRECATED: Must be removed in the future
174
+ if (!props.unselectable) {
175
+ return false
176
+ }
177
+ return Number(props.minValues) === 0 || (sizeOfModelValue.value > Number(props.minValues))
178
+ })
179
+ const isSelectable = computed(() => {
180
+ if (isDisabledOrReadonly.value) {
181
+ return false
182
+ }
183
+ if (!props.multiple) {
184
+ return true
185
+ }
186
+ return sizeOfModelValue.value < hasMaxValues.value
187
+ })
188
+
189
+ // loading
190
+ const localLoading = ref(false)
191
+ const isLoading = computed(() => localLoading.value || loading.value)
192
+
193
+ // icons
194
+ const { hasIconBefore, hasIconAfter } = useComponentIcon(icon, iconPosition)
195
+
196
+ // styles
197
+ const bemCssClasses = useModifiers(
198
+ 'vv-select',
199
+ modifiers,
200
+ computed(() => ({
201
+ 'disabled': disabled.value,
202
+ 'required': required.value,
203
+ 'loading': isLoading.value,
204
+ 'readonly': readonly.value,
205
+ 'icon-before': hasIconBefore.value !== undefined,
206
+ 'icon-after': hasIconAfter.value !== undefined,
207
+ 'valid': valid.value,
208
+ 'invalid': invalid.value,
209
+ 'dirty': isDirty.value,
210
+ 'focus': focused.value || focusedWithin.value || expanded.value,
211
+ 'floating': floating.value,
212
+ 'badges': props.badges,
213
+ })),
214
+ )
215
+
216
+ // options
217
+ const {
218
+ getOptionLabel,
219
+ getOptionValue,
220
+ getOptionGrouped,
221
+ isOptionDisabled,
222
+ } = useOptions(props)
223
+
224
+ function isOptionDisabledOrNotSelectable(option: T) {
225
+ return isOptionDisabled(option) || (!isSelectable.value && !isOptionSelected(option))
226
+ }
227
+
228
+ const filteredOptions = computedAsync(async () => {
229
+ if (propsDefaults.value.searchFunction) {
230
+ localLoading.value = true
231
+ const toReturn = await Promise.resolve(
232
+ propsDefaults.value.searchFunction(
233
+ debouncedSearchText.value,
234
+ props.options,
235
+ ),
236
+ )
237
+ localLoading.value = false
238
+ return toReturn
239
+ }
240
+ return props.options?.filter((option) => {
241
+ return getOptionLabel(option)
242
+ .toLowerCase()
243
+ .includes(debouncedSearchText.value.toLowerCase().trim())
244
+ })
245
+ })
246
+
247
+ /**
248
+ * Check if an option is selected
249
+ * @param {T} option
250
+ */
251
+ function isOptionSelected(option: T) {
252
+ const optionValue = getOptionValue(option)
253
+ if (typeof optionValue === 'object') {
254
+ return localModelValue.value.some((item) => {
255
+ if (typeof item === 'object') {
256
+ return JSON.stringify(item) === JSON.stringify(optionValue)
257
+ }
258
+ return false
259
+ })
260
+ }
261
+ return localModelValue.value.includes(optionValue)
262
+ }
263
+
264
+ /**
265
+ * Compute the label to show to the user
266
+ * Check if is multiple mode, object mode or "string" mode
267
+ */
268
+ const selectedOptions = computed(() => {
269
+ const options = props.options.reduce<T[]>(
270
+ (acc, value) => {
271
+ if (isGroup(value)) {
272
+ return [...acc, ...getOptionGrouped(value)]
273
+ }
274
+ return [...acc, value]
275
+ },
276
+ [],
277
+ )
278
+ return options.filter((option) => {
279
+ return isOptionSelected(option)
280
+ })
281
+ })
282
+
283
+ const hasValue = computed(() => {
284
+ return selectedOptions.value
285
+ .map((option: T) => getOptionLabel(option))
286
+ .join(props.separator)
287
+ })
288
+
289
+ /**
290
+ * Function triggered on click on input
291
+ */
292
+ function onClickInput() {
293
+ props.autoOpen ? expand() : toggleExpanded()
294
+ }
295
+
296
+ /**
297
+ * Function triggered on option click
298
+ * @param option {T} option value
299
+ */
300
+ function onInput(option: T) {
301
+ const isSelected = isOptionSelected(option)
302
+ const optionValue = getOptionValue(option)
303
+ if (isSelected && isUnselectable.value) {
304
+ localModelValue.value = localModelValue.value.filter((item) => {
305
+ if (typeof optionValue === 'object' && typeof item === 'object') {
306
+ return JSON.stringify(item) !== JSON.stringify(optionValue)
307
+ }
308
+ return item !== optionValue
309
+ })
310
+ }
311
+ else if (!isSelected && isSelectable.value) {
312
+ if (!props.multiple) {
313
+ localModelValue.value = []
314
+ }
315
+ localModelValue.value = [...localModelValue.value, optionValue]
316
+ }
317
+ if (!props.multiple && !props.keepOpen) {
318
+ collapse()
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Auto select the first option if autoOpen is enabled
324
+ */
325
+ watch(
326
+ () => props.options,
327
+ (newValue) => {
328
+ if (newValue?.length && props.autoselectFirst && !isDirty.value) {
329
+ onInput(newValue[0])
330
+ }
331
+ },
332
+ { immediate: true },
333
+ )
334
+
335
+ const selectProps = computed(() => ({
336
+ id: hasId.value,
337
+ name: props.name,
338
+ tabindex: hasTabindex.value,
339
+ valid: valid.value,
340
+ validLabel: propsDefaults.value.validLabel,
341
+ invalid: invalid.value,
342
+ invalidLabel: propsDefaults.value.invalidLabel,
343
+ hintLabel: propsDefaults.value.hintLabel,
344
+ loading: isLoading.value,
345
+ loadingLabel: propsDefaults.value.loadingLabel,
346
+ disabled: disabled.value,
347
+ readonly: readonly.value,
348
+ modifiers: propsDefaults.value.modifiers,
349
+ options: propsDefaults.value.options,
350
+ labelKey: propsDefaults.value.labelKey,
351
+ valueKey: propsDefaults.value.valueKey,
352
+ icon: propsDefaults.value.icon,
353
+ iconPosition: propsDefaults.value.iconPosition,
354
+ floating: propsDefaults.value.floating,
355
+ unselectable: isUnselectable.value,
356
+ autoselectFirst: propsDefaults.value.autoselectFirst,
357
+ multiple: propsDefaults.value.multiple,
358
+ label: propsDefaults.value.label,
359
+ placeholder: propsDefaults.value.placeholder,
360
+ modelValue: props.modelValue,
361
+ }))
362
+
363
+ const dropdownProps = computed(() => ({
364
+ id: hasDropdownId.value,
365
+ reference: wrapperEl.value,
366
+ placement: propsDefaults.value.placement,
367
+ strategy: propsDefaults.value.strategy,
368
+ transitionName: propsDefaults.value.transitionName,
369
+ offset: propsDefaults.value.offset,
370
+ shift: propsDefaults.value.shift,
371
+ flip: propsDefaults.value.flip,
372
+ autoPlacement: propsDefaults.value.autoPlacement,
373
+ arrow: propsDefaults.value.arrow,
374
+ autofocusFirst: propsDefaults.value.searchable
375
+ ? true
376
+ : propsDefaults.value.autofocusFirst,
377
+ triggerWidth: propsDefaults.value.triggerWidth,
378
+ modifiers: propsDefaults.value.dropdownModifiers,
379
+ }))
380
+
381
+ // slots
382
+ const slotProps = computed(() => ({
383
+ valid: props.valid,
384
+ invalid: props.invalid,
385
+ modelValue: props.modelValue,
386
+ }))
387
+
388
+ // keyboard
389
+ onKeyStroke(
390
+ [' ', 'Enter'],
391
+ (e) => {
392
+ if (props.autoOpen) {
393
+ return
394
+ }
395
+ if (!expanded.value && focused.value) {
396
+ e.preventDefault()
397
+ e.stopImmediatePropagation()
398
+ toggleExpanded()
399
+ }
400
+ },
401
+ { target: inputEl },
402
+ )
11
403
  </script>
12
404
 
13
- <script setup lang="ts">
14
- import type { Ref } from 'vue'
15
- import { toRefs } from 'vue'
16
- import { VvComboboxProps, VvComboboxEvents } from '.'
17
- import VvIcon from '../VvIcon/VvIcon.vue'
18
- import VvDropdown from '../VvDropdown/VvDropdown.vue'
19
- import VvDropdownOption from '../VvDropdown/VvDropdownOption.vue'
20
- import VvDropdownOptgroup from '../VvDropdown/VvDropdownOptgroup.vue'
21
- import VvSelect from '../VvSelect/VvSelect.vue'
22
- import VvBadge from '../VvBadge/VvBadge.vue'
23
- import VvButton from '../VvButton/VvButton.vue'
24
- import HintSlotFactory from '../common/HintSlot'
25
- import type { Option } from '../../types/generic'
26
- import { DropdownRole } from '../../constants'
27
-
28
- // props, emit and slots
29
- const props = defineProps(VvComboboxProps)
30
- const emit = defineEmits(VvComboboxEvents)
31
- const slots = useSlots()
32
-
33
- // props merged with volver defaults (now only for labels)
34
- const propsDefaults = useDefaults<typeof VvComboboxProps>(
35
- 'VvCombobox',
36
- VvComboboxProps,
37
- props,
38
- )
39
-
40
- // Grouped options
41
- const isGroup = (option: string | Option) => {
42
- if (typeof option === 'string') {
43
- return false
44
- }
45
- return option.options && option.options.length > 0
46
- }
47
-
48
- // hint slot
49
- const {
50
- HintSlot,
51
- hasHintLabelOrSlot,
52
- hasInvalidLabelOrSlot,
53
- hintSlotScope,
54
- } = HintSlotFactory(propsDefaults, slots)
55
-
56
- // template ref
57
- const inputEl: Ref<HTMLElement | null> = ref(null)
58
- const inputSearchEl: Ref<HTMLElement | null> = ref(null)
59
- const wrapperEl: Ref<HTMLElement | null> = ref(null)
60
-
61
- // focus
62
- const { focused } = useComponentFocus(inputEl, emit)
63
- const { focused: focusedWithin } = useFocusWithin(wrapperEl)
64
-
65
- watch(focused, (newValue) => {
66
- if (!props.autoOpen) {
67
- return
68
- }
69
- if (newValue && !expanded.value) {
70
- expand()
71
- return
72
- }
73
- if (!newValue && expanded.value && !focusedWithin.value) {
74
- collapse()
75
- }
76
- })
77
-
78
- watch(focusedWithin, (newValue) => {
79
- if (!focused.value && !newValue && expanded.value) {
80
- collapse()
81
- }
82
- })
83
-
84
- // search
85
- const searchText = ref('')
86
- const debouncedSearchText = refDebounced(
87
- searchText,
88
- computed(() => Number(props.debounceSearch)),
89
- )
90
- watch(debouncedSearchText, () =>
91
- emit('change:search', debouncedSearchText.value),
92
- )
93
-
94
- // expanded
95
- const expanded = ref(false)
96
- const toggleExpanded = () => {
97
- if (props.disabled || props.readonly) return
98
- expanded.value = !expanded.value
99
- }
100
- const expand = () => {
101
- if (props.disabled || props.readonly || expanded.value) return
102
- expanded.value = true
103
- }
104
- const collapse = () => {
105
- if (props.disabled || props.readonly || !expanded.value) return
106
- expanded.value = false
107
- }
108
- const onAfterExpand = () => {
109
- if (propsDefaults.value.searchable) {
110
- if (inputSearchEl.value) {
111
- inputSearchEl.value.focus({
112
- preventScroll: true,
113
- })
114
- }
115
- }
116
- }
117
- const onAfterCollapse = () => {
118
- if (propsDefaults.value.searchable) {
119
- searchText.value = ''
120
- }
121
- }
122
-
123
- // data
124
- const {
125
- id,
126
- icon,
127
- iconPosition,
128
- modifiers,
129
- disabled,
130
- readonly,
131
- loading,
132
- valid,
133
- invalid,
134
- floating,
135
- } = toRefs(props)
136
- const hasId = useUniqueId(id)
137
- const hasHintId = computed(() => `${hasId.value}-hint`)
138
- const hasDropdownId = computed(() => `${hasId.value}-dropdown`)
139
- const hasSearchId = computed(() => `${hasId.value}-search`)
140
- const hasLabelId = computed(() => `${hasId.value}-label`)
141
-
142
- // loading
143
- const localLoading = ref(false)
144
- const isLoading = computed(() => localLoading.value || loading.value)
145
-
146
- // ref
147
- const dropdownEl = ref()
148
-
149
- // icons
150
- const { hasIcon, hasIconBefore, hasIconAfter } = useComponentIcon(
151
- icon,
152
- iconPosition,
153
- )
154
-
155
- // dirty
156
- const isDirty = computed(() => !isEmpty(props.modelValue))
157
-
158
- // tabindex
159
- const hasTabindex = computed(() => {
160
- return disabled.value || readonly.value ? -1 : props.tabindex
161
- })
162
-
163
- // styles
164
- const bemCssClasses = useModifiers(
165
- 'vv-select',
166
- modifiers,
167
- computed(() => ({
168
- disabled: disabled.value,
169
- loading: isLoading.value,
170
- readonly: readonly.value,
171
- 'icon-before': Boolean(hasIconBefore.value),
172
- 'icon-after': Boolean(hasIconAfter.value),
173
- valid: valid.value,
174
- invalid: invalid.value,
175
- dirty: isDirty.value,
176
- focus: focused.value,
177
- floating: floating.value,
178
- badges: props.badges,
179
- })),
180
- )
181
-
182
- const {
183
- getOptionLabel,
184
- getOptionValue,
185
- getOptionGrouped,
186
- isOptionDisabled,
187
- } = useOptions(props)
188
-
189
- // options filtered by search text
190
- const filteredOptions = computedAsync(async () => {
191
- if (propsDefaults.value.searchFunction) {
192
- localLoading.value = true
193
- const toReturn = await Promise.resolve(
194
- propsDefaults.value.searchFunction(
195
- debouncedSearchText.value,
196
- props.options,
197
- ),
198
- )
199
- localLoading.value = false
200
- return toReturn
201
- }
202
- return props.options?.filter((option) => {
203
- return getOptionLabel(option)
204
- .toLowerCase()
205
- .includes(debouncedSearchText.value.toLowerCase().trim())
206
- })
207
- })
208
-
209
- /**
210
- * Check if an option exist into modelValue array (multiple) or is equal to modelValue (single)
211
- * @param {String | Option} option
212
- */
213
- function isOptionSelected(option: string | Option) {
214
- if (Array.isArray(props.modelValue)) {
215
- // check if contain whole option or option value
216
- return (
217
- contains(option, props.modelValue) ||
218
- contains(getOptionValue(option), props.modelValue)
219
- )
220
- }
221
- // check if modelValue is equal to option or option value
222
- return (
223
- equals(option, props.modelValue) ||
224
- equals(getOptionValue(option), props.modelValue)
225
- )
226
- }
227
-
228
- /**
229
- * Compute the label to show to the user
230
- * Check if is multiple mode, object mode or "string" mode
231
- */
232
- const selectedOptions = computed(() => {
233
- const options = props.options.reduce<Array<Option | string>>(
234
- (acc, value) => {
235
- if (isGroup(value)) {
236
- return [...acc, ...getOptionGrouped(value)]
237
- }
238
- return [...acc, value]
239
- },
240
- [],
241
- )
242
- return options.filter((option) => {
243
- return isOptionSelected(option)
244
- })
245
- })
246
-
247
- const hasValue = computed(() => {
248
- return selectedOptions.value
249
- .map((option) => getOptionLabel(option))
250
- .join(props.separator)
251
- })
252
-
253
- /**
254
- * Function triggered on click on input
255
- */
256
- const onClickInput = () => {
257
- props.autoOpen ? expand() : toggleExpanded()
258
- }
259
-
260
- /**
261
- * Function triggered on input of checkbox or radio (multple or single mode)
262
- * @param event on input event (checkbox or radio input)
263
- */
264
- const onInput = (option: string | Option) => {
265
- if (props.disabled || props.readonly) {
266
- return
267
- }
268
-
269
- // get option value
270
- const value = getOptionValue(option)
271
- let toReturn: string | string[] | Option | Option[] | undefined = value
272
-
273
- // check multiple prop, override value with array and remove or add the value
274
- if (props.multiple) {
275
- // check max-values prop and block check new values
276
- if (Array.isArray(props.modelValue)) {
277
- const maxValues = Number(props.maxValues)
278
- if (
279
- props.maxValues !== undefined &&
280
- maxValues >= 0 &&
281
- props.modelValue?.length >= maxValues
282
- ) {
283
- if (!contains(value, props.modelValue)) {
284
- // maxValues reached
285
- return
286
- }
287
- }
288
- toReturn = contains(value, props.modelValue)
289
- ? removeFromList(value, props.modelValue)
290
- : [...props.modelValue, value]
291
- } else {
292
- toReturn = [value as Option]
293
- }
294
- } else {
295
- if (!props.keepOpen) {
296
- collapse()
297
- }
298
- if (Array.isArray(props.modelValue)) {
299
- if (props.unselectable && props.modelValue.includes(value)) {
300
- toReturn = []
301
- } else {
302
- toReturn = [value]
303
- }
304
- } else if (props.unselectable && value === props.modelValue) {
305
- toReturn = undefined
306
- }
307
- }
308
- emit('update:modelValue', toReturn)
309
- }
310
-
311
- const selectProps = computed(() => ({
312
- id: hasId.value,
313
- name: props.name,
314
- tabindex: hasTabindex.value,
315
- valid: valid.value,
316
- validLabel: propsDefaults.value.validLabel,
317
- invalid: invalid.value,
318
- invalidLabel: propsDefaults.value.invalidLabel,
319
- hintLabel: propsDefaults.value.hintLabel,
320
- loading: isLoading.value,
321
- loadingLabel: propsDefaults.value.loadingLabel,
322
- disabled: disabled.value,
323
- readonly: readonly.value,
324
- modifiers: propsDefaults.value.modifiers,
325
- options: propsDefaults.value.options,
326
- labelKey: propsDefaults.value.labelKey,
327
- valueKey: propsDefaults.value.valueKey,
328
- icon: propsDefaults.value.icon,
329
- iconPosition: propsDefaults.value.iconPosition,
330
- floating: propsDefaults.value.floating,
331
- unselectable: propsDefaults.value.unselectable,
332
- multiple: propsDefaults.value.multiple,
333
- label: propsDefaults.value.label,
334
- placeholder: propsDefaults.value.placeholder,
335
- modelValue: props.modelValue,
336
- }))
337
-
338
- const dropdownProps = computed(() => ({
339
- id: hasDropdownId.value,
340
- reference: wrapperEl.value,
341
- placement: propsDefaults.value.placement,
342
- strategy: propsDefaults.value.strategy,
343
- transitionName: propsDefaults.value.transitionName,
344
- offset: propsDefaults.value.offset,
345
- shift: propsDefaults.value.shift,
346
- flip: propsDefaults.value.flip,
347
- autoPlacement: propsDefaults.value.autoPlacement,
348
- arrow: propsDefaults.value.arrow,
349
- autofocusFirst: propsDefaults.value.searchable
350
- ? true
351
- : propsDefaults.value.autofocusFirst,
352
- triggerWidth: propsDefaults.value.triggerWidth,
353
- modifiers: propsDefaults.value.dropdownModifiers,
354
- }))
355
-
356
- // slots
357
- const slotProps = computed(() => ({
358
- valid: props.valid,
359
- invalid: props.invalid,
360
- modelValue: props.modelValue,
361
- }))
362
-
363
- // computed
364
- onKeyStroke(
365
- [' ', 'Enter'],
366
- (e) => {
367
- if (props.autoOpen) {
368
- return
369
- }
370
- if (!expanded.value && focused.value) {
371
- e.preventDefault()
372
- e.stopImmediatePropagation()
373
- toggleExpanded()
374
- }
375
- },
376
- { target: inputEl },
377
- )
405
+ <script lang="ts">
406
+ export default {
407
+ name: 'VvCombobox',
408
+ components: {
409
+ VvDropdown,
410
+ VvDropdownOption,
411
+ VvDropdownOptgroup,
412
+ VvButton,
413
+ },
414
+ }
378
415
  </script>
379
416
 
380
417
  <template>
381
- <div v-if="!native" :id="hasId" :class="bemCssClasses">
382
- <label
383
- v-if="label"
384
- :id="hasLabelId"
385
- :for="propsDefaults.searchable ? hasSearchId : undefined"
386
- >
387
- {{ label }}
388
- </label>
389
- <div ref="wrapperEl" class="vv-select__wrapper">
390
- <VvDropdown
391
- ref="dropdownEl"
392
- v-model="expanded"
393
- v-bind="dropdownProps"
394
- :role="DropdownRole.listbox"
395
- @after-expand="onAfterExpand"
396
- @after-collapse="onAfterCollapse"
397
- >
398
- <template
399
- v-if="
400
- propsDefaults.searchable || $slots['dropdown::before']
401
- "
402
- #before
403
- >
404
- <!-- @slot Slot before dropdown items -->
405
- <slot name="dropdown::before" />
406
- <input
407
- v-if="propsDefaults.searchable && !disabled"
408
- :id="hasSearchId"
409
- ref="inputSearchEl"
410
- v-model="searchText"
411
- aria-autocomplete="list"
412
- :aria-controls="hasDropdownId"
413
- autocomplete="off"
414
- spellcheck="false"
415
- type="search"
416
- class="vv-dropdown__search"
417
- :placeholder="propsDefaults.searchPlaceholder"
418
- />
419
- </template>
420
- <template #default="{ aria }">
421
- <div v-if="$slots.before" class="vv-select__input-before">
422
- <!-- @slot Slot before input -->
423
- <slot name="before" v-bind="slotProps" />
424
- </div>
425
- <div class="vv-select__inner">
426
- <VvIcon
427
- v-if="hasIconBefore"
428
- class="vv-select__icon"
429
- v-bind="hasIcon"
430
- />
431
- <div
432
- ref="inputEl"
433
- v-bind="aria"
434
- class="vv-select__input"
435
- role="combobox"
436
- :aria-expanded="expanded"
437
- :aria-labelledby="hasLabelId"
438
- :aria-describedby="
439
- hasHintLabelOrSlot ? hasHintId : undefined
440
- "
441
- :aria-errormessage="
442
- hasInvalidLabelOrSlot ? hasHintId : undefined
443
- "
444
- :tabindex="hasTabindex"
445
- @click.passive="onClickInput"
446
- >
447
- <!-- @slot Slot for value customization -->
448
- <slot
449
- name="value"
450
- v-bind="{ selectedOptions, onInput }"
451
- >
452
- <template v-if="hasValue">
453
- <div
454
- v-if="!badges"
455
- class="vv-select__value"
456
- >
457
- {{ hasValue }}
458
- </div>
459
- <VvBadge
460
- v-for="(
461
- option, index
462
- ) in selectedOptions"
463
- v-else
464
- :key="index"
465
- :modifiers="badgeModifiers"
466
- class="vv-select__badge"
467
- >
468
- {{ getOptionLabel(option) }}
469
- <button
470
- v-if="
471
- unselectable &&
472
- !readonly &&
473
- !disabled
474
- "
475
- :aria-label="
476
- propsDefaults.deselectActionLabel
477
- "
478
- type="button"
479
- @click.stop="onInput(option)"
480
- >
481
- <VvIcon name="close" />
482
- </button>
483
- </VvBadge>
484
- </template>
485
- <template v-else>
486
- {{ placeholder }}
487
- </template>
488
- </slot>
489
- </div>
490
- <VvIcon
491
- v-if="hasIconAfter"
492
- class="vv-select__icon vv-select__icon-after"
493
- v-bind="hasIcon"
494
- />
495
- </div>
496
- <div v-if="$slots.after" class="vv-select__input-after">
497
- <!-- @slot Slot after input -->
498
- <slot name="after" v-bind="slotProps" />
499
- </div>
500
- </template>
501
- <template #items>
502
- <template v-if="!disabled && filteredOptions?.length">
503
- <template
504
- v-for="(option, index) in filteredOptions"
505
- :key="index"
506
- >
507
- <template v-if="isGroup(option)">
508
- <VvDropdownOptgroup
509
- :label="getOptionLabel(option)"
510
- />
511
- <VvDropdownOption
512
- v-for="(item, i) in getOptionGrouped(
513
- option,
514
- )"
515
- v-bind="{
516
- selected: isOptionSelected(item),
517
- disabled: isOptionDisabled(item),
518
- unselectable,
519
- deselectHintLabel:
520
- propsDefaults.deselectHintLabel,
521
- selectHintLabel:
522
- propsDefaults.selectHintLabel,
523
- selectedHintLabel:
524
- propsDefaults.selectedHintLabel,
525
- }"
526
- :key="i"
527
- class="vv-dropdown-option"
528
- @click.passive="onInput(item)"
529
- >
530
- <!-- @slot Slot for option customization -->
531
- <slot
532
- name="option"
533
- v-bind="{
534
- option,
535
- selectedOptions,
536
- selected: isOptionSelected(item),
537
- disabled: isOptionDisabled(item),
538
- }"
539
- >
540
- {{ getOptionLabel(item) }}
541
- </slot>
542
- </VvDropdownOption>
543
- </template>
544
- <VvDropdownOption
545
- v-else
546
- v-bind="{
547
- selected: isOptionSelected(option),
548
- disabled: isOptionDisabled(option),
549
- unselectable,
550
- deselectHintLabel:
551
- propsDefaults.deselectHintLabel,
552
- selectHintLabel:
553
- propsDefaults.selectHintLabel,
554
- selectedHintLabel:
555
- propsDefaults.selectedHintLabel,
556
- }"
557
- class="vv-dropdown-option"
558
- @click.passive="onInput(option)"
559
- >
560
- <!-- @slot Slot for option customization -->
561
- <slot
562
- name="option"
563
- v-bind="{
564
- option,
565
- selectedOptions,
566
- selected: isOptionSelected(option),
567
- disabled: isOptionDisabled(option),
568
- }"
569
- >
570
- {{ getOptionLabel(option) }}
571
- </slot>
572
- </VvDropdownOption>
573
- </template>
574
- </template>
575
- <VvDropdownOption
576
- v-else-if="!options.length"
577
- modifiers="inert"
578
- >
579
- <!-- @slot Slot for no options available -->
580
- <slot name="no-options">
581
- {{ propsDefaults.noOptionsLabel }}
582
- </slot>
583
- </VvDropdownOption>
584
- <VvDropdownOption v-else-if="!disabled" modifiers="inert">
585
- <!-- @slot Slot for no results available -->
586
- <slot name="no-results">
587
- {{ propsDefaults.noResultsLabel }}
588
- </slot>
589
- </VvDropdownOption>
590
- </template>
591
- <template #after>
592
- <!-- @slot Slot after dropdown items -->
593
- <slot name="dropdown::after">
594
- <!-- Close button if dropdown custom position is enabled and floating-ui disabled -->
595
- <VvButton
596
- v-if="dropdownEl?.customPosition"
597
- :label="propsDefaults.closeLabel"
598
- modifiers="secondary"
599
- @click="dropdownEl.hide()"
600
- />
601
- </slot>
602
- </template>
603
- </VvDropdown>
604
- </div>
605
- <HintSlot :id="hasHintId" class="vv-select__hint">
606
- <template v-if="$slots.hint" #hint>
607
- <slot name="hint" v-bind="hintSlotScope" />
608
- </template>
609
- <template v-if="$slots.loading" #loading>
610
- <slot name="loading" v-bind="hintSlotScope" />
611
- </template>
612
- <template v-if="$slots.valid" #valid>
613
- <slot name="valid" v-bind="hintSlotScope" />
614
- </template>
615
- <template v-if="$slots.invalid" #invalid>
616
- <slot name="invalid" v-bind="hintSlotScope" />
617
- </template>
618
- </HintSlot>
619
- </div>
620
- <VvSelect
621
- v-else
622
- v-bind="selectProps"
623
- @update:model-value="emit('update:modelValue', $event)"
624
- />
418
+ <div v-if="!native" :id="hasId" :class="bemCssClasses">
419
+ <label
420
+ v-if="label"
421
+ :id="hasLabelId"
422
+ :for="propsDefaults.searchable ? hasSearchId : undefined"
423
+ >
424
+ {{ label }}
425
+ </label>
426
+ <div ref="wrapperEl" class="vv-select__wrapper">
427
+ <VvDropdown
428
+ ref="dropdownEl"
429
+ v-model="expanded"
430
+ v-bind="dropdownProps"
431
+ :role="DropdownRole.listbox"
432
+ @after-expand="onAfterExpand"
433
+ @after-collapse="onAfterCollapse"
434
+ >
435
+ <template
436
+ v-if="
437
+ propsDefaults.searchable || $slots['dropdown::before']
438
+ "
439
+ #before
440
+ >
441
+ <!-- @slot Slot before dropdown items -->
442
+ <slot name="dropdown::before" />
443
+ <input
444
+ v-if="propsDefaults.searchable && !disabled"
445
+ :id="hasSearchId"
446
+ ref="inputSearchEl"
447
+ v-model="searchText"
448
+ aria-autocomplete="list"
449
+ :aria-controls="hasDropdownId"
450
+ autocomplete="off"
451
+ spellcheck="false"
452
+ type="search"
453
+ class="vv-dropdown__search"
454
+ :placeholder="propsDefaults.searchPlaceholder"
455
+ >
456
+ </template>
457
+ <template #default="{ aria }">
458
+ <div v-if="$slots.before" class="vv-select__input-before">
459
+ <!-- @slot Slot before input -->
460
+ <slot name="before" v-bind="slotProps" />
461
+ </div>
462
+ <div class="vv-select__inner">
463
+ <VvIcon
464
+ v-if="hasIconBefore"
465
+ v-bind="hasIconBefore"
466
+ class="vv-select__icon"
467
+ />
468
+ <div
469
+ ref="inputEl"
470
+ v-bind="aria"
471
+ class="vv-select__input"
472
+ role="combobox"
473
+ :aria-controls="hasDropdownId"
474
+ :aria-expanded="expanded"
475
+ :aria-labelledby="hasLabelId"
476
+ :aria-describedby="
477
+ hasHintLabelOrSlot ? hasHintId : undefined
478
+ "
479
+ :aria-errormessage="
480
+ hasInvalidLabelOrSlot ? hasHintId : undefined
481
+ "
482
+ :tabindex="hasTabindex"
483
+ @click.passive="onClickInput"
484
+ >
485
+ <!-- @slot Slot for value customization -->
486
+ <slot
487
+ name="value"
488
+ v-bind="{ selectedOptions, onInput }"
489
+ >
490
+ <template v-if="hasValue">
491
+ <div
492
+ v-if="!badges"
493
+ class="vv-select__value"
494
+ >
495
+ {{ hasValue }}
496
+ </div>
497
+ <VvBadge
498
+ v-for="(
499
+ option, index
500
+ ) in selectedOptions"
501
+ v-else
502
+ :key="index"
503
+ :modifiers="badgeModifiers"
504
+ class="vv-select__badge"
505
+ >
506
+ {{ getOptionLabel(option) }}
507
+ <button
508
+ v-if="
509
+ isUnselectable
510
+ "
511
+ :aria-label="
512
+ propsDefaults.deselectActionLabel
513
+ "
514
+ type="button"
515
+ @click.stop="onInput(option)"
516
+ >
517
+ <VvIcon name="close" />
518
+ </button>
519
+ </VvBadge>
520
+ </template>
521
+ <template v-else>
522
+ {{ placeholder }}
523
+ </template>
524
+ </slot>
525
+ </div>
526
+ <VvIcon
527
+ v-if="hasIconAfter"
528
+ v-bind="hasIconAfter"
529
+ class="vv-select__icon vv-select__icon-after"
530
+ />
531
+ </div>
532
+ <div v-if="$slots.after" class="vv-select__input-after">
533
+ <!-- @slot Slot after input -->
534
+ <slot name="after" v-bind="slotProps" />
535
+ </div>
536
+ </template>
537
+ <template #items>
538
+ <template v-if="!disabled && filteredOptions?.length">
539
+ <template
540
+ v-for="(option, index) in filteredOptions"
541
+ :key="index"
542
+ >
543
+ <template v-if="isGroup(option)">
544
+ <VvDropdownOptgroup
545
+ :label="getOptionLabel(option)"
546
+ />
547
+ <VvDropdownOption
548
+ v-for="(item, i) in getOptionGrouped(
549
+ option,
550
+ )"
551
+ v-bind="{
552
+ selected: isOptionSelected(item),
553
+ disabled: isOptionDisabledOrNotSelectable(item),
554
+ unselectable: isUnselectable,
555
+ deselectHintLabel:
556
+ propsDefaults.deselectHintLabel,
557
+ selectHintLabel:
558
+ propsDefaults.selectHintLabel,
559
+ selectedHintLabel:
560
+ propsDefaults.selectedHintLabel,
561
+ }"
562
+ :key="i"
563
+ class="vv-dropdown-option"
564
+ focus-on-hover
565
+ @click.passive="onInput(item)"
566
+ >
567
+ <!-- @slot Slot for option customization -->
568
+ <slot
569
+ name="option"
570
+ v-bind="{
571
+ option,
572
+ selectedOptions,
573
+ selected: isOptionSelected(item),
574
+ disabled: isOptionDisabledOrNotSelectable(item),
575
+ }"
576
+ >
577
+ {{ getOptionLabel(item) }}
578
+ </slot>
579
+ </VvDropdownOption>
580
+ </template>
581
+ <VvDropdownOption
582
+ v-else
583
+ v-bind="{
584
+ selected: isOptionSelected(option),
585
+ disabled: isOptionDisabledOrNotSelectable(option),
586
+ unselectable: isUnselectable,
587
+ deselectHintLabel:
588
+ propsDefaults.deselectHintLabel,
589
+ selectHintLabel:
590
+ propsDefaults.selectHintLabel,
591
+ selectedHintLabel:
592
+ propsDefaults.selectedHintLabel,
593
+ }"
594
+ class="vv-dropdown-option"
595
+ focus-on-hover
596
+ @click.passive="onInput(option)"
597
+ >
598
+ <!-- @slot Slot for option customization -->
599
+ <slot
600
+ name="option"
601
+ v-bind="{
602
+ option,
603
+ selectedOptions,
604
+ selected: isOptionSelected(option),
605
+ disabled: isOptionDisabledOrNotSelectable(option),
606
+ }"
607
+ >
608
+ {{ getOptionLabel(option) }}
609
+ </slot>
610
+ </VvDropdownOption>
611
+ </template>
612
+ </template>
613
+ <VvDropdownOption
614
+ v-else-if="!options.length"
615
+ modifiers="inert"
616
+ >
617
+ <!-- @slot Slot for no options available -->
618
+ <slot name="no-options">
619
+ {{ propsDefaults.noOptionsLabel }}
620
+ </slot>
621
+ </VvDropdownOption>
622
+ <VvDropdownOption v-else-if="!disabled" modifiers="inert">
623
+ <!-- @slot Slot for no results available -->
624
+ <slot name="no-results">
625
+ {{ propsDefaults.noResultsLabel }}
626
+ </slot>
627
+ </VvDropdownOption>
628
+ </template>
629
+ <template #after>
630
+ <!-- @slot Slot after dropdown items -->
631
+ <slot name="dropdown::after">
632
+ <!-- Close button if dropdown custom position is enabled and floating-ui disabled -->
633
+ <VvButton
634
+ v-if="dropdownEl?.customPosition"
635
+ :label="propsDefaults.closeLabel"
636
+ modifiers="secondary"
637
+ @click="dropdownEl.hide()"
638
+ />
639
+ </slot>
640
+ </template>
641
+ </VvDropdown>
642
+ </div>
643
+ <HintSlot :id="hasHintId" class="vv-select__hint">
644
+ <template v-if="$slots.hint" #hint>
645
+ <slot name="hint" v-bind="hintSlotScope" />
646
+ </template>
647
+ <template v-if="$slots.loading" #loading>
648
+ <slot name="loading" v-bind="hintSlotScope" />
649
+ </template>
650
+ <template v-if="$slots.valid" #valid>
651
+ <slot name="valid" v-bind="hintSlotScope" />
652
+ </template>
653
+ <template v-if="$slots.invalid" #invalid>
654
+ <slot name="invalid" v-bind="hintSlotScope" />
655
+ </template>
656
+ </HintSlot>
657
+ </div>
658
+ <VvSelect
659
+ v-else
660
+ v-bind="selectProps"
661
+ @update:model-value="emit('update:modelValue', $event)"
662
+ />
625
663
  </template>