playbook_ui 16.9.0 → 16.10.0.pre.alpha.PLAY3053advancedtablebottompinnedrowsreact17469

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 (375) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +32 -11
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +5 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +27 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +19 -14
  7. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +4 -2
  8. data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +17 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/Utilities/StickyLayoutHelper.ts +100 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +38 -71
  11. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +27 -77
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +7 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +128 -12
  14. data/app/pb_kits/playbook/pb_advanced_table/advanced_table_action_bar.js +31 -9
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +19 -2
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +2 -2
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.html.erb +4 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.jsx +6 -2
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling_rails.md +1 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling_react.md +1 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +36 -44
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +10 -19
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +0 -4
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +3 -5
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +2 -8
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.overrides.json +1 -8
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +0 -1
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +0 -1
  29. data/app/pb_kits/playbook/pb_advanced_table/index.js +20 -29
  30. data/app/pb_kits/playbook/pb_advanced_table/kit.schema.json +0 -12
  31. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +1 -1
  32. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +2 -1
  33. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +16 -2
  34. data/app/pb_kits/playbook/pb_badge/kit.schema.json +1 -1
  35. data/app/pb_kits/playbook/pb_button_toolbar/kit.schema.json +1 -1
  36. data/app/pb_kits/playbook/pb_card/card.rb +1 -1
  37. data/app/pb_kits/playbook/pb_card/kit.schema.json +2 -0
  38. data/app/pb_kits/playbook/pb_checkbox/kit.schema.json +2 -2
  39. data/app/pb_kits/playbook/pb_circle_icon_button/kit.schema.json +2 -2
  40. data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +6 -0
  41. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +19 -2
  42. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +58 -1
  43. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +3 -0
  44. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +319 -65
  45. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_year_asc.html.erb +1 -0
  46. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_year_asc.jsx +15 -0
  47. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_year_asc.md +1 -0
  48. data/app/pb_kits/playbook/pb_date_picker/docs/_playground.json +1 -0
  49. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  50. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +1 -0
  51. data/app/pb_kits/playbook/pb_date_picker/kit.schema.json +9 -1
  52. data/app/pb_kits/playbook/pb_date_time/kit.schema.json +1 -1
  53. data/app/pb_kits/playbook/pb_date_time_stacked/kit.schema.json +1 -1
  54. data/app/pb_kits/playbook/pb_dialog/_dialog.scss +54 -1
  55. data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +21 -5
  56. data/app/pb_kits/playbook/pb_dialog/_dialog_context.tsx +8 -2
  57. data/app/pb_kits/playbook/pb_dialog/child_kits/_dialog_header.tsx +1 -1
  58. data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +5 -1
  59. data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +125 -0
  60. data/app/pb_kits/playbook/pb_dialog/index.js +11 -1
  61. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +1 -1
  62. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners_rails.md +1 -1
  63. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_independent_containers.html.erb +35 -0
  64. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_independent_containers_rails.md +8 -0
  65. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_rails.md +3 -1
  66. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_react.md +1 -1
  67. data/app/pb_kits/playbook/pb_draggable/docs/_playground.json +260 -19
  68. data/app/pb_kits/playbook/pb_draggable/docs/_playground.overrides.json +258 -13
  69. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -0
  70. data/app/pb_kits/playbook/pb_draggable/index.js +10 -3
  71. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +122 -0
  72. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +114 -35
  73. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_display_disabled_option.html.erb +93 -0
  74. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_display_disabled_option.jsx +127 -0
  75. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_display_disabled_option.md +1 -0
  76. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_disabled.html.erb +10 -0
  77. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_disabled.jsx +37 -0
  78. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_disabled_option.html.erb +10 -0
  79. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_disabled_option.jsx +37 -0
  80. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_disabled_option.md +1 -0
  81. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.json +150 -237
  82. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.overrides.json +58 -74
  83. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +6 -0
  84. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +3 -0
  85. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +5 -4
  86. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +6 -1
  87. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +96 -0
  88. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +1 -0
  89. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +2 -0
  90. data/app/pb_kits/playbook/pb_dropdown/dropdown_option.html.erb +2 -2
  91. data/app/pb_kits/playbook/pb_dropdown/dropdown_option.rb +27 -2
  92. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +4 -2
  93. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +2 -0
  94. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +25 -5
  95. data/app/pb_kits/playbook/pb_dropdown/index.js +270 -25
  96. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +19 -10
  97. data/app/pb_kits/playbook/pb_dropdown/kit.schema.json +8 -0
  98. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +39 -2
  99. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +15 -4
  100. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +22 -13
  101. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_remove_replace.html.erb +66 -0
  102. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_remove_replace.jsx +53 -0
  103. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_remove_replace.md +5 -0
  104. data/app/pb_kits/playbook/pb_file_upload/docs/_playground.json +2 -1
  105. data/app/pb_kits/playbook/pb_file_upload/docs/example.yml +3 -1
  106. data/app/pb_kits/playbook/pb_file_upload/docs/index.js +1 -0
  107. data/app/pb_kits/playbook/pb_file_upload/kit.schema.json +3 -3
  108. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +55 -28
  109. data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.tsx +4 -1
  110. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +4 -1
  111. data/app/pb_kits/playbook/pb_filter/Filter/InteractiveFilter.tsx +277 -0
  112. data/app/pb_kits/playbook/pb_filter/_filter.scss +88 -1
  113. data/app/pb_kits/playbook/pb_filter/_filter.tsx +27 -0
  114. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive.html.erb +116 -0
  115. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive.md +12 -0
  116. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.jsx +153 -0
  117. data/app/pb_kits/playbook/pb_filter/docs/_filter_interactive_react.md +10 -0
  118. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_background.html.erb +1 -1
  119. data/app/pb_kits/playbook/pb_filter/docs/_playground.json +308 -5
  120. data/app/pb_kits/playbook/pb_filter/docs/_playground.overrides.json +312 -0
  121. data/app/pb_kits/playbook/pb_filter/docs/example.yml +2 -0
  122. data/app/pb_kits/playbook/pb_filter/docs/index.js +2 -1
  123. data/app/pb_kits/playbook/pb_filter/filter.html.erb +80 -3
  124. data/app/pb_kits/playbook/pb_filter/filter.rb +71 -0
  125. data/app/pb_kits/playbook/pb_filter/filter.test.js +78 -0
  126. data/app/pb_kits/playbook/pb_filter/index.ts +349 -0
  127. data/app/pb_kits/playbook/pb_filter/kit.schema.json +94 -29
  128. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_playground.json +210 -14
  129. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_playground.overrides.json +231 -0
  130. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/kit.schema.json +1 -1
  131. data/app/pb_kits/playbook/pb_flex/docs/_playground.json +297 -38
  132. data/app/pb_kits/playbook/pb_flex/docs/_playground.overrides.json +300 -40
  133. data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.html.erb +20 -19
  134. data/app/pb_kits/playbook/pb_form/docs/_playground.json +1 -13
  135. data/app/pb_kits/playbook/pb_form_group/docs/_playground.json +82 -5
  136. data/app/pb_kits/playbook/pb_form_group/docs/_playground.overrides.json +91 -0
  137. data/app/pb_kits/playbook/pb_form_pill/docs/_playground.json +155 -14
  138. data/app/pb_kits/playbook/pb_form_pill/docs/_playground.overrides.json +147 -0
  139. data/app/pb_kits/playbook/pb_form_pill/kit.schema.json +1 -1
  140. data/app/pb_kits/playbook/pb_full_screen/_full_screen.scss +77 -0
  141. data/app/pb_kits/playbook/pb_full_screen/_full_screen.tsx +183 -0
  142. data/app/pb_kits/playbook/pb_full_screen/docs/_description.md +1 -0
  143. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_content_padding.jsx +68 -0
  144. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_content_padding.md +1 -0
  145. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_custom_trigger.jsx +71 -0
  146. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_custom_trigger.md +1 -0
  147. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_default.html.erb +3 -0
  148. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_default.jsx +63 -0
  149. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_default.md +1 -0
  150. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_header_text_styling.jsx +68 -0
  151. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_header_text_styling.md +1 -0
  152. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_sticky_header.jsx +68 -0
  153. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_sticky_header.md +1 -0
  154. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_table_and_filter.jsx +149 -0
  155. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_table_and_filter.md +1 -0
  156. data/app/pb_kits/playbook/pb_full_screen/docs/_playground.json +155 -0
  157. data/app/pb_kits/playbook/pb_full_screen/docs/_playground.overrides.json +137 -0
  158. data/app/pb_kits/playbook/pb_full_screen/docs/example.yml +14 -0
  159. data/app/pb_kits/playbook/pb_full_screen/docs/index.js +6 -0
  160. data/app/pb_kits/playbook/pb_full_screen/full_screen.html.erb +12 -0
  161. data/app/pb_kits/playbook/pb_full_screen/full_screen.rb +11 -0
  162. data/app/pb_kits/playbook/pb_full_screen/full_screen.test.jsx +237 -0
  163. data/app/pb_kits/playbook/pb_full_screen/kit.schema.json +89 -0
  164. data/app/pb_kits/playbook/pb_full_screen/useFullScreen.ts +15 -0
  165. data/app/pb_kits/playbook/pb_hashtag/docs/_playground.json +72 -11
  166. data/app/pb_kits/playbook/pb_hashtag/docs/_playground.overrides.json +75 -0
  167. data/app/pb_kits/playbook/pb_highlight/docs/_playground.json +75 -4
  168. data/app/pb_kits/playbook/pb_highlight/docs/_playground.overrides.json +75 -0
  169. data/app/pb_kits/playbook/pb_home_address_street/docs/_playground.json +138 -12
  170. data/app/pb_kits/playbook/pb_home_address_street/docs/_playground.overrides.json +162 -0
  171. data/app/pb_kits/playbook/pb_icon/_icon.tsx +22 -11
  172. data/app/pb_kits/playbook/pb_icon/docs/_icon_default.jsx +1 -1
  173. data/app/pb_kits/playbook/pb_icon/docs/_playground.json +66 -41
  174. data/app/pb_kits/playbook/pb_icon/docs/_playground.overrides.json +85 -27
  175. data/app/pb_kits/playbook/pb_icon/icon.rb +5 -2
  176. data/app/pb_kits/playbook/pb_icon/kit.schema.json +3 -5
  177. data/app/pb_kits/playbook/pb_icon_button/docs/_playground.json +111 -9
  178. data/app/pb_kits/playbook/pb_icon_button/docs/_playground.overrides.json +131 -0
  179. data/app/pb_kits/playbook/pb_icon_button/kit.schema.json +1 -1
  180. data/app/pb_kits/playbook/pb_icon_circle/docs/_playground.json +92 -7
  181. data/app/pb_kits/playbook/pb_icon_circle/docs/_playground.overrides.json +108 -0
  182. data/app/pb_kits/playbook/pb_icon_stat_value/docs/_playground.json +32 -17
  183. data/app/pb_kits/playbook/pb_icon_stat_value/docs/_playground.overrides.json +81 -8
  184. data/app/pb_kits/playbook/pb_icon_value/docs/_playground.json +28 -18
  185. data/app/pb_kits/playbook/pb_icon_value/docs/_playground.overrides.json +58 -9
  186. data/app/pb_kits/playbook/pb_image/docs/_playground.json +124 -47
  187. data/app/pb_kits/playbook/pb_image/docs/_playground.overrides.json +122 -47
  188. data/app/pb_kits/playbook/pb_label_pill/docs/_playground.json +68 -6
  189. data/app/pb_kits/playbook/pb_label_pill/docs/_playground.overrides.json +85 -0
  190. data/app/pb_kits/playbook/pb_label_value/docs/_playground.json +59 -36
  191. data/app/pb_kits/playbook/pb_label_value/docs/_playground.overrides.json +101 -30
  192. data/app/pb_kits/playbook/pb_layout/docs/_playground.json +216 -10
  193. data/app/pb_kits/playbook/pb_layout/docs/_playground.overrides.json +188 -0
  194. data/app/pb_kits/playbook/pb_legend/docs/_playground.json +60 -7
  195. data/app/pb_kits/playbook/pb_legend/docs/_playground.overrides.json +77 -0
  196. data/app/pb_kits/playbook/pb_list/docs/_playground.json +165 -17
  197. data/app/pb_kits/playbook/pb_list/docs/_playground.overrides.json +191 -0
  198. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx +3 -1
  199. data/app/pb_kits/playbook/pb_loading_inline/docs/_loading_inline_color.html.erb +21 -0
  200. data/app/pb_kits/playbook/pb_loading_inline/docs/_loading_inline_color.jsx +55 -0
  201. data/app/pb_kits/playbook/pb_loading_inline/docs/_loading_inline_color.md +1 -0
  202. data/app/pb_kits/playbook/pb_loading_inline/docs/_playground.json +28 -1
  203. data/app/pb_kits/playbook/pb_loading_inline/docs/_playground.overrides.json +27 -1
  204. data/app/pb_kits/playbook/pb_loading_inline/docs/example.yml +2 -0
  205. data/app/pb_kits/playbook/pb_loading_inline/docs/index.js +1 -0
  206. data/app/pb_kits/playbook/pb_loading_inline/kit.schema.json +18 -2
  207. data/app/pb_kits/playbook/pb_loading_inline/loading_inline.html.erb +1 -1
  208. data/app/pb_kits/playbook/pb_loading_inline/loading_inline.rb +3 -0
  209. data/app/pb_kits/playbook/pb_map/docs/_playground.json +164 -7
  210. data/app/pb_kits/playbook/pb_map/docs/_playground.overrides.json +180 -0
  211. data/app/pb_kits/playbook/pb_message/docs/_playground.json +114 -8
  212. data/app/pb_kits/playbook/pb_message/docs/_playground.overrides.json +144 -0
  213. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +7 -7
  214. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +127 -12
  215. data/app/pb_kits/playbook/pb_multi_level_select/docs/_playground.json +310 -61
  216. data/app/pb_kits/playbook/pb_multi_level_select/docs/_playground.overrides.json +327 -44
  217. data/app/pb_kits/playbook/pb_multiple_users/docs/_playground.json +35 -6
  218. data/app/pb_kits/playbook/pb_multiple_users/docs/_playground.overrides.json +35 -6
  219. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_playground.json +32 -21
  220. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_playground.overrides.json +32 -21
  221. data/app/pb_kits/playbook/pb_nav/docs/_playground.json +546 -18
  222. data/app/pb_kits/playbook/pb_nav/docs/_playground.overrides.json +561 -14
  223. data/app/pb_kits/playbook/pb_online_status/docs/_playground.json +18 -23
  224. data/app/pb_kits/playbook/pb_online_status/docs/_playground.overrides.json +18 -14
  225. data/app/pb_kits/playbook/pb_overlay/docs/_playground.json +133 -14
  226. data/app/pb_kits/playbook/pb_overlay/docs/_playground.overrides.json +154 -0
  227. data/app/pb_kits/playbook/pb_pagination/docs/_playground.json +35 -14
  228. data/app/pb_kits/playbook/pb_pagination/docs/_playground.overrides.json +35 -14
  229. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb +1 -1
  230. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_common.html.erb +1 -1
  231. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.html.erb +5 -5
  232. data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_strength_change.html.erb +1 -1
  233. data/app/pb_kits/playbook/pb_passphrase/docs/_playground.json +129 -14
  234. data/app/pb_kits/playbook/pb_passphrase/docs/_playground.overrides.json +148 -0
  235. data/app/pb_kits/playbook/pb_passphrase/index.ts +58 -0
  236. data/app/pb_kits/playbook/pb_passphrase/kit.schema.json +13 -0
  237. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +70 -1
  238. data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +70 -0
  239. data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_playground.json +378 -4
  240. data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_playground.overrides.json +245 -0
  241. data/app/pb_kits/playbook/pb_pb_bar_graph/kit.schema.json +1 -1
  242. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_playground.json +215 -4
  243. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_playground.overrides.json +224 -0
  244. data/app/pb_kits/playbook/pb_pb_circle_chart/kit.schema.json +1 -1
  245. data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_playground.json +149 -4
  246. data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_playground.overrides.json +162 -0
  247. data/app/pb_kits/playbook/pb_pb_gauge_chart/kit.schema.json +1 -1
  248. data/app/pb_kits/playbook/pb_pb_line_graph/docs/_playground.json +392 -4
  249. data/app/pb_kits/playbook/pb_pb_line_graph/docs/_playground.overrides.json +212 -0
  250. data/app/pb_kits/playbook/pb_pb_line_graph/kit.schema.json +1 -1
  251. data/app/pb_kits/playbook/pb_person/docs/_playground.json +27 -11
  252. data/app/pb_kits/playbook/pb_person/docs/_playground.overrides.json +34 -9
  253. data/app/pb_kits/playbook/pb_person_contact/docs/_playground.json +72 -21
  254. data/app/pb_kits/playbook/pb_person_contact/docs/_playground.overrides.json +71 -21
  255. data/app/pb_kits/playbook/pb_phone_number_input/docs/_playground.json +179 -21
  256. data/app/pb_kits/playbook/pb_phone_number_input/docs/_playground.overrides.json +180 -0
  257. data/app/pb_kits/playbook/pb_phone_number_input/kit.schema.json +2 -2
  258. data/app/pb_kits/playbook/pb_pill/docs/_playground.json +16 -49
  259. data/app/pb_kits/playbook/pb_pill/docs/_playground.overrides.json +33 -30
  260. data/app/pb_kits/playbook/pb_popover/_popover.scss +27 -0
  261. data/app/pb_kits/playbook/pb_popover/_popover.tsx +49 -16
  262. data/app/pb_kits/playbook/pb_popover/docs/_playground.json +155 -46
  263. data/app/pb_kits/playbook/pb_popover/docs/_playground.overrides.json +162 -30
  264. data/app/pb_kits/playbook/pb_popover/docs/_popover_list.jsx +9 -11
  265. data/app/pb_kits/playbook/pb_popover/index.ts +35 -4
  266. data/app/pb_kits/playbook/pb_popover/popover.html.erb +5 -2
  267. data/app/pb_kits/playbook/pb_popover/popover.test.js +212 -5
  268. data/app/pb_kits/playbook/pb_progress_pills/docs/_playground.json +26 -13
  269. data/app/pb_kits/playbook/pb_progress_pills/docs/_playground.overrides.json +24 -6
  270. data/app/pb_kits/playbook/pb_progress_simple/docs/_playground.json +50 -17
  271. data/app/pb_kits/playbook/pb_progress_simple/docs/_playground.overrides.json +41 -7
  272. data/app/pb_kits/playbook/pb_progress_step/docs/_playground.json +197 -10
  273. data/app/pb_kits/playbook/pb_progress_step/docs/_playground.overrides.json +189 -0
  274. data/app/pb_kits/playbook/pb_radio/docs/_playground.json +80 -6
  275. data/app/pb_kits/playbook/pb_radio/docs/_playground.overrides.json +82 -3
  276. data/app/pb_kits/playbook/pb_radio/kit.schema.json +1 -1
  277. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarDropdown.tsx +12 -24
  278. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.json +152 -22
  279. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.overrides.json +153 -0
  280. data/app/pb_kits/playbook/pb_select/_select.tsx +1 -0
  281. data/app/pb_kits/playbook/pb_select/docs/_playground.json +65 -19
  282. data/app/pb_kits/playbook/pb_select/docs/_playground.overrides.json +54 -14
  283. data/app/pb_kits/playbook/pb_select/kit.schema.json +2 -2
  284. data/app/pb_kits/playbook/pb_select/select.html.erb +1 -1
  285. data/app/pb_kits/playbook/pb_selectable_card/docs/_playground.json +75 -82
  286. data/app/pb_kits/playbook/pb_selectable_card/docs/_playground.overrides.json +76 -76
  287. data/app/pb_kits/playbook/pb_selectable_card/kit.schema.json +2 -2
  288. data/app/pb_kits/playbook/pb_selectable_card_icon/docs/_playground.json +105 -15
  289. data/app/pb_kits/playbook/pb_selectable_card_icon/docs/_playground.overrides.json +106 -0
  290. data/app/pb_kits/playbook/pb_selectable_card_icon/kit.schema.json +2 -2
  291. data/app/pb_kits/playbook/pb_selectable_icon/docs/_playground.json +37 -21
  292. data/app/pb_kits/playbook/pb_selectable_icon/docs/_playground.overrides.json +35 -18
  293. data/app/pb_kits/playbook/pb_selectable_icon/kit.schema.json +1 -1
  294. data/app/pb_kits/playbook/pb_selectable_list/docs/_playground.json +174 -12
  295. data/app/pb_kits/playbook/pb_selectable_list/docs/_playground.overrides.json +162 -10
  296. data/app/pb_kits/playbook/pb_skeleton_loading/docs/_playground.json +68 -6
  297. data/app/pb_kits/playbook/pb_skeleton_loading/docs/_playground.overrides.json +80 -0
  298. data/app/pb_kits/playbook/pb_source/docs/_playground.json +67 -6
  299. data/app/pb_kits/playbook/pb_source/docs/_playground.overrides.json +80 -0
  300. data/app/pb_kits/playbook/pb_star_rating/docs/_playground.json +28 -53
  301. data/app/pb_kits/playbook/pb_star_rating/docs/_playground.overrides.json +33 -32
  302. data/app/pb_kits/playbook/pb_star_rating/kit.schema.json +1 -1
  303. data/app/pb_kits/playbook/pb_stat_change/docs/_playground.json +15 -9
  304. data/app/pb_kits/playbook/pb_stat_change/docs/_playground.overrides.json +15 -5
  305. data/app/pb_kits/playbook/pb_stat_value/docs/_playground.json +19 -9
  306. data/app/pb_kits/playbook/pb_stat_value/docs/_playground.overrides.json +18 -7
  307. data/app/pb_kits/playbook/pb_stat_value/kit.schema.json +1 -1
  308. data/app/pb_kits/playbook/pb_table/docs/_playground.json +223 -21
  309. data/app/pb_kits/playbook/pb_table/docs/_playground.overrides.json +176 -0
  310. data/app/pb_kits/playbook/pb_text_input/docs/_playground.json +44 -5
  311. data/app/pb_kits/playbook/pb_text_input/docs/_playground.overrides.json +39 -3
  312. data/app/pb_kits/playbook/pb_text_input/kit.schema.json +3 -3
  313. data/app/pb_kits/playbook/pb_textarea/docs/_playground.json +35 -3
  314. data/app/pb_kits/playbook/pb_textarea/docs/_playground.overrides.json +28 -3
  315. data/app/pb_kits/playbook/pb_textarea/kit.schema.json +1 -1
  316. data/app/pb_kits/playbook/pb_time/docs/_playground.json +28 -14
  317. data/app/pb_kits/playbook/pb_time/docs/_playground.overrides.json +26 -13
  318. data/app/pb_kits/playbook/pb_time_picker/_time_picker.scss +42 -0
  319. data/app/pb_kits/playbook/pb_time_picker/_time_picker.tsx +309 -167
  320. data/app/pb_kits/playbook/pb_time_picker/docs/_playground.json +36 -30
  321. data/app/pb_kits/playbook/pb_time_picker/docs/_playground.overrides.json +31 -26
  322. data/app/pb_kits/playbook/pb_time_picker/index.ts +263 -11
  323. data/app/pb_kits/playbook/pb_time_range_inline/docs/_playground.json +63 -9
  324. data/app/pb_kits/playbook/pb_time_range_inline/docs/_playground.overrides.json +69 -0
  325. data/app/pb_kits/playbook/pb_time_stacked/docs/_playground.json +30 -9
  326. data/app/pb_kits/playbook/pb_time_stacked/docs/_playground.overrides.json +30 -9
  327. data/app/pb_kits/playbook/pb_timeline/docs/_playground.json +178 -6
  328. data/app/pb_kits/playbook/pb_timeline/docs/_playground.overrides.json +165 -0
  329. data/app/pb_kits/playbook/pb_timestamp/docs/_playground.json +36 -21
  330. data/app/pb_kits/playbook/pb_timestamp/docs/_playground.overrides.json +35 -20
  331. data/app/pb_kits/playbook/pb_toggle/docs/_playground.json +24 -13
  332. data/app/pb_kits/playbook/pb_toggle/docs/_playground.overrides.json +20 -12
  333. data/app/pb_kits/playbook/pb_toggle/kit.schema.json +2 -2
  334. data/app/pb_kits/playbook/pb_tooltip/docs/_playground.json +42 -23
  335. data/app/pb_kits/playbook/pb_tooltip/docs/_playground.overrides.json +35 -15
  336. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +109 -3
  337. data/app/pb_kits/playbook/pb_typeahead/docs/_playground.json +124 -44
  338. data/app/pb_kits/playbook/pb_typeahead/docs/_playground.overrides.json +98 -31
  339. data/app/pb_kits/playbook/pb_typeahead/kit.schema.json +8 -2
  340. data/app/pb_kits/playbook/pb_user/docs/_playground.json +33 -15
  341. data/app/pb_kits/playbook/pb_user/docs/_playground.overrides.json +32 -15
  342. data/app/pb_kits/playbook/pb_user_badge/docs/_playground.json +26 -12
  343. data/app/pb_kits/playbook/pb_user_badge/docs/_playground.overrides.json +26 -9
  344. data/app/pb_kits/playbook/pb_weekday_stacked/docs/_playground.json +32 -5
  345. data/app/pb_kits/playbook/pb_weekday_stacked/docs/_playground.overrides.json +30 -4
  346. data/app/pb_kits/playbook/tokens/_colors.scss +5 -1
  347. data/app/pb_kits/playbook/utilities/_border.scss +262 -0
  348. data/app/pb_kits/playbook/utilities/floatingPortalHosts.ts +565 -0
  349. data/app/pb_kits/playbook/utilities/global-props.schema.json +98 -0
  350. data/app/pb_kits/playbook/utilities/globalProps.ts +83 -1
  351. data/app/pb_kits/playbook/utilities/icons/allicons.tsx +38 -0
  352. data/app/pb_kits/playbook/utilities/test/globalProps/border.test.js +66 -0
  353. data/dist/chunks/{_pb_line_graph-B870s9g1.js → _pb_line_graph-C2H9vs_8.js} +1 -1
  354. data/dist/chunks/_typeahead-Du8dRYaM.js +5 -0
  355. data/dist/chunks/globalProps-DIAZ03-L.js +6 -0
  356. data/dist/chunks/lib-ZHDedNfP.js +29 -0
  357. data/dist/chunks/time_picker_helper-CVMV9ync.js +1 -0
  358. data/dist/chunks/vendor.js +5 -5
  359. data/dist/menu.yml +7 -0
  360. data/dist/playbook-rails-react-bindings.js +1 -1
  361. data/dist/playbook-rails.js +1 -1
  362. data/dist/playbook.css +1 -1
  363. data/lib/playbook/border.rb +87 -0
  364. data/lib/playbook/classnames.rb +1 -0
  365. data/lib/playbook/forms/builder/form_field_builder.rb +2 -0
  366. data/lib/playbook/kit_base.rb +2 -0
  367. data/lib/playbook/pb_forms_global_props_helper.rb +15 -0
  368. data/lib/playbook/version.rb +2 -2
  369. metadata +93 -9
  370. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.jsx +0 -92
  371. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.md +0 -3
  372. data/dist/chunks/_typeahead-jMN-A0_C.js +0 -5
  373. data/dist/chunks/globalProps-BInmh-C7.js +0 -6
  374. data/dist/chunks/lib-CVYIIiwI.js +0 -29
  375. data/dist/chunks/time_picker_helper-Bx8nzyM8.js +0 -1
