@pine-ds/core 4.7.2 → 4.9.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 (536) hide show
  1. package/components/attributes.js +1 -1
  2. package/components/floating-ui.dom.js +1 -1
  3. package/components/index.js +1 -1
  4. package/components/index2.js +1 -1
  5. package/components/keep-hydrated.js +1 -0
  6. package/components/mock-pds-modal.js +1 -1
  7. package/components/pds-alert.js +1 -1
  8. package/components/pds-avatar.js +1 -1
  9. package/components/pds-box2.js +1 -1
  10. package/components/pds-button2.js +1 -1
  11. package/components/pds-checkbox2.js +1 -1
  12. package/components/pds-chip2.js +1 -1
  13. package/components/pds-combobox.js +1 -1
  14. package/components/pds-container.js +1 -1
  15. package/components/pds-copytext.js +1 -1
  16. package/components/pds-datepicker.js +1 -1
  17. package/components/pds-divider.js +1 -1
  18. package/components/pds-drawer-content.js +1 -1
  19. package/components/pds-drawer-footer.js +1 -1
  20. package/components/pds-drawer-header.js +1 -1
  21. package/components/pds-drawer.js +1 -1
  22. package/components/pds-dropdown-menu-item.js +1 -1
  23. package/components/pds-dropdown-menu-separator.js +1 -1
  24. package/components/pds-dropdown-menu.js +1 -1
  25. package/components/pds-filter.js +1 -1
  26. package/components/pds-filters.js +1 -1
  27. package/components/pds-image.js +1 -1
  28. package/components/pds-input2.js +1 -1
  29. package/components/pds-link2.js +1 -1
  30. package/components/pds-loader2.js +1 -1
  31. package/components/pds-modal-content.js +1 -1
  32. package/components/pds-modal-footer.js +1 -1
  33. package/components/pds-modal-header.js +1 -1
  34. package/components/pds-modal2.js +1 -1
  35. package/components/pds-multiselect.js +1 -1
  36. package/components/pds-popover.js +1 -1
  37. package/components/pds-progress.js +1 -1
  38. package/components/pds-property.js +1 -1
  39. package/components/pds-radio-group.js +1 -1
  40. package/components/pds-radio.js +1 -1
  41. package/components/pds-row.js +1 -1
  42. package/components/pds-select.js +1 -1
  43. package/components/pds-sortable-item.js +1 -1
  44. package/components/pds-sortable.js +2 -2
  45. package/components/pds-switch.js +1 -1
  46. package/components/pds-table-body.js +1 -1
  47. package/components/pds-table-cell2.js +1 -1
  48. package/components/pds-table-head-cell2.js +1 -1
  49. package/components/pds-table-head.js +1 -1
  50. package/components/pds-table-row.js +1 -1
  51. package/components/pds-tabpanel.js +1 -1
  52. package/components/pds-tabs.js +1 -1
  53. package/components/pds-text2.js +1 -1
  54. package/components/pds-textarea.js +1 -1
  55. package/components/pds-toast.js +1 -1
  56. package/components/pds-tooltip.js +1 -1
  57. package/components/tabbable.js +1 -0
  58. package/components/truncation-tooltip.js +1 -1
  59. package/dist/cjs/{attributes-BJ7KBHql.js → attributes-CW49XqaL.js} +1 -1
  60. package/dist/cjs/{floating-ui.dom-Dc8Anyel.js → floating-ui.dom-Dw41zbyY.js} +1 -0
  61. package/dist/cjs/{index-jl_Q819j.js → index-BsWY_xEJ.js} +1 -1
  62. package/dist/cjs/{index-5Azb8EQG.js → index-Do70atou.js} +1 -1
  63. package/dist/cjs/index.cjs.js +1 -1
  64. package/dist/cjs/{keep-hydrated-CiXgkEYd.js → keep-hydrated-AKoh0DG4.js} +1 -0
  65. package/dist/cjs/loader.cjs.js +3 -3
  66. package/dist/cjs/mock-pds-modal.cjs.entry.js +3 -3
  67. package/dist/cjs/pds-accordion.cjs.entry.js +3 -3
  68. package/dist/cjs/pds-alert.cjs.entry.js +17 -4
  69. package/dist/cjs/pds-avatar.cjs.entry.js +23 -13
  70. package/dist/cjs/pds-box.cjs.entry.js +4 -4
  71. package/dist/cjs/pds-button.cjs.entry.js +80 -45
  72. package/dist/cjs/pds-checkbox.cjs.entry.js +16 -8
  73. package/dist/cjs/pds-chip.cjs.entry.js +8 -8
  74. package/dist/cjs/pds-combobox.cjs.entry.js +43 -13
  75. package/dist/cjs/pds-container.cjs.entry.js +3 -3
  76. package/dist/cjs/pds-copytext.cjs.entry.js +7 -7
  77. package/dist/cjs/pds-datepicker.cjs.entry.js +6 -6
  78. package/dist/cjs/pds-divider.cjs.entry.js +3 -3
  79. package/dist/cjs/pds-drawer-content.cjs.entry.js +3 -3
  80. package/dist/cjs/pds-drawer-footer.cjs.entry.js +3 -3
  81. package/dist/cjs/pds-drawer-header.cjs.entry.js +3 -3
  82. package/dist/cjs/pds-drawer.cjs.entry.js +4 -4
  83. package/dist/cjs/pds-dropdown-menu-item.cjs.entry.js +34 -5
  84. package/dist/cjs/pds-dropdown-menu-separator.cjs.entry.js +3 -3
  85. package/dist/cjs/pds-dropdown-menu.cjs.entry.js +8 -8
  86. package/dist/cjs/pds-filter.cjs.entry.js +4 -4
  87. package/dist/cjs/pds-filters.cjs.entry.js +3 -3
  88. package/dist/cjs/pds-icon.cjs.entry.js +2 -2
  89. package/dist/cjs/pds-image.cjs.entry.js +4 -4
  90. package/dist/cjs/pds-input.cjs.entry.js +6 -6
  91. package/dist/cjs/pds-link.cjs.entry.js +15 -6
  92. package/dist/cjs/pds-loader.cjs.entry.js +4 -4
  93. package/dist/cjs/pds-modal-content.cjs.entry.js +34 -32
  94. package/dist/cjs/pds-modal-footer.cjs.entry.js +3 -3
  95. package/dist/cjs/pds-modal-header.cjs.entry.js +3 -3
  96. package/dist/cjs/pds-modal.cjs.entry.js +9 -89
  97. package/dist/cjs/pds-multiselect.cjs.entry.js +9 -9
  98. package/dist/cjs/pds-popover.cjs.entry.js +416 -163
  99. package/dist/cjs/pds-progress.cjs.entry.js +4 -4
  100. package/dist/cjs/pds-property.cjs.entry.js +3 -3
  101. package/dist/cjs/pds-radio-group.cjs.entry.js +6 -6
  102. package/dist/cjs/pds-radio.cjs.entry.js +24 -11
  103. package/dist/cjs/pds-row.cjs.entry.js +4 -4
  104. package/dist/cjs/pds-select.cjs.entry.js +132 -21
  105. package/dist/cjs/pds-sortable-item.cjs.entry.js +5 -5
  106. package/dist/cjs/pds-sortable.cjs.entry.js +4 -4
  107. package/dist/cjs/pds-switch.cjs.entry.js +7 -7
  108. package/dist/cjs/pds-tab.cjs.entry.js +3 -3
  109. package/dist/cjs/pds-table-body.cjs.entry.js +3 -3
  110. package/dist/cjs/pds-table-cell.cjs.entry.js +6 -6
  111. package/dist/cjs/pds-table-head-cell.cjs.entry.js +5 -5
  112. package/dist/cjs/pds-table-head.cjs.entry.js +3 -3
  113. package/dist/cjs/pds-table-row.cjs.entry.js +3 -3
  114. package/dist/cjs/pds-table.cjs.entry.js +2 -2
  115. package/dist/cjs/pds-tabpanel.cjs.entry.js +4 -4
  116. package/dist/cjs/pds-tabs.cjs.entry.js +4 -4
  117. package/dist/cjs/pds-text.cjs.entry.js +5 -5
  118. package/dist/cjs/pds-textarea.cjs.entry.js +8 -8
  119. package/dist/cjs/pds-toast.cjs.entry.js +14 -8
  120. package/dist/cjs/pds-tooltip.cjs.entry.js +115 -44
  121. package/dist/cjs/pine-core.cjs.js +3 -3
  122. package/dist/cjs/tabbable-CddSt_Hi.js +85 -0
  123. package/dist/cjs/{truncation-tooltip-DO9xli2e.js → truncation-tooltip-O5nQmXPw.js} +32 -7
  124. package/dist/collection/components/pds-alert/pds-alert.css +13 -0
  125. package/dist/collection/components/pds-alert/pds-alert.js +36 -1
  126. package/dist/collection/components/pds-alert/stories/pds-alert.stories.js +4 -0
  127. package/dist/collection/components/pds-avatar/pds-avatar.js +42 -10
  128. package/dist/collection/components/pds-avatar/stories/pds-avatar.stories.js +2 -0
  129. package/dist/collection/components/pds-box/pds-box.js +1 -1
  130. package/dist/collection/components/pds-button/pds-button.js +36 -44
  131. package/dist/collection/components/pds-button/stories/pds-button.stories.js +3 -3
  132. package/dist/collection/components/pds-checkbox/pds-checkbox.css +79 -0
  133. package/dist/collection/components/pds-checkbox/pds-checkbox.js +36 -5
  134. package/dist/collection/components/pds-checkbox/stories/pds-checkbox.stories.js +38 -0
  135. package/dist/collection/components/pds-chip/pds-chip.js +2 -2
  136. package/dist/collection/components/pds-combobox/pds-combobox.css +33 -0
  137. package/dist/collection/components/pds-combobox/pds-combobox.js +62 -9
  138. package/dist/collection/components/pds-combobox/stories/pds-combobox.stories.js +44 -0
  139. package/dist/collection/components/pds-container/pds-container.js +1 -1
  140. package/dist/collection/components/pds-copytext/pds-copytext.js +1 -1
  141. package/dist/collection/components/pds-datepicker/pds-datepicker.js +2 -2
  142. package/dist/collection/components/pds-datepicker/stories/pds-datepicker.stories.js +1 -1
  143. package/dist/collection/components/pds-divider/pds-divider.js +1 -1
  144. package/dist/collection/components/pds-drawer/pds-drawer-content/pds-drawer-content.js +1 -1
  145. package/dist/collection/components/pds-drawer/pds-drawer-footer/pds-drawer-footer.js +1 -1
  146. package/dist/collection/components/pds-drawer/pds-drawer-header/pds-drawer-header.js +1 -1
  147. package/dist/collection/components/pds-drawer/pds-drawer.js +2 -2
  148. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.css +8 -0
  149. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.js +81 -7
  150. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu-separator/pds-dropdown-menu-separator.js +1 -1
  151. package/dist/collection/components/pds-dropdown-menu/pds-dropdown-menu.js +4 -4
  152. package/dist/collection/components/pds-dropdown-menu/stories/pds-dropdown-menu.stories.js +39 -0
  153. package/dist/collection/components/pds-filters/pds-filter/pds-filter.js +1 -1
  154. package/dist/collection/components/pds-filters/pds-filters.js +1 -1
  155. package/dist/collection/components/pds-image/pds-image.js +2 -2
  156. package/dist/collection/components/pds-input/pds-input.js +2 -2
  157. package/dist/collection/components/pds-input/stories/pds-input.stories.js +6 -6
  158. package/dist/collection/components/pds-link/pds-link.js +34 -3
  159. package/dist/collection/components/pds-link/stories/pds-link.stories.js +3 -2
  160. package/dist/collection/components/pds-loader/pds-loader.js +1 -1
  161. package/dist/collection/components/pds-modal/pds-modal-content/pds-modal-content.js +32 -30
  162. package/dist/collection/components/pds-modal/pds-modal-footer/pds-modal-footer.js +1 -1
  163. package/dist/collection/components/pds-modal/pds-modal-header/pds-modal-header.js +1 -1
  164. package/dist/collection/components/pds-modal/pds-modal.js +5 -85
  165. package/dist/collection/components/pds-modal/test/mock-pds-modal.js +1 -1
  166. package/dist/collection/components/pds-multiselect/pds-multiselect.js +5 -5
  167. package/dist/collection/components/pds-popover/pds-popover.css +6 -0
  168. package/dist/collection/components/pds-popover/pds-popover.js +465 -159
  169. package/dist/collection/components/pds-popover/stories/pds-popover.stories.js +31 -0
  170. package/dist/collection/components/pds-progress/pds-progress.js +1 -1
  171. package/dist/collection/components/pds-property/pds-property.js +1 -1
  172. package/dist/collection/components/pds-radio/pds-radio.css +57 -0
  173. package/dist/collection/components/pds-radio/pds-radio.js +45 -9
  174. package/dist/collection/components/pds-radio/stories/pds-radio.stories.js +15 -0
  175. package/dist/collection/components/pds-radio-group/pds-radio-group.js +3 -3
  176. package/dist/collection/components/pds-radio-group/stories/pds-radio-group.stories.js +45 -0
  177. package/dist/collection/components/pds-row/pds-row.js +1 -1
  178. package/dist/collection/components/pds-select/pds-select.js +128 -17
  179. package/dist/collection/components/pds-select/stories/pds-select.stories.js +2 -2
  180. package/dist/collection/components/pds-sortable/pds-sortable-item/pds-sortable-item.js +1 -1
  181. package/dist/collection/components/pds-sortable/pds-sortable.js +1 -1
  182. package/dist/collection/components/pds-switch/pds-switch.js +3 -3
  183. package/dist/collection/components/pds-table/pds-table-body/pds-table-body.js +1 -1
  184. package/dist/collection/components/pds-table/pds-table-cell/pds-table-cell.js +2 -2
  185. package/dist/collection/components/pds-table/pds-table-head/pds-table-head.js +1 -1
  186. package/dist/collection/components/pds-table/pds-table-head-cell/pds-table-head-cell.js +2 -2
  187. package/dist/collection/components/pds-table/pds-table-row/pds-table-row.js +1 -1
  188. package/dist/collection/components/pds-table/stories/pds-table.stories.js +4 -4
  189. package/dist/collection/components/pds-tabs/pds-tabpanel/pds-tabpanel.js +1 -1
  190. package/dist/collection/components/pds-tabs/pds-tabs.js +1 -1
  191. package/dist/collection/components/pds-text/pds-text.js +1 -1
  192. package/dist/collection/components/pds-text/stories/pds-text.stories.js +1 -1
  193. package/dist/collection/components/pds-textarea/pds-textarea.js +4 -4
  194. package/dist/collection/components/pds-textarea/stories/pds-textarea.stories.js +2 -2
  195. package/dist/collection/components/pds-toast/pds-toast.css +13 -0
  196. package/dist/collection/components/pds-toast/pds-toast.js +33 -5
  197. package/dist/collection/components/pds-toast/stories/pds-toast.stories.js +4 -1
  198. package/dist/collection/components/pds-tooltip/pds-tooltip.js +113 -41
  199. package/dist/collection/utils/aria-references.js +42 -0
  200. package/dist/collection/utils/tabbable.js +81 -0
  201. package/dist/collection/utils/truncation-tooltip.js +31 -6
  202. package/dist/docs.json +367 -13
  203. package/dist/esm/{attributes-WXw_I_uJ.js → attributes-DkeVeN0g.js} +1 -1
  204. package/dist/esm/{floating-ui.dom-BPqJgIq6.js → floating-ui.dom-Cuc0DYlm.js} +1 -1
  205. package/dist/esm/{index-Cw9J31qd.js → index-BFSwd-GQ.js} +1 -1
  206. package/dist/esm/{index-BJXk71tO.js → index-m3pqpeWg.js} +2 -2
  207. package/dist/esm/index.js +1 -1
  208. package/dist/esm/{keep-hydrated-BLG6RDBt.js → keep-hydrated-BgNaWLoS.js} +1 -1
  209. package/dist/esm/loader.js +4 -4
  210. package/dist/esm/mock-pds-modal.entry.js +3 -3
  211. package/dist/esm/pds-accordion.entry.js +3 -3
  212. package/dist/esm/pds-alert.entry.js +17 -4
  213. package/dist/esm/pds-avatar.entry.js +23 -13
  214. package/dist/esm/pds-box.entry.js +4 -4
  215. package/dist/esm/pds-button.entry.js +80 -45
  216. package/dist/esm/pds-checkbox.entry.js +16 -8
  217. package/dist/esm/pds-chip.entry.js +8 -8
  218. package/dist/esm/pds-combobox.entry.js +43 -13
  219. package/dist/esm/pds-container.entry.js +3 -3
  220. package/dist/esm/pds-copytext.entry.js +7 -7
  221. package/dist/esm/pds-datepicker.entry.js +6 -6
  222. package/dist/esm/pds-divider.entry.js +3 -3
  223. package/dist/esm/pds-drawer-content.entry.js +3 -3
  224. package/dist/esm/pds-drawer-footer.entry.js +3 -3
  225. package/dist/esm/pds-drawer-header.entry.js +3 -3
  226. package/dist/esm/pds-drawer.entry.js +4 -4
  227. package/dist/esm/pds-dropdown-menu-item.entry.js +34 -5
  228. package/dist/esm/pds-dropdown-menu-separator.entry.js +3 -3
  229. package/dist/esm/pds-dropdown-menu.entry.js +8 -8
  230. package/dist/esm/pds-filter.entry.js +4 -4
  231. package/dist/esm/pds-filters.entry.js +3 -3
  232. package/dist/esm/pds-icon.entry.js +2 -2
  233. package/dist/esm/pds-image.entry.js +4 -4
  234. package/dist/esm/pds-input.entry.js +6 -6
  235. package/dist/esm/pds-link.entry.js +15 -6
  236. package/dist/esm/pds-loader.entry.js +4 -4
  237. package/dist/esm/pds-modal-content.entry.js +34 -32
  238. package/dist/esm/pds-modal-footer.entry.js +3 -3
  239. package/dist/esm/pds-modal-header.entry.js +3 -3
  240. package/dist/esm/pds-modal.entry.js +7 -87
  241. package/dist/esm/pds-multiselect.entry.js +9 -9
  242. package/dist/esm/pds-popover.entry.js +416 -163
  243. package/dist/esm/pds-progress.entry.js +4 -4
  244. package/dist/esm/pds-property.entry.js +3 -3
  245. package/dist/esm/pds-radio-group.entry.js +6 -6
  246. package/dist/esm/pds-radio.entry.js +24 -11
  247. package/dist/esm/pds-row.entry.js +4 -4
  248. package/dist/esm/pds-select.entry.js +132 -21
  249. package/dist/esm/pds-sortable-item.entry.js +5 -5
  250. package/dist/esm/pds-sortable.entry.js +4 -4
  251. package/dist/esm/pds-switch.entry.js +7 -7
  252. package/dist/esm/pds-tab.entry.js +3 -3
  253. package/dist/esm/pds-table-body.entry.js +3 -3
  254. package/dist/esm/pds-table-cell.entry.js +6 -6
  255. package/dist/esm/pds-table-head-cell.entry.js +5 -5
  256. package/dist/esm/pds-table-head.entry.js +3 -3
  257. package/dist/esm/pds-table-row.entry.js +3 -3
  258. package/dist/esm/pds-table.entry.js +2 -2
  259. package/dist/esm/pds-tabpanel.entry.js +4 -4
  260. package/dist/esm/pds-tabs.entry.js +4 -4
  261. package/dist/esm/pds-text.entry.js +5 -5
  262. package/dist/esm/pds-textarea.entry.js +8 -8
  263. package/dist/esm/pds-toast.entry.js +14 -8
  264. package/dist/esm/pds-tooltip.entry.js +115 -44
  265. package/dist/esm/pine-core.js +4 -4
  266. package/dist/esm/tabbable-DCKBKRUy.js +83 -0
  267. package/dist/esm/{truncation-tooltip-DRXsdKk1.js → truncation-tooltip-D_gvhB9r.js} +32 -7
  268. package/dist/esm-es5/{attributes-WXw_I_uJ.js → attributes-DkeVeN0g.js} +1 -1
  269. package/dist/esm-es5/{floating-ui.dom-BPqJgIq6.js → floating-ui.dom-Cuc0DYlm.js} +1 -1
  270. package/dist/esm-es5/{index-Cw9J31qd.js → index-BFSwd-GQ.js} +2 -2
  271. package/dist/esm-es5/{index-BJXk71tO.js → index-m3pqpeWg.js} +1 -1
  272. package/dist/esm-es5/index.js +1 -1
  273. package/dist/esm-es5/{keep-hydrated-BLG6RDBt.js → keep-hydrated-BgNaWLoS.js} +1 -1
  274. package/dist/esm-es5/loader.js +1 -1
  275. package/dist/esm-es5/mock-pds-modal.entry.js +1 -1
  276. package/dist/esm-es5/pds-accordion.entry.js +1 -1
  277. package/dist/esm-es5/pds-alert.entry.js +1 -1
  278. package/dist/esm-es5/pds-avatar.entry.js +1 -1
  279. package/dist/esm-es5/pds-box.entry.js +1 -1
  280. package/dist/esm-es5/pds-button.entry.js +1 -1
  281. package/dist/esm-es5/pds-checkbox.entry.js +1 -1
  282. package/dist/esm-es5/pds-chip.entry.js +1 -1
  283. package/dist/esm-es5/pds-combobox.entry.js +2 -2
  284. package/dist/esm-es5/pds-container.entry.js +1 -1
  285. package/dist/esm-es5/pds-copytext.entry.js +1 -1
  286. package/dist/esm-es5/pds-datepicker.entry.js +1 -1
  287. package/dist/esm-es5/pds-divider.entry.js +1 -1
  288. package/dist/esm-es5/pds-drawer-content.entry.js +1 -1
  289. package/dist/esm-es5/pds-drawer-footer.entry.js +1 -1
  290. package/dist/esm-es5/pds-drawer-header.entry.js +1 -1
  291. package/dist/esm-es5/pds-drawer.entry.js +1 -1
  292. package/dist/esm-es5/pds-dropdown-menu-item.entry.js +1 -1
  293. package/dist/esm-es5/pds-dropdown-menu-separator.entry.js +1 -1
  294. package/dist/esm-es5/pds-dropdown-menu.entry.js +1 -1
  295. package/dist/esm-es5/pds-filter.entry.js +1 -1
  296. package/dist/esm-es5/pds-filters.entry.js +1 -1
  297. package/dist/esm-es5/pds-icon.entry.js +1 -1
  298. package/dist/esm-es5/pds-image.entry.js +1 -1
  299. package/dist/esm-es5/pds-input.entry.js +1 -1
  300. package/dist/esm-es5/pds-link.entry.js +1 -1
  301. package/dist/esm-es5/pds-loader.entry.js +1 -1
  302. package/dist/esm-es5/pds-modal-content.entry.js +1 -1
  303. package/dist/esm-es5/pds-modal-footer.entry.js +1 -1
  304. package/dist/esm-es5/pds-modal-header.entry.js +1 -1
  305. package/dist/esm-es5/pds-modal.entry.js +1 -1
  306. package/dist/esm-es5/pds-multiselect.entry.js +1 -1
  307. package/dist/esm-es5/pds-popover.entry.js +1 -1
  308. package/dist/esm-es5/pds-progress.entry.js +1 -1
  309. package/dist/esm-es5/pds-property.entry.js +1 -1
  310. package/dist/esm-es5/pds-radio-group.entry.js +1 -1
  311. package/dist/esm-es5/pds-radio.entry.js +1 -1
  312. package/dist/esm-es5/pds-row.entry.js +1 -1
  313. package/dist/esm-es5/pds-select.entry.js +1 -1
  314. package/dist/esm-es5/pds-sortable-item.entry.js +1 -1
  315. package/dist/esm-es5/pds-sortable.entry.js +2 -2
  316. package/dist/esm-es5/pds-switch.entry.js +1 -1
  317. package/dist/esm-es5/pds-tab.entry.js +1 -1
  318. package/dist/esm-es5/pds-table-body.entry.js +1 -1
  319. package/dist/esm-es5/pds-table-cell.entry.js +1 -1
  320. package/dist/esm-es5/pds-table-head-cell.entry.js +1 -1
  321. package/dist/esm-es5/pds-table-head.entry.js +1 -1
  322. package/dist/esm-es5/pds-table-row.entry.js +1 -1
  323. package/dist/esm-es5/pds-table.entry.js +1 -1
  324. package/dist/esm-es5/pds-tabpanel.entry.js +1 -1
  325. package/dist/esm-es5/pds-tabs.entry.js +1 -1
  326. package/dist/esm-es5/pds-text.entry.js +1 -1
  327. package/dist/esm-es5/pds-textarea.entry.js +1 -1
  328. package/dist/esm-es5/pds-toast.entry.js +1 -1
  329. package/dist/esm-es5/pds-tooltip.entry.js +1 -1
  330. package/dist/esm-es5/pine-core.js +1 -1
  331. package/dist/esm-es5/tabbable-DCKBKRUy.js +1 -0
  332. package/dist/esm-es5/truncation-tooltip-D_gvhB9r.js +1 -0
  333. package/dist/pine-core/index.esm.js +1 -1
  334. package/dist/pine-core/p-001d4b86.entry.js +1 -0
  335. package/dist/pine-core/p-06279b93.system.entry.js +1 -0
  336. package/dist/pine-core/{p-b75b0d09.system.entry.js → p-0790dd0d.system.entry.js} +1 -1
  337. package/dist/pine-core/p-079c39d1.entry.js +1 -0
  338. package/dist/pine-core/p-07b4524e.entry.js +1 -0
  339. package/dist/pine-core/{p-b60ac7eb.system.entry.js → p-08bbd3e6.system.entry.js} +1 -1
  340. package/dist/pine-core/{p-c5c9ed36.system.entry.js → p-0bd61097.system.entry.js} +1 -1
  341. package/dist/pine-core/p-0c60f577.system.entry.js +1 -0
  342. package/dist/pine-core/{p-6d603d16.system.entry.js → p-110b4051.system.entry.js} +1 -1
  343. package/dist/pine-core/p-11e7d660.entry.js +1 -0
  344. package/dist/pine-core/p-14d872d3.entry.js +1 -0
  345. package/dist/pine-core/p-17fc76e7.system.entry.js +1 -0
  346. package/dist/pine-core/{p-0913f696.system.entry.js → p-1e5648bf.system.entry.js} +1 -1
  347. package/dist/pine-core/{p-e803f629.system.entry.js → p-22ae92f7.system.entry.js} +1 -1
  348. package/dist/pine-core/p-239774c9.entry.js +1 -0
  349. package/dist/pine-core/{p-0b71ecb6.system.entry.js → p-25bf2f26.system.entry.js} +2 -2
  350. package/dist/pine-core/{p-e7a95a49.system.entry.js → p-272b24ad.system.entry.js} +1 -1
  351. package/dist/pine-core/{p-d2c91e7a.entry.js → p-2c0047cd.entry.js} +1 -1
  352. package/dist/pine-core/p-2d5b1deb.entry.js +1 -0
  353. package/dist/pine-core/{p-e8cb76e8.entry.js → p-3556f6ad.entry.js} +1 -1
  354. package/dist/pine-core/{p-BGLP3keB.js → p-35s7h-dk.js} +1 -1
  355. package/dist/pine-core/{p-080cb087.system.entry.js → p-38b87aa2.system.entry.js} +1 -1
  356. package/dist/pine-core/{p-355e4cf9.entry.js → p-3afb1208.entry.js} +1 -1
  357. package/dist/pine-core/p-3b5b8f73.entry.js +1 -0
  358. package/dist/pine-core/{p-8c8cc079.system.entry.js → p-3cc19ea8.system.entry.js} +1 -1
  359. package/dist/pine-core/{p-bd67156b.system.entry.js → p-3ce7e72e.system.entry.js} +1 -1
  360. package/dist/pine-core/p-3f62581a.system.entry.js +1 -0
  361. package/dist/pine-core/p-414faecf.entry.js +1 -0
  362. package/dist/pine-core/p-463a29fa.entry.js +1 -0
  363. package/dist/pine-core/{p-f029b7da.system.entry.js → p-4ee44585.system.entry.js} +1 -1
  364. package/dist/pine-core/p-50af67ea.system.entry.js +1 -0
  365. package/dist/pine-core/p-5133e8be.system.entry.js +1 -0
  366. package/dist/pine-core/p-55fce29e.entry.js +1 -0
  367. package/dist/pine-core/{p-77395d62.system.entry.js → p-568a9a79.system.entry.js} +1 -1
  368. package/dist/pine-core/p-5967d9fa.system.entry.js +1 -0
  369. package/dist/pine-core/{p-5870b092.system.entry.js → p-5c46553f.system.entry.js} +1 -1
  370. package/dist/pine-core/{p-f0d24298.system.entry.js → p-5ce5836e.system.entry.js} +1 -1
  371. package/dist/pine-core/p-5f3242c8.system.entry.js +1 -0
  372. package/dist/pine-core/{p-80e6f3a0.system.entry.js → p-60d27247.system.entry.js} +1 -1
  373. package/dist/pine-core/{p-bd26a5e8.entry.js → p-60e3b1af.entry.js} +1 -1
  374. package/dist/pine-core/{p-ca0a8f5c.entry.js → p-64283f7b.entry.js} +1 -1
  375. package/dist/pine-core/p-6602b4d0.entry.js +1 -0
  376. package/dist/pine-core/p-6845867f.system.entry.js +1 -0
  377. package/dist/pine-core/{p-1ee86d87.system.entry.js → p-68fdfb8f.system.entry.js} +1 -1
  378. package/dist/pine-core/p-6b6ae1be.entry.js +1 -0
  379. package/dist/pine-core/{p-e5420660.entry.js → p-6d64e6c7.entry.js} +1 -1
  380. package/dist/pine-core/{p-3a959459.system.entry.js → p-6dad76cb.system.entry.js} +1 -1
  381. package/dist/pine-core/p-6f34ad9c.entry.js +1 -0
  382. package/dist/pine-core/{p-55224683.entry.js → p-7073146f.entry.js} +1 -1
  383. package/dist/pine-core/{p-f1702281.entry.js → p-735b3631.entry.js} +1 -1
  384. package/dist/pine-core/p-7a14473e.entry.js +1 -0
  385. package/dist/pine-core/{p-9880d251.system.entry.js → p-7a19477e.system.entry.js} +1 -1
  386. package/dist/pine-core/{p-88ff1604.entry.js → p-7d3a20ba.entry.js} +1 -1
  387. package/dist/pine-core/{p-a939b471.entry.js → p-7fcf3d37.entry.js} +1 -1
  388. package/dist/pine-core/{p-26642718.entry.js → p-87642228.entry.js} +1 -1
  389. package/dist/pine-core/p-89fefe36.entry.js +1 -0
  390. package/dist/pine-core/p-8b97dd57.system.entry.js +1 -0
  391. package/dist/pine-core/{p-0092444c.system.entry.js → p-9201b497.system.entry.js} +1 -1
  392. package/dist/pine-core/{p-ebd0bff2.entry.js → p-92a8cf7d.entry.js} +1 -1
  393. package/dist/pine-core/{p-e836a041.entry.js → p-94597b73.entry.js} +1 -1
  394. package/dist/pine-core/p-9713d6a5.system.entry.js +1 -0
  395. package/dist/pine-core/p-97be00f4.system.entry.js +1 -0
  396. package/dist/pine-core/{p-2ac2457b.system.entry.js → p-98843402.system.entry.js} +1 -1
  397. package/dist/pine-core/{p-b914dde8.entry.js → p-98cc327b.entry.js} +2 -2
  398. package/dist/pine-core/p-9a8971e2.system.entry.js +1 -0
  399. package/dist/pine-core/p-9a8d2985.system.entry.js +3 -0
  400. package/dist/pine-core/{p-cfc52b95.system.entry.js → p-9dbc017f.system.entry.js} +1 -1
  401. package/dist/pine-core/p-9fbcba0d.entry.js +1 -0
  402. package/dist/pine-core/p-9fe4a64a.entry.js +1 -0
  403. package/dist/pine-core/{p-COtCa1Md.system.js → p-BNTlHhoO.system.js} +1 -1
  404. package/dist/pine-core/p-BZ1l3LGl.system.js +1 -0
  405. package/dist/pine-core/p-BgNaWLoS.js +1 -0
  406. package/dist/pine-core/{p-CmSJytt1.js → p-BplEmwUQ.js} +2 -2
  407. package/dist/pine-core/{p-Cy8cvR7I.system.js → p-CANeE7Ss.system.js} +1 -1
  408. package/dist/pine-core/{p-XW4H0W6i.system.js → p-CNXspDYs.system.js} +1 -1
  409. package/dist/pine-core/{p-JtdHT_W5.js → p-CirzxZ33.js} +1 -1
  410. package/dist/pine-core/{p-CGRdQc49.system.js → p-CjRCtzPD.system.js} +2 -2
  411. package/dist/pine-core/{p-BPqJgIq6.js → p-Cuc0DYlm.js} +1 -1
  412. package/dist/pine-core/p-D52aRqFx.system.js +1 -0
  413. package/dist/pine-core/p-DCKBKRUy.js +1 -0
  414. package/dist/pine-core/p-DXO1yd32.system.js +1 -0
  415. package/dist/pine-core/{p-n3_ytl_p.system.js → p-DaCT2ssj.system.js} +1 -1
  416. package/dist/pine-core/p-a2078add.entry.js +1 -0
  417. package/dist/pine-core/{p-97d0b89e.system.entry.js → p-a48b025a.system.entry.js} +1 -1
  418. package/dist/pine-core/{p-9713fb36.entry.js → p-a7d25143.entry.js} +1 -1
  419. package/dist/pine-core/{p-9dcd2cdb.entry.js → p-ad3b1ec3.entry.js} +1 -1
  420. package/dist/pine-core/p-b017eb99.system.entry.js +1 -0
  421. package/dist/pine-core/p-b037dcbd.system.entry.js +1 -0
  422. package/dist/pine-core/{p-db17c626.system.entry.js → p-b243767b.system.entry.js} +1 -1
  423. package/dist/pine-core/{p-341c38f1.system.entry.js → p-b33ad96e.system.entry.js} +1 -1
  424. package/dist/pine-core/p-b6edfdfe.entry.js +2 -0
  425. package/dist/pine-core/{p-8191498f.system.entry.js → p-b7cbd913.system.entry.js} +1 -1
  426. package/dist/pine-core/{p-8f531063.entry.js → p-b9d71b76.entry.js} +1 -1
  427. package/dist/pine-core/p-bcf57566.entry.js +1 -0
  428. package/dist/pine-core/{p-4fd454f6.entry.js → p-bda7e3be.entry.js} +1 -1
  429. package/dist/pine-core/p-bdde1e53.entry.js +1 -0
  430. package/dist/pine-core/{p-cb6a3e4c.system.entry.js → p-be3b4f12.system.entry.js} +1 -1
  431. package/dist/pine-core/{p-b1548a20.entry.js → p-bfdfbe9f.entry.js} +1 -1
  432. package/dist/pine-core/p-c02a32ec.entry.js +1 -0
  433. package/dist/pine-core/p-c1da80e5.entry.js +1 -0
  434. package/dist/pine-core/{p-d8570b4b.system.entry.js → p-c233866c.system.entry.js} +1 -1
  435. package/dist/pine-core/{p-fc25b956.system.entry.js → p-cb560aab.system.entry.js} +1 -1
  436. package/dist/pine-core/{p-02088776.entry.js → p-ce554098.entry.js} +1 -1
  437. package/dist/pine-core/p-ced6a814.system.entry.js +1 -0
  438. package/dist/pine-core/{p-0a84d220.entry.js → p-d7930540.entry.js} +1 -1
  439. package/dist/pine-core/{p-11d98408.system.entry.js → p-d7db749a.system.entry.js} +1 -1
  440. package/dist/pine-core/{p-7a5b21d2.system.entry.js → p-d8bedb58.system.entry.js} +1 -1
  441. package/dist/pine-core/{p-1dc5a7e0.system.entry.js → p-d9243653.system.entry.js} +1 -1
  442. package/dist/pine-core/{p-9ab95438.entry.js → p-d94ebe84.entry.js} +1 -1
  443. package/dist/pine-core/{p-9109b90a.entry.js → p-de176bd9.entry.js} +1 -1
  444. package/dist/pine-core/{p-57a2f927.entry.js → p-dea2a254.entry.js} +1 -1
  445. package/dist/pine-core/p-dfadfcd1.entry.js +1 -0
  446. package/dist/pine-core/{p-1437585e.system.entry.js → p-e1fdd53a.system.entry.js} +1 -1
  447. package/dist/pine-core/{p-4435fff6.system.entry.js → p-e70cb112.system.entry.js} +1 -1
  448. package/dist/pine-core/{p-01aa382c.system.entry.js → p-e9a53a88.system.entry.js} +1 -1
  449. package/dist/pine-core/p-eb93cc6e.entry.js +1 -0
  450. package/dist/pine-core/{p-4d03d1e2.system.entry.js → p-ebf0c51b.system.entry.js} +1 -1
  451. package/dist/pine-core/p-ebf74c43.system.entry.js +1 -0
  452. package/dist/pine-core/{p-cde8eb81.entry.js → p-ee449a4b.entry.js} +1 -1
  453. package/dist/pine-core/p-ef4d8fea.entry.js +1 -0
  454. package/dist/pine-core/p-f09f27ab.system.entry.js +1 -0
  455. package/dist/pine-core/{p-ff3de72e.entry.js → p-f2c487e6.entry.js} +1 -1
  456. package/dist/pine-core/p-f549f2bc.entry.js +1 -0
  457. package/dist/pine-core/p-fc743f6e.entry.js +1 -0
  458. package/dist/pine-core/{p-BJXk71tO.js → p-m3pqpeWg.js} +1 -1
  459. package/dist/pine-core/p-wXfuz0Bd.system.js +1 -0
  460. package/dist/pine-core/pine-core.esm.js +1 -1
  461. package/dist/pine-core/pine-core.js +1 -1
  462. package/dist/types/components/pds-alert/pds-alert.d.ts +10 -0
  463. package/dist/types/components/pds-avatar/pds-avatar.d.ts +8 -0
  464. package/dist/types/components/pds-button/pds-button.d.ts +5 -6
  465. package/dist/types/components/pds-checkbox/pds-checkbox.d.ts +7 -1
  466. package/dist/types/components/pds-combobox/pds-combobox.d.ts +9 -0
  467. package/dist/types/components/pds-dropdown-menu/pds-dropdown-menu-item/pds-dropdown-menu-item.d.ts +20 -3
  468. package/dist/types/components/pds-link/pds-link.d.ts +8 -0
  469. package/dist/types/components/pds-modal/pds-modal-content/pds-modal-content.d.ts +2 -0
  470. package/dist/types/components/pds-popover/pds-popover.d.ts +87 -21
  471. package/dist/types/components/pds-radio/pds-radio.d.ts +9 -3
  472. package/dist/types/components/pds-select/pds-select.d.ts +32 -4
  473. package/dist/types/components/pds-toast/pds-toast.d.ts +9 -0
  474. package/dist/types/components/pds-tooltip/pds-tooltip.d.ts +31 -0
  475. package/dist/types/components.d.ts +139 -18
  476. package/dist/types/utils/aria-references.d.ts +24 -0
  477. package/dist/types/utils/tabbable.d.ts +2 -0
  478. package/dist/types/utils/truncation-tooltip.d.ts +4 -4
  479. package/dist/types/utils/types.d.ts +1 -0
  480. package/dist/vscode.html-data.json +129 -14
  481. package/hydrate/index.js +1040 -416
  482. package/hydrate/index.mjs +1040 -416
  483. package/package.json +2 -2
  484. package/dist/esm-es5/truncation-tooltip-DRXsdKk1.js +0 -1
  485. package/dist/pine-core/p-049f126a.entry.js +0 -1
  486. package/dist/pine-core/p-153ba77b.entry.js +0 -1
  487. package/dist/pine-core/p-208c7dbf.entry.js +0 -1
  488. package/dist/pine-core/p-258770cf.system.entry.js +0 -1
  489. package/dist/pine-core/p-2cb5483a.system.entry.js +0 -1
  490. package/dist/pine-core/p-432d5ec7.entry.js +0 -1
  491. package/dist/pine-core/p-5442d983.system.entry.js +0 -1
  492. package/dist/pine-core/p-576cf904.system.entry.js +0 -1
  493. package/dist/pine-core/p-5c90091e.system.entry.js +0 -1
  494. package/dist/pine-core/p-602c197f.entry.js +0 -1
  495. package/dist/pine-core/p-645a482b.system.entry.js +0 -1
  496. package/dist/pine-core/p-72865997.entry.js +0 -1
  497. package/dist/pine-core/p-75ee0403.entry.js +0 -1
  498. package/dist/pine-core/p-7a287635.system.entry.js +0 -1
  499. package/dist/pine-core/p-7bf6563a.system.entry.js +0 -1
  500. package/dist/pine-core/p-7fa66cad.entry.js +0 -1
  501. package/dist/pine-core/p-80a698ae.entry.js +0 -1
  502. package/dist/pine-core/p-82cf4ec6.entry.js +0 -1
  503. package/dist/pine-core/p-86040cac.system.entry.js +0 -1
  504. package/dist/pine-core/p-875b0436.system.entry.js +0 -1
  505. package/dist/pine-core/p-8cc302aa.system.entry.js +0 -1
  506. package/dist/pine-core/p-8d292b48.entry.js +0 -1
  507. package/dist/pine-core/p-92ae6082.entry.js +0 -1
  508. package/dist/pine-core/p-94593f20.system.entry.js +0 -1
  509. package/dist/pine-core/p-993d1043.entry.js +0 -1
  510. package/dist/pine-core/p-99459e27.entry.js +0 -1
  511. package/dist/pine-core/p-BLG6RDBt.js +0 -1
  512. package/dist/pine-core/p-BR5nujVX.system.js +0 -1
  513. package/dist/pine-core/p-CuSNnuFu.system.js +0 -1
  514. package/dist/pine-core/p-a0960b3d.system.entry.js +0 -1
  515. package/dist/pine-core/p-a1230a74.system.entry.js +0 -1
  516. package/dist/pine-core/p-a19cd59c.entry.js +0 -1
  517. package/dist/pine-core/p-a787b34a.system.entry.js +0 -1
  518. package/dist/pine-core/p-a826f290.entry.js +0 -1
  519. package/dist/pine-core/p-aa032a5e.system.entry.js +0 -1
  520. package/dist/pine-core/p-acce8eb2.entry.js +0 -1
  521. package/dist/pine-core/p-b69f04b7.entry.js +0 -1
  522. package/dist/pine-core/p-bb68431a.entry.js +0 -1
  523. package/dist/pine-core/p-bb73ad66.entry.js +0 -2
  524. package/dist/pine-core/p-beb23781.entry.js +0 -1
  525. package/dist/pine-core/p-bf30dec0.entry.js +0 -1
  526. package/dist/pine-core/p-c36b490e.entry.js +0 -1
  527. package/dist/pine-core/p-c81d8ac8.entry.js +0 -1
  528. package/dist/pine-core/p-ca0d48e8.entry.js +0 -1
  529. package/dist/pine-core/p-cfd012d4.entry.js +0 -1
  530. package/dist/pine-core/p-e0917a26.entry.js +0 -1
  531. package/dist/pine-core/p-e836f3ec.system.entry.js +0 -3
  532. package/dist/pine-core/p-ea4d4741.system.entry.js +0 -1
  533. package/dist/pine-core/p-f2c253d8.entry.js +0 -1
  534. package/dist/pine-core/p-f474d7de.entry.js +0 -1
  535. package/dist/pine-core/p-f77905aa.system.entry.js +0 -1
  536. package/dist/pine-core/p-qhdoK1Jp.system.js +0 -1
