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
@@ -1,6 +1,7 @@
1
1
  import PbEnhancedElement from "../pb_enhanced_element";
2
2
  import { PbDropdownKeyboard } from "./keyboard_accessibility";
3
3
  import { setArrowVisibility, toggleVisibility } from "../utilities/domHelpers";
4
+ import { subscribeFloatingKitReposition, positionDropdownPortalToWrapper } from "../utilities/floatingPortalHosts";
4
5
 
5
6
  const DROPDOWN_SELECTOR = "[data-pb-dropdown]";
6
7
  const TRIGGER_SELECTOR = "[data-dropdown-trigger]";
@@ -17,6 +18,72 @@ const SEARCH_BAR_SELECTOR = "[data-dropdown-search]";
17
18
  const CLEAR_ICON_SELECTOR = "[data-dropdown-clear-icon]";
18
19
  const LABEL_SELECTOR = '[data-dropdown="pb-dropdown-label"]';
19
20
 
21
+ // Portal host + positioning (parity with utilities/floatingPortalHosts.ts + React Dropdown).
22
+ const PB_DIALOG_FLOATING_ROOT = "[data-pb-dialog-floating-root]";
23
+ const PB_FLOATING_OWNER_ATTR = "data-pb-floating-owner";
24
+
25
+ function resolveFloatingOwnerId(fromElement) {
26
+ if (!fromElement) return null;
27
+ const marked = fromElement.closest(`[${PB_FLOATING_OWNER_ATTR}]`);
28
+ if (marked) return marked.getAttribute(PB_FLOATING_OWNER_ATTR);
29
+ const popoverEl = fromElement.closest(".pb_popover_tooltip");
30
+ if (popoverEl?.id) return popoverEl.id;
31
+ const dialogEl = fromElement.closest("dialog, .pb_dialog");
32
+ if (dialogEl?.id) return dialogEl.id;
33
+ return null;
34
+ }
35
+
36
+ const DIALOG_DIRECT_FLOATING_ROOT = `:scope > ${PB_DIALOG_FLOATING_ROOT}`;
37
+ const POPOVER_FLOATING_ROOT = `:scope > .pb_popover_body > ${PB_DIALOG_FLOATING_ROOT}`;
38
+
39
+ function resolveDialogFloatingPortalHost(fromElement) {
40
+ if (!fromElement) return null;
41
+ const dialogEl = fromElement.closest("dialog");
42
+ if (dialogEl) {
43
+ return dialogEl.querySelector(DIALOG_DIRECT_FLOATING_ROOT) || dialogEl;
44
+ }
45
+ const reactModalShell = fromElement.closest(".pb_dialog");
46
+ if (reactModalShell) {
47
+ return (
48
+ reactModalShell.querySelector(DIALOG_DIRECT_FLOATING_ROOT) ||
49
+ reactModalShell
50
+ );
51
+ }
52
+ const popoverEl = fromElement.closest(".pb_popover_tooltip");
53
+ if (popoverEl) {
54
+ return (
55
+ popoverEl.querySelector(POPOVER_FLOATING_ROOT) ||
56
+ popoverEl.querySelector(PB_DIALOG_FLOATING_ROOT) ||
57
+ popoverEl
58
+ );
59
+ }
60
+ return null;
61
+ }
62
+
63
+ function resolvePortaledKitHost(kitRoot, dialogCtxTarget) {
64
+ if (typeof document === "undefined") return null;
65
+ if (kitRoot && kitRoot.closest(".pb_popover_tooltip")) {
66
+ return document.body;
67
+ }
68
+ return (
69
+ resolveDialogFloatingPortalHost(kitRoot) || dialogCtxTarget || null
70
+ );
71
+ }
72
+
73
+ function clearDropdownPortalPanelStyles(panel) {
74
+ [
75
+ "position",
76
+ "left",
77
+ "top",
78
+ "right",
79
+ "bottom",
80
+ "width",
81
+ "z-index",
82
+ "margin",
83
+ ].forEach((prop) => {
84
+ panel.style.removeProperty(prop);
85
+ });
86
+ }
20
87
 
