@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,547 +1,669 @@
1
- <script lang="ts">
2
- export default {
3
- name: 'VvInputText',
4
- }
5
- </script>
6
-
7
1
  <script setup lang="ts">
8
- import type { InputHTMLAttributes } from 'vue'
9
- import { useIMask } from 'vue-imask'
10
- import HintSlotFactory from '../common/HintSlot'
11
- import VvIcon from '../VvIcon/VvIcon.vue'
12
- import VvInputTextActionsFactory from '../VvInputText/VvInputTextActions'
13
- import {
14
- VvInputTextEvents,
15
- VvInputTextProps,
16
- INPUT_TYPES,
17
- TYPES_ICON,
18
- } from '../VvInputText'
2
+ import type { InputHTMLAttributes } from 'vue'
3
+ import { useIMask } from 'vue-imask'
4
+ import HintSlotFactory from '../common/HintSlot'
5
+ import VvIcon from '../VvIcon/VvIcon.vue'
6
+ import { ACTION_ICONS } from '../VvIcon'
7
+ import VvInputTextActionsFactory from '../VvInputText/VvInputTextActions'
8
+ import VvDropdown from '../VvDropdown/VvDropdown.vue'
9
+ import VvDropdownOption from '../VvDropdown/VvDropdownOption.vue'
10
+ import {
11
+ VvInputTextEvents,
12
+ VvInputTextProps,
13
+ INPUT_TYPES,
14
+ } from '../VvInputText'
15
+
16
+ // props, emit, slots and attrs
17
+ const props = defineProps(VvInputTextProps)
18
+
19
+ const emit = defineEmits(VvInputTextEvents)
19
20
 
20
- // props, emit, slots and attrs
21
- const props = defineProps(VvInputTextProps)
22
- const emit = defineEmits(VvInputTextEvents)
23
- const slots = useSlots()
21
+ const slots = useSlots()
24
22
 
25
- // props merged with volver defaults (now only for labels)
26
- const propsDefaults = useDefaults<typeof VvInputTextProps>(
27
- 'VvInputText',
28
- VvInputTextProps,
29
- props,
30
- )
23
+ // props merged with volver defaults (now only for labels)
24
+ const propsDefaults = useDefaults<typeof VvInputTextProps>(
25
+ 'VvInputText',
26
+ VvInputTextProps,
27
+ props,
28
+ )
31
29
 
32
- // data
33
- const {
34
- id,
35
- icon,
36
- iconPosition,
37
- label,
38
- modelValue,
39
- count,
40
- valid,
41
- invalid,
42
- loading,
43
- debounce,
44
- maxlength,
45
- minlength,
46
- type,
47
- iMask,
48
- step,
49
- } = toRefs(props)
50
- const hasId = useUniqueId(id)
51
- const hasHintId = computed(() => `${hasId.value}-hint`)
52
- // BUG: https://www.samanthaming.com/tidbits/88-css-placeholder-shown/
53
- const inputTextPlaceholder = computed(() =>
54
- props.floating && isEmpty(props.placeholder) ? ' ' : props.placeholder,
55
- )
30
+ // data
31
+ const {
32
+ count,
33
+ debounce,
34
+ icon,
35
+ iconPosition,
36
+ iconRemoveSuggestion,
37
+ id,
38
+ invalid,
39
+ label,
40
+ loading,
41
+ maxlength,
42
+ minlength,
43
+ modelValue,
44
+ step,
45
+ storageKey,
46
+ storageType,
47
+ type,
48
+ valid,
49
+ } = toRefs(props)
50
+ const hasId = useUniqueId(id)
51
+ const hasHintId = computed(() => `${hasId.value}-hint`)
52
+ // BUG: https://www.samanthaming.com/tidbits/88-css-placeholder-shown/
53
+ const inputTextPlaceholder = computed(() =>
54
+ props.floating && isEmpty(props.placeholder) ? ' ' : props.placeholder,
55
+ )
56
56
 
