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,65 +1,71 @@
1
1
  <template>
2
- <div ref="container" :class="containerClass" @click="onClick($event)">
3
- <div class="p-hidden-accessible">
4
- <input ref="focusInput" type="text" :id="inputId" readonly :disabled="disabled" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" :tabindex="tabindex"
5
- aria-haspopup="true" :aria-expanded="overlayVisible" :aria-labelledby="ariaLabelledBy"/>
6
- </div>
7
- <input v-if="editable" type="text" class="p-dropdown-label p-inputtext" :disabled="disabled" @focus="onFocus" @blur="onBlur" :placeholder="placeholder" :value="editableInputValue" @input="onEditableInput"
8
- aria-haspopup="listbox" :aria-expanded="overlayVisible">
9
- <span v-if="!editable" :class="labelClass">
10
- <slot name="value" :value="modelValue" :placeholder="placeholder">{{label||'empty'}}</slot>
2
+ <div ref="container" :id="id" :class="containerClass" @click="onContainerClick">
3
+ <input v-if="editable" ref="focusInput" :id="inputId" type="text" :style="inputStyle" :class="inputStyleClass" :value="editableInputValue" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1" :disabled="disabled" autocomplete="off"
4
+ role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="listbox" :aria-expanded="overlayVisible" :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined"
5
+ @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @input="onEditableInput" v-bind="inputProps">
6
+ <span v-else ref="focusInput" :id="inputId" :style="inputStyle" :class="inputStyleClass" :tabindex="!disabled ? tabindex : -1" role="combobox" :aria-label="ariaLabel || (label === 'p-emptylabel' ? undefined : label)" :aria-labelledby="ariaLabelledby"
7
+ aria-haspopup="listbox" :aria-expanded="overlayVisible" :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined" :aria-disabled="disabled"
8
+ @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" v-bind="inputProps">
9
+ <slot name="value" :value="modelValue" :placeholder="placeholder">{{label === 'p-emptylabel' ? '&nbsp;' : label || 'empty'}}</slot>
11
10
  </span>
12
- <i v-if="showClear && modelValue != null" class="p-dropdown-clear-icon pi pi-times" @click="onClearClick($event)"></i>
13
- <div class="p-dropdown-trigger" role="button" aria-haspopup="listbox" :aria-expanded="overlayVisible">
11
+ <i v-if="showClear && modelValue != null" class="p-dropdown-clear-icon pi pi-times" @click="onClearClick" v-bind="clearIconProps"></i>
12
+ <div class="p-dropdown-trigger">
14
13
  <slot name="indicator">
15
- <span :class="dropdownIconClass"></span>
14
+ <span :class="dropdownIconClass" aria-hidden="true"></span>
16
15
  </slot>
17
16
  </div>
18
17
  <Portal :appendTo="appendTo">
19
18
  <transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
20
- <div :ref="overlayRef" :class="panelStyleClass" v-if="overlayVisible" @click="onOverlayClick">
19
+ <div v-if="overlayVisible" :ref="overlayRef" :style="panelStyle" :class="panelStyleClass" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="panelProps">
20
+ <span ref="firstHiddenFocusableElementOnOverlay" role="presentation" aria-hidden="true" class="p-hidden-accessible p-hidden-focusable" :tabindex="0" @focus="onFirstHiddenFocus"></span>
21
21
  <slot name="header" :value="modelValue" :options="visibleOptions"></slot>
22
- <div class="p-dropdown-header" v-if="filter">
23
- <div class="p-dropdown-filter-container">
24
- <input type="text" ref="filterInput" :value="filterValue" @vnode-updated="onFilterUpdated" autoComplete="off" class="p-dropdown-filter p-inputtext p-component" :placeholder="filterPlaceholder" @keydown="onFilterKeyDown" @input="onFilterChange"/>
22
+ <div v-if="filter" class="p-dropdown-header">
23
+ <div class="p-dropdown-filter-container">
24
+ <input type="text" ref="filterInput" :value="filterValue" @vnode-updated="onFilterUpdated" class="p-dropdown-filter p-inputtext p-component" :placeholder="filterPlaceholder"
25
+ role="searchbox" autocomplete="off" :aria-owns="id + '_list'" :aria-activedescendant="focusedOptionId"
26
+ @keydown="onFilterKeyDown" @blur="onFilterBlur" @input="onFilterChange" v-bind="filterInputProps"/>
25
27
  <span class="p-dropdown-filter-icon pi pi-search"></span>
26
28
  </div>
29
+ <span role="status" aria-live="polite" class="p-hidden-accessible">
30
+ {{filterResultMessageText}}
31
+ </span>
27
32
  </div>
28
- <div :ref="itemsWrapperRef" class="p-dropdown-items-wrapper" :style="{'max-height': virtualScrollerDisabled ? scrollHeight : ''}">
29
- <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{'height': scrollHeight}" :disabled="virtualScrollerDisabled">
30
- <template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle }">
31
- <ul :ref="contentRef" :class="['p-dropdown-items', styleClass]" :style="contentStyle" role="listbox">
32
- <template v-if="!optionGroupLabel">
33
- <li v-for="(option, i) of items" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
34
- :key="getOptionRenderKey(option, i)" @click="onOptionSelect($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)">
33
+ <div class="p-dropdown-items-wrapper" :style="{'max-height': virtualScrollerDisabled ? scrollHeight : ''}">
34
+ <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{'height': scrollHeight}" :tabindex="-1" :disabled="virtualScrollerDisabled">
35
+ <template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle, itemSize }">
36
+ <ul :ref="(el) => listRef(el, contentRef)" :id="id + '_list'" :class="['p-dropdown-items', styleClass]" :style="contentStyle" role="listbox">
37
+ <template v-for="(option, i) of items" :key="getOptionRenderKey(option, getOptionIndex(i, getItemOptions))">
38
+ <li v-if="isOptionGroup(option)" :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}" class="p-dropdown-item-group" role="option">
39
+ <slot name="optiongroup" :option="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(option.optionGroup)}}</slot>
40
+ </li>
41
+ <li v-else v-ripple :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}"
42
+ :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-focus': focusedOptionIndex === getOptionIndex(i, getItemOptions), 'p-disabled': isOptionDisabled(option)}]"
43
+ role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" :aria-disabled="isOptionDisabled(option)" :aria-setsize="ariaSetSize" :aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
44
+ @click="onOptionSelect($event, option)" @mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))">
35
45
  <slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot>