@@ -0,0 +1,565 @@
1
+ /**
2
+ * Portal host resolution and positioning for kits whose floating UI (menus, panels)
3
+ * renders outside overflow/scroll regions (Dialog, Filter Popover, React Modal).
4
+ *
5
+ * Used by Typeahead, Dropdown, MultiLevelSelect, DatePicker, and TimePicker.
6
+ */
7
+
8
+ /** Prefer mounting here (sibling to scroll region) so menus are not clipped. */
9
+ export const PB_DIALOG_FLOATING_ROOT_SELECTOR = "[data-pb-dialog-floating-root]"
10
+
11
+ /** Scopes portaled menus to the Dialog / Filter popover that opened them (close-on-click). */
12
+ export const PB_FLOATING_OWNER_ATTR = "data-pb-floating-owner"
13
+
14
+ /** Direct-child floating root on dialog / React modal shells (excludes nested `<dialog>` roots). */
15
+ const DIALOG_DIRECT_FLOATING_ROOT = `:scope > ${PB_DIALOG_FLOATING_ROOT_SELECTOR}`
16
+
17
+ /** Popover floating root lives under `.pb_popover_body`, not on the tooltip root. */
18
+ const POPOVER_FLOATING_ROOT = `:scope > .pb_popover_body > ${PB_DIALOG_FLOATING_ROOT_SELECTOR}`
19
+
20
+ export function resolveDialogFloatingPortalHost(
21
+ fromElement: Element | null | undefined,
22
+ ): HTMLElement | null {
23
+ const dialogEl = fromElement?.closest("dialog")
24
+ if (dialogEl) {
25
+ return (
26
+ dialogEl.querySelector<HTMLElement>(DIALOG_DIRECT_FLOATING_ROOT) ??
27
+ dialogEl
28
+ )
29
+ }
30
+ // react-modal (Playbook React Dialog) uses a div.pb_dialog, not a native <dialog> element.
31
+ const reactModalShell = fromElement?.closest(".pb_dialog")
32
+ if (reactModalShell) {
33
+ return (
34
+ reactModalShell.querySelector<HTMLElement>(DIALOG_DIRECT_FLOATING_ROOT) ??
35
+ (reactModalShell as HTMLElement)
36
+ )
37
+ }
38
+ const popoverEl = fromElement?.closest(".pb_popover_tooltip")
39
+ if (popoverEl) {
40
+ return (
41
+ popoverEl.querySelector<HTMLElement>(POPOVER_FLOATING_ROOT) ??
42
+ popoverEl.querySelector<HTMLElement>(PB_DIALOG_FLOATING_ROOT_SELECTOR) ??
43
+ (popoverEl as HTMLElement)
44
+ )
45
+ }
46
+ return null
47
+ }
48
+
49
+ /**
50
+ * Portal host for Typeahead `menuPortalTarget`, Dropdown / MultiLevelSelect portaled shells, etc.
51
+ *
52
+ * Popper applies `transform` to the popover root. A `position: fixed` menu portaled *inside*
53
+ * that subtree is positioned against the transformed ancestor, not the viewport — so for
54
+ * `.pb_popover_tooltip` we use `document.body`. Native `<dialog>` / React Modal use the
55
+ * floating root or `dialogCtx.selectMenuPortalTarget`.
56
+ */
57
+ export function resolvePortaledKitHost(
58
+ kitRoot: HTMLElement | null | undefined,
59
+ dialogCtxTarget: HTMLElement | null | undefined,
60
+ ): HTMLElement | null {
61
+ if (typeof document === "undefined") return null
62
+
63
+ if (kitRoot?.closest(".pb_popover_tooltip")) {
64
+ return document.body
65
+ }
66
+
67
+ return (
68
+ resolveDialogFloatingPortalHost(kitRoot) ?? dialogCtxTarget ?? null
69
+ )
70
+ }
71
+
72
+ /** True when the kit may need a portaled menu (dialog / filter popover). Cheap `closest` only to skip on plain forms */
73
+ export function kitRequiresPortaledFloatingUi(
74
+ kitRoot: HTMLElement | null | undefined,
75
+ ): boolean {
76
+ if (!kitRoot) return false
77
+ return (
78
+ kitRoot.closest(".pb_popover_tooltip") !== null ||
79
+ kitRoot.closest("dialog") !== null ||
80
+ kitRoot.closest(".pb_dialog") !== null
81
+ )
82
+ }
83
+
84
+ /** Owner id for portaled menus (filter tooltip id, dialog id, React popover targetId) - explicit `data-pb-floating-owner` on the floating root / popover surface */
85
+ export function resolveFloatingOwnerId(
86
+ kitRoot: HTMLElement | null | undefined,
87
+ ): string | null {
88
+ if (!kitRoot) return null
89
+
90
+ const marked = kitRoot.closest(`[${PB_FLOATING_OWNER_ATTR}]`)
91
+ if (marked) {
92
+ return marked.getAttribute(PB_FLOATING_OWNER_ATTR)
93
+ }
94
+
95
+ const popoverTooltip = kitRoot.closest(".pb_popover_tooltip")
96
+ if (popoverTooltip?.id) {
97
+ return popoverTooltip.id
98
+ }
99
+
100
+ const dialogShell = kitRoot.closest("dialog, .pb_dialog")
101
+ if (dialogShell?.id) {
102
+ return dialogShell.id
103
+ }
104
+
105
+ return null
106
+ }
107
+
108
+ export function setFloatingOwnerAttribute(
109
+ element: HTMLElement | null | undefined,
110
+ ownerId: string | null | undefined,
111
+ ): void {
112
+ if (!element) return
113
+ if (ownerId) {
114
+ element.setAttribute(PB_FLOATING_OWNER_ATTR, ownerId)
115
+ } else {
116
+ element.removeAttribute(PB_FLOATING_OWNER_ATTR)
117
+ }
118
+ }
119
+
120
+ function ownerScopeSelector(ownerId: string): string {
121
+ return `[${PB_FLOATING_OWNER_ATTR}="${CSS.escape(ownerId)}"]`
122
+ }
123
+
124
+ function isPortaledFloatingMenuNode(target: HTMLElement): boolean {
125
+ return (
126
+ target.closest(".typeahead-kit-select__menu-portal") !== null ||
127
+ target.closest(".pb_multi_level_select_floating_shell") !== null ||
128
+ target.closest(".pb_dropdown_floating_shell") !== null ||
129
+ target.closest(".pb_date_picker_floating_shell") !== null ||
130
+ target.closest(".flatpickr-calendar") !== null ||
131
+ target.closest(".pb_time_picker_floating_shell") !== null ||
132
+ target.closest(".pb_time_picker_panel_portal") !== null ||
133
+ target.closest(".pb_time_picker_container") !== null ||
134
+ target.closest(".time_dropdown") !== null ||
135
+ target.closest(".time_dropdown_option") !== null
136
+ )
137
+ }
138
+
139
+ const PORTAL_OWNER_HIT_TEST_SELECTORS = [
140
+ ".typeahead-kit-select__menu-portal",
141
+ ".pb_multi_level_select_floating_shell",
142
+ ".pb_dropdown_floating_shell",
143
+ ".pb_date_picker_floating_shell",
144
+ ".flatpickr-calendar",
145
+ ".pb_time_picker_floating_shell",
146
+ ".pb_time_picker_panel_portal",
147
+ ".pb_time_picker_container",
148
+ ".time_dropdown",
149
+ ".time_dropdown_option",
150
+ ].join(", ")
151
+
152
+ function pointInVisibleRect(
153
+ x: number,
154
+ y: number,
155
+ rect: DOMRectReadOnly,
156
+ ): boolean {
157
+ return (
158
+ rect.width > 0 &&
159
+ rect.height > 0 &&
160
+ x >= rect.left &&
161
+ x <= rect.right &&
162
+ y >= rect.top &&
163
+ y <= rect.bottom
164
+ )
165
+ }
166
+
167
+ /** Bounding-rect hit test for portaled menus (fixed children can leave a 0×0 shell). */
168
+ export function portaledFloatingOwnerMenusAtPoint(
169
+ x: number,
170
+ y: number,
171
+ ownerId: string,
172
+ ): boolean {
173
+ if (typeof document === "undefined") {
174
+ return false
175
+ }
176
+
177
+ const roots = document.querySelectorAll<HTMLElement>(
178
+ ownerScopeSelector(ownerId),
179
+ )
180
+
181
+ for (const root of roots) {
182
+ if (
183
+ root.classList.contains("pb_popover_tooltip") ||
184
+ root.classList.contains("pb_popover_body") ||
185
+ root.classList.contains("pb_popover_floating_root")
186
+ ) {
187
+ continue
188
+ }
189
+
190
+ const candidates: HTMLElement[] = [root]
191
+ root
192
+ .querySelectorAll<HTMLElement>(PORTAL_OWNER_HIT_TEST_SELECTORS)
193
+ .forEach((node) => {
194
+ candidates.push(node)
195
+ })
196
+
197
+ for (const node of candidates) {
198
+ if (pointInVisibleRect(x, y, node.getBoundingClientRect())) {
199
+ return true
200
+ }
201
+ }
202
+ }
203
+
204
+ return false
205
+ }
206
+
207
+ export function eventTargetAsElement(
208
+ target: EventTarget | null,
209
+ ): HTMLElement | null {
210
+ if (!target) return null
211
+ if (target instanceof HTMLElement) return target
212
+ if (target instanceof Node) {
213
+ return target.parentElement
214
+ }
215
+ return null
216
+ }
217
+
218
+ /**
219
+ * Native `<select>` menus are OS-rendered (not in the DOM). Firefox may fire
220
+ * mousedown on the dialog/backdrop while picking an option — treat focused or
221
+ * in-dialog selects as an in-menu interaction so the dialog does not close.
222
+ */
223
+ export function isNativeSelectMenuInteraction(
224
+ dialogElement: HTMLElement,
225
+ target: EventTarget | null,
226
+ ): boolean {
227
+ const el = eventTargetAsElement(target)
228
+ const selectFromTarget =
229
+ el instanceof HTMLSelectElement ? el : el?.closest("select") ?? null
230
+
231
+ if (
232
+ selectFromTarget instanceof HTMLSelectElement &&
233
+ dialogElement.contains(selectFromTarget)
234
+ ) {
235
+ return true
236
+ }
237
+
238
+ const active = document.activeElement
239
+ return (
240
+ active instanceof HTMLSelectElement &&
241
+ dialogElement.contains(active)
242
+ )
243
+ }
244
+
245
+ /**
246
+ * Kits that portal menus to `document.body` still belong to the open popover for close-on-click.
247
+ * When `ownerId` is passed, only menus tagged for that surface count (not other open popovers).
248
+ */
249
+ export function targetIsInsidePortaledFloatingKit(
250
+ target: HTMLElement,
251
+ ownerId?: string | null,
252
+ ): boolean {
253
+ if (!isPortaledFloatingMenuNode(target)) {
254
+ return false
255
+ }
256
+
257
+ if (!ownerId) {
258
+ return true
259
+ }
260
+
261
+ return target.closest(ownerScopeSelector(ownerId)) !== null
262
+ }
263
+
264
+ /** Hit-test the full stacking context stack (covers overflow / fixed descendants). */
265
+ export function portaledFloatingKitAtPoint(
266
+ x: number,
267
+ y: number,
268
+ ownerId?: string | null,
269
+ ): boolean {
270
+ if (typeof document === "undefined") {
271
+ return false
272
+ }
273
+
274
+ try {
275
+ if (typeof document.elementsFromPoint === "function") {
276
+ return document.elementsFromPoint(x, y).some((el) => {
277
+ if (!(el instanceof HTMLElement)) return false
278
+ return targetIsInsidePortaledFloatingKit(el, ownerId)
279
+ })
280
+ }
281
+
282
+ if (typeof document.elementFromPoint === "function") {
283
+ const el = document.elementFromPoint(x, y)
284
+ return (
285
+ el instanceof HTMLElement &&
286
+ targetIsInsidePortaledFloatingKit(el, ownerId)
287
+ )
288
+ }
289
+ } catch {
290
+ return false
291
+ }
292
+
293
+ return false
294
+ }
295
+
296
+ type PortaledMenuPointerDown = {
297
+ ownerId: string
298
+ x: number
299
+ y: number
300
+ at: number
301
+ }
302
+
303
+ let portaledMenuPointerDown: PortaledMenuPointerDown | null = null
304
+
305
+ /** Record mousedown on a portaled menu so the following click still counts as in-menu. */
306
+ export function recordPortaledMenuPointerDown(
307
+ ownerId: string,
308
+ x: number,
309
+ y: number,
310
+ ): void {
311
+ portaledMenuPointerDown = { ownerId, x, y, at: Date.now() }
312
+ }
313
+
314
+ export function matchesPortaledMenuPointerDown(
315
+ ownerId: string,
316
+ x: number,
317
+ y: number,
318
+ maxAgeMs = 750,
319
+ ): boolean {
320
+ const rec = portaledMenuPointerDown
321
+ if (!rec || rec.ownerId !== ownerId) return false
322
+ if (Date.now() - rec.at > maxAgeMs) return false
323
+ return Math.abs(rec.x - x) <= 2 && Math.abs(rec.y - y) <= 2
324
+ }
325
+
326
+ export function isPortaledFloatingKitInteraction(
327
+ target: EventTarget | null,
328
+ ownerId?: string | null,
329
+ clientX?: number,
330
+ clientY?: number,
331
+ ): boolean {
332
+ const el = eventTargetAsElement(target)
333
+ if (el && targetIsInsidePortaledFloatingKit(el, ownerId)) {
334
+ return true
335
+ }
336
+
337
+ if (clientX == null || clientY == null) {
338
+ return false
339
+ }
340
+
341
+ if (
342
+ ownerId &&
343
+ matchesPortaledMenuPointerDown(ownerId, clientX, clientY)
344
+ ) {
345
+ return true
346
+ }
347
+
348
+ if (ownerId && portaledFloatingOwnerMenusAtPoint(clientX, clientY, ownerId)) {
349
+ return true
350
+ }
351
+
352
+ return portaledFloatingKitAtPoint(clientX, clientY, ownerId)
353
+ }
354
+
355
+ /**
356
+ * Unified z-index for all portaled floating UI (filter popover on `document.body`
357
+ * and dialog/modal floating roots). Above popover (900–1001), below typical app
358
+ * nav (10010). Dialog menus only stack within the modal; the same cap applies.
359
+ */
360
+ export const PB_PORTALED_FLOATING_Z_INDEX = "1002"
361
+ export const PB_PORTALED_FLOATING_Z_INDEX_MAX = 10009
362
+
363
+ let portaledFloatingZIndexSeq = Number(PB_PORTALED_FLOATING_Z_INDEX)
364
+
365
+ /** Monotonic z-index for any portaled menu/panel. Capped at 10009. */
366
+ export function nextPortaledFloatingZIndex(): string {
367
+ portaledFloatingZIndexSeq = Math.min(
368
+ portaledFloatingZIndexSeq + 1,
369
+ PB_PORTALED_FLOATING_Z_INDEX_MAX,
370
+ )
371
+ return String(portaledFloatingZIndexSeq)
372
+ }
373
+
374
+ /** Caps any portaled host at 10009 (body and dialog use the same range). */
375
+ export function resolvePortaledFloatingZIndex(
376
+ _portalHost: HTMLElement,
377
+ preferred?: string,
378
+ ): string {
379
+ const z = Number(preferred ?? PB_PORTALED_FLOATING_Z_INDEX)
380
+ return String(Math.min(z, PB_PORTALED_FLOATING_Z_INDEX_MAX))
381
+ }
382
+
383
+ export const PB_FLOATING_KIT_OPEN_EVENT = "pb-floating-kit-open"
384
+
385
+ export type FloatingKitOpenDetail = {
386
+ kitKind: string
387
+ ownerId?: string | null
388
+ }
389
+
390
+ export function announceFloatingKitOpen(
391
+ kitKind: string,
392
+ ownerId?: string | null,
393
+ ): void {
394
+ if (typeof document === "undefined") return
395
+ document.dispatchEvent(
396
+ new CustomEvent<FloatingKitOpenDetail>(PB_FLOATING_KIT_OPEN_EVENT, {
397
+ detail: { kitKind, ownerId },
398
+ }),
399
+ )
400
+ }
401
+
402
+ export function subscribeFloatingKitOpen(
403
+ handler: (detail: FloatingKitOpenDetail) => void,
404
+ ): () => void {
405
+ if (typeof document === "undefined") {
406
+ return () => undefined
407
+ }
408
+
409
+ const listener = (event: Event) => {
410
+ handler((event as CustomEvent<FloatingKitOpenDetail>).detail)
411
+ }
412
+
413
+ document.addEventListener(PB_FLOATING_KIT_OPEN_EVENT, listener)
414
+ return () => document.removeEventListener(PB_FLOATING_KIT_OPEN_EVENT, listener)
415
+ }
416
+
417
+ /** Use instead of `=== document.body` (iframes / identity quirks). */
418
+ export function isPortalCoordinateRootBody(el: Element | null | undefined): boolean {
419
+ return el != null && el.nodeName === "BODY"
420
+ }
421
+
422
+ export function positionFloatingShellToInput(args: {
423
+ shell: HTMLElement
424
+ inputViewportRect: DOMRectReadOnly
425
+ menuEl?: HTMLElement | null
426
+ maxMenuHeightPx: number
427
+ positionHost?: HTMLElement | null
428
+ styleTarget?: HTMLElement | null
429
+ zIndex?: string
430
+ }): void {
431
+ const { shell, inputViewportRect, menuEl, maxMenuHeightPx, positionHost, styleTarget } = args
432
+ const coordHost = positionHost ?? shell.parentElement
433
+ if (!coordHost) return
434
+
435
+ const box = styleTarget ?? shell
436
+ const coordTopPx = inputViewportRect.bottom + 4
437
+
438
+ box.style.margin = "0"
439
+ box.style.padding = "0"
440
+ box.style.pointerEvents = "auto"
441
+ box.style.zIndex = resolvePortaledFloatingZIndex(
442
+ coordHost as HTMLElement,
443
+ args.zIndex ?? PB_PORTALED_FLOATING_Z_INDEX,
444
+ )
445
+ box.style.width = `${Math.round(inputViewportRect.width)}px`
446
+
447
+ if (isPortalCoordinateRootBody(coordHost)) {
448
+ box.style.position = "fixed"
449
+ box.style.left = `${Math.round(inputViewportRect.left)}px`
450
+ box.style.top = `${Math.round(coordTopPx)}px`
451
+ } else {
452
+ const hr = coordHost.getBoundingClientRect()
453
+ box.style.position = "absolute"
454
+ box.style.left = `${Math.round(inputViewportRect.left - hr.left)}px`
455
+ box.style.top = `${Math.round(inputViewportRect.bottom - hr.top + 4)}px`
456
+ }
457
+
458
+ if (menuEl) {
459
+ const mh = Math.round(maxMenuHeightPx)
460
+ menuEl.style.maxHeight = `${mh}px`
461
+ menuEl.style.overflow = "auto"
462
+ }
463
+ }
464
+
465
+ export function positionDropdownPortalToWrapper(args: {
466
+ panel: HTMLElement
467
+ wrapperViewportRect: DOMRectReadOnly
468
+ positionHost: HTMLElement
469
+ marginPx?: number
470
+ matchWrapperWidth?: boolean
471
+ /** When true, always place below the wrapper (no flip above when panel is tall). */
472
+ preferBelow?: boolean
473
+ zIndex?: string
474
+ }): void {
475
+ const margin = args.marginPx ?? 5
476
+ const matchWrapperWidth = args.matchWrapperWidth ?? true
477
+ const preferBelow = args.preferBelow ?? false
478
+ const { panel, wrapperViewportRect: wr, positionHost } = args
479
+
480
+ const h =
481
+ panel.getBoundingClientRect().height ||
482
+ panel.scrollHeight ||
483
+ 0
484
+
485
+ const spaceBelow = window.innerHeight - wr.bottom
486
+ const spaceAbove = wr.top
487
+
488
+ let topPx: number
489
+ if (
490
+ !preferBelow &&
491
+ h > 0 &&
492
+ spaceBelow < h + 10 &&
493
+ spaceAbove >= h + 10
494
+ ) {
495
+ topPx = wr.top - h - margin
496
+ } else {
497
+ topPx = wr.bottom + margin
498
+ }
499
+
500
+ panel.style.margin = "0"
501
+ panel.style.pointerEvents = "auto"
502
+ panel.style.zIndex = resolvePortaledFloatingZIndex(
503
+ positionHost,
504
+ args.zIndex ?? PB_PORTALED_FLOATING_Z_INDEX,
505
+ )
506
+ if (matchWrapperWidth) {
507
+ panel.style.width = `${Math.round(wr.width)}px`
508
+ } else {
509
+ panel.style.removeProperty("width")
510
+ }
511
+
512
+ if (isPortalCoordinateRootBody(positionHost)) {
513
+ panel.style.position = "fixed"
514
+ panel.style.left = `${Math.round(wr.left)}px`
515
+ panel.style.top = `${Math.round(topPx)}px`
516
+ } else {
517
+ const hr = positionHost.getBoundingClientRect()
518
+ panel.style.position = "absolute"
519
+ panel.style.left = `${Math.round(wr.left - hr.left)}px`
520
+ panel.style.top = `${Math.round(topPx - hr.top)}px`
521
+ }
522
+ }
523
+
524
+ /** Re-run positioning while a portaled menu is open for Dropdown and Multi Level Select. */
525
+ export function subscribeFloatingKitReposition(reposition: () => void): () => void {
526
+ if (typeof window === "undefined" || typeof document === "undefined") {
527
+ return () => undefined
528
+ }
529
+
530
+ const scrollOpts: AddEventListenerOptions = { capture: true, passive: true }
531
+ let rafId: number | null = null
532
+
533
+ // Coalesce burst scroll/resize events to one layout read + style write per frame.
534
+ const run = () => {
535
+ if (rafId != null) return
536
+ rafId = requestAnimationFrame(() => {
537
+ rafId = null
538
+ reposition()
539
+ })
540
+ }
541
+
542
+ window.addEventListener("scroll", run, scrollOpts)
543
+ document.addEventListener("scroll", run, scrollOpts)
544
+ window.addEventListener("resize", run)
545
+
546
+ const vv = window.visualViewport
547
+ if (vv) {
548
+ vv.addEventListener("scroll", run)
549
+ vv.addEventListener("resize", run)
550
+ }
551
+
552
+ return () => {
553
+ if (rafId != null) {
554
+ cancelAnimationFrame(rafId)
555
+ rafId = null
556
+ }
557
+ window.removeEventListener("scroll", run, scrollOpts)
558
+ document.removeEventListener("scroll", run, scrollOpts)
559
+ window.removeEventListener("resize", run)
560
+ if (vv) {
561
+ vv.removeEventListener("scroll", run)
562
+ vv.removeEventListener("resize", run)
563
+ }
564
+ }
565
+ }
@@ -60,6 +60,97 @@
60
60
  "description": "Align items.",
