primevue 3.15.0 → 3.16.0

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 (394) hide show
  1. package/autocomplete/AutoComplete.d.ts +182 -38
  2. package/autocomplete/AutoComplete.vue +633 -342
  3. package/autocomplete/autocomplete.cjs.js +742 -416
  4. package/autocomplete/autocomplete.cjs.min.js +1 -1
  5. package/autocomplete/autocomplete.esm.js +744 -418
  6. package/autocomplete/autocomplete.esm.min.js +1 -1
  7. package/autocomplete/autocomplete.js +742 -416
  8. package/autocomplete/autocomplete.min.js +1 -1
  9. package/button/Button.vue +4 -1
  10. package/button/button.cjs.js +5 -1
  11. package/button/button.cjs.min.js +1 -1
  12. package/button/button.esm.js +5 -1
  13. package/button/button.esm.min.js +1 -1
  14. package/button/button.js +5 -1
  15. package/button/button.min.js +1 -1
  16. package/calendar/Calendar.d.ts +51 -12
  17. package/calendar/Calendar.vue +258 -113
  18. package/calendar/calendar.cjs.js +412 -218
  19. package/calendar/calendar.cjs.min.js +1 -1
  20. package/calendar/calendar.esm.js +413 -219
  21. package/calendar/calendar.esm.min.js +1 -1
  22. package/calendar/calendar.js +412 -218
  23. package/calendar/calendar.min.js +1 -1
  24. package/carousel/Carousel.vue +25 -0
  25. package/carousel/carousel.cjs.js +25 -0
  26. package/carousel/carousel.cjs.min.js +1 -1
  27. package/carousel/carousel.esm.js +25 -0
  28. package/carousel/carousel.esm.min.js +1 -1
  29. package/carousel/carousel.js +25 -0
  30. package/carousel/carousel.min.js +1 -1
  31. package/cascadeselect/CascadeSelect.d.ts +97 -17
  32. package/cascadeselect/CascadeSelect.vue +560 -135
  33. package/cascadeselect/CascadeSelectSub.vue +48 -129
  34. package/cascadeselect/cascadeselect.cjs.js +670 -306
  35. package/cascadeselect/cascadeselect.cjs.min.js +1 -1
  36. package/cascadeselect/cascadeselect.esm.js +672 -308
  37. package/cascadeselect/cascadeselect.esm.min.js +1 -1
  38. package/cascadeselect/cascadeselect.js +670 -306
  39. package/cascadeselect/cascadeselect.min.js +1 -1
  40. package/checkbox/Checkbox.d.ts +40 -4
  41. package/checkbox/Checkbox.vue +50 -13
  42. package/checkbox/checkbox.cjs.js +64 -23
  43. package/checkbox/checkbox.cjs.min.js +1 -1
  44. package/checkbox/checkbox.esm.js +65 -24
  45. package/checkbox/checkbox.esm.min.js +1 -1
  46. package/checkbox/checkbox.js +64 -23
  47. package/checkbox/checkbox.min.js +1 -1
  48. package/chips/Chips.d.ts +36 -12
  49. package/chips/Chips.vue +116 -22
  50. package/chips/chips.cjs.js +149 -37
  51. package/chips/chips.cjs.min.js +1 -1
  52. package/chips/chips.esm.js +150 -38
  53. package/chips/chips.esm.min.js +1 -1
  54. package/chips/chips.js +150 -39
  55. package/chips/chips.min.js +1 -1
  56. package/colorpicker/ColorPicker.d.ts +3 -6
  57. package/colorpicker/ColorPicker.vue +1 -5
  58. package/colorpicker/colorpicker.cjs.js +2 -7
  59. package/colorpicker/colorpicker.cjs.min.js +1 -1
  60. package/colorpicker/colorpicker.esm.js +2 -7
  61. package/colorpicker/colorpicker.esm.min.js +1 -1
  62. package/colorpicker/colorpicker.js +2 -7
  63. package/colorpicker/colorpicker.min.js +1 -1
  64. package/column/Column.d.ts +4 -0
  65. package/column/Column.vue +4 -0
  66. package/column/column.cjs.js +4 -0
  67. package/column/column.cjs.min.js +1 -1
  68. package/column/column.esm.js +4 -0
  69. package/column/column.esm.min.js +1 -1
  70. package/column/column.js +4 -0
  71. package/column/column.min.js +1 -1
  72. package/config/PrimeVue.d.ts +7 -0
  73. package/config/config.cjs.js +35 -4
  74. package/config/config.cjs.min.js +1 -1
  75. package/config/config.esm.js +35 -4
  76. package/config/config.esm.min.js +1 -1
  77. package/config/config.js +35 -4
  78. package/config/config.min.js +1 -1
  79. package/confirmdialog/ConfirmDialog.vue +4 -1
  80. package/confirmdialog/confirmdialog.cjs.js +6 -2
  81. package/confirmdialog/confirmdialog.cjs.min.js +1 -1
  82. package/confirmdialog/confirmdialog.esm.js +6 -2
  83. package/confirmdialog/confirmdialog.esm.min.js +1 -1
  84. package/confirmdialog/confirmdialog.js +6 -2
  85. package/confirmdialog/confirmdialog.min.js +1 -1
  86. package/contextmenu/ContextMenu.d.ts +1 -1
  87. package/contextmenu/ContextMenuSub.vue +3 -3
  88. package/contextmenu/contextmenu.cjs.js +14 -8
  89. package/contextmenu/contextmenu.cjs.min.js +1 -1
  90. package/contextmenu/contextmenu.esm.js +15 -9
  91. package/contextmenu/contextmenu.esm.min.js +1 -1
  92. package/contextmenu/contextmenu.js +14 -8
  93. package/contextmenu/contextmenu.min.js +1 -1
  94. package/core/core.js +1110 -781
  95. package/core/core.min.js +17 -14
  96. package/datatable/BodyCell.vue +11 -2
  97. package/datatable/DataTable.vue +22 -1
  98. package/datatable/datatable.cjs.js +33 -3
  99. package/datatable/datatable.cjs.min.js +1 -1
  100. package/datatable/datatable.esm.js +33 -3
  101. package/datatable/datatable.esm.min.js +1 -1
  102. package/datatable/datatable.js +33 -3
  103. package/datatable/datatable.min.js +1 -1
  104. package/dialog/Dialog.d.ts +5 -1
  105. package/dropdown/Dropdown.d.ts +93 -39
  106. package/dropdown/Dropdown.vue +537 -398
  107. package/dropdown/dropdown.cjs.js +656 -485
  108. package/dropdown/dropdown.cjs.min.js +1 -1
  109. package/dropdown/dropdown.esm.js +658 -487
  110. package/dropdown/dropdown.esm.min.js +1 -1
  111. package/dropdown/dropdown.js +656 -485
  112. package/dropdown/dropdown.min.js +1 -1
  113. package/editor/Editor.d.ts +32 -0
  114. package/editor/Editor.vue +15 -1
  115. package/editor/editor.cjs.js +15 -1
  116. package/editor/editor.cjs.min.js +1 -1
  117. package/editor/editor.esm.js +15 -1
  118. package/editor/editor.esm.min.js +1 -1
  119. package/editor/editor.js +15 -1
  120. package/editor/editor.min.js +1 -1
  121. package/inputmask/InputMask.vue +9 -6
  122. package/inputmask/inputmask.cjs.js +14 -6
  123. package/inputmask/inputmask.cjs.min.js +1 -1
  124. package/inputmask/inputmask.esm.js +15 -7
  125. package/inputmask/inputmask.esm.min.js +1 -1
  126. package/inputmask/inputmask.js +14 -6
  127. package/inputmask/inputmask.min.js +1 -1
  128. package/inputnumber/InputNumber.d.ts +31 -7
  129. package/inputnumber/InputNumber.vue +54 -21
  130. package/inputnumber/inputnumber.cjs.js +75 -30
  131. package/inputnumber/inputnumber.cjs.min.js +1 -1
  132. package/inputnumber/inputnumber.esm.js +76 -31
  133. package/inputnumber/inputnumber.esm.min.js +1 -1
  134. package/inputnumber/inputnumber.js +75 -30
  135. package/inputnumber/inputnumber.min.js +1 -1
  136. package/inputswitch/InputSwitch.d.ts +24 -8
  137. package/inputswitch/InputSwitch.vue +27 -12
  138. package/inputswitch/inputswitch.cjs.js +38 -20
  139. package/inputswitch/inputswitch.cjs.min.js +1 -1
  140. package/inputswitch/inputswitch.esm.js +39 -21
  141. package/inputswitch/inputswitch.esm.min.js +1 -1
  142. package/inputswitch/inputswitch.js +38 -20
  143. package/inputswitch/inputswitch.min.js +1 -1
  144. package/inputtext/InputText.vue +1 -2
  145. package/inputtext/inputtext.cjs.js +3 -4
  146. package/inputtext/inputtext.cjs.min.js +1 -1
  147. package/inputtext/inputtext.esm.js +4 -5
  148. package/inputtext/inputtext.esm.min.js +1 -1
  149. package/inputtext/inputtext.js +3 -4
  150. package/inputtext/inputtext.min.js +1 -1
  151. package/knob/Knob.d.ts +12 -0
  152. package/knob/Knob.vue +62 -2
  153. package/knob/knob.cjs.js +73 -5
  154. package/knob/knob.cjs.min.js +1 -1
  155. package/knob/knob.esm.js +73 -5
  156. package/knob/knob.esm.min.js +1 -1
  157. package/knob/knob.js +73 -5
  158. package/knob/knob.min.js +1 -1
  159. package/listbox/Listbox.d.ts +53 -7
  160. package/listbox/Listbox.vue +499 -134
  161. package/listbox/listbox.cjs.js +596 -192
  162. package/listbox/listbox.cjs.min.js +1 -1
  163. package/listbox/listbox.esm.js +598 -194
  164. package/listbox/listbox.esm.min.js +1 -1
  165. package/listbox/listbox.js +596 -192
  166. package/listbox/listbox.min.js +1 -1
  167. package/menu/Menu.d.ts +1 -1
  168. package/menu/Menuitem.vue +2 -2
  169. package/menu/menu.cjs.js +12 -6
  170. package/menu/menu.cjs.min.js +1 -1
  171. package/menu/menu.esm.js +13 -7
  172. package/menu/menu.esm.min.js +1 -1
  173. package/menu/menu.js +12 -6
  174. package/menu/menu.min.js +1 -1
  175. package/menubar/MenubarSub.vue +3 -3
  176. package/menubar/menubar.cjs.js +14 -8
  177. package/menubar/menubar.cjs.min.js +1 -1
  178. package/menubar/menubar.esm.js +15 -9
  179. package/menubar/menubar.esm.min.js +1 -1
  180. package/menubar/menubar.js +14 -8
  181. package/menubar/menubar.min.js +1 -1
  182. package/menuitem/MenuItem.d.ts +1 -1
  183. package/multiselect/MultiSelect.d.ts +112 -52
  184. package/multiselect/MultiSelect.vue +622 -337
  185. package/multiselect/multiselect.cjs.js +740 -426
  186. package/multiselect/multiselect.cjs.min.js +1 -1
  187. package/multiselect/multiselect.esm.js +742 -428
  188. package/multiselect/multiselect.esm.min.js +1 -1
  189. package/multiselect/multiselect.js +740 -426
  190. package/multiselect/multiselect.min.js +1 -1
  191. package/overlaypanel/OverlayPanel.d.ts +1 -1
  192. package/overlaypanel/OverlayPanel.vue +13 -1
  193. package/overlaypanel/overlaypanel.cjs.js +13 -1
  194. package/overlaypanel/overlaypanel.cjs.min.js +1 -1
  195. package/overlaypanel/overlaypanel.esm.js +13 -1
  196. package/overlaypanel/overlaypanel.esm.min.js +1 -1
  197. package/overlaypanel/overlaypanel.js +13 -1
  198. package/overlaypanel/overlaypanel.min.js +1 -1
  199. package/package.json +1 -1
  200. package/paginator/Paginator.d.ts +2 -2
  201. package/password/Password.d.ts +36 -8
  202. package/password/Password.vue +50 -14
  203. package/password/password.cjs.js +69 -24
  204. package/password/password.cjs.min.js +1 -1
  205. package/password/password.esm.js +71 -26
  206. package/password/password.esm.min.js +1 -1
  207. package/password/password.js +69 -24
  208. package/password/password.min.js +1 -1
  209. package/picklist/PickList.d.ts +8 -0
  210. package/picklist/PickList.vue +10 -2
  211. package/picklist/picklist.cjs.js +68 -50
  212. package/picklist/picklist.cjs.min.js +1 -1
  213. package/picklist/picklist.esm.js +69 -51
  214. package/picklist/picklist.esm.min.js +1 -1
  215. package/picklist/picklist.js +68 -50
  216. package/picklist/picklist.min.js +1 -1
  217. package/portal/Portal.d.ts +1 -1
  218. package/portal/Portal.vue +6 -13
  219. package/portal/portal.cjs.js +4 -9
  220. package/portal/portal.cjs.min.js +1 -1
  221. package/portal/portal.esm.js +4 -9
  222. package/portal/portal.esm.min.js +1 -1
  223. package/portal/portal.js +4 -9
  224. package/portal/portal.min.js +1 -1
  225. package/radiobutton/RadioButton.d.ts +28 -4
  226. package/radiobutton/RadioButton.vue +36 -11
  227. package/radiobutton/radiobutton.cjs.js +49 -23
  228. package/radiobutton/radiobutton.cjs.min.js +1 -1
  229. package/radiobutton/radiobutton.esm.js +50 -24
  230. package/radiobutton/radiobutton.esm.min.js +1 -1
  231. package/radiobutton/radiobutton.js +49 -23
  232. package/radiobutton/radiobutton.min.js +1 -1
  233. package/rating/Rating.d.ts +4 -0
  234. package/rating/Rating.vue +61 -7
  235. package/rating/rating.cjs.js +90 -16
  236. package/rating/rating.cjs.min.js +1 -1
  237. package/rating/rating.esm.js +91 -17
  238. package/rating/rating.esm.min.js +1 -1
  239. package/rating/rating.js +90 -16
  240. package/rating/rating.min.js +1 -1
  241. package/resources/primevue.css +8 -0
  242. package/resources/primevue.min.css +1 -1
  243. package/resources/themes/arya-blue/theme.css +82 -40
  244. package/resources/themes/arya-green/theme.css +82 -40
  245. package/resources/themes/arya-orange/theme.css +82 -40
  246. package/resources/themes/arya-purple/theme.css +82 -40
  247. package/resources/themes/bootstrap4-dark-blue/theme.css +82 -40
  248. package/resources/themes/bootstrap4-dark-purple/theme.css +82 -40
  249. package/resources/themes/bootstrap4-light-blue/theme.css +82 -40
  250. package/resources/themes/bootstrap4-light-purple/theme.css +82 -40
  251. package/resources/themes/fluent-light/theme.css +82 -40
  252. package/resources/themes/lara-dark-blue/theme.css +82 -40
  253. package/resources/themes/lara-dark-indigo/theme.css +82 -40
  254. package/resources/themes/lara-dark-purple/theme.css +82 -40
  255. package/resources/themes/lara-dark-teal/theme.css +82 -40
  256. package/resources/themes/lara-light-blue/theme.css +82 -40
  257. package/resources/themes/lara-light-indigo/theme.css +82 -40
  258. package/resources/themes/lara-light-purple/theme.css +82 -40
  259. package/resources/themes/lara-light-teal/theme.css +82 -40
  260. package/resources/themes/luna-amber/theme.css +82 -40
  261. package/resources/themes/luna-blue/theme.css +82 -40
  262. package/resources/themes/luna-green/theme.css +82 -40
  263. package/resources/themes/luna-pink/theme.css +82 -40
  264. package/resources/themes/md-dark-deeppurple/theme.css +82 -40
  265. package/resources/themes/md-dark-indigo/theme.css +82 -40
  266. package/resources/themes/md-light-deeppurple/theme.css +82 -40
  267. package/resources/themes/md-light-indigo/theme.css +82 -40
  268. package/resources/themes/mdc-dark-deeppurple/theme.css +82 -40
  269. package/resources/themes/mdc-dark-indigo/theme.css +82 -40
  270. package/resources/themes/mdc-light-deeppurple/theme.css +82 -40
  271. package/resources/themes/mdc-light-indigo/theme.css +82 -40
  272. package/resources/themes/nova/theme.css +82 -40
  273. package/resources/themes/nova-accent/theme.css +82 -40
  274. package/resources/themes/nova-alt/theme.css +82 -40
  275. package/resources/themes/nova-vue/theme.css +82 -40
  276. package/resources/themes/rhea/theme.css +82 -40
  277. package/resources/themes/saga-blue/theme.css +82 -40
  278. package/resources/themes/saga-green/theme.css +82 -40
  279. package/resources/themes/saga-orange/theme.css +82 -40
  280. package/resources/themes/saga-purple/theme.css +82 -40
  281. package/resources/themes/tailwind-light/theme.css +82 -40
  282. package/resources/themes/vela-blue/theme.css +82 -40
  283. package/resources/themes/vela-green/theme.css +82 -40
  284. package/resources/themes/vela-orange/theme.css +82 -40
  285. package/resources/themes/vela-purple/theme.css +82 -40
  286. package/ripple/ripple.cjs.js +1 -0
  287. package/ripple/ripple.cjs.min.js +1 -1
  288. package/ripple/ripple.esm.js +1 -0
  289. package/ripple/ripple.esm.min.js +1 -1
  290. package/ripple/ripple.js +1 -0
  291. package/ripple/ripple.min.js +1 -1
  292. package/selectbutton/SelectButton.d.ts +6 -2
  293. package/selectbutton/SelectButton.vue +89 -12
  294. package/selectbutton/selectbutton.cjs.js +97 -22
  295. package/selectbutton/selectbutton.cjs.min.js +1 -1
  296. package/selectbutton/selectbutton.esm.js +99 -24
  297. package/selectbutton/selectbutton.esm.min.js +1 -1
  298. package/selectbutton/selectbutton.js +97 -22
  299. package/selectbutton/selectbutton.min.js +1 -1
  300. package/slider/Slider.d.ts +9 -1
  301. package/slider/Slider.vue +50 -34
  302. package/slider/slider.cjs.js +59 -38
  303. package/slider/slider.cjs.min.js +1 -1
  304. package/slider/slider.esm.js +59 -38
  305. package/slider/slider.esm.min.js +1 -1
  306. package/slider/slider.js +59 -38
  307. package/slider/slider.min.js +1 -1
  308. package/splitbutton/SplitButton.d.ts +1 -1
  309. package/splitter/Splitter.vue +30 -1
  310. package/splitter/splitter.cjs.js +30 -1
  311. package/splitter/splitter.cjs.min.js +1 -1
  312. package/splitter/splitter.esm.js +30 -1
  313. package/splitter/splitter.esm.min.js +1 -1
  314. package/splitter/splitter.js +30 -1
  315. package/splitter/splitter.min.js +1 -1
  316. package/textarea/Textarea.vue +1 -2
  317. package/textarea/textarea.cjs.js +3 -5
  318. package/textarea/textarea.cjs.min.js +1 -1
  319. package/textarea/textarea.esm.js +4 -6
  320. package/textarea/textarea.esm.min.js +1 -1
  321. package/textarea/textarea.js +3 -5
  322. package/textarea/textarea.min.js +1 -1
  323. package/tieredmenu/TieredMenu.d.ts +1 -1
  324. package/tieredmenu/TieredMenuSub.vue +3 -3
  325. package/tieredmenu/tieredmenu.cjs.js +14 -8
  326. package/tieredmenu/tieredmenu.cjs.min.js +1 -1
  327. package/tieredmenu/tieredmenu.esm.js +15 -9
  328. package/tieredmenu/tieredmenu.esm.min.js +1 -1
  329. package/tieredmenu/tieredmenu.js +14 -8
  330. package/tieredmenu/tieredmenu.min.js +1 -1
  331. package/timeline/Timeline.d.ts +10 -1
  332. package/timeline/Timeline.vue +1 -1
  333. package/timeline/timeline.cjs.js +5 -1
  334. package/timeline/timeline.cjs.min.js +1 -1
  335. package/timeline/timeline.esm.js +5 -1
  336. package/timeline/timeline.esm.min.js +1 -1
  337. package/timeline/timeline.js +5 -1
  338. package/timeline/timeline.min.js +1 -1
  339. package/togglebutton/ToggleButton.d.ts +42 -0
  340. package/togglebutton/ToggleButton.vue +44 -7
  341. package/togglebutton/togglebutton.cjs.js +59 -13
  342. package/togglebutton/togglebutton.cjs.min.js +1 -1
  343. package/togglebutton/togglebutton.esm.js +60 -14
  344. package/togglebutton/togglebutton.esm.min.js +1 -1
  345. package/togglebutton/togglebutton.js +59 -13
  346. package/togglebutton/togglebutton.min.js +1 -1
  347. package/tooltip/tooltip.cjs.js +18 -11
  348. package/tooltip/tooltip.cjs.min.js +1 -1
  349. package/tooltip/tooltip.esm.js +18 -11
  350. package/tooltip/tooltip.esm.min.js +1 -1
  351. package/tooltip/tooltip.js +18 -11
  352. package/tooltip/tooltip.min.js +1 -1
  353. package/tree/Tree.vue +5 -1
  354. package/tree/TreeNode.vue +20 -19
  355. package/tree/tree.cjs.js +47 -32
  356. package/tree/tree.cjs.min.js +1 -1
  357. package/tree/tree.esm.js +47 -32
  358. package/tree/tree.esm.min.js +1 -1
  359. package/tree/tree.js +47 -32
  360. package/tree/tree.min.js +1 -1
  361. package/treeselect/TreeSelect.d.ts +26 -10
  362. package/treeselect/TreeSelect.vue +52 -29
  363. package/treeselect/treeselect.cjs.js +74 -41
  364. package/treeselect/treeselect.cjs.min.js +1 -1
  365. package/treeselect/treeselect.esm.js +76 -43
  366. package/treeselect/treeselect.esm.min.js +1 -1
  367. package/treeselect/treeselect.js +74 -41
  368. package/treeselect/treeselect.min.js +1 -1
  369. package/tristatecheckbox/TriStateCheckbox.d.ts +20 -4
  370. package/tristatecheckbox/TriStateCheckbox.vue +52 -15
  371. package/tristatecheckbox/tristatecheckbox.cjs.js +67 -26
  372. package/tristatecheckbox/tristatecheckbox.cjs.min.js +1 -1
  373. package/tristatecheckbox/tristatecheckbox.esm.js +68 -27
  374. package/tristatecheckbox/tristatecheckbox.esm.min.js +1 -1
  375. package/tristatecheckbox/tristatecheckbox.js +67 -26
  376. package/tristatecheckbox/tristatecheckbox.min.js +1 -1
  377. package/utils/Utils.d.ts +3 -2
  378. package/utils/utils.cjs.js +220 -173
  379. package/utils/utils.cjs.min.js +1 -1
  380. package/utils/utils.esm.js +220 -173
  381. package/utils/utils.esm.min.js +1 -1
  382. package/utils/utils.js +220 -173
  383. package/utils/utils.min.js +1 -1
  384. package/vetur-attributes.json +612 -136
  385. package/vetur-tags.json +180 -59
  386. package/virtualscroller/VirtualScroller.d.ts +10 -0
  387. package/virtualscroller/VirtualScroller.vue +18 -17
  388. package/virtualscroller/virtualscroller.cjs.js +22 -20
  389. package/virtualscroller/virtualscroller.cjs.min.js +1 -1
  390. package/virtualscroller/virtualscroller.esm.js +22 -20
  391. package/virtualscroller/virtualscroller.esm.min.js +1 -1
  392. package/virtualscroller/virtualscroller.js +22 -20
  393. package/virtualscroller/virtualscroller.min.js +1 -1
  394. package/web-types.json +1745 -338