36
46
  </li>
37
47
  </template>
38
- <template v-else>
39
- <template v-for="(optionGroup, i) of items" :key="getOptionGroupRenderKey(optionGroup)">
40
- <li class="p-dropdown-item-group">
41
- <slot name="optiongroup" :option="optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(optionGroup)}}</slot>
42
- </li>
43
- <li v-for="(option, i) of getOptionGroupChildren(optionGroup)" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
44
- :key="getOptionRenderKey(option, i)" @click="onOptionSelect($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)">
45
- <slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot>
46
- </li>
47
- </template>
48
- </template>
49
- <li v-if="filterValue && (!items || (items && items.length === 0))" class="p-dropdown-empty-message">
48
+ <li v-if="filterValue && (!items || (items && items.length === 0))" class="p-dropdown-empty-message" role="option">
50
49
  <slot name="emptyfilter">{{emptyFilterMessageText}}</slot>
51
50
  </li>
52
- <li v-else-if="(!options || (options && options.length === 0))" class="p-dropdown-empty-message">
51
+ <li v-else-if="(!options || (options && options.length === 0))" class="p-dropdown-empty-message" role="option">
53
52
  <slot name="empty">{{emptyMessageText}}</slot>
54
53
  </li>
55
54
  </ul>
55
+ <span v-if="(!options || (options && options.length === 0))" role="status" aria-live="polite" class="p-hidden-accessible">
56
+ {{emptyMessageText}}
57
+ </span>
58
+ <span role="status" aria-live="polite" class="p-hidden-accessible">
59
+ {{selectedMessageText}}
60
+ </span>
56
61
  </template>
57
- <template v-slot:loader="{ options }" v-if="$slots.loader">
62
+ <template v-if="$slots.loader" v-slot:loader="{ options }">
58
63
  <slot name="loader" :options="options"></slot>
59
64
  </template>
60
65
  </VirtualScroller>
61
66
  </div>
62
67
  <slot name="footer" :value="modelValue" :options="visibleOptions"></slot>
68
+ <span ref="lastHiddenFocusableElementOnOverlay" role="presentation" aria-hidden="true" class="p-hidden-accessible p-hidden-focusable" :tabindex="0" @focus="onLastHiddenFocus"></span>
63
69
  </div>
64
70
  </transition>
65
71
  </Portal>
@@ -67,7 +73,7 @@
67
73
  </template>
68
74
 
69
75
  <script>
70
- import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
76
+ import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils,UniqueComponentId} from 'primevue/utils';
71
77
  import OverlayEventBus from 'primevue/overlayeventbus';
72
78
  import {FilterService} from 'primevue/api';
73
79
  import Ripple from 'primevue/ripple';
@@ -76,7 +82,7 @@ import Portal from 'primevue/portal';
76
82
 
