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,8 +1,10 @@
1
1
  <template>
2
- <div ref="container" :class="containerClass" @click="onClick">
2
+ <div ref="container" :class="containerClass" @click="onContainerClick">
3
3
  <div class="p-hidden-accessible">
4
- <input ref="focusInput" type="text" role="listbox" :id="inputId" readonly :disabled="disabled" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" :tabindex="tabindex"
5
- aria-haspopup="true" :aria-expanded="overlayVisible" :aria-labelledby="ariaLabelledBy"/>
4
+ <input ref="focusInput" :id="inputId" type="text" readonly :disabled="disabled" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1"
5
+ role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="listbox" :aria-expanded="overlayVisible"
6
+ :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined"
7
+ @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" v-bind="inputProps" />
6
8
  </div>
7
9
  <div class="p-multiselect-label-container">
8
10
  <div :class="labelClass">
@@ -15,7 +17,7 @@
15
17
  <slot name="chip" :value="item">
16
18
  <span class="p-multiselect-token-label">{{getLabelByValue(item)}}</span>
17
19
  </slot>
18
- <span v-if="!disabled" class="p-multiselect-token-icon pi pi-times-circle" @click="removeChip(item)"></span>
20
+ <span v-if="!disabled" class="p-multiselect-token-icon pi pi-times-circle" @click="removeOption($event, item)"></span>
19
21
  </div>
20
22
  <template v-if="!modelValue || modelValue.length === 0">{{placeholder || 'empty'}}</template>
21
23
  </template>
@@ -24,37 +26,48 @@
24
26
  </div>
25
27
  <div class="p-multiselect-trigger">
26
28
  <slot name="indicator">
27
- <span :class="dropdownIconClass"></span>
29
+ <span :class="dropdownIconClass" aria-hidden="true"></span>
28
30
  </slot>
29
31
  </div>
30
32
  <Portal :appendTo="appendTo">
31
33
  <transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
32
- <div :ref="overlayRef" :class="panelStyleClass" v-if="overlayVisible" @click="onOverlayClick">
34
+ <div v-if="overlayVisible" :ref="overlayRef" :style="panelStyle" :class="panelStyleClass" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="panelProps">
35
+ <span ref="firstHiddenFocusableElementOnOverlay" role="presentation" aria-hidden="true" class="p-hidden-accessible p-hidden-focusable" :tabindex="0" @focus="onFirstHiddenFocus"></span>
33
36
  <slot name="header" :value="modelValue" :options="visibleOptions"></slot>
34
- <div class="p-multiselect-header" v-if="(showToggleAll && selectionLimit == null) || filter">
35
- <div class="p-checkbox p-component" @click="onToggleAll" role="checkbox" :aria-checked="allSelected" v-if="showToggleAll && selectionLimit == null">
37
+ <div v-if="(showToggleAll && selectionLimit == null) || filter" class="p-multiselect-header">
38
+ <div v-if="showToggleAll && selectionLimit == null" :class="headerCheckboxClass" @click="onToggleAll">
36
39
  <div class="p-hidden-accessible">
37
- <input type="checkbox" readonly @focus="onHeaderCheckboxFocus" @blur="onHeaderCheckboxBlur">
40
+ <input type="checkbox" readonly :checked="allSelected" :aria-label="toggleAllAriaLabel" @focus="onHeaderCheckboxFocus" @blur="onHeaderCheckboxBlur">
38
41
  </div>
39
- <div :class="['p-checkbox-box', {'p-highlight': allSelected, 'p-focus': headerCheckboxFocused}]" role="checkbox" :aria-checked="allSelected">
42
+ <div :class="['p-checkbox-box', {'p-highlight': allSelected, 'p-focus': headerCheckboxFocused}]">
40
43
  <span :class="['p-checkbox-icon', {'pi pi-check': allSelected}]"></span>
41
44
  </div>
42
45
  </div>
43
46
  <div v-if="filter" class="p-multiselect-filter-container">
44
- <input type="text" ref="filterInput" v-model="filterValue" autoComplete="on" class="p-multiselect-filter p-inputtext p-component" :placeholder="filterPlaceholder" @input="onFilterChange">
47
+ <input type="text" ref="filterInput" :value="filterValue" @vnode-updated="onFilterUpdated" class="p-multiselect-filter p-inputtext p-component" :placeholder="filterPlaceholder"
48
+ role="searchbox" autocomplete="off" :aria-owns="id + '_list'" :aria-activedescendant="focusedOptionId"
49
+ @keydown="onFilterKeyDown" @blur="onFilterBlur" @input="onFilterChange" v-bind="filterInputProps"/>
45
50
  <span class="p-multiselect-filter-icon pi pi-search"></span>
46
51
  </div>
47
- <button class="p-multiselect-close p-link" @click="onCloseClick" type="button" v-ripple>
52
+ <span v-if="filter" role="status" aria-live="polite" class="p-hidden-accessible">
53
+ {{filterResultMessageText}}
54
+ </span>
55
+ <button class="p-multiselect-close p-link" :aria-label="closeAriaLabel" @click="onCloseClick" type="button" v-ripple v-bind="closeButtonProps">
48
56
  <span class="p-multiselect-close-icon pi pi-times" />
49
57
  </button>
50
58
  </div>
51
59
  <div class="p-multiselect-items-wrapper" :style="{'max-height': virtualScrollerDisabled ? scrollHeight : ''}">
52
- <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{'height': scrollHeight}" :disabled="virtualScrollerDisabled">
53
- <template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle}">
54
- <ul :ref="contentRef" :class="['p-multiselect-items p-component', styleClass]" :style="contentStyle" role="listbox" aria-multiselectable="true">
55
- <template v-if="!optionGroupLabel">
56
- <li v-for="(option, i) of items" :class="['p-multiselect-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" role="option" :aria-selected="isSelected(option)"
57
- :key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @keydown="onOptionKeyDown($event, option)" :tabindex="tabindex||'0'" :aria-label="getOptionLabel(option)" v-ripple>
60
+ <VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{'height': scrollHeight}" :tabindex="-1" :disabled="virtualScrollerDisabled">
61
+ <template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle, itemSize }">
62
+ <ul :ref="(el) => listRef(el, contentRef)" :id="id + '_list'" :class="['p-multiselect-items p-component', styleClass]" :style="contentStyle" role="listbox" aria-multiselectable="true">
63
+ <template v-for="(option, i) of items" :key="getOptionRenderKey(option, getOptionIndex(i, getItemOptions))">
64
+ <li v-if="isOptionGroup(option)" :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}" class="p-multiselect-item-group" role="option">
65
+ <slot name="optiongroup" :option="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(option.optionGroup)}}</slot>
66
+ </li>
67
+ <li v-else v-ripple :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}"
68
+ :class="['p-multiselect-item', {'p-highlight': isSelected(option), 'p-focus': focusedOptionIndex === getOptionIndex(i, getItemOptions), 'p-disabled': isOptionDisabled(option)}]"
69
+ role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" :aria-disabled="isOptionDisabled(option)" :aria-setsize="ariaSetSize" :aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
70
+ @click="onOptionSelect($event, option, getOptionIndex(i, getItemOptions), true)" @mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))">
58
71
  <div class="p-checkbox p-component">