@@ -1,54 +1,61 @@
1
1
  <template>
2
- <span ref="container" :class="containerClass" aria-haspopup="listbox" :aria-owns="listId" :aria-expanded="overlayVisible" :style="style">
3
- <input ref="input" :class="inputFieldClass" :style="inputStyle" v-bind="$attrs" :value="inputValue" @click="onInputClicked" @input="onInput" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @change="onChange"
4
- type="text" autoComplete="off" v-if="!multiple" role="searchbox" aria-autocomplete="list" :aria-controls="listId">
5
- <ul ref="multiContainer" :class="multiContainerClass" v-if="multiple" @click="onMultiContainerClick">
6
- <li v-for="(item, i) of modelValue" :key="i" class="p-autocomplete-token">
7
- <slot name="chip" :value="item">
8
- <span class="p-autocomplete-token-label">{{getItemContent(item)}}</span>
2
+ <div ref="container" :class="containerClass" @click="onContainerClick">
3
+ <input v-if="!multiple" ref="focusInput" :id="inputId" type="text" :style="inputStyle" :class="inputStyleClass" :value="inputValue" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1" :disabled="disabled" autocomplete="off"
4
+ role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="listbox" aria-autocomplete="list" :aria-expanded="overlayVisible" :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined"
5
+ @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @input="onInput" @change="onChange" v-bind="inputProps" />
6
+ <ul v-if="multiple" ref="multiContainer" :class="multiContainerClass" tabindex="-1" role="listbox" aria-orientation="horizontal" :aria-activedescendant="focused ? focusedMultipleOptionId : undefined"
7
+ @focus="onMultipleContainerFocus" @blur="onMultipleContainerBlur" @keydown="onMultipleContainerKeyDown">
8
+ <li v-for="(option, i) of modelValue" :key="i" :id="id + '_multiple_option_' + i" :class="['p-autocomplete-token', {'p-focus': focusedMultipleOptionIndex === i}]"
9
+ role="option" :aria-label="getOptionLabel(option)" :aria-selected="true" :aria-setsize="modelValue.length" :aria-posinset="i + 1">
10
+ <slot name="chip" :value="option">
11
+ <span class="p-autocomplete-token-label">{{getOptionLabel(option)}}</span>
9
12
  </slot>