77
83
  export default {
78
84
  name: 'Dropdown',
79
- emits: ['update:modelValue', 'before-show', 'before-hide', 'show', 'hide', 'change', 'filter', 'focus', 'blur'],
85
+ emits: ['update:modelValue', 'change', 'focus', 'blur', 'before-show', 'before-hide', 'show', 'hide', 'filter'],
80
86
  props: {
81
87
  modelValue: null,
82
88
  options: Array,
@@ -106,12 +112,46 @@ export default {
106
112
  dataKey: null,
107
113
  showClear: Boolean,
108
114
  inputId: String,
109
- tabindex: String,
110
- ariaLabelledBy: null,
115
+ inputStyle: null,
116
+ inputClass: null,
117
+ inputProps: null,
118
+ panelStyle: null,
119
+ panelClass: null,
120
+ panelProps: null,
121
+ filterInputProps: null,
122
+ clearIconProps: null,
111
123
  appendTo: {
112
124
  type: String,
113
125
  default: 'body'
114
126
  },
127
+ loading: {
128
+ type: Boolean,
129
+ default: false
130
+ },
131
+ loadingIcon: {
132
+ type: String,
133
+ default: 'pi pi-spinner pi-spin'
134
+ },
135
+ virtualScrollerOptions: {
136
+ type: Object,
137
+ default: null
138
+ },
139
+ autoOptionFocus: {
140
+ type: Boolean,
141
+ default: true
142
+ },
143
+ filterMessage: {
144
+ type: String,
145
+ default: null
146
+ },
147
+ selectionMessage: {
148
+ type: String,
149
+ default: null
150
+ },
151
+ emptySelectionMessage: {
152
+ type: String,
153
+ default: null
154
+ },
115
155
  emptyFilterMessage: {
116
156
  type: String,
117
157
  default: null
@@ -120,46 +160,55 @@ export default {
120
160
  type: String,
121
161
  default: null
122
162
  },
123
- panelClass: null,
124
- loading: {
125
- type: Boolean,
126
- default: false
163
+ tabindex: {
164
+ type: Number,
165
+ default: 0
127
166
  },
128
- loadingIcon: {
167
+ 'aria-label': {
129
168
  type: String,
130
- default: 'pi pi-spinner pi-spin'
169
+ default: null
131
170
  },
132
- virtualScrollerOptions: {
133
- type: Object,
171
+ 'aria-labelledby': {
172
+ type: String,
134
173
  default: null
135
174
  }
136
175
  },
176
+ outsideClickListener: null,
177
+ scrollHandler: null,
178
+ resizeListener: null,
179
+ overlay: null,
180
+ list: null,
181
+ virtualScroller: null,
182
+ searchTimeout: null,
183
+ searchValue: null,
184
+ isModelValueChanged: false,
185
+ selectOnFocus: false,
186
+ focusOnHover: false,
137
187
  data() {
138
188
  return {
189
+ id: UniqueComponentId(),
139
190
  focused: false,
191
+ focusedOptionIndex: -1,
140
192
  filterValue: null,
141
193
  overlayVisible: false
142
- };
194
+ }
143
195
  },
144
196
  watch: {
145
197
  modelValue() {
146
198
  this.isModelValueChanged = true;
199
+ },
200
+ options() {
201
+ this.autoUpdateModel();
147
202
  }
148
203
  },
149
- outsideClickListener: null,
150
- scrollHandler: null,
151
- resizeListener: null,
152
- searchTimeout: null,
153
- currentSearchChar: null,
154
- previousSearchChar: null,
155
- searchValue: null,
156
- overlay: null,
157
- itemsWrapper: null,
158
- virtualScroller: null,
159
- isModelValueChanged: false,
204
+ mounted() {
205
+ this.id = this.$attrs.id || this.id;
206
+
207
+ this.autoUpdateModel();
208
+ },
160
209
  updated() {
161
210
  if (this.overlayVisible && this.isModelValueChanged) {
162
- this.scrollValueInView();
211
+ this.scrollInView(this.findSelectedOptionIndex());
163
212
  }
164
213
 
165
214
  this.isModelValueChanged = false;
@@ -173,8 +222,6 @@ export default {
173
222
  this.scrollHandler = null;
174
223
  }
175
224
 
176
- this.itemsWrapper = null;
177
-
178
225
  if (this.overlay) {
179
226
  ZIndexUtils.clear(this.overlay);
180
227
  this.overlay = null;
@@ -191,13 +238,13 @@ export default {
191
238
  return this.optionValue ? ObjectUtils.resolveFieldData(option, this.optionValue) : option;
192
239
  },
193
240
  getOptionRenderKey(option, index) {
194
- return this.dataKey ? ObjectUtils.resolveFieldData(option, this.dataKey) : this.getOptionLabel(option) + '_' + index.toString();
241
+ return (this.dataKey ? ObjectUtils.resolveFieldData(option, this.dataKey) : this.getOptionLabel(option)) + '_' + index;
195
242
  },
196
243
  isOptionDisabled(option) {
197
244
  return this.optionDisabled ? ObjectUtils.resolveFieldData(option, this.optionDisabled) : false;
198
245
  },
199
- getOptionGroupRenderKey(optionGroup) {
200
- return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
246
+ isOptionGroup(option) {
247
+ return this.optionGroupLabel && option.optionGroup && option.group;
201
248
  },
202
249
  getOptionGroupLabel(optionGroup) {
203
250
  return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
@@ -205,257 +252,339 @@ export default {
205
252
  getOptionGroupChildren(optionGroup) {
206
253
  return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren);
207
254
  },
208
- getSelectedOption() {
209
- let index = this.getSelectedOptionIndex();
210
- return index !== -1 ? (this.optionGroupLabel ? this.getOptionGroupChildren(this.visibleOptions[index.group])[index.option]: this.visibleOptions[index]) : null;
211
- },
212
- getSelectedOptionIndex() {
213
- if (this.modelValue != null && this.visibleOptions) {
214
- if (this.optionGroupLabel) {
215
- for (let i = 0; i < this.visibleOptions.length; i++) {
216
- let selectedOptionIndex = this.findOptionIndexInList(this.modelValue, this.getOptionGroupChildren(this.visibleOptions[i]));
217
- if (selectedOptionIndex !== -1) {
218
- return {group: i, option: selectedOptionIndex};
219
- }
220
- }
221
- }
222
- else {
223
- return this.findOptionIndexInList(this.modelValue, this.visibleOptions);
224
- }
225
- }
226
-
227
- return -1;
228
- },
229
- findOptionIndexInList(value, list) {
230
- for (let i = 0; i < list.length; i++) {
231
- if ((ObjectUtils.equals(value, this.getOptionValue(list[i]), this.equalityKey))) {
232
- return i;
233
- }
234
- }
235
-
236
- return -1;
237
- },
238
- isSelected(option) {
239
- return ObjectUtils.equals(this.modelValue, this.getOptionValue(option), this.equalityKey);
255
+ getAriaPosInset(index) {
256
+ return (this.optionGroupLabel ? index - this.visibleOptions.slice(0, index).filter(option => this.isOptionGroup(option)).length : index) + 1;
240
257
  },
241
258
  show(isFocus) {
242
259
  this.$emit('before-show');
243
260
  this.overlayVisible = true;
261
+ this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
244
262
 
245
263
  isFocus && this.$refs.focusInput.focus();
246
264
  },
247
- hide() {
248
- this.$emit('before-hide');
249
- this.overlayVisible = false;
265
+ hide(isFocus) {
266
+ const _hide = () => {
267
+ this.$emit('before-hide');
268
+ this.overlayVisible = false;
269
+ this.focusedOptionIndex = -1;
270
+ this.searchValue = '';
271
+
272
+ isFocus && this.$refs.focusInput.focus();
273
+ }
274
+
275
+ setTimeout(() => { _hide() }, 0); // For ScreenReaders
250
276
  },
251
277
  onFocus(event) {
252
278
  this.focused = true;
279
+ this.focusedOptionIndex = this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
280
+ this.overlayVisible && this.scrollInView(this.focusedOptionIndex);
253
281
  this.$emit('focus', event);
254
282
  },
255
283
  onBlur(event) {
256
284
  this.focused = false;
285
+ this.focusedOptionIndex = -1;
286
+ this.searchValue = '';
257
287
  this.$emit('blur', event);
258
288
  },
259
289
  onKeyDown(event) {
260
- switch(event.which) {
261
- //down
262
- case 40:
263
- this.onDownKey(event);
264
- break;
265
-
266
- //up
267
- case 38:
268
- this.onUpKey(event);
269
- break;
270
-
271
- //space
272
- case 32:
273
- if (!this.overlayVisible) {
274
- this.show();
275
- event.preventDefault();
276
- }
277
- break;
290
+ switch (event.code) {
291
+ case 'ArrowDown':
292
+ this.onArrowDownKey(event);
293
+ break;
278
294
 
279
- //enter and escape
280
- case 13:
281
- case 27:
282
- if (this.overlayVisible) {
283
- this.hide();
284
- event.preventDefault();
285
- }
286
- break;
295
+ case 'ArrowUp':
296
+ this.onArrowUpKey(event, this.editable);
297
+ break;
298
+
299
+ case 'ArrowLeft':
300
+ case 'ArrowRight':
301
+ this.onArrowLeftKey(event, this.editable);
302
+ break;
303
+
304
+ case 'Home':
305
+ this.onHomeKey(event, this.editable);
306
+ break;
307
+
308
+ case 'End':
309
+ this.onEndKey(event, this.editable);
310
+ break;
311
+
312
+ case 'PageDown':
313
+ this.onPageDownKey(event);
314
+ break;
315
+
316
+ case 'PageUp':
317
+ this.onPageUpKey(event);
318
+ break;
319
+
320
+ case 'Space':
321
+ this.onSpaceKey(event, this.editable);
322
+ break;
323
+
324
+ case 'Enter':
325
+ this.onEnterKey(event);
326
+ break;
327
+
328
+ case 'Escape':
329
+ this.onEscapeKey(event);
330
+ break;
331
+
332
+ case 'Tab':
333
+ this.onTabKey(event);
334
+ break;
287
335
 
288
- //tab
289
- case 9:
290
- this.hide();
291
- break;
336
+ case 'Backspace':
337
+ this.onBackspaceKey(event, this.editable);
338
+ break;
339
+
340
+ case 'ShiftLeft':
341
+ case 'ShiftRight':
342
+ //NOOP
343
+ break;
292
344
 
293
345
  default:
294
- this.search(event);
295
- break;
346
+ if (ObjectUtils.isPrintableCharacter(event.key)) {
347
+ !this.overlayVisible && this.show();
348
+ !this.editable && this.searchOptions(event, event.key);
349
+ }
350
+
351
+ break;
296
352
  }
297
353
  },
354
+ onEditableInput(event) {
355
+ const value = event.target.value;
356
+
357
+ this.searchValue = '';
358
+ const matched = this.searchOptions(event, value);
359
+ !matched && (this.focusedOptionIndex = -1);
360
+
361
+ this.$emit('update:modelValue', value);
362
+ },
363
+ onContainerClick(event) {
364
+ if (this.disabled || this.loading) {
365
+ return;
366
+ }
367
+
368
+ if (DomHandler.hasClass(event.target, 'p-dropdown-clear-icon') || event.target.tagName === 'INPUT') {
369
+ return;
370
+ }
371
+ else if (!this.overlay || !this.overlay.contains(event.target)) {
372
+ this.overlayVisible ? this.hide(true) : this.show(true);
373
+ }
374
+ },
375
+ onClearClick(event) {
376
+ this.updateModel(event, null);
377
+ },
378
+ onFirstHiddenFocus(event) {
379
+ const relatedTarget = event.relatedTarget;
380
+
381
+ if (relatedTarget === this.$refs.focusInput) {
382
+ const firstFocusableEl = DomHandler.getFirstFocusableElement(this.overlay, ':not(.p-hidden-focusable)');
383
+ firstFocusableEl && firstFocusableEl.focus();
384
+ }
385
+ else {
386
+ this.$refs.focusInput.focus();
387
+ }
388
+ },
389
+ onLastHiddenFocus() {
390
+ this.$refs.firstHiddenFocusableElementOnOverlay.focus();
391
+ },
392
+ onOptionSelect(event, option) {
393
+ const value = this.getOptionValue(option);
394
+
395
+ this.updateModel(event, value);
396
+ this.hide(true);
397
+ },
398
+ onOptionMouseMove(event, index) {
399
+ if (this.focusOnHover) {
400
+ this.changeFocusedOptionIndex(event, index);
401
+ }
402
+ },
403
+ onFilterChange(event) {
404
+ const value = event.target.value;
405
+
406
+ this.filterValue = value;
407
+ this.focusedOptionIndex = -1;
408
+ this.$emit('filter', { originalEvent: event, value });
409
+
410
+ !this.virtualScrollerDisabled && this.virtualScroller.scrollToIndex(0);
411
+ },
298
412
  onFilterKeyDown(event) {
299
- switch (event.which) {
300
- //down
301
- case 40:
302
- this.onDownKey(event);
413
+ switch (event.code) {
414
+ case 'ArrowDown':
415
+ this.onArrowDownKey(event);
303
416
  break;
304
417
 
305
- //up
306
- case 38:
307
- this.onUpKey(event);
418
+ case 'ArrowUp':
419
+ this.onArrowUpKey(event, true);
308
420
  break;
309
421
 
310
- //enter and escape
311
- case 13:
312
- case 27:
313
- this.overlayVisible = false;
314
- event.preventDefault();
315
- break;
422
+ case 'ArrowLeft':
423
+ case 'ArrowRight':
424
+ this.onArrowLeftKey(event, true);
425
+ break;
426
+
427
+ case 'Home':
428
+ this.onHomeKey(event, true);
429
+ break;
430
+
431
+ case 'End':
432
+ this.onEndKey(event, true);
433
+ break;
434
+
435
+ case 'Enter':
436
+ this.onEnterKey(event);
437
+ break;
438
+
439
+ case 'Escape':
440
+ this.onEscapeKey(event);
441
+ break;
442
+
443
+ case 'Tab':
444
+ this.onTabKey(event, true);
445
+ break;
316
446
 
317
447
  default:
318
- break;
448
+ break;
319
449
  }
320
450
  },
321
- onDownKey(event) {
322
- if (this.visibleOptions) {
323
- if (!this.overlayVisible && event.altKey) {
324
- this.show();
325
- }
326
- else {
327
- let nextOption = this.visibleOptions && this.visibleOptions.length > 0 ? this.findNextOption(this.getSelectedOptionIndex()) : null;
328
- if (nextOption) {
329
- this.updateModel(event, this.getOptionValue(nextOption));
330
- }
331
- }
451
+ onFilterBlur() {
452
+ this.focusedOptionIndex = -1;
453
+ },
454
+ onFilterUpdated() {
455
+ if (this.overlayVisible) {
456
+ this.alignOverlay();
332
457
  }
333
-
334
- event.preventDefault();
335
458
  },
336
- onUpKey(event) {
337
- if (this.visibleOptions) {
338
- let prevOption = this.findPrevOption(this.getSelectedOptionIndex());
339
- if (prevOption) {
340
- this.updateModel(event, this.getOptionValue(prevOption));
341
- }
459
+ onOverlayClick(event) {
460
+ OverlayEventBus.emit('overlay-click', {
461
+ originalEvent: event,
462
+ target: this.$el
463
+ });
464
+ },
465
+ onOverlayKeyDown(event) {
466
+ switch (event.code) {
467
+ case 'Escape':
468
+ this.onEscapeKey(event);
469
+ break;
470
+
471
+ default:
472
+ break;
342
473
  }
474
+ },
475
+ onArrowDownKey(event) {
476
+ const optionIndex = this.focusedOptionIndex !== -1 ? this.findNextOptionIndex(this.focusedOptionIndex) : this.findFirstFocusedOptionIndex();
477
+
478
+ this.changeFocusedOptionIndex(event, optionIndex);
343
479
 
480
+ !this.overlayVisible && this.show();
344
481
  event.preventDefault();
345
482
  },
346
- findNextOption(index) {
347
- if (this.optionGroupLabel) {
348
- let groupIndex = index === -1 ? 0 : index.group;
349
- let optionIndex = index === -1 ? -1 : index.option;
350
- let option = this.findNextOptionInList(this.getOptionGroupChildren(this.visibleOptions[groupIndex]), optionIndex);
483
+ onArrowUpKey(event, pressedInInputText = false) {
484
+ if (event.altKey && !pressedInInputText) {
485
+ if (this.focusedOptionIndex !== -1) {
486
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
487
+ }
351
488
 
352
- if (option)
353
- return option;
354
- else if ((groupIndex + 1) !== this.visibleOptions.length)
355
- return this.findNextOption({group: (groupIndex + 1), option: -1});
356
- else
357
- return null;
489
+ this.overlayVisible && this.hide();
490
+ event.preventDefault();
358
491
  }
359
492
  else {
360
- return this.findNextOptionInList(this.visibleOptions, index);
493
+ const optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.findLastFocusedOptionIndex();
494
+
495
+ this.changeFocusedOptionIndex(event, optionIndex);
496
+
497
+ !this.overlayVisible && this.show();
498
+ event.preventDefault();
361
499
  }
362
500
  },
363
- findNextOptionInList(list, index) {
364
- let i = index + 1;
365
- if (i === list.length) {
366
- return null;
367
- }
368
-
369
- let option = list[i];
370
- if (this.isOptionDisabled(option))
371
- return this.findNextOptionInList(i);
372
- else
373
- return option;
501
+ onArrowLeftKey(event, pressedInInputText = false) {
502
+ pressedInInputText && (this.focusedOptionIndex = -1);
374
503
  },
375
- findPrevOption(index) {
376
- if (index === -1) {
377
- return null;
504
+ onHomeKey(event, pressedInInputText = false) {
505
+ if (pressedInInputText) {
506
+ event.currentTarget.setSelectionRange(0, 0);
507
+ this.focusedOptionIndex = -1;
378
508
  }
509
+ else {
510
+ this.changeFocusedOptionIndex(event, this.findFirstOptionIndex());
379
511
 
380
- if (this.optionGroupLabel) {
381
- let groupIndex = index.group;
382
- let optionIndex = index.option;
383
- let option = this.findPrevOptionInList(this.getOptionGroupChildren(this.visibleOptions[groupIndex]), optionIndex);
512
+ !this.overlayVisible && this.show();
513
+ }
384
514
 
385
- if (option)
386
- return option;
387
- else if (groupIndex > 0)
388
- return this.findPrevOption({group: (groupIndex - 1), option: this.getOptionGroupChildren(this.visibleOptions[groupIndex - 1]).length});
389
- else
390
- return null;
515
+ event.preventDefault();
516
+ },
517
+ onEndKey(event, pressedInInputText = false) {
518
+ if (pressedInInputText) {
519
+ const target = event.currentTarget;
520
+ const len = target.value.length;
521
+ target.setSelectionRange(len, len);
522
+ this.focusedOptionIndex = -1;
391
523
  }
392
524
  else {
393
- return this.findPrevOptionInList(this.visibleOptions, index);
394
- }
395
- },
396
- findPrevOptionInList(list, index) {
397
- let i = index - 1;
398
- if (i < 0) {
399
- return null;
525
+ this.changeFocusedOptionIndex(event, this.findLastOptionIndex());
526
+
527
+ !this.overlayVisible && this.show();
400
528
  }
401
529
 
402
- let option = list[i];
403
- if (this.isOptionDisabled(option))
404
- return this.findPrevOption(i);
405
- else
406
- return option;
530
+ event.preventDefault();
407
531
  },
408
- onClearClick(event) {
409
- this.updateModel(event, null);
532
+ onPageUpKey(event) {
533
+ this.scrollInView(0);
534
+ event.preventDefault();
410
535
  },
411
- onClick(event) {
412
- if (this.disabled || this.loading) {
413
- return;
536
+ onPageDownKey(event) {
537
+ this.scrollInView(this.visibleOptions.length - 1);
538
+ event.preventDefault();
539
+ },
540
+ onEnterKey(event) {
541
+ if (!this.overlayVisible) {
542
+ this.onArrowDownKey(event);
414
543
  }
544
+ else {
545
+ if (this.focusedOptionIndex !== -1) {
546
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
547
+ }
415
548
 
416
- if (DomHandler.hasClass(event.target, 'p-dropdown-clear-icon') || event.target.tagName === 'INPUT') {
417
- return;
549
+ this.hide();
418
550
  }
419
- else if (!this.overlay || !this.overlay.contains(event.target)) {
420
- if (this.overlayVisible)
421
- this.hide();
422
- else
423
- this.show();
424
551
 
425
- this.$refs.focusInput.focus();
426
- }
552
+ event.preventDefault();
427
553
  },
428
- onOptionSelect(event, option) {
429
- let value = this.getOptionValue(option);
430
- this.updateModel(event, value);
431
- this.$refs.focusInput.focus();
554
+ onSpaceKey(event, pressedInInputText = false) {
555
+ !pressedInInputText && this.onEnterKey(event);
556
+ },
557
+ onEscapeKey(event) {
558
+ this.overlayVisible && this.hide(true);
559
+ event.preventDefault();
560
+ },
561
+ onTabKey(event, pressedInInputText = false) {
562
+ if (!pressedInInputText) {
563
+ if (this.overlayVisible && this.hasFocusableElements()) {
564
+ this.$refs.firstHiddenFocusableElementOnOverlay.focus();
432
565
 
433
- setTimeout(() => {
434
- this.hide();
435
- }, 200);
566
+ event.preventDefault();
567
+ }
568
+ else {
569
+ if (this.focusedOptionIndex !== -1) {
570
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
571
+ }
572
+
573
+ this.overlayVisible && this.hide(this.filter);
574
+ }
575
+ }
436
576
  },
437
- onEditableInput(event) {
438
- this.$emit('update:modelValue', event.target.value);
577
+ onBackspaceKey(event, pressedInInputText = false) {
578
+ if (pressedInInputText) {
579
+ !this.overlayVisible && this.show();
580
+ }
439
581
  },
440
582
  onOverlayEnter(el) {
441
583
  ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
442
584
  this.alignOverlay();
443
- this.scrollValueInView();
444
-
445
- if (!this.virtualScrollerDisabled) {
446
- const selectedIndex = this.getSelectedOptionIndex();
447
- if (selectedIndex !== -1) {
448
- setTimeout(() => {
449
- this.virtualScroller && this.virtualScroller.scrollToIndex(selectedIndex)
450
- }, 0);
451
- }
452
- }
585
+ this.scrollInView();
453
586
  },
454
587
  onOverlayAfterEnter() {
455
- if (this.filter) {
456
- this.$refs.filterInput.focus();
457
- }
458
-
459
588
  this.bindOutsideClickListener();
460
589
  this.bindScrollListener();
461
590
  this.bindResizeListener();
@@ -466,8 +595,8 @@ export default {
466
595
  this.unbindOutsideClickListener();
467
596
  this.unbindScrollListener();
468
597
  this.unbindResizeListener();
598
+
469
599
  this.$emit('hide');
470
- this.itemsWrapper = null;
471
600
  this.overlay = null;
472
601
  },
473
602
  onOverlayAfterLeave(el) {
@@ -482,10 +611,6 @@ export default {
482
611
  DomHandler.absolutePosition(this.overlay, this.$el);
483
612
  }
484
613
  },
485
- updateModel(event, value) {
486
- this.$emit('update:modelValue', value);
487
- this.$emit('change', {originalEvent: event, value: value});
488
- },
489
614
  bindOutsideClickListener() {
490
615
  if (!this.outsideClickListener) {
491
616
  this.outsideClickListener = (event) => {
@@ -534,162 +659,153 @@ export default {
534
659
  this.resizeListener = null;
535
660
  }
536
661
  },
537
- search(event) {
538
- if (!this.visibleOptions) {
539
- return;
662
+ hasFocusableElements() {
663
+ return DomHandler.getFocusableElements(this.overlay, ':not(.p-hidden-focusable)').length > 0;
664
+ },
665
+ isOptionMatched(option) {
666
+ return this.isValidOption(option) && this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).startsWith(this.searchValue.toLocaleLowerCase(this.filterLocale));
667
+ },
668
+ isValidOption(option) {
669
+ return option && !(this.isOptionDisabled(option) || this.isOptionGroup(option));
670
+ },
671
+ isValidSelectedOption(option) {
672
+ return this.isValidOption(option) && this.isSelected(option);
673
+ },
674
+ isSelected(option) {
675
+ return ObjectUtils.equals(this.modelValue, this.getOptionValue(option), this.equalityKey);
676
+ },
677
+ findFirstOptionIndex() {
678
+ return this.visibleOptions.findIndex(option => this.isValidOption(option));
679
+ },
680
+ findLastOptionIndex() {
681
+ return this.visibleOptions.findLastIndex(option => this.isValidOption(option));
682
+ },
683
+ findNextOptionIndex(index) {
684
+ const matchedOptionIndex = index < (this.visibleOptions.length - 1) ? this.visibleOptions.slice(index + 1).findIndex(option => this.isValidOption(option)) : -1;
685
+ return matchedOptionIndex > -1 ? matchedOptionIndex + index + 1 : index;
686
+ },
687
+ findPrevOptionIndex(index) {
688
+ const matchedOptionIndex = index > 0 ? this.visibleOptions.slice(0, index).findLastIndex(option => this.isValidOption(option)) : -1;
689
+ return matchedOptionIndex > -1 ? matchedOptionIndex : index;
690
+ },
691
+ findSelectedOptionIndex() {
692
+ return this.hasSelectedOption ? this.visibleOptions.findIndex(option => this.isValidSelectedOption(option)) : -1;
693
+ },
694
+ findFirstFocusedOptionIndex() {
695
+ const selectedIndex = this.findSelectedOptionIndex();
696
+ return selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex;
697
+ },
698
+ findLastFocusedOptionIndex() {
699
+ const selectedIndex = this.findSelectedOptionIndex();
700
+ return selectedIndex < 0 ? this.findLastOptionIndex() : selectedIndex;
701
+ },
702
+ searchOptions(event, char) {
703
+ this.searchValue = (this.searchValue || '') + char;
704
+
705
+ let optionIndex = -1;
706
+ let matched = false;
707
+
708
+ if (this.focusedOptionIndex !== -1) {
709
+ optionIndex = this.visibleOptions.slice(this.focusedOptionIndex).findIndex(option => this.isOptionMatched(option));
710
+ optionIndex = optionIndex === -1 ? this.visibleOptions.slice(0, this.focusedOptionIndex).findIndex(option => this.isOptionMatched(option)) : optionIndex + this.focusedOptionIndex;
711
+ }
712
+ else {
713
+ optionIndex = this.visibleOptions.findIndex(option => this.isOptionMatched(option));
540
714
  }
541
715
 
542
- if (this.searchTimeout) {
543
- clearTimeout(this.searchTimeout);
716
+ if (optionIndex !== -1) {
717
+ matched = true;
544
718
  }
545
719
 
546
- const char = event.key;
547
- this.previousSearchChar = this.currentSearchChar;
548
- this.currentSearchChar = char;
720
+ if (optionIndex === -1 && this.focusedOptionIndex === -1) {
721
+ optionIndex = this.findFirstFocusedOptionIndex();
722
+ }
549
723
 
550
- if (this.previousSearchChar === this.currentSearchChar)
551
- this.searchValue = this.currentSearchChar;
552
- else
553
- this.searchValue = this.searchValue ? this.searchValue + char : char;
724
+ if (optionIndex !== -1) {
725
+ this.changeFocusedOptionIndex(event, optionIndex);
726
+ }
554
727
 
555
- if (this.searchValue) {
556
- let searchIndex = this.getSelectedOptionIndex();
557
- let newOption = this.optionGroupLabel ? this.searchOptionInGroup(searchIndex) : this.searchOption(++searchIndex);
558
- if (newOption) {
559
- this.updateModel(event, this.getOptionValue(newOption));
560
- }
728
+ if (this.searchTimeout) {
729
+ clearTimeout(this.searchTimeout);
561
730
  }
562
731
 
563
732
  this.searchTimeout = setTimeout(() => {
564
- this.searchValue = null;
565
- }, 250);
566
- },
567
- searchOption(index) {
568
- let option;
569
-
570
- if (this.searchValue) {
571
- option = this.searchOptionInRange(index, this.visibleOptions.length);
572
-
573
- if (!option) {
574
- option = this.searchOptionInRange(0, index);
575
- }
576
- }
733
+ this.searchValue = '';
734
+ this.searchTimeout = null;
735
+ }, 500);
577
736
 
578
- return option;
737
+ return matched;
579
738
  },
580
- searchOptionInRange(start, end) {
581
- for (let i = start; i < end; i++) {
582
- let opt = this.visibleOptions[i];
583
- if (this.matchesSearchValue(opt)) {
584
- return opt;
739
+ changeFocusedOptionIndex(event, index) {
740
+ if (this.focusedOptionIndex !== index) {
741
+ this.focusedOptionIndex = index;
742
+ this.scrollInView();
743
+
744
+ if (this.selectOnFocus) {
745
+ this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
585
746
  }
586
747
  }
587
-
588
- return null;
589
748
  },
590
- searchOptionInGroup(index) {
591
- let searchIndex = index === -1 ? {group: 0, option: -1} : index;
592
-
593
- for (let i = searchIndex.group; i < this.visibleOptions.length; i++) {
594
- let groupOptions = this.getOptionGroupChildren(this.visibleOptions[i]);
595
- for (let j = (searchIndex.group === i ? searchIndex.option + 1 : 0); j < groupOptions.length; j++) {
596
- if (this.matchesSearchValue(groupOptions[j])) {
597
- return groupOptions[j];
598
- }
599
- }
749
+ scrollInView(index = -1) {
750
+ const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
751
+ const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
752
+ if (element) {
753
+ element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
600
754
  }
601
-
602
- for (let i = 0; i <= searchIndex.group; i++) {
603
- let groupOptions = this.getOptionGroupChildren(this.visibleOptions[i]);
604
- for (let j = 0; j < (searchIndex.group === i ? searchIndex.option: groupOptions.length); j++) {
605
- if (this.matchesSearchValue(groupOptions[j])) {
606
- return groupOptions[j];
607
- }
608
- }
755
+ else if (!this.virtualScrollerDisabled) {
756
+ setTimeout(() => {
757
+ this.virtualScroller && this.virtualScroller.scrollToIndex(index !== -1 ? index : this.focusedOptionIndex);
758
+ }, 0);
609
759
  }
610
-
611
- return null;
612
760
  },
613
- matchesSearchValue(option) {
614
- let label = this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale);
615
- return label.startsWith(this.searchValue.toLocaleLowerCase(this.filterLocale));
761
+ autoUpdateModel() {
762
+ if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
763
+ this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
764
+ const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
765
+ this.updateModel(null, value);
766
+ }
616
767
  },
617
- onFilterChange(event) {
618
- this.filterValue = event.target.value;
619
- this.$emit('filter', {originalEvent: event, value: event.target.value});
768
+ updateModel(event, value) {
769
+ this.$emit('update:modelValue', value);
770
+ this.$emit('change', { originalEvent: event, value });
620
771
  },
621
- onFilterUpdated() {
622
- if (this.overlayVisible) {
623
- this.alignOverlay();
624
- }
772
+ flatOptions(options) {
773
+ return (options || []).reduce((result, option, index) => {
774
+ result.push({ optionGroup: option, group: true, index });
775
+
776
+ const optionGroupChildren = this.getOptionGroupChildren(option);
777
+ optionGroupChildren && optionGroupChildren.forEach(o => result.push(o));
778
+
779
+ return result;
780
+ }, []);
625
781
  },
626
782
  overlayRef(el) {
627
783
  this.overlay = el;
628
784
  },
629
- itemsWrapperRef(el) {
630
- this.itemsWrapper = el;
785
+ listRef(el, contentRef) {
786
+ this.list = el;
787
+ contentRef && contentRef(el); // For VirtualScroller
631
788
  },
632
789
  virtualScrollerRef(el) {
633
790
  this.virtualScroller = el;
634
- },
635
- scrollValueInView() {
636
- if (this.overlay) {
637
- let selectedItem = DomHandler.findSingle(this.overlay, 'li.p-highlight');
638
- if (selectedItem) {
639
- selectedItem.scrollIntoView({ block: 'nearest', inline: 'start' });
640
- }
641
- }
642
- },
643
- onOverlayClick(event) {
644
- OverlayEventBus.emit('overlay-click', {
645
- originalEvent: event,
646
- target: this.$el
647
- });
648
791
  }
649
792
  },
650
793
  computed: {
651
- visibleOptions() {
652
- if (this.filterValue) {
653
- if (this.optionGroupLabel) {
654
- let filteredGroups = [];
655
- for (let optgroup of this.options) {
656
- let filteredSubOptions = FilterService.filter(this.getOptionGroupChildren(optgroup), this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
657
- if (filteredSubOptions && filteredSubOptions.length) {
658
- let filteredGroup = {...optgroup};
659
- filteredGroup[this.optionGroupChildren] = filteredSubOptions;
660
- filteredGroups.push(filteredGroup);
661
- }
662
- }
663
- return filteredGroups
664
- }
665
- else {
666
- return FilterService.filter(this.options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
667
- }
668
- }
669
- else {
670
- return this.options;
671
- }
672
- },
673
794
  containerClass() {
674
- return [
675
- 'p-dropdown p-component p-inputwrapper',
676
- {
677
- 'p-disabled': this.disabled,
678
- 'p-dropdown-clearable': this.showClear && !this.disabled,
679
- 'p-focus': this.focused,
680
- 'p-inputwrapper-filled': this.modelValue,
681
- 'p-inputwrapper-focus': this.focused || this.overlayVisible
682
- }
683
- ];
684
- },
685
- labelClass() {
686
- return [
687
- 'p-dropdown-label p-inputtext',
688
- {
689
- 'p-placeholder': this.label === this.placeholder,
690
- 'p-dropdown-label-empty': !this.$slots['value'] && (this.label === 'p-emptylabel' || this.label.length === 0)
691
- }
692
- ];
795
+ return ['p-dropdown p-component p-inputwrapper', {
796
+ 'p-disabled': this.disabled,
797
+ 'p-dropdown-clearable': this.showClear && !this.disabled,
798
+ 'p-focus': this.focused,
799
+ 'p-inputwrapper-filled': this.modelValue,
800
+ 'p-inputwrapper-focus': this.focused || this.overlayVisible,
801
+ 'p-overlay-open': this.overlayVisible
802
+ }];
803
+ },
804
+ inputStyleClass() {
805
+ return ['p-dropdown-label p-inputtext', this.inputClass, {
806
+ 'p-placeholder': !this.editable && this.label === this.placeholder,
807
+ 'p-dropdown-label-empty': !this.editable && !this.$slots['value'] && (this.label === 'p-emptylabel' || this.label.length === 0)
808
+ }];
693
809
  },
694
810
  panelStyleClass() {
695
811
  return ['p-dropdown-panel p-component', this.panelClass, {
@@ -697,19 +813,24 @@ export default {
697
813
  'p-ripple-disabled': this.$primevue.config.ripple === false
698
814
  }];
699
815
  },
816
+ dropdownIconClass() {
817
+ return ['p-dropdown-trigger-icon', (this.loading ? this.loadingIcon : 'pi pi-chevron-down')];
818
+ },
819
+ visibleOptions() {
820
+ const options = this.optionGroupLabel ? this.flatOptions(this.options) : (this.options || []);
821
+
822
+ return this.filterValue ? FilterService.filter(options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale) : options;
823
+ },
824
+ hasSelectedOption() {
825
+ return ObjectUtils.isNotEmpty(this.modelValue);
826
+ },
700
827
  label() {
701
- let selectedOption = this.getSelectedOption();
702
- if (selectedOption !== null)
703
- return this.getOptionLabel(selectedOption);
704
- else
705
- return this.placeholder||'p-emptylabel';
828
+ const selectedOptionIndex = this.findSelectedOptionIndex();
829
+ return selectedOptionIndex !== -1 ? this.getOptionLabel(this.visibleOptions[selectedOptionIndex]) : (this.placeholder || 'p-emptylabel');
706
830
  },
707
831
  editableInputValue() {
708
- let selectedOption = this.getSelectedOption();
709
- if (selectedOption)
710
- return this.getOptionLabel(selectedOption);
711
- else
712
- return this.modelValue;
832
+ const selectedOptionIndex = this.findSelectedOptionIndex();
833
+ return selectedOptionIndex !== -1 ? this.getOptionLabel(this.visibleOptions[selectedOptionIndex]) : (this.modelValue || '');
713
834
  },
714
835
  equalityKey() {
715
836
  return this.optionValue ? null : this.dataKey;
@@ -717,17 +838,35 @@ export default {
717
838
  searchFields() {
718
839
  return this.filterFields || [this.optionLabel];
719
840
  },
841
+ filterResultMessageText() {
842
+ return ObjectUtils.isNotEmpty(this.visibleOptions) ? this.filterMessageText.replaceAll('{0}', this.visibleOptions.length) : this.emptyFilterMessageText;
843
+ },
844
+ filterMessageText() {
845
+ return this.filterMessage || this.$primevue.config.locale.searchMessage;
846
+ },
720
847
  emptyFilterMessageText() {
721
- return this.emptyFilterMessage || this.$primevue.config.locale.emptyFilterMessage;
848
+ return this.emptyFilterMessage || this.$primevue.config.locale.emptySearchMessage || this.$primevue.config.locale.emptyFilterMessage;
722
849
  },
723
850
  emptyMessageText() {
724
851
  return this.emptyMessage || this.$primevue.config.locale.emptyMessage;
725
852
  },
853
+ selectionMessageText() {
854
+ return this.selectionMessage || this.$primevue.config.locale.selectionMessage;
855
+ },
856
+ emptySelectionMessageText() {
857
+ return this.emptySelectionMessage || this.$primevue.config.locale.emptySelectionMessage;
858
+ },
859
+ selectedMessageText() {
860
+ return this.hasSelectedOption ? this.selectionMessageText.replaceAll('{0}', '1') : this.emptySelectionMessageText;
861
+ },
862
+ focusedOptionId() {
863
+ return this.focusedOptionIndex !== -1 ? `${this.id}_${this.focusedOptionIndex}` : null;
864
+ },
865
+ ariaSetSize() {
866
+ return this.visibleOptions.filter(option => !this.isOptionGroup(option)).length;
867
+ },
726
868
  virtualScrollerDisabled() {
727
869
  return !this.virtualScrollerOptions;
728
- },
729
- dropdownIconClass() {
730
- return ['p-dropdown-trigger-icon', this.loading ? this.loadingIcon : 'pi pi-chevron-down'];
731
870
  }
732
871
  },
733
872
  directives: {
@@ -773,7 +912,7 @@ export default {
773
912
 
774
913
  .p-dropdown-label-empty {
775
914
  overflow: hidden;
776
- visibility: hidden;
915
+ opacity: 0;
777
916
  }
778
917
 
779
918
  input.p-dropdown-label {