playbook_ui 18.3.0.pre.alpha.PLAY3245advancedtablecustomheadertooltipstylerails20919 → 18.3.0.pre.alpha.PLAY3342advancedtablereactmulticolumnselectablerow21082

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +62 -2
  3. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +105 -66
  4. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +4 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +633 -1
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.jsx +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.md +5 -2
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.md +3 -1
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi_select_all.jsx +82 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi_select_all.md +3 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -1
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.jsx +177 -58
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +7 -1
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/kit.schema.json +36 -16
  17. data/app/pb_kits/playbook/pb_avatar/kit.schema.json +22 -10
  18. data/app/pb_kits/playbook/pb_background/docs/_playground.json +1 -0
  19. data/app/pb_kits/playbook/pb_background/kit.schema.json +10 -3
  20. data/app/pb_kits/playbook/pb_badge/docs/_playground.json +2 -0
  21. data/app/pb_kits/playbook/pb_badge/kit.schema.json +27 -13
  22. data/app/pb_kits/playbook/pb_body/docs/_playground.json +3 -3
  23. data/app/pb_kits/playbook/pb_body/kit.schema.json +14 -5
  24. data/app/pb_kits/playbook/pb_button/_button.tsx +3 -1
  25. data/app/pb_kits/playbook/pb_button/button.rb +3 -0
  26. data/app/pb_kits/playbook/pb_button/button.test.js +154 -0
  27. data/app/pb_kits/playbook/pb_button/docs/_button_options_rails.md +5 -0
  28. data/app/pb_kits/playbook/pb_button/docs/_button_options_react.md +9 -0
  29. data/app/pb_kits/playbook/pb_button/docs/_playground.json +4 -2
  30. data/app/pb_kits/playbook/pb_button/docs/_playground.overrides.json +1 -1
  31. data/app/pb_kits/playbook/pb_button/docs/example.yml +1 -1
  32. data/app/pb_kits/playbook/pb_button/kit.schema.json +31 -27
  33. data/app/pb_kits/playbook/pb_caption/kit.schema.json +17 -7
  34. data/app/pb_kits/playbook/pb_card/docs/_playground.json +1 -0
  35. data/app/pb_kits/playbook/pb_card/kit.schema.json +2 -1
  36. data/app/pb_kits/playbook/pb_checkbox/docs/_playground.json +6 -1
  37. data/app/pb_kits/playbook/pb_checkbox/kit.schema.json +10 -5
  38. data/app/pb_kits/playbook/pb_contact/docs/_playground.json +1 -0
  39. data/app/pb_kits/playbook/pb_contact/kit.schema.json +2 -1
  40. data/app/pb_kits/playbook/pb_copy_button/docs/_playground.json +5 -1
  41. data/app/pb_kits/playbook/pb_copy_button/kit.schema.json +10 -5
  42. data/app/pb_kits/playbook/pb_currency/docs/_playground.json +1 -1
  43. data/app/pb_kits/playbook/pb_currency/kit.schema.json +6 -2
  44. data/app/pb_kits/playbook/pb_dashboard_value/docs/_playground.json +2 -2
  45. data/app/pb_kits/playbook/pb_dashboard_value/kit.schema.json +4 -2
  46. data/app/pb_kits/playbook/pb_date/docs/_playground.json +1 -0
  47. data/app/pb_kits/playbook/pb_date/kit.schema.json +16 -7
  48. data/app/pb_kits/playbook/pb_date_picker/docs/_playground.json +4 -1
  49. data/app/pb_kits/playbook/pb_date_picker/kit.schema.json +32 -14
  50. data/app/pb_kits/playbook/pb_date_range_inline/docs/_playground.json +1 -0
  51. data/app/pb_kits/playbook/pb_date_range_inline/kit.schema.json +2 -1
  52. data/app/pb_kits/playbook/pb_date_time/docs/_playground.json +2 -1
  53. data/app/pb_kits/playbook/pb_date_time/kit.schema.json +2 -1
  54. data/app/pb_kits/playbook/pb_date_time_stacked/docs/_playground.json +1 -0
  55. data/app/pb_kits/playbook/pb_date_time_stacked/kit.schema.json +2 -1
  56. data/app/pb_kits/playbook/pb_detail/docs/_playground.json +2 -1
  57. data/app/pb_kits/playbook/pb_detail/kit.schema.json +2 -1
  58. data/app/pb_kits/playbook/pb_dialog/docs/_playground.json +1 -1
  59. data/app/pb_kits/playbook/pb_dialog/kit.schema.json +22 -9
  60. data/app/pb_kits/playbook/pb_distribution_bar/docs/_playground.json +2 -2
  61. data/app/pb_kits/playbook/pb_distribution_bar/kit.schema.json +2 -1
  62. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.json +7 -2
  63. data/app/pb_kits/playbook/pb_dropdown/kit.schema.json +18 -8
  64. data/app/pb_kits/playbook/pb_empty_state/docs/_playground.json +1 -1
  65. data/app/pb_kits/playbook/pb_empty_state/kit.schema.json +2 -1
  66. data/app/pb_kits/playbook/pb_file_upload/docs/_playground.json +3 -2
  67. data/app/pb_kits/playbook/pb_file_upload/kit.schema.json +8 -3
  68. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_playground.json +4 -4
  69. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/kit.schema.json +6 -3
  70. data/app/pb_kits/playbook/pb_flex/docs/_playground.json +3 -0
  71. data/app/pb_kits/playbook/pb_flex/kit.schema.json +27 -12
  72. data/app/pb_kits/playbook/pb_form/form.rb +1 -1
  73. data/app/pb_kits/playbook/pb_form/kit.schema.json +1 -6
  74. data/app/pb_kits/playbook/pb_form_pill/docs/_playground.json +3 -0
  75. data/app/pb_kits/playbook/pb_form_pill/kit.schema.json +6 -3
  76. data/app/pb_kits/playbook/pb_full_screen/docs/_playground.json +3 -3
  77. data/app/pb_kits/playbook/pb_full_screen/kit.schema.json +8 -4
  78. data/app/pb_kits/playbook/pb_hashtag/docs/_playground.json +2 -2
  79. data/app/pb_kits/playbook/pb_hashtag/kit.schema.json +2 -1
  80. data/app/pb_kits/playbook/pb_highlight/kit.schema.json +2 -1
  81. data/app/pb_kits/playbook/pb_icon/docs/_playground.json +2 -2
  82. data/app/pb_kits/playbook/pb_icon/kit.schema.json +30 -13
  83. data/app/pb_kits/playbook/pb_icon_circle/docs/_playground.json +2 -2
  84. data/app/pb_kits/playbook/pb_icon_circle/kit.schema.json +2 -1
  85. data/app/pb_kits/playbook/pb_icon_stat_value/docs/_playground.json +3 -2
  86. data/app/pb_kits/playbook/pb_icon_stat_value/kit.schema.json +4 -2
  87. data/app/pb_kits/playbook/pb_image/_image.tsx +2 -2
  88. data/app/pb_kits/playbook/pb_image/docs/_playground.json +27 -27
  89. data/app/pb_kits/playbook/pb_image/kit.schema.json +56 -24
  90. data/app/pb_kits/playbook/pb_label_value/docs/_playground.json +2 -2
  91. data/app/pb_kits/playbook/pb_label_value/kit.schema.json +2 -1
  92. data/app/pb_kits/playbook/pb_layout/docs/_playground.json +2 -2
  93. data/app/pb_kits/playbook/pb_layout/kit.schema.json +43 -20
  94. data/app/pb_kits/playbook/pb_legend/docs/_playground.json +2 -2
  95. data/app/pb_kits/playbook/pb_legend/kit.schema.json +2 -1
  96. data/app/pb_kits/playbook/pb_lightbox/_lightbox.tsx +2 -2
  97. data/app/pb_kits/playbook/pb_lightbox/kit.schema.json +84 -0
  98. data/app/pb_kits/playbook/pb_link/docs/_playground.json +6 -3
  99. data/app/pb_kits/playbook/pb_link/kit.schema.json +14 -6
  100. data/app/pb_kits/playbook/pb_list/docs/_playground.json +2 -2
  101. data/app/pb_kits/playbook/pb_list/kit.schema.json +2 -1
  102. data/app/pb_kits/playbook/pb_loading_inline/docs/_playground.json +0 -1
  103. data/app/pb_kits/playbook/pb_loading_inline/kit.schema.json +4 -1
  104. data/app/pb_kits/playbook/pb_map/kit.schema.json +4 -6
  105. data/app/pb_kits/playbook/pb_message/kit.schema.json +2 -1
  106. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +4 -1
  107. data/app/pb_kits/playbook/pb_multiple_users/docs/_playground.json +2 -1
  108. data/app/pb_kits/playbook/pb_multiple_users/kit.schema.json +19 -11
  109. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_playground.json +1 -0
  110. data/app/pb_kits/playbook/pb_multiple_users_stacked/kit.schema.json +2 -1
  111. data/app/pb_kits/playbook/pb_nav/docs/_playground.json +2 -0
  112. data/app/pb_kits/playbook/pb_nav/kit.schema.json +4 -2
  113. data/app/pb_kits/playbook/pb_overlay/docs/_playground.json +3 -3
  114. data/app/pb_kits/playbook/pb_overlay/kit.schema.json +22 -12
  115. data/app/pb_kits/playbook/pb_pagination/kit.schema.json +6 -3
  116. data/app/pb_kits/playbook/pb_passphrase/docs/_playground.json +6 -4
  117. data/app/pb_kits/playbook/pb_passphrase/kit.schema.json +10 -5
  118. data/app/pb_kits/playbook/pb_pb_gauge_chart/kit.schema.json +2 -1
  119. data/app/pb_kits/playbook/pb_person_contact/docs/_playground.json +3 -3
  120. data/app/pb_kits/playbook/pb_person_contact/kit.schema.json +2 -1
  121. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.html.erb +1 -1
  122. data/app/pb_kits/playbook/pb_phone_number_input/docs/_playground.json +3 -0
  123. data/app/pb_kits/playbook/pb_phone_number_input/kit.schema.json +6 -3
  124. data/app/pb_kits/playbook/pb_popover/docs/_playground.json +1 -2
  125. data/app/pb_kits/playbook/pb_popover/kit.schema.json +18 -9
  126. data/app/pb_kits/playbook/pb_progress_pills/docs/_playground.json +1 -0
  127. data/app/pb_kits/playbook/pb_progress_pills/kit.schema.json +2 -1
  128. data/app/pb_kits/playbook/pb_progress_simple/docs/_playground.json +3 -2
  129. data/app/pb_kits/playbook/pb_progress_simple/kit.schema.json +4 -2
  130. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.json +9 -2
  131. data/app/pb_kits/playbook/pb_rich_text_editor/kit.schema.json +18 -9
  132. data/app/pb_kits/playbook/pb_selectable_card/docs/_playground.json +1 -0
  133. data/app/pb_kits/playbook/pb_selectable_card/kit.schema.json +4 -2
  134. data/app/pb_kits/playbook/pb_selectable_card_icon/docs/_playground.json +1 -0
  135. data/app/pb_kits/playbook/pb_selectable_card_icon/kit.schema.json +2 -1
  136. data/app/pb_kits/playbook/pb_source/docs/_playground.json +1 -0
  137. data/app/pb_kits/playbook/pb_source/kit.schema.json +2 -1
  138. data/app/pb_kits/playbook/pb_star_rating/docs/_playground.json +1 -0
  139. data/app/pb_kits/playbook/pb_star_rating/kit.schema.json +15 -7
  140. data/app/pb_kits/playbook/pb_stat_change/docs/_playground.json +1 -0
  141. data/app/pb_kits/playbook/pb_stat_change/kit.schema.json +2 -1
  142. data/app/pb_kits/playbook/pb_stat_value/docs/_playground.json +3 -1
  143. data/app/pb_kits/playbook/pb_stat_value/kit.schema.json +2 -1
  144. data/app/pb_kits/playbook/pb_table/docs/_playground.json +5 -1
  145. data/app/pb_kits/playbook/pb_table/kit.schema.json +28 -11
  146. data/app/pb_kits/playbook/pb_text_input/docs/_playground.json +3 -0
  147. data/app/pb_kits/playbook/pb_text_input/kit.schema.json +22 -9
  148. data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +4 -1
  149. data/app/pb_kits/playbook/pb_time/kit.schema.json +13 -5
  150. data/app/pb_kits/playbook/pb_time_picker/docs/_playground.json +1 -0
  151. data/app/pb_kits/playbook/pb_time_picker/kit.schema.json +2 -1
  152. data/app/pb_kits/playbook/pb_time_range_inline/kit.schema.json +12 -5
  153. data/app/pb_kits/playbook/pb_title/kit.schema.json +23 -10
  154. data/app/pb_kits/playbook/pb_title_count/docs/_playground.json +1 -0
  155. data/app/pb_kits/playbook/pb_title_count/kit.schema.json +2 -1
  156. data/app/pb_kits/playbook/pb_tooltip/docs/_playground.json +5 -1
  157. data/app/pb_kits/playbook/pb_tooltip/kit.schema.json +10 -5
  158. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +4 -1
  159. data/app/pb_kits/playbook/pb_user/docs/_playground.json +3 -1
  160. data/app/pb_kits/playbook/pb_user/kit.schema.json +19 -9
  161. data/app/pb_kits/playbook/pb_weekday_stacked/docs/_playground.json +1 -0
  162. data/app/pb_kits/playbook/pb_weekday_stacked/kit.schema.json +2 -1
  163. data/dist/ai/all-schemas.json +870 -375
  164. data/dist/ai/forms.json +1 -1
  165. data/dist/ai/index.json +10 -2
  166. data/dist/ai/kits/advanced_table.schema.json +36 -16
  167. data/dist/ai/kits/avatar.schema.json +21 -9
  168. data/dist/ai/kits/background.schema.json +10 -3
  169. data/dist/ai/kits/badge.schema.json +26 -12
  170. data/dist/ai/kits/body.schema.json +14 -5
  171. data/dist/ai/kits/button.schema.json +29 -25
  172. data/dist/ai/kits/caption.schema.json +17 -7
  173. data/dist/ai/kits/card.schema.json +2 -1
  174. data/dist/ai/kits/checkbox.schema.json +10 -5
  175. data/dist/ai/kits/contact.schema.json +2 -1
  176. data/dist/ai/kits/copy_button.schema.json +10 -5
  177. data/dist/ai/kits/currency.schema.json +6 -2
  178. data/dist/ai/kits/dashboard_value.schema.json +4 -2
  179. data/dist/ai/kits/date.schema.json +15 -6
  180. data/dist/ai/kits/date_picker.schema.json +31 -13
  181. data/dist/ai/kits/date_range_inline.schema.json +2 -1
  182. data/dist/ai/kits/date_time.schema.json +2 -1
  183. data/dist/ai/kits/date_time_stacked.schema.json +2 -1
  184. data/dist/ai/kits/detail.schema.json +2 -1
  185. data/dist/ai/kits/dialog.schema.json +22 -9
  186. data/dist/ai/kits/distribution_bar.schema.json +2 -1
  187. data/dist/ai/kits/dropdown.schema.json +18 -8
  188. data/dist/ai/kits/empty_state.schema.json +2 -1
  189. data/dist/ai/kits/file_upload.schema.json +8 -3
  190. data/dist/ai/kits/fixed_confirmation_toast.schema.json +6 -3
  191. data/dist/ai/kits/flex.schema.json +27 -12
  192. data/dist/ai/kits/form.schema.json +1 -6
  193. data/dist/ai/kits/form_pill.schema.json +6 -3
  194. data/dist/ai/kits/full_screen.schema.json +8 -4
  195. data/dist/ai/kits/hashtag.schema.json +2 -1
  196. data/dist/ai/kits/highlight.schema.json +2 -1
  197. data/dist/ai/kits/icon.schema.json +30 -13
  198. data/dist/ai/kits/icon_circle.schema.json +2 -1
  199. data/dist/ai/kits/icon_stat_value.schema.json +4 -2
  200. data/dist/ai/kits/image.schema.json +56 -24
  201. data/dist/ai/kits/label_value.schema.json +2 -1
  202. data/dist/ai/kits/layout.schema.json +43 -20
  203. data/dist/ai/kits/legend.schema.json +2 -1
  204. data/dist/ai/kits/lightbox.schema.json +86 -0
  205. data/dist/ai/kits/link.schema.json +14 -6
  206. data/dist/ai/kits/list.schema.json +2 -1
  207. data/dist/ai/kits/loading_inline.schema.json +4 -1
  208. data/dist/ai/kits/map.schema.json +4 -7
  209. data/dist/ai/kits/message.schema.json +2 -1
  210. data/dist/ai/kits/multiple_users.schema.json +19 -11
  211. data/dist/ai/kits/multiple_users_stacked.schema.json +2 -1
  212. data/dist/ai/kits/nav.schema.json +4 -2
  213. data/dist/ai/kits/overlay.schema.json +22 -12
  214. data/dist/ai/kits/pagination.schema.json +6 -3
  215. data/dist/ai/kits/passphrase.schema.json +10 -5
  216. data/dist/ai/kits/pb_gauge_chart.schema.json +2 -1
  217. data/dist/ai/kits/person_contact.schema.json +2 -1
  218. data/dist/ai/kits/phone_number_input.schema.json +6 -3
  219. data/dist/ai/kits/popover.schema.json +17 -8
  220. data/dist/ai/kits/progress_pills.schema.json +2 -1
  221. data/dist/ai/kits/progress_simple.schema.json +4 -2
  222. data/dist/ai/kits/rich_text_editor.schema.json +18 -9
  223. data/dist/ai/kits/selectable_card.schema.json +4 -2
  224. data/dist/ai/kits/selectable_card_icon.schema.json +2 -1
  225. data/dist/ai/kits/source.schema.json +2 -1
  226. data/dist/ai/kits/star_rating.schema.json +15 -7
  227. data/dist/ai/kits/stat_change.schema.json +2 -1
  228. data/dist/ai/kits/stat_value.schema.json +2 -1
  229. data/dist/ai/kits/table.schema.json +28 -11
  230. data/dist/ai/kits/text_input.schema.json +22 -9
  231. data/dist/ai/kits/time.schema.json +12 -4
  232. data/dist/ai/kits/time_picker.schema.json +2 -1
  233. data/dist/ai/kits/time_range_inline.schema.json +12 -5
  234. data/dist/ai/kits/title.schema.json +23 -10
  235. data/dist/ai/kits/title_count.schema.json +2 -1
  236. data/dist/ai/kits/tooltip.schema.json +10 -5
  237. data/dist/ai/kits/user.schema.json +19 -9
  238. data/dist/ai/kits/weekday_stacked.schema.json +2 -1
  239. data/dist/ai/visual-index.json +1 -1
  240. data/dist/chunks/{_typeahead-C3MN3apM.js → _typeahead-CkiAf8zx.js} +1 -1
  241. data/dist/chunks/vendor.js +2 -2
  242. data/dist/menu.yml +1 -1
  243. data/dist/playbook-rails-react-bindings.js +1 -1
  244. data/dist/playbook-rails.js +1 -1
  245. data/dist/playbook.css +1 -1
  246. data/lib/playbook/changelog_generator.rb +47 -21
  247. data/lib/playbook/connect_message_generator.rb +15 -2
  248. data/lib/playbook/version.rb +1 -1
  249. metadata +10 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 165a24b36fe82b732fa3727e952e810edc9d1d733294130d2575db598c21a5d7