59
72
  <div :class="['p-checkbox-box', {'p-highlight': isSelected(option)}]">
60
73
  <span :class="['p-checkbox-icon', {'pi pi-check': isSelected(option)}]"></span>
@@ -65,38 +78,27 @@
65
78
  </slot>
66
79
  </li>
67
80
  </template>
68
- <template v-else>
69
- <template v-for="(optionGroup, i) of items" :key="getOptionGroupRenderKey(optionGroup)">
70
- <li class="p-multiselect-item-group">
71
- <slot name="optiongroup" :option="optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(optionGroup)}}</slot>
72
- </li>
73
- <li v-for="(option, i) of getOptionGroupChildren(optionGroup)" :class="['p-multiselect-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" role="option" :aria-selected="isSelected(option)"
74
- :key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @keydown="onOptionKeyDown($event, option)" :tabindex="tabindex||'0'" :aria-label="getOptionLabel(option)" v-ripple>
75
- <div class="p-checkbox p-component">
76
- <div :class="['p-checkbox-box', {'p-highlight': isSelected(option)}]">
77
- <span :class="['p-checkbox-icon', {'pi pi-check': isSelected(option)}]"></span>
78
- </div>
79
- </div>
80
- <slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">
81
- <span>{{getOptionLabel(option)}}</span>
82
- </slot>
83
- </li>
84
- </template>
85
- </template>
86
- <li v-if="filterValue && (!items || (items && items.length === 0))" class="p-multiselect-empty-message">
81
+ <li v-if="filterValue && (!items || (items && items.length === 0))" class="p-multiselect-empty-message" role="option">
87
82
  <slot name="emptyfilter">{{emptyFilterMessageText}}</slot>
88
83
  </li>
89
- <li v-else-if="(!options || (options && options.length === 0))" class="p-multiselect-empty-message">
84
+ <li v-else-if="(!options || (options && options.length === 0))" class="p-multiselect-empty-message" role="option">
90
85
  <slot name="empty">{{emptyMessageText}}</slot>
91
86
  </li>
92
87
  </ul>
88
+ <span v-if="(!options || (options && options.length === 0))" role="status" aria-live="polite" class="p-hidden-accessible">
89
+ {{emptyMessageText}}
90
+ </span>
91
+ <span role="status" aria-live="polite" class="p-hidden-accessible">
92
+ {{selectedMessageText}}
93
+ </span>
93
94
  </template>
94
- <template v-slot:loader="{ options }" v-if="$slots.loader">
95
+ <template v-if="$slots.loader" v-slot:loader="{ options }">
95
96
  <slot name="loader" :options="options"></slot>
96
97
  </template>
97
98
  </VirtualScroller>
98
99
  </div>
99
100
  <slot name="footer" :value="modelValue" :options="visibleOptions"></slot>
101
+ <span ref="lastHiddenFocusableElementOnOverlay" role="presentation" aria-hidden="true" class="p-hidden-accessible p-hidden-focusable" :tabindex="0" @focus="onLastHiddenFocus"></span>
100
102
  </div>
101
103
  </transition>
102
104
  </Portal>
@@ -104,7 +106,7 @@
104
106
  </template>
105
107
 
106
108
  <script>