57
- // template refs
58
- const maskReady = ref(false)
59
- const { el, mask, typed, masked, unmasked } = useIMask(
60
- computed(
61
- () =>
62
- iMask?.value ?? {
63
- mask: /./,
64
- },
65
- ),
66
- {
67
- emit,
68
- onAccept: () => {
69
- if (!maskReady.value) {
70
- return
71
- }
72
- emit('update:masked', masked.value)
73
- if (type.value === INPUT_TYPES.NUMBER) {
74
- if (masked.value === '') {
75
- if (
76
- localModelValue.value === null ||
77
- localModelValue.value === undefined
78
- ) {
79
- return
80
- }
81
- localModelValue.value = undefined
82
- return
83
- }
84
- if (typeof typed.value !== 'number') {
85
- localModelValue.value = Number(typed.value)
86
- return
87
- }
88
- localModelValue.value = typed.value
89
- return
90
- }
91
- if (type.value === INPUT_TYPES.DATE) {
92
- if (
93
- el.value instanceof HTMLInputElement &&
94
- el.value.type === 'date'
95
- ) {
96
- localModelValue.value = el.value.value
97
- return
98
- }
99
- let date = typed.value
100
- if (date === null || date === '') {
101
- if (!localModelValue.value) {
102
- return
103
- }
104
- localModelValue.value = ''
105
- return
106
- }
107
- if (!(date instanceof Date)) {
108
- date = new Date(date)
109
- }
110
- localModelValue.value = `${date.getFullYear()}-${(
111
- '0' +
112
- (date.getMonth() + 1)
113
- ).slice(-2)}-${('0' + date.getDate()).slice(-2)}`
114
- return
115
- }
116
- if (type.value === INPUT_TYPES.DATETIME_LOCAL) {
117
- if (
118
- el.value instanceof HTMLInputElement &&
119
- el.value.type === 'datetime-local'
120
- ) {
121
- localModelValue.value = el.value.value
122
- return
123
- }
124
- let date = typed.value
125
- if (date === null || date === '') {
126
- if (!localModelValue.value) {
127
- return
128
- }
129
- localModelValue.value = ''
130
- return
131
- }
132
- if (!(typed.value instanceof Date)) {
133
- date = new Date(date)
134
- }
135
- localModelValue.value = `${date.getFullYear()}-${(
136
- '0' +
137
- (date.getMonth() + 1)
138
- ).slice(-2)}-${('0' + date.getDate()).slice(-2)}T${(
139
- '0' + date.getHours()
140
- ).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`
141
- return
142
- }
143
- if (!localModelValue.value && !unmasked.value) {
144
- return
145
- }
146
- localModelValue.value = unmasked.value
147
- },
148
- },
149
- )
150
- onMounted(() => {
151
- if (mask.value) {
152
- maskReady.value = true
153
- typed.value = localModelValue.value ?? ''
154
- }
155
- })
156
- watch(
157
- () => props.modelValue,
158
- (newValue) => {
159
- if (mask.value) {
160
- typed.value =
161
- newValue && iMask?.value?.mask === Date
162
- ? new Date(newValue)
163
- : newValue ?? ''
164
- }
165
- },
166
- )
167
- watch(
168
- () => props.masked,
169
- (newValue) => {
170
- masked.value = newValue ?? ''
171
- },
172
- )
173
- const inputEl = el as Ref<HTMLInputElement>
174
- const innerEl = ref()
57
+ // debounce
58
+ const localModelValue = useDebouncedInput(
59
+ modelValue,
60
+ emit,
61
+ debounce?.value ?? 0,
62
+ )
175
63
 
176
- defineExpose({ $inner: innerEl })
64
+ // mask
65
+ const NEGATIVE_ZERO_REGEX = /^-0?[.,]?[0*]?$/
66
+ const maskReady = ref(false)
67
+ const { el, mask, typed, masked, unmasked } = useIMask(
68
+ computed(
69
+ () =>
70
+ props.iMask ?? {
71
+ mask: /./,
72
+ },
73
+ ),
74
+ {
75
+ emit,
76
+ onAccept: () => {
77
+ if (!maskReady.value) {
78
+ return
79
+ }
80
+ emit('update:masked', masked.value)
81
+ if (type.value === INPUT_TYPES.NUMBER) {
82
+ if (/^-$|^$/.test(unmasked.value)) {
83
+ if (
84
+ localModelValue.value === null
85
+ || localModelValue.value === undefined
86
+ ) {
87
+ return
88
+ }
89
+ localModelValue.value = undefined
90
+ return
91
+ }
92
+ if (NEGATIVE_ZERO_REGEX.test(unmasked.value)) {
93
+ localModelValue.value = 0
94
+ return
95
+ }
96
+ if (typeof typed.value !== 'number') {
97
+ localModelValue.value = Number(typed.value)
98
+ return
99
+ }
100
+ localModelValue.value = typed.value
101
+ return
102
+ }
103
+ if (type.value === INPUT_TYPES.DATE) {
104
+ if (
105
+ el.value instanceof HTMLInputElement
106
+ && el.value.type === 'date'
107
+ ) {
108
+ localModelValue.value = el.value.value
109
+ return
110
+ }
111
+ let date = typed.value
112
+ if (date === null || date === '') {
113
+ if (!localModelValue.value) {
114
+ return
115
+ }
116
+ localModelValue.value = ''
117
+ return
118
+ }
119
+ if (!(date instanceof Date)) {
120
+ date = new Date(date)
121
+ }
122
+ localModelValue.value = `${date.getFullYear()}-${(
123
+ `0${
124
+ date.getMonth() + 1}`
125
+ ).slice(-2)}-${(`0${date.getDate()}`).slice(-2)}`
126
+ return
127
+ }
128
+ if (type.value === INPUT_TYPES.DATETIME_LOCAL) {
129
+ if (
130
+ el.value instanceof HTMLInputElement
131
+ && el.value.type === 'datetime-local'
132
+ ) {
133
+ localModelValue.value = el.value.value
134
+ return
135
+ }
136
+ let date = typed.value
137
+ if (date === null || date === '') {
138
+ if (!localModelValue.value) {
139
+ return
140
+ }
141
+ localModelValue.value = ''
142
+ return
143
+ }
144
+ if (!(typed.value instanceof Date)) {
145
+ date = new Date(date)
146
+ }
147
+ localModelValue.value = `${date.getFullYear()}-${(
148
+ `0${
149
+ date.getMonth() + 1}`
150
+ ).slice(-2)}-${(`0${date.getDate()}`).slice(-2)}T${(
151
+ `0${date.getHours()}`
152
+ ).slice(-2)}:${(`0${date.getMinutes()}`).slice(-2)}`
153
+ return
154
+ }
155
+ if (!localModelValue.value && !unmasked.value) {
156
+ return
157
+ }
158
+ localModelValue.value = unmasked.value
159
+ },
160
+ },
161
+ )
162
+ function updateMaskValue(newValue: string | number | undefined) {
163
+ if (newValue === undefined) {
164
+ typed.value = ''
165
+ unmasked.value = ''
166
+ return
167
+ }
168
+ if (props.iMask?.mask === Date) {
169
+ typed.value = new Date(newValue)
170
+ return
171
+ }
172
+ if (
173
+ type.value === INPUT_TYPES.NUMBER
174
+ && NEGATIVE_ZERO_REGEX.test(unmasked.value)
175
+ && newValue === 0
176
+ ) {
177
+ return
178
+ }
179
+ typed.value = newValue
180
+ unmasked.value = `${typed.value}`
181
+ }
182
+ onMounted(() => {
183
+ if (mask.value) {
184
+ maskReady.value = true
185
+ updateMaskValue(props.modelValue)
186
+ }
187
+ })
188
+ watch(
189
+ () => props.modelValue,
190
+ (newValue) => {
191
+ if (mask.value) {
192
+ updateMaskValue(newValue)
193
+ }
194
+ },
195
+ )
196
+ watch(
197
+ () => props.masked,
198
+ (newValue) => {
199
+ masked.value = newValue ?? ''
200
+ },
201
+ )
177
202
 