4
- data.tar.gz: 7b4a2b5f87fdcb57b973b098727b09bb87d41d83d1728e955890d136475a2ef2
3
+ metadata.gz: 106354f9d720a7693c85b275f1de67cb17a21e3e28f28f90a758ee9b19942367
4
+ data.tar.gz: 9a5fbcd069bdaf722663195395f810d351e72e322a527e0157d666609363cc60
5
5
  SHA512:
6
- metadata.gz: 7d47264d6f7fe1c3960f18752809c9a9330395453a9f178c7a75e036584649d06d6a618847e888fc911da60439fc82a4eb3f1011f37879020ce69948ad4a5d30
7
- data.tar.gz: 56358953c5797ca33876dc3231114a1f7c3103d272f1a07c420dba81bd52de2a34b06f3d84df4c41f1ecea27a91334de73c9197086b17cd443e74cb641ec59bf
6
+ metadata.gz: 8a13eb3272cf0c06bb2defa816ca14a48f2cb2fffd1185516f6ff40556fab6e9c9766d3929929680ea18511efc952ebefa5a1d836e554c99df384a1d9ef88ea4
7
+ data.tar.gz: d754688073c058e93739e273d4f6d8f54fa26f5a86869c7e764a3dddfb492f6c63efb86b914b6d9d45424f859e0996269f416b8ab38411268a8b89b23b17915c
@@ -105,7 +105,7 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
105
105
  }