10
- <span class="p-autocomplete-token-icon pi pi-times-circle" @click="removeItem($event, i)"></span>
13
+ <span class="p-autocomplete-token-icon pi pi-times-circle" @click="removeOption($event, i)" aria-hidden="true"></span>
11
14
  </li>
12
- <li class="p-autocomplete-input-token">
13
- <input ref="input" type="text" autoComplete="off" v-bind="$attrs" @input="onInput" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @change="onChange"
14
- role="searchbox" aria-autocomplete="list" :aria-controls="listId">
15
+ <li class="p-autocomplete-input-token" role="option">
16
+ <input ref="focusInput" :id="inputId" type="text" :style="inputStyle" :class="inputClass" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1" :disabled="disabled" autocomplete="off"
17
+ role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="listbox" aria-autocomplete="list" :aria-expanded="overlayVisible" :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined"
18
+ @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @input="onInput" @change="onChange" v-bind="inputProps" />
15
19
  </li>
16
20
  </ul>
17
- <i :class="loadingIconClass" v-if="searching"></i>
18
- <Button ref="dropdownButton" type="button" icon="pi pi-chevron-down" class="p-autocomplete-dropdown" :disabled="$attrs.disabled" @click="onDropdownClick" v-if="dropdown"/>
21
+ <i v-if="searching" :class="loadingIconClass" aria-hidden="true"></i>
22
+ <Button v-if="dropdown" ref="dropdownButton" type="button" icon="pi pi-chevron-down" class="p-autocomplete-dropdown" tabindex="-1" :disabled="disabled" aria-hidden="true" @click="onDropdownClick" />
23
+ <span role="status" aria-live="polite" class="p-hidden-accessible">
24
+ {{searchResultMessageText}}
25
+ </span>
19
26
  <Portal :appendTo="appendTo">