178
- // debounce
179
- const localModelValue = useDebouncedInput(
180
- modelValue,
181
- emit,
182
- debounce?.value ?? 0,
183
- )
203
+ // template refs
204
+ const inputEl = el as Ref<HTMLInputElement>
205
+ const innerEl = ref<HTMLInputElement>()
206
+ const wrapperEl = ref<HTMLDivElement>()
207
+ const dropdownEl = ref<typeof VvDropdown>()
184
208
 
185
- // focus
186
- const { focused } = useComponentFocus(inputEl, emit)
187
- const isFocused = computed(
188
- () => focused.value && !props.disabled && !props.readonly,
189
- )
190
- watch(isFocused, (newValue) => {
191
- if (newValue && propsDefaults.value.selectOnFocus && inputEl.value) {
192
- inputEl.value.select()
193
- }
194
- })
209
+ defineExpose({ $inner: innerEl })
195
210
 
196
- // visibility
197
- const isVisible = useElementVisibility(inputEl)
198
- watch(isVisible, (newValue) => {
199
- if (newValue && props.autofocus && !props.disabled && !props.readonly) {
200
- focused.value = true
201
- }
202
- })
211
+ // focus
212
+ const { focused } = useComponentFocus(inputEl, emit)
213
+ const isFocused = computed(
214
+ () => focused.value && !props.disabled && !props.readonly,
215
+ )
216
+ watch(isFocused, (newValue) => {
217
+ if (newValue && propsDefaults.value.selectOnFocus && inputEl.value) {
218
+ inputEl.value.select()
219
+ }
220
+ if (newValue) {
221
+ dropdownEl.value?.show()
222
+ return
223
+ }
224
+ setTimeout(() => {
225
+ if (isDirty.value && suggestions.value) {
226
+ const suggestionsLimit = props.maxSuggestions - 1
227
+ if (
228
+ suggestions.value.size > suggestionsLimit
229
+ && !suggestions.value.has(localModelValue.value)
230
+ ) {
231
+ suggestions.value = new Set(
232
+ [...suggestions.value].slice(
233
+ suggestions.value.size - suggestionsLimit,
234
+ ),
235
+ )
236
+ }
237
+ suggestions.value.add(localModelValue.value)
238
+ }
239
+ }, 300)
240
+ })
203
241
 
204
- // password
205
- const showPassword = ref(false)
206
- const isPassword = computed(() => props.type === INPUT_TYPES.PASSWORD)
207
- const onTogglePassword = () => {
208
- showPassword.value = !showPassword.value
209
- }
242
+ // visibility
243
+ const isVisible = useElementVisibility(inputEl)
244
+ watch(isVisible, (newValue) => {
245
+ if (newValue && props.autofocus && !props.disabled && !props.readonly) {
246
+ focused.value = true
247
+ }
248
+ })
210
249
 
211
- // time, datetime and date
212
- const isDateTime = computed(
213
- () =>
214
- props.type === INPUT_TYPES.TIME ||
215
- props.type === INPUT_TYPES.DATETIME_LOCAL ||
216
- props.type === INPUT_TYPES.DATE ||
217
- props.type === INPUT_TYPES.WEEK ||
218
- props.type === INPUT_TYPES.MONTH,
219
- )
250
+ // password
251
+ const showPassword = ref(false)
252
+ const isPassword = computed(() => props.type === INPUT_TYPES.PASSWORD)
253
+ function onTogglePassword() {
254
+ showPassword.value = !showPassword.value
255
+ }
220
256
 