61
61
  "example": "alignItems=\"start\" or alignItems={{ default: \"start\", md: \"end\" }}"
62
62
  },
63
+ "border": {
64
+ "type": "enum",
65
+ "values": [
66
+ "none",
67
+ "default",
68
+ "active",
69
+ "default_thick",
70
+ "default_thicker",
71
+ "active_thick",
72
+ "active_thicker"
73
+ ],
74
+ "description": "Border."
75
+ },
76
+ "borderTop": {
77
+ "type": "enum",
78
+ "values": [
79
+ "none",
80
+ "default",
81
+ "active",
82
+ "default_thick",
83
+ "default_thicker",
84
+ "active_thick",
85
+ "active_thicker"
86
+ ],
87
+ "description": "Top border."
88
+ },
89
+ "borderBottom": {
90
+ "type": "enum",
91
+ "values": [
92
+ "none",
93
+ "default",
94
+ "active",
95
+ "default_thick",
96
+ "default_thicker",
97
+ "active_thick",
98
+ "active_thicker"
99
+ ],
100
+ "description": "Bottom border."
101
+ },
102
+ "borderLeft": {
103
+ "type": "enum",
104
+ "values": [
105
+ "none",
106
+ "default",
107
+ "active",
108
+ "default_thick",
109
+ "default_thicker",
110
+ "active_thick",
111
+ "active_thicker"
112
+ ],
113
+ "description": "Left border."
114
+ },
115
+ "borderRight": {
116
+ "type": "enum",
117
+ "values": [
118
+ "none",
119
+ "default",
120
+ "active",
121
+ "default_thick",
122
+ "default_thicker",
123
+ "active_thick",
124
+ "active_thicker"
125
+ ],
126
+ "description": "Right border."
127
+ },
128
+ "borderX": {
129
+ "type": "enum",
130
+ "values": [
131
+ "none",
132
+ "default",
133
+ "active",
134
+ "default_thick",
135
+ "default_thicker",
136
+ "active_thick",
137
+ "active_thicker"
138
+ ],
139
+ "description": "Horizontal border (left + right)."
140
+ },
141
+ "borderY": {
142
+ "type": "enum",
143
+ "values": [
144
+ "none",
145
+ "default",
146
+ "active",
147
+ "default_thick",
148
+ "default_thicker",
149
+ "active_thick",
150
+ "active_thicker"
151
+ ],
152
+ "description": "Vertical border (top + bottom)."
153
+ },
63
154
  "borderRadius": {
64
155
  "type": "enum",
65
156
  "values": [
@@ -750,6 +841,13 @@
750
841
  "paddingX",
751
842
  "paddingY",
752
843
  "padding",
844
+ "border",
845
+ "borderTop",
846
+ "borderBottom",
847
+ "borderLeft",
848
+ "borderRight",
849
+ "borderX",
850
+ "borderY",
753
851
  "dark",
754
852
  "enableDrag",
755
853
  "requiredIndicator"