@@ -1,11 +1,35 @@
1
1
  import { Host, h } from "@stencil/core";
2
+ import { autoUpdate, computePosition, flip, offset, platform, shift } from "@floating-ui/dom";
2
3
  import { closest, containsComposed } from "../../utils/closest";
3
4
  import { restoreReflectedDefault } from "../../utils/reflected-attribute-default";
4
5
  import { setAttributesIfChanged } from "../../utils/attributes";
5
6
  import { cssEscape } from "../../utils/css";
6
7
  import { limitRestores } from "../../utils/keep-hydrated";
7
- /** Open auto popovers, in the order they opened: Escape goes to the last one it applies to. */
8
- const openAutoPopovers = [];
8
+ import { tabbableIn } from "../../utils/tabbable";
9
+ /** Open popovers that close on Escape, in the order they opened: Escape goes to the last one it applies to. */
10
+ const popoversTakingEscape = [];
11
+ /** Hovering the trigger waits this long before opening, so a pointer passing over it doesn't open it. */
12
+ const HOVER_OPEN_DELAY_MS = 120;
13
+ /** Leaving the trigger and panel waits this long before closing, which covers the gap between them. */
14
+ const HOVER_CLOSE_DELAY_MS = 200;
15
+ /**
16
+ * floating-ui reporting viewport coordinates, as `position: fixed` uses without a containing block. Its own
17
+ * containing-block check misses a backdrop filter in WebKit, so handlePopoverPositioning corrects for one itself.
18
+ */
19
+ const viewportPlatform = Object.assign(Object.assign({}, platform), { getOffsetParent: () => window });
20
+ /**
21
+ * Where `top: 0; left: 0` puts a fixed element beside the given one. An empty probe is measured instead of the
22
+ * element, whose own transforms, such as an entrance animation, would otherwise read as part of the offset.
23
+ */
24
+ const containingBlockOrigin = (element) => {
25
+ var _a;
26
+ const probe = document.createElement('div');
27
+ probe.style.cssText = 'all: initial; position: fixed; top: 0; left: 0;';
28
+ (_a = element.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(probe, element);
29
+ const { top, left } = probe.getBoundingClientRect();
30
+ probe.remove();
31
+ return { top, left };
32
+ };
9
33
  /** The focused element, followed down through shadow roots to the control that has focus. */
10
34
  function deepActiveElement() {
11
35
  var _a;
@@ -14,6 +38,27 @@ function deepActiveElement() {
14
38
  active = active.shadowRoot.activeElement;
15
39
  return active;
16
40
  }
41
+ /** `node`, or the shadow host it sits in, lifted until it shares a tree with `other` or reaches the document. */
42
+ function liftToTreeOf(node, other) {
43
+ let current = node;
44
+ while (current.getRootNode() !== other.getRootNode() && current.getRootNode() instanceof ShadowRoot) {
45
+ current = current.getRootNode().host;
46
+ }
47
+ return current;
48
+ }
49
+ /**
50
+ * Where `node` sits relative to `ref`, as `compareDocumentPosition` reports it. Whichever of the two
51
+ * is inside a shadow root is lifted to its host first, so a control inside a component compares too.
52
+ */
53
+ function positionAcrossTrees(ref, node) {
54
+ const lifted = liftToTreeOf(node, ref);
55
+ return liftToTreeOf(ref, lifted).compareDocumentPosition(lifted);
56
+ }
57
+ const isPosition = (position, flag) => (position & Node.DOCUMENT_POSITION_DISCONNECTED) === 0 && (position & flag) !== 0;
58
+ /** The popover each panel belongs to, so a popover inside another one's panel can find it. */
59
+ const panelOwners = new WeakMap();
60
+ /** Floating layers Pine components put at the end of the page or of a dialog, as a popover does its panel. */
61
+ const FLOATING_LAYERS = '.pds-popover, .pds-datepicker-calendar-portal, .pds-combobox-dropdown-portal';
17
62
  /**
18
63
  * @slot trigger - The trigger element for the popover
19
64
  * @slot (default) - The content to display inside the popover
@@ -50,14 +95,21 @@ export class PdsPopover {
50
95
  */
51
96
  this.portalEl = null;
52
97
  /**
53
- * Guard to prevent repositioning loops
98
+ * Stops floating-ui's autoUpdate, which repositions the open panel as its trigger or the page moves or resizes
99
+ */
100
+ this.stopAutoUpdate = null;
101
+ /**
102
+ * Counts positioning runs, so a run that resolves after a newer one started is dropped
103
+ */
104
+ this.positioningRun = 0;
105
+ /**
106
+ * The latest positioning run, which pdsPopoverOpen waits for so the panel's side is set when it fires
54
107
  */
55
- this.isRepositioning = false;
108
+ this.positioning = Promise.resolve();
56
109
  /**
57
- * Debounce timers for performance optimization
110
+ * Set while show() waits to emit pdsPopoverOpen, so a hide() in the meantime emits it first
58
111
  */
59
- this.scrollDebounceTimer = null;
60
- this.resizeDebounceTimer = null;
112
+ this.openEventPending = false;
61
113
  /**
62
114
  * Track moved nodes and their placeholders for restoration
63
115
  */
@@ -66,11 +118,41 @@ export class PdsPopover {
66
118
  * Timestamp when popover was opened (for preventing immediate close)
67
119
  */
68
120
  this.openTimestamp = 0;
121
+ /**
122
+ * Set while hover holds the popover open, until a click pins it or it closes
123
+ */
124
+ this.hoverOpened = false;
125
+ /**
126
+ * Set when the pointer left while focus was in the panel, so focus leaving it closes it instead
127
+ */
128
+ this.closeWhenFocusLeaves = false;
129
+ /**
130
+ * How far the pointer was from the panel at its last move after leaving the trigger
131
+ */
132
+ this.panelDistance = Infinity;
133
+ /**
134
+ * Stands in for the panel in the Tab order, right after the trigger, while the popover is open
135
+ */
136
+ this.tabGuardEl = null;
137
+ /**
138
+ * Set while focus passes through the guard on its way out of the panel
139
+ */
140
+ this.leavingPanel = false;
141
+ /**
142
+ * The direction of the Tab key being handled, until its default action has run
143
+ */
144
+ this.tabDirection = null;
69
145
  /**
70
146
  * Determines the action that triggers the popover. For manual popovers, the consumer is responsible for toggling this value.
71
147
  * @defaultValue "show"
72
148
  */
73
149
  this.popoverTargetAction = 'show';
150
+ /**
151
+ * Determines how the popover opens. With `hover`, it also opens when the pointer rests on the trigger and closes
152
+ * when the pointer leaves, until a click on the trigger keeps it open. Enter or Space on the trigger opens it either way.
153
+ * @defaultValue "click"
154
+ */
155
+ this.openOn = 'click';
74
156
  /**
75
157
  * Determines the type of popover. Auto popovers can be "light dismissed" by clicking outside of the popover.
76
158
  * Manual popovers require the consumer to handle the visibility of the popover.
@@ -81,6 +163,11 @@ export class PdsPopover {
81
163
  * @defaultValue 352
82
164
  */
83
165
  this.maxWidth = 352;
166
+ /**
167
+ * Sets the padding of the popover content
168
+ * @defaultValue "md"
169
+ */
170
+ this.padding = 'md';
84
171
  /**
85
172
  * Determines the preferred position of the popover
86
173
  * @defaultValue "right"
@@ -95,6 +182,7 @@ export class PdsPopover {
95
182
  // Clean up previous trigger's event listener if it exists
96
183
  if (this.triggerEl != null) {
97
184
  this.triggerEl.removeEventListener('click', this.handleTriggerClick);
185
+ this.stopListeningForHover(this.triggerEl);
98
186
  }
99
187
  if (assignedElements.length > 0) {
100
188
  // Use the first assigned element as the trigger
@@ -102,10 +190,14 @@ export class PdsPopover {
102
190
  this.linkTriggerToPortal();
103
191
  // Attach click listener to handle popover visibility
104
192
  this.triggerEl.addEventListener('click', this.handleTriggerClick);
193
+ this.listenForHover(this.triggerEl);
105
194
  }
106
195
  else {
107
196
  this.triggerEl = null;
108
197
  }
198
+ // autoUpdate watches the trigger it started with, so an open popover starts it again on the new one.
199
+ if (this.active)
200
+ this.addScrollAndResizeListeners();
109
201
  this.observeTrigger();
110
202
  };
111
203
  /**
@@ -128,6 +220,13 @@ export class PdsPopover {
128
220
  if (!anchorWithHref) {
129
221
  event.preventDefault();
130
222
  }
223
+ if (this.openOn === 'hover' && this.popoverTargetAction !== 'hide') {
224
+ const heldByHover = this.hoverOpened;
225
+ this.pin();
226
+ // Pinning, not toggling: the hover before a click has already opened it.
227
+ if (heldByHover)
228
+ return;
229
+ }
131
230
  // Execute the appropriate action based on popoverTargetAction prop
132
231
  switch (this.popoverTargetAction) {
133
232
  case 'show':
@@ -142,6 +241,60 @@ export class PdsPopover {
142
241
  break;
143
242
  }
144
243
  };
244
+ // A tap sends touch pointer events and then a click, so touch takes the click path alone.
245
+ this.handleHoverEnter = (event) => {
246
+ if (event.pointerType === 'touch')
247
+ return;
248
+ this.clearHoverTimers();
249
+ if (this.active)
250
+ return;
251
+ this.hoverOpenTimer = setTimeout(() => {
252
+ this.hoverOpenTimer = undefined;
253
+ if (this.active || this.portalEl == null)
254
+ return;
255
+ this.hoverOpened = true;
256
+ this.show();
257
+ }, HOVER_OPEN_DELAY_MS);
258
+ };
259
+ this.handleHoverLeave = (event) => {
260
+ if (event.pointerType === 'touch')
261
+ return;
262
+ this.clearHoverTimers();
263
+ if (!this.hoverOpened)
264
+ return;
265
+ this.hoverCloseTimer = setTimeout(this.closeFromHover, HOVER_CLOSE_DELAY_MS);
266
+ if (event.currentTarget !== this.triggerEl)
267
+ return;
268
+ this.panelDistance = this.distanceToPanel(event);
269
+ document.addEventListener('pointermove', this.handleMoveTowardPanel);
270
+ };
271
+ // A slow diagonal from the trigger to a panel shorter than it runs beside the panel for longer
272
+ // than the close delay, so each move that brings the pointer closer starts the delay again.
273
+ this.handleMoveTowardPanel = (event) => {
274
+ const distance = this.distanceToPanel(event);
275
+ if (distance < this.panelDistance) {
276
+ clearTimeout(this.hoverCloseTimer);
277
+ this.hoverCloseTimer = setTimeout(this.closeFromHover, HOVER_CLOSE_DELAY_MS);
278
+ }
279
+ this.panelDistance = distance;
280
+ };
281
+ this.handleHoverFocusOut = (event) => {
282
+ if (!this.closeWhenFocusLeaves || containsComposed(this.portalEl, event.relatedTarget))
283
+ return;
284
+ this.closeWhenFocusLeaves = false;
285
+ this.hoverCloseTimer = setTimeout(this.closeFromHover, HOVER_CLOSE_DELAY_MS);
286
+ };
287
+ this.closeFromHover = () => {
288
+ this.clearHoverTimers();
289
+ if (!this.hoverOpened)
290
+ return;
291
+ // Content shown on hover stays while focus is in it (WCAG 1.4.13).
292
+ if (containsComposed(this.portalEl, deepActiveElement())) {
293
+ this.closeWhenFocusLeaves = true;
294
+ return;
295
+ }
296
+ this.hide();
297
+ };
145
298
  /** The focus style copied into a shadow root the panel opened in, which `document.head` can't reach. */
146
299
  this.shadowFocusStyle = null;
147
300
  /** The dialog the panel was opened in, closed along with it. */
@@ -162,6 +315,85 @@ export class PdsPopover {
162
315
  event.stopPropagation();
163
316
  }
164
317
  };
318
+ // At the end of the body or of a dialog, the panel would come last in the Tab order. The guard
319
+ // after the trigger takes its place there, while the panel has a control for it to lead to.
320
+ this.syncTabGuard = (event) => {
321
+ if (event.key !== 'Tab')
322
+ return;
323
+ this.releasePanel();
324
+ this.tabDirection = event.shiftKey ? 'backward' : 'forward';
325
+ setTimeout(this.endTabKey);
326
+ // Read on each Tab, as the panel's content can arrive after it opens.
327
+ const guarding = this.guardedTabbables().length > 0;
328
+ if (this.tabGuardEl != null)
329
+ this.tabGuardEl.tabIndex = guarding ? 0 : -1;
330
+ // Inert for this key press, the panel is reached only through the guard, either way round. A
331
+ // control in another floating layer, such as a nested popover's panel, may move focus back into it.
332
+ const focused = deepActiveElement();
333
+ if (guarding && !containsComposed(this.portalEl, focused) && !closest(FLOATING_LAYERS, focused !== null && focused !== void 0 ? focused : document)) {
334
+ this.portalEl.inert = true;
335
+ }
336
+ };
337
+ this.endTabKey = () => {
338
+ this.tabDirection = null;
339
+ this.releasePanel();
340
+ };
341
+ this.handleTabGuardFocus = (event) => {
342
+ if (this.leavingPanel)
343
+ return;
344
+ // An inert panel's controls aren't tabbable, so the guard would find none to send focus to.
345
+ this.releasePanel();
346
+ const tabbables = this.guardedTabbables();
347
+ // A Tab press says which end of the panel focus comes in at; without one, where it came from does.
348
+ const from = event.relatedTarget;
349
+ const backward = this.tabDirection != null ? this.tabDirection === 'backward' : from != null && this.isAfterPopover(from);
350
+ const target = backward ? tabbables[tabbables.length - 1] : tabbables[0];
351
+ // Focus can reach the guard without a Tab keydown here (from a frame, or assistive tech) after
352
+ // the panel's controls are gone. The trigger is the nearest visible place for it.
353
+ if (target == null)
354
+ this.returnFocusToTrigger();
355
+ else
356
+ target.focus();
357
+ };
358
+ this.handleTabFromPanel = (event) => {
359
+ if (event.key !== 'Tab' || event.defaultPrevented || this.tabGuardEl == null)
360
+ return;
361
+ const tabbables = this.guardedTabbables();
362
+ const edge = event.shiftKey ? tabbables[0] : tabbables[tabbables.length - 1];
363
+ if (edge == null || deepActiveElement() !== edge)
364
+ return;
365
+ this.leavePanel(edge, event.shiftKey);
366
+ };
367
+ this.releasePanel = () => {
368
+ if (this.portalEl != null)
369
+ this.portalEl.inert = false;
370
+ };
371
+ }
372
+ openOnChanged() {
373
+ this.pin();
374
+ this.stopListeningForHover(this.triggerEl);
375
+ this.stopListeningForHover(this.portalEl);
376
+ // Out of the page, connectedCallback binds them when it comes back.
377
+ if (!this.isComponentMounted)
378
+ return;
379
+ this.listenForHover(this.triggerEl);
380
+ this.listenForHover(this.portalEl);
381
+ }
382
+ applyPadding() {
383
+ if (this.portalEl != null)
384
+ this.portalEl.style.padding = this.paddingToken();
385
+ }
386
+ paddingToken() {
387
+ switch (this.padding) {
388
+ case 'none':
389
+ return 'var(--pine-dimension-none)';
390
+ case 'xs':
391
+ return 'var(--pine-dimension-xs)';
392
+ case 'sm':
393
+ return 'var(--pine-dimension-sm)';
394
+ default:
395
+ return 'var(--pine-dimension-md)';
396
+ }
165
397
  }
166
398
  restorePlacementDefault(newValue) {
167
399
  this.placement = restoreReflectedDefault(this.el, 'placement', newValue, 'right');
@@ -171,8 +403,6 @@ export class PdsPopover {
171
403
  // Bind event handlers for cleanup
172
404
  this.boundClickOutsideHandler = this.handleClickOutside.bind(this);
173
405
  this.boundEscapeKeyHandler = this.handleEscapeKey.bind(this);
174
- this.boundScrollHandler = this.handleScroll.bind(this);
175
- this.boundResizeHandler = this.handleResize.bind(this);
176
406
  // Create portal element
177
407
  this.createPortal();
178
408
  this.hasLoaded = true;
@@ -213,6 +443,48 @@ export class PdsPopover {
213
443
  // Skips values already in place, so the trigger observer's own callback doesn't loop.
214
444
  return setAttributesIfChanged(this.triggerEl, { 'aria-expanded': String(this.active), 'aria-controls': this.portalEl.id });
215
445
  }
446
+ listenForHover(el) {
447
+ if (this.openOn !== 'hover' || el == null)
448
+ return;
449
+ el.addEventListener('pointerenter', this.handleHoverEnter);
450
+ el.addEventListener('pointerleave', this.handleHoverLeave);
451
+ el.addEventListener('focusout', this.handleHoverFocusOut);
452
+ }
453
+ stopListeningForHover(el) {
454
+ if (el == null)
455
+ return;
456
+ el.removeEventListener('pointerenter', this.handleHoverEnter);
457
+ el.removeEventListener('pointerleave', this.handleHoverLeave);
458
+ el.removeEventListener('focusout', this.handleHoverFocusOut);
459
+ }
460
+ distanceToPanel({ clientX, clientY }) {
461
+ const panel = this.portalEl.getBoundingClientRect();
462
+ return Math.hypot(Math.max(panel.left - clientX, 0, clientX - panel.right), Math.max(panel.top - clientY, 0, clientY - panel.bottom));
463
+ }
464
+ /**
465
+ * Keeps a popover that hover opened open, closing from then on as one opened by a click does. A
466
+ * manual one gives up Escape again, which it took only while hover held it.
467
+ */
468
+ pin() {
469
+ var _a;
470
+ this.clearHoverTimers();
471
+ if (!this.hoverOpened)
472
+ return;
473
+ this.hoverOpened = false;
474
+ if (this.popoverType === 'auto')
475
+ return;
476
+ this.forgetOpen();
477
+ (_a = this.portalEl) === null || _a === void 0 ? void 0 : _a.removeAttribute('data-pds-popover-open');
478
+ document.removeEventListener('keydown', this.boundEscapeKeyHandler);
479
+ }
480
+ clearHoverTimers() {
481
+ clearTimeout(this.hoverOpenTimer);
482
+ clearTimeout(this.hoverCloseTimer);
483
+ this.hoverOpenTimer = undefined;
484
+ this.hoverCloseTimer = undefined;
485
+ this.closeWhenFocusLeaves = false;
486
+ document.removeEventListener('pointermove', this.handleMoveTowardPanel);
487
+ }
216
488
  // componentDidLoad doesn't run again when a popover comes back, so rebuild whatever
217
489
  // disconnectedCallback tore down. Each step is a no-op when nothing was.
218
490
  connectedCallback() {
@@ -222,17 +494,19 @@ export class PdsPopover {
222
494
  this.isComponentMounted = true;
223
495
  this.createPortal();
224
496
  (_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.addEventListener('click', this.handleTriggerClick);
497
+ this.listenForHover(this.triggerEl);
225
498
  this.observeTrigger();
226
499
  this.linkTriggerToPortal();
227
500
  // Still open after a move: the trigger moved, so the portal follows it, into the dialog it
228
501
  // is in now, if any.
229
502
  if (this.active) {
230
503
  this.placePortal();
231
- requestAnimationFrame(() => this.handlePopoverPositioning());
504
+ // autoUpdate listens to the scroll containers around where the trigger was, so it starts again.
505
+ this.addScrollAndResizeListeners();
232
506
  }
233
507
  }
234
508
  disconnectedCallback() {
235
- var _a;
509
+ var _a, _b;
236
510
  // Moved in one operation (a DOM morph, or a framework reparenting it), the popover is
237
511
  // already back in the page. Its portal is outside the popover, so it stays open, with focus
238
512
  // where it was; connectedCallback moves it to follow the popover.
@@ -247,6 +521,7 @@ export class PdsPopover {
247
521
  this.restorePortalContent();
248
522
  this.active = false;
249
523
  this.linkTriggerToPortal();
524
+ this.emitOpenEvent();
250
525
  this.pdsPopoverClose.emit({
251
526
  componentId: this.componentId,
252
527
  popoverType: this.popoverType,
@@ -256,36 +531,27 @@ export class PdsPopover {
256
531
  if (this.triggerEl != null) {
257
532
  this.triggerEl.removeEventListener('click', this.handleTriggerClick);
258
533
  }
534
+ this.stopListeningForHover(this.triggerEl);
259
535
  (_a = this.triggerObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
260
536
  this.triggerObserver = null;
261
537
  // Clean up all event listeners
262
538
  this.removeLightDismissListeners();
263
539
  this.removeScrollAndResizeListeners();
264
540
  document.removeEventListener('submit', this.handleSubmitFromPanel, true);
265
- // Clear any pending debounce timers
266
- this.clearDebounceTimers();
541
+ document.removeEventListener('keydown', this.syncTabGuard, true);
542
+ (_b = this.tabGuardEl) === null || _b === void 0 ? void 0 : _b.removeAttribute('tabindex');
543
+ this.clearHoverTimers();
544
+ this.hoverOpened = false;
267
545
  // Remove portal from DOM
268
546
  this.removePortal();
269
547
  }
270
- /**
271
- * Clears any pending debounce timers
272
- */
273
- clearDebounceTimers() {
274
- if (this.scrollDebounceTimer !== null) {
275
- clearTimeout(this.scrollDebounceTimer);
276
- this.scrollDebounceTimer = null;
277
- }
278
- if (this.resizeDebounceTimer !== null) {
279
- clearTimeout(this.resizeDebounceTimer);
280
- this.resizeDebounceTimer = null;
281
- }
282
- }
283
548
  createPortal() {
284
549
  var _a;
285
550
  if (this.portalEl !== null)
286
551
  return;
287
552
  this.portalEl = document.createElement('div');
288
553
  this.portalEl.className = 'pds-popover';
554
+ panelOwners.set(this.portalEl, this);
289
555
  // Apply all styles inline since portal is outside shadow DOM
290
556
  this.portalEl.style.position = 'fixed';
291
557
  this.portalEl.style.zIndex = 'var(--pine-z-index-raised)';
@@ -297,7 +563,7 @@ export class PdsPopover {
297
563
  this.portalEl.style.borderRadius = 'var(--pine-dimension-125)';
298
564
  this.portalEl.style.boxShadow = 'var(--pine-box-shadow-200)';
299
565
  this.portalEl.style.margin = 'var(--pine-dimension-none)';
300
- this.portalEl.style.padding = 'var(--pine-dimension-md)';
566
+ this.portalEl.style.padding = this.paddingToken();
301
567
  // Generate unique ID
302
568
  if (!this.componentId) {
303
569
  (_a = this.generatedPortalId) !== null && _a !== void 0 ? _a : (this.generatedPortalId = `pds-popover-portal-${PdsPopover.instanceCounter++}`);
@@ -311,6 +577,8 @@ export class PdsPopover {
311
577
  // Add global focus styles to match Pine design system
312
578
  // This is done after appending to ensure it's part of the document and can access CSS variables
313
579
  this.addPortalFocusStyles();
580
+ this.listenForHover(this.portalEl);
581
+ this.portalEl.addEventListener('keydown', this.handleTabFromPanel);
314
582
  }
315
583
  /**
316
584
  * Adds Pine design system focus styles and dark mode border to the portal element
@@ -438,27 +706,40 @@ export class PdsPopover {
438
706
  // Update portal content with latest slot content
439
707
  this.updatePortalContent();
440
708
  // Show portal. The attribute tells a modal around it that this popover takes Escape first; only
441
- // an auto popover listens for Escape.
442
- if (this.popoverType === 'auto')
709
+ // an auto popover, or one hover opened, listens for Escape.
710
+ if (this.popoverType === 'auto' || this.hoverOpened)
443
711
  this.portalEl.setAttribute('data-pds-popover-open', '');
444
712
  this.portalEl.style.display = 'block';
445
713
  this.portalEl.style.opacity = '1';
446
714
  this.portalEl.style.visibility = 'visible';
447
- // Position the popover
448
- requestAnimationFrame(() => {
449
- if (!this.isComponentMounted)
450
- return;
451
- this.handlePopoverPositioning();
452
- });
453
- // Add scroll and resize listeners for repositioning (always)
715
+ // Position the popover now, and again whenever its trigger or the page moves or resizes
454
716
  this.addScrollAndResizeListeners();
455
717
  document.addEventListener('submit', this.handleSubmitFromPanel, true);
456
- // Add document listeners for light dismiss and escape key (auto type only)
718
+ document.addEventListener('keydown', this.syncTabGuard, true);
719
+ // Add document listeners for light dismiss and escape key (auto type only), or for the escape
720
+ // key alone while hover holds a manual popover open
457
721
  if (this.popoverType === 'auto') {
458
- openAutoPopovers.push(this);
722
+ popoversTakingEscape.push(this);
459
723
  this.addLightDismissListeners();
460
724
  }
461
- // Emit open event
725
+ else if (this.hoverOpened) {
726
+ popoversTakingEscape.push(this);
727
+ document.addEventListener('keydown', this.boundEscapeKeyHandler);
728
+ }
729
+ // Emit open event once the panel is positioned, with the side it took already on it. A reconnect, a
730
+ // trigger swap or another show() can start a newer run meanwhile, which drops this one, so wait for the latest.
731
+ this.openEventPending = true;
732
+ let positioning;
733
+ do {
734
+ positioning = this.positioning;
735
+ await positioning;
736
+ } while (positioning !== this.positioning);
737
+ this.emitOpenEvent();
738
+ }
739
+ emitOpenEvent() {
740
+ if (!this.openEventPending)
741
+ return;
742
+ this.openEventPending = false;
462
743
  this.pdsPopoverOpen.emit({
463
744
  componentId: this.componentId,
464
745
  popoverType: this.popoverType,
@@ -468,9 +749,12 @@ export class PdsPopover {
468
749
  * Closes the popover programmatically
469
750
  */
470
751
  async hide() {
752
+ var _a;
753
+ this.clearHoverTimers();
471
754
  if (!this.active || !this.portalEl)
472
755
  return;
473
756
  this.active = false;
757
+ this.hoverOpened = false;
474
758
  this.unwatchDialogClose();
475
759
  // Restoring the content drops its focus to the body, so check where focus is first. In a
476
760
  // shadow root, document.activeElement is only its host.
@@ -481,6 +765,7 @@ export class PdsPopover {
481
765
  // Hide portal. The dark-mode border set in a shadow root is worked out again on the next open.
482
766
  this.portalEl.style.border = '';
483
767
  this.portalEl.removeAttribute('data-pds-popover-open');
768
+ this.portalEl.removeAttribute('data-pds-popover-placement');
484
769
  this.portalEl.style.display = 'none';
485
770
  this.portalEl.style.opacity = '0';
486
771
  this.portalEl.style.visibility = 'hidden';
@@ -494,8 +779,11 @@ export class PdsPopover {
494
779
  this.removeLightDismissListeners();
495
780
  this.removeScrollAndResizeListeners();
496
781
  document.removeEventListener('submit', this.handleSubmitFromPanel, true);
497
- // Clear any pending timers
498
- this.clearDebounceTimers();
782
+ document.removeEventListener('keydown', this.syncTabGuard, true);
783
+ (_a = this.tabGuardEl) === null || _a === void 0 ? void 0 : _a.removeAttribute('tabindex');
784
+ this.releasePanel();
785
+ // Closed before its first position resolved, it still announces the open before the close.
786
+ this.emitOpenEvent();
499
787
  // Emit close event
500
788
  this.pdsPopoverClose.emit({
501
789
  componentId: this.componentId,
@@ -507,10 +795,10 @@ export class PdsPopover {
507
795
  */
508
796
  async toggle() {
509
797
  if (this.active) {
510
- this.hide();
798
+ await this.hide();
511
799
  }
512
800
  else {
513
- this.show();
801
+ await this.show();
514
802
  }
515
803
  }
516
804
  /**
@@ -549,9 +837,9 @@ export class PdsPopover {
549
837
  this.portalEl.style.border = root instanceof ShadowRoot && closest('[data-theme="dark"]', this.el) ? 'var(--pine-border)' : '';
550
838
  }
551
839
  forgetOpen() {
552
- const index = openAutoPopovers.indexOf(this);
840
+ const index = popoversTakingEscape.indexOf(this);
553
841
  if (index >= 0)
554
- openAutoPopovers.splice(index, 1);
842
+ popoversTakingEscape.splice(index, 1);
555
843
  }
556
844
  /**
557
845
  * Whether an Escape is this popover's. One from a dialog the popover isn't in belongs to that
@@ -594,19 +882,62 @@ export class PdsPopover {
594
882
  document.removeEventListener('click', this.boundClickOutsideHandler, true);
595
883
  document.removeEventListener('keydown', this.boundEscapeKeyHandler);
596
884
  }
885
+ /**
886
+ * The panel's controls that Tab reaches through the guard. None when the panel sits right after
887
+ * the popover, in a dialog, where it's already next in the Tab order.
888
+ */
889
+ guardedTabbables() {
890
+ if (this.portalEl == null || this.el.nextElementSibling === this.portalEl)
891
+ return [];
892
+ return tabbableIn(this.portalEl);
893
+ }
894
+ isAfterPopover(node) {
895
+ if (containsComposed(this.el, node))
896
+ return false;
897
+ return isPosition(positionAcrossTrees(this.el, node), Node.DOCUMENT_POSITION_FOLLOWING);
898
+ }
899
+ /**
900
+ * Moves focus to the guard without preventing the Tab, so the browser's Tab carries on from there.
901
+ * Inert until then, the panel can't be where it lands.
902
+ */
903
+ leavePanel(edge, backward) {
904
+ var _a, _b;
905
+ this.leavingPanel = true;
906
+ (_a = this.tabGuardEl) === null || _a === void 0 ? void 0 : _a.focus();
907
+ this.leavingPanel = false;
908
+ this.portalEl.inert = true;
909
+ setTimeout(() => this.finishLeavingPanel(edge));
910
+ // Last in another popover's panel, the guard hands the Tab on to that popover's own guard.
911
+ const outer = panelOwners.get(closest('.pds-popover', this.el));
912
+ const outerTabbables = (_b = outer === null || outer === void 0 ? void 0 : outer.guardedTabbables()) !== null && _b !== void 0 ? _b : [];
913
+ if (!backward && outerTabbables[outerTabbables.length - 1] === this.tabGuardEl)
914
+ outer.leavePanel(edge, false);
915
+ }
916
+ // With nowhere for the browser's Tab to go, focus would stay on the invisible guard.
917
+ finishLeavingPanel(edge) {
918
+ var _a;
919
+ this.releasePanel();
920
+ if (this.active && ((_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.activeElement) === this.tabGuardEl)
921
+ edge.focus();
922
+ }
597
923
  /**
598
924
  * Adds scroll and resize listeners for repositioning
599
925
  */
600
926
  addScrollAndResizeListeners() {
601
- window.addEventListener('scroll', this.boundScrollHandler, true);
602
- window.addEventListener('resize', this.boundResizeHandler);
927
+ this.removeScrollAndResizeListeners();
928
+ if (this.triggerEl == null || this.portalEl == null)
929
+ return;
930
+ this.stopAutoUpdate = autoUpdate(this.triggerEl, this.portalEl, () => {
931
+ this.positioning = this.handlePopoverPositioning().catch(error => console.warn('pds-popover: failed to position the panel', error));
932
+ });
603
933
  }
604
934
  /**
605
935
  * Removes scroll and resize listeners
606
936
  */
607
937
  removeScrollAndResizeListeners() {
608
- window.removeEventListener('scroll', this.boundScrollHandler, true);
609
- window.removeEventListener('resize', this.boundResizeHandler);
938
+ var _a;
939
+ (_a = this.stopAutoUpdate) === null || _a === void 0 ? void 0 : _a.call(this);
940
+ this.stopAutoUpdate = null;
610
941
  }
611
942
  /**
612
943
  * Handles clicks outside the popover for light dismiss (auto type only)
@@ -660,7 +991,7 @@ export class PdsPopover {
660
991
  return;
661
992
  // Like the native Popover API, Escape closes only the top popover: the last one opened that
662
993
  // it applies to. Every open popover hears it, so each checks whether it's that one.
663
- const top = [...openAutoPopovers].reverse().find(popover => popover.takesEscapeFrom(event));
994
+ const top = [...popoversTakingEscape].reverse().find(popover => popover.takesEscapeFrom(event));
664
995
  if (top !== this)
665
996
  return;
666
997
  // Take the key, so the dialog or modal around it doesn't close too.
@@ -670,122 +1001,38 @@ export class PdsPopover {
670
1001
  this.hide();
671
1002
  }
672
1003
  /**
673
- * Handles scroll events to reposition the popover (debounced for performance)
1004
+ * Positions the popover relative to its trigger element, flipping to the opposite side when only that side has
1005
+ * room and shifting to stay 8px inside the viewport. The side it takes goes on the panel's `data-pds-popover-placement`.
674
1006
  */
675
- handleScroll() {
676
- if (!this.active)
677
- return;
678
- if (this.scrollDebounceTimer !== null) {
679
- clearTimeout(this.scrollDebounceTimer);
680
- }
681
- this.scrollDebounceTimer = setTimeout(() => {
682
- this.handlePopoverPositioning();
683
- this.scrollDebounceTimer = null;
684
- }, 10); // 10ms debounce for smooth repositioning
685
- }
686
- /**
687
- * Handles resize events to reposition the popover (debounced for performance)
688
- */
689
- handleResize() {
690
- if (!this.active)
691
- return;
692
- if (this.resizeDebounceTimer !== null) {
693
- clearTimeout(this.resizeDebounceTimer);
694
- }
695
- this.resizeDebounceTimer = setTimeout(() => {
696
- this.handlePopoverPositioning();
697
- this.resizeDebounceTimer = null;
698
- }, 100); // 100ms debounce for resize
699
- }
700
- /**
701
- * Positions the popover relative to its trigger element
702
- */
703
- handlePopoverPositioning() {
704
- // Prevent repositioning loops
705
- if (this.isRepositioning) {
706
- return;
707
- }
708
- this.isRepositioning = true;
709
- if (this.triggerEl == null || this.portalEl == null) {
710
- this.isRepositioning = false;
1007
+ async handlePopoverPositioning() {
1008
+ // Counted before the guards, so a run still in flight is dropped even when this one can't position.
1009
+ const run = ++this.positioningRun;
1010
+ if (this.triggerEl == null || this.portalEl == null)
711
1011
  return;
712
- }
713
- const triggerRect = this.triggerEl.getBoundingClientRect();
714
- const popoverRect = this.portalEl.getBoundingClientRect();
715
1012
  // Safety check: ensure trigger has valid dimensions (is rendered and visible)
716
- if (triggerRect.width === 0 || triggerRect.height === 0) {
717
- this.isRepositioning = false;
1013
+ const triggerRect = this.triggerEl.getBoundingClientRect();
1014
+ if (triggerRect.width === 0 || triggerRect.height === 0)
718
1015
  return;
719
- }
720
- let top = 0;
721
- let left = 0;
722
- const offset = 8;
723
- switch (this.placement) {
724
- case 'top':
725
- top = triggerRect.top - popoverRect.height - offset;
726
- left = triggerRect.left + (triggerRect.width - popoverRect.width) / 2;
727
- break;
728
- case 'top-start':
729
- top = triggerRect.top - popoverRect.height - offset;
730
- left = triggerRect.left;
731
- break;
732
- case 'top-end':
733
- top = triggerRect.top - popoverRect.height - offset;
734
- left = triggerRect.right - popoverRect.width;
735
- break;
736
- case 'right':
737
- top = triggerRect.top + (triggerRect.height - popoverRect.height) / 2;
738
- left = triggerRect.right + offset;
739
- break;
740
- case 'right-start':
741
- top = triggerRect.top;
742
- left = triggerRect.right + offset;
743
- break;
744
- case 'right-end':
745
- top = triggerRect.bottom - popoverRect.height;
746
- left = triggerRect.right + offset;
747
- break;
748
- case 'bottom':
749
- top = triggerRect.bottom + offset;
750
- left = triggerRect.left + (triggerRect.width - popoverRect.width) / 2;
751
- break;
752
- case 'bottom-start':
753
- top = triggerRect.bottom + offset;
754
- left = triggerRect.left;
755
- break;
756
- case 'bottom-end':
757
- top = triggerRect.bottom + offset;
758
- left = triggerRect.right - popoverRect.width;
759
- break;
760
- case 'left':
761
- top = triggerRect.top + (triggerRect.height - popoverRect.height) / 2;
762
- left = triggerRect.left - popoverRect.width - offset;
763
- break;
764
- case 'left-start':
765
- top = triggerRect.top;
766
- left = triggerRect.left - popoverRect.width - offset;
767
- break;
768
- case 'left-end':
769
- top = triggerRect.bottom - popoverRect.height;
770
- left = triggerRect.left - popoverRect.width - offset;
771
- break;
772
- }
773
- this.portalEl.style.top = `${top}px`;
774
- this.portalEl.style.left = `${left}px`;
1016
+ const portal = this.portalEl;
1017
+ const { x: left, y: top, placement } = await computePosition(this.triggerEl, portal, {
1018
+ placement: this.placement,
1019
+ strategy: 'fixed',
1020
+ // With no room on either side, stay on the preferred side: the side that overflows less can still push
1021
+ // a tall panel's start above the viewport.
1022
+ middleware: [offset(8), flip({ fallbackStrategy: 'initialPlacement' }), shift({ padding: 8 })],
1023
+ platform: viewportPlatform,
1024
+ });
1025
+ if (!this.active || run !== this.positioningRun || portal !== this.portalEl)
1026
+ return;
1027
+ portal.setAttribute('data-pds-popover-placement', placement);
775
1028
  // `position: fixed` measures from the viewport unless an ancestor becomes its containing block,
776
- // as a modal dialog does with its backdrop filter. Shift by however far it landed from the spot.
777
- const placed = this.portalEl.getBoundingClientRect();
778
- if (Math.abs(placed.top - top) > 0.5 || Math.abs(placed.left - left) > 0.5) {
779
- this.portalEl.style.top = `${2 * top - placed.top}px`;
780
- this.portalEl.style.left = `${2 * left - placed.left}px`;
781
- }
782
- // Reset the repositioning guard after a short delay
783
- setTimeout(() => {
784
- this.isRepositioning = false;
785
- }, 16); // ~1 frame at 60fps
1029
+ // as a modal dialog does with its backdrop filter. Offset by however far that block's corner is from the viewport's.
1030
+ const origin = containingBlockOrigin(portal);
1031
+ portal.style.top = `${top - origin.top}px`;
1032
+ portal.style.left = `${left - origin.left}px`;
786
1033
  }
787
1034
  render() {
788
- return (h(Host, { key: 'da8a0c715df1199231b1265085f3f9ae0234032d', id: this.componentId }, h("span", { key: 'f35023492399420829cec2e88556462f5ac1663e', class: "pds-popover__trigger-wrapper" }, h("slot", { key: '38ebe92eebb87665467b3f92ff94dc8095450063', name: "trigger", onSlotchange: this.handleTriggerSlotChange })), h("div", { key: '8917930f4520544d14bbd68b4c7936dd60af19e3', class: "pds-popover__content-slot-wrapper" }, h("slot", { key: '28d3f9112256edd95721a79a7072a9e35a3712bf', onSlotchange: this.handleContentSlotChange }))));
1035
+ return (h(Host, { key: '85422eb7544a4795ce78b51684b7224a5d856a4e', id: this.componentId }, h("span", { key: '6fe9c827ed4d46ca723d6013f296faf80ba31366', class: "pds-popover__trigger-wrapper" }, h("slot", { key: '970d1974d2be1451e670a36e7d2ccdc5979595bb', name: "trigger", onSlotchange: this.handleTriggerSlotChange })), h("span", { key: '0c76f76286a30d8e6e948bd0abab3317b3673aa6', class: "pds-popover__tab-guard", ref: (el) => (this.tabGuardEl = el !== null && el !== void 0 ? el : null), onFocus: this.handleTabGuardFocus }), h("div", { key: '692c45e93899e74a3d5970f3a3625f6115ab63b0', class: "pds-popover__content-slot-wrapper" }, h("slot", { key: 'f1566e0eb1eb08626f2a8285447702ce96b09f4d', onSlotchange: this.handleContentSlotChange }))));
789
1036
  }
790
1037
  static get is() { return "pds-popover"; }
791
1038
  static get encapsulation() { return "shadow"; }
@@ -824,6 +1071,29 @@ export class PdsPopover {
824
1071
  "attribute": "popover-target-action",
825
1072
  "defaultValue": "'show'"
826
1073
  },
1074
+ "openOn": {
1075
+ "type": "string",
1076
+ "mutable": false,
1077
+ "complexType": {
1078
+ "original": "'click' | 'hover'",
1079
+ "resolved": "\"click\" | \"hover\"",
1080
+ "references": {}
1081
+ },
1082
+ "required": false,
1083
+ "optional": true,
1084
+ "docs": {
1085
+ "tags": [{
1086
+ "name": "defaultValue",
1087
+ "text": "\"click\""
1088
+ }],
1089
+ "text": "Determines how the popover opens. With `hover`, it also opens when the pointer rests on the trigger and closes\nwhen the pointer leaves, until a click on the trigger keeps it open. Enter or Space on the trigger opens it either way."
1090
+ },
1091
+ "getter": false,
1092
+ "setter": false,
1093
+ "reflect": false,
1094
+ "attribute": "open-on",
1095
+ "defaultValue": "'click'"
1096
+ },
827
1097
  "popoverType": {
828
1098
  "type": "string",
829
1099
  "mutable": false,
@@ -886,6 +1156,36 @@ export class PdsPopover {
886
1156
  "attribute": "max-width",
887
1157
  "defaultValue": "352"
888
1158
  },
1159
+ "padding": {
1160
+ "type": "string",
1161
+ "mutable": false,
1162
+ "complexType": {
1163
+ "original": "PopoverPaddingType",
1164
+ "resolved": "\"md\" | \"none\" | \"sm\" | \"xs\"",
1165
+ "references": {
1166
+ "PopoverPaddingType": {
1167
+ "location": "import",
1168
+ "path": "@utils/types",
1169
+ "id": "src/utils/types.ts::PopoverPaddingType",
1170
+ "referenceLocation": "PopoverPaddingType"
1171
+ }
1172
+ }
1173
+ },
1174
+ "required": false,
1175
+ "optional": true,
1176
+ "docs": {
1177
+ "tags": [{
1178
+ "name": "defaultValue",
1179
+ "text": "\"md\""
1180
+ }],
1181
+ "text": "Sets the padding of the popover content"
1182
+ },
1183
+ "getter": false,
1184
+ "setter": false,
1185
+ "reflect": false,
1186
+ "attribute": "padding",
1187
+ "defaultValue": "'md'"
1188
+ },
889
1189
  "placement": {
890
1190
  "type": "string",
891
1191
  "mutable": true,
@@ -1028,6 +1328,12 @@ export class PdsPopover {
1028
1328
  static get elementRef() { return "el"; }
1029
1329
  static get watchers() {
1030
1330
  return [{
1331
+ "propName": "openOn",
1332
+ "methodName": "openOnChanged"
1333
+ }, {
1334
+ "propName": "padding",
1335
+ "methodName": "applyPadding"
1336
+ }, {
1031
1337
  "propName": "placement",
1032
1338
  "methodName": "restorePlacementDefault"
1033
1339
  }];