221
- // number
222
- const isNumber = computed(() => props.type === INPUT_TYPES.NUMBER)
223
- const onStepUp = () => {
224
- if (isClickable.value) {
225
- if (iMask?.value) {
226
- typed.value = typed.value + Number(step?.value ?? 1)
227
- return
228
- }
229
- inputEl.value.stepUp()
230
- localModelValue.value = unref(inputEl).value
231
- }
232
- }
233
- const onStepDown = () => {
234
- if (isClickable.value) {
235
- if (iMask?.value) {
236
- typed.value = typed.value - Number(step?.value ?? 1)
257
+ // time, datetime and date
258
+ const isDateTime = computed(
259
+ () =>
260
+ props.type === INPUT_TYPES.TIME
261
+ || props.type === INPUT_TYPES.DATETIME_LOCAL
262
+ || props.type === INPUT_TYPES.DATE
263
+ || props.type === INPUT_TYPES.WEEK
264
+ || props.type === INPUT_TYPES.MONTH,
265
+ )
237
266
 
238
- return
239
- }
240
- inputEl.value.stepDown()
241
- localModelValue.value = unref(inputEl).value
242
- }
243
- }
267
+ // number
268
+ const isNumber = computed(() => props.type === INPUT_TYPES.NUMBER)
269
+ function onStepUp() {
270
+ if (isClickable.value) {
271
+ if (props.iMask) {
272
+ typed.value = typed.value + Number(step?.value ?? 1)
273
+ return
274
+ }
275
+ inputEl.value.stepUp()
276
+ localModelValue.value = Number(unref(inputEl).value)
277
+ }
278
+ }
279
+ function onStepDown() {
280
+ if (isClickable.value) {
281
+ if (props.iMask) {
282
+ typed.value = typed.value - Number(step?.value ?? 1)
244
283
 
245
- // search
246
- const isSearch = computed(() => props.type === INPUT_TYPES.SEARCH)
247
- const onClear = () => {
248
- localModelValue.value = ''
249
- }
284
+ return
285
+ }
286
+ inputEl.value.stepDown()
287
+ localModelValue.value = Number(unref(inputEl).value)
288
+ }
289
+ }
250
290
 
251
- // icons
252
- const { hasIcon, hasIconBefore, hasIconAfter } = useComponentIcon(
253
- icon,
254
- iconPosition,
255
- )
256
- const defaultAfterIcon = computed(() => {
257
- switch (props.type) {
258
- case INPUT_TYPES.COLOR:
259
- return { name: TYPES_ICON.COLOR }
260
- case INPUT_TYPES.DATE:
261
- case INPUT_TYPES.DATETIME_LOCAL:
262
- case INPUT_TYPES.WEEK:
263
- case INPUT_TYPES.MONTH:
264
- return { name: TYPES_ICON.DATE }
265
- case INPUT_TYPES.TIME:
266
- return { name: TYPES_ICON.TIME }
267
- default:
268
- return ''
269
- }
270
- })
291
+ // search
292
+ const isSearch = computed(() => props.type === INPUT_TYPES.SEARCH)
293
+ function onClear() {
294
+ localModelValue.value = ''
295
+ }
271
296
 
272
- // count
273
- const { formatted: countFormatted } = useTextCount(localModelValue, {
274
- mode: count.value,
275
- upperLimit: Number(maxlength?.value),
276
- lowerLimit: Number(minlength?.value),
277
- })
297
+ // icons
298
+ const { hasIconBefore, hasIconAfter } = useComponentIcon(icon, iconPosition)
299
+ const iconAfter = computed(() => {
300
+ if (hasIconAfter.value !== undefined) {
301
+ return hasIconAfter.value
302
+ }
303
+ switch (props.type) {
304
+ case INPUT_TYPES.COLOR:
305
+ return { name: ACTION_ICONS.showColorPicker }
306
+ case INPUT_TYPES.DATE:
307
+ case INPUT_TYPES.DATETIME_LOCAL:
308
+ case INPUT_TYPES.WEEK:
309
+ case INPUT_TYPES.MONTH:
310
+ return { name: ACTION_ICONS.showDatePicker }
311
+ case INPUT_TYPES.TIME:
312
+ return { name: ACTION_ICONS.showTimePicker }
313
+ }
314
+ return undefined
315
+ })
316
+ const { hasIcon: hasIconRemoveSuggestion }
317
+ = useComponentIcon(iconRemoveSuggestion)
278
318
 
279
- // tabindex
280
- const isClickable = computed(() => !props.disabled && !props.readonly)
281
- const hasTabindex = computed(() =>
282
- isClickable.value ? props.tabindex : -1,
283
- )
319
+ // count
320
+ const { formatted: countFormatted } = useTextCount(localModelValue, {
321
+ mode: count.value,
322
+ upperLimit: Number(maxlength?.value),
323
+ lowerLimit: Number(minlength?.value),
324
+ })
284
325
 
285
- // dirty
286
- const isDirty = computed(() => !isEmpty(modelValue))
326
+ // tabindex
327
+ const isClickable = computed(() => !props.disabled && !props.readonly)
328
+ const hasTabindex = computed(() =>
329
+ isClickable.value ? props.tabindex : -1,
330
+ )
287
331
 
288
- // invalid
289
- const isInvalid = computed(() => {
290
- if (invalid.value === true) {
291
- return true
292
- }
293
- if (valid.value === true) {
294
- return false
295
- }
296
- return undefined
297
- })
332
+ // dirty
333
+ const isDirty = computed(() => !isEmpty(modelValue))
298
334
 
