@volverjs/ui-vue 0.0.10-beta.4 → 0.0.10-beta.40

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