20
- <transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
21
- <div :ref="overlayRef" :class="panelStyleClass" :style="{'max-height': virtualScrollerDisabled ? scrollHeight : ''}" v-if="overlayVisible" @click="onOverlayClick">
22
- <slot name="header" :value="modelValue" :suggestions="suggestions"></slot>
23
- <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="{'height': scrollHeight}" :items="suggestions" :disabled="virtualScrollerDisabled">
24
- <template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle }">
25
- <ul :id="listId" :ref="(el) => listRef(el, contentRef)" :class="['p-autocomplete-items', styleClass]" :style="contentStyle" role="listbox">
26
- <template v-if="!optionGroupLabel">
27
- <li v-for="(item, i) of items" class="p-autocomplete-item" :key="getOptionRenderKey(item)" @click="selectItem($event, item)" role="option" v-ripple :data-index="getOptionIndex(i, getItemOptions)">
28
- <slot name="item" :item="item" :index="getOptionIndex(i, getItemOptions)">{{getItemContent(item)}}</slot>
27
+ <transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
28
+ <div v-if="overlayVisible" :ref="overlayRef" :class="panelStyleClass" :style="{...panelStyle, 'max-height': virtualScrollerDisabled ? scrollHeight : ''}" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="panelProps">
29
+ <slot name="header" :value="modelValue" :suggestions="visibleOptions"></slot>
30
+ <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="{'height': scrollHeight}" :items="visibleOptions" :tabindex="-1" :disabled="virtualScrollerDisabled">
31
+ <template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle, itemSize }">
32
+ <ul :ref="(el) => listRef(el, contentRef)" :id="id + '_list'" :class="['p-autocomplete-items', styleClass]" :style="contentStyle" role="listbox">
33
+ <template v-for="(option, i) of items" :key="getOptionRenderKey(option, getOptionIndex(i, getItemOptions))">
34
+ <li v-if="isOptionGroup(option)" :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}" class="p-autocomplete-item-group" role="option">
35
+ <slot name="optiongroup" :option="option.optionGroup" :item="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(option.optionGroup)}}</slot>
36
+ </li>
37
+ <li v-else v-ripple :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}"
38
+ :class="['p-autocomplete-item', {'p-highlight': isSelected(option), 'p-focus': focusedOptionIndex === getOptionIndex(i, getItemOptions), 'p-disabled': isOptionDisabled(option)}]"
39
+ role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" :aria-disabled="isOptionDisabled(option)" :aria-setsize="ariaSetSize" :aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
40
+ @click="onOptionSelect($event, option)" @mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))">
41
+ <slot v-if="$slots.option" name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot>
42
+ <slot v-else name="item" :item="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot> <!--TODO: Deprecated since v3.16.0-->
29
43
  </li>
30
- </template>
31
- <template v-else>
32
- <template v-for="(optionGroup, i) of items" :key="getOptionGroupRenderKey(optionGroup)">
33
- <li class="p-autocomplete-item-group">
34
- <slot name="optiongroup" :item="optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(optionGroup)}}</slot>
35
- </li>
36
- <li v-for="(item, j) of getOptionGroupChildren(optionGroup)" class="p-autocomplete-item" :key="j" @click="selectItem($event, item)" role="option" v-ripple :data-group="i" :data-index="getOptionIndex(j, getItemOptions)">
37
- <slot name="item" :item="item" :index="getOptionIndex(j, getItemOptions)">{{getItemContent(item)}}</slot>
38
- </li>
39
- </template>
40
44
  </template>
41
45
  </ul>
46
+ <span role="status" aria-live="polite" class="p-hidden-accessible">
47
+ {{selectedMessageText}}
48
+ </span>
42
49
  </template>
43
- <template v-slot:loader="{ options }" v-if="$slots.loader">
50
+ <template v-if="$slots.loader" v-slot:loader="{ options }">
44
51
  <slot name="loader" :options="options"></slot>
45
52
  </template>
46
53
  </VirtualScroller>
47
- <slot name="footer" :value="modelValue" :suggestions="suggestions"></slot>
54
+ <slot name="footer" :value="modelValue" :suggestions="visibleOptions"></slot>
48
55
  </div>
49
56
  </transition>
50
57
  </Portal>
51
- </span>
58
+ </div>
52
59
  </template>
53
60
 
54
61
  <script>
@@ -61,18 +68,19 @@ import Portal from 'primevue/portal';
61
68
 