299
- // styles
300
- const { modifiers } = toRefs(props)
301
- const bemCssClasses = useModifiers(
302
- 'vv-input-text',
303
- modifiers,
304
- computed(() => ({
305
- valid: valid.value,
306
- invalid: invalid.value,
307
- loading: loading.value,
308
- disabled: props.disabled,
309
- readonly: props.readonly,
310
- 'icon-before': hasIconBefore.value,
311
- 'icon-after': hasIconAfter.value || !isEmpty(defaultAfterIcon),
312
- floating: props.floating && !isEmpty(props.label),
313
- dirty: isDirty.value,
314
- focus: isFocused.value,
315
- 'auto-width': props.autoWidth,
316
- })),
317
- )
335
+ // invalid
336
+ const isInvalid = computed(() => {
337
+ if (invalid.value === true) {
338
+ return true
339
+ }
340
+ if (valid.value === true) {
341
+ return false
342
+ }
343
+ return undefined
344
+ })
318
345
 
319
- // attrs
320
- const hasAttrs = computed(() => {
321
- const type = (() => {
322
- if (isPassword.value && showPassword.value) {
323
- return INPUT_TYPES.TEXT
324
- }
325
- if (isDateTime.value && !isDirty.value && !focused.value) {
326
- return INPUT_TYPES.TEXT
327
- }
328
- if (iMask?.value) {
329
- return INPUT_TYPES.TEXT
330
- }
331
- return props.type
332
- })()
333
- const toReturn: InputHTMLAttributes = {
334
- type,
335
- name: props.name,
336
- tabindex: hasTabindex.value,
337
- disabled: props.disabled,
338
- readonly: props.readonly,
339
- required: props.required,
340
- autocomplete: props.autocomplete,
341
- 'aria-invalid': isInvalid.value,
342
- 'aria-describedby': hasHintLabelOrSlot.value
343
- ? hasHintId.value
344
- : undefined,
345
- 'aria-errormessage': hasInvalidLabelOrSlot.value
346
- ? hasHintId.value
347
- : undefined,
348
- }
349
- if (
350
- type === INPUT_TYPES.DATE ||
351
- type === INPUT_TYPES.MONTH ||
352
- type === INPUT_TYPES.WEEK ||
353
- type === INPUT_TYPES.TIME ||
354
- type === INPUT_TYPES.DATETIME_LOCAL ||
355
- type === INPUT_TYPES.NUMBER
356
- ) {
357
- toReturn.step = props.step
358
- toReturn.max =
359
- props.max !== undefined ? String(props.max) : undefined
360
- toReturn.min =
361
- props.min !== undefined ? String(props.min) : undefined
362
- }
363
- if (
364
- type === INPUT_TYPES.TEXT ||
365
- type === INPUT_TYPES.SEARCH ||
366
- type === INPUT_TYPES.URL ||
367
- type === INPUT_TYPES.TEL ||
368
- type === INPUT_TYPES.EMAIL ||
369
- type === INPUT_TYPES.PASSWORD ||
370
- type === INPUT_TYPES.NUMBER
371
- ) {
372
- toReturn.placeholder = inputTextPlaceholder.value
373
- }
374
- if (
375
- type === INPUT_TYPES.TEXT ||
376
- type === INPUT_TYPES.SEARCH ||
377
- type === INPUT_TYPES.URL ||
378
- type === INPUT_TYPES.TEL ||
379
- type === INPUT_TYPES.EMAIL ||
380
- type === INPUT_TYPES.PASSWORD
381
- ) {
382
- toReturn.minlength = props.minlength
383
- toReturn.maxlength = props.maxlength
384
- toReturn.pattern = props.pattern
385
- }
386
- if (type === INPUT_TYPES.EMAIL) {
387
- toReturn.multiple = props.multiple
388
- }
389
- return toReturn
390
- })
346
+ // suggestions
347
+ const suggestions = usePersistence<Set<string>>(
348
+ storageKey,
349
+ storageType,
350
+ new Set(),
351
+ )
352
+ const filteredSuggestions = computed(() => {
353
+ if (!suggestions.value) {
354
+ return []
355
+ }
356
+ return [...suggestions.value]
357
+ .filter(
358
+ suggestion =>
359
+ isEmpty(localModelValue.value)
360
+ || (`${suggestion}`
361
+ .toLowerCase()
362
+ .includes(`${localModelValue.value}`.toLowerCase())
363
+ && suggestion !== localModelValue.value),
364
+ )
365
+ .reverse()
366
+ })
367
+ const hasSuggestions = computed(
368
+ () =>
369
+ storageKey?.value
370
+ && suggestions.value
371
+ && suggestions.value.size > 0,
372
+ )
373
+ function onSuggestionSelect(suggestion: string) {
374
+ localModelValue.value = suggestion
375
+ dropdownEl.value?.hide()
376
+ }
377
+ function onSuggestionRemove(suggestion: string) {
378
+ suggestions.value?.delete(suggestion)
379
+ }
391
380
 