106
106
  };
107
107
  return (
108
- <>
108
+ <React.Fragment key={node.id}>
109
109
  <Checkbox
110
110
  checked={allOn}
111
111
  indeterminate={!allOn && someOn}
@@ -120,7 +120,7 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
120
120
  child.children ? renderGroup(child) : renderLeaf(child.id, child.label),
121
121
  )}
122
122
  </Flex>
123
- </>
123
+ </React.Fragment>
124
124
  );
125
125
  };
126
126
  // ------------ End of column visibility logic --------
@@ -143,6 +143,47 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
143
143
  const handleShouldClose = (shouldClose: boolean) =>
144
144
  setShowPopover(!shouldClose)
145
145
 
146
+ // Select All only changes columns listed in the popover that can be hidden.
147
+ // The first column and ids omitted by includeIds stay as they are.
148
+ // Skip the leaf walk unless the checkbox is enabled.
149
+ const selectAllRequested = columnVisibilityControl?.showSelectAll === true
150
+ const availableColumns = selectAllRequested
151
+ ? tree.flatMap(gatherLeafIds).flatMap((id) => {
152
+ const column = table.getColumn(id)
153
+ return column?.getCanHide() ? [column] : []
154
+ })
155
+ : []
156
+ const allAvailableVisible =
157
+ availableColumns.length > 0 &&
158
+ availableColumns.every((column) => column.getIsVisible())
159
+ const someAvailableVisible = availableColumns.some((column) => column.getIsVisible())
160
+ const showSelectAll = availableColumns.length > 0
161
+ const selectAllLabel = allAvailableVisible ? "Deselect All" : "Select All"
162
+
163
+ // Uses the same updater form as toggleVisibility, so onChange gets the same kind of value.
164
+ const handleSelectAllChange = () => {
165
+ const selectAllVisibility = Object.fromEntries(
166
+ availableColumns.map((column) => [column.id, !allAvailableVisible])
167
+ )
168
+ table.setColumnVisibility((previousVisibility: { [id: string]: boolean }) => ({
169
+ ...previousVisibility,
170
+ ...selectAllVisibility,
171
+ }))
172
+
173
+ if (columnVisibilityControl?.onColumnVisibilityChange) {
174
+ const nextVisibility = { ...table.getState().columnVisibility, ...selectAllVisibility }
175
+ // Same shape as the single toggles: root column ids, groups visible if any leaf is visible
176
+ const updatedVisibilityState = table.getAllColumns().reduce((
177
+ acc: { [id: string]: boolean },
178
+ column: { getLeafColumns: () => { id: string }[]; id: string }
179
+ ) => {
180
+ acc[column.id] = column.getLeafColumns().some((leaf) => nextVisibility[leaf.id] ?? true)
181
+ return acc
182
+ }, {})
183
+ columnVisibilityControl.onColumnVisibilityChange(updatedVisibilityState)
184
+ }
185
+ }
186
+
146
187
  const popoverReference = (
147
188
  <Tooltip
148
189
  placement="top"
@@ -197,6 +238,25 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
197
238
  textAlign="center"
198
239
  />
199
240
  <SectionSeparator paddingBottom="xs" />
241
+ {showSelectAll && (
242
+ <>
243
+ <Flex
244
+ cursor="pointer"
245
+ flexDirection="column"
246
+ paddingX="xs"
247
+ >
248
+ <Checkbox
249
+ aria={{ label: selectAllLabel }}
250
+ checked={allAvailableVisible}
251
+ indeterminate={!allAvailableVisible && someAvailableVisible}
252
+ onChange={handleSelectAllChange}
253
+ paddingBottom="xs"
254
+ text={selectAllLabel}
255
+ />
256
+ </Flex>
257
+ <SectionSeparator paddingBottom="xs" />
258
+ </>
259
+ )}
200
260
  {tree.map((node: VisibilityNode) => (
201
261
  <Flex cursor="pointer"
202
262
  flexDirection="column"
@@ -32,6 +32,7 @@ export const TableHeader = ({
32
32
  ...props
33
33
  }: TableHeaderProps) => {
34
34
  const {
35
+ columnVisibilityControl,
35
36
  enableToggleExpansion,
36
37
  handleExpandOrCollapse,
37
38
  loading,
@@ -63,42 +64,83 @@ export const TableHeader = ({
63
64
  `${responsive === "scroll" && "pinned-left"}`,
64
65
  );
65
66
 
67
+ // TanStack drops header rows when every leaf in a group is hidden.
68
+ // Spacer rows keep that height only when Select All can hide a whole group.
69
+ const showSelectAll = columnVisibilityControl?.showSelectAll === true
70
+ let hiddenHeaderRowCount = 0
71
+ let spacerColSpan = 0
72
+ if (showSelectAll) {
73
+ const columnHeaderDepth = Math.max(
74
+ ...table.getAllFlatColumns().map((column: GenericObject) => column.depth + 1)
75
+ )
76
+ hiddenHeaderRowCount = columnHeaderDepth - table.getHeaderGroups().length
77
+ spacerColSpan = table.getVisibleLeafColumns().length + (!hasAnySubRows && selectableRows ? 1 : 0)
78
+ }
79
+
80
+ const renderSpacerRows = (rowClassName?: string) =>
81
+ Array.from({ length: Math.max(0, hiddenHeaderRowCount) }, (_, index) => (
82
+ <tr
83
+ aria-hidden="true"
84
+ className={classnames("header-spacer-row", rowClassName)}
85
+ key={`header-spacer-${index}`}
86
+ >
87
+ {/* header-spacer-cell stays off .table-header-cells so width measurement and sticky-left styles skip it. */}
88
+ <th
89
+ className="header-spacer-cell"
90
+ colSpan={spacerColSpan}
91
+ />
92
+ </tr>
93
+ ))
94
+
95
+ // Empty checkbox-column cell on upper multi-header rows; checkbox only on the lowest row.
96
+ const renderSelectableHeaderCell = (
97
+ isLowestHeaderRow: boolean,
98
+ extraClassName?: string
99
+ ) => (
100
+ <th className={classnames(customCellClassnames, "checkbox-cell-header", extraClassName)}>
101
+ {isLowestHeaderRow ? (
102
+ <Checkbox
103
+ checked={table?.getIsAllRowsSelected()}
104
+ indeterminate={table?.getIsSomeRowsSelected()}
105
+ onChange={table?.getToggleAllRowsSelectedHandler()}
106
+ />
107
+ ) : null}
108
+ </th>
109
+ )
110
+
66
111
  const renderRegularTableHeader = () => (
67
112
  <thead className={classes}
68
113
  id={id}
69
114
  ref={headerRef}
70
115
  >
71
- {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>) => (
72
- <tr key={`${headerGroup.id}-headerGroup`}>
73
- {!hasAnySubRows && selectableRows && (
74
- <th className={customCellClassnames}>
75
- <Checkbox
76
- checked={table?.getIsAllRowsSelected()}
77
- indeterminate={table?.getIsSomeRowsSelected()}
78
- onChange={table?.getToggleAllRowsSelectedHandler()}
79
- />
80
- </th>
81
- )}
82
- {headerGroup.headers.map(header => {
83
- const isPinnedLeft = columnPinning.left.includes(header.id)
84
- return (
85
- <TableHeaderCell
86
- enableSorting={enableSorting}
87
- enableToggleExpansion={enableToggleExpansion}
88
- handleExpandOrCollapse={handleExpandOrCollapse}
89
- header={header}
90
- headerChildren={children}
91
- isPinnedLeft={isPinnedLeft}
92
- key={`${header.id}-header`}
93
- loading={loading}
94
- persistToggleExpansionButton={persistToggleExpansionButton}
95
- sortIcon={sortIcon}
96
- table={table}
97
- />
98
- )
99
- })}
100
- </tr>
101
- ))}
116
+ {renderSpacerRows()}
117
+ {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>, headerGroupIndex: number, headerGroups: HeaderGroup<GenericObject>[]) => {
118
+ const isLowestHeaderRow = headerGroupIndex === headerGroups.length - 1
119
+
120
+ return (
121
+ <tr key={`${headerGroup.id}-headerGroup`}>
122
+ {!hasAnySubRows && selectableRows && renderSelectableHeaderCell(isLowestHeaderRow)}
123
+ {headerGroup.headers.map(header => {
124
+ const isPinnedLeft = columnPinning.left.includes(header.id)
125
+ return (
126
+ <TableHeaderCell
127
+ enableSorting={enableSorting}
128
+ enableToggleExpansion={enableToggleExpansion}
129
+ handleExpandOrCollapse={handleExpandOrCollapse}
130
+ header={header}
131
+ headerChildren={children}
132
+ isPinnedLeft={isPinnedLeft}
133
+ key={`${header.id}-header`}
134
+ loading={loading}
135
+ persistToggleExpansionButton={persistToggleExpansionButton}
136
+ sortIcon={sortIcon}
137
+ table={table}
138
+ />
139
+ )
140
+ })}
141
+ </tr>
142
+ )
143
+ })}
102
144
  </thead>
103
145
  );
104
146
 
@@ -109,41 +151,38 @@ export const TableHeader = ({
109
151
  id={id}
110
152
  ref={headerRef}
111
153
  >
112
- {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>) => (
113
- <tr
114
- className="virtualized-header-row-header"
115
- key={`${headerGroup.id}-headerGroup-virtualized`}
116
- >
117
- {!hasAnySubRows && selectableRows && (
118
- <th className={classnames(customCellClassnames, "virtualized-header-cell")}>
119
- <Checkbox
120
- checked={table?.getIsAllRowsSelected()}
121
- indeterminate={table?.getIsSomeRowsSelected()}
122
- onChange={table?.getToggleAllRowsSelectedHandler()}
123
- />
124
- </th>
125
- )}
126
- {headerGroup.headers.map(header => {
127
- const isPinnedLeft = columnPinning.left.includes(header.id)
128
- return (
129
- <TableHeaderCell
130
- enableSorting={enableSorting}
131
- enableToggleExpansion={enableToggleExpansion}
132
- handleExpandOrCollapse={handleExpandOrCollapse}
133
- header={header}
134
- headerChildren={children}
135
- isPinnedLeft={isPinnedLeft}
136
- isVirtualized
137
- key={`${header.id}-header-virtualized`}
138
- loading={loading}
139
- persistToggleExpansionButton={persistToggleExpansionButton}
140
- sortIcon={sortIcon}
141
- table={table}
142
- />
143
- )
144
- })}
145
- </tr>
146
- ))}
154
+ {renderSpacerRows("virtualized-header-row-header")}
155
+ {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>, headerGroupIndex: number, headerGroups: HeaderGroup<GenericObject>[]) => {
156
+ const isLowestHeaderRow = headerGroupIndex === headerGroups.length - 1
157
+
158
+ return (
159
+ <tr
160
+ className="virtualized-header-row-header"
161
+ key={`${headerGroup.id}-headerGroup-virtualized`}
162
+ >
163
+ {!hasAnySubRows && selectableRows && renderSelectableHeaderCell(isLowestHeaderRow, "virtualized-header-cell")}
164
+ {headerGroup.headers.map(header => {
165
+ const isPinnedLeft = columnPinning.left.includes(header.id)
166
+ return (
167
+ <TableHeaderCell
168
+ enableSorting={enableSorting}
169
+ enableToggleExpansion={enableToggleExpansion}
170
+ handleExpandOrCollapse={handleExpandOrCollapse}
171
+ header={header}
172
+ headerChildren={children}
173
+ isPinnedLeft={isPinnedLeft}
174
+ isVirtualized
175
+ key={`${header.id}-header-virtualized`}
176
+ loading={loading}
177
+ persistToggleExpansionButton={persistToggleExpansionButton}
178
+ sortIcon={sortIcon}
179
+ table={table}
180
+ />
181
+ )
182
+ })}
183
+ </tr>
184
+ )
185
+ })}
147
186
  </thead>
148
187
  );
149
188
  return (
@@ -251,6 +251,10 @@
251
251
  th[colspan]:not([colspan="1"]) {
252
252
  border-right: 1px solid $border_light !important;
253
253
  }
254
+ // Spacer rows have no text, so give them one line of header height.
255
+ .header-spacer-cell::before {
256
+ content: "\00a0";
257
+ }
254
258
  .table-header-cells-custom {
255
259
  text-align: center;
256
260
  [class^="pb_checkbox_kit"] .pb_checkbox_label {