62
69
  export default {
63
70
  name: 'AutoComplete',
64
- inheritAttrs: false,
65
- emits: ['update:modelValue', 'item-select', 'item-unselect', 'dropdown-click', 'clear', 'complete'],
71
+ emits: ['update:modelValue', 'change', 'focus', 'blur', 'item-select', 'item-unselect', 'dropdown-click', 'clear', 'complete', 'before-show', 'before-hide', 'show', 'hide'],
66
72
  props: {
67
73
  modelValue: null,
68
74
  suggestions: {
69
75
  type: Array,
70
76
  default: null
71
77
  },
72
- field: {
78
+ field: { // TODO: Deprecated since v3.16.0
73
79
  type: [String,Function],
74
80
  default: null
75
81
  },
82
+ optionLabel: null,
83
+ optionDisabled: null,
76
84
  optionGroupLabel: null,
77
85
  optionGroupChildren: null,
78
86
  scrollHeight: {
@@ -87,7 +95,7 @@ export default {
87
95
  type: String,
88
96
  default: 'blank'
89
97
  },
90
- autoHighlight: {
98
+ autoHighlight: { // TODO: Deprecated since v3.16.0
91
99
  type: Boolean,
92
100
  default: false
93
101
  },
@@ -95,6 +103,18 @@ export default {
95
103
  type: Boolean,
96
104
  default: false
97
105
  },
106
+ disabled: {
107
+ type: Boolean,
108
+ default: false
109
+ },
110
+ placeholder: {
111
+ type: String,
112
+ default: null
113
+ },
114
+ dataKey: {
115
+ type: String,
116
+ default: null
117
+ },
98
118
  minLength: {
99
119
  type: Number,
100
120
  default: 1
@@ -115,45 +135,95 @@ export default {
115
135
  type: Boolean,
116
136
  default: false
117
137
  },
118
- inputClass: null,
138
+ inputId: String,
119
139
  inputStyle: null,
120
- class: null,
121
- style: null,
140
+ inputClass: null,
141
+ inputProps: null,
142
+ panelStyle: null,
122
143
  panelClass: null,
144
+ panelProps: null,
145
+ loadingIcon: {
146
+ type: String,
147
+ default: 'pi pi-spinner'
148
+ },
123
149
  virtualScrollerOptions: {
124
150
  type: Object,
125
151
  default: null
126
152
  },
127
- loadingIcon: {
153
+ autoOptionFocus: {
154
+ type: Boolean,
155
+ default: true
156
+ },
157
+ searchLocale: {
128
158
  type: String,
129
- default: 'pi pi-spinner'
159
+ default: undefined
160
+ },
161
+ searchMessage: {
162
+ type: String,
163
+ default: null
164
+ },
165
+ selectionMessage: {
166
+ type: String,
167
+ default: null
168
+ },
169
+ emptySelectionMessage: {
170
+ type: String,
171
+ default: null
172
+ },
173
+ emptySearchMessage: {
174
+ type: String,
175
+ default: null
176
+ },
177
+ tabindex: {
178
+ type: Number,
179
+ default: 0
180
+ },
181
+ 'aria-label': {
182
+ type: String,
183
+ default: null
184
+ },
185
+ 'aria-labelledby': {
186
+ type: String,
187
+ default: null
130
188
  }
131
189
  },
132
- timeout: null,
133
190
  outsideClickListener: null,
134
191
  resizeListener: null,
135
192
  scrollHandler: null,
136
193
  overlay: null,
137
194
  virtualScroller: null,
195
+ searchTimeout: null,
196
+ selectOnFocus: false,
197
+ focusOnHover: false,
138
198
  data() {
139
199
  return {
140
- searching: false,
200
+ id: UniqueComponentId(),
141
201
  focused: false,
202
+ focusedOptionIndex: -1,
203
+ focusedMultipleOptionIndex: -1,
142
204
  overlayVisible: false,
143
- inputTextValue: null,
144
- highlightItem: null
145
- };
205
+ searching: false
206
+ }
146
207
  },
147
208
  watch: {
148
209
  suggestions() {
149
210
  if (this.searching) {
150
- if (this.suggestions && this.suggestions.length)
151
- this.showOverlay();
152
- else
153
- this.hideOverlay();
154
-
211
+ ObjectUtils.isNotEmpty(this.suggestions) ? this.show() : this.hide();
212
+ this.focusedOptionIndex = this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
155
213
  this.searching = false;
156
214
  }
215
+
216
+ this.autoUpdateModel();
217
+ }
218
+ },
219
+ mounted() {
220
+ this.id = this.$attrs.id || this.id;
221
+
222
+ this.autoUpdateModel();
223
+ },
224
+ updated() {
225
+ if (this.overlayVisible) {
226
+ this.alignOverlay();
157
227
  }
158
228
  },
159
229
  beforeUnmount() {
@@ -170,20 +240,24 @@ export default {
170
240
  this.overlay = null;
171
241
  }
172
242
  },
173
- updated() {
174
- if (this.overlayVisible) {
175
- this.alignOverlay();
176
- }
177
- },
178
243
  methods: {
179
244
  getOptionIndex(index, fn) {
180
245
  return this.virtualScrollerDisabled ? index : (fn && fn(index)['index']);
181
246
  },
182
- getOptionRenderKey(option) {
183
- return this.getItemContent(option);
247
+ getOptionLabel(option) {
248
+ return this.field || this.optionLabel ? ObjectUtils.resolveFieldData(option, this.field || this.optionLabel) : option;
184
249
  },
185
- getOptionGroupRenderKey(optionGroup) {
186
- return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
250
+ getOptionValue(option) {
251
+ return option; // TODO: The 'optionValue' properties can be added.
252
+ },
253
+ getOptionRenderKey(option, index) {
254
+ return (this.dataKey ? ObjectUtils.resolveFieldData(option, this.dataKey) : this.getOptionLabel(option)) + '_' + index;
255
+ },
256
+ isOptionDisabled(option) {
257
+ return this.optionDisabled ? ObjectUtils.resolveFieldData(option, this.optionDisabled) : false;
258
+ },
259
+ isOptionGroup(option) {
260
+ return this.optionGroupLabel && option.optionGroup && option.group;
187
261
  },
188
262
  getOptionGroupLabel(optionGroup) {
189
263
  return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
@@ -191,28 +265,393 @@ export default {
191
265
  getOptionGroupChildren(optionGroup) {
192
266
  return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren);
193
267
  },
268
+ getAriaPosInset(index) {
269
+ return (this.optionGroupLabel ? index - this.visibleOptions.slice(0, index).filter(option => this.isOptionGroup(option)).length : index) + 1;
270
+ },
271
+ show(isFocus) {
272
+ this.$emit('before-show');
273
+ this.overlayVisible = true;
274
+ this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
275
+
276
+ isFocus && this.$refs.focusInput.focus();
277
+ },
278
+ hide(isFocus) {
279
+ const _hide = () => {
280
+ this.$emit('before-hide');
281
+ this.overlayVisible = false;
282
+ this.focusedOptionIndex = -1;
283
+
284
+ isFocus && this.$refs.focusInput.focus();
285
+ }
286
+
287
+ setTimeout(() => { _hide() }, 0); // For ScreenReaders
288
+ },
289
+ onFocus(event) {
290
+ this.focused = true;
291
+ this.focusedOptionIndex = this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
292
+ this.overlayVisible && this.scrollInView(this.focusedOptionIndex);
293
+ this.$emit('focus', event);
294
+ },
295
+ onBlur(event) {
296
+ this.focused = false;
297
+ this.focusedOptionIndex = -1;
298
+ this.$emit('blur', event);
299
+ },
300
+ onKeyDown(event) {
301
+ switch (event.code) {
302
+ case 'ArrowDown':
303
+ this.onArrowDownKey(event);
304
+ break;
305
+
306
+ case 'ArrowUp':
307
+ this.onArrowUpKey(event);
308
+ break;
309
+
310
+ case 'ArrowLeft':
311
+ this.onArrowLeftKey(event);
312
+ break;
313
+
314
+ case 'ArrowRight':
315
+ this.onArrowRightKey(event);
316
+ break;
317
+
318
+ case 'Home':
319
+ this.onHomeKey(event);
320
+ break;
321
+
322
+ case 'End':
323
+ this.onEndKey(event);
324
+ break;
325
+
326
+ case 'PageDown':
327
+ this.onPageDownKey(event);
328
+ break;
329
+
330
+ case 'PageUp':
331
+ this.onPageUpKey(event);
332
+ break;
333
+
334
+ case 'Enter':
335
+ this.onEnterKey(event);
336
+ break;
337
+
338
+ case 'Escape':
339
+ this.onEscapeKey(event);
340
+ break;
341
+
342
+ case 'Tab':
343
+ this.onTabKey(event);
344
+ break;
345
+
346
+ case 'Backspace':
347
+ this.onBackspaceKey(event);
348
+ break;
349
+
350
+ case 'ShiftLeft':
351
+ case 'ShiftRight':
352
+ //NOOP
353
+ break;
354
+
355
+ default:
356
+ break;
357
+ }
358
+ },
359
+ onInput(event) {
360
+ if (this.searchTimeout) {
361
+ clearTimeout(this.searchTimeout);
362
+ }
363
+
364
+ let query = event.target.value;
365
+ if (!this.multiple) {
366
+ this.updateModel(event, query);
367
+ }
368
+
369
+ if (query.length === 0) {
370
+ this.hide();
371
+ this.$emit('clear');
372
+ }
373
+ else {
374
+ if (query.length >= this.minLength) {
375
+ this.focusedOptionIndex = -1;
376
+
377
+ this.searchTimeout = setTimeout(() => {
378
+ this.search(event, query, 'input');
379
+ }, this.delay);
380
+ }
381
+ else {
382
+ this.hide();
383
+ }
384
+ }
385
+ },
386
+ onChange(event) {
387
+ if (this.forceSelection) {
388
+ let valid = false;
389
+
390
+ if (this.visibleOptions) {
391
+ const matchedValue = this.visibleOptions.find(option => this.isOptionMatched(option, event.target.value));
392
+
393
+ if (matchedValue !== undefined) {
394
+ valid = true;
395
+ !this.isSelected(matchedValue) && this.onOptionSelect(event, matchedValue);
396
+ }
397
+ }
398
+
399
+ if (!valid) {
400
+ this.$refs.focusInput.value = '';
401
+ this.$emit('clear');
402
+ !this.multiple && this.updateModel(event, null);
403
+ }
404
+ }
405
+ },
406
+ onMultipleContainerFocus() {
407
+ this.focused = true;
408
+ },
409
+ onMultipleContainerBlur() {
410
+ this.focusedMultipleOptionIndex = -1;
411
+ this.focused = false;
412
+ },
413
+ onMultipleContainerKeyDown(event) {
414
+ switch (event.code) {
415
+ case 'ArrowLeft':
416
+ this.onArrowLeftKeyOnMultiple(event);
417
+ break;
418
+
419
+ case 'ArrowRight':
420
+ this.onArrowRightKeyOnMultiple(event);
421
+ break;
422
+
423
+ case 'Backspace':
424
+ this.onBackspaceKeyOnMultiple(event);
425
+ break;
426
+
427
+ default:
428
+ break;
429
+ }
430
+ },
431
+ onContainerClick(event) {
432
+ if (this.disabled || this.searching) {
433
+ return;
434
+ }
435
+
436
+ if (this.isDropdownClicked(event) || event.target.tagName === 'INPUT') {
437
+ return;
438
+ }
439
+ else if (!this.overlay || !this.overlay.contains(event.target)) {
440
+ if (this.completeOnFocus) {
441
+ this.search(event, '', 'click');
442
+ }
443
+
444
+ this.$refs.focusInput.focus();
445
+ }
446
+ },
447
+ onDropdownClick(event) {
448
+ let query = undefined;
449
+
450
+ if (this.overlayVisible) {
451
+ this.hide(true);
452
+ }
453
+ else {
454
+ this.$refs.focusInput.focus();
455
+ query = this.$refs.focusInput.value;
456
+
457
+ if (this.dropdownMode === 'blank')
458
+ this.search(event, '', 'dropdown');
459
+ else if (this.dropdownMode === 'current')
460
+ this.search(event, query, 'dropdown');
461
+ }
462
+
463
+ this.$emit('dropdown-click', { originalEvent: event, query });
464
+ },
465
+ onOptionSelect(event, option) {
466
+ const value = this.getOptionValue(option);
467
+
468
+ if (this.multiple) {
469
+ this.$refs.focusInput.value = '';
470
+
471
+ if (!this.isSelected(option)) {
472
+ this.updateModel(event, [...(this.modelValue || []), value]);
473
+ }
474
+ }
475
+ else {
476
+ this.updateModel(event, value);
477
+ }
478
+
479
+ this.$emit('item-select', { originalEvent: event, value: option });
480
+
481
+ this.hide(true);
482
+ },
483
+ onOptionMouseMove(event, index) {
484
+ if (this.focusOnHover) {
485
+ this.changeFocusedOptionIndex(event, index);
486
+ }
487
+ },
488
+ onOverlayClick(event) {
489
+ OverlayEventBus.emit('overlay-click', {
490
+ originalEvent: event,
491
+ target: this.$el
492
+ });
493
+ },
494
+ onOverlayKeyDown(event) {
495
+ switch (event.code) {
496
+ case 'Escape':
497
+ this.onEscapeKey(event);
498
+ break;
499
+
500
+ default:
501
+ break;
502
+ }
503
+ },
504
+ onArrowDownKey(event) {
505
+ if (!this.overlayVisible) {
506
+ return;
507
+ }
508
+
509
+ const optionIndex = this.focusedOptionIndex !== -1 ? this.findNextOptionIndex(this.focusedOptionIndex) : this.findFirstFocusedOptionIndex();
510
+
511
+ this.changeFocusedOptionIndex(event, optionIndex);
512
+
513
+ event.preventDefault();
514
+ },
515
+ onArrowUpKey(event) {
516
+ if (!this.overlayVisible) {
517
+ return;
518
+ }
519
+
520
+ if (event.altKey) {
521
+ if (this.focusedOptionIndex !== -1) {
522
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
523
+ }
524
+
525
+ this.overlayVisible && this.hide();
526
+ event.preventDefault();
527
+ }
528
+ else {
529
+ const optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.findLastFocusedOptionIndex();
530
+
531
+ this.changeFocusedOptionIndex(event, optionIndex);
532
+
533
+ event.preventDefault();
534
+ }
535
+ },
536
+ onArrowLeftKey(event) {
537
+ const target = event.currentTarget;
538
+ this.focusedOptionIndex = -1;
539
+
540
+ if (this.multiple) {
541
+ if (ObjectUtils.isEmpty(target.value) && this.hasSelectedOption) {
542
+ this.$refs.multiContainer.focus();
543
+ this.focusedMultipleOptionIndex = this.modelValue.length;
544
+ }
545
+ else {
546
+ event.stopPropagation(); // To prevent onArrowLeftKeyOnMultiple method
547
+ }
548
+ }
549
+ },
550
+ onArrowRightKey(event) {
551
+ this.focusedOptionIndex = -1;
552
+
553
+ this.multiple && event.stopPropagation(); // To prevent onArrowRightKeyOnMultiple method
554
+ },
555
+ onHomeKey(event) {
556
+ event.currentTarget.setSelectionRange(0, 0);
557
+ this.focusedOptionIndex = -1;
558
+
559
+ event.preventDefault();
560
+ },
561
+ onEndKey(event) {
562
+ const target = event.currentTarget;
563
+ const len = target.value.length;
564
+ target.setSelectionRange(len, len);
565
+ this.focusedOptionIndex = -1;
566
+
567
+ event.preventDefault();
568
+ },
569
+ onPageUpKey(event) {
570
+ this.scrollInView(0);
571
+ event.preventDefault();
572
+ },
573
+ onPageDownKey(event) {
574
+ this.scrollInView(this.visibleOptions.length - 1);
575
+ event.preventDefault();
576
+ },
577
+ onEnterKey(event) {
578
+ if (!this.overlayVisible) {
579
+ this.onArrowDownKey(event);
580
+ }
581
+ else {
582
+ if (this.focusedOptionIndex !== -1) {
583
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
584
+ }
585
+
586
+ this.hide();
587
+ }
588
+
589
+ event.preventDefault();
590
+ },
591
+ onEscapeKey(event) {
592
+ this.overlayVisible && this.hide(true);
593
+ event.preventDefault();
594
+ },
595
+ onTabKey(event) {
596
+ if (this.focusedOptionIndex !== -1) {
597
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
598
+ }
599
+
600
+ this.overlayVisible && this.hide();
601
+ },
602
+ onBackspaceKey(event) {
603
+ if (this.multiple) {
604
+ if (ObjectUtils.isNotEmpty(this.modelValue) && !this.$refs.focusInput.value) {
605
+ const removedValue = this.modelValue[this.modelValue.length - 1];
606
+ const newValue = this.modelValue.slice(0, -1);
607
+
608
+ this.$emit('update:modelValue', newValue);
609
+ this.$emit('item-unselect', { originalEvent: event, value: removedValue });
610
+ }
611
+
612
+ event.stopPropagation(); // To prevent onBackspaceKeyOnMultiple method
613
+ }
614
+ },
615
+ onArrowLeftKeyOnMultiple() {
616
+ this.focusedMultipleOptionIndex = this.focusedMultipleOptionIndex < 1 ? 0 : this.focusedMultipleOptionIndex - 1;
617
+ },
618
+ onArrowRightKeyOnMultiple() {
619
+ this.focusedMultipleOptionIndex++;
620
+
621
+ if (this.focusedMultipleOptionIndex > (this.modelValue.length - 1)) {
622
+ this.focusedMultipleOptionIndex = -1;
623
+ this.$refs.focusInput.focus();
624
+ }
625
+ },
626
+ onBackspaceKeyOnMultiple(event) {
627
+ if (this.focusedMultipleOptionIndex !== -1) {
628
+ this.removeOption(event, this.focusedMultipleOptionIndex);
629
+ }
630
+ },
194
631
  onOverlayEnter(el) {
195
632
  ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
196
633
  this.alignOverlay();
634
+ },
635
+ onOverlayAfterEnter() {
197
636
  this.bindOutsideClickListener();
198
637
  this.bindScrollListener();
199
638
  this.bindResizeListener();
200
639
 
201
- if (this.autoHighlight && this.suggestions && this.suggestions.length) {
202
- DomHandler.addClass(this.list.firstElementChild, 'p-highlight');
203
- }
640
+ this.$emit('show');
204
641
  },
205
642
  onOverlayLeave() {
206
643
  this.unbindOutsideClickListener();
207
644
  this.unbindScrollListener();
208
645
  this.unbindResizeListener();
646
+
647
+ this.$emit('hide');
209
648
  this.overlay = null;
210
649
  },
211
650
  onOverlayAfterLeave(el) {
212
651
  ZIndexUtils.clear(el);
213
652
  },
214
653
  alignOverlay() {
215
- let target = this.multiple ? this.$refs.multiContainer : this.$refs.input;
654
+ let target = this.multiple ? this.$refs.multiContainer : this.$refs.focusInput;
216
655
  if (this.appendTo === 'self') {
217
656
  DomHandler.relativePosition(this.overlay, target);
218
657
  }
@@ -225,17 +664,23 @@ export default {
225
664
  if (!this.outsideClickListener) {
226
665
  this.outsideClickListener = (event) => {
227
666
  if (this.overlayVisible && this.overlay && this.isOutsideClicked(event)) {
228
- this.hideOverlay();
667
+ this.hide();
229
668
  }
230
669
  };
231
670
  document.addEventListener('click', this.outsideClickListener);
232
671
  }
233
672
  },
673
+ unbindOutsideClickListener() {
674
+ if (this.outsideClickListener) {
675
+ document.removeEventListener('click', this.outsideClickListener);
676
+ this.outsideClickListener = null;
677
+ }
678
+ },
234
679
  bindScrollListener() {
235
680
  if (!this.scrollHandler) {
236
681
  this.scrollHandler = new ConnectedOverlayScrollHandler(this.$refs.container, () => {
237
682
  if (this.overlayVisible) {
238
- this.hideOverlay();
683
+ this.hide();
239
684
  }
240
685
  });
241
686
  }
@@ -251,7 +696,7 @@ export default {
251
696
  if (!this.resizeListener) {
252
697
  this.resizeListener = () => {
253
698
  if (this.overlayVisible && !DomHandler.isTouchDevice()) {
254
- this.hideOverlay();
699
+ this.hide();
255
700
  }
256
701
  };
257
702
  window.addEventListener('resize', this.resizeListener);
@@ -270,79 +715,47 @@ export default {
270
715
  if (this.multiple)
271
716
  return event.target === this.$refs.multiContainer || this.$refs.multiContainer.contains(event.target);
272
717
  else
273
- return event.target === this.$refs.input;
718
+ return event.target === this.$refs.focusInput;
274
719
  },
275
720
  isDropdownClicked(event) {
276
721
  return this.$refs.dropdownButton ? (event.target === this.$refs.dropdownButton || this.$refs.dropdownButton.$el.contains(event.target)) : false;
277
722
  },
278
- unbindOutsideClickListener() {
279
- if (this.outsideClickListener) {
280
- document.removeEventListener('click', this.outsideClickListener);
281
- this.outsideClickListener = null;
282
- }
723
+ isOptionMatched(option, value) {
724
+ return this.isValidOption(option) && this.getOptionLabel(option).toLocaleLowerCase(this.searchLocale) === value.toLocaleLowerCase(this.searchLocale);
283
725
  },
284
- selectItem(event, item) {
285
- if (this.multiple) {
286
- this.$refs.input.value = '';
287
- this.inputTextValue = '';
288
-
289
- if (!this.isSelected(item)) {
290
- let newValue = this.modelValue ? [...this.modelValue, item] : [item];
291
- this.$emit('update:modelValue', newValue);
292
- }
293
- }
294
- else {
295
- this.$emit('update:modelValue', item);
296
- }
297
-
298
- this.$emit('item-select', {
299
- originalEvent: event,
300
- value: item
301
- });
302
-
303
- this.focus();
304
- this.hideOverlay();
726
+ isValidOption(option) {
727
+ return option && !(this.isOptionDisabled(option) || this.isOptionGroup(option));
305
728
  },
306
- onMultiContainerClick(event) {
307
- this.focus();
308
- if(this.completeOnFocus) {
309
- this.search(event, '', 'click');
310
- }
729
+ isValidSelectedOption(option) {
730
+ return this.isValidOption(option) && this.isSelected(option);
311
731
  },
312
- removeItem(event, index) {
313
- let removedValue = this.modelValue[index];
314
- let newValue = this.modelValue.filter((val, i) => (index !== i));
315
- this.$emit('update:modelValue', newValue);
316
- this.$emit('item-unselect', {
317
- originalEvent: event,
318
- value: removedValue
319
- });
732
+ isSelected(option) {
733
+ return ObjectUtils.equals(this.modelValue, this.getOptionValue(option), this.equalityKey);
320
734
  },
321
- onDropdownClick(event) {
322
- this.focus();
323
- const query = this.$refs.input.value;
324
-
325
- if (this.dropdownMode === 'blank')
326
- this.search(event, '', 'dropdown');
327
- else if (this.dropdownMode === 'current')
328
- this.search(event, query, 'dropdown');
329
-
330
- this.$emit('dropdown-click', {
331
- originalEvent: event,
332
- query: query
333
- });
735
+ findFirstOptionIndex() {
736
+ return this.visibleOptions.findIndex(option => this.isValidOption(option));
334
737
  },
335
- getItemContent(item) {
336
- return this.field ? ObjectUtils.resolveFieldData(item, this.field) : item;
738
+ findLastOptionIndex() {
739
+ return this.visibleOptions.findLastIndex(option => this.isValidOption(option));
337
740
  },
338
- showOverlay() {
339
- this.overlayVisible = true;
741
+ findNextOptionIndex(index) {
742
+ const matchedOptionIndex = index < (this.visibleOptions.length - 1) ? this.visibleOptions.slice(index + 1).findIndex(option => this.isValidOption(option)) : -1;
743
+ return matchedOptionIndex > -1 ? matchedOptionIndex + index + 1 : index;
340
744
  },
341
- hideOverlay() {
342
- this.overlayVisible = false;
745
+ findPrevOptionIndex(index) {
746
+ const matchedOptionIndex = index > 0 ? this.visibleOptions.slice(0, index).findLastIndex(option => this.isValidOption(option)) : -1;
747
+ return matchedOptionIndex > -1 ? matchedOptionIndex : index;
343
748
  },
344
- focus() {
345
- this.$refs.input.focus();
749
+ findSelectedOptionIndex() {
750
+ return this.hasSelectedOption ? this.visibleOptions.findIndex(option => this.isValidSelectedOption(option)) : -1;
751
+ },
752
+ findFirstFocusedOptionIndex() {
753
+ const selectedIndex = this.findSelectedOptionIndex();
754
+ return selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex;
755
+ },
756
+ findLastFocusedOptionIndex() {
757
+ const selectedIndex = this.findSelectedOptionIndex();
758
+ return selectedIndex < 0 ? this.findLastOptionIndex() : selectedIndex;
346
759
  },
347
760
  search(event, query, source) {
348
761
  //allow empty string but not undefined or null
@@ -356,248 +769,92 @@ export default {
356
769
  }
357
770
 
358
771
  this.searching = true;
359
- this.$emit('complete', {
360
- originalEvent: event,
361
- query: query
362
- });
363
- },
364
- onInputClicked(event) {
365
- if(this.completeOnFocus) {
366
- this.search(event, '', 'click');
367
- }
772
+ this.$emit('complete', { originalEvent: event, query });
368
773
  },
369
- onInput(event) {
370
- this.inputTextValue = event.target.value;
371
-
372
- if (this.timeout) {
373
- clearTimeout(this.timeout);
374
- }
774
+ removeOption(event, index) {
775
+ const removedOption = this.modelValue[index];
776
+ const value = this.modelValue.filter((_, i) => i !== index).map(option => this.getOptionValue(option));
375
777
 
376
- let query = event.target.value;
377
- if (!this.multiple) {
378
- this.$emit('update:modelValue', query);
379
- }
380
-
381
- if (query.length === 0) {
382
- this.hideOverlay();
383
- this.$emit('clear');
384
- }
385
- else {
386
- if (query.length >= this.minLength) {
387
- this.timeout = setTimeout(() => {
388
- this.search(event, query, 'input');
389
- }, this.delay);
390
- }
391
- else {
392
- this.hideOverlay();
393
- }
394
- }
395
- },
396
- onFocus() {
397
- this.focused = true;
778
+ this.updateModel(event, value);
779
+ this.$emit('item-unselect', { originalEvent: event, value: removedOption });
780
+ this.$refs.focusInput.focus();
398
781
  },
399
- onBlur() {
400
- this.focused = false;
401
- },
402
- onKeyDown(event) {
403
- if (this.overlayVisible) {
404
- let highlightItem = DomHandler.findSingle(this.list, 'li.p-highlight');
405
-
406
- switch(event.which) {
407
- //down
408
- case 40:
409
- if (highlightItem) {
410
- let nextElement = this.findNextItem(highlightItem);
411
- if (nextElement) {
412
- DomHandler.addClass(nextElement, 'p-highlight');
413
- DomHandler.removeClass(highlightItem, 'p-highlight');
414
- nextElement.scrollIntoView({ block: 'nearest', inline: 'start' });
415
- }
416
- }
417
- else {
418
- highlightItem = this.list.firstElementChild;
419
- if (DomHandler.hasClass(highlightItem, 'p-autocomplete-item-group')) {
420
- highlightItem = this.findNextItem(highlightItem);
421
- }
422
-
423
- if (highlightItem) {
424
- DomHandler.addClass(highlightItem, 'p-highlight');
425
- }
426
- }
427
-
428
- event.preventDefault();
429
- break;
430
-
431
- //up
432
- case 38:
433
- if (highlightItem) {
434
- let previousElement = this.findPrevItem(highlightItem);
435
- if (previousElement) {
436
- DomHandler.addClass(previousElement, 'p-highlight');
437
- DomHandler.removeClass(highlightItem, 'p-highlight');
438
- previousElement.scrollIntoView({ block: 'nearest', inline: 'start' });
439
- }
440
- }
441
-
442
- event.preventDefault();
443
- break;
444
-
445
- //enter
446
- case 13:
447
- if (highlightItem) {
448
- this.selectHighlightItem(event, highlightItem);
449
- this.hideOverlay();
450
- }
451
-
452
- event.preventDefault();
453
- break;
454
-
455
- //escape
456
- case 27:
457
- this.hideOverlay();
458
- event.preventDefault();
459
- break;
460
-
461
- //tab
462
- case 9:
463
- if (highlightItem) {
464
- this.selectHighlightItem(event, highlightItem);
465
- }
466
-
467
- this.hideOverlay();
468
- break;
469
-
470
- default:
471
- break;
472
- }
473
- }
474
-
475
- if (this.multiple) {
476
- switch(event.which) {
477
- //backspace
478
- case 8:
479
- if (this.modelValue && this.modelValue.length && !this.$refs.input.value) {
480
- let removedValue = this.modelValue[this.modelValue.length - 1];
481
- let newValue = this.modelValue.slice(0, -1);
482
-
483
- this.$emit('update:modelValue', newValue);
484
- this.$emit('item-unselect', {
485
- originalEvent: event,
486
- value: removedValue
487
- });
488
- }
489
- break;
782
+ changeFocusedOptionIndex(event, index) {
783
+ if (this.focusedOptionIndex !== index) {
784
+ this.focusedOptionIndex = index;
785
+ this.scrollInView();
490
786
 
491
- default:
492
- break;
787
+ if (this.selectOnFocus || this.autoHighlight) {
788
+ this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
493
789
  }
494
790
  }
495
791
  },
496
- selectHighlightItem(event, item) {
497
- if (this.optionGroupLabel) {
498
- let optionGroup = this.suggestions[item.dataset.group];
499
- this.selectItem(event, this.getOptionGroupChildren(optionGroup)[item.dataset.index]);
792
+ scrollInView(index = -1) {
793
+ const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
794
+ const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
795
+ if (element) {
796
+ element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
500
797
  }
501
- else {
502
- this.selectItem(event, this.suggestions[item.dataset.index]);
798
+ else if (!this.virtualScrollerDisabled) {
799
+ setTimeout(() => {
800
+ this.virtualScroller && this.virtualScroller.scrollToIndex(index !== -1 ? index : this.focusedOptionIndex);
801
+ }, 0);
503
802
  }
504
803
  },
505
- findNextItem(item) {
506
- let nextItem = item.nextElementSibling;
507
-
508
- if (nextItem)
509
- return DomHandler.hasClass(nextItem, 'p-autocomplete-item-group') ? this.findNextItem(nextItem) : nextItem;
510
- else
511
- return null;
804
+ autoUpdateModel() {
805
+ if ((this.selectOnFocus || this.autoHighlight) && this.autoOptionFocus && !this.hasSelectedOption) {
806
+ this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
807
+ const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
808
+ this.updateModel(null, this.multiple ? [value] : value);
809
+ }
512
810
  },
513
- findPrevItem(item) {
514
- let prevItem = item.previousElementSibling;
515
-
516
- if (prevItem)
517
- return DomHandler.hasClass(prevItem, 'p-autocomplete-item-group') ? this.findPrevItem(prevItem) : prevItem;
518
- else
519
- return null;
811
+ updateModel(event, value) {
812
+ this.$emit('update:modelValue', value);
813
+ this.$emit('change', { originalEvent: event, value });
520
814
  },
521
- onChange(event) {
522
- if (this.forceSelection) {
523
- let valid = false;
524
- let inputValue = event.target.value.trim();
525
-
526
- if (this.suggestions) {
527
- for (let item of this.suggestions) {
528
- let itemValue = this.field ? ObjectUtils.resolveFieldData(item, this.field) : item;
529
- if (itemValue && inputValue === itemValue.trim()) {
530
- valid = true;
531
- this.selectItem(event, item);
532
- break;
533
- }
534
- }
535
- }
815
+ flatOptions(options) {
816
+ return (options || []).reduce((result, option, index) => {
817
+ result.push({ optionGroup: option, group: true, index });
536
818
 
537
- if (!valid) {
538
- this.$refs.input.value = '';
539
- this.inputTextValue = '';
540
- this.$emit('clear');
541
- if (!this.multiple) {
542
- this.$emit('update:modelValue', null);
543
- }
544
- }
545
- }
546
- },
547
- isSelected(val) {
548
- let selected = false;
549
- if (this.modelValue && this.modelValue.length) {
550
- for (let i = 0; i < this.modelValue.length; i++) {
551
- if (ObjectUtils.equals(this.modelValue[i], val)) {
552
- selected = true;
553
- break;
554
- }
555
- }
556
- }
819
+ const optionGroupChildren = this.getOptionGroupChildren(option);
820
+ optionGroupChildren && optionGroupChildren.forEach(o => result.push(o));
557
821
 
558
- return selected;
822
+ return result;
823
+ }, []);
559
824
  },
560
825
  overlayRef(el) {
561
826
  this.overlay = el;
562
827
  },
563
828
  listRef(el, contentRef) {
564
829
  this.list = el;
565
- contentRef && contentRef(el); // for virtualScroller
830
+ contentRef && contentRef(el); // For VirtualScroller
566
831
  },
567
832
  virtualScrollerRef(el) {
568
833
  this.virtualScroller = el;
569
- },
570
- onOverlayClick(event) {
571
- OverlayEventBus.emit('overlay-click', {
572
- originalEvent: event,
573
- target: this.$el
574
- });
575
834
  }
576
835
  },
577
836
  computed: {
578
837
  containerClass() {
579
- return ['p-autocomplete p-component p-inputwrapper', this.class, {
838
+ return ['p-autocomplete p-component p-inputwrapper', {
839
+ 'p-disabled': this.disabled,
840
+ 'p-focus': this.focused,
580
841
  'p-autocomplete-dd': this.dropdown,
581
842
  'p-autocomplete-multiple': this.multiple,
582
- 'p-inputwrapper-filled': ((this.modelValue) || (this.inputTextValue && this.inputTextValue.length)),
583
- 'p-inputwrapper-focus': this.focused
843
+ 'p-inputwrapper-filled': this.modelValue || ObjectUtils.isNotEmpty(this.inputValue),
844
+ 'p-inputwrapper-focus': this.focused,
845
+ 'p-overlay-open': this.overlayVisible
584
846
  }];
585
847
  },
586
- inputFieldClass() {
848
+ inputStyleClass() {
587
849
  return ['p-autocomplete-input p-inputtext p-component', this.inputClass, {
588
- 'p-autocomplete-dd-input': this.dropdown,
589
- 'p-disabled': this.$attrs.disabled
850
+ 'p-autocomplete-dd-input': this.dropdown
590
851
  }];
591
852
  },
592
853
  multiContainerClass() {
593
- return ['p-autocomplete-multiple-container p-component p-inputtext', {
594
- 'p-disabled': this.$attrs.disabled,
595
- 'p-focus': this.focused
596
- }];
854
+ return ['p-autocomplete-multiple-container p-component p-inputtext'];
597
855
  },
598
856
  panelStyleClass() {
599
- return [
600
- 'p-autocomplete-panel p-component', this.panelClass, {
857
+ return ['p-autocomplete-panel p-component', this.panelClass, {
601
858
  'p-input-filled': this.$primevue.config.inputStyle === 'filled',
602
859
  'p-ripple-disabled': this.$primevue.config.ripple === false
603
860
  }];
@@ -605,21 +862,55 @@ export default {
605
862
  loadingIconClass() {
606
863
  return ['p-autocomplete-loader pi-spin', this.loadingIcon];
607
864
  },
865
+ visibleOptions() {
866
+ return this.optionGroupLabel ? this.flatOptions(this.suggestions) : (this.suggestions || []);
867
+ },
608
868
  inputValue() {
609
869
  if (this.modelValue) {
610
- if (this.field && typeof this.modelValue === 'object') {
611
- const resolvedFieldData = ObjectUtils.resolveFieldData(this.modelValue, this.field);
612
- return resolvedFieldData != null ? resolvedFieldData : this.modelValue;
870
+ if (typeof this.modelValue === 'object') {
871
+ const label = this.getOptionLabel(this.modelValue);
872
+ return label != null ? label : this.modelValue;
613
873
  }
614
- else
874
+ else {
615
875
  return this.modelValue;
876
+ }
616
877
  }
617
878
  else {
618
879
  return '';
619
880
  }
620
881
  },
621
- listId() {
622
- return UniqueComponentId() + '_list';
882
+ hasSelectedOption() {
883
+ return ObjectUtils.isNotEmpty(this.modelValue);
884
+ },
885
+ equalityKey() {
886
+ return this.dataKey; // TODO: The 'optionValue' properties can be added.
887
+ },
888
+ searchResultMessageText() {
889
+ return ObjectUtils.isNotEmpty(this.visibleOptions) && this.overlayVisible ? this.searchMessageText.replaceAll('{0}', this.visibleOptions.length) : this.emptySearchMessageText;
890
+ },
891
+ searchMessageText() {
892
+ return this.searchMessage || this.$primevue.config.locale.searchMessage;
893
+ },
894
+ emptySearchMessageText() {
895
+ return this.emptySearchMessage || this.$primevue.config.locale.emptySearchMessage;
896
+ },
897
+ selectionMessageText() {
898
+ return this.selectionMessage || this.$primevue.config.locale.selectionMessage;
899
+ },
900
+ emptySelectionMessageText() {
901
+ return this.emptySelectionMessage || this.$primevue.config.locale.emptySelectionMessage;
902
+ },
903
+ selectedMessageText() {
904
+ return this.hasSelectedOption ? this.selectionMessageText.replaceAll('{0}', this.multiple ? this.modelValue.length : '1') : this.emptySelectionMessageText;
905
+ },
906
+ focusedOptionId() {
907
+ return this.focusedOptionIndex !== -1 ? `${this.id}_${this.focusedOptionIndex}` : null;
908
+ },
909
+ focusedMultipleOptionId() {
910
+ return this.focusedMultipleOptionIndex !== -1 ? `${this.id}_multiple_option_${this.focusedMultipleOptionIndex}` : null;
911
+ },
912
+ ariaSetSize() {
913
+ return this.visibleOptions.filter(option => !this.isOptionGroup(option)).length;
623
914
  },
624
915
  virtualScrollerDisabled() {
625
916
  return !this.virtualScrollerOptions;