392
- // slots
393
- const slotProps = computed(() => ({
394
- valid: props.valid,
395
- invalid: props.invalid,
396
- modelValue: props.modelValue,
397
- togglePassword: onTogglePassword,
398
- stepUp: onStepUp,
399
- stepDown: onStepDown,
400
- clear: onClear,
401
- }))
381
+ // styles
382
+ const { modifiers } = toRefs(props)
383
+ const bemCssClasses = useModifiers(
384
+ 'vv-input-text',
385
+ modifiers,
386
+ computed(() => ({
387
+ 'valid': valid.value,
388
+ 'invalid': invalid.value,
389
+ 'loading': loading.value,
390
+ 'disabled': props.disabled,
391
+ 'readonly': props.readonly,
392
+ 'icon-before': !!hasIconBefore.value,
393
+ 'icon-after': !!iconAfter.value,
394
+ 'floating': props.floating && !isEmpty(props.label),
395
+ 'dirty': isDirty.value,
396
+ 'focus': isFocused.value,
397
+ 'auto-width': props.autoWidth,
398
+ })),
399
+ )
402
400
 
403
- // components
404
- const {
405
- HintSlot,
406
- hasHintLabelOrSlot,
407
- hasInvalidLabelOrSlot,
408
- hintSlotScope,
409
- } = HintSlotFactory(propsDefaults, slots)
410
- const PasswordInputActions = VvInputTextActionsFactory(
411
- INPUT_TYPES.PASSWORD,
412
- props,
413
- )
414
- const NumberInputActions = VvInputTextActionsFactory(
415
- INPUT_TYPES.NUMBER,
416
- props,
417
- )
418
- const SearchInputActions = VvInputTextActionsFactory(
419
- INPUT_TYPES.SEARCH,
420
- props,
421
- )
401
+ // attrs
402
+ const hasAttrs = computed(() => {
403
+ const type = (() => {
404
+ if (isPassword.value && showPassword.value) {
405
+ return INPUT_TYPES.TEXT
406
+ }
407
+ if (isDateTime.value && !isDirty.value && !focused.value) {
408
+ return INPUT_TYPES.TEXT
409
+ }
410
+ if (props.iMask) {
411
+ return INPUT_TYPES.TEXT
412
+ }
413
+ return props.type
414
+ })()
415
+ const toReturn: InputHTMLAttributes = {
416
+ type,
417
+ 'name': props.name,
418
+ 'tabindex': hasTabindex.value,
419
+ 'disabled': props.disabled,
420
+ 'readonly': props.readonly,
421
+ 'required': props.required,
422
+ 'autocomplete': props.autocomplete,
423
+ 'aria-invalid': isInvalid.value,
424
+ 'aria-describedby': hasHintLabelOrSlot.value
425
+ ? hasHintId.value
426
+ : undefined,
427
+ 'aria-errormessage': hasInvalidLabelOrSlot.value
428
+ ? hasHintId.value
429
+ : undefined,
430
+ }
431
+ if (
432
+ type === INPUT_TYPES.DATE
433
+ || type === INPUT_TYPES.MONTH
434
+ || type === INPUT_TYPES.WEEK
435
+ || type === INPUT_TYPES.TIME
436
+ || type === INPUT_TYPES.DATETIME_LOCAL
437
+ || type === INPUT_TYPES.NUMBER
438
+ ) {
439
+ let max = props.max
440
+ if (type === INPUT_TYPES.DATE && !max) {
441
+ max = '9999-12-31'
442
+ }
443
+ toReturn.step = props.step
444
+ toReturn.max = max !== undefined ? String(max) : undefined
445
+ toReturn.min
446
+ = props.min !== undefined ? String(props.min) : undefined
447
+ }
448
+ if (
449
+ type === INPUT_TYPES.TEXT
450
+ || type === INPUT_TYPES.SEARCH
451
+ || type === INPUT_TYPES.URL
452
+ || type === INPUT_TYPES.TEL
453
+ || type === INPUT_TYPES.EMAIL
454
+ || type === INPUT_TYPES.PASSWORD
455
+ || type === INPUT_TYPES.NUMBER
456
+ ) {
457
+ toReturn.placeholder = inputTextPlaceholder.value
458
+ }
459
+ if (
460
+ type === INPUT_TYPES.TEXT
461
+ || type === INPUT_TYPES.SEARCH
462
+ || type === INPUT_TYPES.URL
463
+ || type === INPUT_TYPES.TEL
464
+ || type === INPUT_TYPES.EMAIL
465
+ || type === INPUT_TYPES.PASSWORD
466
+ ) {
467
+ toReturn.minlength = props.minlength
468
+ toReturn.maxlength = props.maxlength
469
+ toReturn.pattern = props.pattern
470
+ }
471
+ if (type === INPUT_TYPES.EMAIL) {
472
+ toReturn.multiple = props.multiple
473
+ }
474
+ return toReturn
475
+ })
422
476
 