21
88
  export default class PbDropdown extends PbEnhancedElement {
22
89
  static get selector() {
@@ -58,6 +125,12 @@ export default class PbDropdown extends PbEnhancedElement {
58
125
  };
59
126
  }
60
127
 
128
+ /** Options live under `[data-dropdown-container]`; use this when the menu is portaled to body. */
129
+ queryAllOptions() {
130
+ const root = this.target || this.element;
131
+ return root.querySelectorAll(OPTION_SELECTOR);
132
+ }
133
+
61
134
  selectedOptions = new Set();
62
135
  clearBtn = null;
63
136
 
@@ -66,7 +139,21 @@ export default class PbDropdown extends PbEnhancedElement {
66
139
  this.element._pbDropdownInstance = this;
67
140
  this.cacheElements();
68
141
 
142
+ this.portalHost = null;
143
+ this.useMenuPortal = false;
144
+ this.floatingOwnerId = null;
145
+ this._floatingResolved = false;
146
+ this.portalShell = null;
147
+ this._portalParent = null;
148
+ this._portalNext = null;
149
+ this.boundApplyPortalPosition = () => {
150
+ if (this.target?.classList.contains("open")) {
151
+ this.applyPortalPosition();
152
+ }
153
+ };
154
+
69
155
  this.keyboardHandler = new PbDropdownKeyboard(this);
156
+ this.isDisabled = this.element.dataset.pbDropdownDisabled === "true";
70
157
  this.isMultiSelect = this.element.dataset.pbDropdownMultiSelect === "true";
71
158
  this.closeOnClick = this.element.dataset.pbDropdownCloseOnClick || "any";
72
159
  this.formPillProps = this.element.dataset.formPillProps
@@ -95,6 +182,7 @@ export default class PbDropdown extends PbEnhancedElement {
95
182
  this.clearBtn.addEventListener("click", this.clearBtnHandler);
96
183
  }
97
184
  this.updateClearButton();
185
+ this.applyDisabledState();
98
186
 
99
187
  // Listen for clear and select events from external source
100
188
  this.handleClearEventBound = this.handleClearEvent.bind(this);
@@ -117,6 +205,8 @@ export default class PbDropdown extends PbEnhancedElement {
117
205
  }
118
206
 
119
207
  disconnect() {
208
+ this.unmountPortalMenu();
209
+
120
210
  // Clean up stored instance reference
121
211
  if (this.element._pbDropdownInstance === this) {
122
212
  delete this.element._pbDropdownInstance
@@ -193,10 +283,45 @@ export default class PbDropdown extends PbEnhancedElement {
193
283
  this.clearBtn.style.display = hasSelection ? "" : "none";
194
284
  }
195
285
 
286
+ applyDisabledState() {
287
+ if (!this.isDisabled) return;
288
+
289
+ const focusableSelector = [
290
+ "a[href]",
291
+ "button",
292
+ "input",
293
+ "select",
294
+ "textarea",
295
+ "[tabindex]",
296
+ "[contenteditable='true']",
297
+ CLEAR_ICON_SELECTOR,
298
+ DOWN_ARROW_SELECTOR,
299
+ UP_ARROW_SELECTOR,
300
+ ].join(",");
301
+
302
+ this.element.querySelectorAll(focusableSelector).forEach((element) => {
303
+ element.setAttribute("aria-disabled", "true");
304
+ element.setAttribute("tabindex", "-1");
305
+
306
+ if (element.matches("input, select, textarea, button")) {
307
+ element.setAttribute("disabled", "disabled");
308
+ }
309
+ });
310
+
311
+ this.element.querySelectorAll(`${CLEAR_ICON_SELECTOR}, ${DOWN_ARROW_SELECTOR}, ${UP_ARROW_SELECTOR}`).forEach((icon) => {
312
+ icon.setAttribute("aria-hidden", "true");
313
+ icon.setAttribute("focusable", "false");
314
+ });
315
+
316
+ this.hideElement(this.target);
317
+ this.updateArrowDisplay(false);
318
+ }
319
+
196
320
  bindEventListeners() {
197
321
  const customTrigger = this.customTrigger || this.element;
198
322
  this.customTriggerClickHandler = (e) => {
199
323
  const label = e.target.closest(LABEL_SELECTOR);
324
+ if (this.isDisabled) return;
200
325
  if (label && label.htmlFor) {
201
326
  const trigger = this.element.querySelector(
202
327
  `#${CSS.escape(label.htmlFor)}`,
@@ -265,6 +390,9 @@ export default class PbDropdown extends PbEnhancedElement {
265
390
  el.offsetHeight; // force reflow
266
391
  el.style.height = el.scrollHeight + "px";
267
392
  }
393
+ if (this.useMenuPortal) {
394
+ this.applyPortalPosition();
395
+ }
268
396
  });
269
397
  }
270
398
  }
@@ -272,6 +400,11 @@ export default class PbDropdown extends PbEnhancedElement {
272
400
  adjustDropdownPosition(container) {
273
401
  if (!container) return;
274
402
 
403
+ if (this.useMenuPortal) {
404
+ this.applyPortalPosition();
405
+ return;
406
+ }
407
+
275
408
  const wrapper = this.dropdownWrapper;
276
409
  if (!wrapper) return;
277
410
 
@@ -295,10 +428,93 @@ export default class PbDropdown extends PbEnhancedElement {
295
428
  }
296
429
  }
297
430
 
431
+ ensureFloatingPortalConfig() {
432
+ if (this._floatingResolved) return;
433
+ this.portalHost = resolvePortaledKitHost(this.element, null);
434
+ this.floatingOwnerId = resolveFloatingOwnerId(this.element);
435
+ this.useMenuPortal = Boolean(this.portalHost);
436
+ this._floatingResolved = true;
437
+ }
438
+
439
+ mountPortalMenu(container) {
440
+ if (!this.useMenuPortal || !this.portalHost) return;
441
+ if (container.dataset.pbDropdownPortaled === "true") return;
442
+
443
+ this._portalParent = container.parentNode;
444
+ this._portalNext = container.nextSibling;
445
+
446
+ const shell = document.createElement("div");
447
+ shell.className = `${this.element.className} pb_dropdown_floating_shell`.trim();
448
+ if (this.floatingOwnerId) {
449
+ shell.setAttribute(PB_FLOATING_OWNER_ATTR, this.floatingOwnerId);
450
+ }
451
+
452
+ const innerWrap = document.createElement("div");
453
+ const hasError = this.dropdownWrapper?.classList.contains("error");
454
+ innerWrap.className = hasError ? "dropdown_wrapper error" : "dropdown_wrapper";
455
+ Object.assign(innerWrap.style, {
456
+ background: "transparent",
457
+ border: "none",
458
+ boxShadow: "none",
459
+ margin: "0",
460
+ minHeight: "0",
461
+ padding: "0",
462
+ position: "static",
463
+ });
464
+
465
+ innerWrap.appendChild(container);
466
+ shell.appendChild(innerWrap);
467
+ this.portalHost.appendChild(shell);
468
+ this.portalShell = shell;
469
+ container.dataset.pbDropdownPortaled = "true";
470
+ }
471
+
472
+ unmountPortalMenu() {
473
+ if (this._unsubscribePortalReposition) {
474
+ this._unsubscribePortalReposition();
475
+ this._unsubscribePortalReposition = null;
476
+ }
477
+ if (this.boundApplyPortalPosition) {
478
+ window.removeEventListener("resize", this.boundApplyPortalPosition);
479
+ }
480
+ if (!this.target || this.target.dataset.pbDropdownPortaled !== "true") {
481
+ return;
482
+ }
483
+ delete this.target.dataset.pbDropdownPortaled;
484
+ clearDropdownPortalPanelStyles(this.target);
485
+
486
+ if (this._portalParent && this.target) {
487
+ if (this._portalNext && this._portalNext.parentNode === this._portalParent) {
488
+ this._portalParent.insertBefore(this.target, this._portalNext);
489
+ } else {
490
+ this._portalParent.appendChild(this.target);
491
+ }
492
+ }
493
+ this._portalParent = null;
494
+ this._portalNext = null;
495
+
496
+ if (this.portalShell) {
497
+ this.portalShell.remove();
498
+ }
499
+ this.portalShell = null;
500
+ }
501
+
502
+ applyPortalPosition() {
503
+ if (!this.useMenuPortal || !this.portalHost || !this.target || !this.dropdownWrapper) {
504
+ return;
505
+ }
506
+ positionDropdownPortalToWrapper({
507
+ panel: this.target,
508
+ wrapperViewportRect: this.dropdownWrapper.getBoundingClientRect(),
509
+ positionHost: this.portalHost,
510
+ });
511
+ }
512
+
298
513
  handleSearch(term = "") {
514
+ if (this.isDisabled) return;
299
515
  const lcTerm = term.toLowerCase();
300
516
  let hasMatch = false;
301
- this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
517
+ this.queryAllOptions().forEach((opt) => {
302
518
  //make it so that if the option is selected, it will not show up in the search results
303
519
  if (
304
520
  this.isMultiSelect &&
@@ -326,7 +542,7 @@ export default class PbDropdown extends PbEnhancedElement {
326
542
  }
327
543
 
328
544
  showNoOptionsMessage() {
329
- if (this.element.querySelector(".dropdown_no_options")) return;
545
+ if (this.target?.querySelector(".dropdown_no_options")) return;
330
546
 
331
547
  const noOptionElement = document.createElement("div");
332
548
  noOptionElement.className =
@@ -337,17 +553,20 @@ export default class PbDropdown extends PbEnhancedElement {
337
553
  }
338
554
 
339
555
  removeNoOptionsMessage() {
340
- const existing = this.element.querySelector(".dropdown_no_options");
556
+ const existing = this.target?.querySelector(".dropdown_no_options");
341
557
  if (existing) {
342
558
  existing.remove();
343
559
  }
344
560
  }
345
561
 
346
562
  handleOptionClick(event) {
563
+ if (this.isDisabled) return;
347
564
  const option = event.target.closest(OPTION_SELECTOR);
348
565
  const hiddenInput = this.baseInput;
349
566
 
350
567
  if (option) {
568
+ if (option.dataset.dropdownOptionDisabled === "true") return;
569
+
351
570
  const value = option.dataset.dropdownOptionLabel;
352
571
  if (this.isMultiSelect) {
353
572
  const alreadySelected = this.selectedOptions.has(value);
@@ -389,6 +608,7 @@ export default class PbDropdown extends PbEnhancedElement {
389
608
  // ----- External events handling section -----
390
609
  // Handles pb:dropdown:clear - clear this dropdown when event.detail.dropdownId matches.
391
610
  handleClearEvent(event) {
611
+ if (this.isDisabled) return;
392
612
  const targetId = event.detail?.dropdownId;
393
613
  if (targetId && this.element.id === targetId) {
394
614
  this.clearSelection();
@@ -397,6 +617,7 @@ export default class PbDropdown extends PbEnhancedElement {
397
617
 
398
618
  // Handles custom_event_type events (e.g. turbo:submit-end) - clear when detail.dropdownId matches or is omitted.
399
619
  handleCustomClearEvent(event) {
620
+ if (this.isDisabled) return;
400
621
  const targetId = event.detail?.dropdownId;
401
622
  if (targetId == null || this.element.id === targetId) {
402
623
  this.clearSelection();
@@ -406,6 +627,7 @@ export default class PbDropdown extends PbEnhancedElement {
406
627
  // Handles pb:dropdown:select - set dropdown selection by option id(s).
407
628
  // Single: detail: { dropdownId, optionId }. Multi: detail: { dropdownId, optionIds: ['id1', 'id2'] }.
408
629
  handleSelectEvent(event) {
630
+ if (this.isDisabled) return;
409
631
  const targetId = event.detail?.dropdownId;
410
632
  if (!targetId || this.element.id !== targetId) return;
411
633
 
@@ -422,7 +644,7 @@ export default class PbDropdown extends PbEnhancedElement {
422
644
  setSelectionByOptionId(optionId) {
423
645
  if (this.isMultiSelect) return;
424
646
  const hiddenInput = this.baseInput;
425
- const optionEls = Array.from(this.element.querySelectorAll(OPTION_SELECTOR));
647
+ const optionEls = Array.from(this.queryAllOptions());
426
648
  const selectedOption = optionEls.find((opt) => {
427
649
  try {
428
650
  return JSON.parse(opt.dataset.dropdownOptionLabel).id === optionId;
@@ -431,6 +653,7 @@ export default class PbDropdown extends PbEnhancedElement {
431
653
  }
432
654
  });
433
655
  if (!selectedOption) return;
656
+ if (selectedOption.dataset.dropdownOptionDisabled === "true") return;
434
657
 
435
658
  optionEls.forEach((opt) => opt.classList.remove("pb_dropdown_option_selected"));
436
659
  selectedOption.classList.add("pb_dropdown_option_selected");
@@ -485,7 +708,7 @@ export default class PbDropdown extends PbEnhancedElement {
485
708
  // Set multi-select dropdown to the options with the given ids. Invalid ids are skipped.
486
709
  setSelectionByOptionIds(optionIds) {
487
710
  if (!this.isMultiSelect || !optionIds.length) return;
488
- const optionEls = Array.from(this.element.querySelectorAll(OPTION_SELECTOR));
711
+ const optionEls = Array.from(this.queryAllOptions());
489
712
  this.selectedOptions.clear();
490
713
  optionEls.forEach((opt) => {
491
714
  opt.classList.remove("pb_dropdown_option_selected");
@@ -501,6 +724,8 @@ export default class PbDropdown extends PbEnhancedElement {
501
724
  }
502
725
  });
503
726
  if (opt) {
727
+ if (opt.dataset.dropdownOptionDisabled === "true") return;
728
+
504
729
  const raw = opt.dataset.dropdownOptionLabel;
505
730
  this.selectedOptions.add(raw);
506
731
  opt.style.display = "none";
@@ -525,7 +750,7 @@ export default class PbDropdown extends PbEnhancedElement {
525
750
  return !clickInTrigger && !clickInContainer;
526
751
  } else {
527
752
  const triggerElement = this.trigger;
528
- const containerElement = this.element.querySelector(CONTAINER_SELECTOR);
753
+ const containerElement = this.target;
529
754
 
530
755
  const isOutsideTrigger = triggerElement
531
756
  ? !triggerElement.contains(event.target)
@@ -547,7 +772,7 @@ export default class PbDropdown extends PbEnhancedElement {
547
772
  const hiddenInput = this.baseInput;
548
773
  detail = hiddenInput.value
549
774
  ? JSON.parse(
550
- this.element.querySelector(
775
+ (this.target || this.element).querySelector(
551
776
  OPTION_SELECTOR +
552
777
  `[data-dropdown-option-label*='"id":"${hiddenInput.value}"']`,
553
778
  ).dataset.dropdownOptionLabel,
@@ -663,19 +888,14 @@ export default class PbDropdown extends PbEnhancedElement {
663
888
  this.emitSelectionChange();
664
889
  }
665
890
 
666
- const customTrigger = this.customTrigger;
667
891
  const shouldCloseOnOptionSelect =
668
892
  this.closeOnClick === "any" || this.closeOnClick === "inside";
669
- if (
670
- customTrigger &&
671
- shouldCloseOnOptionSelect &&
672
- this.target.classList.contains("open")
673
- ) {
893
+ if (shouldCloseOnOptionSelect && this.target.classList.contains("open")) {
674
894
  this.hideElement(this.target);
675
895
  this.updateArrowDisplay(false);
676
896
  }
677
897
 
678
- const options = this.element.querySelectorAll(OPTION_SELECTOR);
898
+ const options = this.queryAllOptions();
679
899
  if (this.isMultiSelect) {
680
900
  this.emitSelectionChange();
681
901
  Array.from(this.selectedOptions).map((option) => {
@@ -702,9 +922,16 @@ export default class PbDropdown extends PbEnhancedElement {
702
922
  }
703
923
 
704
924
  showElement(elem) {
925
+ if (this.isDisabled) return;
926
+
927
+ this.ensureFloatingPortalConfig();
928
+ if (this.useMenuPortal) {
929
+ this.mountPortalMenu(elem);
930
+ }
931
+
705
932
  elem.classList.remove("close");
706
933
  elem.classList.add("open");
707
-
934
+
708
935
  const shouldConstrain = elem.classList.contains("constrain_height");
709
936
  if (shouldConstrain) {
710
937
  // Calculate height respecting max-height constraint (18em)
@@ -716,14 +943,30 @@ export default class PbDropdown extends PbEnhancedElement {
716
943
  } else {
717
944
  elem.style.height = elem.scrollHeight + "px";
718
945
  }
719
-
720
- // Auto-position dropdown above if not enough space below
721
- this.adjustDropdownPosition(elem);
946
+
947
+ if (this.useMenuPortal) {
948
+ this.applyPortalPosition();
949
+ window.removeEventListener("resize", this.boundApplyPortalPosition);
950
+ window.addEventListener("resize", this.boundApplyPortalPosition);
951
+ if (this._unsubscribePortalReposition) {
952
+ this._unsubscribePortalReposition();
953
+ this._unsubscribePortalReposition = null;
954
+ }
955
+ this._unsubscribePortalReposition = subscribeFloatingKitReposition(
956
+ this.boundApplyPortalPosition,
957
+ );
958
+ window.requestAnimationFrame(() => this.applyPortalPosition());
959
+ } else {
960
+ this.adjustDropdownPosition(elem);
961
+ }
722
962
  }
723
963
 
724
964
  hideElement(elem) {
725
965
  elem.style.height = elem.scrollHeight + "px";
726
966
  window.setTimeout(() => {
967
+ if (this.useMenuPortal) {
968
+ this.unmountPortalMenu();
969
+ }
727
970
  elem.classList.add("close");
728
971
  elem.classList.remove("open");
729
972
  this.resetFocus();
@@ -733,7 +976,7 @@ export default class PbDropdown extends PbEnhancedElement {
733
976
  resetFocus() {
734
977
  if (this.keyboardHandler) {
735
978
  this.keyboardHandler.focusedOptionIndex = -1;
736
- const options = this.element.querySelectorAll(OPTION_SELECTOR);
979
+ const options = this.queryAllOptions();
737
980
  options.forEach((option) =>
738
981
  option.classList.remove("pb_dropdown_option_focused"),
739
982
  );
@@ -741,6 +984,7 @@ export default class PbDropdown extends PbEnhancedElement {
741
984
  }
742
985
 
743
986
  toggleElement(elem) {
987
+ if (this.isDisabled) return;
744
988
  const isOpen = toggleVisibility({
745
989
  isVisible: elem.classList.contains("open"),
746
990
  onHide: () => this.hideElement(elem),
@@ -805,7 +1049,7 @@ export default class PbDropdown extends PbEnhancedElement {
805
1049
  setDefaultValue() {
806
1050
  const hiddenInput = this.baseInput;
807
1051
  const optionEls = Array.from(
808
- this.element.querySelectorAll(OPTION_SELECTOR),
1052
+ this.queryAllOptions(),
809
1053
  );
810
1054
  const defaultValue = hiddenInput.dataset.defaultValue || "";
811
1055
  if (!defaultValue) return;
@@ -917,7 +1161,7 @@ export default class PbDropdown extends PbEnhancedElement {
917
1161
 
918
1162
  resetDropdownValue() {
919
1163
  const hiddenInput = this.baseInput;
920
- const options = this.element.querySelectorAll(OPTION_SELECTOR);
1164
+ const options = this.queryAllOptions();
921
1165
  options.forEach((option) => {
922
1166
  option.classList.remove("pb_dropdown_option_selected");
923
1167
  option.style.display = "";
@@ -1006,7 +1250,7 @@ export default class PbDropdown extends PbEnhancedElement {
1006
1250
  const id = pill.dataset.pillId;
1007
1251
  this.selectedOptions.delete(option);
1008
1252
 
1009
- const optEl = this.element.querySelector(
1253
+ const optEl = (this.target || this.element).querySelector(
1010
1254
  `${OPTION_SELECTOR}[data-dropdown-option-label*='"id":${JSON.stringify(
1011
1255
  id,
1012
1256
  )}']`,
@@ -1028,9 +1272,10 @@ export default class PbDropdown extends PbEnhancedElement {
1028
1272
  }
1029
1273
 
1030
1274
  clearSelection() {
1275
+ if (this.isDisabled) return;
1031
1276
  if (this.isMultiSelect) {
1032
1277
  this.selectedOptions.clear();
1033
- this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
1278
+ this.queryAllOptions().forEach((opt) => {
1034
1279
  opt.style.display = "";
1035
1280
  });
1036
1281
  if (this.target.classList.contains("open")) {
@@ -1156,7 +1401,7 @@ export default class PbDropdown extends PbEnhancedElement {
1156
1401
 
1157
1402
  handleBackspaceClear() {
1158
1403
  if (!this.isMultiSelect) {
1159
- this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
1404
+ this.queryAllOptions().forEach((opt) => {
1160
1405
  opt.classList.remove("pb_dropdown_option_selected");
1161
1406
  opt.style.display = "";
1162
1407
  this.adjustDropdownHeight();
@@ -1170,7 +1415,7 @@ export default class PbDropdown extends PbEnhancedElement {
1170
1415
  this.setTriggerElementText(placeholder.dataset.dropdownPlaceholder);
1171
1416
  }
1172
1417
  if (this.isMultiSelect) {
1173
- this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
1418
+ this.queryAllOptions().forEach((opt) => {
1174
1419
  const optValue = opt.dataset.dropdownOptionLabel;
1175
1420
  if (
1176
1421
  this.selectedOptions.size > 0 &&
@@ -6,7 +6,7 @@ export class PbDropdownKeyboard {
6
6
  this.dropdown = dropdown;
7
7
  this.dropdownElement = dropdown.element;
8
8
  this.options = Array.from(
9
- this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
9
+ (dropdown.target || this.dropdownElement).querySelectorAll(OPTION_SELECTOR),
10
10
  );
11
11
  this.focusedOptionIndex = -1;
12
12
  this.searchInput = this.dropdownElement.querySelector(
@@ -45,12 +45,17 @@ export class PbDropdownKeyboard {
45
45
 
46
46
  getVisibleOptions() {
47
47
  // We only want to return the options that are visible
48
- return Array.from(
49
- this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
50
- ).filter((opt) => opt.style.display !== "none");
48
+ const scope = this.dropdown.target || this.dropdownElement;
49
+ return Array.from(scope.querySelectorAll(OPTION_SELECTOR)).filter(
50
+
51
+ (opt) => opt.style.display !== "none" && opt.dataset.dropdownOptionDisabled !== "true"
52
+ ,
53
+ );
51
54
  }
52
55
 
53
56
  openDropdownIfClosed() {
57
+ if (this.dropdown.isDisabled) return;
58
+
54
59
  if (!this.dropdown.target.classList.contains("open")) {
55
60
  this.dropdown.showElement(this.dropdown.target);
56
61
  this.dropdown.updateArrowDisplay(true);
@@ -58,6 +63,8 @@ export class PbDropdownKeyboard {
58
63
  }
59
64
 
60
65
  handleKeyDown(event) {
66
+ if (this.dropdown.isDisabled) return;
67
+
61
68
  switch (event.key) {
62
69
  case "ArrowDown":
63
70
  event.preventDefault();
@@ -105,9 +112,8 @@ export class PbDropdownKeyboard {
105
112
  }
106
113
 
107
114
  moveFocus(direction) {
108
- const allOptions = Array.from(
109
- this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
110
- );
115
+ const scope = this.dropdown.target || this.dropdownElement;
116
+ const allOptions = Array.from(scope.querySelectorAll(OPTION_SELECTOR));
111
117
  const visible = this.getVisibleOptions();
112
118
  if (!visible.length) return;
113
119
 
@@ -133,12 +139,15 @@ moveFocus(direction) {
133
139
 
134
140
 
135
141
  selectOption() {
136
- const allOptions = Array.from(
137
- this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
138
- );
142
+ if (this.dropdown.isDisabled) return;
143
+
144
+ const scope = this.dropdown.target || this.dropdownElement;
145
+ const allOptions = Array.from(scope.querySelectorAll(OPTION_SELECTOR));
139
146
  if (this.focusedOptionIndex < 0) return;
140
147
 
141
148
  const optionEl = allOptions[this.focusedOptionIndex];
149
+ if (optionEl.dataset.dropdownOptionDisabled === "true") return;
150
+
142
151
  this.dropdown.handleOptionClick({ target: optionEl });
143
152
  this.dropdown.toggleElement(this.dropdown.target);
144
153
  this.dropdown.updateClearButton();
@@ -59,6 +59,14 @@
59
59
  "rails"
60
60
  ]
61
61
  },
62
+ "disabled": {
63
+ "type": "boolean",
64
+ "platforms": [
65
+ "react",
66
+ "rails"
67
+ ],
68
+ "default": false
69
+ },
62
70
  "formPillProps": {
63
71
  "type": "GenericObject",
64
72
  "platforms": [