107
- import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
109
+ import {ConnectedOverlayScrollHandler,UniqueComponentId,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
108
110
  import OverlayEventBus from 'primevue/overlayeventbus';
109
111
  import {FilterService} from 'primevue/api';
110
112
  import Ripple from 'primevue/ripple';
@@ -113,7 +115,7 @@ import Portal from 'primevue/portal';
113
115
 
114
116
  export default {
115
117
  name: 'MultiSelect',
116
- emits: ['update:modelValue', 'before-show', 'before-hide', 'change', 'show', 'hide', 'filter', 'selectall-change'],
118
+ emits: ['update:modelValue', 'change', 'focus', 'blur' , 'before-show', 'before-hide', 'show', 'hide', 'filter', 'selectall-change'],
117
119
  props: {
118
120
  modelValue: null,
119
121
  options: Array,
@@ -128,8 +130,13 @@ export default {
128
130
  },
129
131
  placeholder: String,
130
132
  disabled: Boolean,
131
- tabindex: String,
132
133
  inputId: String,
134
+ inputProps: null,
135
+ panelStyle: null,
136
+ panelClass: null,
137
+ panelProps: null,
138
+ filterInputProps: null,
139
+ closeButtonProps: null,
133
140
  dataKey: null,
134
141
  filter: Boolean,
135
142
  filterPlaceholder: String,
@@ -142,24 +149,14 @@ export default {
142
149
  type: Array,
143
150
  default: null
144
151
  },
145
- ariaLabelledBy: null,
146
152
  appendTo: {
147
153
  type: String,
148
154
  default: 'body'
149
155
  },
150
- emptyFilterMessage: {
151
- type: String,
152
- default: null
153
- },
154
- emptyMessage: {
155
- type: String,
156
- default: null
157
- },
158
156
  display: {
159
157
  type: String,
160
158
  default: 'comma'
161
159
  },
162
- panelClass: null,
163
160
  selectedItemsLabel: {
164
161
  type: String,
165
162
  default: '{0} items selected'
@@ -195,21 +192,75 @@ export default {
195
192
  virtualScrollerOptions: {
196
193
  type: Object,
197
194
  default: null
195
+ },
196
+ autoOptionFocus: {
197
+ type: Boolean,
198
+ default: true
199
+ },
200
+ filterMessage: {
201
+ type: String,
202
+ default: null
203
+ },
204
+ selectionMessage: {
205
+ type: String,
206
+ default: null
207
+ },
208
+ emptySelectionMessage: {
209
+ type: String,
210
+ default: null
211
+ },
212
+ emptyFilterMessage: {
213
+ type: String,
214
+ default: null
215
+ },
216
+ emptyMessage: {
217
+ type: String,
218
+ default: null
219
+ },
220
+ tabindex: {
221
+ type: Number,
222
+ default: 0
223
+ },
224
+ 'aria-label': {
225
+ type: String,
226
+ default: null
227
+ },
228
+ 'aria-labelledby': {
229
+ type: String,
230
+ default: null
198
231
  }
199
232
  },
233
+ outsideClickListener: null,
234
+ scrollHandler: null,
235
+ resizeListener: null,
236
+ overlay: null,
237
+ list: null,
238
+ virtualScroller: null,
239
+ startRangeIndex: -1,
240
+ searchTimeout: null,
241
+ searchValue: '',
242
+ selectOnFocus: false,
243
+ focusOnHover: false,
200
244
  data() {
201
245
  return {
246
+ id: UniqueComponentId(),
202
247
  focused: false,
248
+ focusedOptionIndex: -1,
203
249
  headerCheckboxFocused: false,
204
250
  filterValue: null,
205
251
  overlayVisible: false
206
- };
252
+ }
253
+ },
254
+ watch: {
255
+ options() {
256
+ this.autoUpdateModel();
257
+ }
258
+ },
259
+ mounted() {
260
+ this.id = this.$attrs.id || this.id;
261
+
262
+ this.autoUpdateModel();
207
263
  },
208
- outsideClickListener: null,
209
- resizeListener: null,
210
- scrollHandler: null,
211
- overlay: null,
212
- virtualScroller: null,
213
264
  beforeUnmount() {
214
265
  this.unbindOutsideClickListener();
215
266
  this.unbindResizeListener();
@@ -237,15 +288,6 @@ export default {
237
288
  getOptionRenderKey(option) {
238
289
  return this.dataKey ? ObjectUtils.resolveFieldData(option, this.dataKey) : this.getOptionLabel(option);
239
290
  },
240
- getOptionGroupRenderKey(optionGroup) {
241
- return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
242
- },
243
- getOptionGroupLabel(optionGroup) {
244
- return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
245
- },
246
- getOptionGroupChildren(optionGroup) {
247
- return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren);
248
- },
249
291
  isOptionDisabled(option) {
250
292
  if (this.maxSelectionLimitReached && !this.isSelected(option)) {
251
293
  return true;
@@ -253,112 +295,141 @@ export default {
253
295
 
254
296
  return this.optionDisabled ? ObjectUtils.resolveFieldData(option, this.optionDisabled) : false;
255
297
  },
256
- getSelectedOptionIndex() {
257
- if (this.modelValue != null && this.options) {
258
- if (this.optionGroupLabel) {
259
- for (let i = 0; i < this.options.length; i++) {
260
- let selectedOptionIndex = this.findOptionIndexInList(this.modelValue, this.getOptionGroupChildren(this.options[i]));
261
- if (selectedOptionIndex !== -1) {
262
- return {group: i, option: selectedOptionIndex};
263
- }
264
- }
265
- }
266
- else {
267
- return this.findOptionIndexInList(this.modelValue, this.options);
268
- }
269
- }
270
-
271
- return -1;
298
+ isOptionGroup(option) {
299
+ return this.optionGroupLabel && option.optionGroup && option.group;
272
300
  },
273
- findOptionIndexInList(value, list) {
274
- return value ? list.findIndex(item => value.some(val => ObjectUtils.equals(val, this.getOptionValue(item), this.equalityKey))) : -1;
301
+ getOptionGroupLabel(optionGroup) {
302
+ return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel);
275
303
  },
276
- isSelected(option) {
277
- if (this.modelValue) {
278
- let optionValue = this.getOptionValue(option);
279
- let key = this.equalityKey;
280
-
281
- return this.modelValue.some(val => ObjectUtils.equals(val, optionValue, key));
282
- }
283
-
284
- return false;
304
+ getOptionGroupChildren(optionGroup) {
305
+ return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren);
306
+ },
307
+ getAriaPosInset(index) {
308
+ return (this.optionGroupLabel ? index - this.visibleOptions.slice(0, index).filter(option => this.isOptionGroup(option)).length : index) + 1;
285
309
  },
286
- show() {
310
+ show(isFocus) {
287
311
  this.$emit('before-show');
288
312
  this.overlayVisible = true;
313
+ this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
314
+
315
+ isFocus && this.$refs.focusInput.focus();
289
316
  },
290
- hide() {
317
+ hide(isFocus) {
291
318
  this.$emit('before-hide');
292
319
  this.overlayVisible = false;
293
- if (this.resetFilterOnHide) {
294
- this.filterValue = null;
295
- }
320
+ this.focusedOptionIndex = -1;
321
+ this.searchValue = '';
322
+
323
+ this.resetFilterOnHide && (this.filterValue = null);
324
+ isFocus && this.$refs.focusInput.focus();
296
325
  },
297
- onFocus() {
326
+ onFocus(event) {
298
327
  this.focused = true;
328
+ this.focusedOptionIndex = this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
329
+ this.overlayVisible && this.scrollInView(this.focusedOptionIndex);
330
+ this.$emit('focus', event);
299
331
  },
300
- onBlur() {
332
+ onBlur(event) {
301
333
  this.focused = false;
334
+ this.focusedOptionIndex = -1;
335
+ this.searchValue = '';
336
+ this.$emit('blur', event);
302
337
  },
303
- onHeaderCheckboxFocus() {
304
- this.headerCheckboxFocused = true;
305
- },
306
- onHeaderCheckboxBlur() {
307
- this.headerCheckboxFocused = false;
308
- },
309
- onClick(event) {
310
- if (this.disabled || this.loading) {
311
- return;
312
- }
338
+ onKeyDown(event) {
339
+ switch (event.code) {
340
+ case 'ArrowDown':
341
+ this.onArrowDownKey(event);
342
+ break;
313
343
 
314
- if ((!this.overlay || !this.overlay.contains(event.target)) && !DomHandler.hasClass(event.target, 'p-multiselect-close')) {
315
- DomHandler.hasClass(event.target, 'p-multiselect-close');
316
- if (this.overlayVisible)
317
- this.hide();
318
- else
319
- this.show();
344
+ case 'ArrowUp':
345
+ this.onArrowUpKey(event);
346
+ break;
320
347
 
321
- this.$refs.focusInput.focus();
322
- }
323
- },
324
- onCloseClick() {
325
- this.hide();
326
- },
327
- onKeyDown(event) {
328
- switch(event.which) {
329
- //down
330
- case 40:
331
- if (this.visibleOptions && !this.overlayVisible && event.altKey) {
332
- this.show();
333
- }
334
- break;
348
+ case 'Home':
349
+ this.onHomeKey(event);
350
+ break;
351
+
352
+ case 'End':
353
+ this.onEndKey(event);
354
+ break;
355
+
356
+ case 'PageDown':
357
+ this.onPageDownKey(event);
358
+ break;
359
+
360
+ case 'PageUp':
361
+ this.onPageUpKey(event);
362
+ break;
363
+
364
+ case 'Enter':
365
+ case 'Space':
366
+ this.onEnterKey(event);
367
+ break;
368
+
369
+ case 'Escape':
370
+ this.onEscapeKey(event);
371
+ break;
372
+
373
+ case 'Tab':
374
+ this.onTabKey(event);
375
+ break;
376
+
377
+ case 'ShiftLeft':
378
+ case 'ShiftRight':
379
+ this.onShiftKey(event);
380
+ break;
381
+
382
+ default:
383
+ if (event.code === 'KeyA' && (event.metaKey || event.ctrlKey)) {
384
+ const value = this.visibleOptions.filter(option => this.isValidOption(option)).map(option => this.getOptionValue(option));
385
+ this.updateModel(event, value);
335
386
 
336
- //space
337
- case 32:
338
- if (!this.overlayVisible) {
339
- this.show();
340
387
  event.preventDefault();
388
+ break;
341
389
  }
342
- break;
343
390
 
344
- //escape
345
- case 27:
346
- if (this.overlayVisible) {
347
- this.hide();
391
+ if (ObjectUtils.isPrintableCharacter(event.key)) {
392
+ !this.overlayVisible && this.show();
393
+ this.searchOptions(event);
348
394
  event.preventDefault();
349
395
  }
350
- break;
351
396
 
352
- //tab
353
- case 9:
354
- this.hide();
355
- break;
397
+ break;
398
+ }
399
+ },
400
+ onContainerClick(event) {
401
+ if (this.disabled || this.loading) {
402
+ return;
403
+ }
356
404
 
357
- default:
358
- break;
405
+ if (!this.overlay || !this.overlay.contains(event.target)) {
406
+ this.overlayVisible ? this.hide(true) : this.show(true);
407
+ }
408
+ },
409
+ onFirstHiddenFocus(event) {
410
+ const relatedTarget = event.relatedTarget;
411
+
412
+ if (relatedTarget === this.$refs.focusInput) {
413
+ const firstFocusableEl = DomHandler.getFirstFocusableElement(this.overlay, ':not(.p-hidden-focusable)');
414
+ firstFocusableEl && firstFocusableEl.focus();
415
+ }
416
+ else {
417
+ this.$refs.focusInput.focus();
359
418
  }
360
419
  },
361
- onOptionSelect(event, option) {
420
+ onLastHiddenFocus() {
421
+ this.$refs.firstHiddenFocusableElementOnOverlay.focus();
422
+ },
423
+ onCloseClick() {
424
+ this.hide(true);
425
+ },
426
+ onHeaderCheckboxFocus() {
427
+ this.headerCheckboxFocused = true;
428
+ },
429
+ onHeaderCheckboxBlur() {
430
+ this.headerCheckboxFocused = false;
431
+ },
432
+ onOptionSelect(event, option, index = -1, isFocus = false) {
362
433
  if (this.disabled || this.isOptionDisabled(option)) {
363
434
  return;
364
435
  }
@@ -371,87 +442,241 @@ export default {
371
442
  else
372
443
  value = [...(this.modelValue || []), this.getOptionValue(option)];
373
444
 
374
- this.$emit('update:modelValue', value);
375
- this.$emit('change', {originalEvent: event, value: value});
445
+ this.updateModel(event, value);
446
+ isFocus && this.$refs.focusInput.focus();
447
+ index !== -1 && (this.focusedOptionIndex = index);
448
+ },
449
+ onOptionMouseMove(event, index) {
450
+ if (this.focusOnHover) {
451
+ this.changeFocusedOptionIndex(event, index);
452
+ }
376
453
  },
377
- onOptionKeyDown(event, option) {
378
- let listItem = event.target;
454
+ onOptionSelectRange(event, start = -1, end = -1) {
455
+ start === -1 && (start = this.findNearestSelectedOptionIndex(end, true));
456
+ end === -1 && (end = this.findNearestSelectedOptionIndex(start));
379
457
 
380
- switch(event.which) {
381
- //down
382
- case 40:
383
- var nextItem = this.findNextItem(listItem);
384
- if (nextItem) {
385
- nextItem.focus();
386
- }
458
+ if (start !== -1 && end !== -1) {
459
+ const rangeStart = Math.min(start, end);
460
+ const rangeEnd = Math.max(start, end);
461
+ const value = this.visibleOptions.slice(rangeStart, rangeEnd + 1).filter(option => this.isValidOption(option)).map(option => this.getOptionValue(option));
387
462
 
388
- event.preventDefault();
389
- break;
463
+ this.updateModel(event, value);
464
+ }
465
+ },
466
+ onFilterChange(event) {
467
+ const value = event.target.value;
390
468
 
391
- //up
392
- case 38:
393
- var prevItem = this.findPrevItem(listItem);
394
- if (prevItem) {
395
- prevItem.focus();
396
- }
469
+ this.filterValue = value;
470
+ this.focusedOptionIndex = -1;
471
+ this.$emit('filter', { originalEvent: event, value });
397
472
 
398
- event.preventDefault();
399
- break;
473
+ !this.virtualScrollerDisabled && this.virtualScroller.scrollToIndex(0);
474
+ },
475
+ onFilterKeyDown(event) {
476
+ switch (event.code) {
477
+ case 'ArrowDown':
478
+ this.onArrowDownKey(event);
479
+ break;
400
480
 
401
- //enter
402
- case 13:
403
- this.onOptionSelect(event, option);
404
- event.preventDefault();
405
- break;
481
+ case 'ArrowUp':
482
+ this.onArrowUpKey(event, true);
483
+ break;
484
+
485
+ case 'ArrowLeft':
486
+ case 'ArrowRight':
487
+ this.onArrowLeftKey(event, true);
488
+ break;
489
+
490
+ case 'Home':
491
+ this.onHomeKey(event, true);
492
+ break;
493
+
494
+ case 'End':
495
+ this.onEndKey(event, true);
496
+ break;
497
+
498
+ case 'Enter':
499
+ this.onEnterKey(event);
500
+ break;
501
+
502
+ case 'Escape':
503
+ this.onEscapeKey(event);
504
+ break;
505
+
506
+ case 'Tab':
507
+ this.onTabKey(event, true);
508
+ break;
406
509
 
407
510
  default:
408
- break;
511
+ break;
512
+ }
513
+ },
514
+ onFilterBlur() {
515
+ this.focusedOptionIndex = -1;
516
+ },
517
+ onFilterUpdated() {
518
+ if (this.overlayVisible) {
519
+ this.alignOverlay();
409
520
  }
410
521
  },
411
- findNextItem(item) {
412
- let nextItem = item.nextElementSibling;
522
+ onOverlayClick(event) {
523
+ OverlayEventBus.emit('overlay-click', {
524
+ originalEvent: event,
525
+ target: this.$el
526
+ });
527
+ },
528
+ onOverlayKeyDown(event) {
529
+ switch (event.code) {
530
+ case 'Escape':
531
+ this.onEscapeKey(event);
532
+ break;
413
533
 
414
- if (nextItem)
415
- return DomHandler.hasClass(nextItem, 'p-disabled') || DomHandler.hasClass(nextItem, 'p-multiselect-item-group') ? this.findNextItem(nextItem) : nextItem;
416
- else
417
- return null;
534
+ default:
535
+ break;
536
+ }
418
537
  },
419
- findPrevItem(item) {
420
- let prevItem = item.previousElementSibling;
538
+ onArrowDownKey(event) {
539
+ const optionIndex = this.focusedOptionIndex !== -1 ? this.findNextOptionIndex(this.focusedOptionIndex) : this.findFirstFocusedOptionIndex();
421
540
 
422
- if (prevItem)
423
- return DomHandler.hasClass(prevItem, 'p-disabled') || DomHandler.hasClass(prevItem, 'p-multiselect-item-group') ? this.findPrevItem(prevItem) : prevItem;
424
- else
425
- return null;
541
+ if (event.shiftKey) {
542
+ this.onOptionSelectRange(event, this.startRangeIndex, optionIndex);
543
+ }
544
+
545
+ this.changeFocusedOptionIndex(event, optionIndex);
546
+
547
+ !this.overlayVisible && this.show();
548
+ event.preventDefault();
426
549
  },
427
- onOverlayEnter(el) {
428
- ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
429
- this.alignOverlay();
550
+ onArrowUpKey(event, pressedInInputText = false) {
551
+ if (event.altKey && !pressedInInputText) {
552
+ if (this.focusedOptionIndex !== -1) {
553
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
554
+ }
555
+
556
+ this.overlayVisible && this.hide();
557
+ event.preventDefault();
558
+ }
559
+ else {
560
+ const optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.findLastFocusedOptionIndex();
561
+
562
+ if (event.shiftKey) {
563
+ this.onOptionSelectRange(event, optionIndex, this.startRangeIndex);
564
+ }
565
+
566
+ this.changeFocusedOptionIndex(event, optionIndex);
567
+
568
+ !this.overlayVisible && this.show();
569
+ event.preventDefault();
570
+ }
571
+ },
572
+ onArrowLeftKey(event, pressedInInputText = false) {
573
+ pressedInInputText && (this.focusedOptionIndex = -1);
574
+ },
575
+ onHomeKey(event, pressedInInputText = false) {
576
+ if (pressedInInputText) {
577
+ event.currentTarget.setSelectionRange(0, 0);
578
+ this.focusedOptionIndex = -1;
579
+ }
580
+ else {
581
+ let metaKey = event.metaKey || event.ctrlKey;
582
+ let optionIndex = this.findFirstOptionIndex();
583
+
584
+ if (event.shiftKey && metaKey) {
585
+ this.onOptionSelectRange(event, optionIndex, this.startRangeIndex);
586
+ }
587
+
588
+ this.changeFocusedOptionIndex(event, optionIndex);
589
+
590
+ !this.overlayVisible && this.show();
591
+ }
592
+
593
+ event.preventDefault();
594
+ },
595
+ onEndKey(event, pressedInInputText = false) {
596
+ if (pressedInInputText) {
597
+ const target = event.currentTarget;
598
+ const len = target.value.length;
599
+ target.setSelectionRange(len, len);
600
+ this.focusedOptionIndex = -1;
601
+ }
602
+ else {
603
+ let metaKey = event.metaKey || event.ctrlKey;
604
+ let optionIndex = this.findLastOptionIndex();
605
+
606
+ if (event.shiftKey && metaKey) {
607
+ this.onOptionSelectRange(event, this.startRangeIndex, optionIndex);
608
+ }
609
+
610
+ this.changeFocusedOptionIndex(event, optionIndex);
611
+
612
+ !this.overlayVisible && this.show();
613
+ }
614
+
615
+ event.preventDefault();
616
+ },
617
+ onPageUpKey(event) {
618
+ this.scrollInView(0);
619
+ event.preventDefault();
620
+ },
621
+ onPageDownKey(event) {
622
+ this.scrollInView(this.visibleOptions.length - 1);
623
+ event.preventDefault();
624
+ },
625
+ onEnterKey(event) {
626
+ if (!this.overlayVisible) {
627
+ this.onArrowDownKey(event);
628
+ }
629
+ else {
630
+ if (this.focusedOptionIndex !== -1) {
631
+ if (event.shiftKey)
632
+ this.onOptionSelectRange(event, this.focusedOptionIndex);
633
+ else
634
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
635
+ }
636
+ }
637
+
638
+ event.preventDefault();
639
+ },
640
+ onEscapeKey(event) {
641
+ this.overlayVisible && this.hide(true);
642
+ event.preventDefault();
643
+ },
644
+ onTabKey(event, pressedInInputText = false) {
645
+ if (!pressedInInputText) {
646
+ if (this.overlayVisible && this.hasFocusableElements()) {
647
+ this.$refs.firstHiddenFocusableElementOnOverlay.focus();
648
+
649
+ event.preventDefault();
650
+ }
651
+ else {
652
+ if (this.focusedOptionIndex !== -1) {
653
+ this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
654
+ }
430
655
 
431
- if (!this.virtualScrollerDisabled) {
432
- const selectedIndex = this.getSelectedOptionIndex();
433
- if (selectedIndex !== -1) {
434
- setTimeout(() => {
435
- this.virtualScroller && this.virtualScroller.scrollToIndex(selectedIndex)
436
- }, 0);
656
+ this.overlayVisible && this.hide(this.filter);
437
657
  }
438
658
  }
439
659
  },
660
+ onShiftKey() {
661
+ this.startRangeIndex = this.focusedOptionIndex;
662
+ },
663
+ onOverlayEnter(el) {
664
+ ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
665
+ this.alignOverlay();
666
+ this.scrollInView();
667
+ },
440
668
  onOverlayAfterEnter() {
441
669
  this.bindOutsideClickListener();
442
670
  this.bindScrollListener();
443
671
  this.bindResizeListener();
444
672
 
445
- if (this.filter) {
446
- this.$refs.filterInput.focus();
447
- }
448
-
449
673
  this.$emit('show');
450
674
  },
451
675
  onOverlayLeave() {
452
676
  this.unbindOutsideClickListener();
453
677
  this.unbindScrollListener();
454
678
  this.unbindResizeListener();
679
+
455
680
  this.$emit('hide');
456
681
  this.overlay = null;
457
682
  },
@@ -518,34 +743,9 @@ export default {
518
743
  isOutsideClicked(event) {
519
744
  return !(this.$el.isSameNode(event.target) || this.$el.contains(event.target) || (this.overlay && this.overlay.contains(event.target)));
520
745
  },
521
- getLabelByValue(val) {
522
- let option;
523
- if (this.options) {
524
- if (this.optionGroupLabel) {
525
- for (let optionGroup of this.options) {
526
- option = this.findOptionByValue(val, this.getOptionGroupChildren(optionGroup));
527
- if (option) {
528
- break;
529
- }
530
- }
531
- }
532
- else {
533
- option = this.findOptionByValue(val, this.options);
534
- }
535
- }
536
-
537
- return option ? this.getOptionLabel(option): null;
538
- },
539
- findOptionByValue(val, list) {
540
- for (let option of list) {
541
- let optionValue = this.getOptionValue(option);
542
-
543
- if(ObjectUtils.equals(optionValue, val, this.equalityKey)) {
544
- return option;
545
- }
546
- }
547
-
548
- return null;
746
+ getLabelByValue(value) {
747
+ const matchedOption = this.visibleOptions.find(option => !this.isOptionGroup(option) && ObjectUtils.equals(this.getOptionValue(option), value, this.equalityKey));
748
+ return matchedOption ? this.getOptionLabel(matchedOption): null;
549
749
  },
550
750
  getSelectedItemsLabel() {
551
751
  let pattern = /{(.*?)}/;
@@ -560,85 +760,176 @@ export default {
560
760
  this.$emit('selectall-change', {originalEvent: event, checked: !this.allSelected});
561
761
  }
562
762
  else {
563
- let value = null;
763
+ const value = this.allSelected ? [] : this.visibleOptions.filter(option => !this.isOptionGroup(option)).map(option => this.getOptionValue(option));
764
+
765
+ this.updateModel(event, value);
766
+ }
767
+
768
+ this.headerCheckboxFocused = true;
769
+ },
770
+ removeOption(event, optionValue) {
771
+ let value = this.modelValue.filter(val => !ObjectUtils.equals(val, optionValue, this.equalityKey));
772
+
773
+ this.updateModel(event, value);
774
+ },
775
+ clearFilter() {
776
+ this.filterValue = null;
777
+ },
778
+ hasFocusableElements() {
779
+ return DomHandler.getFocusableElements(this.overlay, ':not(.p-hidden-focusable)').length > 0;
780
+ },
781
+ isOptionMatched(option) {
782
+ return this.isValidOption(option) && this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).startsWith(this.searchValue.toLocaleLowerCase(this.filterLocale));
783
+ },
784
+ isValidOption(option) {
785
+ return option && !(this.isOptionDisabled(option) || this.isOptionGroup(option));
786
+ },
787
+ isValidSelectedOption(option) {
788
+ return this.isValidOption(option) && this.isSelected(option);
789
+ },
790
+ isSelected(option) {
791
+ const optionValue = this.getOptionValue(option);
792
+ return (this.modelValue || []).some(value => ObjectUtils.equals(value, optionValue, this.equalityKey));
793
+ },
794
+ findFirstOptionIndex() {
795
+ return this.visibleOptions.findIndex(option => this.isValidOption(option));
796
+ },
797
+ findLastOptionIndex() {
798
+ return ObjectUtils.findLastIndex(this.visibleOptions, option => this.isValidOption(option));
799
+ },
800
+ findNextOptionIndex(index) {
801
+ const matchedOptionIndex = index < (this.visibleOptions.length - 1) ? this.visibleOptions.slice(index + 1).findIndex(option => this.isValidOption(option)) : -1;
802
+ return matchedOptionIndex > -1 ? matchedOptionIndex + index + 1 : index;
803
+ },
804
+ findPrevOptionIndex(index) {
805
+ const matchedOptionIndex = index > 0 ? ObjectUtils.findLastIndex(this.visibleOptions.slice(0, index), option => this.isValidOption(option)) : -1;
806
+ return matchedOptionIndex > -1 ? matchedOptionIndex : index;
807
+ },
808
+ findFirstSelectedOptionIndex() {
809
+ return this.hasSelectedOption ? this.visibleOptions.findIndex(option => this.isValidSelectedOption(option)) : -1;
810
+ },
811
+ findLastSelectedOptionIndex() {
812
+ return this.hasSelectedOption ? ObjectUtils.findLastIndex(this.visibleOptions, option => this.isValidSelectedOption(option)) : -1;
813
+ },
814
+ findNextSelectedOptionIndex(index) {
815
+ const matchedOptionIndex = this.hasSelectedOption && index < (this.visibleOptions.length - 1) ? this.visibleOptions.slice(index + 1).findIndex(option => this.isValidSelectedOption(option)) : -1;
816
+ return matchedOptionIndex > -1 ? matchedOptionIndex + index + 1 : -1;
817
+ },
818
+ findPrevSelectedOptionIndex(index) {
819
+ const matchedOptionIndex = this.hasSelectedOption && index > 0 ? ObjectUtils.findLastIndex(this.visibleOptions.slice(0, index), option => this.isValidSelectedOption(option)) : -1;
820
+ return matchedOptionIndex > -1 ? matchedOptionIndex : -1;
821
+ },
822
+ findNearestSelectedOptionIndex(index, firstCheckUp = false) {
823
+ let matchedOptionIndex = -1;
564
824
 
565
- if (this.allSelected) {
566
- value = [];
825
+ if (this.hasSelectedOption) {
826
+ if (firstCheckUp) {
827
+ matchedOptionIndex = this.findPrevSelectedOptionIndex(index);
828
+ matchedOptionIndex = matchedOptionIndex === -1 ? this.findNextSelectedOptionIndex(index) : matchedOptionIndex;
567
829
  }
568
- else if (this.visibleOptions) {
569
- if (this.optionGroupLabel) {
570
- value = [];
571
- this.visibleOptions.forEach(optionGroup => {
572
- for (let option of this.getOptionGroupChildren(optionGroup)) {
573
- value.push(this.getOptionValue(option));
574
- }
575
- });
576
- }
577
- else {
578
- value = this.visibleOptions.map(option => this.getOptionValue(option));
579
- }
830
+ else {
831
+ matchedOptionIndex = this.findNextSelectedOptionIndex(index);
832
+ matchedOptionIndex = matchedOptionIndex === -1 ? this.findPrevSelectedOptionIndex(index) : matchedOptionIndex;
580
833
  }
834
+ }
835
+
836
+ return matchedOptionIndex > -1 ? matchedOptionIndex : index;
837
+ },
838
+ findFirstFocusedOptionIndex() {
839
+ const selectedIndex = this.findFirstSelectedOptionIndex();
840
+ return selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex;
841
+ },
842
+ findLastFocusedOptionIndex() {
843
+ const selectedIndex = this.findLastSelectedOptionIndex();
844
+ return selectedIndex < 0 ? this.findLastOptionIndex() : selectedIndex;
845
+ },
846
+ searchOptions(event) {
847
+ this.searchValue = (this.searchValue || '') + event.key;
848
+
849
+ let optionIndex = -1;
850
+ if (this.focusedOptionIndex !== -1) {
851
+ optionIndex = this.visibleOptions.slice(this.focusedOptionIndex).findIndex(option => this.isOptionMatched(option));
852
+ optionIndex = optionIndex === -1 ? this.visibleOptions.slice(0, this.focusedOptionIndex).findIndex(option => this.isOptionMatched(option)) : optionIndex + this.focusedOptionIndex;
853
+ }
854
+ else {
855
+ optionIndex = this.visibleOptions.findIndex(option => this.isOptionMatched(option));
856
+ }
857
+
858
+ if (optionIndex === -1 && this.focusedOptionIndex === -1) {
859
+ const selectedIndex = this.findSelectedOptionIndex();
860
+ optionIndex = selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex;
861
+ }
862
+
863
+ if (optionIndex !== -1) {
864
+ this.changeFocusedOptionIndex(event, optionIndex);
865
+ }
866
+
867
+ if (this.searchTimeout) {
868
+ clearTimeout(this.searchTimeout);
869
+ }
581
870
 
582
- this.$emit('update:modelValue', value);
583
- this.$emit('change', {originalEvent: event, value: value});
871
+ this.searchTimeout = setTimeout(() => {
872
+ this.searchValue = '';
873
+ this.searchTimeout = null;
874
+ }, 500);
875
+ },
876
+ changeFocusedOptionIndex(event, index) {
877
+ if (this.focusedOptionIndex !== index) {
878
+ this.focusedOptionIndex = index;
879
+ this.scrollInView();
584
880
  }
585
881
  },
586
- onFilterChange(event) {
587
- this.$emit('filter', {originalEvent: event, value: event.target.value});
588
- if (this.overlayVisible) {
589
- this.alignOverlay();
882
+ scrollInView(index = -1) {
883
+ const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
884
+ const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
885
+ if (element) {
886
+ element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'nearest' });
887
+ }
888
+ else if (!this.virtualScrollerDisabled) {
889
+ this.virtualScroller && this.virtualScroller.scrollToIndex(index !== -1 ? index : this.focusedOptionIndex);
590
890
  }
591
891
  },
592
- overlayRef(el) {
593
- this.overlay = el;
892
+ autoUpdateModel() {
893
+ if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
894
+ this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
895
+ const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
896
+ this.updateModel(null, [value]);
897
+ }
594
898
  },
595
- virtualScrollerRef(el) {
596
- this.virtualScroller = el;
899
+ updateModel(event, value) {
900
+ this.$emit('update:modelValue', value);
901
+ this.$emit('change', { originalEvent: event, value });
597
902
  },
598
- removeChip(item) {
599
- let value = this.modelValue.filter(val => !ObjectUtils.equals(val, item, this.equalityKey));
903
+ flatOptions(options) {
904
+ return (options || []).reduce((result, option, index) => {
905
+ result.push({ optionGroup: option, group: true, index });
600
906
 
601
- this.$emit('update:modelValue', value);
602
- this.$emit('change', {originalEvent: event, value: value});
907
+ const optionGroupChildren = this.getOptionGroupChildren(option);
908
+ optionGroupChildren && optionGroupChildren.forEach(o => result.push(o));
909
+
910
+ return result;
911
+ }, []);
603
912
  },
604
- onOverlayClick(event) {
605
- OverlayEventBus.emit('overlay-click', {
606
- originalEvent: event,
607
- target: this.$el
608
- });
913
+ overlayRef(el) {
914
+ this.overlay = el;
609
915
  },
610
- clearFilter() {
611
- this.filterValue = null;
916
+ listRef(el, contentRef) {
917
+ this.list = el;
918
+ contentRef && contentRef(el); // For VirtualScroller
919
+ },
920
+ virtualScrollerRef(el) {
921
+ this.virtualScroller = el;
612
922
  }
613
923
  },
614
924
  computed: {
615
- visibleOptions() {
616
- if (this.filterValue) {
617
- if (this.optionGroupLabel) {
618
- let filteredGroups = [];
619
- for (let optgroup of this.options) {
620
- let filteredSubOptions = FilterService.filter(this.getOptionGroupChildren(optgroup), this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
621
- if (filteredSubOptions && filteredSubOptions.length) {
622
- filteredGroups.push({...optgroup, ...{items: filteredSubOptions}});
623
- }
624
- }
625
- return filteredGroups
626
- }
627
- else {
628
- return FilterService.filter(this.options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale);
629
- }
630
- }
631
- else {
632
- return this.options;
633
- }
634
- },
635
925
  containerClass() {
636
926
  return ['p-multiselect p-component p-inputwrapper', {
637
927
  'p-multiselect-chip': this.display === 'chip',
638
928
  'p-disabled': this.disabled,
639
929
  'p-focus': this.focused,
640
930
  'p-inputwrapper-filled': this.modelValue && this.modelValue.length,
641
- 'p-inputwrapper-focus': this.focused || this.overlayVisible
931
+ 'p-inputwrapper-focus': this.focused || this.overlayVisible,
932
+ 'p-overlay-open': this.overlayVisible
642
933
  }];
643
934
  },
644
935
  labelClass() {
@@ -647,13 +938,27 @@ export default {
647
938
  'p-multiselect-label-empty': !this.placeholder && (!this.modelValue || this.modelValue.length === 0)
648
939
  }];
649
940
  },
941
+ dropdownIconClass() {
942
+ return ['p-multiselect-trigger-icon', this.loading ? this.loadingIcon : 'pi pi-chevron-down'];
943
+ },
650
944
  panelStyleClass() {
651
945
  return ['p-multiselect-panel p-component', this.panelClass, {
652
946
  'p-input-filled': this.$primevue.config.inputStyle === 'filled',
653
947
  'p-ripple-disabled': this.$primevue.config.ripple === false
654
948
  }];
655
949
  },
656
- label() {
950
+ headerCheckboxClass() {
951
+ return ['p-checkbox p-component', {
952
+ 'p-checkbox-checked': this.allSelected,
953
+ 'p-checkbox-focused': this.headerCheckboxFocused
954
+ }];
955
+ },
956
+ visibleOptions() {
957
+ const options = this.optionGroupLabel ? this.flatOptions(this.options) : (this.options || []);
958
+
959
+ return this.filterValue ? FilterService.filter(options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale) : options;
960
+ },
961
+ label() { // TODO: Refactor
657
962
  let label;
658
963
 
659
964
  if (this.modelValue && this.modelValue.length) {
@@ -662,8 +967,8 @@ export default {
662
967
  }
663
968
  else {
664
969
  label = '';
665
- for(let i = 0; i < this.modelValue.length; i++) {
666
- if(i !== 0) {
970
+ for (let i = 0; i < this.modelValue.length; i++) {
971
+ if (i !== 0) {
667
972
  label += ', ';
668
973
  }
669
974
 
@@ -678,48 +983,10 @@ export default {
678
983
  return label;
679
984
  },
680
985
  allSelected() {
681
- if (this.selectAll !== null) {
682
- return this.selectAll;
683
- }
684
- else {
685
- if (this.filterValue && this.filterValue.trim().length > 0) {
686
- if (this.visibleOptions.length === 0) {
687
- return false;
688
- }
689
-
690
- if (this.optionGroupLabel) {
691
- for (let optionGroup of this.visibleOptions) {
692
- for (let option of this.getOptionGroupChildren(optionGroup)) {
693
- if (!this.isSelected(option)) {
694
- return false;
695
- }
696
- }
697
- }
698
- }
699
- else {
700
- for (let option of this.visibleOptions) {
701
- if (!this.isSelected(option)) {
702
- return false;
703
- }
704
- }
705
- }
706
-
707
- return true;
708
- }
709
- else {
710
- if (this.modelValue && this.options) {
711
- let optionCount = 0;
712
- if (this.optionGroupLabel)
713
- this.options.forEach(optionGroup => optionCount += this.getOptionGroupChildren(optionGroup).length);
714
- else
715
- optionCount = this.options.length;
716
-
717
- return optionCount > 0 && optionCount === this.modelValue.length;
718
- }
719
-
720
- return false;
721
- }
722
- }
986
+ return (this.selectAll !== null) ? this.selectAll : (ObjectUtils.isNotEmpty(this.visibleOptions) && this.visibleOptions.every(option => this.isOptionGroup(option) || this.isValidSelectedOption(option)));
987
+ },
988
+ hasSelectedOption() {
989
+ return ObjectUtils.isNotEmpty(this.modelValue);
723
990
  },
724
991
  equalityKey() {
725
992
  return this.optionValue ? null : this.dataKey;
@@ -727,20 +994,44 @@ export default {
727
994
  searchFields() {
728
995
  return this.filterFields || [this.optionLabel];
729
996
  },
997
+ maxSelectionLimitReached() {
998
+ return this.selectionLimit && (this.modelValue && this.modelValue.length === this.selectionLimit);
999
+ },
1000
+ filterResultMessageText() {
1001
+ return ObjectUtils.isNotEmpty(this.visibleOptions) ? this.filterMessageText.replaceAll('{0}', this.visibleOptions.length) : this.emptyFilterMessageText;
1002
+ },
1003
+ filterMessageText() {
1004
+ return this.filterMessage || this.$primevue.config.locale.searchMessage || '';
1005
+ },
730
1006
  emptyFilterMessageText() {
731
- return this.emptyFilterMessage || this.$primevue.config.locale.emptyFilterMessage;
1007
+ return this.emptyFilterMessage || this.$primevue.config.locale.emptySearchMessage || this.$primevue.config.locale.emptyFilterMessage || '';
732
1008
  },
733
1009
  emptyMessageText() {
734
- return this.emptyMessage || this.$primevue.config.locale.emptyMessage;
1010
+ return this.emptyMessage || this.$primevue.config.locale.emptyMessage || '';
735
1011
  },
736
- virtualScrollerDisabled() {
737
- return !this.virtualScrollerOptions;
1012
+ selectionMessageText() {
1013
+ return this.selectionMessage || this.$primevue.config.locale.selectionMessage || '';
738
1014
  },
739
- maxSelectionLimitReached() {
740
- return this.selectionLimit && (this.modelValue && this.modelValue.length === this.selectionLimit);
1015
+ emptySelectionMessageText() {
1016
+ return this.emptySelectionMessage || this.$primevue.config.locale.emptySelectionMessage || '';
741
1017
  },
742
- dropdownIconClass() {
743
- return ['p-multiselect-trigger-icon', this.loading ? this.loadingIcon : 'pi pi-chevron-down'];
1018
+ selectedMessageText() {
1019
+ return this.hasSelectedOption ? this.selectionMessageText.replaceAll('{0}', this.modelValue.length) : this.emptySelectionMessageText;
1020
+ },
1021
+ focusedOptionId() {
1022
+ return this.focusedOptionIndex !== -1 ? `${this.id}_${this.focusedOptionIndex}` : null;
1023
+ },
1024
+ ariaSetSize() {
1025
+ return this.visibleOptions.filter(option => !this.isOptionGroup(option)).length;
1026
+ },
1027
+ toggleAllAriaLabel() {
1028
+ return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria[this.allSelected ? 'selectAll' : 'unselectAll'] : undefined;
1029
+ },
1030
+ closeAriaLabel() {
1031
+ return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.close : undefined;
1032
+ },
1033
+ virtualScrollerDisabled() {
1034
+ return !this.virtualScrollerOptions;
744
1035
  }
745
1036
  },
746
1037
  directives: {