primevue 3.15.0 → 3.16.2

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