423
- // auto-width
424
- const onClickInner = () => {
425
- if (isClickable.value) {
426
- focused.value = true
427
- }
428
- }
429
- const hasStyle = computed(() => {
430
- if (!props.autoWidth) {
431
- return undefined
432
- }
433
- return {
434
- width:
477
+ // slots
478
+ const slotProps = computed(() => ({
479
+ valid: props.valid,
480
+ invalid: props.invalid,
481
+ modelValue: props.modelValue,
482
+ togglePassword: onTogglePassword,
483
+ stepUp: onStepUp,
484
+ stepDown: onStepDown,
485
+ clear: onClear,
486
+ }))
487
+
488
+ // components
489
+ const {
490
+ HintSlot,
491
+ hasHintLabelOrSlot,
492
+ hasInvalidLabelOrSlot,
493
+ hintSlotScope,
494
+ } = HintSlotFactory(propsDefaults, slots)
495
+ const PasswordInputActions = VvInputTextActionsFactory(
496
+ INPUT_TYPES.PASSWORD,
497
+ props,
498
+ )
499
+ const NumberInputActions = VvInputTextActionsFactory(
500
+ INPUT_TYPES.NUMBER,
501
+ props,
502
+ )
503
+ const SearchInputActions = VvInputTextActionsFactory(
504
+ INPUT_TYPES.SEARCH,
505
+ props,
506
+ )
507
+
508
+ // auto-width
509
+ function onClickInner() {
510
+ if (isClickable.value) {
511
+ focused.value = true
512
+ }
513
+ }
514
+ const hasStyle = computed(() => {
515
+ if (!props.autoWidth) {
516
+ return undefined
517
+ }
518
+ return {
519
+ width:
435
520
  localModelValue.value !== undefined
436
- ? `${String(localModelValue.value).length + 1}ch`
437
- : undefined,
438
- }
439
- })
521
+ ? `${String(localModelValue.value).length + 1}ch`
522
+ : undefined,
523
+ }
524
+ })
440
525
 
441
- // keydown
442
- const onKeyDown = (event: KeyboardEvent) => {
443
- switch (event.code) {
444
- case 'ArrowUp':
445
- if (isNumber.value) {
446
- onStepUp()
447
- event.preventDefault()
448
- }
449
- break
526
+ // keydown
527
+ function onKeyDown(event: KeyboardEvent) {
528
+ switch (event.code) {
529
+ case 'ArrowUp':
530
+ if (isNumber.value) {
531
+ onStepUp()
532
+ event.preventDefault()
533
+ }
534
+ break
450
535
 
451
- case 'ArrowDown':
452
- if (isNumber.value) {
453
- onStepDown()
454
- event.preventDefault()
455
- }
456
- break
457
- }
458
- emit('keydown', event)
459
- }
536
+ case 'ArrowDown':
537
+ if (isNumber.value) {
538
+ onStepDown()
539
+ event.preventDefault()
540
+ }
541
+ break
542
+ }
543
+ emit('keydown', event)
544
+ }
545
+ </script>
546
+
547
+ <script lang="ts">
548
+ export default {
549
+ name: 'VvInputText',
550
+ }
460
551
  </script>
461
552
 
462
553
  <template>
463
- <div :class="bemCssClasses">
464
- <label v-if="label" :for="hasId" class="vv-input-text__label">
465
- {{ label }}
466
- </label>
467
- <div class="vv-input-text__wrapper">
468
- <div v-if="$slots.before" class="vv-input-text__input-before">
469
- <!-- @slot Slot before input icon -->
470
- <slot name="before" v-bind="slotProps" />
471
- </div>
472
- <div
473
- ref="innerEl"
474
- class="vv-input-text__inner"
475
- @click.stop="onClickInner"
476
- >
477
- <VvIcon
478
- v-if="hasIconBefore"
479
- class="vv-input-text__icon"
480
- v-bind="hasIcon"
481
- />
482
- <input
483
- :id="hasId"
484
- ref="inputEl"
485
- v-bind="hasAttrs"
486
- :style="hasStyle"
487
- @keyup="emit('keyup', $event)"
488
- @keydown="onKeyDown"
489
- @keypress="emit('keypress', $event)"
490
- />
491
- <div
492
- v-if="(unit || $slots.unit) && isDirty"
493
- class="vv-input-text__unit"
494
- >
495
- <!-- @slot Slot to replace unit-->
496
- <slot name v-bind="slotProps">
497
- {{ unit }}
498
- </slot>
499
- </div>
500
- </div>
501
- <!-- @slot Slot to replace right icon -->
502
- <VvIcon
503
- v-if="hasIconAfter || defaultAfterIcon"
504
- class="vv-input-text__icon vv-input-text__icon-after"
505
- v-bind="hasIconAfter ? hasIcon : defaultAfterIcon"
506
- />
507
- <PasswordInputActions
508
- v-else-if="isPassword && !hideActions && isClickable"
509
- @toggle-password="onTogglePassword"
510
- />
511
- <NumberInputActions
512
- v-else-if="isNumber && !hideActions && isClickable"
513
- @step-up="onStepUp"
514
- @step-down="onStepDown"
515
- />
516
- <SearchInputActions
517
- v-else-if="isSearch && !hideActions && isClickable"
518
- @clear="onClear"
519
- />
520
- <!-- @slot Slot after input -->
521
- <div v-if="$slots.after" class="vv-input-text__input-after">
522
- <!-- @slot Slot before input icon -->
523
- <slot name="after" v-bind="slotProps" />
524
- </div>
525
- <span v-if="count" class="vv-input-text__limit">
526
- <!-- @slot Slot to replace count -->
527
- <slot name="count" v-bind="slotProps">
528
- {{ countFormatted }}
529
- </slot>
530
- </span>
531
- </div>
532
- <HintSlot :id="hasHintId" class="vv-input-text__hint">
533
- <template v-if="$slots.hint" #hint>
534
- <slot name="hint" v-bind="hintSlotScope" />
535
- </template>
536
- <template v-if="$slots.loading" #loading>
537
- <slot name="loading" v-bind="hintSlotScope" />
538
- </template>
539
- <template v-if="$slots.valid" #valid>
540
- <slot name="valid" v-bind="hintSlotScope" />
541
- </template>
542
- <template v-if="$slots.invalid" #invalid>
543
- <slot name="invalid" v-bind="hintSlotScope" />
544
- </template>
545
- </HintSlot>
546
- </div>
554
+ <div :class="bemCssClasses">
555
+ <label v-if="label" :for="hasId" class="vv-input-text__label">
556
+ {{ label }}
557
+ </label>
558
+ <div ref="wrapperEl" class="vv-input-text__wrapper">
559
+ <div v-if="$slots.before" class="vv-input-text__input-before">
560
+ <!-- @slot Slot before input icon -->
561
+ <slot name="before" v-bind="slotProps" />
562
+ </div>
563
+ <div
564
+ ref="innerEl"
565
+ class="vv-input-text__inner"
566
+ @click.stop="onClickInner"
567
+ >
568
+ <VvIcon
569
+ v-if="hasIconBefore"
570
+ v-bind="hasIconBefore"
571
+ class="vv-input-text__icon"
572
+ />
573
+ <input
574
+ :id="hasId"
575
+ ref="inputEl"
576
+ v-bind="hasAttrs"
577
+ :style="hasStyle"
578
+ @keyup="emit('keyup', $event)"
579
+ @keydown="onKeyDown"
580
+ @keypress="emit('keypress', $event)"
581
+ >
582
+ <div
583
+ v-if="(unit || $slots.unit) && isDirty"
584
+ class="vv-input-text__unit"
585
+ >
586
+ <!-- @slot Slot to replace unit -->
587
+ <slot name v-bind="slotProps">
588
+ {{ unit }}
589
+ </slot>
590
+ </div>
591
+ </div>
592
+ <!-- @slot Slot to replace right icon -->
593
+ <VvIcon
594
+ v-if="iconAfter"
595
+ v-bind="iconAfter"
596
+ class="vv-input-text__icon vv-input-text__icon-after"
597
+ />
598
+ <PasswordInputActions
599
+ v-else-if="isPassword && !hideActions && isClickable"
600
+ @toggle-password="onTogglePassword"
601
+ />
602
+ <NumberInputActions
603
+ v-else-if="isNumber && !hideActions && isClickable"
604
+ @step-up="onStepUp"
605
+ @step-down="onStepDown"
606
+ />
607
+ <SearchInputActions
608
+ v-else-if="isSearch && !hideActions && isClickable"
609
+ @clear="onClear"
610
+ />
611
+ <!-- @slot Slot after input -->
612
+ <div v-if="$slots.after" class="vv-input-text__input-after">
613
+ <!-- @slot Slot before input icon -->
614
+ <slot name="after" v-bind="slotProps" />
615
+ </div>
616
+ <span v-if="count" class="vv-input-text__limit">
617
+ <!-- @slot Slot to replace count -->
618
+ <slot name="count" v-bind="slotProps">
619
+ {{ countFormatted }}
620
+ </slot>
621
+ </span>
622
+ </div>
623
+ <HintSlot :id="hasHintId" class="vv-input-text__hint">
624
+ <template v-if="$slots.hint" #hint>
625
+ <slot name="hint" v-bind="hintSlotScope" />
626
+ </template>
627
+ <template v-if="$slots.loading" #loading>
628
+ <slot name="loading" v-bind="hintSlotScope" />
629
+ </template>
630
+ <template v-if="$slots.valid" #valid>
631
+ <slot name="valid" v-bind="hintSlotScope" />
632
+ </template>
633
+ <template v-if="$slots.invalid" #invalid>
634
+ <slot name="invalid" v-bind="hintSlotScope" />
635
+ </template>
636
+ </HintSlot>
637
+ <VvDropdown
638
+ v-if="hasSuggestions"
639
+ ref="dropdownEl"
640
+ :reference="wrapperEl"
641
+ :autofocus-first="false"
642
+ :trigger-width="true"
643
+ >
644
+ <template #items>
645
+ <VvDropdownOption
646
+ v-for="value in filteredSuggestions"
647
+ :key="value"
648
+ @click.stop="onSuggestionSelect(value)"
649
+ >
650
+ <div class="flex-1">
651
+ <slot name="suggestion" v-bind="{ value }">
652
+ {{ value }}
653
+ </slot>
654
+ </div>
655
+ <button
656
+ v-if="suggestions && hasIconRemoveSuggestion"
657
+ type="button"
658
+ tabindex="-1"
659
+ class="cursor-pointer"
660
+ :title="labelRemoveSuggestion"
661
+ @click.stop="onSuggestionRemove(value)"
662
+ >
663
+ <VvIcon v-bind="hasIconRemoveSuggestion" />
664
+ </button>
665
+ </VvDropdownOption>
666
+ </template>
667
+ </VvDropdown>
668
+ </div>
547
669
  </template>